diff options
author | Freya Murphy <freya@freyacat.org> | 2025-04-30 21:07:46 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2025-05-01 15:51:32 -0400 |
commit | 1a10a3725e7bea67e558715f6e9f78abcb415b3a (patch) | |
tree | 1f35cf35f61cd58a86f2a8e7ea14c565db20a211 /kernel | |
parent | tarfs (diff) | |
download | comus-1a10a3725e7bea67e558715f6e9f78abcb415b3a.tar.gz comus-1a10a3725e7bea67e558715f6e9f78abcb415b3a.tar.bz2 comus-1a10a3725e7bea67e558715f6e9f78abcb415b3a.zip |
finish syscall impls
Diffstat (limited to '')
-rw-r--r-- | kernel/fs/tar.c | 15 | ||||
-rw-r--r-- | kernel/include/comus/fs.h | 11 | ||||
-rw-r--r-- | kernel/include/comus/limits.h | 4 | ||||
-rw-r--r-- | kernel/include/comus/procs.h | 4 | ||||
-rw-r--r-- | kernel/include/comus/syscalls.h | 3 | ||||
-rw-r--r-- | kernel/include/comus/user.h | 4 | ||||
-rw-r--r-- | kernel/main.c | 5 | ||||
-rw-r--r-- | kernel/procs.c | 3 | ||||
-rw-r--r-- | kernel/syscall.c | 181 | ||||
-rw-r--r-- | kernel/user.c | 59 |
10 files changed, 267 insertions, 22 deletions
diff --git a/kernel/fs/tar.c b/kernel/fs/tar.c index 7f34107..86af81f 100644 --- a/kernel/fs/tar.c +++ b/kernel/fs/tar.c @@ -150,15 +150,15 @@ int tar_seek(struct file *in, long int off, int whence) switch (whence) { case SEEK_SET: file->offset = off; - return 0; + return file->offset; case SEEK_CUR: file->offset += off; - return 0; + return file->offset; case SEEK_END: file->offset = file->len + off; - return 0; + return file->offset; default: - return 1; + return -1; } } @@ -202,12 +202,17 @@ void tar_close(struct file *file) kfree(file); } -int tar_open(struct file_system *fs, const char *path, struct file **out) +int tar_open(struct file_system *fs, const char *path, int flags, + struct file **out) { struct tar_file *file; struct tar_hdr hdr; size_t sect; + // cannot create or write files + if (flags != O_RDONLY) + return 1; + if (tar_locate(fs, path, &hdr, §, NULL, false)) return 1; diff --git a/kernel/include/comus/fs.h b/kernel/include/comus/fs.h index 2f678b6..044330b 100644 --- a/kernel/include/comus/fs.h +++ b/kernel/include/comus/fs.h @@ -148,6 +148,15 @@ struct file { void (*close)(struct file *file); }; +/// open flags +enum { + O_CREATE = 0x01, + O_RDONLY = 0x02, + O_WRONLY = 0x04, + O_APPEND = 0x08, + O_RDWR = 0x10, +}; + /// file system vtable, used for opening /// and stating files. filesystem mount functions must /// set fs_name, fs_disk, open, and stat. @@ -200,7 +209,7 @@ struct file_system { /// filesystem name const char *fs_name; /// opens a file - int (*open)(struct file_system *fs, const char *fullpath, + int (*open)(struct file_system *fs, const char *fullpath, int flags, struct file **out); /// stats a file int (*stat)(struct file_system *fs, const char *fullpath, diff --git a/kernel/include/comus/limits.h b/kernel/include/comus/limits.h index 4cb348d..1ef13b4 100644 --- a/kernel/include/comus/limits.h +++ b/kernel/include/comus/limits.h @@ -12,6 +12,10 @@ /// max number of processes #define N_PROCS 256 +/// process limits +#define N_OPEN_FILES 64 +#define N_ARGS 64 + /// max nubmer of pci devices #define N_PCI_DEV 256 diff --git a/kernel/include/comus/procs.h b/kernel/include/comus/procs.h index 7b1a70a..3df31c3 100644 --- a/kernel/include/comus/procs.h +++ b/kernel/include/comus/procs.h @@ -13,6 +13,7 @@ #include <comus/limits.h> #include <comus/memory.h> #include <comus/syscalls.h> +#include <comus/fs.h> #include <lib.h> #include <elf.h> @@ -59,6 +60,9 @@ struct pcb { char *heap_start; size_t heap_len; + // open files + struct file *open_files[N_OPEN_FILES]; + // elf metadata Elf64_Ehdr elf_header; Elf64_Phdr elf_segments[N_ELF_SEGMENTS]; diff --git a/kernel/include/comus/syscalls.h b/kernel/include/comus/syscalls.h index f714184..8b671c2 100644 --- a/kernel/include/comus/syscalls.h +++ b/kernel/include/comus/syscalls.h @@ -30,9 +30,10 @@ #define SYS_poweroff 17 #define SYS_drm 18 #define SYS_ticks 19 +#define SYS_seek 20 // UPDATE THIS DEFINITION IF MORE SYSCALLS ARE ADDED! -#define N_SYSCALLS 20 +#define N_SYSCALLS 21 // interrupt vector entry for system calls #define VEC_SYSCALL 0x80 diff --git a/kernel/include/comus/user.h b/kernel/include/comus/user.h index a1a718b..1b35ac4 100644 --- a/kernel/include/comus/user.h +++ b/kernel/include/comus/user.h @@ -9,13 +9,15 @@ #ifndef USER_H_ #define USER_H_ +#include "comus/memory.h" #include <comus/procs.h> #include <comus/fs.h> /** * Load a user elf program from a file into a pcb */ -int user_load(struct pcb *pcb, struct file *file); +int user_load(struct pcb *pcb, struct file *file, const char **args, + mem_ctx_t args_ctx); /** * Clone a user process. Used for fork(). diff --git a/kernel/main.c b/kernel/main.c index a306e2b..72a6668 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -26,6 +26,7 @@ void load_init(void) { struct file_system *fs; struct file *file; + const char *init_vector[] = { NULL }; if (pcb_alloc(&init_pcb)) return; @@ -36,10 +37,10 @@ void load_init(void) return; // get init bin - if (fs->open(fs, "bin/apple", &file)) + if (fs->open(fs, "bin/init", O_RDONLY, &file)) return; - if (user_load(init_pcb, file)) { + if (user_load(init_pcb, file, init_vector, kernel_mem_ctx)) { file->close(file); return; } diff --git a/kernel/procs.c b/kernel/procs.c index 9bf7508..d471416 100644 --- a/kernel/procs.c +++ b/kernel/procs.c @@ -1,3 +1,4 @@ +#include "lib/kio.h" #include <comus/drivers/pit.h> #include <comus/syscalls.h> #include <comus/memory.h> @@ -218,7 +219,7 @@ void pcb_zombify(struct pcb *victim) status = (int *)PCB_ARG2(parent); if (pid == 0 || pid == victim->pid) { - PCB_RET(parent) = zchild->pid; + PCB_RET(parent) = victim->pid; assert( pcb_queue_remove(syscall_queue[SYS_waitpid], parent) == SUCCESS, diff --git a/kernel/syscall.c b/kernel/syscall.c index 96d2fcf..44ebfa0 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -1,3 +1,5 @@ +#include "comus/fs.h" +#include "lib/kio.h" #include <comus/user.h> #include <comus/cpu.h> #include <comus/syscalls.h> @@ -23,6 +25,16 @@ static struct pcb *pcb; #define stdout 1 #define stderr 2 +static struct file *get_file_ptr(int fd) +{ + // valid index? + if (fd < 3 || fd >= (N_OPEN_FILES + 3)) + return NULL; + + // will be NULL if not open + return pcb->open_files[fd - 3]; +} + __attribute__((noreturn)) static int sys_exit(void) { ARG1(int, status); @@ -36,6 +48,33 @@ __attribute__((noreturn)) static int sys_exit(void) static int sys_waitpid(void) { + ARG1(pid_t, pid); + ARG2(int *, status); + + struct pcb *child; + for (int i = 0; i < N_PROCS; i++) { + child = &ptable[i]; + if (child->state != PROC_STATE_ZOMBIE) + continue; + if (child->parent != pcb) + continue; + + // we found a child! + if (pid && pid != child->pid) + continue; + + // set status + mem_ctx_switch(pcb->memctx); + *status = child->exit_status; + mem_ctx_switch(kernel_mem_ctx); + + // clean up child process + pcb_cleanup(child); + + // return + return child->pid; + } + // arguments are read later // by procs.c pcb->state = PROC_STATE_BLOCKED; @@ -60,6 +99,125 @@ static int sys_fork(void) return 0; } +static int sys_exec(void) +{ + ARG1(const char *, in_filename); + ARG2(const char **, in_args); + + struct file_system *fs; + struct file *file; + char filename[N_FILE_NAME]; + struct pcb save; + + // save data + file = NULL; + save = *pcb; + + // read filename + mem_ctx_switch(pcb->memctx); + memcpy(filename, in_filename, strlen(in_filename) + 1); + mem_ctx_switch(kernel_mem_ctx); + + // get binary + fs = fs_get_root_file_system(); + if (fs == NULL) + goto fail; + if (fs->open(fs, filename, O_RDONLY, &file)) + goto fail; + + // load program + save = *pcb; + if (user_load(pcb, file, in_args, save.memctx)) + goto fail; + file->close(file); + mem_ctx_free(save.memctx); + schedule(pcb); + dispatch(); + +fail: + *pcb = save; + if (file) + file->close(file); + return 1; +} + +static int sys_open(void) +{ + ARG1(const char *, in_filename); + ARG2(int, flags); + + char filename[N_FILE_NAME]; + struct file_system *fs; + struct file **file; + int fd; + + // read filename + mem_ctx_switch(pcb->memctx); + memcpy(filename, in_filename, strlen(in_filename)); + mem_ctx_switch(kernel_mem_ctx); + + // get fd + for (fd = 3; fd < (N_OPEN_FILES + 3); fd++) { + if (pcb->open_files[fd - 3] == NULL) { + file = &pcb->open_files[fd - 3]; + break; + } + } + + // could not find fd + if (fd == (N_OPEN_FILES + 3)) + return -1; + + // open file + fs = fs_get_root_file_system(); + if (fs == NULL) + return -1; + if (fs->open(fs, filename, flags, file)) + return -1; + + // file opened + return fd; +} + +static int sys_close(void) +{ + ARG1(int, fd); + + struct file *file; + file = get_file_ptr(fd); + if (file == NULL) + return 1; + + file->close(file); + return 0; +} + +static int sys_read(void) +{ + ARG1(int, fd); + ARG2(void *, buffer); + ARG3(size_t, nbytes); + + struct file *file; + char *map_buf; + + map_buf = kmapuseraddr(pcb->memctx, buffer, nbytes); + if (map_buf == NULL) + return -1; + + file = get_file_ptr(fd); + if (file == NULL) + goto fail; + + nbytes = file->read(file, map_buf, nbytes); + kunmapaddr(map_buf); + return nbytes; + +fail: + kunmapaddr(map_buf); + return -1; +} + static int sys_write(void) { ARG1(int, fd); @@ -324,17 +482,34 @@ static int sys_ticks(void) return 0; } +static int sys_seek(void) +{ + RET(long int, ret); + ARG1(int, fd); + ARG2(long int, off); + ARG3(int, whence); + + struct file *file; + file = get_file_ptr(fd); + if (file == NULL) + return -1; + + *ret = file->seek(file, off, whence); + return 0; +} + static int (*syscall_tbl[N_SYSCALLS])(void) = { [SYS_exit] = sys_exit, [SYS_waitpid] = sys_waitpid, - [SYS_fork] = sys_fork, [SYS_exec] = NULL, - [SYS_open] = NULL, [SYS_close] = NULL, - [SYS_read] = NULL, [SYS_write] = sys_write, + [SYS_fork] = sys_fork, [SYS_exec] = sys_exec, + [SYS_open] = sys_open, [SYS_close] = sys_close, + [SYS_read] = sys_read, [SYS_write] = sys_write, [SYS_getpid] = sys_getpid, [SYS_getppid] = sys_getppid, [SYS_gettime] = sys_gettime, [SYS_getprio] = sys_getprio, [SYS_setprio] = sys_setprio, [SYS_kill] = sys_kill, [SYS_sleep] = sys_sleep, [SYS_brk] = sys_brk, [SYS_sbrk] = sys_sbrk, [SYS_poweroff] = sys_poweroff, [SYS_drm] = sys_drm, [SYS_ticks] = sys_ticks, + [SYS_seek] = sys_seek, }; void syscall_handler(void) diff --git a/kernel/user.c b/kernel/user.c index 4007383..9612710 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -57,7 +57,7 @@ static int user_load_segment(struct pcb *pcb, struct file *file, int idx) return 1; // seek to start of segment - if (file->seek(file, hdr.p_offset, SEEK_SET)) + if (file->seek(file, hdr.p_offset, SEEK_SET) < 0) return 1; // load data @@ -151,7 +151,7 @@ static int user_load_elf(struct pcb *pcb, struct file *file) { int ret = 0; - if (file->seek(file, 0, SEEK_SET)) + if (file->seek(file, 0, SEEK_SET) < 0) return 1; ret = file->read(file, (char *)&pcb->elf_header, sizeof(Elf64_Ehdr)); if (ret < 0) @@ -161,7 +161,7 @@ static int user_load_elf(struct pcb *pcb, struct file *file) return 1; pcb->n_elf_segments = pcb->elf_header.e_phnum; - if (file->seek(file, pcb->elf_header.e_phoff, SEEK_SET)) + if (file->seek(file, pcb->elf_header.e_phoff, SEEK_SET) < 0) return 1; ret = file->read(file, (char *)&pcb->elf_segments, sizeof(Elf64_Phdr) * pcb->elf_header.e_phnum); @@ -171,14 +171,56 @@ static int user_load_elf(struct pcb *pcb, struct file *file) return 0; } -static int user_setup_stack(struct pcb *pcb) +static int user_setup_stack(struct pcb *pcb, const char **args, + mem_ctx_t args_ctx) { - // allocate stack + /* args */ + int argbytes = 0; + int argc = 0; + + mem_ctx_switch(args_ctx); + + while (args[argc] != NULL) { + int n = strlen(args[argc]) + 1; + if ((argbytes + n) > USER_STACK_LEN) { + // oops - ignore this and any others + break; + } + argbytes += n; + argc++; + } + + // round to nearest multiple of 8 + argbytes = (argbytes + 7) & 0xfffffffffffffff8; + + // allocate arg strings on kernel stack + char argstrings[argbytes]; + char *argv[argc + 1]; + memset(argstrings, 0, sizeof(argstrings)); + memset(argv, 0, sizeof(argv)); + + // Next, duplicate the argument strings, and create pointers to + // each one in our argv. + char *tmp = argstrings; + for (int i = 0; i < argc; ++i) { + int nb = strlen(args[i]) + 1; + strcpy(tmp, args[i]); + argv[i] = tmp; + tmp += nb; + } + + // trailing NULL pointer + argv[argc] = NULL; + + mem_ctx_switch(kernel_mem_ctx); + + /* stack */ if (mem_alloc_pages_at(pcb->memctx, USER_STACK_LEN / PAGE_SIZE, (void *)(USER_STACK_TOP - USER_STACK_LEN), F_WRITEABLE | F_UNPRIVILEGED) == NULL) return 1; + /* regs */ memset(&pcb->regs, 0, sizeof(struct cpu_regs)); // pgdir @@ -189,7 +231,7 @@ static int user_setup_stack(struct pcb *pcb) pcb->regs.es = USER_DATA | RING3; pcb->regs.ds = USER_DATA | RING3; // registers - pcb->regs.rdi = 0; // argc + pcb->regs.rdi = argc; // argc pcb->regs.rsi = 0; // argv // intruction pointer pcb->regs.rip = pcb->elf_header.e_entry; @@ -205,7 +247,8 @@ static int user_setup_stack(struct pcb *pcb) return 0; } -int user_load(struct pcb *pcb, struct file *file) +int user_load(struct pcb *pcb, struct file *file, const char **args, + mem_ctx_t args_ctx) { // check inputs if (pcb == NULL || file == NULL) @@ -225,7 +268,7 @@ int user_load(struct pcb *pcb, struct file *file) goto fail; // setup process stack - if (user_setup_stack(pcb)) + if (user_setup_stack(pcb, args, args_ctx)) goto fail; // success |