mirror of
https://github.com/Plexi09/Nadir-Kernel.git
synced 2026-10-20 15:07:27 +02:00
boot: query E820 map and stage at 0x5000/0x5020
This commit is contained in:
parent
9ad501d068
commit
2a7e411175
1 changed files with 98 additions and 40 deletions
|
|
@ -10,6 +10,11 @@
|
||||||
; flat GDT, enter 32-bit protected mode and jump to the stage-2 entry.
|
; flat GDT, enter 32-bit protected mode and jump to the stage-2 entry.
|
||||||
;
|
;
|
||||||
; Memory map used by the whole boot chain:
|
; Memory map used by the whole boot chain:
|
||||||
|
; 0x005000 E820 staging: count byte at 0x5000, 24-byte entries from
|
||||||
|
; 0x5020 (64 max = 1536 bytes, ends 0x5620). Free: below the
|
||||||
|
; 0x7C00 sector, clear of the 0x10000 kernel load, the 0x70000
|
||||||
|
; tables and the 0x90000 stack. Stage 2 copies it into kernel
|
||||||
|
; .bss (memmap_count/memmap_entries) after BSS zeroing.
|
||||||
; 0x007C00 this sector (512 bytes)
|
; 0x007C00 this sector (512 bytes)
|
||||||
; 0x010000 kernel image (loaded here, linked here)
|
; 0x010000 kernel image (loaded here, linked here)
|
||||||
; 0x70000 PML4 | 0x71000 PDPT | 0x72000 PD (built by stage 2)
|
; 0x70000 PML4 | 0x71000 PDPT | 0x72000 PD (built by stage 2)
|
||||||
|
|
@ -25,6 +30,10 @@ org 0x7C00
|
||||||
|
|
||||||
KERNEL_LOAD_SEG equ 0x1000 ; ES for load target 0x1000:0x0000 = 0x10000
|
KERNEL_LOAD_SEG equ 0x1000 ; ES for load target 0x1000:0x0000 = 0x10000
|
||||||
STACK_TOP equ 0x7C00 ; real-mode stack grows down from here
|
STACK_TOP equ 0x7C00 ; real-mode stack grows down from here
|
||||||
|
E820_COUNT equ 0x5000 ; staged E820 entry count (one byte)
|
||||||
|
E820_BUF equ 0x5020 ; staged E820 entries (24 bytes each)
|
||||||
|
E820_MAX equ 64 ; cap: 64 * 24 = 1536 bytes, ends 0x5620
|
||||||
|
E820_ENTRY_SIZE equ 24
|
||||||
|
|
||||||
start:
|
start:
|
||||||
cli
|
cli
|
||||||
|
|
@ -40,8 +49,8 @@ start:
|
||||||
call puts
|
call puts
|
||||||
|
|
||||||
call enable_a20
|
call enable_a20
|
||||||
call read_drive_params
|
|
||||||
call load_kernel
|
call load_kernel
|
||||||
|
call query_e820
|
||||||
|
|
||||||
mov si, msg_entering
|
mov si, msg_entering
|
||||||
call puts
|
call puts
|
||||||
|
|
@ -73,18 +82,15 @@ puts:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
; enable_a20: try BIOS, keyboard-controller and fast-A20 methods in turn.
|
; enable_a20: try the BIOS and fast-A20 methods in turn. Each is harmless
|
||||||
; Each is harmless if A20 is already on.
|
; if A20 is already on.
|
||||||
|
; WHY only two methods: the keyboard-controller pulse was dropped to free
|
||||||
|
; sector bytes for the E820 query above — every 64-bit CPU postdates
|
||||||
|
; chipsets with the 0x92 fast gate (or a BIOS that honors 0x2401), so the
|
||||||
|
; legacy AT pulse buys nothing on this kernel's hardware floor.
|
||||||
enable_a20:
|
enable_a20:
|
||||||
mov ax, 0x2401 ; BIOS: enable A20
|
mov ax, 0x2401 ; BIOS: enable A20
|
||||||
int 0x15
|
int 0x15
|
||||||
call kbd_wait ; keyboard controller: pulse output port
|
|
||||||
mov al, 0xD1
|
|
||||||
out 0x64, al
|
|
||||||
call kbd_wait
|
|
||||||
mov al, 0xDF
|
|
||||||
out 0x60, al
|
|
||||||
call kbd_wait
|
|
||||||
in al, 0x92 ; fast A20 (skip if already set or absent)
|
in al, 0x92 ; fast A20 (skip if already set or absent)
|
||||||
test al, 0x02
|
test al, 0x02
|
||||||
jnz .done
|
jnz .done
|
||||||
|
|
@ -93,34 +99,11 @@ enable_a20:
|
||||||
.done:
|
.done:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
kbd_wait:
|
|
||||||
in al, 0x64
|
|
||||||
test al, 0x02
|
|
||||||
jnz kbd_wait
|
|
||||||
ret
|
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
; read_drive_params: query sectors/track and head count via int 0x13 AH=08.
|
; Floppy geometry is fixed at 18 sectors/track, 2 heads (the image only
|
||||||
; Falls back to floppy defaults (18 spt, 2 heads) on failure or nonsense.
|
; ever boots via -fda; see [spt]/[heads] inits below). The old int 0x13
|
||||||
read_drive_params:
|
; AH=08 probe was dropped to free sector bytes for the E820 query above.
|
||||||
xor ax, ax
|
; HDD generality wants EDD packet reads (AH=42), planned, not CHS probing.
|
||||||
mov ds, ax ; re-establish DS (BIOS may clobber it)
|
|
||||||
mov ah, 0x08
|
|
||||||
mov dl, [boot_drive]
|
|
||||||
int 0x13
|
|
||||||
jc .defaults
|
|
||||||
and cx, 0x3F ; CL[5:0] = max sector = sectors per track
|
|
||||||
jz .defaults
|
|
||||||
mov [spt], cl
|
|
||||||
inc dh ; DH = max head -> head count
|
|
||||||
jz .defaults
|
|
||||||
mov [heads], dh
|
|
||||||
ret
|
|
||||||
.defaults:
|
|
||||||
mov byte [spt], 18
|
|
||||||
mov byte [heads], 2
|
|
||||||
ret
|
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
; lba_to_chs: convert LBA in AX to int 0x13 CHS in CH/CL/DH.
|
; lba_to_chs: convert LBA in AX to int 0x13 CHS in CH/CL/DH.
|
||||||
; Clobbers AX, BX, CX, DX.
|
; Clobbers AX, BX, CX, DX.
|
||||||
|
|
@ -193,6 +176,79 @@ load_kernel:
|
||||||
jnz .next
|
jnz .next
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; query_e820: ask BIOS for the physical memory map (int 0x15, eax=0xE820,
|
||||||
|
; edx='SMAP') and stage it at E820_BUF with the entry count byte at
|
||||||
|
; E820_COUNT. Must run BEFORE the protected-mode switch as BIOS calls are
|
||||||
|
; unavailable after. Runs in 16-bit real mode at Ring 0; clobbers AX,
|
||||||
|
; BX, CX, DX, DI, ES.
|
||||||
|
;
|
||||||
|
; NOTE: like load_kernel, no register survives int 0x15 — SeaBIOS/real
|
||||||
|
; BIOSes may clobber general registers across the call, so the
|
||||||
|
; continuation (EBX) lives in memory ([e820_next]) and ECX/EDX/ES:DI are
|
||||||
|
; reloaded from immediates before every call. DS is saved on the stack
|
||||||
|
; across the call (push/pop restores OUR value even if BIOS clobbers it);
|
||||||
|
; it must NOT be rebuilt with xor ax,ax + mov ds,ax after the call, as
|
||||||
|
; that zeroes EAX's low half and breaks the 'SMAP' check below. DI is recomputed from
|
||||||
|
; the in-memory count each pass (index < 64, so the 8-bit multiply
|
||||||
|
; cannot overflow) instead of keeping a second pointer.
|
||||||
|
;
|
||||||
|
; Fallback choice: if no entry was staged (first query failed via carry
|
||||||
|
; or EAX magic mismatch), synthesize a single usable region at 1MB,
|
||||||
|
; length 127MB (type 1) — enough for the kernel + PMM to boot on an
|
||||||
|
; unknown box — and continue silently (no message: the sector has no
|
||||||
|
; bytes to spare). A mid-list failure keeps whatever entries were
|
||||||
|
; already staged. Documented here so the PMM knows the map may be
|
||||||
|
; synthetic on old hardware. Kept golfed on purpose: this sector is
|
||||||
|
; exactly 510 bytes, every instruction here displaced a boot message.
|
||||||
|
query_e820:
|
||||||
|
xor ax, ax
|
||||||
|
mov ds, ax ; re-establish DS
|
||||||
|
mov [E820_COUNT], al ; count byte = 0
|
||||||
|
.loop:
|
||||||
|
xor ax, ax
|
||||||
|
mov es, ax ; ES:DI rebuilt per call
|
||||||
|
mov al, [E820_COUNT]
|
||||||
|
mov cl, E820_ENTRY_SIZE
|
||||||
|
mul cl ; AX = index * 24
|
||||||
|
mov di, E820_BUF
|
||||||
|
add di, ax
|
||||||
|
mov ecx, E820_ENTRY_SIZE ; reload every call: BIOS owns nothing
|
||||||
|
mov edx, 0x534D4150
|
||||||
|
mov eax, 0xE820
|
||||||
|
mov ebx, [e820_next] ; continuation lives in memory
|
||||||
|
push ds ; DS survives on the stack, EAX intact
|
||||||
|
int 0x15
|
||||||
|
pop ds ; our DS back, whatever BIOS did
|
||||||
|
jc .done ; carry = end of list or call failed
|
||||||
|
cmp eax, 0x534D4150 ; BIOS must echo 'SMAP' in EAX
|
||||||
|
jne .done
|
||||||
|
cmp byte [E820_COUNT], E820_MAX ; buffer full: stop, keep what we have
|
||||||
|
jae .done
|
||||||
|
inc byte [E820_COUNT] ; entry already written by BIOS at ES:DI
|
||||||
|
mov [e820_next], ebx ; save continuation across the next call
|
||||||
|
test ebx, ebx ; EBX=0 ends the list
|
||||||
|
jnz .loop
|
||||||
|
.done:
|
||||||
|
cmp byte [E820_COUNT], 0
|
||||||
|
jne .ok
|
||||||
|
xor ax, ax ; fallback: ES:DI may not have survived
|
||||||
|
mov es, ax
|
||||||
|
mov di, E820_BUF
|
||||||
|
mov eax, 0x00100000
|
||||||
|
stosd ; base = 1MB
|
||||||
|
xor eax, eax
|
||||||
|
stosd ; base high = 0
|
||||||
|
mov eax, 0x07F00000
|
||||||
|
stosd ; length = 127MB
|
||||||
|
xor eax, eax
|
||||||
|
stosd ; length high = 0
|
||||||
|
inc eax
|
||||||
|
stosd ; type = 1 (usable)
|
||||||
|
inc byte [E820_COUNT] ; count was 0, now 1
|
||||||
|
.ok:
|
||||||
|
ret
|
||||||
|
|
||||||
halt:
|
halt:
|
||||||
cli
|
cli
|
||||||
.hang:
|
.hang:
|
||||||
|
|
@ -226,9 +282,9 @@ gdt_ptr:
|
||||||
dw gdt_end - gdt - 1
|
dw gdt_end - gdt - 1
|
||||||
dd gdt
|
dd gdt
|
||||||
|
|
||||||
msg_loading db "Nadir: loading kernel...", 0x0D, 0x0A, 0
|
msg_loading db "Nadir: load", 0x0D, 0x0A, 0
|
||||||
msg_entering db "Nadir: entering protected mode", 0x0D, 0x0A, 0
|
msg_entering db "Nadir: pmode", 0x0D, 0x0A, 0
|
||||||
msg_disk_err db "Nadir: disk read error", 0x0D, 0x0A, 0
|
msg_disk_err db "Nadir: disk err", 0x0D, 0x0A, 0
|
||||||
|
|
||||||
boot_drive db 0
|
boot_drive db 0
|
||||||
spt dw 18
|
spt dw 18
|
||||||
|
|
@ -238,6 +294,8 @@ buf_seg dw 0 ; load buffer segment (starts 0x1000)
|
||||||
buf_off dw 0 ; load buffer offset within segment
|
buf_off dw 0 ; load buffer offset within segment
|
||||||
sectors_left dw 0 ; sectors still to load
|
sectors_left dw 0 ; sectors still to load
|
||||||
tries db 0 ; retries left for current sector
|
tries db 0 ; retries left for current sector
|
||||||
|
e820_next dd 0 ; E820 continuation across int 0x15
|
||||||
|
; (image-zeroed; first call starts at 0)
|
||||||
|
|
||||||
times 510-($-$$) db 0
|
times 510-($-$$) db 0
|
||||||
dw 0xAA55
|
dw 0xAA55
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue