diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | README.md | 3 | ||||
-rwxr-xr-x | make_cdrom.sh | 20 | ||||
-rw-r--r-- | src/apps/init/main.c | 55 | ||||
-rw-r--r-- | src/common/include/proto/proc.h | 7 | ||||
-rw-r--r-- | src/kernel/core/idt.c | 2 | ||||
-rw-r--r-- | src/kernel/fs/iso9660.c | 16 | ||||
-rw-r--r-- | src/kernel/user/process.c | 21 | ||||
-rw-r--r-- | src/lib/libkogata/debug.c | 4 | ||||
-rw-r--r-- | src/lib/libkogata/syscall.c | 2 | ||||
-rw-r--r-- | src/sysbin/giosrv/Makefile | 12 | ||||
-rw-r--r-- | src/sysbin/giosrv/main.c | 28 | ||||
-rw-r--r-- | src/sysbin/init/Makefile (renamed from src/apps/init/Makefile) | 2 | ||||
-rw-r--r-- | src/sysbin/init/main.c | 211 | ||||
-rw-r--r-- | src/sysbin/linker.ld (renamed from src/apps/linker.ld) | 0 | ||||
-rw-r--r-- | src/sysbin/login/Makefile | 12 | ||||
-rw-r--r-- | src/sysbin/login/main.c | 19 |
17 files changed, 336 insertions, 82 deletions
@@ -1,4 +1,6 @@ -DIRS = src/common/libkogata src/common/libc src/common/libalgo src/kernel src/lib/libkogata src/apps/init +DIRS = src/common/libkogata src/common/libc src/common/libalgo \ + src/kernel src/lib/libkogata \ + src/sysbin/init src/sysbin/giosrv src/sysbin/login all: for dir in $(DIRS); do \ @@ -104,7 +104,8 @@ running the tests): src/common/ code shared between kernel and userspace libs src/common/include/proto datastructures & constants used for system calls src/lib/ code for userspace libraries - src/apps/ userspace binaries + src/lib/include/proto definition of IPC protocols used in the system + src/sysbin/ userspace system binaries src/tests/ test suite ## Roadmap diff --git a/make_cdrom.sh b/make_cdrom.sh index d67b3ec..b539273 100755 --- a/make_cdrom.sh +++ b/make_cdrom.sh @@ -8,23 +8,29 @@ fi # Copy system files to CDROM -cp src/kernel/kernel.bin cdrom; strip cdrom/kernel.bin -cp src/apps/init/init.bin cdrom; strip cdrom/init.bin +cp src/kernel/kernel.bin cdrom/boot; strip cdrom/boot/kernel.bin +cp src/sysbin/init/init.bin cdrom/boot; strip cdrom/boot/init.bin + +mkdir -p cdrom/sys/bin +cp src/sysbin/giosrv/giosrv.bin cdrom/sys/bin +cp src/sysbin/login/login.bin cdrom/sys/bin + +for BIN in cdrom/sys/bin/*.bin; do strip $BIN; done cp README.md cdrom # Setup config files +mkdir -p cdrom/config/default + +echo "root:/sys" > cdrom/config/default/sysdir + cat > cdrom/boot/grub/menu.lst <<EOF timeout 10 default 0 title kogata OS -kernel /kernel.bin root=io:/disk/atapi0 root_opts=l init=root:/init.bin - -title kogata OS without root -kernel /kernel.bin init=io:/mod/init.bin -module /init.bin +kernel /boot/kernel.bin root=io:/disk/atapi0 root_opts=l init=root:/boot/init.bin config=default EOF # Generate CDROm image diff --git a/src/apps/init/main.c b/src/apps/init/main.c deleted file mode 100644 index b351615..0000000 --- a/src/apps/init/main.c +++ /dev/null @@ -1,55 +0,0 @@ -#include <string.h> - -#include <malloc.h> - -#include <syscall.h> -#include <debug.h> -#include <user_region.h> - -int main(int argc, char **argv) { - dbg_print("Hello, world! from user process.\n"); - - { - fd_t f = open("io:/", FM_READDIR); - dbg_printf("openned io:/ as %d\n", f); - dirent_t x; - size_t ent_no = 0; - while (readdir(f, ent_no++, &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, "io:/"); - strcpy(buf+4, 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); - dbg_print_region_info(); - 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); - } - - { - fd_t f = open("root:/", FM_READDIR); - dbg_printf("openned root:/ as %d\n", f); - dirent_t x; - size_t ent_no = 0; - while (readdir(f, ent_no++, &x)) { - dbg_printf("- '%s' %p %d\n", x.name, x.st.type, x.st.size); - } - close(f); - } - - return 0; -} - -/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/common/include/proto/proc.h b/src/common/include/proto/proc.h index 29b5b91..fafb2fd 100644 --- a/src/common/include/proto/proc.h +++ b/src/common/include/proto/proc.h @@ -7,9 +7,10 @@ typedef int pid_t; #define PS_LOADING 1 #define PS_RUNNING 2 -#define PS_FINISHED 3 -#define PS_FAILURE 4 // exception or segfault or stuff -#define PS_KILLED 5 +#define PS_EXITING 3 +#define PS_FINISHED 4 +#define PS_FAILURE 5 // exception or segfault or stuff +#define PS_KILLED 6 #define FAIL_EXCEPTION 1 // unhandled processor exception #define FAIL_ZEROPTR 2 // segfault at < 4k diff --git a/src/kernel/core/idt.c b/src/kernel/core/idt.c index eef3ca6..b94695f 100644 --- a/src/kernel/core/idt.c +++ b/src/kernel/core/idt.c @@ -122,7 +122,7 @@ void idt_irq_handler(registers_t *regs) { if (regs->err_code == 0) { irq0_handler(regs, st); } else { - dbg_printf("IRQ%d\n", regs->err_code); + dbg_printf("irq%d.", regs->err_code); if (irq_handlers[regs->err_code] != 0) { irq_handlers[regs->err_code](regs); diff --git a/src/kernel/fs/iso9660.c b/src/kernel/fs/iso9660.c index 4c1bdd2..4de6f2b 100644 --- a/src/kernel/fs/iso9660.c +++ b/src/kernel/fs/iso9660.c @@ -186,8 +186,6 @@ bool iso9660_dir_walk(fs_node_t *n, const char* search_for, struct fs_node *node size_t filename_len = strlen(search_for); - dbg_printf("Looking up %s...\n", search_for); - size_t dr_len = 0; for (size_t pos = 0; pos < node->dr.size.lsb; pos += dr_len) { union { @@ -206,11 +204,13 @@ bool iso9660_dir_walk(fs_node_t *n, const char* search_for, struct fs_node *node if (node->fs->use_lowercase) convert_dr_to_lowercase(dr); char* name = dr->name; - size_t len = dr->name_len - 2; + size_t len = dr->name_len; + if (!(dr->flags & ISO9660_DR_FLAG_DIR)) len -= 2; + + if (!(dr->flags & ISO9660_DR_FLAG_DIR) && name[len] != ';') continue; + if (name[len-1] == '.') len--; // file with no extension - if (name[len] != ';') continue; if (len != filename_len) continue; - if (strncmp(name, search_for, len) == 0) { // Found it ! iso9660_node_t *n = (iso9660_node_t*)malloc(sizeof(iso9660_node_t)); @@ -309,9 +309,11 @@ bool iso9660_dir_readdir(fs_handle_t *h, size_t ent_no, dirent_t *d) { if (node->fs->use_lowercase) convert_dr_to_lowercase(dr); char* name = dr->name; - size_t len = dr->name_len - 2; + size_t len = dr->name_len; + if (!(dr->flags & ISO9660_DR_FLAG_DIR)) len -= 2; - if (name[len] != ';') continue; + if (!(dr->flags & ISO9660_DR_FLAG_DIR) && name[len] != ';') continue; + if (name[len-1] == '.') len--; // file with no extension if (idx == ent_no) { // Found the node we are interested in diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c index 18b4255..63b568a 100644 --- a/src/kernel/user/process.c +++ b/src/kernel/user/process.c @@ -161,13 +161,26 @@ void current_process_exit(int status, int exit_code) { free(d); } + process_t *p = current_process(); + + mutex_lock(&p->lock); + if (p->status == PS_EXITING) { + mutex_unlock(&p->lock); + exit(); + } + + p->status = PS_EXITING; + exit_data_t *d = (exit_data_t*)malloc(sizeof(exit_data_t)); - d->proc = current_process();; + d->proc = p; d->status = status; d->exit_code = exit_code; - worker_push(process_exit_v, d); + while (!worker_push(process_exit_v, d)) yield(); + + mutex_unlock(&p->lock); + exit(); } @@ -184,7 +197,7 @@ void process_exit(process_t *p, int status, int exit_code) { mutex_lock(&p->lock); - ASSERT(p->status == PS_RUNNING || p->status == PS_LOADING); + ASSERT(p->status == PS_RUNNING || p->status == PS_LOADING || p->status == PS_EXITING); p->status = status; p->exit_code = exit_code; @@ -450,6 +463,8 @@ int proc_add_fd(process_t *p, fs_handle_t *f) { } bool proc_add_fd_as(process_t *p, fs_handle_t *f, int fd) { + if (fd <= 0) return false; + if (hashtbl_find(p->files, (void*)fd) != 0) return false; if (fd >= p->next_fd) p->next_fd = fd + 1; diff --git a/src/lib/libkogata/debug.c b/src/lib/libkogata/debug.c index a8b9414..ac3e0e2 100644 --- a/src/lib/libkogata/debug.c +++ b/src/lib/libkogata/debug.c @@ -5,13 +5,13 @@ #include <syscall.h> void panic(const char* msg, const char* file, int line) { - dbg_printf("Panic '%s', at %s:%d\n", msg, file, line); + dbg_printf("PANIC in user process\n %s\n at %s:%d\n", msg, file, line); exit(-1); while(true); } void panic_assert(const char* assert, const char* file, int line) { - dbg_printf("Assert failed '%s', at %s:%d\n", assert, file, line); + dbg_printf("ASSERT FAILED in user process\n %s\n at %s:%d\n", assert, file, line); exit(-1); while(true); } diff --git a/src/lib/libkogata/syscall.c b/src/lib/libkogata/syscall.c index 67f95fd..bf0b35e 100644 --- a/src/lib/libkogata/syscall.c +++ b/src/lib/libkogata/syscall.c @@ -182,7 +182,7 @@ bool bind_make_fs(pid_t pid, const char* name, const char* driver, fd_t source, return call(SC_BIND_MAKE_FS, (uint32_t)&args, 0, 0, 0, 0); } bool bind_fd(pid_t pid, fd_t new_fd, fd_t fd) { - return call(SC_BIND_FD, new_fd, fd, 0, 0, 0); + return call(SC_BIND_FD, pid, new_fd, fd, 0, 0); } bool proc_exec(pid_t pid, const char* file) { return call(SC_PROC_EXEC, pid, (uint32_t)file, strlen(file), 0, 0); diff --git a/src/sysbin/giosrv/Makefile b/src/sysbin/giosrv/Makefile new file mode 100644 index 0000000..102bf4c --- /dev/null +++ b/src/sysbin/giosrv/Makefile @@ -0,0 +1,12 @@ + +OBJ = main.o + +LIB = ../../lib/libkogata/libkogata.lib ../../common/libc/libc.lib + +CFLAGS = -I ./include -I ../../common/include -I ../../lib/include + +LDFLAGS = -T ../linker.ld -Xlinker -Map=giosrv.map + +OUT = giosrv.bin + +include ../../rules.make diff --git a/src/sysbin/giosrv/main.c b/src/sysbin/giosrv/main.c new file mode 100644 index 0000000..ab30664 --- /dev/null +++ b/src/sysbin/giosrv/main.c @@ -0,0 +1,28 @@ +#include <string.h> + +#include <malloc.h> + +#include <syscall.h> +#include <debug.h> +#include <user_region.h> + +#include <proto/fb.h> + +int main(int argc, char **argv) { + dbg_print("[giosrv] Starting up.\n"); + + fd_t fbdev = open("io:/display/vesa", FM_READ | FM_WRITE | FM_MMAP); + if (fbdev == 0) PANIC("Could not open fbdev"); + + framebuffer_info_t i; + int r = ioctl(fbdev, IOCTL_FB_GET_INFO, &i); + dbg_printf("[giosrv] ioctl -> %d\n", r); + ASSERT(r == 1); + dbg_printf("[giosrv] Running on FB %dx%d\n", i.width, i.height); + + while(true); // nothing to do + + return 0; +} + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/apps/init/Makefile b/src/sysbin/init/Makefile index c54bbfb..53a1f45 100644 --- a/src/apps/init/Makefile +++ b/src/sysbin/init/Makefile @@ -1,7 +1,7 @@ OBJ = main.o -LIB = ../../lib/libkogata/libkogata.lib ../../common/libc/libc.lib +LIB = ../../lib/libkogata/libkogata.lib ../../common/libc/libc.lib ../../common/libalgo/libalgo.lib CFLAGS = -I ./include -I ../../common/include -I ../../lib/include diff --git a/src/sysbin/init/main.c b/src/sysbin/init/main.c new file mode 100644 index 0000000..a2c607d --- /dev/null +++ b/src/sysbin/init/main.c @@ -0,0 +1,211 @@ +#include <string.h> +#include <printf.h> + +#include <malloc.h> + +#include <syscall.h> +#include <debug.h> +#include <user_region.h> + +#include <btree.h> + +pid_t giosrv_pid = 0, login_pid = 0; +fd_pair_t root_gip_chan; + +btree_t *parse_cmdline(const char* x) { + btree_t *ret = create_btree(str_key_cmp_fun, free_key_val); + ASSERT(ret != 0); + + x = strchr(x, ' '); + if (x == 0) return ret; + + while ((*x) != 0) { + while (*x == ' ') x++; + + char* eq = strchr(x, '='); + char* sep = strchr(x, ' '); + if (sep == 0) { + if (eq == 0) { + btree_add(ret, strdup(x), strdup(x)); + } else { + btree_add(ret, strndup(x, eq - x), strdup(eq + 1)); + } + break; + } else { + if (eq == 0 || eq > sep) { + btree_add(ret, strndup(x, sep - x), strndup(x, sep - x)); + } else { + btree_add(ret, strndup(x, eq - x), strndup(eq + 1, sep - eq - 1)); + } + x = sep + 1; + } + } + + void iter(void* a, void* b) { + dbg_printf(" '%s' -> '%s'\n", a, b); + } + btree_iter(ret, iter); + + return ret; +} + +btree_t* read_cmdline() { + char cmdline_buf[256]; + + fd_t f = open("io:/cmdline", FM_READ); + if (f == 0) return 0; + + size_t len = read(f, 0, 255, cmdline_buf); + cmdline_buf[len] = 0; + + close(f); + + return parse_cmdline(cmdline_buf); +} + +void setup_sys() { + fd_t sysdir_cfg = open("config:/sysdir", FM_READ); + if (sysdir_cfg == 0) PANIC("[init] Could not read config:/sysdir"); + + char buf[256]; + size_t l = read(sysdir_cfg, 0, 255, buf); + buf[l] = 0; + close(sysdir_cfg); + + char* eol = strchr(buf, '\n'); + if (eol) *eol = 0; + + dbg_printf("[init] Using system directory %s\n", buf); + bool ok; + + char* sep = strchr(buf, ':'); + if (sep == 0) { + ok = fs_subfs("sys", "root", buf, FM_READ | FM_MMAP); + } else { + *sep = 0; + ok = fs_subfs("sys", buf, sep +1, FM_READ | FM_MMAP); + } + + if (!ok) PANIC("[init] Could not bind root:/sys to sys:/"); +} + +void launch_giosrv() { + if (giosrv_pid != 0) return; + + giosrv_pid = new_proc(); + if (giosrv_pid == 0) { + PANIC("[init] Could not create process for giosrv"); + } + + dbg_printf("[init] Setting up giosrv, pid: %d\n", giosrv_pid); + + bool ok; + + ok = bind_fs(giosrv_pid, "io", "io"); + if (!ok) PANIC("[init] Could not bind io:/ to giosrv"); + + ok = bind_fs(giosrv_pid, "sys", "sys"); + if (!ok) PANIC("[init] Could not bind sys:/ to giosrv"); + + ok = bind_fs(giosrv_pid, "config", "config"); + if (!ok) PANIC("[init] Could not bind config:/ to giosrv"); + + ok = bind_fd(giosrv_pid, 1, root_gip_chan.a); + if (!ok) PANIC("[init] Could not bind root GIP channel FD to giosrv"); + + ok = proc_exec(giosrv_pid, "sys:/bin/giosrv.bin"); + if (!ok) PANIC("[init] Could not run giosrv.bin"); + + dbg_printf("[init] giosrv started.\n"); +} + +void launch_login() { + if (login_pid != 0) return; + + login_pid = new_proc(); + if (login_pid == 0) { + PANIC("[init] Could not create process for login"); + } + + dbg_printf("[init] Setting up login, pid: %d\n", login_pid); + + bool ok; + + ok = bind_fs(login_pid, "root", "root"); + if (!ok) PANIC("[init] Could not bind root:/ to login"); + + ok = bind_fs(login_pid, "sys", "sys"); + if (!ok) PANIC("[init] Could not bind sys:/ to login"); + + ok = bind_fs(login_pid, "config", "config"); + if (!ok) PANIC("[init] Could not bind config:/ to login"); + + ok = bind_fd(login_pid, 1, root_gip_chan.a); + if (!ok) PANIC("[init] Could not bind root GIP channel FD to login"); + + ok = proc_exec(login_pid, "sys:/bin/login.bin"); + if (!ok) PANIC("[init] Could not run login.bin"); + + dbg_printf("[init] login started.\n"); +} + +int main(int argc, char **argv) { + dbg_print("[init] Starting up!\n"); + + // Read kernel cmdline + btree_t *cmdline = read_cmdline(); + if (cmdline == 0) PANIC("[init] Could not parse cmdline"); + + // Later : setup config: and read config file + if (btree_find(cmdline, "config") == 0) { + PANIC("[init] No config=xxx option specified on command line"); + } else { + char* config = (char*)btree_find(cmdline, "config"); + dbg_printf("[init] Loading system configuration: %s\n", config); + ASSERT(strlen(config) < 30); + + char buf[50]; + snprintf(buf, 50, "/config/%s", config); + bool ok = fs_subfs("config", "root", buf, FM_READ | FM_WRITE | FM_MMAP); + if (!ok) PANIC("[init] Could not setup config:"); + } + + // Setup sys: partition + setup_sys(); + + // Setup GIP channel for communication between giosrv and login + root_gip_chan = make_channel(false); + if (root_gip_chan.a == 0 || root_gip_chan.b == 0) { + PANIC("[init] Could not create root GIP channel."); + } + + // Launch giosrv && login + launch_giosrv(); + launch_login(); + + // Make sure no one dies + while(true) { + proc_status_t s; + proc_wait(0, false, &s); + if (s.pid != 0) { + if (s.pid == giosrv_pid) { + giosrv_pid = 0; + + dbg_printf("[init] giosrv died, restarting.\n"); + launch_giosrv(); + } else if (s.pid == login_pid) { + login_pid = 0; + + dbg_printf("[init] login died, restarting.\n"); + launch_login(); + } else { + ASSERT(false); + } + } + usleep(1000000); + } + + return 0; +} + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/apps/linker.ld b/src/sysbin/linker.ld index 50bebbe..50bebbe 100644 --- a/src/apps/linker.ld +++ b/src/sysbin/linker.ld diff --git a/src/sysbin/login/Makefile b/src/sysbin/login/Makefile new file mode 100644 index 0000000..01be4e1 --- /dev/null +++ b/src/sysbin/login/Makefile @@ -0,0 +1,12 @@ + +OBJ = main.o + +LIB = ../../lib/libkogata/libkogata.lib ../../common/libc/libc.lib + +CFLAGS = -I ./include -I ../../common/include -I ../../lib/include + +LDFLAGS = -T ../linker.ld -Xlinker -Map=login.map + +OUT = login.bin + +include ../../rules.make diff --git a/src/sysbin/login/main.c b/src/sysbin/login/main.c new file mode 100644 index 0000000..f92b18c --- /dev/null +++ b/src/sysbin/login/main.c @@ -0,0 +1,19 @@ +#include <string.h> + +#include <malloc.h> + +#include <syscall.h> +#include <debug.h> +#include <user_region.h> + +int main(int argc, char **argv) { + dbg_print("[login] Starting up.\n"); + + usleep(10000000); // pretend we are doing something + + // and now pretend we have exited due to some kind of failure + + return 0; +} + +/* vim: set ts=4 sw=4 tw=0 noet :*/ |