#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" enum { IDT_PRESENT = 0x80, IDT_INT = 0x0e, IDT_TRAP = 0x0f }; 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 bool sc_start_task(uint32_t drive_number, char *path) { switch_to_kernel_cr3(); bool result = try_elf_run(drives + drive_number, path); switch_to_task_cr3(); return result; } static void sc_log_string(char *sz) { logsz(sz); } static char sc_get_key() { panic("TODO: get key system call"); } 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: this process memory left"); default: return -1; } } void const *syscall_table[] = { &sc_open_file, &sc_close_file, &sc_file_read, &sc_file_get_size, &sc_start_task, &sc_log_string, &sc_get_key, &sc_allocate_ram, &sc_memory_info }; typedef void isr_t; extern isr_t syscall_isr; extern isr_t quit_isr; extern isr_t yield_isr; 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; } 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); outb(0x0021, 0xff); outb(0x00a1, 0xff); asm volatile ( "lidt %0" : : "m" (idtr) : "al"); }