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 } 175