diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2021-12-26 17:50:11 +0200 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2021-12-26 17:50:11 +0200 |
| commit | d98ec57128628b81fcd32269a92742a037b7f713 (patch) | |
| tree | 0e3f8d78d8347ef0a6e69d41b9d9be20c822b642 /common | |
| parent | a64f3588ff5da7f148659ccb0eff844ccfb57088 (diff) | |
| download | kmi-d98ec57128628b81fcd32269a92742a037b7f713.tar.gz kmi-d98ec57128628b81fcd32269a92742a037b7f713.zip | |
First useful jump to userspace!
Diffstat (limited to 'common')
| -rw-r--r-- | common/elf.c | 85 | ||||
| -rw-r--r-- | common/initrd.c | 8 | ||||
| -rw-r--r-- | common/vmem.c | 9 |
3 files changed, 92 insertions, 10 deletions
diff --git a/common/elf.c b/common/elf.c index c6a37e0..c73d56c 100644 --- a/common/elf.c +++ b/common/elf.c @@ -1,12 +1,83 @@ #include <apos/elf.h> #include <apos/vmem.h> +#include <apos/bytes.h> +#include <apos/string.h> -vm_t bin_entry(vm_t bin) +static void __map_exec(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart, size_t phnum, size_t phsize) { - struct elf_header *e = (struct elf_header *)bin; - /* TODO: check that address points to a valid ELF executable */ - /* oh yeah, this only works for DYN objects, fuck */ - /* eh, fuck it, I'll fix this later, today has been a decently - * productive day as is */ - return ((vm_t)e->e_entry) + bin; + /* TODO: take alignment into consideration? */ + vm_t runner = phstart; + for(size_t i = 0; i < phnum; ++i, runner += phsize){ + if(program_header_prop(ei_c, runner, p_type) != PT_LOAD) + continue; + + vm_t va = program_header_prop(ei_c, runner, p_vaddr); + size_t vsz = program_header_prop(ei_c, runner, p_memsz); + + vm_t start = 0; + if(!(start = alloc_fixed_region(&t->sp_r, va, vsz, 0))) + return; /* out of memory or something */ + + uint8_t vflags = VM_V | VM_U; + uint8_t bflags = program_header_prop(ei_c, runner, p_flags); + if(bflags & PF_X) + vflags |= VM_X; + + if(bflags & PF_W) + vflags |= VM_W; + + if(bflags & PF_R) + vflags |= VM_R; + + map_fill_region(t->b_r, start, vsz, VM_V | VM_X | VM_R | VM_W | VM_U); + + vm_t vo = bin + program_header_prop(ei_c, runner, p_offset); + vm_t vfz = program_header_prop(ei_c, runner, p_filesz); + memcpy((void *)va, (void *)vo, vfz); + + /* skip while testing + pm_t paddr = 0; + stat_vmem(t->b_r, va, &paddr, 0, 0); + mod_vmem(t->b_r, va, paddr, vflags); + */ + } +} + +static vm_t __map_dyn(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart, size_t phnum, size_t phsize) +{ + /* TODO */ +} + +static vm_t __prepare_proc(struct tcb *t, uint8_t ei_c, vm_t elf) +{ + short e_type = elf_header_prop(ei_c, elf, e_type); + if(e_type != ET_DYN && e_type != ET_EXEC) + return 0; + + vm_t phstart = ptradd(elf, elf_header_prop(ei_c, elf, e_phoff)); + size_t phnum = elf_header_prop(ei_c, elf, e_phnum); + size_t phsize = elf_header_prop(ei_c, elf, e_phentsize); + + vm_t entry = elf_header_prop(ei_c, elf, e_entry); + if(e_type == ET_EXEC){ + __map_exec(t, elf, ei_c, phstart, phnum, phsize); + return entry; + } else { + vm_t o = __map_dyn(t, elf, ei_c, phstart, phnum, phsize); + return o + entry; + } +} + +/* sets up all memory regions etc, returns the entry address */ +vm_t prepare_proc(struct tcb *t, vm_t p) +{ + struct elf_ident *i = (struct elf_ident *)p; + if(i->ei_magic != cpu_to_be32(EI_MAGIC)) + return 0; + + if(i->ei_class != ELFCLASS32 && i->ei_class != ELFCLASS64) + return 0; + + /* more sanity checks? */ + return __prepare_proc(t, i->ei_class, p); } diff --git a/common/initrd.c b/common/initrd.c index 61aaaff..18db836 100644 --- a/common/initrd.c +++ b/common/initrd.c @@ -86,6 +86,14 @@ size_t get_init_size(void *fdt) return convnum(cp->c_filesize, 8, 16); } +vm_t get_init_base(void *fdt) +{ + char *c = (char *)get_initrdbase(fdt); + struct cpio_header *cp = find_file(c, init_n, init_nlen); + size_t name_len = convnum(cp->c_namesize, 8, 16); + return ((vm_t)cp) + align_up(sizeof(struct cpio_header) + name_len, 4); +} + void move_init(void *fdt, void *target) { char *c = (char *)get_initrdbase(fdt); diff --git a/common/vmem.c b/common/vmem.c index 7b1fa4f..229963c 100644 --- a/common/vmem.c +++ b/common/vmem.c @@ -299,8 +299,11 @@ vm_t alloc_region(struct sp_reg_root *r, vm_t alloc_fixed_region(struct sp_reg_root *r, vm_t start, size_t size, size_t *actual_size) { - *actual_size = align_up(size, BASE_PAGE_SIZE); - size_t pages = __page(*actual_size); + size_t asize = align_up(size, BASE_PAGE_SIZE); + if(actual_size) + *actual_size = asize; + + size_t pages = __page(asize); start = __page(start); struct sp_mem *m = sp_find_used_closest(r, start); @@ -309,7 +312,7 @@ vm_t alloc_fixed_region(struct sp_reg_root *r, /* locate actual region where start is between the region start and end */ while(!((m->start <= start) && (start <= m->end))){ - if(start < m->start) + if(start > m->start) m = m->next; else m = m->prev; |
