From c4f8ef91f18d854a4ede7a94e95b2eab898d6963 Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Sun, 10 Aug 2025 15:40:19 -0400 Subject: working usermode objdir iteration --- syscall/handler.c | 76 +++++++++++++++++++++----------------- syscall/handles.h | 21 ++++++++++- syscall/invoke-untyped.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++ syscall/invoke_objdir.c | 94 +++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 238 insertions(+), 49 deletions(-) create mode 100644 syscall/invoke-untyped.c (limited to 'syscall') diff --git a/syscall/handler.c b/syscall/handler.c index efab179..6ac71da 100644 --- a/syscall/handler.c +++ b/syscall/handler.c @@ -3,64 +3,74 @@ #include "handles.h" #include "device/processor.h" #include "print.h" +#include "error.h" +#include "lock.h" +#include "memory.h" #include #include +extern int _syscall_handler_arch(objdir_t *root_dir, objdir_entry_t *target, uint8_t *payload, size_t payload_at); + +static inline int +s_invoke_release( + objdir_t *root_dir, + objdir_entry_t *target, + uint8_t *payload, + size_t payload_at, + int (*invoke)(objdir_t*, objdir_entry_t*, uint8_t*, size_t)) +{ + int e = invoke(root_dir, target, payload, payload_at); + return e; +} + static int -s_syscall_handle_invoke(objdir_t *root_dir, void *payload) +s_syscall_handle_invoke(objdir_t *root_dir, uint8_t *payload) { - struct syscallInvokeHeader *invokeHeader = payload; - uintmax_t target_path = invokeHeader->target_path; - objdir_entry_t *target_entry = objdir_seek(root_dir, target_path); - - klogf("target entry %x:%p func %i\n", target_path, target_entry->data, invokeHeader->func_id); + size_t payload_at = 0; + size_t target_pathw; + objdir_entry_t *target_entry; + SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, target_pathw, target_entry); - if(target_entry == NULL) return -1; switch(target_entry->type) { case KO_NONE: - return -1; + return -KE_BADOBJ; case KO_OBJECT_DIRECTORY: - return syscall_handle_invoke_objdir(root_dir, (objdir_t*)target_entry->data, payload); + return s_invoke_release(root_dir, target_entry, payload, payload_at, syscall_handle_invoke_objdir); + case KO_MEMORY_UNTYPED: + return s_invoke_release(root_dir, target_entry, payload, payload_at, syscall_handle_invoke_untyped); + case KO_MEMORY_MAPPING: + return s_invoke_release(root_dir, target_entry, payload, payload_at, syscall_handle_invoke_mapping); default: - klogf("Missing implementation of invoke for type %i\n", target_entry->type); - return -1; + return _syscall_handler_arch(root_dir, target_entry, payload, payload_at); } } int _syscall_handler(uintmax_t argsi, int calli) { - objdir_t *objdir = ((processor_t*)processor_current())->odir; - objdir_entry_t *payload_entry = objdir_seek(objdir, argsi); - if(payload_entry == NULL) { - klogf("Missing object for syscall %i (%x)\n", calli, argsi); - return -1; - } + objdir_t *root_dir = ((processor_t*)processor_current())->odir; + objdir_entry_t *payload_entry = objdir_seek(root_dir, (uint8_t*)&argsi, sizeof(uintmax_t)); + if(payload_entry->type != KO_MESSAGE) { klogf("Tried to invoke syscall %i with invalid object %x\n", calli, argsi); - return -1; + return -KE_BADMSG; } - - uintmax_t *payload = (void*)payload_entry->data; + mtx_acquire(&payload_entry->lock); + uint8_t *payload = ko_entry_data(payload_entry); switch(calli) { - case SYSCALL_INVOKE: return s_syscall_handle_invoke(objdir, payload); + case SYSCALL_INVOKE: { + int e = s_syscall_handle_invoke(root_dir, payload); + mtx_release(&payload_entry->lock); + return e; + } case SYSCALL_DEBUG_PUTC: kprintf("%c", (char)payload[0]); + mtx_release(&payload_entry->lock); return 0; - case SYSCALL_DEBUG_IDENTIFY: - { - objdir_entry_t *target_entry = objdir_seek(objdir, payload[0]); - if(payload_entry == NULL) { - payload[0] = KO_NONE; - } else { - payload[0] = target_entry->type; - } - return 0; - } default: klogf("Invalid syscall %i caught! Failing.\n", calli); - return -1; + mtx_release(&payload_entry->lock); + return -KE_BADCALL; } - return -1; } diff --git a/syscall/handles.h b/syscall/handles.h index f9fd79c..5b6e395 100644 --- a/syscall/handles.h +++ b/syscall/handles.h @@ -2,7 +2,26 @@ #define _JOVE_SYSCALL_HANDLES_H 1 #include "object.h" +#include -int syscall_handle_invoke_objdir(objdir_t *root_dir, objdir_t *target_dir, void *payload); +#define SYSCALL_PAYLOAD_TAKEL(p, at, val, type) \ + if(sizeof(type) + at >= KO_MESSAGE_BYTES) return -KE_BADMSG; \ + val = *((type*)(&p[at])); \ + at += sizeof(type) + +#define SYSCALL_PAYLOAD_TAKEP(p, at, val, type) \ + if(sizeof(type) + at >= KO_MESSAGE_BYTES) return -KE_BADMSG; \ + val = ((type*)(&p[at])); \ + at += sizeof(type) + +#define SYSCALL_PAYLOAD_TAKEOBJ(p, at, w, o) \ + SYSCALL_PAYLOAD_TAKEL(p, at, w, size_t); \ + if(w + payload_at >= KO_MESSAGE_BYTES) return -KE_BADMSG; \ + o = objdir_seek(root_dir, &p[at], w); \ + at += w + +int syscall_handle_invoke_objdir(objdir_t *root_dir, objdir_entry_t *target, uint8_t *payload, size_t payload_at); +int syscall_handle_invoke_untyped(objdir_t *root_dir, objdir_entry_t *target, uint8_t *payload, size_t payload_at); +int syscall_handle_invoke_mapping(objdir_t *root_dir, objdir_entry_t *target, uint8_t *payload, size_t payload_at); #endif diff --git a/syscall/invoke-untyped.c b/syscall/invoke-untyped.c new file mode 100644 index 0000000..6b9199f --- /dev/null +++ b/syscall/invoke-untyped.c @@ -0,0 +1,96 @@ +#include "handles.h" +#include "syscall.h" +#include "error.h" +#include "memory.h" +#include "print.h" + +static int +s_handle_invoke_untyped_size( + objdir_t *root_dir, + objdir_entry_t *target, + uint8_t *payload, + size_t payload_at + ) +{ + size_t *dest; + SYSCALL_PAYLOAD_TAKEP(payload, payload_at, dest, size_t); + + size_t *untyped = ko_entry_data(target); +#ifdef DBG_SYSCALL + klogf("root_dir %p target %p data %p\n", root_dir, target, untyped); +#endif + *dest = *untyped; + return 0; +} + +static int +s_handle_invoke_untyped_alignment( + objdir_t *root_dir, + objdir_entry_t *target, + uint8_t *payload, + size_t payload_at + ) +{ + size_t *dest; + SYSCALL_PAYLOAD_TAKEP(payload, payload_at, dest, size_t); +#ifdef DBG_SYSCALL + klogf("root_dir %p target %p data %p\n", root_dir, target, target->data); +#endif + + *dest = target->data & 0xFFF; + return 0; +} + +static int +s_handle_invoke_untyped_split( + objdir_t *root_dir, + objdir_entry_t *target, + uint8_t *payload, + size_t payload_at + ) +{ + size_t dest_pathw; + size_t dest_bytes; + objdir_entry_t *dest_entry; + + SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, dest_pathw, dest_entry); + if(dest_entry->type != KO_NONE) return -KE_BADOBJ; + + size_t *untyped = (size_t*)target->data; + size_t untyped_size = *untyped; + + SYSCALL_PAYLOAD_TAKEL(payload, payload_at, dest_bytes, size_t); + if(untyped_size - sizeof(size_t) <= dest_bytes) return -KE_TOOSMALL; + + size_t *split = (size_t*)(((uintptr_t)untyped) + untyped_size - dest_bytes); + *untyped -= dest_bytes; + *split = dest_bytes; + + *dest_entry = (objdir_entry_t) { + .type = KO_MEMORY_UNTYPED, + .data = (uintptr_t)split + }; + return 0; +} + +static int (*s_invoke_handles[])(objdir_t*, objdir_entry_t*, uint8_t*, size_t) = { + [INVOKE_UNTYPED_SIZE] = s_handle_invoke_untyped_size, + [INVOKE_UNTYPED_SPLIT] = s_handle_invoke_untyped_split, + + [INVOKE_UNTYPED_ALIGNMENT] = s_handle_invoke_untyped_alignment +}; +static size_t s_invoke_handles_count = sizeof(s_invoke_handles) / sizeof(void*); + +int +syscall_handle_invoke_untyped( + objdir_t *root_dir, + objdir_entry_t *target, + uint8_t *payload, + size_t payload_at) +{ + uint8_t funcid; + SYSCALL_PAYLOAD_TAKEL(payload, payload_at, funcid, uint8_t); + + if(funcid >= s_invoke_handles_count) return -KE_BADFUNC; + return s_invoke_handles[funcid](root_dir, target, payload, payload_at); +} diff --git a/syscall/invoke_objdir.c b/syscall/invoke_objdir.c index 4698f34..9cd3f32 100644 --- a/syscall/invoke_objdir.c +++ b/syscall/invoke_objdir.c @@ -1,34 +1,98 @@ #include "handles.h" #include "syscall.h" +#include "error.h" +#include "lock.h" +#include "print.h" static int -s_handle_invoke_objdir_nmemb(objdir_t *root_dir, objdir_t *target_dir, void *payload) +s_handle_invoke_objdir_nmemb( + objdir_t *root_dir, + objdir_t *target_dir, + uint8_t *payload, + size_t payload_at + ) { - struct syscallInvoke_objdir_nmemb *payloadStruct = payload; - payloadStruct->value = target_dir->self.data; - return 0; + uint8_t *dest; + SYSCALL_PAYLOAD_TAKEP(payload, payload_at, dest, uint8_t); + + *dest = target_dir->self.data; + +#ifdef DBG_SYSCALL + klogf("objdir_nmemb %p[%i]\n", dest, *dest); +#endif + return KE_OK; +} + +static int +s_handle_invoke_objdir_getmemb( + objdir_t *root_dir, + objdir_t *target_dir, + uint8_t *payload, + size_t payload_at + ) +{ + path_byte_t member; + obj_type_t *dest; + + SYSCALL_PAYLOAD_TAKEL(payload, payload_at, member, uint8_t); + SYSCALL_PAYLOAD_TAKEP(payload, payload_at, dest, obj_type_t); + + *dest = target_dir->entries[member].type; + +#ifdef DBG_SYSCALL + klogf("objdir_getmemb %i ret %i\n", member, *dest); +#endif + return KE_OK; } static int -s_handle_invoke_objdir_getmemb(objdir_t *root_dir, objdir_t *target_dir, void *payload) +s_handle_invoke_objdir_lastfree( + objdir_t *root_dir, + objdir_t *target_dir, + uint8_t *payload, + size_t payload_at + ) { - struct syscallInvoke_objdir_getmemb *payloadStruct = payload; - payloadStruct->value = target_dir->entries[payloadStruct->member].type; - return 0; + path_byte_t *dest; + SYSCALL_PAYLOAD_TAKEP(payload, payload_at, dest, path_byte_t); + + for(int i = 0; i < 256; i++) { + if(target_dir->entries[i].type == KO_NONE) { + *dest = (path_byte_t)i; + return KE_OK; + } + } + return -KE_FULL; } -static int (*s_invoke_handles[])(objdir_t*, objdir_t*, void*) = { +static int (*s_invoke_handles[])(objdir_t*, objdir_t*, uint8_t*, size_t) = { [INVOKE_OBJDIR_NMEMB] = s_handle_invoke_objdir_nmemb, - [INVOKE_OBJDIR_GETMEMB] = s_handle_invoke_objdir_getmemb + [INVOKE_OBJDIR_GETMEMB] = s_handle_invoke_objdir_getmemb, + [INVOKE_OBJDIR_LASTFREE] = s_handle_invoke_objdir_lastfree }; static size_t s_invoke_handles_count = sizeof(s_invoke_handles) / sizeof(void*); int -syscall_handle_invoke_objdir(objdir_t *root_dir, objdir_t *target_dir, void *payload) +syscall_handle_invoke_objdir( + objdir_t *root_dir, + objdir_entry_t *target_entry, + uint8_t *payload, + size_t payload_at + ) { - struct syscallInvokeHeader *invokeHeader = payload; - size_t funcid = invokeHeader->func_id; + uint8_t funcid; + SYSCALL_PAYLOAD_TAKEL(payload, payload_at, funcid, uint8_t); + + if(funcid >= s_invoke_handles_count) return -KE_BADFUNC; + objdir_t *target_dir = (objdir_t*)target_entry->data; + + if((void*)target_entry == root_dir) target_dir = root_dir; +#ifdef DBG_SYSCALL + klogf("Call %i root_dir %p target %p\n", funcid, root_dir, target_entry); +#endif - if(funcid >= s_invoke_handles_count) return -1; - return s_invoke_handles[funcid](root_dir, target_dir, payload); + mtx_acquire(&target_entry->lock); + int e = s_invoke_handles[funcid](root_dir, target_dir, payload, payload_at); + mtx_release(&target_entry->lock); + return e; } -- cgit v1.2.1