diff options
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/syscall.c | 2 | ||||
| -rw-r--r-- | sys/syscall.h | 1 | ||||
| -rw-r--r-- | sys/syscall_initrd_file.c | 98 |
3 files changed, 100 insertions, 1 deletions
diff --git a/sys/syscall.c b/sys/syscall.c index 5cef3d6..1c9af45 100644 --- a/sys/syscall.c +++ b/sys/syscall.c @@ -39,7 +39,7 @@ static const syscall_handle_t s_syscall_handles[128] = { [JOVE_OBJ_SHMEMORY] = _syscall_handle_generic, [JOVE_OBJ_PCB] = _syscall_handle_generic, [JOVE_OBJ_INT_HANDLE] = _syscall_handle_generic, - [JOVE_OBJ_INITRD_FILE] = _syscall_handle_generic, + [JOVE_OBJ_INITRD_FILE] = _syscall_handle_initrd_file, [JOVE_OBJ_FRAMEBUFFER] = _syscall_handle_generic, [JOVE_OBJ_VIRTTERM] = _syscall_handle_vtt, [JOVE_OBJ_MESSAGE] = _syscall_handle_generic, diff --git a/sys/syscall.h b/sys/syscall.h index e6358cb..ab13118 100644 --- a/sys/syscall.h +++ b/sys/syscall.h @@ -57,5 +57,6 @@ int _syscall_handle_vtt(syscall_context_t *ctx); int _syscall_handle_objdir(syscall_context_t *ctx); int _syscall_handle_untyped(syscall_context_t *ctx); int _syscall_handle_pagedir(syscall_context_t *ctx); +int _syscall_handle_initrd_file(syscall_context_t *ctx); #endif diff --git a/sys/syscall_initrd_file.c b/sys/syscall_initrd_file.c new file mode 100644 index 0000000..8e34488 --- /dev/null +++ b/sys/syscall_initrd_file.c @@ -0,0 +1,98 @@ +#include "api/error.h" +#include "boot/initrd.h" +#include "lib/printf.h" +#include "sys/message.h" +#include "sys/syscall.h" +#include "lib/string.h" + +int +s_syscall_initrd_file_name( + jove_owned_obj_t *initrd_file, + jove_owned_obj_t *message) +{ + const char *filename = initrd_file_name(initrd_file); + size_t filename_len = strlen(filename); + + size_t bytes_left = message_len(message); + size_t bytes_needed = filename_len + sizeof(struct syscall_initrd_file_name_ret); + + CHECK_TOOSMALL(bytes_needed, bytes_left, "Message is too small for file name."); + struct syscall_initrd_file_name_ret *payload = message_data(message); + + payload->len = filename_len; + memcpy(payload->c_str, filename, filename_len); + return 0; +} + +int +s_syscall_initrd_file_size(jove_owned_obj_t *initrd_file) +{ + return initrd_file_size(initrd_file); +} + +int +s_syscall_initrd_file_read( + jove_owned_obj_t *initrd_file, + jove_owned_obj_t *message, + size_t bytes_left, + void *payload_data) +{ + //Ensure that the message payload could hold the required read payload. + size_t bytes_needed = sizeof(struct syscall_initrd_file_read); + CHECK_TOOSMALL(bytes_needed, bytes_left, + "Message is too small to hold read payload."); + + struct syscall_initrd_file_read *payload = payload_data; + bytes_needed = payload->read_size; + bytes_left = message_len(message); + + //Ensure that the message is big enough to hold the read file data. + CHECK_TOOSMALL(bytes_needed, bytes_left, + "Message is too small to hold read bytes."); + + size_t file_size = initrd_file_size(initrd_file); + char *file_data = initrd_file_data(initrd_file); + + //Ensure that the start index is within the file. + if(payload->start_index >= file_size) { + klogf("Start index exceeds file length! (%i > %i)\n", + payload->start_index, file_size); + return -EOOB; + } + + //Ensure that the read bounds is within the file. + if(payload->start_index + payload->read_size > file_size) { + klogf("Read bounds exceed file length! (%i+%i > %i)\n", + payload->start_index, payload->read_size, file_size); + return -ETOOBIG; + } + + void *read_data = message_data(message); + memcpy(read_data, file_data + payload->start_index, payload->read_size); + return 0; +} + +int +_syscall_handle_initrd_file(syscall_context_t *ctx) +{ + switch(ctx->header->callid) { + case SYSCALL_INITRD_FILE_NAME: + if(ctx->target.permissions & SYSCALL_PERM_INITRD_FILE_NAME) + return s_syscall_initrd_file_name( + ctx->target.obj, ctx->message.obj); + return -EPERM; + + case SYSCALL_INITRD_FILE_SIZE: + if(ctx->target.permissions & SYSCALL_PERM_INITRD_FILE_SIZE) + return s_syscall_initrd_file_size(ctx->target.obj); + return -EPERM; + + case SYSCALL_INITRD_FILE_READ: + if(ctx->target.permissions & SYSCALL_PERM_INITRD_FILE_READ) + return s_syscall_initrd_file_read( + ctx->target.obj, ctx->message.obj, ctx->bytes_left, ctx->payload); + return -EPERM; + default: + return -EBADCALL; + } +} |
