bootloader:
Code: Select all
org 0x7C00 ; set up start address of bootloader
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; setup a stack and segment regs ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, ax
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; read kernel from floppy disk ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov [bootdrive], dl ; boot drive stored by BIOS in DL.
; we save it to [bootdrive] to play for safety.
load_kernel:
xor ax, ax ; mov ax, 0 => function "reset"
int 0x13
jc load_kernel ; trouble? try again
mov bx, 0x8000 ; set up start address of kernel
; set parameters for reading function
; 8-bit-wise for better overview
mov dl,[bootdrive] ; select boot drive
mov al, 59 ; read n sectors
mov ch, 0 ; cylinder = 0
mov cl, 2 ; sector = 2
mov dh, 0 ; head = 0
mov ah, 2 ; function "read"
int 0x13
jc load_kernel ; trouble? try again
; show loading message
mov si,loadmsg
call print_string
call Waitingloop
;;;;;;;;;;;;;
; A20-Gate ;
;;;;;;;;;;;;;
in al, 0x92 ; switch A20 gate via fast A20 port 92
cmp al, 0xff ; if it reads 0xFF, nothing's implemented on this port
je .no_fast_A20
or al, 2 ; set A20_Gate_Bit (bit 1)
and al, ~1 ; clear INIT_NOW bit (don't reset pc...)
out 0x92, al
jmp .A20_done
.no_fast_A20: ; no fast shortcut -> use the slow kbc...
call empty_8042
mov al, 0xD1 ; kbc command: write to output port
out 0x64, al
call empty_8042
mov al, 0xDF ; writing this to kbc output port enables A20
out 0x60, al
call empty_8042
.A20_done:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Load GDT, switch to PM, and jump to kernel ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cli ; clear interrupts
lgdt [gdtr] ; load GDT via GDTR (defined in file "gtd.inc")
mov eax, cr0 ; switch-over to Protected Mode
or eax, 1 ; set bit 0 of CR0 register
mov cr0, eax ;
jmp 0x8:0x8000 ; this is a 16-bit-FAR-Jmp, but CS is loaded with "index" 8 in GDT
; hence, the code will be interpreted as 32 bit from here on
; the address can be found in the linker script (phys)
;;;;;;;;;
; Calls ;
;;;;;;;;;
print_string:
mov ah, 0x0E ; VGA BIOS fnct. 0x0E: teletype
.loop:
lodsb ; grab a byte from SI
test al, al ; NUL?
jz .done ; if the result is zero, get out
int 0x10 ; otherwise, print out the character!
jmp .loop
.done:
ret
empty_8042:
call Waitingloop
in al, 0x64
cmp al, 0xff ; ... no real kbc at all?
je .done
test al, 1 ; something in input buffer?
jz .no_output
call Waitingloop
in al, 0x60 ; yes: read buffer
jmp empty_8042 ; and try again
.no_output:
test al, 2 ; command buffer empty?
jnz empty_8042 ; no: we can't send anything new till it's empty
.done:
ret
Waitingloop:
mov cx,0xFFFF
.loop_start:
dec cx
jnz .loop_start
ret
;;;;;;;;;;;;
; Includes ;
;;;;;;;;;;;;
%include "gdt.inc"
;;;;;;;;
; data ;
;;;;;;;;
bootdrive db 0 ; boot drive
loadmsg db "bootloader message: loading kernel ...",13,10,0
times 510-($-$$) hlt
db 0x55
db 0xAA
Code: Select all
[Bits 32]
section .text ; ld needs that for coff format
[global KernelStart]
KernelStart:
mov ax, 0x10
mov ds, ax ; data descriptor --> data, stack and extra segment
mov ss, ax
mov es, ax
xor eax, eax ; null desriptor --> FS and GS
mov fs, ax
mov gs, ax
mov esp, 0x200000 ; set stack below 2 MB limit
[extern _main] ; entry point in ckernel.c
call _main ; ->-> C-Kernel
jmp $