elflink: Move more code from core/ into ldlinux
authorMatt Fleming <matt.fleming@linux.intel.com>
Fri, 8 Apr 2011 12:21:51 +0000 (13:21 +0100)
committerMatt Fleming <matt.fleming@linux.intel.com>
Tue, 26 Apr 2011 08:53:31 +0000 (09:53 +0100)
ldlinux now contains all the code necessary to load and execute
modules, none is contained in the core.

This change also allows us to change the spawn_load() prototype and to
push the job of processing arguments to executable functions (e.g. the
contents of char *argv[] as passed to a module's main function) into
ldlinux/execute.c instead of doing it in spawn_load(). Moving it into
ldlinux/ makes sense because the only core user of spawn_load() is
load_env32() and we don't require any sort of argument processing in
that path.

Signed-off-by: Matt Fleming <matt.fleming@linux.intel.com>
com32/elflink/ldlinux/Makefile
com32/elflink/ldlinux/execute.c [moved from core/elflink/execute.c with 73% similarity]
com32/elflink/ldlinux/kernel.c [moved from core/elflink/kernel.c with 100% similarity]
com32/include/sys/exec.h
com32/lib/sys/module/exec.c
core/elflink/load_env32.c

index 6fbe1b1..09aa4af 100644 (file)
@@ -19,7 +19,7 @@ CFLAGS += -I../modules -I$(topdir)/core/elflink -I$(topdir)/core/include
 all: ldlinux.c32
 
 ldlinux.c32 : ldlinux.o cli.o readconfig.o refstr.o colors.o getadv.o \
-               adv.o ipappend.o
+               adv.o ipappend.o execute.o kernel.o
        $(LD) $(LDFLAGS) -o $@ $^
 
 tidy dist:
similarity index 73%
rename from core/elflink/execute.c
rename to com32/elflink/ldlinux/execute.c
index 7e70323..f67d707 100644 (file)
@@ -43,13 +43,10 @@ static inline int my_isspace(char c)
 
 void execute(const char *cmdline, enum kernel_type type)
 {
-       com32sys_t ireg;
        const char *p, *const *pp;
-       char *q;
        const char *kernel, *args;
-
-       /* work around for spawn_load parameter */
-       char *spawn_load_param[2] = { NULL, NULL};
+       com32sys_t ireg;
+       char *q;
 
        memset(&ireg, 0, sizeof ireg);
 
@@ -87,18 +84,70 @@ void execute(const char *cmdline, enum kernel_type type)
 
        if (type == KT_COM32) {
                /* new entry for elf format c32 */
-               spawn_load_param[0] = args;
+               char **argv;
+               int i, argc;
+
+               q = args;
+               for (argc = 0; *q; q++) {
+                       argc++;
+
+                       /* Find the end of this arg */
+                       while(*q && !my_isspace(*q))
+                               q++;
+
+                       /*
+                        * Now skip all whitespace between arguments.
+                        */
+                       while (*q && my_isspace(*q))
+                               q++;
+               }
+
+               /*
+                * Generate a copy of argv on the stack as this is
+                * traditionally where process arguments go.
+                *
+                * argv[0] must be the command name, so bump argc to
+                * include argv[0].
+                */
+               argc += 1;
+               argv = alloca(argc * sizeof(char *));
+               argv[0] = kernel;
+
+               for (q = args, i = 1; i < argc - 1; i++) {
+                       char *start;
+                       int len = 0;
+
+                       start = q;
+
+                       /* Find the end of this arg */
+                       while(*q && !my_isspace(*q)) {
+                               q++;
+                               len++;
+                       }
+
+                       argv[i] = malloc(len + 1);
+                       strncpy(argv[i], start, len);
+                       argv[i][len] = '\0';
+
+                       /*
+                        * Now skip all whitespace between arguments.
+                        */
+                       while (*q && my_isspace(*q))
+                               q++;
+               }
+
+               argv[argc] = NULL;
                module_load_dependencies(kernel, "modules.dep");
-               spawn_load(kernel, spawn_load_param);
+               spawn_load(kernel, argc, argv);
        } else if (type <= KT_KERNEL) {
                /* Need add one item for kernel load, as we don't use
                * the assembly runkernel.inc any more */
                new_linux_kernel(kernel, cmdline);
        } else if (type == KT_CONFIG) {
                /* kernel contains the config file name */
-               spawn_load_param[0] = args;
+               char *spawn_load_param[2] = { args, NULL };
                module_load_dependencies("ui.c32", "modules.dep");
-               spawn_load(kernel, spawn_load_param);
+               spawn_load(kernel, 1, spawn_load_param);
        } else {
                /* process the image need int 22 support */
                if (type == KT_LOCALBOOT) {
index 31b62be..656f8e2 100644 (file)
@@ -33,6 +33,7 @@
  * spawn_load - Load a library module or executes an executable one
  * @name       the name of the library/executable to use, including the extension
  *                     (e.g. 'sort.c32')
+ * @argc:      the number of string arguments in @argv
  * @argv:      a NULL-terminated vector of string arguments, starting with
  *                     the program name.
  *
@@ -40,7 +41,7 @@
  * kind of module it is ( executable or library ), after which is performs the
  * appropriate action, either spawning or simply loading the module into memory.
  */
-extern int spawn_load(const char *name,const char **argv);
+extern int spawn_load(const char *name, int argc, char **argv);
 
 extern int module_load_dependencies(const char*name,const char*dep_file);
 
index 78df72e..1ed3263 100644 (file)
@@ -220,12 +220,25 @@ int spawnl(const char *name, const char *arg, ...)
 
 struct elf_module *cur_module;
 
-int spawn_load(const char *name,const char **argv)
+/*
+ * Load a module and runs its start function.
+ *
+ * For library modules the start function is module->init_func and for
+ * executable modules its module->main_func.
+ *
+ * "name" is the name of the module to load.
+ *
+ * "argv" and "argc" are only passed to module->main_func, for library
+ * modules these arguments can be NULL and 0, respectively.
+ *
+ * "argv" is an array of arguments to pass to module->main_func.
+ * argv[0] must be a pointer to "name" and argv[argc] must be NULL.
+ *
+ * "argc" is the number of arguments in "argv".
+ */
+int spawn_load(const char *name, int argc, char **argv)
 {
        int res, ret_val = 0;
-       const char **arg;
-       int argc;
-       char **argp, **args;
        struct elf_module *previous;
        //malloc_tag_t prev_mem_tag;
        struct elf_module *module = module_alloc(name);
@@ -238,6 +251,11 @@ int spawn_load(const char *name,const char **argv)
        if (module == NULL)
                return -1;
 
+       if (get_module_type(module) == EXEC_MODULE) {
+               if (!argc || !argv || strcmp(argv[0], name))
+                       return -1;
+       }
+
        if (!strcmp(cur_module->name, module->name)) {
                dprintf("We is running this module %s already!", module->name);
 
@@ -295,21 +313,6 @@ int spawn_load(const char *name,const char **argv)
                __syslinux_current = module;
                //__mem_set_tag_global((malloc_tag_t)module);
 
-               // Generate a new process copy of argv (on the stack)
-               argc = 0;
-               for (arg = argv; *arg; arg++)
-                       argc++;
-
-               args = alloca((argc+1) * sizeof(char *));
-
-               for (arg = argv, argp = args; *arg; arg++, argp++) {
-                       size_t l = strlen(*arg)+1;
-                       *argp = alloca(l);
-                       memcpy(*argp, *arg, l);
-               }
-
-               *args = NULL;
-
                // Execute the program
                ret_val = setjmp(module->u.x.process_exit);
 
@@ -318,7 +321,7 @@ int spawn_load(const char *name,const char **argv)
                else if (!module->main_func)
                        ret_val = -1;
                else
-                       exit((module->main_func)(argc, args)); /* Actually run! */
+                       exit((module->main_func)(argc, argv)); /* Actually run! */
 
 
                // Clean up the allocation context
@@ -468,13 +471,13 @@ int module_load_dependencies(const char *name,const char *dep_file)
                i++;    /* skip a space */
 
                if (strlen(temp_name)) {
-                       char *argv[2] = { NULL, NULL };
+                       char *argv[2] = { temp_name, NULL };
                        int ret;
 
                        ret = module_load_dependencies(temp_name,
                                                       MODULES_DEP);
                        if (!ret) {
-                               if (spawn_load(temp_name, argv) < 0)
+                               if (spawn_load(temp_name, 1, argv) < 0)
                                        continue;
                        }
                }
index 501f267..8a71634 100644 (file)
@@ -18,6 +18,8 @@
 #include "menu.h"
 #include "core-elf.h"
 
+#define LDLINUX        "ldlinux.c32"
+
 typedef void (*constructor_t) (void);
 constructor_t __ctors_start[], __ctors_end[];
 
@@ -68,10 +70,13 @@ static void call_constr(void)
 /* note to self: do _*NOT*_ use static key word on this function */
 void load_env32(com32sys_t * regs)
 {
+       char *argv[] = { LDLINUX, NULL };
+
        dprintf("Starting 32 bit elf module subsystem...\n");
        call_constr();
 
        init_module_subsystem(&core_module);
 
-       execute("ldlinux.c32", KT_COM32);
+       module_load_dependencies(LDLINUX, "modules.dep");
+       spawn_load(LDLINUX, 1, argv);
 }