| /* |
| * exec.c |
| * |
| * Created on: Aug 14, 2008 |
| * Author: Stefan Bucur <[email protected]> |
| */ |
| |
| #include <sys/module.h> |
| #include <sys/exec.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdarg.h> |
| #include <setjmp.h> |
| #include <setjmp.h> |
| #include <alloca.h> |
| #include <dprintf.h> |
| |
| #define DBG_PRINT(fmt, args...) dprintf("[EXEC] " fmt, ##args) |
| |
| struct elf_module *__syslinux_current = NULL; |
| |
| int get_module_type(struct elf_module *module) |
| { |
| if(module->main_func) return EXEC_MODULE; |
| return LIB_MODULE; |
| } |
| |
| jmp_buf __process_exit_jmp; |
| |
| #if 0 |
| int spawnv(const char *name, const char **argv) |
| { |
| int res, ret_val = 0; |
| const char **arg; |
| int argc; |
| char **argp, **args; |
| struct elf_module *previous; |
| malloc_tag_t prev_mem_tag; |
| |
| struct elf_module *module = module_alloc(name); |
| |
| if (module == NULL) |
| return -1; |
| |
| res = module_load(module); |
| if (res != 0) { |
| module_unload(module); |
| return res; |
| } |
| |
| if (module->main_func == NULL) { |
| // We can't execute without a main function |
| module_unload(module); |
| return -1; |
| } |
| /*if (module->main_func != NULL) { |
| const char **last_arg = argv; |
| void *old_tag; |
| while (*last_arg != NULL) |
| last_arg++; |
| |
| // Setup the memory allocation context |
| old_tag = __mem_get_tag_global(); |
| __mem_set_tag_global(module); |
| |
| // Execute the program |
| ret_val = (*(module->main_func))(last_arg - argv, argv); |
| |
| // Clean up the allocation context |
| __free_tagged(module); |
| // Restore the allocation context |
| __mem_set_tag_global(old_tag); |
| } else { |
| // We can't execute without a main function |
| module_unload(module); |
| return -1; |
| }*/ |
| // Set up the process context |
| previous = __syslinux_current; |
| prev_mem_tag = __mem_get_tag_global(); |
| |
| // Setup the new process context |
| __syslinux_current = module; |
| __mem_set_tag_global((malloc_tag_t)module); |
| |
| // Generate a new process copy of argv (on the stack) |
| argc = 0; |
| for (arg = argv; *arg; arg++) |
| argc++; |
| |
| args = alloca((argc+1) * sizeof(char *)); |
| |
| for (arg = argv, argp = args; *arg; arg++, argp++) { |
| size_t l = strlen(*arg)+1; |
| *argp = alloca(l); |
| memcpy(*argp, *arg, l); |
| } |
| |
| *args = NULL; |
| |
| // Execute the program |
| ret_val = setjmp(module->u.x.process_exit); |
| |
| if (ret_val) |
| ret_val--; /* Valid range is 0-255 */ |
| else if (!module->main_func) |
| ret_val = -1; |
| else |
| exit((module->main_func)(argc, args)); /* Actually run! */ |
| |
| // Clean up the allocation context |
| __free_tagged(module); |
| // Restore the allocation context |
| __mem_set_tag_global(prev_mem_tag); |
| // Restore the process context |
| __syslinux_current = previous; |
| |
| res = module_unload(module); |
| |
| if (res != 0) { |
| return res; |
| } |
| |
| return ((unsigned int)ret_val & 0xFF); |
| } |
| |
| int spawnl(const char *name, const char *arg, ...) |
| { |
| /* |
| * NOTE: We assume the standard ABI specification for the i386 |
| * architecture. This code may not work if used in other |
| * circumstances, including non-variadic functions, different |
| * architectures and calling conventions. |
| */ |
| return spawnv(name, &arg); |
| } |
| #endif |
| |
| /* |
| * Load a module and runs its start function. |
| * |
| * For library modules the start function is module->init_func and for |
| * executable modules its module->main_func. |
| * |
| * "name" is the name of the module to load. |
| * |
| * "argv" and "argc" are only passed to module->main_func, for library |
| * modules these arguments can be NULL and 0, respectively. |
| * |
| * "argv" is an array of arguments to pass to module->main_func. |
| * argv[0] must be a pointer to "name" and argv[argc] must be NULL. |
| * |
| * "argc" is the number of arguments in "argv". |
| */ |
| int spawn_load(const char *name, int argc, char **argv) |
| { |
| int res, ret_val = 0; |
| struct elf_module *previous; |
| //malloc_tag_t prev_mem_tag; |
| struct elf_module *module = module_alloc(name); |
| struct elf_module *cur_module; |
| int type; |
| |
| dprintf("enter: name = %s", name); |
| |
| if (module == NULL) |
| return -1; |
| |
| if (get_module_type(module) == EXEC_MODULE) { |
| if (!argc || !argv || strcmp(argv[0], name)) { |
| dprintf("invalid args for %s\n", name); |
| res = -1; |
| goto out; |
| } |
| } |
| |
| cur_module = module_current(); |
| if (!strcmp(cur_module->name, module->name)) { |
| dprintf("We is running this module %s already!", module->name); |
| |
| module_unload(cur_module); |
| } |
| |
| res = module_load(module); |
| if (res != 0) { |
| dprintf("failed to load module %s\n", module->name); |
| goto out; |
| } |
| |
| type = get_module_type(module); |
| |
| dprintf("type = %d, prev = %s, cur = %s", |
| type, cur_module->name, module->name); |
| |
| if(type==EXEC_MODULE) |
| { |
| previous = __syslinux_current; |
| //prev_mem_tag = __mem_get_tag_global(); |
| |
| // Setup the new process context |
| __syslinux_current = module; |
| //__mem_set_tag_global((malloc_tag_t)module); |
| |
| // Execute the program |
| ret_val = setjmp(module->u.x.process_exit); |
| |
| if (ret_val) |
| ret_val--; /* Valid range is 0-255 */ |
| else if (!module->main_func) |
| ret_val = -1; |
| else |
| exit((module->main_func)(argc, argv)); /* Actually run! */ |
| |
| // Clean up the allocation context |
| //__free_tagged(module); |
| // Restore the allocation context |
| //__mem_set_tag_global(prev_mem_tag); |
| // Restore the process context |
| __syslinux_current = previous; |
| |
| res = module_unload(module); |
| |
| if (res != 0) |
| goto out; |
| } |
| |
| out: |
| if (res) |
| _module_unload(module); |
| return res; |
| } |
| |
| void exec_term(void) |
| { |
| modules_term(); |
| } |