#include "sys/syscall.h" #include "arch/x86_64/hal/obj.h" #include "hal/smp.h" #include "hal/process.h" #include "jove.h" #include "lib/printf.h" #include "sys/message.h" int _syscall_handle_generic( jove_owned_obj_t *pcb_obj, jove_owned_obj_t *objdir, jove_owned_obj_t *message_obj, jove_owned_obj_t *target_obj, struct syscall_header *header, size_t bytes_left, void *payload) { pcb_t *pcb = obj_deref(pcb_obj); kprintf("syscall: Process %i encountered stub syscall on object %P\n", pcb_pid(pcb), header->path, header->pathlen); return EBADOBJ; } static const syscall_handle_t s_syscall_handles[128] = { [JOVE_OBJ_NONE] = NULL, [JOVE_OBJ_UNTYPED] = _syscall_handle_generic, [JOVE_OBJ_OBJDIR] = _syscall_handle_generic, [JOVE_OBJ_PAGEDIR] = _syscall_handle_generic, [JOVE_OBJ_PROCESSOR] = _syscall_handle_generic, [JOVE_OBJ_PROCESS] = _syscall_handle_generic, [JOVE_OBJ_PAGEFRAME] = _syscall_handle_generic, [JOVE_OBJ_INITRD_FILE] = _syscall_handle_generic, [JOVE_OBJ_FRAMEBUFFER] = _syscall_handle_generic, [JOVE_OBJ_VIRTTERM] = _syscall_handle_generic, [JOVE_OBJ_MESSAGE] = _syscall_handle_generic, }; int syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen) { uint16_t *message_path = (uint16_t*)&message_path_raw; if(message_pathlen > sizeof(uintmax_t) >> 1) { return EBADPATH; } jove_owned_obj_t *pcb_obj = process_current(); pcb_t *pcb = obj_deref(pcb_obj); jove_owned_obj_t *objdir = pcb_rootdir(pcb); kprintf("Syscall: %p : %P \n", objdir, message_path, message_pathlen); jove_owned_obj_t *message_obj = objdir_getobj(objdir, message_path, message_pathlen); if(message_obj == 0) { obj_release(objdir); obj_release(pcb_obj); return errno; } #define SYSCALL_MIDWAY_CLEANUP \ obj_release(message_obj); \ obj_release(objdir); \ obj_release(pcb_obj) if(obj_gettype(message_obj) != JOVE_OBJ_MESSAGE) { kprintf("syscall: Process %i tried to call syscall with invalid object: %P\n", pcb_pid(pcb), message_path, message_pathlen); SYSCALL_MIDWAY_CLEANUP; return EBADOBJ; } size_t messagelen = message_len(message_obj); void *messagedata = message_data(message_obj); struct syscall_header *header = messagedata; size_t header_bytes = sizeof(struct syscall_header) + header->pathlen * 2; int bytes_left = messagelen - header_bytes; kprintf("syscall: Payload %p len %i\n", messagedata, header->pathlen); if(bytes_left < 0) { //Target path exceeds message length. kprintf("syscall: Process %i tried to call syscall with OOB target path.\n", pcb_pid(pcb)); SYSCALL_MIDWAY_CLEANUP; return EBADPATH; } jove_owned_obj_t *target = objdir_getobj(objdir, header->path, header->pathlen); if(target == 0) { //Could not find payload target in pcb rootdir. kprintf("syscall: Process %i tried to call syscall with bad target path %P\n", pcb_pid(pcb), header->path, header->pathlen); SYSCALL_MIDWAY_CLEANUP; return errno; } int sysret = 0; uint8_t target_type = obj_gettype(target); if(target_type > 0x7F) { sysret = syscall_handle_arch(pcb_obj, objdir, message_obj, target, header, bytes_left, messagedata + header_bytes); }else{ syscall_handle_t call_handle = s_syscall_handles[obj_gettype(target)]; if(call_handle == NULL) { kprintf("syscall: Process %i tried to call syscall on object %P which doesn't support syscalls!\n", pcb_pid(pcb), header->path, header->pathlen); sysret = EBADOBJ; }else sysret = call_handle(pcb_obj, objdir, message_obj, target, header, bytes_left, message_data + header_bytes); } obj_release(target); SYSCALL_MIDWAY_CLEANUP; return sysret; }