lib: launch: implement passing args and environment variables to new tasks
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
#include "elf.h"
|
||||
#include "stack.h"
|
||||
|
||||
#include <launch.h>
|
||||
#include <mango/handle.h>
|
||||
#include <mango/log.h>
|
||||
#include <mango/task.h>
|
||||
#include <mango/vm.h>
|
||||
#include <rosetta/bootstrap.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -34,6 +36,58 @@ static kern_handle_t get_library(
|
||||
return result;
|
||||
}
|
||||
|
||||
static virt_addr_t write_bootstrap_data(
|
||||
struct stack_writer *stack,
|
||||
const struct launch_parameters *params)
|
||||
{
|
||||
virt_addr_t bs_remote;
|
||||
struct rosetta_bootstrap *bs
|
||||
= stack_writer_put(stack, NULL, sizeof *bs, &bs_remote);
|
||||
|
||||
memset(bs, 0x0, sizeof *bs);
|
||||
|
||||
bs->bs_argc = params->p_argc;
|
||||
bs->bs_envc = params->p_envc;
|
||||
bs->bs_handles_count = params->p_handle_count;
|
||||
bs->bs_channels_count = params->p_channel_count;
|
||||
|
||||
const char **argv, **envp;
|
||||
|
||||
if (bs->bs_argc > 0) {
|
||||
virt_addr_t remote_argv;
|
||||
argv = stack_writer_put(
|
||||
stack,
|
||||
NULL,
|
||||
bs->bs_argc * sizeof(char *),
|
||||
&remote_argv);
|
||||
bs->bs_argv = (const char **)remote_argv;
|
||||
}
|
||||
|
||||
if (bs->bs_envc > 0) {
|
||||
virt_addr_t remote_envp;
|
||||
envp = stack_writer_put(
|
||||
stack,
|
||||
NULL,
|
||||
bs->bs_envc * sizeof(char *),
|
||||
&remote_envp);
|
||||
bs->bs_envp = (const char **)remote_envp;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < params->p_argc; i++) {
|
||||
virt_addr_t arg_ptr;
|
||||
stack_writer_put_string(stack, params->p_argv[i], &arg_ptr);
|
||||
argv[i] = (const char *)arg_ptr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < params->p_envc; i++) {
|
||||
virt_addr_t env_ptr;
|
||||
stack_writer_put_string(stack, params->p_envp[i], &env_ptr);
|
||||
envp[i] = (const char *)env_ptr;
|
||||
}
|
||||
|
||||
return bs_remote;
|
||||
}
|
||||
|
||||
enum launch_status launch_ctx_execute(
|
||||
struct launch_ctx *ctx,
|
||||
const struct launch_parameters *params,
|
||||
@@ -102,7 +156,7 @@ enum launch_status launch_ctx_execute(
|
||||
return status;
|
||||
}
|
||||
|
||||
virt_addr_t stack_buf;
|
||||
virt_addr_t remote_stack_buf, local_stack_buf;
|
||||
kstatus = vm_region_map_relative(
|
||||
remote_address_space,
|
||||
VM_REGION_ANY_OFFSET,
|
||||
@@ -110,7 +164,15 @@ enum launch_status launch_ctx_execute(
|
||||
0,
|
||||
STACK_SIZE,
|
||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||
&stack_buf);
|
||||
&remote_stack_buf);
|
||||
kstatus = vm_region_map_relative(
|
||||
params->p_local_address_space,
|
||||
VM_REGION_ANY_OFFSET,
|
||||
stack_vmo,
|
||||
0,
|
||||
STACK_SIZE,
|
||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||
&local_stack_buf);
|
||||
kern_handle_close(stack_vmo);
|
||||
|
||||
if (kstatus != KERN_OK) {
|
||||
@@ -120,11 +182,23 @@ enum launch_status launch_ctx_execute(
|
||||
return LAUNCH_ERR_MEMORY_MAP_FAILED;
|
||||
}
|
||||
|
||||
struct stack_writer stack;
|
||||
stack_writer_init(
|
||||
&stack,
|
||||
local_stack_buf + STACK_SIZE,
|
||||
remote_stack_buf + STACK_SIZE);
|
||||
virt_addr_t bsdata = write_bootstrap_data(&stack, params);
|
||||
|
||||
virt_addr_t ip = image.e_hdr.e_entry + image.e_remote_base;
|
||||
virt_addr_t sp = stack_buf + STACK_SIZE;
|
||||
|
||||
kern_handle_t thread;
|
||||
kstatus = task_create_thread(remote_task, ip, sp, NULL, 0, &thread);
|
||||
kstatus = task_create_thread(
|
||||
remote_task,
|
||||
ip,
|
||||
stack.w_remote_sp,
|
||||
&bsdata,
|
||||
1,
|
||||
&thread);
|
||||
if (kstatus != KERN_OK) {
|
||||
elf_image_cleanup(&image);
|
||||
kern_handle_close(remote_address_space);
|
||||
|
||||
Reference in New Issue
Block a user