Home | History | Annotate | Download | only in ldlinux
      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