aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md13
-rw-r--r--src/apps/init/main.c25
-rw-r--r--src/common/include/syscallproto.h44
-rw-r--r--src/common/libc/string.c2
-rw-r--r--src/kernel/include/process.h8
-rw-r--r--src/kernel/user/process.c32
-rw-r--r--src/kernel/user/syscall.c220
-rw-r--r--src/lib/include/syscall.h17
-rw-r--r--src/lib/libkogata/syscall.c43
9 files changed, 371 insertions, 33 deletions
diff --git a/README.md b/README.md
index 81ca3e4..589c0f9 100644
--- a/README.md
+++ b/README.md
@@ -30,12 +30,6 @@ I would love to have kogata fit on a 1.44MB floppy and run with a full GUI and
some cool apps (remember the QNX demo floppy!). Also, I want to be able to use
it on older computers and prove that such machines can still be put to use.
-### Plans for the future
-
-* Module system for extending the kernel
-* In userspace, simple Scheme-like scripting language
-* The obvious stuff ;-)
-
## How to build
### Requirements
@@ -104,11 +98,18 @@ running the tests):
* Have several threads in a single process
* Better handling of errors (rather than panicing) ; userspace apps should not
have the possibility of crashing the system
+* How does a process transmit information (such as environment or arguments) to its children ?
### Things not sure
* VFS thread safety : is the design correct ? (probably)
+### Plans for the later future
+
+* Module system for extending the kernel
+* In userspace, simple Scheme-like scripting language
+* The obvious stuff ;-)
+
## Licence
None of the source files have a licence header because it's cumbersome. All the
diff --git a/src/apps/init/main.c b/src/apps/init/main.c
index 25f08e8..02fd9df 100644
--- a/src/apps/init/main.c
+++ b/src/apps/init/main.c
@@ -32,6 +32,31 @@ int main(int argc, char **argv) {
dbg_printf("malloc test OK.\n");
dbg_print_region_info();
+ fd_t f = open("dev:/", FM_READDIR);
+ dbg_printf("openned /: %d\n", f);
+ dirent_t x;
+ while (readdir(f, &x)) {
+ dbg_printf("- '%s' %p %d\n", x.name, x.st.type, x.st.size);
+ if (x.st.type == FT_REGULAR) {
+ char buf[256];
+ strcpy(buf, "dev:/");
+ strcpy(buf+5, x.name);
+ dbg_printf("trying to open %s...\n", buf);
+ fd_t ff = open(buf, FM_READ);
+ if (ff != 0) {
+ dbg_printf("ok, open as %d\n", ff);
+ char* cont = malloc(x.st.size + 1);
+ read(ff, 0, x.st.size, cont);
+ cont[x.st.size] = 0;
+ dbg_printf(" %s\n", cont);
+ close(ff);
+ } else {
+ dbg_printf("Could not open '%s'\n", buf);
+ }
+ }
+ }
+ close(f);
+
return 0;
}
diff --git a/src/common/include/syscallproto.h b/src/common/include/syscallproto.h
index bfcd37a..8c86762 100644
--- a/src/common/include/syscallproto.h
+++ b/src/common/include/syscallproto.h
@@ -3,28 +3,28 @@
#define SC_MAX 128 // maximum number of syscalls
-#define SC_DBG_PRINT 0
-#define SC_EXIT 1
-#define SC_YIELD 2
-
-#define SC_MMAP 10
-#define SC_MMAP_FILE 11
-#define SC_MCHMAP 12
-#define SC_MUNMAP 13
-
-#define SC_CREATE 20
-#define SC_DELETE 21
-#define SC_MOVE 22
-#define SC_STAT 23
-#define SC_IOCTL 24
-
-#define SC_OPEN 30
-#define SC_CLOSE 31
-#define SC_READ 32
-#define SC_WRITE 33
-#define SC_READDIR 34
-#define SC_STAT_OPEN 35 // stat on open file handle
-#define SC_GET_MODE 36 // get mode for open file handle
+#define SC_DBG_PRINT 0 // args: msg, msg_strlen
+#define SC_EXIT 1 // args: code
+#define SC_YIELD 2 // args: ()
+
+#define SC_MMAP 10 // args: addr, size, mode
+#define SC_MMAP_FILE 11 // args: handle, offset, addr, size, mode
+#define SC_MCHMAP 12 // args: addr, new_mode
+#define SC_MUNMAP 13 // args: addr
+
+#define SC_CREATE 20 // args: file, file_strlen, type
+#define SC_DELETE 21 // args: file, file_strlen
+#define SC_MOVE 22 // args: old_file, old_file_strlen, new_file, new_file_strlen
+#define SC_STAT 23 // args: file, file_strlen, out stat_t* data
+#define SC_IOCTL 24 // args: file, file_strlen, code, out void* data
+
+#define SC_OPEN 30 // args: file, file_strlen, mode
+#define SC_CLOSE 31 // args: fd
+#define SC_READ 32 // args: fd, offset, size, out char* data
+#define SC_WRITE 33 // args: fd, offset, size, data
+#define SC_READDIR 34 // args: fd, out dirent_t *data
+#define SC_STAT_OPEN 35 // args: fd, out stat_t *data -- stat on open file handle
+#define SC_GET_MODE 36 // args: fd -- get mode for open file handle
#define SC_MAKE_FS 40
#define SC_FS_ADD_SRC 41
diff --git a/src/common/libc/string.c b/src/common/libc/string.c
index 7aa155d..dfc93e6 100644
--- a/src/common/libc/string.c
+++ b/src/common/libc/string.c
@@ -30,7 +30,7 @@ char *strcpy(char *dest, const char *src) {
}
char *strncpy(char *dest, const char *src, size_t n) {
- size_t x = strlen(src + 1);
+ size_t x = strlen(src);
if (n < x) x = n;
memcpy(dest, src, x);
if (n > x) memset(dest + x, 0, n - x);
diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h
index 5d9c3bf..07cc14e 100644
--- a/src/kernel/include/process.h
+++ b/src/kernel/include/process.h
@@ -18,7 +18,6 @@
#include <mmap.h>
-
#define USERSTACK_ADDR 0xB8000000
#define USERSTACK_SIZE 0x00020000 // 32 KB
@@ -29,6 +28,8 @@ typedef struct process {
btree_t *regions_idx;
hashtbl_t *filesystems;
+ hashtbl_t *files;
+ int next_fd;
thread_t *thread;
@@ -47,7 +48,10 @@ bool start_process(process_t *p, proc_entry_t entry); // maps a region for user
bool proc_add_fs(process_t *p, fs_t *fs, const char* name);
fs_t *proc_find_fs(process_t *p, const char* name);
-bool proc_rm_fs(process_t *p, const char* name);
+void proc_rm_fs(process_t *p, const char* name);
+int proc_add_fd(process_t *p, fs_handle_t *f); // on error returns 0, nonzero other<ise
+fs_handle_t *proc_read_fd(process_t *p, int fd);
+void proc_close_fd(process_t *p, int fd);
bool mmap(process_t *proc, void* addr, size_t size, int mode); // create empty zone
bool mmap_file(process_t *proc, fs_handle_t *h, size_t offset, void* addr, size_t size, int mode);
diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c
index 6cba0f7..3ee78a7 100644
--- a/src/kernel/user/process.c
+++ b/src/kernel/user/process.c
@@ -38,6 +38,9 @@ process_t *new_process(process_t *parent) {
proc->filesystems = create_hashtbl(str_key_eq_fun, str_hash_fun, free_key);
if (proc->filesystems == 0) goto error;
+ proc->files = create_hashtbl(id_key_eq_fun, id_hash_fun, 0);
+ if (proc->files == 0) goto error;
+
proc->regions_idx = create_btree(id_key_cmp_fun, 0);
if (proc->regions_idx == 0) goto error;
@@ -48,12 +51,14 @@ process_t *new_process(process_t *parent) {
proc->thread = 0;
proc->pid = (next_pid++);
proc->parent = parent;
+ proc->next_fd = 1;
return proc;
error:
if (proc && proc->regions_idx) delete_btree(proc->regions_idx);
if (proc && proc->filesystems) delete_hashtbl(proc->filesystems);
+ if (proc && proc->files) delete_hashtbl(proc->files);
if (proc) free(proc);
return 0;
}
@@ -123,7 +128,32 @@ bool proc_add_fs(process_t *p, fs_t *fs, const char* name) {
}
fs_t *proc_find_fs(process_t *p, const char* name) {
- return hashtbl_find(p->filesystems, name);
+ return (fs_t*)hashtbl_find(p->filesystems, name);
+}
+
+void proc_remove_fs(process_t *p, const char* name) {
+ hashtbl_remove(p->filesystems, name);
+}
+
+int proc_add_fd(process_t *p, fs_handle_t *f) {
+ int fd = p->next_fd++;
+
+ bool add_ok = hashtbl_add(p->files, (void*)fd, f);
+ if (!add_ok) return 0;
+
+ return fd;
+}
+
+fs_handle_t *proc_read_fd(process_t *p, int fd) {
+ return (fs_handle_t*)hashtbl_find(p->files, (void*)fd);
+}
+
+void proc_close_fd(process_t *p, int fd) {
+ fs_handle_t *x = proc_read_fd(p, fd);
+ if (x != 0) {
+ unref_file(x);
+ hashtbl_remove(p->files, (void*)fd);
+ }
}
// ============================= //
diff --git a/src/kernel/user/syscall.c b/src/kernel/user/syscall.c
index ca5a65c..eee65d6 100644
--- a/src/kernel/user/syscall.c
+++ b/src/kernel/user/syscall.c
@@ -57,6 +57,14 @@ static uint32_t mmap_sc(sc_args_t args) {
return mmap(current_process(), (void*)args.a, args.b, args.c);
}
+static uint32_t mmap_file_sc(sc_args_t args) {
+ int fd = args.a;
+ fs_handle_t *h = proc_read_fd(current_process(), fd);
+ if (h == 0) return false;
+
+ return mmap_file(current_process(), h, args.b, (void*)args.c, args.d, args.e);
+}
+
static uint32_t mchmap_sc(sc_args_t args) {
return mchmap(current_process(), (void*)args.a, args.b);
}
@@ -65,6 +73,203 @@ static uint32_t munmap_sc(sc_args_t args) {
return munmap(current_process(), (void*)args.a);
}
+static uint32_t create_sc(sc_args_t args) {
+ bool ret = false;
+
+ char* fn = sc_copy_string(args.a, args.b);
+ if (fn == 0) goto end_create;
+
+ char* sep = strchr(fn, ':');
+ if (sep == 0) goto end_create;
+
+ *sep = 0;
+ char* file = sep + 1;
+
+ fs_t *fs = proc_find_fs(current_process(), fn);
+ if (fs == 0) goto end_create;
+
+ ret = fs_create(fs, file, args.c);
+
+end_create:
+ if (fn) free(fn);
+ return ret;
+}
+
+static uint32_t delete_sc(sc_args_t args) {
+ bool ret = false;
+
+ char* fn = sc_copy_string(args.a, args.b);
+ if (fn == 0) goto end_del;
+
+ char* sep = strchr(fn, ':');
+ if (sep == 0) goto end_del;
+
+ *sep = 0;
+ char* file = sep + 1;
+
+ fs_t *fs = proc_find_fs(current_process(), fn);
+ if (fs == 0) goto end_del;
+
+ ret = fs_delete(fs, file);
+
+end_del:
+ if (fn) free(fn);
+ return ret;
+}
+
+static uint32_t move_sc(sc_args_t args) {
+ bool ret = false;
+
+ char *fn_a = sc_copy_string(args.a, args.b),
+ *fn_b = sc_copy_string(args.c, args.d);
+ if (fn_a == 0 || fn_b == 0) goto end_move;
+
+ char* sep_a = strchr(fn_a, ':');
+ if (sep_a == 0) goto end_move;
+ *sep_a = 0;
+
+ char* sep_b = strchr(fn_b, ':');
+ if (sep_b == 0) goto end_move;
+ *sep_b = 0;
+
+ if (strcmp(fn_a, fn_b) != 0) goto end_move; // can only move within same FS
+
+ char *file_a = sep_a + 1, *file_b = sep_b + 1;
+
+ fs_t *fs = proc_find_fs(current_process(), fn_a);
+ if (fs == 0) goto end_move;
+
+ ret = fs_move(fs, file_a, file_b);
+
+end_move:
+ if (fn_a) free(fn_a);
+ if (fn_b) free(fn_b);
+ return ret;
+}
+
+static uint32_t stat_sc(sc_args_t args) {
+ bool ret = false;
+
+ char* fn = sc_copy_string(args.a, args.b);
+ if (fn == 0) goto end_stat;
+
+ char* sep = strchr(fn, ':');
+ if (sep == 0) goto end_stat;
+
+ *sep = 0;
+ char* file = sep + 1;
+
+ fs_t *fs = proc_find_fs(current_process(), fn);
+ if (fs == 0) goto end_stat;
+
+ probe_for_write((stat_t*)args.c, sizeof(stat_t));
+ ret = fs_stat(fs, file, (stat_t*)args.c);
+
+end_stat:
+ if (fn) free(fn);
+ return ret;
+}
+
+static uint32_t ioctl_sc(sc_args_t args) {
+ int ret = -1;
+
+ char* fn = sc_copy_string(args.a, args.b);
+ if (fn == 0) goto end_ioctl;
+
+ char* sep = strchr(fn, ':');
+ if (sep == 0) goto end_ioctl;
+
+ *sep = 0;
+ char* file = sep + 1;
+
+ fs_t *fs = proc_find_fs(current_process(), fn);
+ if (fs == 0) goto end_ioctl;
+
+ void* data = (void*)args.d;
+ if (data >= (void*)K_HIGHHALF_ADDR) goto end_ioctl;
+ ret = fs_ioctl(fs, file, args.c, data);
+
+end_ioctl:
+ if (fn) free(fn);
+ return ret;
+}
+
+static uint32_t open_sc(sc_args_t args) {
+ int ret = 0;
+
+ char* fn = sc_copy_string(args.a, args.b);
+ if (fn == 0) goto end_open;
+
+ char* sep = strchr(fn, ':');
+ if (sep == 0) goto end_open;
+
+ *sep = 0;
+ char* file = sep + 1;
+
+ fs_t *fs = proc_find_fs(current_process(), fn);
+ if (fs == 0) goto end_open;
+
+ fs_handle_t *h = fs_open(fs, file, args.c);
+ if (h == 0) goto end_open;
+
+ ret = proc_add_fd(current_process(), h);
+ if (ret == 0) unref_file(h);
+
+end_open:
+ if (fn) free(fn);
+ return ret;
+}
+
+static uint32_t close_sc(sc_args_t args) {
+ proc_close_fd(current_process(), args.a);
+ return 0;
+}
+
+static uint32_t read_sc(sc_args_t args) {
+ fs_handle_t *h = proc_read_fd(current_process(), args.a);
+ if (h == 0) return 0;
+
+ char* data = (char*)args.d;
+ size_t len = args.c;
+ probe_for_write(data, len);
+ return file_read(h, args.b, len, data);
+}
+
+static uint32_t write_sc(sc_args_t args) {
+ fs_handle_t *h = proc_read_fd(current_process(), args.a);
+ if (h == 0) return 0;
+
+ char* data = (char*)args.d;
+ size_t len = args.c;
+ probe_for_read(data, len);
+ return file_write(h, args.b, len, data);
+}
+
+static uint32_t readdir_sc(sc_args_t args) {
+ fs_handle_t *h = proc_read_fd(current_process(), args.a);
+ if (h == 0) return false;
+
+ dirent_t *o = (dirent_t*)args.b;
+ probe_for_write(o, sizeof(dirent_t));
+ return file_readdir(h, o);
+}
+
+static uint32_t stat_open_sc(sc_args_t args) {
+ fs_handle_t *h = proc_read_fd(current_process(), args.a);
+ if (h == 0) return false;
+
+ stat_t *o = (stat_t*)args.b;
+ probe_for_write(o, sizeof(stat_t));
+ return file_stat(h, o);
+}
+
+static uint32_t get_mode_sc(sc_args_t args) {
+ fs_handle_t *h = proc_read_fd(current_process(), args.a);
+ if (h == 0) return 0;
+
+ return file_get_mode(h);
+}
+
// ====================== //
// SYSCALLS SETUP ROUTINE //
// ====================== //
@@ -75,8 +280,23 @@ void setup_syscalls() {
sc_handlers[SC_DBG_PRINT] = dbg_print_sc;
sc_handlers[SC_MMAP] = mmap_sc;
+ sc_handlers[SC_MMAP_FILE] = mmap_file_sc;
sc_handlers[SC_MCHMAP] = mchmap_sc;
sc_handlers[SC_MUNMAP] = munmap_sc;
+
+ sc_handlers[SC_CREATE] = create_sc;
+ sc_handlers[SC_DELETE] = delete_sc;
+ sc_handlers[SC_MOVE] = move_sc;
+ sc_handlers[SC_STAT] = stat_sc;
+ sc_handlers[SC_IOCTL] = ioctl_sc;
+
+ sc_handlers[SC_OPEN] = open_sc;
+ sc_handlers[SC_CLOSE] = close_sc;
+ sc_handlers[SC_READ] = read_sc;
+ sc_handlers[SC_WRITE] = write_sc;
+ sc_handlers[SC_READDIR] = readdir_sc;
+ sc_handlers[SC_STAT_OPEN] = stat_open_sc;
+ sc_handlers[SC_GET_MODE] = get_mode_sc;
}
void syscall_handler(registers_t *regs) {
diff --git a/src/lib/include/syscall.h b/src/lib/include/syscall.h
index e0f08eb..3d9fcd5 100644
--- a/src/lib/include/syscall.h
+++ b/src/lib/include/syscall.h
@@ -10,14 +10,31 @@
#include <fs.h>
#include <debug.h>
+typedef int fd_t;
+
void dbg_print(const char* str);
void yield();
void exit(int code);
bool mmap(void* addr, size_t size, int mode);
+bool mmap_file(fd_t file, size_t offset, void* addr, size_t size, int mode);
bool mchmap(void* addr, int mode);
bool munmap(void* addr);
+bool create(const char* name, int type);
+bool delete(const char* name);
+bool move(const char* oldname, const char* newname);
+bool stat(const char* name, stat_t *s);
+int ioctl(const char* filename, int command, void* data);
+
+fd_t open(const char* name, int mode);
+void close(fd_t file);
+size_t read(fd_t file, size_t offset, size_t len, char *buf);
+size_t write(fd_t file, size_t offset, size_t len, const char* buf);
+bool readdir(fd_t file, dirent_t *d);
+bool stat_open(fd_t file, stat_t *s);
+int get_mode(fd_t file);
+
// more todo
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/lib/libkogata/syscall.c b/src/lib/libkogata/syscall.c
index 8d24628..008a2a9 100644
--- a/src/lib/libkogata/syscall.c
+++ b/src/lib/libkogata/syscall.c
@@ -4,7 +4,7 @@
#include <string.h>
#include <printf.h>
-static uint32_t call(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t ss, uint32_t dd) {
+static inline uint32_t call(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t ss, uint32_t dd) {
uint32_t ret;
asm volatile("int $0x40"
:"=a"(ret)
@@ -38,6 +38,9 @@ void exit(int code) {
bool mmap(void* addr, size_t size, int mode) {
return call(SC_MMAP, (uint32_t)addr, size, mode, 0, 0);
}
+bool mmap_file(fd_t file, size_t offset, void* addr, size_t size, int mode) {
+ return call(SC_MMAP_FILE, file, offset, (uint32_t)addr, size, mode);
+}
bool mchmap(void* addr, int mode) {
return call(SC_MCHMAP, (uint32_t)addr, mode, 0, 0, 0);
}
@@ -45,4 +48,42 @@ bool munmap(void* addr) {
return call(SC_MUNMAP, (uint32_t)addr, 0, 0, 0, 0);
}
+bool create(const char* name, int type) {
+ return call(SC_CREATE, (uint32_t)name, strlen(name), type, 0, 0);
+}
+bool delete(const char* name) {
+ return call(SC_CREATE, (uint32_t)name, strlen(name), 0, 0, 0);
+}
+bool move(const char* oldname, const char* newname) {
+ return call(SC_MOVE, (uint32_t)oldname, strlen(oldname), (uint32_t)newname, strlen(newname), 0);
+}
+bool stat(const char* name, stat_t *s) {
+ return call(SC_STAT, (uint32_t)name, strlen(name), (uint32_t)s, 0, 0);
+}
+int ioctl(const char* filename, int command, void* data) {
+ return call(SC_IOCTL, (uint32_t)filename, strlen(filename), command, (uint32_t)data, 0);
+}
+
+fd_t open(const char* name, int mode) {
+ return call(SC_OPEN, (uint32_t)name, strlen(name), mode, 0, 0);
+}
+void close(fd_t file) {
+ call(SC_CLOSE, file, 0, 0, 0, 0);
+}
+size_t read(fd_t file, size_t offset, size_t len, char *buf) {
+ return call(SC_READ, file, offset, len, (uint32_t)buf, 0);
+}
+size_t write(fd_t file, size_t offset, size_t len, const char* buf) {
+ return call(SC_WRITE, file, offset, len, (uint32_t)buf, 0);
+}
+bool readdir(fd_t file, dirent_t *d) {
+ return call(SC_READDIR, file, (uint32_t)d, 0, 0, 0);
+}
+bool stat_open(fd_t file, stat_t *s) {
+ return call(SC_STAT_OPEN, file, (uint32_t)s, 0, 0, 0);
+}
+int get_mode(fd_t file) {
+ return call(SC_GET_MODE, file, 0, 0, 0, 0);
+}
+
/* vim: set ts=4 sw=4 tw=0 noet :*/