source: bootcd/isolinux/syslinux-6.03/com32/mboot/mboot.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 6.2 KB
Line 
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
37struct multiboot_info mbinfo;
38struct syslinux_pm_regs regs;
39struct my_options opt, set;
40
41struct module_data {
42    void *data;
43    size_t len;
44    const char *cmdline;
45};
46
47static 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
91static 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
151int 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}
Note: See TracBrowser for help on using the repository browser.