aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_loader.c
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-05-16 00:13:02 -0400
committerIan Moffett <ian@osmora.org>2024-05-16 00:13:02 -0400
commit4d82697cc521c42cfd51bf8d617802c698ce5e31 (patch)
tree2feafbb29eb67550ddd0d46426fae7c7ec767eeb /sys/kern/kern_loader.c
parent84da00bbc2bb8a93507179a404dfc91c630c6e96 (diff)
kernel: sched: Move loader code away from sched
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/kern/kern_loader.c')
-rw-r--r--sys/kern/kern_loader.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/sys/kern/kern_loader.c b/sys/kern/kern_loader.c
index a7f15e5..091a92b 100644
--- a/sys/kern/kern_loader.c
+++ b/sys/kern/kern_loader.c
@@ -33,6 +33,7 @@
#include <sys/types.h>
#include <sys/syslog.h>
#include <sys/errno.h>
+#include <sys/proc.h>
#include <vm/vm.h>
#include <vm/map.h>
#include <vm/physseg.h>
@@ -65,6 +66,63 @@ loader_unload(struct vas vas, struct vm_range *exec_range)
return vm_map_destroy(vas, start, (end - start));
}
+uintptr_t
+loader_init_stack(void *stack_top, struct exec_args args)
+{
+ uintptr_t *sp = stack_top;
+ uintptr_t old_sp = 0;
+ size_t argc, envc, len;
+ char **argvp = args.argp;
+ char **envp = args.envp;
+ struct auxval auxv = args.auxv;
+
+ /* Copy strings */
+ old_sp = (uintptr_t)sp;
+ for (argc = 0; argvp[argc] != NULL; ++argc) {
+ len = strlen(argvp[argc]) + 1;
+ sp = (void *)((char *)sp - len);
+ memcpy((char *)sp, argvp[argc], len);
+ }
+ for (envc = 0; envp[envc] != NULL; ++envc) {
+ len = strlen(envp[envc]) + 1;
+ sp = (void *)((char *)sp - len);
+ memcpy((char *)sp, envp[envc], len);
+ }
+
+ /* Ensure the stack is aligned */
+ sp = (void *)__ALIGN_DOWN((uintptr_t)sp, 16);
+ if (((argc + envc + 1) & 1) != 0)
+ --sp;
+
+ AUXVAL(sp, AT_NULL, 0x0);
+ AUXVAL(sp, AT_SECURE, 0x0);
+ AUXVAL(sp, AT_ENTRY, auxv.at_entry);
+ AUXVAL(sp, AT_PHDR, auxv.at_phdr);
+ AUXVAL(sp, AT_PHNUM, auxv.at_phnum);
+ AUXVAL(sp, AT_PAGESIZE, vm_get_page_size());
+ STACK_PUSH(sp, 0);
+
+ /* Copy envp pointers */
+ sp -= envc;
+ for (int i = 0; i < envc; ++i) {
+ len = strlen(envp[i]) + 1;
+ old_sp -= len;
+ sp[i] = KERN_TO_USER(old_sp);
+ }
+
+ /* Copy argvp pointers */
+ STACK_PUSH(sp, 0);
+ sp -= argc;
+ for (int i = 0; i < argc; ++i) {
+ len = strlen(argvp[i]) + 1;
+ old_sp -= len;
+ sp[i] = KERN_TO_USER(old_sp);
+ }
+
+ STACK_PUSH(sp, argc);
+ return (uintptr_t)sp;
+}
+
int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv,
size_t load_base, char **ld_path, struct vm_range *prog_range)
{