• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
4  *   Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
5  *
6  *   Permission is hereby granted, free of charge, to any person
7  *   obtaining a copy of this software and associated documentation
8  *   files (the "Software"), to deal in the Software without
9  *   restriction, including without limitation the rights to use,
10  *   copy, modify, merge, publish, distribute, sublicense, and/or
11  *   sell copies of the Software, and to permit persons to whom
12  *   the Software is furnished to do so, subject to the following
13  *   conditions:
14  *
15  *   The above copyright notice and this permission notice shall
16  *   be included in all copies or substantial portions of the Software.
17  *
18  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  *   OTHER DEALINGS IN THE SOFTWARE.
26  *
27  * ----------------------------------------------------------------------- */
28 
29 /*
30  * mboot.c
31  *
32  * Module to load a multiboot kernel
33  */
34 
35 #include "mboot.h"
36 
37 struct multiboot_info mbinfo;
38 struct syslinux_pm_regs regs;
39 struct my_options opt, set;
40 
41 struct module_data {
42     void *data;
43     size_t len;
44     const char *cmdline;
45 };
46 
map_modules(struct module_data * modules,int nmodules)47 static int map_modules(struct module_data *modules, int nmodules)
48 {
49     struct mod_list *mod_list;
50     addr_t map_list = 0;
51     size_t list_size = nmodules * sizeof *mod_list;
52     int i;
53 
54     mod_list = malloc(list_size);
55     if (!mod_list) {
56 	printf("Failed to allocate module list\n");
57 	return -1;
58     }
59 
60     map_list = map_data(mod_list, list_size, 16, 0);
61     if (!map_list) {
62 	printf("Cannot map module list\n");
63 	return -1;
64     }
65 
66     for (i = 0; i < nmodules; i++) {
67 	addr_t mod_map = 0;
68 	addr_t cmd_map = 0;
69 
70 	dprintf("Module %d cmdline: \"%s\"\n", i, modules[i].cmdline);
71 
72 	cmd_map = map_string(modules[i].cmdline);
73 
74 	mod_map = map_data(modules[i].data, modules[i].len, 4096, MAP_HIGH);
75 	if (!mod_map) {
76 	    printf("Failed to map module (memory fragmentation issue?)\n");
77 	    return -1;
78 	}
79 	mod_list[i].mod_start = mod_map;
80 	mod_list[i].mod_end = mod_map + modules[i].len;
81 	mod_list[i].cmdline = cmd_map;
82 	mod_list[i].pad = 0;
83     }
84 
85     mbinfo.flags |= MB_INFO_MODS;
86     mbinfo.mods_count = nmodules;
87     mbinfo.mods_addr = map_list;
88     return 0;
89 }
90 
get_modules(char ** argv,struct module_data ** mdp)91 static int get_modules(char **argv, struct module_data **mdp)
92 {
93     char **argp, **argx;
94     struct module_data *mp;
95     int rv;
96     int module_count = 1;
97     int arglen;
98     const char module_separator[] = "---";
99 
100     for (argp = argv; *argp; argp++) {
101 	if (!strcmp(*argp, module_separator))
102 	    module_count++;
103     }
104 
105     *mdp = mp = malloc(module_count * sizeof(struct module_data));
106     if (!mp) {
107 	error("Out of memory!\n");
108 	return -1;
109     }
110 
111     argp = argv;
112     while (*argp) {
113 	/* Note: it seems Grub transparently decompresses all compressed files,
114 	   not just the primary kernel. */
115 	printf("Loading %s... ", *argp);
116 	rv = zloadfile(*argp, &mp->data, &mp->len);
117 
118 	if (rv) {
119 	    printf("failed!\n");
120 	    return -1;
121 	}
122 	printf("ok\n");
123 
124 	/*
125 	 * Note: Grub includes the kernel filename in the command line, so we
126 	 * want to match that behavior.
127 	 */
128 	arglen = 0;
129 	for (argx = argp; *argx && strcmp(*argx, module_separator); argx++)
130 	    arglen += strlen(*argx) + 1;
131 
132 	if (arglen == 0) {
133 	    mp->cmdline = strdup("");
134 	} else {
135 	    char *p;
136 	    mp->cmdline = p = malloc(arglen);
137 	    for (; *argp && strcmp(*argp, module_separator); argp++) {
138 		p = stpcpy(p, *argp);
139 		*p++ = ' ';
140 	    }
141 	    *--p = '\0';
142 	}
143 	mp++;
144 	if (*argp)
145 	    argp++;		/* Advance past module_separator */
146     }
147 
148     return module_count;
149 }
150 
main(int argc,char * argv[])151 int main(int argc, char *argv[])
152 {
153     int nmodules;
154     struct module_data *modules;
155     struct multiboot_header *mbh;
156     bool keeppxe = false;
157 
158     openconsole(&dev_null_r, &dev_stdcon_w);
159 
160     (void)argc;			/* Unused */
161     argv++;
162 
163     while (*argv) {
164 	bool v = true;
165 	const char *p = *argv;
166 
167 	if (!memcmp(p, "-no", 3)) {
168 	    v = false;
169 	    p += 3;
170 	}
171 
172 	if (!strcmp(p, "-solaris")) {
173 	    opt.solaris = v;
174 	    set.solaris = true;
175 	} else if (!strcmp(p, "-aout")) {
176 	    opt.aout = v;
177 	    set.aout = true;
178 	} else
179 	    break;
180 	argv++;
181     }
182 
183     if (!*argv) {
184 	error
185 	    ("Usage: mboot.c32 [opts] mboot_file args... [--- module args...]...\n"
186 	     "Options:\n"
187 	     "  -solaris  Enable Solaris DHCP information passing\n"
188 	     "  -aout     Use the \"a.out kludge\" if enabled, even for ELF\n"
189 	     "            This matches the Multiboot spec, but differs from Grub\n");
190 	return 1;
191     }
192 
193     /* Load the files */
194     nmodules = get_modules(argv, &modules);
195     if (nmodules < 1) {
196 	error("No files found!\n");
197 	return 1;		/* Failure */
198     }
199 
200     if (init_map())
201 	return 1;		/* Failed to allocate initial map */
202 
203     /*
204      * Map the primary image.  This should be done before mapping anything
205      * else, since it will have fixed address requirements.
206      */
207     mbh = map_image(modules[0].data, modules[0].len);
208     if (!mbh)
209 	return 1;
210 
211     /* Map the mbinfo structure */
212     regs.ebx = map_data(&mbinfo, sizeof mbinfo, 4, 0);
213     if (!regs.ebx) {
214 	error("Failed to map Multiboot info structure!\n");
215 	return 1;
216     }
217 
218     /* Map the primary command line */
219     if (modules[0].cmdline) {
220 	mbinfo.cmdline = map_string(modules[0].cmdline);
221 	dprintf("Main cmdline: \"%s\"\n", modules[0].cmdline);
222 	if (mbinfo.cmdline)
223 	    mbinfo.flags |= MB_INFO_CMDLINE;
224     }
225 
226     /* Map auxilliary images */
227     if (nmodules > 1) {
228 	if (map_modules(modules + 1, nmodules - 1))
229 	    return 1;
230     }
231 
232     /* Add auxilliary information */
233     mboot_make_memmap();
234     mboot_apm();
235     mboot_syslinux_info();
236 
237     if (opt.solaris)
238 	mboot_solaris_dhcp_hack();
239 
240     /* Set the graphics mode if requested */
241     set_graphics_mode(mbh, &mbinfo);
242 
243     /* Run it */
244     mboot_run(keeppxe ? 3 : 0);
245     error("mboot.c32: boot failed\n");
246     return 1;
247 }
248