BITS 16
global pread_sector
extern boot2_main
%define BIOS_MEMDETECT_MAGIC 0x534d4150
%define MMAP_BASE 0x1000
start:
mov si, hallo
call print
push dword MMAP_BASE
call near detect_memory
add esp, 4
; hide cursor
mov ah, 0x01
mov cx, 0x2607
int 0x10
jmp enter_protected
hallo: db 'xos boot loader stage 1 ...', 0xa, 0xd, 0
print:
mov ah, 0x0e
.repeat:
lodsb
cmp al, 0
je .done
int 0x10
jmp .repeat
.done:
ret
enter_protected:
cli
lgdt [gdt_desc]
mov eax, cr0
or al, 1
mov cr0, eax
jmp 0x08:protected_main
detect_memory:
mov di, [esp + 2] ; mmap base
add di, 4 ; first dword reserved for count
xor ebp, ebp ; valid entries counter
xor ebx, ebx
call .e820
jc .failed
; first call checks:
cmp eax, BIOS_MEMDETECT_MAGIC
jne .failed
test ebx, ebx
je .failed
.item:
jcxz .next
cmp cl, 0x18 ; extended record?
jb .normal
.extended:
test [di + 20], byte 1 ; ignored
je .next
.normal:
mov ecx, [di + 8]
or ecx, [di + 12] ; zero length?
jz .next
inc bp
add di, 20
.next:
test ebx, ebx
je .finish
call .e820
jc .finish
jmp .item
.failed:
mov ebp, 0
.finish:
mov di, [esp+2]
mov [di], ebp
ret
.e820
mov eax, 0xe820
mov edx, BIOS_MEMDETECT_MAGIC
mov [di + 20], dword 1
mov ecx, 24
int 0x15
ret
bits 32
protected_main:
mov eax, 0x10
mov ds, ax
mov es, ax
mov ss, ax
mov eax, 0x8000
mov esp, eax
jmp boot2_main
; pread_sector(unit32_t lba, uint8_t *dest)
%define DRIVE_PORT_BASE 0x01f0
%define DRIVE_PORT(n) (DRIVE_PORT_BASE + n)
%macro PORT_OUTB 2
mov dx, %1
mov al, %2
out dx, al
%endmacro
pread_sector:
push ebp
mov ebp, esp
push edi
mov ecx, 8
mov dx, DRIVE_PORT(7)
in al, dx
in al, dx
in al, dx
in al, dx
mov eax, [ebp + 8]
shr eax, 24
and eax, 0x0f
or al, 0xe0
PORT_OUTB DRIVE_PORT(6), al ; drive select MASTER | 4bits of LBA high
mov ecx, 4
mov dx, DRIVE_PORT(7)
.delay:
in al, dx
loop .delay
;PORT_OUTB DRIVE_PORT(1), 0x00 ; legacy
PORT_OUTB DRIVE_PORT(2), 0x01 ; sector count
mov eax, [ebp + 8]
and eax, 0xff
PORT_OUTB DRIVE_PORT(3), al ; LBA low
mov eax, [ebp + 8]
shr eax, 8
and eax, 0xff
PORT_OUTB DRIVE_PORT(4), al ; LBA mid
mov eax, [ebp + 8]
shr eax, 16
and eax, 0xff
PORT_OUTB DRIVE_PORT(5), al ; LBA high
PORT_OUTB DRIVE_PORT(7), 0x20 ; PIO READ
mov dx, DRIVE_PORT(7)
.wait_rdy:
in al, dx
and al, 0x80
jnz .wait_rdy
mov dx, DRIVE_PORT(0)
mov edi, [ebp + 12]
mov ecx, 0x80 ; 128 x 4 byte = 512 byte block
.read_loop:
in eax, dx
stosd
loop .read_loop
pop edi
pop ebp
ret
bits 16
gdt_desc:
dw 0x1f
dd gdt
gdt:
gdt_entry0: ; invalid
.limit_low: dw 0x42
.base_low: dw 0
.base_middle: db 0
.access: db 0 ;b10011010
.granularity: db 0 ;b11000000
.base_high: db 0
gdt_entry1: ; flat code
.limit_low: dw 0xffff
.base_low: dw 0
.base_middle: db 0
.access: db 0b10011010
.granularity: db 0b11001111
.base_high: db 0
gdt_entry2: ; flat data
.limit_low: dw 0xffff
.base_low: dw 0x0000
.base_middle: db 0
.access: db 0b10010010
.granularity: db 0b11001111
.base_high: db 0