#include "drive.h" #include "elf.h" #include "util.h" #include "idt.h" #include "log.h" #include "panic.h" #include "task.h" #include "paging.h" #include "pmap.h" #include "kbd.h" enum { IDT_PRESENT = 0x80, IDT_INT = 0x0e, }; struct idt_entry { uint16_t addr_low; uint16_t cs; uint8_t zero; uint8_t flags; uint16_t addr_high; } __attribute__ ((packed)); struct idt_entry idt[256]; struct { uint16_t limit; uint32_t start; } __attribute__ ((packed)) idtr = { .limit = 256 * sizeof(struct idt_entry) - 1, .start = (uint32_t)idt }; //file handles as (drive_number << 8) + file_id_t static uint32_t sc_open_file(uint32_t drive_number, char *path) { return (drive_number << 8) + drives[drive_number].get_file(drives + drive_number, path); } static void sc_close_file(uint32_t handle) { drives[handle >> 8].free_file(drives + (handle >> 8), handle & 0xff); } static uint32_t sc_file_get_size(uint32_t handle) { return drives[handle >> 8].get_file_length(drives + (handle >> 8), handle & 0xff); } static uint32_t sc_file_read(uint32_t handle, uint32_t file_offset, uint32_t count, void *buffer) { uint32_t len = sc_file_get_size(handle); if (file_offset + count > len) count = len - file_offset; fmcpy(buffer, drives + (handle >> 8), handle & 0xff, file_offset, count); return count; } static uint32_t sc_start_task(uint32_t drive_number, char *path, const char *pass) { switch_to_kernel_cr3(); uint32_t process_id = try_elf_run(drives + drive_number, vma_to_pma(active_task->page_directory, path), pass); switch_to_task_cr3(); return process_id; } static void *sc_allocate_ram(uint32_t pages) { return pd_user_allocate_anywhere_writable(active_task->page_directory, pages); } enum mi_arg { MI_KERNEL_MAX, MI_KERNEL_LEFT, MI_USER_MAX, MI_USER_LEFT, MI_TASK_LEFT }; __attribute__ ((pure)) static uint32_t sc_memory_info(enum mi_arg arg) { switch (arg) { case MI_KERNEL_MAX: return max_kernel_pages; case MI_KERNEL_LEFT: return kernel_pages_left; case MI_USER_MAX: return max_user_pages; case MI_USER_LEFT: return user_pages_left; case MI_TASK_LEFT: PANIC("TODO: memory info task left"); default: return -1; } } static void sc_wait_for_task(uint32_t handle) { active_task->wait_mode = PROCESS_END; active_task->wait_arg = handle; } static uint32_t sc_enumerate_dir(uint32_t drive_number, const char *path, struct directory_content_info *buffer, uint32_t max_entries) { return drives[drive_number].enumerate_dir(drives + drive_number, path, buffer, max_entries); } void const *syscall_table[] = { &sc_open_file, &sc_close_file, &sc_file_read, &sc_file_get_size, &sc_start_task, &logsz, &get_key_code, &sc_allocate_ram, &sc_memory_info, &sc_wait_for_task, &sc_enumerate_dir }; //these aren't really void ()'s, but gcc complains if we take an address of a void, so we give it a type typedef void isr_t(); extern isr_t syscall_isr; extern isr_t quit_isr; extern isr_t yield_isr; extern isr_t kbd_isr; extern isr_t udf_isr; extern isr_t dfa_isr; extern isr_t tsf_isr; extern isr_t npf_isr; extern isr_t ssf_isr; extern isr_t gpf_isr; extern isr_t pff_isr; __attribute__ ((noreturn)) void exception_halt(const char *id, uint32_t code, uint32_t eip, uint32_t cs) { char nbuf[11]; set_log_mode(LOG_PANIC); logsz("Exception #"); logsz(id); logsz(" at 0x"); u8_hex(cs, nbuf); logsz(nbuf); logsz(":0x"); u32_hex(eip, nbuf); logsz(nbuf); logsz("\nerror code = 0x"); u32_hex(code, nbuf); logsz(nbuf); logsz("\ntask name = "); logsz(active_task->name); logsz("\ncr3 = 0x"); uint32_t cr3; asm ( "mov %%cr3, %0" : "=r" (cr3)); u32_hex(cr3, nbuf); logsz(nbuf); logsz("\nHalting."); while (1) asm ("hlt"); } static void register_int(uint8_t n, isr_t *isr, uint8_t dpl) { idt[n].addr_low = (uint32_t)isr & 0xffff; idt[n].addr_high = (uint32_t)isr >> 16; idt[n].cs = 0x10; idt[n].flags = IDT_PRESENT | (dpl << 5) | IDT_INT; } enum { PIC_MCMD = 0x0020, PIC_MDATA = 0x0021, PIC_SCMD = 0x00a0, PIC_SDATA = 0x00a1 }; enum { PIC_RESET = 0x11 }; void init_idt() { for (uint16_t i = 0; i < 256; ++i) { idt[i].flags = 0; idt[i].zero = 0; } register_int(0x30, &syscall_isr, 3); register_int(0x38, &quit_isr, 3); register_int(0x39, &yield_isr, 3); register_int(0x21, &kbd_isr, 0); register_int(0x08, &udf_isr, 0); register_int(0x08, &dfa_isr, 0); register_int(0x0a, &tsf_isr, 0); register_int(0x0b, &npf_isr, 0); register_int(0x0c, &ssf_isr, 0); register_int(0x0d, &gpf_isr, 0); register_int(0x0e, &pff_isr, 0); outb(PIC_MCMD, PIC_RESET); outb(PIC_SCMD, PIC_RESET); outb(PIC_MDATA, 0x20); outb(PIC_SDATA, 0x28); outb(PIC_MDATA, 0x04); outb(PIC_SDATA, 0x02); outb(PIC_MDATA, 0x01); outb(PIC_SDATA, 0x01); outb(PIC_MDATA, 0xfd); outb(PIC_SDATA, 0xff); asm volatile ( "lidt %0" : : "m" (idtr) : "al"); }