summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/syscall.c41
-rw-r--r--sys/syscall.h4
-rw-r--r--sys/syscall_objdir.c24
-rw-r--r--sys/syscall_pagedir.c112
-rw-r--r--sys/syscall_untyped.c17
5 files changed, 168 insertions, 30 deletions
diff --git a/sys/syscall.c b/sys/syscall.c
index 9a98030..eb2874d 100644
--- a/sys/syscall.c
+++ b/sys/syscall.c
@@ -7,6 +7,22 @@
#include "sys/link.h"
#include "sys/message.h"
+int __syscall_generic_objpath(jove_owned_obj_t *objdir, size_t payload_bytes, void *payload_data, jove_owned_obj_t **retobj)
+{
+ size_t bytes_needed = sizeof(struct syscall_generic_objpath);
+ CHECK_TOOSMALL(bytes_needed, payload_bytes,
+ "Message too small for payload.");
+ struct syscall_generic_objpath *payload = payload_data;
+
+ bytes_needed += payload->pathlen << 1;
+ CHECK_TOOSMALL(bytes_needed, payload_bytes,
+ "Message too small for object path.");
+
+ errno = 0;
+ *retobj = objdir_getobj(objdir, payload->path, payload->pathlen);
+ return errno;
+}
+
int
_syscall_handle_generic(
jove_owned_obj_t *pcb_obj,
@@ -47,17 +63,15 @@ syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen)
jove_owned_obj_t *pcb_obj = process_current();
pcb_t *pcb = obj_deref(pcb_obj);
-
jove_owned_obj_t *objdir = pcb_rootdir(pcb);
-
jove_owned_obj_t *message_obj = objdir_getobj(objdir, message_path, message_pathlen);
+
+ int sysret = 0;
if(message_obj == 0) {
- obj_release(objdir);
- obj_release(pcb_obj);
- return errno;
+ sysret = errno;
+ goto release_premsg;
}
- int sysret = 0;
if(obj_gettype_linked(message_obj) != JOVE_OBJ_MESSAGE) {
kprintf("syscall: Process %i tried to call syscall with invalid object: %P\n", pcb_pid(pcb), message_path, message_pathlen);
sysret = EBADOBJ;
@@ -68,12 +82,11 @@ syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen)
void *messagedata = message_data(message_obj);
struct syscall_header *header = messagedata;
- size_t header_bytes = sizeof(struct syscall_header) + header->pathlen * 2;
- int bytes_left = messagelen - header_bytes;
- if(bytes_left < 0) {
+ size_t bytes_needed = sizeof(struct syscall_header) + header->pathlen * 2;
+ if(bytes_needed > messagelen) {
//Target path exceeds message length.
- kprintf("syscall: Process %i tried to call syscall with OOB target path.\n", pcb_pid(pcb));
- sysret = EBADPATH;
+ kprintf("syscall: Process %i tried to call syscall with target path too big for message.\n", pcb_pid(pcb));
+ sysret = ETOOSMALL;
goto release_return;
}
jove_owned_obj_t *target = objdir_getobj(objdir, header->path, header->pathlen);
@@ -86,10 +99,11 @@ syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen)
}
uint8_t target_type = obj_gettype(target);
+ size_t bytes_left = messagelen - bytes_needed;
if(target_type > 0x7F) {
sysret = _syscall_handle_arch(
pcb_obj, objdir, message_obj, target,
- header, bytes_left, messagedata + header_bytes);
+ header, bytes_left, messagedata + bytes_needed);
}else{
syscall_handle_t call_handle = s_syscall_handles[obj_gettype(target)];
if(call_handle == NULL) {
@@ -99,11 +113,12 @@ syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen)
}else
sysret = call_handle(
pcb_obj, objdir, message_obj, target,
- header, bytes_left, messagedata + header_bytes);
+ header, bytes_left, messagedata + bytes_needed);
}
obj_release(target);
release_return:
obj_release(message_obj);
+release_premsg:
obj_release(objdir);
obj_release(pcb_obj);
return sysret;
diff --git a/sys/syscall.h b/sys/syscall.h
index ea75152..2044069 100644
--- a/sys/syscall.h
+++ b/sys/syscall.h
@@ -20,6 +20,7 @@ do { if(obj == NULL) { \
#define CHECK_OBJTYPE(obj, type, fail_msg) \
do { if(obj_gettype(obj) != type) { \
kprintf("%s: %s\n", __func__, fail_msg); \
+ obj_release(obj); \
return EBADOBJ; \
} } while(0)
@@ -34,11 +35,14 @@ do { if(obj == NULL) { \
typedef int (*syscall_handle_t)(SYSCALL_FUNCTION_ARGS);
+int __syscall_generic_objpath(jove_owned_obj_t *objdir, size_t bytes_left, void *payload_data, jove_owned_obj_t **retobj);
+
int _syscall_handle_generic(SYSCALL_FUNCTION_ARGS);
int _syscall_handle_arch(SYSCALL_FUNCTION_ARGS);
int _syscall_handle_vtt(SYSCALL_FUNCTION_ARGS);
int _syscall_handle_objdir(SYSCALL_FUNCTION_ARGS);
int _syscall_handle_untyped(SYSCALL_FUNCTION_ARGS);
+int _syscall_handle_pagedir(SYSCALL_FUNCTION_ARGS);
#endif
diff --git a/sys/syscall_objdir.c b/sys/syscall_objdir.c
index 5e49fd4..277639f 100644
--- a/sys/syscall_objdir.c
+++ b/sys/syscall_objdir.c
@@ -1,3 +1,4 @@
+#include "arch/x86_64/hal/obj.h"
#include "hal/process.h"
#include "jove.h"
#include "lib/printf.h"
@@ -10,20 +11,17 @@ s_syscall_objdir_objtype(
size_t payload_size,
void *payload_data)
{
- int bytes_needed = sizeof(struct syscall_generic_objpath);
- CHECK_TOOSMALL(bytes_needed, payload_size, "Message is too small for this payload!");
-
- struct syscall_generic_objpath *payload = payload_data;
- bytes_needed += payload->pathlen * 2;
- CHECK_TOOSMALL(bytes_needed, payload_size, "Message is too small for second target path!");
+ size_t bytes_needed = 2;
+ CHECK_TOOSMALL(bytes_needed, payload_size, "Message is too small for payload.");
- int retval = 0;
- jove_owned_obj_t *second_obj = objdir_getobj(objdir, payload->path, payload->pathlen);
- CHECK_OBJEXISTS(second_obj, "Second target does not exist!");
+ uint16_t local_idx = *((uint16_t*)payload_data);
+ if(local_idx > JOVE_OBJDIR_ENTRIES) {
+ kprintf("%s: Object index is out of bounds (>= 512)\n", __func__);
+ return EOOB;
+ }
- retval = obj_gettype(second_obj);
- obj_release(second_obj);
- return retval;
+ jove_obj_t local_obj = objdir_peeklocal(target_dir, local_idx);
+ return obj_peektype(local_obj);
}
int
@@ -41,6 +39,6 @@ _syscall_handle_objdir(
return s_syscall_objdir_objtype(objdir, target_obj, bytes_left, payload);
default:
kprintf("syscall_handle_objdir: Objdir does not support syscall %i\n", header->callid);
- return EOOB;
+ return EBADARG;
}
}
diff --git a/sys/syscall_pagedir.c b/sys/syscall_pagedir.c
new file mode 100644
index 0000000..144a02b
--- /dev/null
+++ b/sys/syscall_pagedir.c
@@ -0,0 +1,112 @@
+#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;
+ }
+}
diff --git a/sys/syscall_untyped.c b/sys/syscall_untyped.c
index 3467830..fcdb5f6 100644
--- a/sys/syscall_untyped.c
+++ b/sys/syscall_untyped.c
@@ -20,7 +20,7 @@ s_syscall_untyped_split(
jove_owned_obj_t *dst_obj = objdir_getobj(objdir, payload->dest_path, payload->dest_pathlen);
CHECK_OBJTYPE(dst_obj, JOVE_OBJ_NONE, "Destination path is occupied!");
-
+
return untyped_split(target_obj, dst_obj, payload->bytes);
}
@@ -41,7 +41,14 @@ s_syscall_untyped_merge(
jove_owned_obj_t *snd_obj = objdir_getobj(objdir, payload->path, payload->pathlen);
CHECK_OBJTYPE(snd_obj, JOVE_OBJ_UNTYPED, "Second object is not an untyped!");
- return untyped_merge(target_obj, snd_obj);
+ int sysret = untyped_merge(target_obj, snd_obj);
+ if(obj_gettype(snd_obj) == JOVE_OBJ_UNTYPED) {
+ //Untyped merged into second object. We need to switch objects.
+ obj_settype(target_obj, JOVE_OBJ_UNTYPED);
+ obj_setvalue(target_obj, obj_getvalue(snd_obj));
+ obj_settype(snd_obj, JOVE_OBJ_NONE);
+ }
+ return sysret;
}
@@ -55,12 +62,14 @@ int _syscall_handle_untyped(
void* payload)
{
switch(header->callid) {
+ case SYSCALL_UNTYPED_ADDRESS:
+ return untyped_address(target_obj);
case SYSCALL_UNTYPED_SIZE:
return untyped_size(target_obj);
- case SYSCALL_UNTYPED_ALIGN:
- return untyped_align(target_obj);
case SYSCALL_UNTYPED_SPLIT:
return s_syscall_untyped_split(objdir, target_obj, payload_bytes, payload);
+ case SYSCALL_UNTYPED_MERGE:
+ return s_syscall_untyped_merge(objdir, target_obj, payload_bytes, payload);
default:
kprintf("syscall_untyped: Untyped object does not support syscall %i\n", header->callid);
return EBADARG;