:: commit 6b75c3bd8b0c7b1a70e703c51f6dc1dabbc2a0f9

mintsuki <mintsuki@protonmail.com> — 2020-10-15 09:35

parents: e44096cb07

Move A20 handler out of bootsector and into stage 2

diff --git a/bootsect/a20_enabler.inc b/bootsect/a20_enabler.inc
deleted file mode 100644
index 0a50d234..00000000
--- a/bootsect/a20_enabler.inc
+++ /dev/null
@@ -1,126 +0,0 @@
-a20_check:
-
-; *************************************************
-;     Checks if the A20 address line is enabled
-; *************************************************
-
-; OUT:
-; Carry if disabled, cleared if enabled
-
-push ax										; Save registers
-push bx
-push es
-push fs
-
-xor ax, ax									; Set ES segment to zero
-mov es, ax
-not ax										; Set FS segment to 0xFFFF
-mov fs, ax
-
-mov ax, word [es:0x7DFE]					; Check using boot signature
-cmp word [fs:0x7E0E], ax					; If A20 is disabled, this should be the
-											; same address as the boot signature
-je .change_values							; If they are equal, check again with another value
-
-.enabled:
-
-clc											; A20 is enabled, clear carry flag
-jmp .done
-
-.change_values:
-
-mov word [es:0x7DFE], 0x1234				; Change the value of 0000:7DFE to 0x1234
-cmp word [fs:0x7E0E], 0x1234				; Is FFFF:7E0E changed as well?
-jne .enabled								; If it is, A20 is enabled
-
-stc											; Otherwise set carry
-
-.done:
-
-mov word [es:0x7DFE], ax					; Restore boot signature
-pop fs										; Restore registers
-pop es
-pop bx
-pop ax
-ret											; Exit routine
-
-
-
-
-enable_a20:
-
-; ********************************************
-;     Tries to enable the A20 address line
-; ********************************************
-
-; OUT:
-; Carry cleared if success, set if fail
-
-push eax								; Save registers
-
-call a20_check							; Check if a20 is already enabled
-jnc .done								; If it is, we are done
-
-mov ax, 0x2401							; Use BIOS to try to enable a20
-int 0x15
-
-call a20_check							; Check again to see if BIOS succeeded
-jnc .done								; If it has, we are done
-
-.keyboard_method:
-
-cli										; Disable interrupts
-
-call .a20wait							; Use the keyboard controller to try and
-mov al, 0xAD							; open the A20 gate
-out 0x64, al
-
-call .a20wait
-mov al, 0xD0
-out 0x64, al
-
-call .a20wait2
-in al, 0x60
-push eax
-
-call .a20wait
-mov al, 0xD1
-out 0x64, al
-
-call .a20wait
-pop eax
-or al, 2
-out 0x60, al
-
-call .a20wait
-mov al, 0xAE
-out 0x64, al
-
-call .a20wait
-sti										; Enable interrupts back
-
-jmp .keyboard_done
-
-.a20wait:
-
-in al, 0x64
-test al, 2
-jnz .a20wait
-ret
-
-.a20wait2:
-
-in al, 0x64
-test al, 1
-jz .a20wait2
-ret
-
-.keyboard_done:
-
-call a20_check							; Check for success
-
-; Now just quit the routine, forwarding the carry flag to the caller
-
-.done:
-pop eax
-ret
diff --git a/bootsect/bootsect.asm b/bootsect/bootsect.asm
index fa167af7..618c8bc9 100644
--- a/bootsect/bootsect.asm
+++ b/bootsect/bootsect.asm
@@ -41,96 +41,38 @@ start:
     mov dl, 0x80
 
   .continue:
-    mov si, LoadingMsg
-    call simple_print
-
-    ; ****************** Load stage 1.5 ******************
-
     ; Make sure int 13h extensions are supported
     mov ah, 0x41
     mov bx, 0x55aa
     int 0x13
-    jc err_reading_disk
+    jc err
     cmp bx, 0xaa55
-    jne err_reading_disk
+    jne err
 
     ; If int 13h extensions are supported, then we are definitely running on
     ; a 386+. We have no idea whether the upper 16 bits of esp are cleared, so
     ; make sure that is the case now.
     mov esp, 0x7c00
 
-    mov eax, dword [stage15_sector]
-    mov bx, 0x7e00
-    mov cx, 1
-    call read_sectors
-
-    jc err_reading_disk
-
-    jmp 0x7e00
-
-err_reading_disk:
-    mov si, ErrReadDiskMsg
-    call simple_print
-    jmp halt
-
-err_enabling_a20:
-    mov si, ErrEnableA20Msg
-    call simple_print
-    jmp halt
-
-halt:
-    hlt
-    jmp halt
-
-; Data
-
-LoadingMsg db 0x0D, 0x0A, 'Limine', 0x0D, 0x0A, 0x0A, 0x00
-ErrReadDiskMsg db 0x0D, 0x0A, 'Disk err', 0x00
-ErrEnableA20Msg db 0x0D, 0x0A, 'A20 err', 0x00
-
-times 0xda-($-$$) db 0
-times 6 db 0
-
-; Includes
-
-%include 'simple_print.inc'
-%include 'disk.inc'
-
-times 0x1b0-($-$$) db 0
-stage15_sector: dd 1
-
-times 0x1b8-($-$$) db 0
-times 510-($-$$) db 0
-dw 0xaa55
-
-; ********************* Stage 1.5 *********************
-
-stage15:
-    push es
     push 0x7000
     pop es
