From 20c7b5be3bbb5f56a31536c018e20706100f57ae Mon Sep 17 00:00:00 2001 From: dzwdz Date: Sat, 23 Jul 2022 19:28:43 +0200 Subject: user_bootstrap: pass the initrd in an argument to init's main --- src/user/app/main.c | 9 +++++---- src/user/lib/elfload.c | 51 +++++++++++++++++++++++++++++++---------------- src/user/lib/elfload.h | 1 + src/user_bootstrap/main.c | 12 +++++++---- 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/user/app/main.c b/src/user/app/main.c index 28c4aa0..9f4d50c 100644 --- a/src/user/app/main.c +++ b/src/user/app/main.c @@ -9,16 +9,17 @@ #include #include -// extern char _initrd; +__attribute__((visibility("hidden"))) +extern char _image_base[]; void read_file(const char *path, size_t len); __attribute__((section(".text.startup"))) -int main(void) { +int main(void *initrd) { elf_selfreloc(); file_reopen(stdout, "/com1", 0); - printf("preinit\n"); + printf("in init, loaded at 0x%x\n", &_image_base); /* move everything provided by the kernel to /kdev */ MOUNT("/kdev/", fs_passthru(NULL)); @@ -28,7 +29,7 @@ int main(void) { } if (!fork2_n_mount("/")) fs_dir_inject("/kdev/"); // TODO should be part of fs_whitelist - // MOUNT("/init/", tar_driver(&_initrd)); + MOUNT("/init/", tar_driver(initrd)); MOUNT("/tmp/", tmpfs_drv()); MOUNT("/keyboard", ps2_drv()); MOUNT("/vga_tty", ansiterm_drv()); diff --git a/src/user/lib/elfload.c b/src/user/lib/elfload.c index 6c75268..ef14388 100644 --- a/src/user/lib/elfload.c +++ b/src/user/lib/elfload.c @@ -62,41 +62,58 @@ static size_t elf_spread(const void *elf) { return high - low; } -/* frees memory outside of [low; high] and jumps to *entry */ -static void freejmp(void *entry, void *low, void *high) { +/* frees memory outside of [low; low + len] and jumps to *entry */ +static void freejmp(void *entry, void *low, size_t len) { + uintptr_t high = (uintptr_t)low + len; uint64_t buf[] = { EXECBUF_SYSCALL, _SYSCALL_MEMFLAG, 0, (uintptr_t)low, 0, 0, - EXECBUF_SYSCALL, _SYSCALL_MEMFLAG, (uintptr_t)high, ~0 - 0xF000 - (uintptr_t)high, 0, 0, + EXECBUF_SYSCALL, _SYSCALL_MEMFLAG, high, ~0 - 0xF000 - high, 0, 0, EXECBUF_JMP, (uintptr_t)entry, }; _syscall_execbuf(buf, sizeof buf); + // should never return } -void elf_exec(void *base) { - struct Elf64_Ehdr *ehdr = base; +static void *elf_loadmem(struct Elf64_Ehdr *ehdr) { void *exebase; - if (!valid_ehdr(ehdr)) return; - _syscall_debug_klog("here", 4); - size_t spread = elf_spread(base); + size_t spread = elf_spread(ehdr); switch (ehdr->e_type) { case ET_EXEC: exebase = (void*)0; break; case ET_DYN: exebase = _syscall_memflag((void*)0x1000, spread, MEMFLAG_FINDFREE); - if (!exebase) { - printf("elf: out of memory\n"); - _syscall_exit(1); - } + if (!exebase) + return NULL; break; default: - return; + return NULL; } for (size_t phi = 0; phi < ehdr->e_phnum; phi++) { - if (!load_phdr(base, exebase, phi)) - return; + if (!load_phdr((void*)ehdr, exebase, phi)) { + _syscall_memflag(exebase, spread, 0); + return NULL; + } } + return exebase; +} + +void elf_exec(void *base) { + struct Elf64_Ehdr *ehdr = base; + if (!valid_ehdr(ehdr)) return; + + void *exebase = elf_loadmem(ehdr); + if (!exebase) return; + + freejmp(exebase + ehdr->e_entry, exebase, elf_spread(ehdr) + 0x1000); +} + +void *elf_partialexec(void *base) { + struct Elf64_Ehdr *ehdr = base; + if (!valid_ehdr(ehdr)) return NULL; + + void *exebase = elf_loadmem(ehdr); + if (!exebase) return NULL; - freejmp(exebase + ehdr->e_entry, exebase, exebase + spread + 0x1000); - printf("elf: execbuf failed?"); + return exebase + ehdr->e_entry; } diff --git a/src/user/lib/elfload.h b/src/user/lib/elfload.h index f79be6e..40c4874 100644 --- a/src/user/lib/elfload.h +++ b/src/user/lib/elfload.h @@ -3,5 +3,6 @@ void elf_execf(libc_file *f); void elf_exec(void *elf); +void *elf_partialexec(void *elf); /* returns pointer to entry point */ void elf_selfreloc(void); // elfreloc.c diff --git a/src/user_bootstrap/main.c b/src/user_bootstrap/main.c index 71647c4..52d7058 100644 --- a/src/user_bootstrap/main.c +++ b/src/user_bootstrap/main.c @@ -10,7 +10,7 @@ extern char _initrd; /* libc stubs */ int printf(const char *fmt, ...) {(void)fmt; return 0;} void *malloc(size_t size) {(void)size; _syscall_exit(1);} -void free(void *ptr) {} +void free(void *ptr) {(void)ptr;} int file_read(libc_file *f, char *buf, size_t len) {(void)f; (void)buf; (void)len; _syscall_exit(1);} @@ -52,8 +52,12 @@ int main(void) { _syscall_memflag(&_bss_start, &_bss_end - &_bss_start, MEMFLAG_PRESENT); void *init = tar_find(&_initrd, "init.elf"); - elf_exec(init); - _syscall_debug_klog("bootstrap failed", sizeof("bootstrap failed")); - + void (*entry)(void*) = elf_partialexec(init); + if (entry) { + // TODO dynamically link initrd + entry(&_initrd); + } else { + _syscall_debug_klog("bootstrap failed", sizeof("bootstrap failed")); + } _syscall_exit(0); } -- cgit v1.2.3