diff --git a/stage23/Makefile b/stage23/Makefile index 08e0a62b..304d7a30 100644 --- a/stage23/Makefile +++ b/stage23/Makefile @@ -74,8 +74,7 @@ ifeq ($(TARGET), bios) -static \ -fno-pie \ -lgcc \ - -static-libgcc \ - -Wl,--gc-sections + -static-libgcc endif .PHONY: all clean builddir diff --git a/stage23/entry.s2.c b/stage23/entry.s2.c index c6b08fe9..d8f91aae 100644 --- a/stage23/entry.s2.c +++ b/stage23/entry.s2.c @@ -20,6 +20,7 @@ #include #include #include +#include extern uint64_t stage3_build_id; @@ -74,6 +75,8 @@ void entry(uint8_t boot_drive, int boot_from) { if (!a20_enable()) panic("Could not enable A20 line"); + init_idt(); + init_e820(); init_memmap(); @@ -90,7 +93,7 @@ void entry(uint8_t boot_drive, int boot_from) { ); if (!stage3_loaded) - panic("Failed to load stage 3.\n"); + panic("Failed to load stage 3."); __attribute__((noreturn)) void (*stage3)(int boot_from) = (void *)stage3_addr; diff --git a/stage23/lib/blib.c b/stage23/lib/blib.c index 3252c502..bf9d4f41 100644 --- a/stage23/lib/blib.c +++ b/stage23/lib/blib.c @@ -83,7 +83,7 @@ bool efi_exit_boot_services(void) { status = uefi_call_wrapper(gBS->ExitBootServices, 2, efi_image_handle, mmap_key); if (status) - panic("efi: Failed to exit boot services\n"); + panic("efi: Failed to exit boot services"); asm volatile ("cli" ::: "memory"); diff --git a/stage23/lib/real.asm b/stage23/lib/real.asm index 911c3101..4c43af98 100644 --- a/stage23/lib/real.asm +++ b/stage23/lib/real.asm @@ -2,6 +2,9 @@ section .realmode global rm_hcf rm_hcf: + ; Load BIOS IVT + lidt [.rm_idt] + ; Jump to real mode jmp 0x08:.bits16 .bits16: @@ -30,6 +33,9 @@ rm_hcf: jmp .hang bits 32 + .rm_idt: dw 0x3ff + dd 0 + global rm_int rm_int: ; Self-modifying code: int $int_no @@ -47,6 +53,12 @@ rm_int: ; Save GDT in case BIOS overwrites it sgdt [.gdt] + ; Save IDT + sidt [.idt] + + ; Load BIOS IVT + lidt [.rm_idt] + ; Save non-scratch GPRs push ebx push esi @@ -116,7 +128,10 @@ rm_int: mov esp, dword [ss:.esp] ; Restore GDT - lgdt [ss:.gdt] + o32 lgdt [ss:.gdt] + + ; Restore IDT + o32 lidt [ss:.idt] ; Jump back to pmode mov eax, cr0 @@ -146,3 +161,6 @@ align 16 .out_regs: dd 0 .in_regs: dd 0 .gdt: dq 0 + .idt: dq 0 + .rm_idt: dw 0x3ff + dd 0 diff --git a/stage23/lib/sleep.asm b/stage23/lib/sleep.asm index 470a429b..0cc2ab5b 100644 --- a/stage23/lib/sleep.asm +++ b/stage23/lib/sleep.asm @@ -26,6 +26,15 @@ _pit_sleep_and_quit_on_keypress: mov dword [int_08_ticks_counter], 0 + ; Save GDT in case BIOS overwrites it + sgdt [.gdt] + + ; Save IDT + sidt [.idt] + + ; Load BIOS IVT + lidt [.rm_idt] + ; Save non-scratch GPRs push ebx push esi @@ -81,6 +90,12 @@ _pit_sleep_and_quit_on_keypress: .done: cli + ; Restore GDT + o32 lgdt [ss:.gdt] + + ; Restore IDT + o32 lidt [ss:.idt] + ; Jump back to pmode mov ebx, cr0 or bl, 1 @@ -115,3 +130,8 @@ _pit_sleep_and_quit_on_keypress: pop edx ret + + .gdt: dq 0 + .idt: dq 0 + .rm_idt: dw 0x3ff + dd 0 diff --git a/stage23/linker_stage2only.ld b/stage23/linker_stage2only.ld index f2739603..aa27c5d5 100644 --- a/stage23/linker_stage2only.ld +++ b/stage23/linker_stage2only.ld @@ -28,6 +28,7 @@ SECTIONS *(.stage3_build_id*) full_map = .; limine_sys_size = .; + getchar_internal = .; } .bss : { diff --git a/stage23/sys/exceptions.s2.c b/stage23/sys/exceptions.s2.c new file mode 100644 index 00000000..ea51d3cf --- /dev/null +++ b/stage23/sys/exceptions.s2.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include + +#if defined (bios) + +static const char *exception_names[] = { + "Division by 0", + "Debug", + "NMI", + "Breakpoint", + "Overflow", + "Bound range exceeded", + "Invalid opcode", + "Device not available", + "Double fault", + "???", + "Invalid TSS", + "Segment not present", + "Stack-segment fault", + "General protection fault", + "Page fault", + "???", + "x87 exception", + "Alignment check", + "Machine check", + "SIMD exception", + "Virtualisation", + "???", + "???", + "???", + "???", + "???", + "???", + "???", + "???", + "???", + "Security" +}; + +void except(uint32_t exception, uint32_t error_code, uint32_t ebp, uint32_t eip) { + (void)ebp; + panic("%s at %x. Error code: %x", exception_names[exception], eip, error_code); +} + +#endif diff --git a/stage23/sys/gdt.s2.c b/stage23/sys/gdt.s2.c index f918573f..bf2f2ebd 100644 --- a/stage23/sys/gdt.s2.c +++ b/stage23/sys/gdt.s2.c @@ -59,6 +59,9 @@ static struct gdt_desc gdt_descs[] = { } }; +#if defined (bios) +__attribute__((section(".realmode"))) +#endif struct gdtr gdt = { sizeof(gdt_descs) - 1, (uintptr_t)gdt_descs, diff --git a/stage23/sys/idt.h b/stage23/sys/idt.h new file mode 100644 index 00000000..856a4a7c --- /dev/null +++ b/stage23/sys/idt.h @@ -0,0 +1,27 @@ +#ifndef __SYS__IDT_H__ +#define __SYS__IDT_H__ + +#include + +#if defined (bios) + +struct idtr { + uint16_t limit; + uint32_t ptr; +} __attribute__((packed)); + +struct idt_entry { + uint16_t offset_lo; + uint16_t selector; + uint8_t unused; + uint8_t type_attr; + uint16_t offset_hi; +} __attribute__((packed)); + +extern struct idtr idt; + +void init_idt(void); + +#endif + +#endif diff --git a/stage23/sys/idt.s2.c b/stage23/sys/idt.s2.c new file mode 100644 index 00000000..cc514042 --- /dev/null +++ b/stage23/sys/idt.s2.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +#if defined (bios) + +__attribute__((section(".realmode"))) +static struct idt_entry idt_entries[32]; + +__attribute__((section(".realmode"))) +struct idtr idt = { + sizeof(idt_entries) - 1, + (uintptr_t)idt_entries +}; + +static void register_interrupt_handler(size_t vec, void *handler, uint8_t type) { + uint32_t p = (uint32_t)handler; + + idt_entries[vec].offset_lo = (uint16_t)p; + idt_entries[vec].selector = 0x18; + idt_entries[vec].unused = 0; + idt_entries[vec].type_attr = type; + idt_entries[vec].offset_hi = (uint16_t)(p >> 16); +} + +extern void *exceptions[]; + +void init_idt(void) { + for (size_t i = 0; i < SIZEOF_ARRAY(idt_entries); i++) + register_interrupt_handler(i, exceptions[i], 0x8e); + + asm volatile ("lidt %0" :: "m"(idt) : "memory"); +} + +#endif diff --git a/stage23/sys/int_thunks.s2.asm b/stage23/sys/int_thunks.s2.asm new file mode 100644 index 00000000..7c82a000 --- /dev/null +++ b/stage23/sys/int_thunks.s2.asm @@ -0,0 +1,39 @@ +section .text + +extern except + +%macro raise_exception 1 +align 16 +raise_exception_%1: + cld +%if %1 == 8 || %1 == 10 || %1 == 11 || %1 == 12 || %1 == 13 || %1 == 14 || %1 == 17 || %1 == 30 + pop eax +%else + xor eax, eax +%endif + push ebp + mov ebp, esp + push eax + push %1 + call except +%endmacro + +%assign i 0 +%rep 32 +raise_exception i +%assign i i+1 +%endrep + +section .rodata + +%macro raise_exception_getaddr 1 +dd raise_exception_%1 +%endmacro + +global exceptions +exceptions: +%assign i 0 +%rep 32 +raise_exception_getaddr i +%assign i i+1 +%endrep