[e16e8f2] | 1 | /* ----------------------------------------------------------------------- * |
---|
| 2 | * |
---|
| 3 | * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved |
---|
| 4 | * |
---|
| 5 | * This program is free software; you can redistribute it and/or modify |
---|
| 6 | * it under the terms of the GNU General Public License as published by |
---|
| 7 | * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
---|
| 8 | * Boston MA 02110-1301, USA; either version 2 of the License, or |
---|
| 9 | * (at your option) any later version; incorporated herein by reference. |
---|
| 10 | * |
---|
| 11 | * ----------------------------------------------------------------------- */ |
---|
| 12 | |
---|
| 13 | #include <stdlib.h> |
---|
| 14 | #include <string.h> |
---|
| 15 | #include <stdio.h> |
---|
| 16 | #include <dprintf.h> |
---|
| 17 | |
---|
| 18 | #include <com32.h> |
---|
| 19 | #include <sys/exec.h> |
---|
| 20 | #include <sys/io.h> |
---|
| 21 | #include <sys/module.h> |
---|
| 22 | #include "core.h" |
---|
| 23 | #include "menu.h" |
---|
| 24 | #include "fs.h" |
---|
| 25 | #include "config.h" |
---|
| 26 | #include "localboot.h" |
---|
| 27 | #include "bios.h" |
---|
| 28 | |
---|
| 29 | #include <syslinux/bootrm.h> |
---|
| 30 | #include <syslinux/movebits.h> |
---|
| 31 | #include <syslinux/config.h> |
---|
| 32 | #include <syslinux/boot.h> |
---|
| 33 | |
---|
| 34 | const struct image_types image_boot_types[] = { |
---|
| 35 | { "localboot", IMAGE_TYPE_LOCALBOOT }, |
---|
| 36 | { "kernel", IMAGE_TYPE_KERNEL }, |
---|
| 37 | { "linux", IMAGE_TYPE_LINUX }, |
---|
| 38 | { "boot", IMAGE_TYPE_BOOT }, |
---|
| 39 | { "bss", IMAGE_TYPE_BSS }, |
---|
| 40 | { "pxe", IMAGE_TYPE_PXE }, |
---|
| 41 | { "fdimage", IMAGE_TYPE_FDIMAGE }, |
---|
| 42 | { "com32", IMAGE_TYPE_COM32 }, |
---|
| 43 | { "config", IMAGE_TYPE_CONFIG }, |
---|
| 44 | { NULL, 0 }, |
---|
| 45 | }; |
---|
| 46 | |
---|
| 47 | extern int create_args_and_load(char *); |
---|
| 48 | |
---|
| 49 | __export void execute(const char *cmdline, uint32_t type, bool sysappend) |
---|
| 50 | { |
---|
| 51 | const char *kernel, *args; |
---|
| 52 | const char *p; |
---|
| 53 | com32sys_t ireg; |
---|
| 54 | char *q, ch; |
---|
| 55 | |
---|
| 56 | memset(&ireg, 0, sizeof ireg); |
---|
| 57 | |
---|
| 58 | if (strlen(cmdline) >= MAX_CMDLINE_LEN) { |
---|
| 59 | printf("cmdline too long\n"); |
---|
| 60 | return; |
---|
| 61 | } |
---|
| 62 | |
---|
| 63 | q = malloc(MAX_CMDLINE_LEN); |
---|
| 64 | if (!q) { |
---|
| 65 | printf("%s(): Fail to malloc a buffer to exec %s\n", |
---|
| 66 | __func__, cmdline); |
---|
| 67 | return; |
---|
| 68 | } |
---|
| 69 | |
---|
| 70 | kernel = q; |
---|
| 71 | p = cmdline; |
---|
| 72 | while (*p && !my_isspace(*p)) |
---|
| 73 | *q++ = *p++; |
---|
| 74 | *q++ = '\0'; |
---|
| 75 | |
---|
| 76 | args = q; |
---|
| 77 | while (*p && my_isspace(*p)) |
---|
| 78 | p++; |
---|
| 79 | |
---|
| 80 | do { |
---|
| 81 | *q++ = ch = *p++; |
---|
| 82 | } while (ch); |
---|
| 83 | |
---|
| 84 | if (sysappend) { |
---|
| 85 | /* If we've seen some args, insert a space */ |
---|
| 86 | if (--q != args) |
---|
| 87 | *q++ = ' '; |
---|
| 88 | |
---|
| 89 | do_sysappend(q); |
---|
| 90 | } |
---|
| 91 | |
---|
| 92 | dprintf("kernel is %s, args = %s type = %d \n", kernel, args, type); |
---|
| 93 | |
---|
| 94 | if (kernel[0] == '.') { |
---|
| 95 | /* It might be a type specifier */ |
---|
| 96 | const struct image_types *t; |
---|
| 97 | for (t = image_boot_types; t->name; t++) { |
---|
| 98 | if (!strcmp(kernel + 1, t->name)) { |
---|
| 99 | /* |
---|
| 100 | * Strip the type specifier, apply the |
---|
| 101 | * filename extension if COM32 and |
---|
| 102 | * retry. |
---|
| 103 | */ |
---|
| 104 | p = args; |
---|
| 105 | if (t->type == IMAGE_TYPE_COM32) { |
---|
| 106 | p = apply_extension(p, ".c32"); |
---|
| 107 | if (!p) |
---|
| 108 | return; |
---|
| 109 | } |
---|
| 110 | |
---|
| 111 | execute(p, t->type, sysappend); |
---|
| 112 | return; |
---|
| 113 | } |
---|
| 114 | } |
---|
| 115 | } |
---|
| 116 | |
---|
| 117 | if (type == IMAGE_TYPE_COM32) { |
---|
| 118 | /* |
---|
| 119 | * We may be called with the console in an unknown |
---|
| 120 | * state, so initialise it. |
---|
| 121 | */ |
---|
| 122 | ldlinux_console_init(); |
---|
| 123 | |
---|
| 124 | /* new entry for elf format c32 */ |
---|
| 125 | if (create_args_and_load((char *)cmdline)) |
---|
| 126 | printf("Failed to load COM32 file %s\n", kernel); |
---|
| 127 | |
---|
| 128 | /* |
---|
| 129 | * The old COM32 module code would run the module then |
---|
| 130 | * drop the user back at the command prompt, |
---|
| 131 | * irrespective of how the COM32 module was loaded, |
---|
| 132 | * e.g. from vesamenu.c32. |
---|
| 133 | */ |
---|
| 134 | unload_modules_since(LDLINUX); |
---|
| 135 | |
---|
| 136 | /* Restore the console */ |
---|
| 137 | ldlinux_console_init(); |
---|
| 138 | |
---|
| 139 | ldlinux_enter_command(); |
---|
| 140 | } else if (type == IMAGE_TYPE_CONFIG) { |
---|
| 141 | char *argv[] = { LDLINUX, NULL, NULL }; |
---|
| 142 | char *config; |
---|
| 143 | int rv; |
---|
| 144 | |
---|
| 145 | /* kernel contains the config file name */ |
---|
| 146 | config = malloc(FILENAME_MAX); |
---|
| 147 | if (!config) |
---|
| 148 | goto out; |
---|
| 149 | |
---|
| 150 | realpath(config, kernel, FILENAME_MAX); |
---|
| 151 | |
---|
| 152 | /* If we got anything on the command line, do a chdir */ |
---|
| 153 | if (*args) |
---|
| 154 | mangle_name(config_cwd, args); |
---|
| 155 | |
---|
| 156 | argv[1] = config; |
---|
| 157 | rv = start_ldlinux(2, argv); |
---|
| 158 | printf("Failed to exec %s: %s\n", LDLINUX, strerror(rv)); |
---|
| 159 | } else if (type == IMAGE_TYPE_LOCALBOOT) { |
---|
| 160 | local_boot(strtoul(kernel, NULL, 0)); |
---|
| 161 | } else if (type == IMAGE_TYPE_PXE || type == IMAGE_TYPE_BSS || |
---|
| 162 | type == IMAGE_TYPE_BOOT) { |
---|
| 163 | chainboot_file(kernel, type); |
---|
| 164 | } else { |
---|
| 165 | /* Need add one item for kernel load, as we don't use |
---|
| 166 | * the assembly runkernel.inc any more */ |
---|
| 167 | new_linux_kernel((char *)kernel, (char *)args); |
---|
| 168 | } |
---|
| 169 | |
---|
| 170 | out: |
---|
| 171 | free((void *)kernel); |
---|
| 172 | |
---|
| 173 | /* If this returns, something went bad; return to menu */ |
---|
| 174 | } |
---|