fixed bootloader by adding lba conversion from chs

This commit is contained in:
2025-08-02 21:48:51 -07:00
parent 267130281a
commit 4a189f482f

View File

@@ -21,25 +21,26 @@ start:
mov es, ax mov es, ax
; Load second-stage bootloader (boot1.asm) to 0x7E00 ; Load second-stage bootloader (boot1.asm) to 0x7E00
mov si, 0x7E00 ; Destination offset (ES already zero, so physical 0x7E00) mov ax, 1 ; LBA of boot1.asm (starts at sector 1)
mov al, 1 ; Number of sectors to read (adjust if needed) call lba_to_chs
mov cl, 1 ; Starting sector (CHS - sector number, 1-based) mov si, 0x7E00
mov al, 4 ; Number of sectors to read
call read_chs call read_chs
jc disk_error ; Jump if carry set (read error)
; Load kernel to 0x100000 (1 MB) ; Load kernel to 0x100000 (1 MB)
mov si, 0x0000 ; Destination offset mov si, 0x0000 ; Destination offset
mov ax, 0x1000 ; ES = 0x1000 (0x1000:0x0000 = 1 MB) mov ax, 0x1000 ; ES = 0x1000 (0x1000:0x0000 = 1 MB)
mov es, ax mov es, ax
xor bx, bx xor bx, bx
mov al, 16 ; Number of sectors for kernel (example) mov ax, 5 ; LBA of kernel start (boot1 is 4 sectors: LBA 14 → kernel at LBA 5)
mov cl, 2 ; Starting sector (adjust as per your disk layout) call lba_to_chs
mov al, 16 ; Number of sectors for kernel
call read_chs call read_chs
jc disk_error jc disk_error
; Memory Validation: Verify checksum of second stage bootloader ; Memory Validation: Verify checksum of second stage bootloader
mov si, 0x7E00 ; Start of second stage mov si, 0x7E00 ; Start of second stage
mov cx, 512 ; Size in bytes (adjust if more sectors loaded) mov cx, 512 * 4 ; Size in bytes (adjust if more sectors loaded)
call verify_checksum call verify_checksum
jc disk_error ; Jump if checksum fails jc disk_error ; Jump if checksum fails
@@ -100,16 +101,52 @@ verify_checksum:
; AL = number of sectors ; AL = number of sectors
; CL = starting sector (1-based) ; CL = starting sector (1-based)
; SI = destination offset (Segment:ES already set) ; SI = destination offset (Segment:ES already set)
; Inputs:
; AL = sector count
; CH = cylinder
; DH = head
; CL = sector (163, with top 2 bits as high cylinder bits)
; SI = destination offset (segment ES must be set)
; ----------------------------------------------------------------
; Convert LBA to CHS
; Inputs:
; AX = LBA sector number (0-based)
; Outputs:
; CH = cylinder
; DH = head
; CL = sector (1-63, top 2 bits are upper cylinder bits)
lba_to_chs:
pusha
xor dx, dx
mov bx, [sectors_per_track]
div bx ; AX = LBA / sectors_per_track, DX = LBA % spt
mov si, ax ; temp quotient
mov cx, [heads_per_cylinder]
xor dx, dx
div cx ; AX = cylinder, DX = head
mov ch, al ; CH = cylinder low
mov dh, dl ; DH = head
mov cl, sil ; CL = sector number (0-based)
inc cl ; Sector is 1-based
mov ah, al
and ah, 0xC0 ; upper 2 bits of cylinder
or cl, ah ; insert upper cylinder bits into CL
popa
ret
read_chs: read_chs:
pusha pusha
push dx push dx
mov cx, 5 mov cx, 5
.retry: .retry:
mov ah, 0x02 ; BIOS read sector mov ah, 0x02 ; BIOS: Read sectors
mov dl, [bootdev] ; Drive number mov dl, [bootdev] ; Boot device
; Assume CH, DH, CL already set before this call
int 0x13 int 0x13
jc .error
jc .error ; Carry flag set = error
pop dx pop dx
popa popa
ret ret
@@ -123,27 +160,58 @@ read_chs:
; ---------------------------------------------------------------- ; ----------------------------------------------------------------
enable_a20: enable_a20:
; Fast A20 gate method ; Try fast A20 gate method
in al, 0x92 in al, 0x92
or al, 0x02 or al, 0x02
and al, 0xFE ; Clear bit 0 to avoid fast A20 bugs
out 0x92, al out 0x92, al
; Fallback method (keyboard controller)
jc .fallbackenable_a20:
; Fast A20 method
in al, 0x92
or al, 0x02
and al, 0xFE ; Clear bit 0 to avoid fast A20 issues on some systems
out 0x92, al
; Verify A20 ; Verify A20
call check_a20 call check_a20
jnc .done jnc .done ; Success
; Fallback method
mov al, 0xAD ; Fallback: use keyboard controller method
out 0x64, al call .fallback
; ... (rest of keyboard controller code)
.done: .done:
ret ret
.fallback:
mov al, 0xAD ; Disable keyboard
out 0x64, al
call .wait_input_clear
mov al, 0xD0 ; Command: read output port
out 0x64, al
call .wait_output_full
in al, 0x60
or al, 0x02 ; Set A20 enable bit
mov bl, al
call .wait_input_clear
mov al, 0xD1 ; Command: write output port
out 0x64, al
call .wait_input_clear
mov al, bl
out 0x60, al
call .wait_input_clear
mov al, 0xAE ; Enable keyboard
out 0x64, al
ret
.wait_input_clear:
in al, 0x64
test al, 0x02
jnz .wait_input_clear
ret
.wait_output_full:
in al, 0x64
test al, 0x01
jz .wait_output_full
ret
check_a20: check_a20:
in al, 0x64 ; Read keyboard controller status in al, 0x64 ; Read keyboard controller status
test al, 0x02 ; Check if input buffer is full test al, 0x02 ; Check if input buffer is full
@@ -166,19 +234,6 @@ check_a20:
clc ; Clear carry flag to indicate success clc ; Clear carry flag to indicate success
ret ret
.fallback:
mov al, 0xAD
out 0x64, al
mov al, 0xD0
out 0x64, al
in al, 0x60
or al, 0x02
mov al, 0xD1
out 0x64, al
mov al, 0xAE
out 0x64, al
ret
; ---------------------------------------------------------------- ; ----------------------------------------------------------------
gdt_start: gdt_start:
dq 0x0000000000000000 ; Null descriptor dq 0x0000000000000000 ; Null descriptor