enable a20 in stage 2 prelude

main
pantonshire 1 year ago
parent a86d73e6ee
commit 121e13165b

@ -206,10 +206,128 @@ panic_simple:
%endif
; TODO:
; - Make sure A20 is enabled before the switch to protected mode
; Check whether the A20 line is enabled. Writes to the boot sector identifier.
; Arguments: none
; Return:
; - ax: 0 if A20 disabled, nonzero if A20 enabled
; Clobber: none
test_a20:
push bp
mov bp, sp
push gs
; Restore the boot sector identifier in case it was overwritten by anything.
mov word [0x7dfe], 0xaa55
mov ax, 0xffff
mov gs, ax
xor ax, ax
; If the word at 0x107dfe (1 MiB after the boot sector identifier) is different to the boot
; sector identifier, than A20 must be enabled.
cmp word gs:[0x7e0e], 0xaa55
setne al
jne .return
; Even if A20 was enabled, the two words may have been equal by chance, so we temporarily swap
; the boot sector identifier bytes and test again.
ror word [0x7dfe], 8
cmp word gs:[0x7e0e], 0x55aa
setne al
ror word [0x7dfe], 8
jmp .return
.return:
pop gs
pop bp
ret
; Wait for the Intel 8042 input buffer to become empty, so we can write.
; Arguments: none
; Return: none
; Clobber: al
intel_8042_wait_write:
.loop:
; Read the 8042 status register.
in al, INTEL_8042_IN_STATUS
; Input buffer status flag set means the input buffer is full, so loop in this case.
test al, INTEL_8042_STATUS_MASK_IBUF
jnz .loop
ret
; Wait for the Intel 8042 output buffer to become filled, so we can read.
; Arguments: none
; Return: none
; Clobber: al
intel_8042_wait_read:
.loop:
; Read the 8042 status register.
in al, INTEL_8042_IN_STATUS
; Output buffer status flag unset means output buffer is empty, so loop in this case.
test al, INTEL_8042_STATUS_MASK_OBUF
jz .loop
ret
; Try to enable A20 using the Intel 8042 PS/2 keyboard controller.
; Arguments: none
; Return: none
; Clobber: ax, cx, dx
enable_a20_intel_8042:
; Temporarily disable the keyboard.
call intel_8042_wait_write
mov al, INTEL_8042_CMD_PS2_1_DISABLE
out INTEL_8042_OUT_CMD, al
; Read the controller output port.
call intel_8042_wait_write
mov al, INTEL_8042_CMD_CONTROLLER_OUT_PORT_READ
out INTEL_8042_OUT_CMD, al
call intel_8042_wait_read
in al, INTEL_8042_IO_DATA
; The second bit is "A20 enabled", so set it.
mov cl, al
or cl, 2
; Write the modified byte back to the controller output port.
call intel_8042_wait_write
mov al, INTEL_8042_CMD_CONTROLLER_OUT_PORT_WRITE
out INTEL_8042_OUT_CMD, al
call intel_8042_wait_write
mov al, cl
out INTEL_8042_IO_DATA, al
; Re-enable the keyboard.
call intel_8042_wait_write
mov al, INTEL_8042_CMD_PS2_1_ENABLE
out INTEL_8042_OUT_CMD, al
; Wait for writes to finish.
call intel_8042_wait_write
ret
prelude_main:
call test_a20
test al, al
jnz .a20_enabled
; Try to enable A20 using the Intel 8042 PS/2 keyboard controller.
call enable_a20_intel_8042
call test_a20
test al, al
jnz .a20_enabled
; TODO: try other methods first before we panic:
; - [ ] BIOS interrupt
; - [ ] Fast A20 enable
jmp panic_simple
.a20_enabled:
mov ax, 0x0003
int 0x10

@ -1,7 +1,6 @@
run:
qemu-system-x86_64 \
-monitor stdio \
-d int \
-no-reboot \
-bios seabios/out/bios.bin \
-m 512M \

Loading…
Cancel
Save