hazel/kernel/kernel.c

121 lines
4.3 KiB
C

#include <kernel/kernel.h>
#include <kernel/multiboot.h>
#include <kernel/mem.h>
#include <kernel/serial.h>
#include <kernel/idt.h>
#include <kernel/pic.h>
#include <kernel/pit.h>
#include <stdint.h>
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];
extern uint32_t boot_page_dir[1024];
extern uint32_t boot_page_tab[1024];
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;
}
int strcmp(const char *str1, const char *str2) {
while (*str1 && (*str1 == *str2)) {
str1++;
str2++;
}
return *(uint8_t *)str1 - *(uint8_t *)str2;
}
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));
multi_mod_t *init = (multi_mod_t *)(info->moduleaddress + KERNEL_VMA);
elf_t *elf = (elf_t *)(init->mod_start+KERNEL_VMA);
section_t *str = (section_t *)((uint32_t)elf + elf->e_shoff + elf->e_shstrndx*elf->e_shentsize);
section_t *text = 0;
for (int i = 0; i < elf->e_shnum; i++) {
section_t *sec = (section_t *)((uint32_t)elf + elf->e_shoff + i*elf->e_shentsize);
//LOG("Pingas: %d\n", elf->e_shstrndx);
const char *name = (char *)((uint32_t)elf + str->sh_offset + sec->sh_name);
if (!strcmp(name, ".text")) {
text = sec;
}
}
uint32_t elf_phys = (uint32_t)elf - KERNEL_VMA;
LOG("0x%08X\n", elf_phys);
uint32_t *elf_page_dir = mmap_find_first_free_block();
uint32_t *elf_page_tab = mmap_find_first_free_block();
elf_page_dir[768] = ((uint32_t)boot_page_tab - KERNEL_VMA) | 3;
elf_page_dir[PAGE_DIR_INDEX(elf->e_entry)] = ((uint32_t)elf_page_tab - KERNEL_VMA) | 7;
for (int i = 0; i < 1024; i++) {
elf_page_tab[i] = (elf_phys + 0x1000*i) | 7;
}
asm volatile ("mov %0, %%cr3" :: "r"((uint32_t)elf_page_dir - KERNEL_VMA));
uint32_t stack = (uint32_t)mmap_find_first_free_block();
LOG("Switching to ring 3... EIP: 0x%08X ESP: 0x%08X\n", elf->e_entry+text->sh_offset, stack+0x1000);
jmp_user_mode(stack+0x1000, elf->e_entry+text->sh_offset);
halt:
for (;;) {}
}