diff --git a/hake/menu.lst.armv8_a57_qemu b/hake/menu.lst.armv8_a57_qemu index 2e8b676..0039026 100644 --- a/hake/menu.lst.armv8_a57_qemu +++ b/hake/menu.lst.armv8_a57_qemu @@ -5,6 +5,6 @@ bootdriver /armv8/sbin/boot_armv8_generic cpudriver /armv8/sbin/cpu_a57_qemu loglevel=3 serial=0x9000000 logmask=128 module /armv8/sbin/init -module /armv8/sbin/hello +module /armv8/sbin/hello argument1 argument2 argument3 # End of file, this needs to have a certain length... diff --git a/lib/spawn/spawn.c b/lib/spawn/spawn.c index c39051a..08ce23c 100644 --- a/lib/spawn/spawn.c +++ b/lib/spawn/spawn.c @@ -130,7 +130,14 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si, // - Get the module from the multiboot image // and map it (take a look at multiboot.c) + debug_printf("[spawn_load_argv]: argc: %d, argv: ", argc); + for (int i = 0; i < argc; ++i) { + printf("\"%s\", ", argv[i]); + } + printf("\n"); + assert(argc > 0); + assert(argc < MAX_CMDLINE_ARGS); struct mem_region *module = multiboot_find_module(bi, argv[0]); if (module == NULL) return SPAWN_ERR_FIND_MODULE; size_t elf_bytes = module->mrmod_size; @@ -201,7 +208,7 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si, // - Setup the child's vspace // afeer: create level 0 page table - // the l0 page table is in the first slot of the pagecn cnode. + // the l0 page table is in the first slot (PAGECN_SLOT_VROOT) of the pagecn cnode. // lower-level pagetables and mappings are stored on different slots of the pagecn cnode. si->vspace_cap_l0_pagetable.cnode = si->cspace_l2_cnode_pagecn; si->vspace_cap_l0_pagetable.slot = PAGECN_SLOT_VROOT; @@ -284,7 +291,54 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si, disp_gen->eh_frame_hdr_size = 0; // - Setup the environment - // TODO + // afeer: create a frame (=?= page) for the arguments + err = frame_create(si->cspace_cap_argspage, ARGS_SIZE, NULL); + if (err_is_fail(err)) return err_push(err, SPAWN_ERR_CREATE_ARGSPG); + + // afeer: map frame to self + char * arguments_page_in_self; + err = paging_map_frame_attr( + get_current_paging_state(), (void **) &arguments_page_in_self, + ARGS_SIZE, si->cspace_cap_argspage, VREGION_FLAGS_READ_WRITE); + if (err_is_fail(err)) return err_push(err, SPAWN_ERR_MAP_ARGSPG_TO_SELF); + // afeer: zero the page content + memset(arguments_page_in_self, 0, ARGS_SIZE); + + // afeer: map frame to new process + lvaddr_t arguments_page_in_child; + err = paging_map_frame_attr( + &child_paging_state, (void **) &arguments_page_in_child, + ARGS_SIZE, si->cspace_cap_argspage, VREGION_FLAGS_READ_WRITE); + if (err_is_fail(err)) return err_push(err, SPAWN_ERR_MAP_ARGSPG_TO_NEW); + + // afeer: put the arguments into the argspage + struct spawn_domain_params * domain_params = (struct spawn_domain_params *) arguments_page_in_self; + domain_params->argc = argc; + + // afeer: TODO: what do i put here? do we need to set these fields to some value? + // domain_params->vspace_buf = NULL; + // domain_params->vspace_buf_len = 0; + // domain_params->tls_init_base = NULL; + // domain_params->tls_init_len = 0; + // domain_params->tls_total_len = 0; + // domain_params->pagesize = BASE_PAGE_SIZE; + + size_t offset = sizeof(struct spawn_domain_params); + for (int i = 0; i < argc; ++i) { + // afeer: put the argument into page in self + size_t argument_length = strlen(argv[i]); + strncpy(argv[i], arguments_page_in_self + offset, argument_length); + // afeer: specify the child-space address of the argument + domain_params->argv[i] = (char *) arguments_page_in_child + offset; + offset += argument_length + 1; + } + assert(offset <= ARGS_SIZE); + // afeer: null-terminate the arg list + domain_params->argv[argc] = NULL; + domain_params->envp[0] = NULL; + + // afeer: script page 104: set the first register using registers_set_param(arch_registers_state_t) + registers_set_param(enabled_area, (uint64_t) arguments_page_in_child); // - Make the new dispatcher runnable // TODO @@ -312,13 +366,25 @@ errval_t spawn_load_by_name(char *binary_name, struct spawninfo * si, errval_t err; // - Get the mem_region from the multiboot image - // TODO + struct mem_region * module = multiboot_find_module(bi, binary_name); + if (module == NULL) return SPAWN_ERR_FIND_MODULE; // - Fill in argc/argv from the multiboot command line - // TODO - int argc = 1; - char *argv[1]; - argv[0] = binary_name; + const char * c_arguments_str = multiboot_module_opts(module); + // printf("c_arguments_str: %s\n", c_arguments_str); + char raw_arguments_str[strlen(c_arguments_str)]; + strcpy(raw_arguments_str, c_arguments_str); + // printf("raw_arguments_str: %s\n", raw_arguments_str); + + // afeer: explode the raw_arguments_str into argv + char * argv[MAX_CMDLINE_ARGS]; + int argc = 0; + char * token = strtok(raw_arguments_str, " "); + while (token != NULL) { + argv[argc] = token; + token = strtok(NULL, " "); + argc += 1; + } // - Call spawn_load_argv err = spawn_load_argv(argc, argv, si, pid);