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 #include #include +#include #include #include #include @@ -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 +#include +#include +#include +#include +#include + +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 + +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) {