Home | History | Annotate | Download | only in module
      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