]> git.dujemihanovic.xyz Git - nameless-os.git/commitdiff
Enable A20 gate
authorDuje Mihanović <duje.mihanovic@skole.hr>
Thu, 16 Sep 2021 14:41:24 +0000 (16:41 +0200)
committerDuje Mihanović <duje.mihanovic@skole.hr>
Thu, 16 Sep 2021 14:41:24 +0000 (16:41 +0200)
Makefile
boot/x86/a20.s
boot/x86/boot [deleted file]
boot/x86/boot.s
boot/x86/print.s [new file with mode: 0644]
boot/x86/protected.s
kernel/kernel.c

index 9d1c34475a160d1bb3af2d6fd2ff3f28feb0169e..8d4b3653f3c8f16c9749254f8908bf568e48b17d 100644 (file)
--- 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}
index f6a292ba6bd23bbf2e24564b1351d530836930ae..b1c86cee6fb9521693c5e91ce146f78e585f3748 100644 (file)
@@ -1,42 +1,45 @@
 ; Some routines for managing the A20 line
 
 ; Check if A20 is enabled
-; Based on <https://wiki.osdev.org/A20_Line#Testing_the_A20_line>, slightly modified
-check_a20
-       pushf ; save EFLAGS
-       ; save segment and index registers
-       push ds 
+; Based on <https://wiki.osdev.org/A20_Line#Testing_the_A20_line>
+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 (file)
index a708651..0000000
Binary files a/boot/x86/boot and /dev/null differ
index be6c6531d0a581d9c7b49fa91bbd977e6d52f183..572ef74453e99d3efb870ac590d636ed038d7dfa 100644 (file)
@@ -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 (file)
index 0000000..bffa229
--- /dev/null
@@ -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
index d1c7eea34df31ac1a191c26bc2abeb6bb45924d6..966390af1a8dad8101595cfa6ed045159dc82636 100644 (file)
@@ -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
index 1e27a1b3ddcfdf0df9100505ae096dbe3a30cea0..7ac2ad72d79127aa2c942ca62a3561b3a8da9cb6 100644 (file)
@@ -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)