aboutsummaryrefslogtreecommitdiff
path: root/libs/libc/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libc/sys.c')
-rw-r--r--libs/libc/sys.c203
1 files changed, 203 insertions, 0 deletions
diff --git a/libs/libc/sys.c b/libs/libc/sys.c
new file mode 100644
index 0000000..491c37c
--- /dev/null
+++ b/libs/libc/sys.c
@@ -0,0 +1,203 @@
+// MIT License, Copyright (c) 2020 Marvin Borner
+// Syscall implementation
+
+#include <arg.h>
+#include <assert.h>
+#include <errno.h>
+#include <sys.h>
+
+#if defined(userspace)
+
+/**
+ * Definitions
+ */
+
+#define ERRIFY(ret) \
+ if (ret < 0) { \
+ errno = -ret; \
+ return -1; \
+ } \
+ errno = 0; \
+ return ret
+
+res sys0(enum sys num);
+res sys0(enum sys num)
+{
+ int a;
+ __asm__ volatile("int $0x80" : "=a"(a) : "0"(num));
+ ERRIFY(a);
+}
+
+res sys1(enum sys num, int d1);
+res sys1(enum sys num, int d1)
+{
+ int a;
+ __asm__ volatile("int $0x80" : "=a"(a) : "0"(num), "b"((int)d1));
+ ERRIFY(a);
+}
+
+res sys2(enum sys num, int d1, int d2);
+res sys2(enum sys num, int d1, int d2)
+{
+ int a;
+ __asm__ volatile("int $0x80" : "=a"(a) : "0"(num), "b"((int)d1), "c"((int)d2));
+ ERRIFY(a);
+}
+
+res sys3(enum sys num, int d1, int d2, int d3);
+res sys3(enum sys num, int d1, int d2, int d3)
+{
+ int a;
+ __asm__ volatile("int $0x80"
+ : "=a"(a)
+ : "0"(num), "b"((int)d1), "c"((int)d2), "d"((int)d3));
+ ERRIFY(a);
+}
+
+res sys4(enum sys num, int d1, int d2, int d3, int d4);
+res sys4(enum sys num, int d1, int d2, int d3, int d4)
+{
+ int a;
+ __asm__ volatile("int $0x80"
+ : "=a"(a)
+ : "0"(num), "b"((int)d1), "c"((int)d2), "d"((int)d3), "S"((int)d4));
+ ERRIFY(a);
+}
+
+res sys5(enum sys num, int d1, int d2, int d3, int d4, int d5);
+res sys5(enum sys num, int d1, int d2, int d3, int d4, int d5)
+{
+ int a;
+ __asm__ volatile("int $0x80"
+ : "=a"(a)
+ : "0"(num), "b"((int)d1), "c"((int)d2), "d"((int)d3), "S"((int)d4),
+ "D"((int)d5));
+ ERRIFY(a);
+}
+
+/**
+ * Syscalls
+ */
+
+res sys_alloc(u32 size, u32 *addr)
+{
+ u32 id = 0;
+ return sys4(SYS_ALLOC, (int)size, (int)addr, (int)&id, 0);
+}
+
+res sys_free(void *ptr)
+{
+ return sys1(SYS_FREE, (int)ptr);
+}
+
+res shalloc(u32 size, u32 *addr, u32 *id)
+{
+ return sys4(SYS_ALLOC, (int)size, (int)addr, (int)id, 1);
+}
+
+res shaccess(u32 id, u32 *addr, u32 *size)
+{
+ return sys3(SYS_SHACCESS, (int)id, (int)addr, (int)size);
+}
+
+void loop(void)
+{
+ sys0(SYS_LOOP);
+}
+
+res read(const char *path, void *buf, u32 offset, u32 count)
+{
+ return sys4(SYS_READ, (int)path, (int)buf, (int)offset, (int)count);
+}
+
+res write(const char *path, const void *buf, u32 offset, u32 count)
+{
+ return sys4(SYS_WRITE, (int)path, (int)buf, (int)offset, (int)count);
+}
+
+res ioctl(const char *path, ...)
+{
+ va_list ap;
+ int args[4] = { 0 };
+
+ va_start(ap, path);
+ for (int i = 0; i < 4; i++)
+ args[i] = va_arg(ap, int);
+ va_end(ap);
+
+ return sys5(SYS_IOCTL, (int)path, args[0], args[1], args[2], args[3]);
+}
+
+res stat(const char *path, struct stat *buf)
+{
+ return sys2(SYS_STAT, (int)path, (int)buf);
+}
+
+res poll(const char **files)
+{
+ return sys1(SYS_POLL, (int)files);
+}
+
+res exec(const char *path, ...)
+{
+ va_list ap;
+ int args[4] = { 0 };
+
+ va_start(ap, path);
+ for (int i = 0; i < 4; i++)
+ args[i] = va_arg(ap, int);
+ va_end(ap);
+
+ return sys5(SYS_EXEC, (int)path, args[0], args[1], args[2], args[3]);
+}
+
+res yield(void)
+{
+ return sys0(SYS_YIELD);
+}
+
+static void atexit_trigger(void);
+void exit(s32 status)
+{
+ atexit_trigger();
+ sys1(SYS_EXIT, (int)status);
+ while (1)
+ yield();
+}
+
+res boot(u32 cmd)
+{
+ return sys2(SYS_BOOT, SYS_BOOT_MAGIC, cmd);
+}
+
+u32 time(void)
+{
+ return (u32)sys0(SYS_TIME);
+}
+
+/**
+ * At exit
+ */
+
+#define ATEXIT_MAX 32
+
+static u32 slot = 0;
+static void (*funcs[ATEXIT_MAX])(void) = { 0 };
+
+static void atexit_trigger(void)
+{
+ while (slot-- > 0) {
+ if (funcs[slot]) {
+ funcs[slot]();
+ funcs[slot] = NULL;
+ }
+ }
+}
+
+void atexit(void (*func)(void))
+{
+ if (slot < ATEXIT_MAX)
+ funcs[slot++] = func;
+}
+
+#endif