#include "hal/memory.h" #include "jove.h" #include "lib/printf.h" #include "syscall.h" static int s_syscall_pagedir_map( jove_owned_obj_t *objdir, jove_owned_obj_t *target_obj, size_t payload_bytes, void *payload_data, jove_owned_obj_t **untyped_ret) { size_t bytes_needed = sizeof(struct syscall_pagedir_map); CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message too small for payload."); struct syscall_pagedir_map *payload = payload_data; if(payload->virtual_address > 0xFFFF800000000000ULL) { kprintf("%s: Virtual address is above user limit.\n", __func__); return EBADARG; } bytes_needed += payload->untyped_pathlen << 1; CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message too small for untyped path."); errno = 0; jove_owned_obj_t *untyped_obj = objdir_getobj(objdir, payload->untyped_path, payload->untyped_pathlen); if(errno) { kprintf("%s: Untyped path does not point to a valid object.\n", __func__); return errno; } CHECK_OBJTYPE(untyped_obj, JOVE_OBJ_UNTYPED, "Untyped path does not point to an untyped object."); jove_untyped_t *untyped_data = obj_deref(untyped_obj); if((uintptr_t)untyped_data & 0xFFF) { kprintf("%s: Untyped object is not page aligned.\n", __func__); obj_release(untyped_obj); return EALIGN; } if(untyped_data->limit != 0x1000) { kprintf("%s: Untyped object is not page sized.\n", __func__); obj_release(untyped_obj); return EBADSIZE; } *untyped_ret = untyped_obj; return 0; } static int s_syscall_pagedir_map_frame( jove_owned_obj_t *objdir, jove_owned_obj_t *target_obj, size_t payload_bytes, void *payload_data) { jove_owned_obj_t *untyped_obj = NULL; int sysret = s_syscall_pagedir_map(objdir, target_obj, payload_bytes, payload_data, &untyped_obj); if(sysret != 0) { return sysret; } struct syscall_pagedir_map *payload = payload_data; sysret = pagedir_map_frame(target_obj, untyped_obj, payload->virtual_address, payload->flags); obj_release(untyped_obj); return sysret; } static int s_syscall_pagedir_map_table( jove_owned_obj_t *objdir, jove_owned_obj_t *target_obj, size_t payload_bytes, void *payload_data) { jove_owned_obj_t *untyped_obj = NULL; int sysret = s_syscall_pagedir_map(objdir, target_obj, payload_bytes, payload_data, &untyped_obj); if(sysret != 0) { return sysret; } struct syscall_pagedir_map *payload = payload_data; sysret = pagedir_map_frame(target_obj, untyped_obj, payload->virtual_address, payload->flags); obj_release(untyped_obj); return sysret; } int _syscall_handle_pagedir( 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) { switch(header->callid) { case SYSCALL_PAGEDIR_MAP_FRAME: return s_syscall_pagedir_map_frame(objdir, target_obj, bytes_left, payload); case SYSCALL_PAGEDIR_MAP_TABLE: return s_syscall_pagedir_map_table(objdir, target_obj, bytes_left, payload); default: kprintf("syscall_handle_pagedir: Pagedir does not support syscall %i\n", header->callid); return EBADARG; } }