4 * Created on: Aug 14, 2008
5 * Author: Stefan Bucur <stefanb@zytor.com>
8 #include <sys/module.h>
19 #define DBG_PRINT(fmt, args...) dprintf("[EXEC] " fmt, ##args)
21 static struct elf_module
*mod_root
= NULL
;
22 struct elf_module
*__syslinux_current
= NULL
;
32 // Load the root module
33 mod_root
= module_alloc(EXEC_ROOT_NAME
);
38 res
= module_load_shallow(mod_root
, 0);
47 int get_module_type(struct elf_module
*module
)
49 if(module
->main_func
) return EXEC_MODULE
;
53 jmp_buf __process_exit_jmp
;
56 int spawnv(const char *name
, const char **argv
)
62 struct elf_module
*previous
;
63 malloc_tag_t prev_mem_tag
;
65 struct elf_module
*module
= module_alloc(name
);
70 res
= module_load(module
);
72 module_unload(module
);
76 if (module
->main_func
== NULL
) {
77 // We can't execute without a main function
78 module_unload(module
);
81 /*if (module->main_func != NULL) {
82 const char **last_arg = argv;
84 while (*last_arg != NULL)
87 // Setup the memory allocation context
88 old_tag = __mem_get_tag_global();
89 __mem_set_tag_global(module);
91 // Execute the program
92 ret_val = (*(module->main_func))(last_arg - argv, argv);
94 // Clean up the allocation context
95 __free_tagged(module);
96 // Restore the allocation context
97 __mem_set_tag_global(old_tag);
99 // We can't execute without a main function
100 module_unload(module);
103 // Set up the process context
104 previous
= __syslinux_current
;
105 prev_mem_tag
= __mem_get_tag_global();
107 // Setup the new process context
108 __syslinux_current
= module
;
109 __mem_set_tag_global((malloc_tag_t
)module
);
111 // Generate a new process copy of argv (on the stack)
113 for (arg
= argv
; *arg
; arg
++)
116 args
= alloca((argc
+1) * sizeof(char *));
118 for (arg
= argv
, argp
= args
; *arg
; arg
++, argp
++) {
119 size_t l
= strlen(*arg
)+1;
121 memcpy(*argp
, *arg
, l
);
126 // Execute the program
127 ret_val
= setjmp(module
->u
.x
.process_exit
);
130 ret_val
--; /* Valid range is 0-255 */
131 else if (!module
->main_func
)
134 exit((module
->main_func
)(argc
, args
)); /* Actually run! */
136 // Clean up the allocation context
137 __free_tagged(module
);
138 // Restore the allocation context
139 __mem_set_tag_global(prev_mem_tag
);
140 // Restore the process context
141 __syslinux_current
= previous
;
143 res
= module_unload(module
);
149 return ((unsigned int)ret_val
& 0xFF);
152 int spawnl(const char *name
, const char *arg
, ...)
155 * NOTE: We assume the standard ABI specification for the i386
156 * architecture. This code may not work if used in other
157 * circumstances, including non-variadic functions, different
158 * architectures and calling conventions.
160 return spawnv(name
, &arg
);
164 struct elf_module
*cur_module
;
167 * Load a module and runs its start function.
169 * For library modules the start function is module->init_func and for
170 * executable modules its module->main_func.
172 * "name" is the name of the module to load.
174 * "argv" and "argc" are only passed to module->main_func, for library
175 * modules these arguments can be NULL and 0, respectively.
177 * "argv" is an array of arguments to pass to module->main_func.
178 * argv[0] must be a pointer to "name" and argv[argc] must be NULL.
180 * "argc" is the number of arguments in "argv".
182 int spawn_load(const char *name
, int argc
, char **argv
)
184 int res
, ret_val
= 0;
185 struct elf_module
*previous
;
186 //malloc_tag_t prev_mem_tag;
187 struct elf_module
*module
= module_alloc(name
);
188 struct elf_module
*prev_module
;
191 dprintf("enter: name = %s", name
);
196 if (get_module_type(module
) == EXEC_MODULE
) {
197 if (!argc
|| !argv
|| strcmp(argv
[0], name
)) {
203 if (!strcmp(cur_module
->name
, module
->name
)) {
204 dprintf("We is running this module %s already!", module
->name
);
207 * If we're already running the module and it's of
208 * type EXEC_MODULE, then just return. We don't reload
209 * the module because that might cause us to re-run
210 * the init functions, which will cause us to run the
211 * main function, which will take control of this
214 * This can happen if some other EXEC_MODULE is
215 * resolving a symbol that is exported by the current
218 if (get_module_type(module
) == EXEC_MODULE
)
222 res
= module_load(module
);
226 type
= get_module_type(module
);
227 prev_module
= cur_module
;
230 dprintf("type = %d, prev = %s, cur = %s",
231 type
, prev_module
->name
, cur_module
->name
);
233 if(type
==EXEC_MODULE
)
235 previous
= __syslinux_current
;
236 //prev_mem_tag = __mem_get_tag_global();
238 // Setup the new process context
239 __syslinux_current
= module
;
240 //__mem_set_tag_global((malloc_tag_t)module);
242 // Execute the program
243 ret_val
= setjmp(module
->u
.x
.process_exit
);
246 ret_val
--; /* Valid range is 0-255 */
247 else if (!module
->main_func
)
250 exit((module
->main_func
)(argc
, argv
)); /* Actually run! */
252 // Clean up the allocation context
253 //__free_tagged(module);
254 // Restore the allocation context
255 //__mem_set_tag_global(prev_mem_tag);
256 // Restore the process context
257 __syslinux_current
= previous
;
259 cur_module
= prev_module
;
260 res
= module_unload(module
);
268 _module_unload(module
);