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/user.c | |
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/user.c | 59 |
1 files changed, 51 insertions, 8 deletions
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 |