From 61776524a99f646a56bd20466a9d42febe983ea6 Mon Sep 17 00:00:00 2001 From: karutoh Date: Wed, 1 Nov 2023 00:38:16 -0700 Subject: [PATCH] Added a secondary stage bootloader. --- CMakeLists.txt | 18 ++-- src/boot/boot.asm | 151 ++++++++++++++-------------------- src/boot/boot2.asm | 43 ++++++++++ src/kernel/linker.ld | 32 ++++--- x86-baremetal-toolchain.cmake | 2 +- 5 files changed, 135 insertions(+), 111 deletions(-) create mode 100644 src/boot/boot2.asm diff --git a/CMakeLists.txt b/CMakeLists.txt index e25d0a0..a0fe5c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ set(CMAKE_BINARY_DIR ${CMAKE_CURRENT_LIST_DIR}/build) include(x86-baremetal-toolchain.cmake) +project(ClassicOSBL VERSION 0.0.1 LANGUAGES ASM_NASM) project(ClassicOS VERSION 0.0.1 LANGUAGES C CXX ASM_NASM) set(IS_OS_WINDOWS FALSE) @@ -28,12 +29,10 @@ set(BOOT_SOURCE_FILES src/boot/linker.ld ) -#[[ set(GRUB_SOURCE_FILES src/boot/grub/grub.cfg src/boot/grub/menu.lst ) -]] set(DRIVERS_SOURCE_FILES src/drivers/audio/audio.c @@ -111,18 +110,13 @@ set(UTIL_SOURCE_FILES ) add_executable(ClassicOS - ${GRUB_SOURCE_FILES} ${KERNEL_SOURCE_FILES} ${DRIVERS_SOURCE_FILES} ) -if (IS_OS_LINUX) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") - set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -f elf") - set(CMAKE_EXE_LINKER_FLAGS "-g -s") - set(CMAKE_LINK_FLAGS "${CMAKE_LINK_FLAGS} -e kernel_main") +add_executable(ClassicOSBL + ${BOOT_SOURCE_FILES} + ${GRUB_SOURCE_FILES} +) - #set_target_properties(ClassicOS PROPERTIES LINK_FLAGS "-T ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld") -elseif (IS_OS_WINDOWS) - set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -f win32") -endif () \ No newline at end of file +message("${CMAKE_EXE_LINKER_FLAGS}") \ No newline at end of file diff --git a/src/boot/boot.asm b/src/boot/boot.asm index 51a73e5..a2977b9 100644 --- a/src/boot/boot.asm +++ b/src/boot/boot.asm @@ -1,112 +1,87 @@ [BITS 16] +[ORG 0x7c00] -; Set up the segment registers -xor ax, ax -mov ds, ax -mov es, ax +start: + XOR AX, AX + MOV DS, AX + MOV SS, AX + MOV SP, 0x7c00 -; Set up stack and jump to main -mov ss, ax -mov sp, 0x7c00 -jmp main + MOV SI, loading + CALL printnl -; Print 'Booting ClassicOS!' to the screen -print: - mov si, message - mov ah, 0x0e -.loop: - lodsb - test al, al - jz .done - int 0x10 - jmp .loop -.done: - ret + CALL reset_drives + CALL read_drive -; Set the video mode to a 40 column text mode -set_video_mode: - mov ax, 0x0003 ; Set up a 80x25 text mode - int 0x10 + MOV SI, loadedSS + CALL printnl - ; Set the number of columns to 40 - mov ax, 0x1112 - mov bx, 0x0007 - int 0x10 + JMP 0x1000:0x0000 - ret + RET -; Detect floppy disk drive -detect_disk: - mov ah, 0x08 - int 0x13 - cmp ah, 0 - jne .error - ret +printnl: + LODSB + OR AL, AL + JZ .stop -.error: - ; Handle disk detection error - ; Display error message or take appropriate action - ret + MOV AH, 0x0E + MOV BH, 0x00 + MOV BL, 0x07 + INT 0x10 -; Read sectors from floppy disk -read_sectors: - mov ah, 0x02 - mov al, 1 ; Number of sectors to read - mov ch, 0 ; Cylinder/Track number - mov cl, 2 ; Sector number (starting from 1) - mov dh, 0 ; Head number - mov dl, 0 ; Drive number (0 for floppy disk) + JMP printnl - mov bx, buffer ; Destination buffer - mov es, bx - xor bx, bx + .stop: + MOV AH, 0x03 ; AH = 0x03 (Get Cursor Position and Shape) + XOR BH, BH ; BH = 0x00 (Video Page Number) + INT 0x10 ; Call video interrupt - int 0x13 + INC DH - jc .error ; Check carry flag for error - ret + MOV AH, 0x02 ; Set cursor position + XOR BH, BH ; Page number + XOR DL, DL ; Column (start from 0) + INT 0x10 ; Call video interrupt + RET -.error: - ; Handle read error - ; Display error message or take appropriate action - ret +reset_drives: + XOR AH, AH ; 0 = Reset floppy disk + INT 0x13 + JC .reset_error ; If carry flag was set, try again + RET -; Bootloader entry point -main: - ; Call the set_video_mode function - call set_video_mode + .reset_error: + MOV SI, resetError + CALL printnl + RET - ; Clear the screen - mov ah, 0x06 - mov al, 0 - xor bx, bx - xor cx, cx - mov dh, 24 - mov dl, 39 - int 0x10 +read_drive: + MOV AH, 0x02 + MOV AL, 1 ; Number of sectors to read + XOR CH, CH ; Cylinder/Track number + MOV CL, 2 ; Sector number (starting from 1) + XOR DH, DH ; Head number + XOR DL, DL ; Drive number (0x0 for floppy disk / 0x80 for hard disk) - ; Call the print function - call print + MOV BX, 0x1000 + MOV ES, BX + XOR BX, BX - ; Wait for a key press to exit the loop - mov ah, 0x00 - int 0x16 + INT 0x13 - ; Call the detect_disk function - call detect_disk + JC .read_error + RET - ; Call the read_sectors function - call read_sectors + .read_error: + MOV SI, readError + CALL printnl + RET - ; Infinite loop -.loop: - jmp .loop - -; Message to print -message db 'Booting ClassicOS!', 0 - -; Buffer to store read sectors -buffer times 512 db 0 +loading db "Loading Second Stage", 0 +resetError db "Failed to reset drives.", 0 +readError db "Failed to read drive", 0 +loadedSS db "Loaded second stage...", 0 times 510-($-$$) db 0 dw 0xaa55 \ No newline at end of file diff --git a/src/boot/boot2.asm b/src/boot/boot2.asm new file mode 100644 index 0000000..4dc5e76 --- /dev/null +++ b/src/boot/boot2.asm @@ -0,0 +1,43 @@ +[BITS 16] +[ORG 0x0000] + +start: + MOV AX, CS + MOV DS, AX + MOV SS, AX + MOV SP, 0xFFFF + + MOV SI, msg + JMP println + + JMP $ + + RET + +println: + .next_char: + LODSB + OR AL, AL + JZ .stop + + MOV AH, 0x0E + MOV BH, 0x00 + MOV BL, 0x07 + INT 0x10 + + JMP .next_char + + .stop: + MOV AH, 0x03 ; AH = 0x03 (Get Cursor Position and Shape) + XOR BH, BH ; BH = 0x00 (Video Page Number) + INT 0x10 ; Call video interrupt + + INC DH + + MOV AH, 0x02 ; Set cursor position + XOR BH, BH ; Page number + XOR DL, DL ; Column (start from 0) + INT 0x10 ; Call video interrupt + RET + +msg db "Second stage loaded, and Gbowne1 stinks.", 0 \ No newline at end of file diff --git a/src/kernel/linker.ld b/src/kernel/linker.ld index 6f90a30..7dcdfcd 100644 --- a/src/kernel/linker.ld +++ b/src/kernel/linker.ld @@ -1,21 +1,33 @@ ENTRY(kernel_main) +PHDRS { + headers PT_PHDR PHDRS ; + text_seg PT_LOAD FLAGS(5); /* Read and Execute */ + data_seg PT_LOAD FLAGS(6); /* Read and Write */ +} + SECTIONS { - . = 0x100000; + . = 0xC0000000; /* Starting virtual address */ - .text : { + /* Text Section */ + .text : AT(ADDR(.text) - 0xC0000000) + { *(.text) - } + } :text_seg - .rodata : { - *(.rodata) - } + . = ALIGN(4096); /* Align to page boundary */ - .data : { + /* Data Section */ + .data : AT(ADDR(.data) - 0xC0000000) + { *(.data) - } + } :data_seg - .bss : { + . = ALIGN(4096); /* Align to page boundary */ + + /* BSS Section */ + .bss : AT(ADDR(.bss) - 0xC0000000) + { *(.bss) - } + } :data_seg /* Use the same segment as .data */ } \ No newline at end of file diff --git a/x86-baremetal-toolchain.cmake b/x86-baremetal-toolchain.cmake index 7a2cece..d0d6139 100644 --- a/x86-baremetal-toolchain.cmake +++ b/x86-baremetal-toolchain.cmake @@ -12,4 +12,4 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_ASM_NASM_FLAGS "-f elf32") set(CMAKE_C_FLAGS "-m32 -ffreestanding -nostdlib") set(CMAKE_CXX_FLAGS "-m32 -ffreestanding -nostdlib") -set(CMAKE_EXE_LINKER_FLAGS "-T${CMAKE_CURRENT_LIST_DIR}/linker.ld -m32") \ No newline at end of file +set(CMAKE_EXE_LINKER_FLAGS "-e kernel_main -T${CMAKE_CURRENT_LIST_DIR}/linker.ld -m32 -z noexecstack") \ No newline at end of file