From 575ab461098b0ed9b08cb4e96bec39615498d634 Mon Sep 17 00:00:00 2001 From: pantonshire Date: Mon, 22 Jul 2024 09:33:02 +0100 Subject: [PATCH] enable a20 --- boot1.s | 97 ++++++++++++++++++++++++++++++++++++++++++++-------- defines.s | 12 +++++++ readme.md | 2 +- resources.md | 4 +++ 4 files changed, 99 insertions(+), 16 deletions(-) diff --git a/boot1.s b/boot1.s index e2cd47c..0eab9d8 100644 --- a/boot1.s +++ b/boot1.s @@ -223,22 +223,25 @@ main: call vga_println call test_a20 - test ax, ax + test al, al jnz .a20_enabled mov ax, msg_a20_disabled call vga_println - mov eax, 0xa1b2c3d4 - mov ebx, 0x12345678 - mov ecx, 0xdeadbeef - mov edx, 0xcafebabe - mov esi, 0xfeedface - mov edi, 0x66778899 - panic PANIC_TYPE_A20 + mov ax, msg_a20_8042 + call vga_println - ; TODO: enable a20 - hlt + ; 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 + panic PANIC_TYPE_A20 .a20_enabled: mov ax, msg_a20_enabled @@ -596,11 +599,6 @@ nybble_to_hex_char: ret -enable_a20: - fnstart - fnret - - ; Check whether the A20 line is enabled. Writes to the boot sector identifier. ; Arguments: none ; Return: @@ -638,9 +636,78 @@ test_a20: 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, (1 << INTEL_8042_STATUS_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, (1 << INTEL_8042_STATUS_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 + + msg_boot1_loaded db "boot1 loaded. hello!", 0 msg_a20_enabled db "a20 enabled", 0 msg_a20_disabled db "a20 not enabled", 0 +msg_a20_8042 db "trying 8042", 0 msg_panic db "panic!", 0 msg_reg_eip db "eip", 0 diff --git a/defines.s b/defines.s index 1a20f89..dbbc5e9 100644 --- a/defines.s +++ b/defines.s @@ -11,6 +11,18 @@ %define VGA_WIDTH 80 %define VGA_HEIGHT 25 +%define INTEL_8042_IO_DATA 0x60 +%define INTEL_8042_IN_STATUS 0x64 +%define INTEL_8042_OUT_CMD 0x64 + +%define INTEL_8042_STATUS_OBUF 0 +%define INTEL_8042_STATUS_IBUF 1 + +%define INTEL_8042_CMD_PS2_1_DISABLE 0xad +%define INTEL_8042_CMD_PS2_1_ENABLE 0xae +%define INTEL_8042_CMD_CONTROLLER_OUT_PORT_READ 0xd0 +%define INTEL_8042_CMD_CONTROLLER_OUT_PORT_WRITE 0xd1 + ; boot0 base stack frame variable offsets / globals ; (we use the same offsets once we copy the variables to the globals section) ; ------------------------------------------------------------------------------------------------- diff --git a/readme.md b/readme.md index f76904a..e8e4fc3 100644 --- a/readme.md +++ b/readme.md @@ -11,7 +11,7 @@ fit into 440 bytes. Its tasks are: `boot1.s` is the second-stage bootloader. Its tasks are: - [x] Load its own sectors not loaded by the first stage -- [ ] Enable A20 +- [x] Enable A20 - [ ] Detect available memory - [ ] Enter unreal mode - [ ] Read the kernel ELF from disk (don't have to parse the ELF just yet) diff --git a/resources.md b/resources.md index 500c556..b1c31a2 100644 --- a/resources.md +++ b/resources.md @@ -33,3 +33,7 @@ ## ELF - - + +## Intel 8042 PS/2 controller +- +-