1 /* 2 * exec.c 3 * 4 * Created on: Aug 14, 2008 5 * Author: Stefan Bucur <stefanb (at) zytor.com> 6 */ 7 8 #include <sys/module.h> 9 #include <sys/exec.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <stdarg.h> 14 #include <setjmp.h> 15 #include <setjmp.h> 16 #include <alloca.h> 17 #include <dprintf.h> 18 19 #define DBG_PRINT(fmt, args...) dprintf("[EXEC] " fmt, ##args) 20 21 struct elf_module *__syslinux_current = NULL; 22 23 int get_module_type(struct elf_module *module) 24 { 25 if(module->main_func) return EXEC_MODULE; 26 return LIB_MODULE; 27 } 28 29 jmp_buf __process_exit_jmp; 30 31 #if 0 32 int spawnv(const char *name, const char **argv) 33 { 34 int res, ret_val = 0; 35 const char **arg; 36 int argc; 37 char **argp, **args; 38 struct elf_module *previous; 39 malloc_tag_t prev_mem_tag; 40 41 struct elf_module *module = module_alloc(name); 42 43 if (module == NULL) 44 return -1; 45 46 res = module_load(module); 47 if (res != 0) { 48 module_unload(module); 49 return res; 50 } 51 52 if (module->main_func == NULL) { 53 // We can't execute without a main function 54 module_unload(module); 55 return -1; 56 } 57 /*if (module->main_func != NULL) { 58 const char **last_arg = argv; 59 void *old_tag; 60 while (*last_arg != NULL) 61 last_arg++; 62 63 // Setup the memory allocation context 64 old_tag = __mem_get_tag_global(); 65 __mem_set_tag_global(module); 66 67 // Execute the program 68 ret_val = (*(module->main_func))(last_arg - argv, argv); 69 70 // Clean up the allocation context 71 __free_tagged(module); 72 // Restore the allocation context 73 __mem_set_tag_global(old_tag); 74 } else { 75 // We can't execute without a main function 76 module_unload(module); 77 return -1; 78 }*/ 79 // Set up the process context 80 previous = __syslinux_current; 81 prev_mem_tag = __mem_get_tag_global(); 82 83 // Setup the new process context 84 __syslinux_current = module; 85 __mem_set_tag_global((malloc_tag_t)module); 86 87 // Generate a new process copy of argv (on the stack) 88 argc = 0; 89 for (arg = argv; *arg; arg++) 90 argc++; 91 92 args = alloca((argc+1) * sizeof(char *)); 93 94 for (arg = argv, argp = args; *arg; arg++, argp++) { 95 size_t l = strlen(*arg)+1; 96 *argp = alloca(l); 97 memcpy(*argp, *arg, l); 98 } 99 100 *args = NULL; 101 102 // Execute the program 103 ret_val = setjmp(module->u.x.process_exit); 104 105 if (ret_val) 106 ret_val--; /* Valid range is 0-255 */ 107 else if (!module->main_func) 108 ret_val = -1; 109 else 110 exit((module->main_func)(argc, args)); /* Actually run! */ 111 112 // Clean up the allocation context 113 __free_tagged(module); 114 // Restore the allocation context 115 __mem_set_tag_global(prev_mem_tag); 116 // Restore the process context 117 __syslinux_current = previous; 118 119 res = module_unload(module); 120 121 if (res != 0) { 122 return res; 123 } 124 125 return ((unsigned int)ret_val & 0xFF); 126 } 127 128 int spawnl(const char *name, const char *arg, ...) 129 { 130 /* 131 * NOTE: We assume the standard ABI specification for the i386 132 * architecture. This code may not work if used in other 133 * circumstances, including non-variadic functions, different 134 * architectures and calling conventions. 135 */ 136 return spawnv(name, &arg); 137 } 138 #endif 139 140 /* 141 * Load a module and runs its start function. 142 * 143 * For library modules the start function is module->init_func and for 144 * executable modules its module->main_func. 145 * 146 * "name" is the name of the module to load. 147 * 148 * "argv" and "argc" are only passed to module->main_func, for library 149 * modules these arguments can be NULL and 0, respectively. 150 * 151 * "argv" is an array of arguments to pass to module->main_func. 152 * argv[0] must be a pointer to "name" and argv[argc] must be NULL. 153 * 154 * "argc" is the number of arguments in "argv". 155 */ 156 int spawn_load(const char *name, int argc, char **argv) 157 { 158 int res, ret_val = 0; 159 struct elf_module *previous; 160 //malloc_tag_t prev_mem_tag; 161 struct elf_module *module = module_alloc(name); 162 struct elf_module *cur_module; 163 int type; 164 165 dprintf("enter: name = %s", name); 166 167 if (module == NULL) 168 return -1; 169 170 if (get_module_type(module) == EXEC_MODULE) { 171 if (!argc || !argv || strcmp(argv[0], name)) { 172 dprintf("invalid args for %s\n", name); 173 res = -1; 174 goto out; 175 } 176 } 177 178 cur_module = module_current(); 179 if (!strcmp(cur_module->name, module->name)) { 180 dprintf("We is running this module %s already!", module->name); 181 182 module_unload(cur_module); 183 } 184 185 res = module_load(module); 186 if (res != 0) { 187 dprintf("failed to load module %s\n", module->name); 188 goto out; 189 } 190 191 type = get_module_type(module); 192 193 dprintf("type = %d, prev = %s, cur = %s", 194 type, cur_module->name, module->name); 195 196 if(type==EXEC_MODULE) 197 { 198 previous = __syslinux_current; 199 //prev_mem_tag = __mem_get_tag_global(); 200 201 // Setup the new process context 202 __syslinux_current = module; 203 //__mem_set_tag_global((malloc_tag_t)module); 204 205 // Execute the program 206 ret_val = setjmp(module->u.x.process_exit); 207 208 if (ret_val) 209 ret_val--; /* Valid range is 0-255 */ 210 else if (!module->main_func) 211 ret_val = -1; 212 else 213 exit((module->main_func)(argc, argv)); /* Actually run! */ 214 215 // Clean up the allocation context 216 //__free_tagged(module); 217 // Restore the allocation context 218 //__mem_set_tag_global(prev_mem_tag); 219 // Restore the process context 220 __syslinux_current = previous; 221 222 res = module_unload(module); 223 224 if (res != 0) 225 goto out; 226 } 227 228 out: 229 if (res) 230 _module_unload(module); 231 return res; 232 } 233 234 void exec_term(void) 235 { 236 modules_term(); 237 } 238