diff options
| author | Jon Santmyer <jon@jonsantmyer.com> | 2026-10-03 12:03:11 -0400 |
|---|---|---|
| committer | Jon Santmyer <jon@jonsantmyer.com> | 2026-10-03 12:03:11 -0400 |
| commit | 2497a94013261d6fa9159b9c6e94abe6f2d4fd9e (patch) | |
| tree | d9bfa0536d882a9f28cddf415ebfd75b6b54c837 | |
| parent | c2788174198632e0c8bdbfa7762081f595460bdf (diff) | |
| download | jove-kernel-2497a94013261d6fa9159b9c6e94abe6f2d4fd9e.tar.gz jove-kernel-2497a94013261d6fa9159b9c6e94abe6f2d4fd9e.tar.bz2 jove-kernel-2497a94013261d6fa9159b9c6e94abe6f2d4fd9e.zip | |
process rbtree. add syscall for initrd_file access.
| -rw-r--r-- | api/syscall.h | 41 | ||||
| -rw-r--r-- | arch/x86_64/proc/process.c | 1 | ||||
| -rw-r--r-- | doc/syscall.md | 60 | ||||
| -rw-r--r-- | lib/rbtree.c | 84 | ||||
| -rw-r--r-- | lib/rbtree.h | 2 | ||||
| -rw-r--r-- | sys/syscall.c | 2 | ||||
| -rw-r--r-- | sys/syscall.h | 1 | ||||
| -rw-r--r-- | sys/syscall_initrd_file.c | 98 |
8 files changed, 280 insertions, 9 deletions
diff --git a/api/syscall.h b/api/syscall.h index 1cdc941..9f8ec13 100644 --- a/api/syscall.h +++ b/api/syscall.h @@ -29,15 +29,15 @@ struct syscall_generic_write char data[]; }; -/* If the message is too small for path, the kernel will return ETOOSMALL. - * If the path does not point to an object, the kernel will return EBADPATH. - * */ struct syscall_generic_objpath { uint16_t pathlen; objpath_part_t path[]; }; +/**JOVE_OBJ_UNTYPED syscalls. + * */ + enum { _SYSCALL_UNTYPED_BADCALL = 0, @@ -60,6 +60,9 @@ struct syscall_untyped_split objpath_part_t dest_path[]; }; +/**JOVE_OBJ_OBJDIR syscalls. + * */ + enum { _SYSCALL_OBJDIR_BADCALL = 0, @@ -68,6 +71,9 @@ enum #define SYSCALL_PERM_OBJDIR_OBJTYPE JOVE_PERM_READ +/* JOVE_OBJ_PAGEDIR syscalls + * */ + enum { _SYSCALL_PAGEDIR_NONE = 0, @@ -117,6 +123,35 @@ struct syscall_pagedir_unmap objpath_part_t none_path[]; }; +/**JOVE_OBJ_INITRD_FILE syscalls + * */ + +enum +{ + _SYSCALL_INITRD_FILE_NONE = 0, + SYSCALL_INITRD_FILE_NAME, + SYSCALL_INITRD_FILE_SIZE, + SYSCALL_INITRD_FILE_READ +}; + +#define SYSCALL_PERM_INITRD_FILE_NAME (JOVE_PERM_READ) +#define SYSCALL_PERM_INITRD_FILE_SIZE (JOVE_PERM_READ) +#define SYSCALL_PERM_INITRD_FILE_READ (JOVE_PERM_READ) + +struct syscall_initrd_file_name_ret +{ + size_t len; + char c_str[]; +}; + +struct syscall_initrd_file_read +{ + size_t start_index; + size_t read_size; +}; + +/**JOVE_OBJ_VIRTTERM syscalls.*/ + enum { _SYSCALL_VTT_NONE = 0, diff --git a/arch/x86_64/proc/process.c b/arch/x86_64/proc/process.c index 55af85a..0c5c282 100644 --- a/arch/x86_64/proc/process.c +++ b/arch/x86_64/proc/process.c @@ -32,6 +32,7 @@ processing_setup(void (*process_main)) uintptr_t ksp = ((uintptr_t)&_init_pcb_bytes) + 0xFF8; _init_pcb->tree_node.get_key = (void*)pcb_pid; + _init_pcb->tree_node.color = 1; _init_pcb->pid = 1; _init_pcb->ksp = (void*)ksp; diff --git a/doc/syscall.md b/doc/syscall.md index 9304785..3bfa00b 100644 --- a/doc/syscall.md +++ b/doc/syscall.md @@ -8,9 +8,9 @@ To resolve the message object, the kernel requires an object path and a path len On x86_64, the encoding is as follows: -| | Message Path | Message Path Length | -|----------|--------------|---------------------| -| Register | rdi | rsi | +| Message Path | Message Path Length | +|--------------|---------------------| +| rdi | rsi | If the message path exceeds the width of the message path register, the kernel will return `-EBADPATH`. @@ -118,7 +118,7 @@ If the entry index exceeds `JOVE_OBJDIR_ENTRIES`, the kernel returns `-EOOB`. |-----------------------------|:-------------------------------:|:-------------------------------------------------:|:-------------------------------:| | SYSCALL_PAGEDIR_MAP_FRAME | JOVE_PERM_READ, JOVE_PERM_WRITE | JOVE_PERM_MUTATE | JOVE_PERM_READ, JOVE_PERM_WRITE | | SYSCALL_PAGEDIR_MAP_TABLE | JOVE_PERM_READ, JOVE_PERM_WRITE | JOVE_PERM_READ, JOVE_PERM_WRITE, JOVE_PERM_MUTATE | | -| SYSCALL_PAGEDIR_MAP_SHMEM | JOVE_PERM_READ, JOVE_PERM_WRITE | | JOVE_PERM_READ, JOVE_PERM_WRITE | +| SYSCALL_PAGEDIR_MAP_SHMEM | JOVE_PERM_READ, JOVE_PERM_WRITE | JOVE_PERM_READ | JOVE_PERM_WRITE | | SYSCALL_PAGEDIR_UNMAP_FRAME | JOVE_PERM_READ, JOVE_PERM_WRITE | | | | SYSCALL_PAGEDIR_UNMAP_TABLE | JOVE_PERM_READ, JOVE_PERM_WRITE | | | | SYSCALL_PAGEDIR_UNMAP_SHMEM | JOVE_PERM_READ, JOVE_PERM_WRITE | | | @@ -262,3 +262,55 @@ If the virtual address does not have a page frame associated with it, the kernel If the page frame pointed to by virtual address does not correspond to a shared memory frame, the kernel will return `-EBADOBJ`. Successful unmapping returns `0`. + +### JOVE_OBJ_INITRD_FILE + +| Syscall | Target Permissions | +|--------------------------|--------------------| +| SYSCALL_INITRD_FILE_NAME | JOVE_PERM_READ | +| SYSCALL_INITRD_FILE_SIZE | JOVE_PERM_READ | +| SYSCALL_INITRD_FILE_READ | JOVE_PERM_READ | + +#### SYSCALL_INITRD_FILE_NAME + +Populates the message with the name of the target file. + +Names start with a size_t length specifier, which is followed by a NULL-terminated c-string. + +| Data | Name Length | Name | Null Terminator | +|--------------|----------------|-------------|-----------------| +| Size (bytes) | sizeof(size_t) | Name Length | 1 | + + +If the message is too small for the file name, the kernel will return `-ETOOSMALL`. + +#### SYSCALL_INITRD_FILE_SIZE + +Returns the size of the target file in bytes. + +#### SYSCALL_INITRD_FILE_READ + +Populates the message with the bytes read from the target file. + +##### Payload + +| Data | Starting index | Read size | +|--------------|----------------|----------------| +| Size (bytes) | sizeof(size_t) | sizeof(size_t) | + +##### Return + +| Data | Data | +|--------------|-----------| +| Size (bytes) | Read size | + + +If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`. + +If the starting index exceeds the file length, the kernel will return `-EOOB`. + +If the read size + starting index > file size, the kernel will return `-EOOB`. + +If the message is too small for the read bytes, the kernel will return `-ETOOBIG`. + +Successful reading returns `0`. diff --git a/lib/rbtree.c b/lib/rbtree.c new file mode 100644 index 0000000..dc9caf1 --- /dev/null +++ b/lib/rbtree.c @@ -0,0 +1,84 @@ +#include "rbtree.h" + +static inline int +s_direction(const struct rbtree_node *node) +{ + return node == node->parent->children[0] ? 0 : 1; +} + +static struct rbtree_node* +s_rotate(struct rbtree_node *sub, int dir) +{ + int opp = 1 - dir; + struct rbtree_node *sub_parent = sub->parent; + struct rbtree_node *new_root = sub_parent->children[opp]; + struct rbtree_node *new_child = new_root->children[dir]; + + sub_parent->children[opp] = new_child; + if(new_child) new_child->parent = sub; + + new_root->children[dir] = sub; + new_root->parent = sub_parent; + sub->parent = new_root; + + if(sub_parent) + sub_parent->children[s_direction(sub)] = new_root; + return new_root; +} + +void +rbtree_insert(struct rbtree_node *root, struct rbtree_node *node) +{ + struct rbtree_node *parent = root; + int direction; + while(1) { + direction = parent->get_key(parent) < node->get_key(node); + if(parent->children[direction] == 0) break; + parent = parent->children[direction]; + } + + node->color = 1; + parent->children[direction] = node; + node->parent = parent; + + //Rebalance the tree + do { + //Tree is already balanced, return + if(parent->color == 0) return; + struct rbtree_node *gparent = parent->parent; + + //Parent is the root node, set parent to black. + if(!gparent) { + parent->color = 0; + return; + } + + direction = s_direction(parent); + struct rbtree_node *uncle = gparent->children[1-direction]; + if(!uncle || uncle->color == 0) { + //If the uncle node DNE or is black, the tree has to be rotated. + if(node == parent->children[1-direction]) { + //Rotate parent node so that node is the new parent. + s_rotate(parent, direction); + node = parent; + parent = gparent->children[direction]; + } + + //Rotate the parent node so that the gparent is the new parent. + s_rotate(gparent, 1-direction); + parent->color = 0; + gparent->color = 1; + return; + } + + //Both the parent and uncle are red. Push up the red and iterate up. + parent->color = 0; + uncle->color = 0; + gparent->color = 1; + node = gparent; + } while((parent = node->parent)); + + //Tree is balanced now. +} + + diff --git a/lib/rbtree.h b/lib/rbtree.h index 1dbd5b2..22c44f8 100644 --- a/lib/rbtree.h +++ b/lib/rbtree.h @@ -12,6 +12,6 @@ struct rbtree_node intmax_t (*get_key)(struct rbtree_node*); }; - +void rbtree_insert(struct rbtree_node *parent, struct rbtree_node *node); #endif 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; + } +} |
