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