From: Duje Mihanović Date: Thu, 16 Sep 2021 14:41:24 +0000 (+0200) Subject: Enable A20 gate X-Git-Tag: 0.1.0~19 X-Git-Url: http://git.dujemihanovic.xyz/posts?a=commitdiff_plain;h=6c6312e540a570d376aae5551626128fcc1cd1c6;p=nameless-os.git Enable A20 gate --- diff --git a/Makefile b/Makefile index 9d1c344..8d4b365 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ boot.img: boot/x86/boot kernel/kernel.bin cat boot/x86/boot kernel/kernel.bin > $@ truncate -s1440K $@ -boot/x86/boot: boot/x86/boot.s boot/x86/a20.s boot/x86/protected.s +boot/x86/boot: boot/x86/boot.s boot/x86/a20.s boot/x86/protected.s boot/x86/print.s $(AS) -f bin boot/x86/boot.s -o $@ kernel/kernel.bin: ${KERNEL_OBJ} diff --git a/boot/x86/a20.s b/boot/x86/a20.s index f6a292b..b1c86ce 100644 --- a/boot/x86/a20.s +++ b/boot/x86/a20.s @@ -1,42 +1,45 @@ ; Some routines for managing the A20 line ; Check if A20 is enabled -; Based on , slightly modified -check_a20 - pushf ; save EFLAGS - ; save segment and index registers - push ds +; Based on +check_a20: + pushf + push ds push es push di push si - cli ; disable interrupts - xor ax, ax ; ax = 0 - mov es, ax ; es = 0 + cli + + xor ax, ax + mov es, ax - not ax ; ax = FFFFh - mov ds, ax ; ds = FFFFh + not ax + mov ds, ax mov di, 500h mov si, 510h - mov al, [es:di] ; preserve contents of 0:500h - mov ah, [ds:si] ; preserve contents of FFFFh:510h - push ax ; push all that to stack + mov al, byte [es:di] + push ax + + mov al, byte [ds:si] + push ax - mov byte [es:di], 0 ; set 0:500h to 0 - mov byte [ds:si], 0FFh ; set FFFFh:510h to FFh + mov byte [es:di], 0 + mov byte [ds:si], 0FFh - cmp byte [es:di], 0FFh ; compare 0:500h with FFh - ; if A20 is enabled, this will not be equal, but if A20 is disabled it will be + cmp byte [es:di], 0FFh - pop ax ; pop old contents of the 2 addresses - mov [ds:si], ah ; restore contents of FFFFh:510h - mov [es:di], al ; restore contents of 0:500h + pop ax + mov byte [ds:si], al + + pop ax + mov byte [es:di], al - xor ax, ax ; clear ax - je .exit ; if A20 is disabled, return 0 - mov ax, 1 ; otherwise return 1 + mov ax, 0 + je .exit + mov ax, 1 .exit pop si @@ -44,6 +47,67 @@ check_a20 pop es pop ds popf - sti ret +a20_i8042_wait + in al, 64h + test al, 2 + jnz a20_i8042_wait + ret + +a20_i8042_wait2 + in al, 64h + test al, 1 + jnz a20_i8042_wait2 + ret + +enable_a20 + mov ax, 2401h + int 15h + call check_a20 + cmp ax, 1 + jne .fail +.success + ret +.fail + cli ; disable interrupts + + call a20_i8042_wait + mov al, 0ADh ; disable 1st PS/2 port + out 64h, al + + call a20_i8042_wait + mov al, 0D0h ; read controller output port + out 64h, al + + call a20_i8042_wait2 + in al, 60h ; do the actual read + push ax ; save the register + + call a20_i8042_wait + mov al, 0D1h ; write byte to output port + out 64h, al + + call a20_i8042_wait + pop ax ; restore the register + or al, 2 ; toggle A20 bit + out 60h, al + + call a20_i8042_wait + mov al, 0AEh ; reenable 1st PS/2 port + out 64h, al + + call a20_i8042_wait + sti ; enable interrupts + ret + + call check_a20 + cmp ax, 1 + jne .fail2 + ret +.fail2 + mov si, A20_FAIL + call print + jmp $ + +A20_FAIL db "A20 enable fail, not booting!", 0 diff --git a/boot/x86/boot b/boot/x86/boot deleted file mode 100644 index a708651..0000000 Binary files a/boot/x86/boot and /dev/null differ diff --git a/boot/x86/boot.s b/boot/x86/boot.s index be6c653..572ef74 100644 --- a/boot/x86/boot.s +++ b/boot/x86/boot.s @@ -27,27 +27,34 @@ KERNEL_OFFSET equ 1000h ; where we will load our kernel jc read_error ; halt if read fails cmp al, 10 ; make sure we actually read 10 sectors jl read_error ; halt if we didn't - jmp switch_to_pm ; if all is good, begin the switch to 32-bit protected mode + + call check_a20 + cmp ax, 1 + jne a20_is_off + +a20_is_on + jmp switch_to_pm +a20_is_off + call enable_a20 + jmp switch_to_pm reset_error mov bx, 0B800h mov es, bx mov byte [es:di], '1' - jmp halt + jmp $ read_error mov bx, 0B800h mov es, bx mov byte [es:di], '2' - jmp halt - -halt jmp $ %include "a20.s" +%include "print.s" %include "protected.s" -BOOT_DRIVE db 0 ; reserve a spot in RAM for our boot drive variable +BOOT_DRIVE resb 1 times 510-($-$$) db 0 dw 0AA55h ; MBR signature diff --git a/boot/x86/print.s b/boot/x86/print.s new file mode 100644 index 0000000..bffa229 --- /dev/null +++ b/boot/x86/print.s @@ -0,0 +1,27 @@ +; cs:si - pointer to ASCIIZ string +print + pushf + push ax + push bx + push si + xor bh, bh + mov ah, 0Eh + +.loop + mov al, [cs:si] + cmp al, 0 + je .done + int 10h + inc si + jmp .loop + +.done + mov al, 0Dh + int 10h + mov al, 0Ah + int 10h + pop si + pop bx + pop ax + popf + ret diff --git a/boot/x86/protected.s b/boot/x86/protected.s index d1c7eea..966390a 100644 --- a/boot/x86/protected.s +++ b/boot/x86/protected.s @@ -37,10 +37,6 @@ protected mov ebp, 090000h mov esp, ebp - ; print a string to let us know that we survived the switch - mov ebx, pm_success - call pmprint - ; transfer control to the kernel call KERNEL_OFFSET @@ -70,7 +66,6 @@ pmprint popa ; restore registers from stack ret ; return -pm_success db "Now in protected mode", 0 video_memory equ 0B8000h ; the actual Global Descriptor Table diff --git a/kernel/kernel.c b/kernel/kernel.c index 1e27a1b..7ac2ad7 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -4,9 +4,10 @@ const char *string = "Hello there!\n\n\ Hopefully your machine manages to print this text.\n\ If it did, that's great news because I managed to write a partial VGA driver.\n\n\ Right now, the short-term roadmap is as follows:\n\n\ +* Complete the text-mode part of the VGA driver.\n\ * Enable interrupts using the PIC.\n\ * Write a driver for the Intel 8042 PS/2 controller so the OS can receive keystrokes.\n\ -* A working i8042 driver will also aid in enabling A20 Gate, which should be done ASAP so the OS can address odd (as in odd/even number) megabytes.\n\n\ +* Once all that is done, it would be desirable to start the switch to userspace so the OS can actually be remotely usable.\n\n\ Feel free to mess around with the code, although I doubt it will be very interesting at the moment.\n"; void _start(void)