diff --git a/Makefile b/Makefile index 0a7eed1..643a050 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ TARGET = BOOTX64.EFI TARGET_SO = bootx64.so OBJ = $(BUILD_DIR)/main.o KERNEL_TARGET = kernel.elf -KERNEL_OBJS = $(BUILD_DIR)/kernel.o $(BUILD_DIR)/string_utils.o $(BUILD_DIR)/commands.o +KERNEL_OBJS = $(BUILD_DIR)/kernel.o $(BUILD_DIR)/string_utils.o $(BUILD_DIR)/commands.o $(BUILD_DIR)/idt.o $(BUILD_DIR)/isr.o KERNEL_LD = kernel.ld # QEMU settings @@ -76,7 +76,6 @@ QEMU_FLAGS = -machine q35 \ -drive if=pflash,format=raw,file=$(BUILD_DIR)/OVMF_VARS.fd \ -drive format=raw,file=fat:rw:$(BUILD_DIR) \ -net none \ - -nographic \ -no-reboot # Phony targets @@ -112,6 +111,16 @@ $(BUILD_DIR)/commands.o: $(SRC_DIR)/commands.c $(CC) -ffreestanding -fno-stack-protector -fno-pic -fshort-wchar \ -mno-red-zone -Wall -Wextra $(EFI_INCLUDES) -c $< -o $@ +$(BUILD_DIR)/idt.o: $(SRC_DIR)/idt.c + @echo "Compiling idt.c..." + $(CC) -ffreestanding -fno-stack-protector -fno-pic -fshort-wchar \ + -mno-red-zone -Wall -Wextra $(EFI_INCLUDES) -c $< -o $@ + +$(BUILD_DIR)/isr.o: $(SRC_DIR)/isr.S + @echo "Compiling isr.S..." + $(CC) -ffreestanding -fno-stack-protector -fno-pic -fshort-wchar \ + -mno-red-zone -Wall -Wextra $(EFI_INCLUDES) -c $< -o $@ + # Link kernel ELF $(BUILD_DIR)/$(KERNEL_TARGET): $(KERNEL_OBJS) $(KERNEL_LD) @echo "Linking kernel ELF..." diff --git a/idt.c b/idt.c new file mode 100644 index 0000000..89c1168 --- /dev/null +++ b/idt.c @@ -0,0 +1,166 @@ +#include "idt.h" + +#define IDT_SIZE 256 +#define IDT_TYPE_INTERRUPT 0x8E + +typedef struct { + UINT16 offset_low; + UINT16 selector; + UINT8 ist; + UINT8 type_attr; + UINT16 offset_mid; + UINT32 offset_high; + UINT32 zero; +} __attribute__((packed)) IdtEntry; + +typedef struct { + UINT16 limit; + UINT64 base; +} __attribute__((packed)) IdtPtr; + +static IdtEntry idt[IDT_SIZE]; +static BootInfo *gBoot = NULL; + +extern void (*isr_stub_table[])(void); + +static void idt_set_gate(UINTN index, void (*handler)(void)) +{ + UINT64 addr = (UINT64)(UINTN)handler; + UINT16 selector = 0; + + __asm__ __volatile__("mov %%cs, %0" : "=r"(selector)); + + idt[index].offset_low = (UINT16)(addr & 0xFFFF); + idt[index].selector = selector; + idt[index].ist = 0; + idt[index].type_attr = IDT_TYPE_INTERRUPT; + idt[index].offset_mid = (UINT16)((addr >> 16) & 0xFFFF); + idt[index].offset_high = (UINT32)((addr >> 32) & 0xFFFFFFFF); + idt[index].zero = 0; +} + +static void lidt(const IdtPtr *idtr) +{ + __asm__ __volatile__("lidt (%0)" :: "r"(idtr)); +} + +static const CHAR16 *exception_name(UINTN vector) +{ + switch (vector) { + case 0: return L"Divide Error"; + case 1: return L"Debug"; + case 2: return L"Non-Maskable Interrupt"; + case 3: return L"Breakpoint"; + case 4: return L"Overflow"; + case 5: return L"Bound Range Exceeded"; + case 6: return L"Invalid Opcode"; + case 7: return L"Device Not Available"; + case 8: return L"Double Fault"; + case 9: return L"Coprocessor Segment Overrun"; + case 10: return L"Invalid TSS"; + case 11: return L"Segment Not Present"; + case 12: return L"Stack-Segment Fault"; + case 13: return L"General Protection Fault"; + case 14: return L"Page Fault"; + case 15: return L"Reserved"; + case 16: return L"x87 Floating-Point"; + case 17: return L"Alignment Check"; + case 18: return L"Machine Check"; + case 19: return L"SIMD Floating-Point"; + case 20: return L"Virtualization"; + case 21: return L"Control Protection"; + case 22: return L"Reserved"; + case 23: return L"Reserved"; + case 24: return L"Reserved"; + case 25: return L"Reserved"; + case 26: return L"Reserved"; + case 27: return L"Reserved"; + case 28: return L"Hypervisor Injection"; + case 29: return L"VMM Communication"; + case 30: return L"Security"; + case 31: return L"Reserved"; + default: return L"Unknown"; + } +} + +static inline void outb(UINT16 port, UINT8 value) +{ + __asm__ __volatile__("outb %0, %1" :: "a"(value), "Nd"(port)); +} + +static void pic_eoi(UINTN vector) +{ + if (vector >= 40) { + outb(0xA0, 0x20); /* EOI to slave PIC */ + } + outb(0x20, 0x20); /* EOI to master PIC */ +} + +static void halt_forever(void) +{ + for (;;) { + __asm__ __volatile__("cli; hlt"); + } +} + +void isr_handler(ISRFrame *frame) +{ + UINT64 cr2 = 0; + + /* Hardware IRQs (vectors 32-47): send EOI and return */ + if (frame->vector >= 32 && frame->vector <= 47) { + pic_eoi(frame->vector); + return; + } + + /* CPU exceptions (vectors 0-31): print diagnostics and halt */ + if (gBoot != NULL && gBoot->print != NULL) { + gBoot->print(L"\n\rEXCEPTION: %d (%s)\n\r", frame->vector, + exception_name(frame->vector)); + gBoot->print(L" Error Code: 0x%lx\n\r", frame->error_code); + gBoot->print(L" RIP: 0x%lx CS: 0x%lx RFLAGS: 0x%lx\n\r", + frame->rip, frame->cs, frame->rflags); + } + + if (frame->vector == 14) { + __asm__ __volatile__("mov %%cr2, %0" : "=r"(cr2)); + if (gBoot != NULL && gBoot->print != NULL) { + gBoot->print(L" CR2: 0x%lx\n\r", cr2); + } + } + + halt_forever(); +} + +void idt_init(BootInfo *Boot) +{ + IdtPtr old_idtr; + IdtPtr idtr; + IdtEntry *old_idt = NULL; + UINTN i = 0; + + gBoot = Boot; + + /* Read the firmware's existing IDT so we can preserve its entries */ + __asm__ __volatile__("sidt %0" : "=m"(old_idtr)); + old_idt = (IdtEntry *)(UINTN)old_idtr.base; + + /* Copy the entire existing IDT first (preserves firmware IRQ handlers) */ + for (i = 0; i < IDT_SIZE; i++) { + if (old_idt != NULL && (i * sizeof(IdtEntry)) < (UINTN)(old_idtr.limit + 1)) { + idt[i] = old_idt[i]; + } else { + idt_set_gate(i, isr_stub_table[i]); + } + } + + /* Override only CPU exception vectors (0-31) with our handlers */ + for (i = 0; i < 32; i++) { + idt_set_gate(i, isr_stub_table[i]); + } + + idtr.limit = (UINT16)(sizeof(idt) - 1); + idtr.base = (UINT64)(UINTN)idt; + + lidt(&idtr); +} diff --git a/idt.h b/idt.h new file mode 100644 index 0000000..4c4fd06 --- /dev/null +++ b/idt.h @@ -0,0 +1,32 @@ +#ifndef IDT_H +#define IDT_H + +#include +#include "boot_info.h" + +typedef struct { + UINT64 r15; + UINT64 r14; + UINT64 r13; + UINT64 r12; + UINT64 r11; + UINT64 r10; + UINT64 r9; + UINT64 r8; + UINT64 rbp; + UINT64 rdi; + UINT64 rsi; + UINT64 rdx; + UINT64 rcx; + UINT64 rbx; + UINT64 rax; + UINT64 vector; + UINT64 error_code; + UINT64 rip; + UINT64 cs; + UINT64 rflags; +} ISRFrame; + +void idt_init(BootInfo *Boot); + +#endif diff --git a/isr.S b/isr.S new file mode 100644 index 0000000..5b9b68d --- /dev/null +++ b/isr.S @@ -0,0 +1,577 @@ +.text + +.global isr_handler +.global isr_stub_table + +.macro ISR_NOERR num +.global isr\num +isr\num: + pushq $0 + pushq $\num + jmp isr_common +.endm + +.macro ISR_ERR num +.global isr\num +isr\num: + pushq $\num + jmp isr_common +.endm + +isr_common: + cld + + pushq %rax + pushq %rbx + pushq %rcx + pushq %rdx + pushq %rsi + pushq %rdi + pushq %rbp + pushq %r8 + pushq %r9 + pushq %r10 + pushq %r11 + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + + movq %rsp, %rdi + call isr_handler + + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %r11 + popq %r10 + popq %r9 + popq %r8 + popq %rbp + popq %rdi + popq %rsi + popq %rdx + popq %rcx + popq %rbx + popq %rax + + addq $16, %rsp + iretq + +ISR_NOERR 0 +ISR_NOERR 1 +ISR_NOERR 2 +ISR_NOERR 3 +ISR_NOERR 4 +ISR_NOERR 5 +ISR_NOERR 6 +ISR_NOERR 7 +ISR_ERR 8 +ISR_NOERR 9 +ISR_ERR 10 +ISR_ERR 11 +ISR_ERR 12 +ISR_ERR 13 +ISR_ERR 14 +ISR_NOERR 15 +ISR_NOERR 16 +ISR_ERR 17 +ISR_NOERR 18 +ISR_NOERR 19 +ISR_NOERR 20 +ISR_NOERR 21 +ISR_NOERR 22 +ISR_NOERR 23 +ISR_NOERR 24 +ISR_NOERR 25 +ISR_NOERR 26 +ISR_NOERR 27 +ISR_NOERR 28 +ISR_NOERR 29 +ISR_ERR 30 +ISR_NOERR 31 +ISR_NOERR 32 +ISR_NOERR 33 +ISR_NOERR 34 +ISR_NOERR 35 +ISR_NOERR 36 +ISR_NOERR 37 +ISR_NOERR 38 +ISR_NOERR 39 +ISR_NOERR 40 +ISR_NOERR 41 +ISR_NOERR 42 +ISR_NOERR 43 +ISR_NOERR 44 +ISR_NOERR 45 +ISR_NOERR 46 +ISR_NOERR 47 +ISR_NOERR 48 +ISR_NOERR 49 +ISR_NOERR 50 +ISR_NOERR 51 +ISR_NOERR 52 +ISR_NOERR 53 +ISR_NOERR 54 +ISR_NOERR 55 +ISR_NOERR 56 +ISR_NOERR 57 +ISR_NOERR 58 +ISR_NOERR 59 +ISR_NOERR 60 +ISR_NOERR 61 +ISR_NOERR 62 +ISR_NOERR 63 +ISR_NOERR 64 +ISR_NOERR 65 +ISR_NOERR 66 +ISR_NOERR 67 +ISR_NOERR 68 +ISR_NOERR 69 +ISR_NOERR 70 +ISR_NOERR 71 +ISR_NOERR 72 +ISR_NOERR 73 +ISR_NOERR 74 +ISR_NOERR 75 +ISR_NOERR 76 +ISR_NOERR 77 +ISR_NOERR 78 +ISR_NOERR 79 +ISR_NOERR 80 +ISR_NOERR 81 +ISR_NOERR 82 +ISR_NOERR 83 +ISR_NOERR 84 +ISR_NOERR 85 +ISR_NOERR 86 +ISR_NOERR 87 +ISR_NOERR 88 +ISR_NOERR 89 +ISR_NOERR 90 +ISR_NOERR 91 +ISR_NOERR 92 +ISR_NOERR 93 +ISR_NOERR 94 +ISR_NOERR 95 +ISR_NOERR 96 +ISR_NOERR 97 +ISR_NOERR 98 +ISR_NOERR 99 +ISR_NOERR 100 +ISR_NOERR 101 +ISR_NOERR 102 +ISR_NOERR 103 +ISR_NOERR 104 +ISR_NOERR 105 +ISR_NOERR 106 +ISR_NOERR 107 +ISR_NOERR 108 +ISR_NOERR 109 +ISR_NOERR 110 +ISR_NOERR 111 +ISR_NOERR 112 +ISR_NOERR 113 +ISR_NOERR 114 +ISR_NOERR 115 +ISR_NOERR 116 +ISR_NOERR 117 +ISR_NOERR 118 +ISR_NOERR 119 +ISR_NOERR 120 +ISR_NOERR 121 +ISR_NOERR 122 +ISR_NOERR 123 +ISR_NOERR 124 +ISR_NOERR 125 +ISR_NOERR 126 +ISR_NOERR 127 +ISR_NOERR 128 +ISR_NOERR 129 +ISR_NOERR 130 +ISR_NOERR 131 +ISR_NOERR 132 +ISR_NOERR 133 +ISR_NOERR 134 +ISR_NOERR 135 +ISR_NOERR 136 +ISR_NOERR 137 +ISR_NOERR 138 +ISR_NOERR 139 +ISR_NOERR 140 +ISR_NOERR 141 +ISR_NOERR 142 +ISR_NOERR 143 +ISR_NOERR 144 +ISR_NOERR 145 +ISR_NOERR 146 +ISR_NOERR 147 +ISR_NOERR 148 +ISR_NOERR 149 +ISR_NOERR 150 +ISR_NOERR 151 +ISR_NOERR 152 +ISR_NOERR 153 +ISR_NOERR 154 +ISR_NOERR 155 +ISR_NOERR 156 +ISR_NOERR 157 +ISR_NOERR 158 +ISR_NOERR 159 +ISR_NOERR 160 +ISR_NOERR 161 +ISR_NOERR 162 +ISR_NOERR 163 +ISR_NOERR 164 +ISR_NOERR 165 +ISR_NOERR 166 +ISR_NOERR 167 +ISR_NOERR 168 +ISR_NOERR 169 +ISR_NOERR 170 +ISR_NOERR 171 +ISR_NOERR 172 +ISR_NOERR 173 +ISR_NOERR 174 +ISR_NOERR 175 +ISR_NOERR 176 +ISR_NOERR 177 +ISR_NOERR 178 +ISR_NOERR 179 +ISR_NOERR 180 +ISR_NOERR 181 +ISR_NOERR 182 +ISR_NOERR 183 +ISR_NOERR 184 +ISR_NOERR 185 +ISR_NOERR 186 +ISR_NOERR 187 +ISR_NOERR 188 +ISR_NOERR 189 +ISR_NOERR 190 +ISR_NOERR 191 +ISR_NOERR 192 +ISR_NOERR 193 +ISR_NOERR 194 +ISR_NOERR 195 +ISR_NOERR 196 +ISR_NOERR 197 +ISR_NOERR 198 +ISR_NOERR 199 +ISR_NOERR 200 +ISR_NOERR 201 +ISR_NOERR 202 +ISR_NOERR 203 +ISR_NOERR 204 +ISR_NOERR 205 +ISR_NOERR 206 +ISR_NOERR 207 +ISR_NOERR 208 +ISR_NOERR 209 +ISR_NOERR 210 +ISR_NOERR 211 +ISR_NOERR 212 +ISR_NOERR 213 +ISR_NOERR 214 +ISR_NOERR 215 +ISR_NOERR 216 +ISR_NOERR 217 +ISR_NOERR 218 +ISR_NOERR 219 +ISR_NOERR 220 +ISR_NOERR 221 +ISR_NOERR 222 +ISR_NOERR 223 +ISR_NOERR 224 +ISR_NOERR 225 +ISR_NOERR 226 +ISR_NOERR 227 +ISR_NOERR 228 +ISR_NOERR 229 +ISR_NOERR 230 +ISR_NOERR 231 +ISR_NOERR 232 +ISR_NOERR 233 +ISR_NOERR 234 +ISR_NOERR 235 +ISR_NOERR 236 +ISR_NOERR 237 +ISR_NOERR 238 +ISR_NOERR 239 +ISR_NOERR 240 +ISR_NOERR 241 +ISR_NOERR 242 +ISR_NOERR 243 +ISR_NOERR 244 +ISR_NOERR 245 +ISR_NOERR 246 +ISR_NOERR 247 +ISR_NOERR 248 +ISR_NOERR 249 +ISR_NOERR 250 +ISR_NOERR 251 +ISR_NOERR 252 +ISR_NOERR 253 +ISR_NOERR 254 +ISR_NOERR 255 + +isr_stub_table: + .quad isr0 + .quad isr1 + .quad isr2 + .quad isr3 + .quad isr4 + .quad isr5 + .quad isr6 + .quad isr7 + .quad isr8 + .quad isr9 + .quad isr10 + .quad isr11 + .quad isr12 + .quad isr13 + .quad isr14 + .quad isr15 + .quad isr16 + .quad isr17 + .quad isr18 + .quad isr19 + .quad isr20 + .quad isr21 + .quad isr22 + .quad isr23 + .quad isr24 + .quad isr25 + .quad isr26 + .quad isr27 + .quad isr28 + .quad isr29 + .quad isr30 + .quad isr31 + .quad isr32 + .quad isr33 + .quad isr34 + .quad isr35 + .quad isr36 + .quad isr37 + .quad isr38 + .quad isr39 + .quad isr40 + .quad isr41 + .quad isr42 + .quad isr43 + .quad isr44 + .quad isr45 + .quad isr46 + .quad isr47 + .quad isr48 + .quad isr49 + .quad isr50 + .quad isr51 + .quad isr52 + .quad isr53 + .quad isr54 + .quad isr55 + .quad isr56 + .quad isr57 + .quad isr58 + .quad isr59 + .quad isr60 + .quad isr61 + .quad isr62 + .quad isr63 + .quad isr64 + .quad isr65 + .quad isr66 + .quad isr67 + .quad isr68 + .quad isr69 + .quad isr70 + .quad isr71 + .quad isr72 + .quad isr73 + .quad isr74 + .quad isr75 + .quad isr76 + .quad isr77 + .quad isr78 + .quad isr79 + .quad isr80 + .quad isr81 + .quad isr82 + .quad isr83 + .quad isr84 + .quad isr85 + .quad isr86 + .quad isr87 + .quad isr88 + .quad isr89 + .quad isr90 + .quad isr91 + .quad isr92 + .quad isr93 + .quad isr94 + .quad isr95 + .quad isr96 + .quad isr97 + .quad isr98 + .quad isr99 + .quad isr100 + .quad isr101 + .quad isr102 + .quad isr103 + .quad isr104 + .quad isr105 + .quad isr106 + .quad isr107 + .quad isr108 + .quad isr109 + .quad isr110 + .quad isr111 + .quad isr112 + .quad isr113 + .quad isr114 + .quad isr115 + .quad isr116 + .quad isr117 + .quad isr118 + .quad isr119 + .quad isr120 + .quad isr121 + .quad isr122 + .quad isr123 + .quad isr124 + .quad isr125 + .quad isr126 + .quad isr127 + .quad isr128 + .quad isr129 + .quad isr130 + .quad isr131 + .quad isr132 + .quad isr133 + .quad isr134 + .quad isr135 + .quad isr136 + .quad isr137 + .quad isr138 + .quad isr139 + .quad isr140 + .quad isr141 + .quad isr142 + .quad isr143 + .quad isr144 + .quad isr145 + .quad isr146 + .quad isr147 + .quad isr148 + .quad isr149 + .quad isr150 + .quad isr151 + .quad isr152 + .quad isr153 + .quad isr154 + .quad isr155 + .quad isr156 + .quad isr157 + .quad isr158 + .quad isr159 + .quad isr160 + .quad isr161 + .quad isr162 + .quad isr163 + .quad isr164 + .quad isr165 + .quad isr166 + .quad isr167 + .quad isr168 + .quad isr169 + .quad isr170 + .quad isr171 + .quad isr172 + .quad isr173 + .quad isr174 + .quad isr175 + .quad isr176 + .quad isr177 + .quad isr178 + .quad isr179 + .quad isr180 + .quad isr181 + .quad isr182 + .quad isr183 + .quad isr184 + .quad isr185 + .quad isr186 + .quad isr187 + .quad isr188 + .quad isr189 + .quad isr190 + .quad isr191 + .quad isr192 + .quad isr193 + .quad isr194 + .quad isr195 + .quad isr196 + .quad isr197 + .quad isr198 + .quad isr199 + .quad isr200 + .quad isr201 + .quad isr202 + .quad isr203 + .quad isr204 + .quad isr205 + .quad isr206 + .quad isr207 + .quad isr208 + .quad isr209 + .quad isr210 + .quad isr211 + .quad isr212 + .quad isr213 + .quad isr214 + .quad isr215 + .quad isr216 + .quad isr217 + .quad isr218 + .quad isr219 + .quad isr220 + .quad isr221 + .quad isr222 + .quad isr223 + .quad isr224 + .quad isr225 + .quad isr226 + .quad isr227 + .quad isr228 + .quad isr229 + .quad isr230 + .quad isr231 + .quad isr232 + .quad isr233 + .quad isr234 + .quad isr235 + .quad isr236 + .quad isr237 + .quad isr238 + .quad isr239 + .quad isr240 + .quad isr241 + .quad isr242 + .quad isr243 + .quad isr244 + .quad isr245 + .quad isr246 + .quad isr247 + .quad isr248 + .quad isr249 + .quad isr250 + .quad isr251 + .quad isr252 + .quad isr253 + .quad isr254 + .quad isr255 + +.section .note.GNU-stack,"",@progbits diff --git a/kernel.c b/kernel.c index e07b391..4030b9a 100644 --- a/kernel.c +++ b/kernel.c @@ -2,6 +2,7 @@ #include "boot_info.h" #include "commands.h" +#include "idt.h" #define SAFE_PRINT(Boot, ...) \ do { \ @@ -34,6 +35,8 @@ void kmain(BootInfo *Boot) } } + idt_init(Boot); + SAFE_PRINT(Boot, L"================================================\n\r"); SAFE_PRINT(Boot, L" Welcome to Simple UEFI Operating System!\n\r"); SAFE_PRINT(Boot, L"================================================\n\r");