aboutsummaryrefslogtreecommitdiffstats
path: root/com32/elflink/ldlinux/execute.c
diff options
context:
space:
mode:
Diffstat (limited to 'com32/elflink/ldlinux/execute.c')
-rw-r--r--com32/elflink/ldlinux/execute.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/com32/elflink/ldlinux/execute.c b/com32/elflink/ldlinux/execute.c
new file mode 100644
index 00000000..f67d707b
--- /dev/null
+++ b/com32/elflink/ldlinux/execute.c
@@ -0,0 +1,171 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston MA 02110-1301, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <dprintf.h>
+
+#include <com32.h>
+#include <sys/exec.h>
+#include "core.h"
+#include "core-elf.h"
+
+/* Must match enum kernel_type */
+const char *const kernel_types[] = {
+ "none",
+ "localboot",
+ "kernel",
+ "linux",
+ "boot",
+ "bss",
+ "pxe",
+ "fdimage",
+ "comboot",
+ "com32",
+ "config",
+ NULL
+};
+
+static inline int my_isspace(char c)
+{
+ return (unsigned char)c <= ' ';
+}
+
+void execute(const char *cmdline, enum kernel_type type)
+{
+ const char *p, *const *pp;
+ const char *kernel, *args;
+ com32sys_t ireg;
+ char *q;
+
+ memset(&ireg, 0, sizeof ireg);
+
+ /* for parameter will be passed to __intcall, we need use
+ * lmalloc a block of low memory */
+ q = lmalloc(128);
+ if (!q) {
+ printf("%s(): Fail to lmalloc a buffer to exec %s\n",
+ __func__, cmdline);
+ return;
+ }
+
+ kernel = q;
+ p = cmdline;
+ while (*p && !my_isspace(*p))
+ *q++ = *p++;
+ *q++ = '\0';
+
+ args = q;
+ while (*p && my_isspace(*p))
+ p++;
+
+ strcpy(q, p);
+
+ dprintf("kernel is %s, args = %s type = %d \n", kernel, args, type);
+
+ if (kernel[0] == '.' && type == KT_NONE) {
+ /* It might be a type specifier */
+ enum kernel_type type = KT_NONE;
+ for (pp = kernel_types; *pp; pp++, type++) {
+ if (!strcmp(kernel + 1, *pp))
+ execute(p, type); /* Strip the type specifier and retry */
+ }
+ }
+
+ if (type == KT_COM32) {
+ /* new entry for elf format c32 */
+ 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, 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 */
+ char *spawn_load_param[2] = { args, NULL };
+ module_load_dependencies("ui.c32", "modules.dep");
+ spawn_load(kernel, 1, spawn_load_param);
+ } else {
+ /* process the image need int 22 support */
+ if (type == KT_LOCALBOOT) {
+ ireg.eax.w[0] = 0x0014; /* Local boot */
+ ireg.edx.w[0] = strtoul(kernel, NULL, 0);
+ }
+ ireg.eax.w[0] = 0x0016; /* Run kernel image */
+ ireg.esi.w[0] = OFFS(kernel);
+ ireg.ds = SEG(kernel);
+ ireg.ebx.w[0] = OFFS(args);
+ ireg.es = SEG(args);
+ ireg.edx.l = type - KT_KERNEL;
+ /* ireg.ecx.l = 0; *//* We do ipappend "manually" */
+
+ __intcall(0x22, &ireg, NULL);
+ }
+
+ lfree(kernel);
+
+ /* If this returns, something went bad; return to menu */
+}