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