-    mov eax, dword [stage15_sector]
-    inc eax
+    mov eax, dword [stage2_sector]
     xor bx, bx
-    mov cx, 62
+    mov cx, 63
     call read_sectors
-    pop es
-    jc err_reading_disk
-
-    call enable_a20
-    jc err_enabling_a20
+    jc err
 
     call load_gdt
 
     cli
 
     mov eax, cr0
-    or al, 1
+    bts ax, 0
     mov cr0, eax
 
-    jmp 0x18:.pmode
+    jmp 0x18:.mode32
     bits 32
-  .pmode:
+  .mode32:
     mov ax, 0x20
     mov ds, ax
     mov es, ax
@@ -142,16 +84,34 @@ stage15:
     push edx
 
     push stage2.size
-    push (stage2 - 0x8000) + 0x70000
+    push (stage2 - decompressor) + 0x70000
 
     call 0x70000
 
 bits 16
-%include 'a20_enabler.inc'
+
+err:
+    hlt
+    jmp err
+
+times 0xda-($-$$) db 0
+times 6 db 0
+
+; Includes
+
+%include 'disk.inc'
 %include 'gdt.inc'
 
-times 1024-($-$$) db 0
+times 0x1b0-($-$$) db 0
+stage2_sector: dd 1
+
+times 0x1b8-($-$$) db 0
+times 510-($-$$) db 0
+dw 0xaa55
+
+; ********************* Stage 2 *********************
 
+decompressor:
 incbin '../decompressor/decompressor.bin'
 
 align 16
diff --git a/bootsect/simple_print.inc b/bootsect/simple_print.inc
deleted file mode 100644
index ee68dcc9..00000000
--- a/bootsect/simple_print.inc
+++ /dev/null
@@ -1,22 +0,0 @@
-; **************************************
-;     Prints a string using the BIOS
-; **************************************
-
-; IN:
-; SI = points to a 0x00 terminated string
-
-simple_print:
-    push ax
-    push si
-    ; int 0x10, function 0x0e (print character)
-    mov ah, 0x0e
-  .loop:
-    lodsb
-    test al, al
-    jz .done
-    int 0x10
-    jmp .loop
-  .done:
-    pop si
-    pop ax
-    ret
diff --git a/limine.bin b/limine.bin
index 0d97ae49..c12c9867 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/stage2/main.c b/stage2/main.c
index b20eb736..a43a8c72 100644
--- a/stage2/main.c
+++ b/stage2/main.c
@@ -6,6 +6,7 @@
 #include <lib/part.h>
 #include <lib/config.h>
 #include <sys/e820.h>
+#include <sys/a20.h>
 #include <lib/print.h>
 #include <fs/file.h>
 #include <lib/elf.h>
