summaryrefslogtreecommitdiff
path: root/src/libk/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/libk/include')
-rw-r--r--src/libk/include/assert.h7
-rw-r--r--src/libk/include/camellia/errno.h28
-rw-r--r--src/libk/include/camellia/execbuf.h9
-rw-r--r--src/libk/include/camellia/flags.h35
-rw-r--r--src/libk/include/camellia/fsutil.h12
-rw-r--r--src/libk/include/camellia/path.h17
-rw-r--r--src/libk/include/camellia/syscalls.h96
-rw-r--r--src/libk/include/camellia/types.h41
-rw-r--r--src/libk/include/shared/mem.h18
-rw-r--r--src/libk/include/shared/printf.h6
-rw-r--r--src/libk/include/shared/ring.h23
11 files changed, 292 insertions, 0 deletions
diff --git a/src/libk/include/assert.h b/src/libk/include/assert.h
new file mode 100644
index 0000000..7520aa9
--- /dev/null
+++ b/src/libk/include/assert.h
@@ -0,0 +1,7 @@
+#ifdef NDEBUG
+#define assert(stmt) do {} while (0)
+#else
+#define assert(stmt) do { if (!(stmt)) __badassert(__func__, __FILE__, __LINE__); } while (0)
+#endif
+
+_Noreturn void __badassert(const char *func, const char *file, int line);
diff --git a/src/libk/include/camellia/errno.h b/src/libk/include/camellia/errno.h
new file mode 100644
index 0000000..1177f54
--- /dev/null
+++ b/src/libk/include/camellia/errno.h
@@ -0,0 +1,28 @@
+#pragma once
+/* the comments are directly pasted into user visible strings.
+ * keep them short, don't include " */
+
+#define EGENERIC 1 /* unknown error */
+#define EFAULT 2
+#define EBADF 3 /* bad file descriptor */
+#define EINVAL 4
+#define ENOSYS 5 /* unsupported */
+#define ERANGE 6
+#define ENOMEM 7
+#define ENOENT 8
+#define ENOTEMPTY 9
+#define EACCES 10
+#define EMFILE 11 /* all file descriptors taken */
+#define ECONNRESET 12
+#define EPIPE 13
+#define ECHILD 14
+
+#define EISDIR 200
+#define ENAMETOOLONG 201
+#define ENOTDIR 202
+#define ELOOP 203
+#define ENOEXEC 204
+#define EINTR 205
+#define EWOULDBLOCK 206
+#define EEXIST 207
+#define EAGAIN 208
diff --git a/src/libk/include/camellia/execbuf.h b/src/libk/include/camellia/execbuf.h
new file mode 100644
index 0000000..de7ae3b
--- /dev/null
+++ b/src/libk/include/camellia/execbuf.h
@@ -0,0 +1,9 @@
+#pragma once
+/* the instruction format is bound to change, atm it's extremely inefficient */
+
+#define EXECBUF_MAX_LEN 4096
+
+/* takes 6 arguments */
+#define EXECBUF_SYSCALL 0xF0000001
+/* takes 1 argument, changes %rip */
+#define EXECBUF_JMP 0xF0000002
diff --git a/src/libk/include/camellia/flags.h b/src/libk/include/camellia/flags.h
new file mode 100644
index 0000000..f4c54fe
--- /dev/null
+++ b/src/libk/include/camellia/flags.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#define MEMFLAG_PRESENT 1
+#define MEMFLAG_FINDFREE 2
+
+#define FORK_NOREAP 1
+#define FORK_NEWFS 2
+#define FORK_SHAREMEM 4
+#define FORK_SHAREHANDLE 8
+
+#define WRITE_TRUNCATE 1
+
+#define FSR_DELEGATE 1
+
+#define DUP_SEARCH 1
+
+#define OPEN_READ 1
+#define OPEN_WRITE 2
+#define OPEN_RW 3
+/* not setting OPEN_READ nor OPEN_WRITE works as if OPEN_READ was set, but it also checks the execute bit.
+ * same as in plan9. */
+#define OPEN_EXEC 0
+
+#define OPEN_READABLE(flags) ((flags & 3) != OPEN_WRITE)
+#define OPEN_WRITEABLE(flags) (flags & OPEN_WRITE)
+
+/* Requires OPEN_WRITE to be set, enforced by the kernel.
+ * The idea is that if all flags which allow modifying the filesystem state require
+ * OPEN_WRITE to be set, filesystem handlers could just check for the OPEN_WRITE flag. */
+#define OPEN_CREATE 4
+
+
+/* special handles */
+#define HANDLE_NULLFS -2
+#define HANDLE_PROCFS -3
diff --git a/src/libk/include/camellia/fsutil.h b/src/libk/include/camellia/fsutil.h
new file mode 100644
index 0000000..8b8c4fc
--- /dev/null
+++ b/src/libk/include/camellia/fsutil.h
@@ -0,0 +1,12 @@
+#pragma once
+#include <stdbool.h>
+#include <stddef.h>
+
+/** Normalizes the offset and length passed to a fs into safe values.
+ *
+ * @param expand Can this operation expand the target file?
+ * true if writing to a file with an adjustable size
+ * false if reading any sort of file
+ * or writing to a file with static size
+ */
+void fs_normslice(long *restrict offset, size_t *restrict length, size_t max, bool expand);
diff --git a/src/libk/include/camellia/path.h b/src/libk/include/camellia/path.h
new file mode 100644
index 0000000..b268595
--- /dev/null
+++ b/src/libk/include/camellia/path.h
@@ -0,0 +1,17 @@
+#pragma once
+#include <stddef.h>
+
+#define PATH_MAX 512
+
+/** Reduce a path to its simplest form.
+ * Kinds of invalid paths:
+ * - relative - "" "a" "./a"
+ * - going behind the root directory - "/../"
+ *
+ * @return On success, length of the string in *out, <= len. 0 if the path was invalid.
+ *
+ * returns an unsigned type because:
+ * 1. valid paths always return at least 1, for the initial slash
+ * 2. it makes it easier to assign the result to an unsigned variable and check for error
+ */
+size_t path_simplify(const char *in, char *out, size_t len);
diff --git a/src/libk/include/camellia/syscalls.h b/src/libk/include/camellia/syscalls.h
new file mode 100644
index 0000000..9a8fa94
--- /dev/null
+++ b/src/libk/include/camellia/syscalls.h
@@ -0,0 +1,96 @@
+#pragma once
+
+#define _SYS_EXIT 0
+#define _SYS_AWAIT 1
+#define _SYS_FORK 2
+#define _SYS_OPEN 3
+#define _SYS_MOUNT 4
+#define _SYS_DUP 5
+#define _SYS_READ 6
+#define _SYS_WRITE 7
+#define _SYS_GETSIZE 8
+#define _SYS_REMOVE 9
+#define _SYS_CLOSE 10
+#define _SYS_FS_WAIT 11
+#define _SYS_FS_RESPOND 12
+#define _SYS_MEMFLAG 13
+#define _SYS_PIPE 14
+#define _SYS_SLEEP 15
+#define _SYS_FILICIDE 16
+#define _SYS_INTR 17
+#define _SYS_INTR_SET 18
+#define _SYS_GETPID 19
+#define _SYS_GETPPID 20
+#define _SYS_WAIT2 21
+
+#define _SYS_EXECBUF 100
+#define _SYS_DEBUG_KLOG 101
+
+#ifndef ASM_FILE
+#include <camellia/types.h>
+#include <stddef.h>
+
+long _syscall(long, long, long, long, long, long);
+
+/** Kills the current process.
+ */
+_Noreturn void _sys_exit(long ret);
+
+/** Waits for a child to exit.
+ * @return the value the child passed to exit()
+ */
+long _sys_await(void);
+
+/** Creates a copy of the current process, and executes it.
+ * All user memory pages get copied too.
+ *
+ * @param flags FORK_NOREAP, FORK_NEWFS
+ * @param fs_front requires FORK_NEWFS. the front handle to the new fs is put there
+ *
+ * @return 0 in the child, the CID in the parent.
+ */
+long _sys_fork(int flags, hid_t __user *fs_front);
+
+hid_t _sys_open(const char __user *path, long len, int flags);
+long _sys_mount(hid_t h, const char __user *path, long len);
+hid_t _sys_dup(hid_t from, hid_t to, int flags);
+
+long _sys_read(hid_t h, void __user *buf, size_t len, long offset);
+long _sys_write(hid_t h, const void __user *buf, size_t len, long offset, int flags);
+long _sys_getsize(hid_t h);
+long _sys_remove(hid_t h);
+long _sys_close(hid_t h);
+
+hid_t _sys_fs_wait(char __user *buf, long max_len, struct ufs_request __user *res);
+long _sys_fs_respond(hid_t hid, const void __user *buf, long ret, int flags);
+
+/** Modifies the virtual address space.
+ *
+ * If the MEMFLAG_PRESENT flag is present - mark the memory region as allocated.
+ * Otherwise, free it.
+ *
+ * MEMFLAG_FINDFREE tries to find the first free region of length `len`.
+ *
+ * @return address of the first affected page (usually == addr)
+ */
+void __user *_sys_memflag(void __user *addr, size_t len, int flags);
+long _sys_pipe(hid_t __user user_ends[2], int flags);
+
+void _sys_sleep(long ms);
+
+void _sys_filicide(void);
+void _sys_intr(void);
+void _sys_intr_set(void __user *ip);
+
+uint32_t _sys_getpid(void);
+uint32_t _sys_getppid(void);
+
+// TODO deprecate await
+int _sys_wait2(int pid, int flags, struct sys_wait2 __user *out);
+
+/* see shared/execbuf.h */
+long _sys_execbuf(void __user *buf, size_t len);
+
+void _sys_debug_klog(const void __user *buf, size_t len);
+
+#endif
diff --git a/src/libk/include/camellia/types.h b/src/libk/include/camellia/types.h
new file mode 100644
index 0000000..65200d7
--- /dev/null
+++ b/src/libk/include/camellia/types.h
@@ -0,0 +1,41 @@
+#pragma once
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __CHECKER__
+# define __user __attribute__((noderef, address_space(__user)))
+# define __force __attribute__((force))
+#else
+# define __user
+# define __force
+#endif
+
+typedef void __user * userptr_t;
+typedef int hid_t;
+
+enum vfs_op {
+ VFSOP_OPEN,
+ VFSOP_READ,
+ VFSOP_WRITE,
+ VFSOP_GETSIZE,
+ VFSOP_REMOVE,
+ VFSOP_CLOSE,
+};
+
+struct ufs_request {
+ enum vfs_op op;
+ size_t len; // how much was put in *buf
+ size_t capacity; // how much output can be accepted by the caller
+ void __user *id; // file id (returned by the open handler, passed to other calls)
+ long offset;
+ int flags;
+};
+
+struct intr_data {
+ void __user *ip;
+ void __user *sp; /* last for pop %rsp */
+};
+
+struct sys_wait2 {
+ long status;
+};
diff --git a/src/libk/include/shared/mem.h b/src/libk/include/shared/mem.h
new file mode 100644
index 0000000..3597edf
--- /dev/null
+++ b/src/libk/include/shared/mem.h
@@ -0,0 +1,18 @@
+#pragma once
+#include <stdarg.h>
+#include <stddef.h>
+
+/* note: (partially) tested in the userland tests */
+
+void *memchr(const void *s, int c, size_t n);
+int memcmp(const void *s1, const void *s2, size_t n);
+
+void *memcpy(void *dest, const void *src, size_t n);
+void *memmove(void *dest, const void *src, size_t n);
+void *memset(void *s, int c, size_t n);
+
+int strcmp(const char *s1, const char *s2);
+size_t strlen(const char *s);
+
+int snprintf(char *restrict str, size_t len, const char *restrict fmt, ...);
+int vsnprintf(char *restrict str, size_t len, const char *restrict fmt, va_list ap);
diff --git a/src/libk/include/shared/printf.h b/src/libk/include/shared/printf.h
new file mode 100644
index 0000000..45fd358
--- /dev/null
+++ b/src/libk/include/shared/printf.h
@@ -0,0 +1,6 @@
+#pragma once
+#include <stdarg.h>
+#include <stddef.h>
+
+int __printf_internal(const char *fmt, va_list argp,
+ void (*back)(void*, const char*, size_t), void *back_arg);
diff --git a/src/libk/include/shared/ring.h b/src/libk/include/shared/ring.h
new file mode 100644
index 0000000..dbaf331
--- /dev/null
+++ b/src/libk/include/shared/ring.h
@@ -0,0 +1,23 @@
+#pragma once
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct {
+ char *buf;
+ size_t capacity;
+ size_t _head, _tail;
+} ring_t;
+
+/** Returns amount of bytes stored in the buffer. */
+size_t ring_used(ring_t*);
+/** Returns amount of space left in the buffer. */
+size_t ring_avail(ring_t*);
+
+void ring_put(ring_t*, const void*, size_t);
+void ring_put1b(ring_t*, uint8_t);
+
+size_t ring_get(ring_t*, void*, size_t);
+
+/** Consumes up to `len` bytes, and returns a pointer to the buffer where it's stored.
+ * Not thread-safe. */
+void* ring_contig(ring_t*, size_t *len);