summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/syscall.h41
-rw-r--r--arch/x86_64/proc/process.c1
-rw-r--r--doc/syscall.md60
-rw-r--r--lib/rbtree.c84
-rw-r--r--lib/rbtree.h2
-rw-r--r--sys/syscall.c2
-rw-r--r--sys/syscall.h1
-rw-r--r--sys/syscall_initrd_file.c98
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;
+ }
+}