@@ -24,6 +25,9 @@ void entry(int boot_drive) {
 
     print("Limine " LIMINE_VERSION "\n\n");
 
+    if (!a20_enable())
+        panic("Could not enable A20 line");
+
     print("Boot drive: %x\n", boot_drive);
 
     // Look for config file.
diff --git a/stage2/sys/a20.c b/stage2/sys/a20.c
new file mode 100644
index 00000000..571f7d6c
--- /dev/null
+++ b/stage2/sys/a20.c
@@ -0,0 +1,54 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <sys/a20.h>
+#include <sys/cpu.h>
+#include <lib/real.h>
+
+bool a20_check(void) {
+    if (mminw(0x7dfe) != mminw(0x7dfe + 0x100000))
+        return true;
+
+    mmoutw(0x7dfe, ~mminw(0x7dfe));
+
+    if (mminw(0x7dfe) != mminw(0x7dfe + 0x100000))
+        return true;
+
+    return false;
+}
+
+// Keyboard controller method code below taken from:
+// https://wiki.osdev.org/A20_Line
+
+bool a20_enable(void) {
+    if (a20_check())
+        return true;
+
+    // BIOS method
+    struct rm_regs r = {0};
+    r.eax = 0x2401;
+    rm_int(0x15, &r, &r);
+
+    if (a20_check())
+        return true;
+
+    // Keyboard controller method
+    while (inb(0x64) & 2);
+    outb(0x64, 0xad);
+    while (inb(0x64) & 2);
+    outb(0x64, 0xd0);
+    while (!(inb(0x64) & 1));
+    uint8_t b = inb(0x60);
+    while (inb(0x64) & 2);
+    outb(0x64, 0xd1);
+    while (inb(0x64) & 2);
+    outb(0x60, b | 2);
+    while (inb(0x64) & 2);
+    outb(0x64, 0xae);
+    while (inb(0x64) & 2);
+
+    if (a20_check())
+        return true;
+
+    return false;
+}
diff --git a/stage2/sys/a20.h b/stage2/sys/a20.h
new file mode 100644
index 00000000..29fd9e32
--- /dev/null
+++ b/stage2/sys/a20.h
@@ -0,0 +1,9 @@
+#ifndef __SYS__A20_H__
+#define __SYS__A20_H__
+
+#include <stdbool.h>
+
+bool a20_check(void);
+bool a20_enable(void);
+
+#endif
diff --git a/stage2/sys/cpu.h b/stage2/sys/cpu.h
index 9a3215bd..5b96e49a 100644
--- a/stage2/sys/cpu.h
+++ b/stage2/sys/cpu.h
@@ -55,81 +55,81 @@ static inline uint32_t ind(uint16_t port) {
     return value;
 }
 
-static inline void mmoutb(void *addr, uint8_t value) {
+static inline void mmoutb(uintptr_t addr, uint8_t value) {
     asm volatile (
         "mov %0, %1"
         : "=m" (BYTE_PTR(addr))
-        : "g"  (value)
+        : "ir" (value)
         : "memory"
     );
 }
 
-static inline void mmoutw(void *addr, uint16_t value) {
+static inline void mmoutw(uintptr_t addr, uint16_t value) {
     asm volatile (
         "mov %0, %1"
         : "=m" (WORD_PTR(addr))
-        : "g"  (value)
+        : "ir" (value)
         : "memory"
     );
 }
 
-static inline void mmoutd(void *addr, uint32_t value) {
+static inline void mmoutd(uintptr_t addr, uint32_t value) {
     asm volatile (
         "mov %0, %1"
         : "=m" (DWORD_PTR(addr))
-        : "g"  (value)
+        : "ir" (value)
         : "memory"
     );
 }
 
-static inline void mmoutq(void *addr, uint64_t value) {
+static inline void mmoutq(uintptr_t addr, uint64_t value) {
     asm volatile (
         "mov %0, %1"
         : "=m" (QWORD_PTR(addr))
-        : "g"  (value)
+        : "ir" (value)
         : "memory"
     );
 }
 
-static inline uint8_t mminb(void *addr) {
+static inline uint8_t mminb(uintptr_t addr) {
     uint8_t ret;
     asm volatile (
         "mov %0, %1"
         : "=r" (ret)
-        : "g"  (BYTE_PTR(addr))
+        : "m"  (BYTE_PTR(addr))
         : "memory"
     );
     return ret;
 }
 
-static inline uint16_t mminw(void *addr) {
+static inline uint16_t mminw(uintptr_t addr) {
     uint16_t ret;
     asm volatile (
         "mov %0, %1"
         : "=r" (ret)
-        : "g"  (WORD_PTR(addr))
+        : "m"  (WORD_PTR(addr))
         : "memory"
     );
     return ret;
 }
 
-static inline uint32_t mmind(void *addr) {
+static inline uint32_t mmind(uintptr_t addr) {
     uint32_t ret;
     asm volatile (
         "mov %0, %1"
         : "=r" (ret)
-        : "g"  (DWORD_PTR(addr))
+        : "m"  (DWORD_PTR(addr))
         : "memory"
     );
     return ret;
 }
 
-static inline uint64_t mminq(void *addr) {
+static inline uint64_t mminq(uintptr_t addr) {
     uint64_t ret;
     asm volatile (
         "mov %0, %1"
         : "=r" (ret)
-        : "g"  (QWORD_PTR(addr))
+        : "m"  (QWORD_PTR(addr))
         : "memory"
     );
     return ret;
diff --git a/stage2/sys/lapic.c b/stage2/sys/lapic.c
index 44f379fa..66636efb 100644
--- a/stage2/sys/lapic.c
+++ b/stage2/sys/lapic.c
@@ -16,12 +16,12 @@ struct dmar {
 
 uint32_t lapic_read(uint32_t reg) {
     size_t lapic_mmio_base = (size_t)(rdmsr(0x1b) & 0xfffff000);
-    return mmind((void *)(lapic_mmio_base + reg));
+    return mmind(lapic_mmio_base + reg);
 }
 
 void lapic_write(uint32_t reg, uint32_t data) {
     size_t lapic_mmio_base = (size_t)(rdmsr(0x1b) & 0xfffff000);
-    mmoutd((void *)(lapic_mmio_base + reg), data);
+    mmoutd(lapic_mmio_base + reg, data);
 }
 
 bool x2apic_check(void) {
tab: 248 wrap: offon