From 2d9ba6ae709d8f807acae9d9a06e9f9407e0c415 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 8 Mar 2011 23:12:38 +0100 Subject: [PATCH] forwarding arguments to the new tasks --- include/metalsvm/tasks.h | 4 +- kernel/tasks.c | 119 ++++++++++++++++++++++++-- kernel/tests.c | 6 +- newlib/examples/hello.c | 4 + newlib/examples/tests.c | 7 +- newlib/src/libgloss/metalsvm/crt0.asm | 16 +--- 6 files changed, 127 insertions(+), 29 deletions(-) diff --git a/include/metalsvm/tasks.h b/include/metalsvm/tasks.h index ca1d86a3..c381bb48 100644 --- a/include/metalsvm/tasks.h +++ b/include/metalsvm/tasks.h @@ -37,8 +37,8 @@ int multitasking_init(void); /* create a kernel task. */ int create_kernel_task(tid_t*, entry_point_t, void*); -/* create a user level task. if sz is zero, the task with the default stack size will be created */ -int create_user_task(tid_t* id, size_t sz, const char* filename, int argc, char** argv); +/* create a user level task. */ +int create_user_task(tid_t* id, const char* filename, char** argv); /* until a child task is terminated, the current task is block */ tid_t wait(int32_t* result); diff --git a/kernel/tasks.c b/kernel/tasks.c index 2843daec..9d451bee 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -241,13 +241,28 @@ int create_kernel_task(tid_t* id, entry_point_t ep, void* arg) return create_task(id, ep, arg); } -static int load_task(vfs_node_t* node) +#define MAX_ARGS (PAGE_SIZE - 2*sizeof(int) - sizeof(vfs_node_t*)) + +typedef struct { + vfs_node_t* node; + int argc; + int envc; + char buffer[MAX_ARGS]; +} load_args_t; + +static int load_task(load_args_t* largs) { - uint32_t i, addr, npages, flags, stack = 0; + uint32_t i, offset, idx; + uint32_t addr, npages, flags, stack = 0; elf_header_t header; elf_program_header_t prog_header; //elf_section_header_t sec_header; + vfs_node_t* node; + if (!largs) + return -EINVAL; + + node = largs->node; if (!node) return -EINVAL; @@ -361,7 +376,34 @@ static int load_task(vfs_node_t* node) return -ENOMEM; } - jump_to_user_code(header.entry, stack+DEFAULT_STACK_SIZE-64); + // push strings on the stack + offset = DEFAULT_STACK_SIZE-MAX_ARGS-8; + memcpy((void*) (stack+offset), largs->buffer, MAX_ARGS); + idx = offset; + + // push argv on the stack + offset -= largs->argc * sizeof(char*); + i = 0; + while(iargc) { + ((char**) (stack+offset))[i] = (char*) (stack+idx); + i++; + + while((iargc) && ((char*) stack)[idx] != '\0') + idx++; + idx++; + } + + // push pointer to argv + offset -= sizeof(char**); + *((char***) (stack+offset)) = (char**) (stack + offset + sizeof(char**)); + + // push argc on the stack + offset -= sizeof(int); + *((int*) (stack+offset)) = largs->argc; + + kfree(largs, sizeof(load_args_t)); + + jump_to_user_code(header.entry, stack+offset); return 0; @@ -373,29 +415,88 @@ invalid: static int STDCALL user_entry(void* arg) { - return load_task((vfs_node_t*) arg); + return load_task((load_args_t*) arg); } -int create_user_task(tid_t* id, size_t sz, const char* fname, int argc, char** argv) +int create_user_task(tid_t* id, const char* fname, char** argv) { vfs_node_t* node; + int argc = 0; + size_t i, buffer_size = 0; + load_args_t* load_args = NULL; + char *dest, *src; node = findnode_fs((char*) fname); if (!node || !(node->type == FS_FILE)) return -EINVAL; - return create_task(id, user_entry, node); + // determine buffer size of argv + if (argv) { + while (argv[argc]) { + buffer_size += (strlen(argv[argc]) + 1); + argc++; + } + } + + if (argc <= 0) + return -EINVAL; + if (buffer_size >= MAX_ARGS) + return -EINVAL; + + load_args = kmalloc(sizeof(load_args_t)); + if (BUILTIN_EXPECT(!load_args, 0)) + return -ENOMEM; + load_args->node = node; + load_args->argc = argc; + load_args->envc = 0; + dest = load_args->buffer; + for (i=0; itype == FS_FILE)) return -EINVAL; + // determine buffer size of argv + if (argv) { + while (argv[argc]) { + buffer_size += (strlen(argv[argc]) + 1); + argc++; + } + } + + if (argc <= 0) + return -EINVAL; + if (buffer_size >= MAX_ARGS) + return -EINVAL; + + load_args = kmalloc(sizeof(load_args_t)); + if (BUILTIN_EXPECT(!load_args, 0)) + return -ENOMEM; + + load_args->node = node; + load_args->argc = argc; + load_args->envc = 0; + dest = load_args->buffer; + for (i=0; ivma_lock)); // remove old program @@ -414,7 +515,11 @@ int sys_execve(const char* fname, char** argv, char** env) * => we could directly load the new task */ - return load_task(node); + ret = load_task(load_args); + + kfree(load_args, sizeof(load_args_t)); + + return ret; } tid_t wait(int32_t* result) diff --git a/kernel/tests.c b/kernel/tests.c index c62870c2..dec3d299 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -102,7 +102,7 @@ static int STDCALL join_test(void* arg) int test_init(void) { - char* argv[1] = {"dummy"}; + char* argv[] = {"/bin/tests", NULL}; sem_init(&producing, 1); sem_init(&consuming, 0); @@ -112,8 +112,8 @@ int test_init(void) //create_kernel_task(NULL, join_test, NULL); //create_kernel_task(NULL, producer, NULL); //create_kernel_task(NULL, consumer, NULL); - //create_user_task(NULL, 8192, "/bin/hello", 1, argv); - create_user_task(NULL, 8192, "/bin/tests", 1, argv); + //create_user_task(NULL, "/bin/hello", 1, argv); + create_user_task(NULL, "/bin/tests", argv); return 0; } diff --git a/newlib/examples/hello.c b/newlib/examples/hello.c index 9e4fa70d..1c6f1f2f 100644 --- a/newlib/examples/hello.c +++ b/newlib/examples/hello.c @@ -27,8 +27,12 @@ extern int errno; int main(int argc, char** argv) { + int i; char str[] = "Hello World!!!\n"; + for(i=0; i