#include #include #include #include #include #include #include #include kernel_ctx_t ctx = {0}; struct idt_entry idt[256] = {0}; struct idtr idtr = {0}; tss_t tss = {0}; extern uint32_t isr_stub_table[32]; extern void pit_isr(void); extern void jmp_user_mode(uint32_t esp, uint32_t eip); extern void flush_tss(uint32_t segment_selector); extern gdt_t gdt[6]; void exception_handler(int_stack_frame_t r) { LOG("Exception 0x%X (0x%X) has occurred\nEAX: 0x%08X\nECX: 0x%08X\nEDX: 0x%08X\nEBX: 0x%08X\nESI: 0x%08X\nEDI: 0x%08X\nEBP: 0x%08X\nESP: 0x%08X\n", r.int_no, r.err_code, r.eax, r.ecx, r.edx, r.ebx, r.esi, r.edi, r.ebp, r.esp+24); LOG("\nEIP: 0x%08X\nCS: 0x%08X\nEFLAGS: 0x%08X\n", r.eip, r.cs, r.eflags); } void sleep(int delay) { uint64_t end = ctx.ticks + delay; while (ctx.ticks < end) cpu_relax; } typedef struct { uint32_t eip; uint32_t esp; uint32_t cr3; } task_t; #define KERNEL_VMA 0xC0000000 void kernel(multiboot_info_t *info) { if (!CHECK_FLAG(info->flags, 3)) goto halt; // Modules if (!CHECK_FLAG(info->flags, 6)) goto halt; // Memory map if (!CHECK_FLAG(info->flags, 12)) goto halt; // VBE data ctx.multi_mmap = (multi_mmap_t *)(info->memmapaddress + KERNEL_VMA); ctx.multi_mmap_size = info->memmaplength; if (serial_port_init(COM1)) ctx.log_method = LOG_COM1; LOG("Kernel log being sent to COM1\n"); if (!mmap_init()) goto halt; LOG("%d bytes of RAM detected\nCreated a %d byte large physical memory map at 0x%08X\n", ctx.mmap_size*BLOCK_SIZE*8, ctx.mmap_size, (uint32_t)ctx.mmap); for (int i = 0; i < 32; i++) { idt_encode_entry(idt, i, isr_stub_table[i], GDT_SEGMENT_SELECTOR(1, 0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT); } idt_encode_entry(idt, 32, (uint32_t)pit_isr, GDT_SEGMENT_SELECTOR(1, 0), INT_GATE_32 | INT_RING0 | INT_PRESENT); idtr.size = (sizeof(struct idt_entry) * 256) - 1; idtr.base = (uint32_t) idt; asm volatile ("lidt %0" :: "m"(idtr)); pic_remap(PIC_1_START, PIC_2_START); asm volatile ("sti" ::); ctx.ticks = 0; pit_init(); uint32_t base = (uint32_t)&tss; uint32_t limit = base + sizeof(tss_t); gdt[5].base_low = base & 0xFFFF; gdt[5].base_middle = (base >> 16) & 0xFF; gdt[5].base_high = (base >> 24) & 0xFF; gdt[5].limit_low = limit & 0xFFFF; gdt[5].granularity = (limit >> 16) & 0x0F; gdt[5].granularity |= 0x40; gdt[5].access = 0x89; tss.ss0 = GDT_SEGMENT_SELECTOR(2, RING0); uint32_t esp0 = 0; asm volatile ("mov %%esp, %0" : "=r" (esp0)); tss.esp0 = esp0; tss.cs = GDT_SEGMENT_SELECTOR(3, RING3); tss.ss = tss.ds = tss.es = tss.fs = tss.gs = GDT_SEGMENT_SELECTOR(4, RING3); flush_tss(GDT_SEGMENT_SELECTOR(5, RING3)); #define PAGE_PRESENT (1<<0) #define PAGE_RW (1<<1) #define PAGE_USER (1<<2) #define PAGE_DIR_INDEX(x) (((x) >> 22) & 0x3FF) #define PAGE_TAB_INDEX(x) (((x) >> 12) & 0x3FF) #define PAGE_OFFSET(x) ((x) & 0xFFF) uint32_t stack = (uint32_t)mmap_find_first_free_block(); multi_mod_t *init = (multi_mod_t *)(info->moduleaddress + KERNEL_VMA); LOG("Switching to ring 3... EIP: 0x%08X ESP: 0x%08X\n", init->mod_start+KERNEL_VMA, stack+0x1000); jmp_user_mode(stack+0x1000, init->mod_start+KERNEL_VMA); halt: for (;;) {} }