; legacy BIOS PC-boot code, starts in 16-bit real mode ; BIOS always loads us to this location [org 0x7c00] ; 16-bit real-mode [bits 16] ; export a map of kernel symbols for debugging [map symbols kernel.map] ; initialize segment registers mov ax, 0 mov ds, ax mov es, ax mov ss, ax ; dl contains the boot drive, primarily because that's the last function ; called by the BIOS MBR loader, we remember that for loading additional ; blocks from the boot medium mov [BOOT_DRIVE], dl ; make sure we know the location of the stack by setting it on our own ; this stack is only used in real mode in stage 1, so it's growing from ; 0xffff down mov bp, 0xFFFF mov sp, bp ; print out some information about CPU mode and BIOS boot drive mov si, MESSAGE_REAL_MODE call print_string mov si, MESSAGE_BOOT_DRIVE call print_string mov ax, dx call print_hex call print_newline ; print we are going to load stage 2 of the boot blocks mov si, MESSAGE_LOADING_STAGE_2 call print_string ; load stage 2 and the kernel together to 0x7e00 (directly ; after the boot sector) mov dl, [BOOT_DRIVE] call read_from_disk ; jump over variables and subroutines of stage 1 and execute stage 2 jmp stage2 %include "stage1_functions.asm" DISK_ERROR: db "DISK ERROR ", 0 SHORT_READ: db "DISK SHORT READ", 0 MESSAGE_REAL_MODE: db "Started in 16-bit Real Mode", 13, 10, 0 MESSAGE_BOOT_DRIVE: db "Booting from drive ", 0 MESSAGE_LOADING_STAGE_2: db "Loading stage 2 boot loader", 13, 10, 0 BOOT_DRIVE: db 0 ; pad rest of sector with zeroes so we get 512 bytes in the end times 510-($-$$) db 0 ; magic number of a boot sector dw 0xaa55 stage2: ; print a message that we are indeed in stage 2 now mov si, MESSAGE_STAGE_2_LOADED call print_string ; remember current position on screen, otherwise we loose this ; information after switching to protected mode call current_row mov [CURSOR_Y], dh ; enter protected mode call switch_to_protected_mode ; we should never get here, but just in case jmp $ MESSAGE_STAGE_2_LOADED: db "Stage 2 boot sectors loaded", 13, 10, 0 %include "switch_mode.asm" [bits 32] BEGIN_PROTECTED_MODE: ; we switched to protected mode mov si, MESSAGE_PROTECTED_MODE call pm_print_string call pm_print_newline ; check sanity of kernel by searching for MAGIC string at a given ; position call check_magic cmp ax, 1 jnz HALT_OS ; print a message before we call the C level kernel mov si, MESSAGE_CALL_C_ENTRY call pm_print_string call pm_print_newline ; call our kernel call c_entry ; restore cursor variables from VGA hardware call read_hardware_vga_cursor ; "kernel halted" message, when we terminate the C kernel HALT_OS: mov si, MESSAGE_HALTED call pm_print_string call pm_print_newline ; end of C, disable interupts again, NMIs can still happen ; make sure we loop endlessly here but without burning too ; much CPU cli _halt_loop: hlt jmp _halt_loop MESSAGE_PROTECTED_MODE: db "Switched to 32-bit Protected Mode", 0 MESSAGE_CALL_C_ENTRY: db "Calling C entry function", 0 MESSAGE_HALTED: db "Operating system halted", 0 %include "stage2_functions.asm" ; make sure we have full sectors, stage one is 512 bytes, so we ; have to will up 3 sectors times 2048-($-$$) db 0 ; position is 0x8400 now for the C entry c_entry: