diff --git a/errors/errno.fugu b/errors/errno.fugu index 7db67d5..eb4a145 100755 --- a/errors/errno.fugu +++ b/errors/errno.fugu @@ -583,6 +583,7 @@ errors spawn SPAWN_ERR_ { failure VSPACE_INIT "Failure in spawn_vspace_init", failure SETUP_DISPATCHER "Failure in spawn_setup_dispatcher", failure ELF_MAP "Failure in spawn_elf_map", + failure ELF_LOAD "Failure in elf_load", failure SET_CAPS "Failure in set_special_caps", failure MONEP_SLOT_ALLOC "Failure allocating a slot for monitor EP", diff --git a/lib/spawn/spawn.c b/lib/spawn/spawn.c index 4fb4bb5..118584c 100644 --- a/lib/spawn/spawn.c +++ b/lib/spawn/spawn.c @@ -86,6 +86,43 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si, return LIB_ERR_NOT_IMPLEMENTED; } +struct allocate_state { + // TODO: add fields +}; + +static errval_t elf_allocate( + void *state, + genvaddr_t base, + size_t size, + uint32_t flags, + void **ret +) { + errval_t err; + // struct allocate_state *st = state; + + // Allocate a frame + struct capref frame; + err = slot_alloc(&frame); + if (err_is_fail(err)) return err_push(err, LIB_ERR_SLOT_ALLOC); + + size_t alloc_bytes; + err = frame_create(frame, size, &alloc_bytes); + if (err_is_fail(err)) { + slot_free(frame); + return err_push(err, LIB_ERR_FRAME_ALLOC); + } + + // Map into current address space + err = paging_map_frame_attr( + get_current_paging_state(), ret, + alloc_bytes, frame, VREGION_FLAGS_READ_WRITE + ); + if (err_is_fail(err)) return err; + + // TODO: Map into child address space + + return SYS_ERR_OK; +} /** * TODO(M2): Implement this function. @@ -108,6 +145,7 @@ errval_t spawn_load_by_name(char *binary_name, struct spawninfo * si, struct mem_region *module = multiboot_find_module(bi, binary_name); if (module == NULL) return SPAWN_ERR_FIND_MODULE; + // - Get the frame of the ELF struct capref child_frame = { .cnode = cnode_module, .slot = module->mrmod_slot, @@ -117,8 +155,9 @@ errval_t spawn_load_by_name(char *binary_name, struct spawninfo * si, err = cap_direct_identify(child_frame, &c); if (err_is_fail(err)) return err; gensize_t frame_size = get_size(&c); - if (frame_size < module->mr_bytes) return SPAWN_ERR_MODULE_FRAME_TOO_SMALL; + if (frame_size < module->mrmod_size) return SPAWN_ERR_MODULE_FRAME_TOO_SMALL; + // - Map the ELF into the current addess space char *module_data; err = paging_map_frame_attr( get_current_paging_state(), (void **)&module_data, @@ -126,8 +165,14 @@ errval_t spawn_load_by_name(char *binary_name, struct spawninfo * si, ); if (err_is_fail(err)) return err_push(err, SPAWN_ERR_MAP_MODULE); - debug_printf("SPAWN: mapped %s, magic: %"PRIx8" %c%c%c\n", - binary_name, module_data[0], module_data[1], module_data[2], module_data[3]); + debug_printf("SPAWN: mapped %s, size: %"PRIx64", magic: %"PRIx8" %c%c%c\n", + binary_name, module->mrmod_size, module_data[0], module_data[1], module_data[2], module_data[3]); + + // - Parse the ELF + struct allocate_state st = {}; + genvaddr_t entry; + err = elf_load(EM_AARCH64, elf_allocate, &st, (lvaddr_t)module_data, module->mrmod_size, &entry); + if (err_is_fail(err)) return err_push(err, SPAWN_ERR_ELF_LOAD); // - Fill in argc/argv from the multiboot command line // - Call spawn_load_argv