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) {
