diff options
author | Ian Moffett <ian@osmora.org> | 2024-03-07 16:21:12 -0500 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2024-03-07 16:26:25 -0500 |
commit | 21a122bcffcd4863a7f56b9680396919b909d232 (patch) | |
tree | b153a2dcb006b8057264ea6bac1ceffe6b750bb1 /sys/kern/kern_loader.c | |
parent | f621116fcaf15cd5dc0c53dab9a88f53f0effcd8 (diff) |
kernel: Require VAS arg in vm + loader refactor
This commit adds vas argument to VM mapping functions as well as
changing how mapping is done in the loader. This commit also fixes weird
error handling and parses needed PHDRs within the loader
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/kern/kern_loader.c')
-rw-r--r-- | sys/kern/kern_loader.c | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/sys/kern/kern_loader.c b/sys/kern/kern_loader.c index cf51c72..73dc8c7 100644 --- a/sys/kern/kern_loader.c +++ b/sys/kern/kern_loader.c @@ -32,9 +32,11 @@ #include <sys/elf.h> #include <sys/types.h> #include <sys/syslog.h> +#include <sys/errno.h> #include <vm/vm.h> #include <vm/map.h> #include <vm/physseg.h> +#include <vm/dynalloc.h> #include <string.h> #include <assert.h> @@ -51,14 +53,15 @@ __KERNEL_META("$Hyra$: kern_loader.c, Ian Marco Moffett, " #define PHDR(hdrptr, IDX) \ (void *)((uintptr_t)hdr + (hdrptr)->e_phoff + (hdrptr->e_phentsize*IDX)) -int -loader_load(const void *dataptr, struct auxval *auxv) +int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, + size_t load_base, char **ld_path) { const Elf64_Ehdr *hdr = dataptr; Elf64_Phdr *phdr; vm_prot_t prot = 0; uintptr_t physmem; + uintptr_t map_addr; size_t misalign, page_count; int status; @@ -92,20 +95,50 @@ loader_load(const void *dataptr, struct auxval *auxv) page_count = __DIV_ROUNDUP(phdr->p_memsz + misalign, GRANULE); physmem = vm_alloc_pageframe(page_count); - __assert(physmem != 0); /* TODO: Handle better */ - status = vm_map_create(phdr->p_vaddr, physmem, prot, - page_count * GRANULE); + /* Do we not have enough page frames? */ + if (physmem == 0) { + DBG("Failed to allocate physical memory\n"); + vm_free_pageframe(physmem, page_count); + return -ENOMEM; + } + + map_addr = phdr->p_vaddr + load_base; + status = vm_map_create(vas, map_addr, physmem, prot, page_count*GRANULE); - __assert(status == 0); /* TODO: Handle better */ + if (status != 0) { + DBG("Failed to map 0x%p - 0x%p\n", + phdr->p_vaddr + load_base, + (phdr->p_vaddr + load_base) + (page_count * GRANULE)); + + return status; + } /* Now we want to copy the data */ tmp_ptr = (void *)((uintptr_t)hdr + phdr->p_offset); - memcpy((void *)phdr->p_vaddr, tmp_ptr, phdr->p_filesz); + memcpy(PHYS_TO_VIRT(physmem), tmp_ptr, phdr->p_filesz); + break; + case PT_INTERP: + if (ld_path == NULL) { + break; + } + + *ld_path = dynalloc(phdr->p_filesz); + + if (ld_path == NULL) { + DBG("Failed to allocate memory for PT_INTERP path\n"); + return -ENOMEM; + } + + memcpy(*ld_path, (char *)hdr + phdr->p_offset, phdr->p_filesz); + break; + case PT_PHDR: + auxv->at_phdr = phdr->p_vaddr + load_base; + break; } } - auxv->at_entry = hdr->e_entry; + auxv->at_entry = hdr->e_entry + load_base; auxv->at_phent = hdr->e_phentsize; auxv->at_phnum = hdr->e_phnum; return 0; |