• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * exec.c
3  *
4  *  Created on: Aug 14, 2008
5  *      Author: Stefan Bucur <stefanb@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 
get_module_type(struct elf_module * module)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  */
spawn_load(const char * name,int argc,char ** argv)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 
exec_term(void)234 void exec_term(void)
235 {
236 	modules_term();
237 }
238