source: bootcd/isolinux/syslinux-6.03/com32/elflink/ldlinux/ldlinux.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.5 KB
RevLine 
[e16e8f2]1#include <linux/list.h>
2#include <sys/times.h>
3#include <fcntl.h>
4#include <stdbool.h>
5#include <string.h>
6#include <core.h>
7#include <fs.h>
8#include "cli.h"
9#include "console.h"
10#include "com32.h"
11#include "menu.h"
12#include "config.h"
13#include "syslinux/adv.h"
14#include "syslinux/boot.h"
15#include "syslinux/config.h"
16
17#include <sys/module.h>
18
19struct file_ext {
20        const char *name;
21        enum kernel_type type;
22};
23
24static const struct file_ext file_extensions[] = {
25        { ".c32", IMAGE_TYPE_COM32 },
26        { ".img", IMAGE_TYPE_FDIMAGE },
27        { ".bss", IMAGE_TYPE_BSS },
28        { ".bin", IMAGE_TYPE_BOOT },
29        { ".bs", IMAGE_TYPE_BOOT },
30        { ".0", IMAGE_TYPE_PXE },
31        { NULL, 0 },
32};
33
34/*
35 * Return a pointer to one byte after the last character of the
36 * command.
37 */
38static inline const char *find_command(const char *str)
39{
40        const char *p;
41
42        p = str;
43        while (*p && !my_isspace(*p))
44                p++;
45        return p;
46}
47
48__export uint32_t parse_image_type(const char *kernel)
49{
50        const struct file_ext *ext;
51        const char *p;
52        int len;
53
54        /* Find the end of the command */
55        p = find_command(kernel);
56        len = p - kernel;
57
58        for (ext = file_extensions; ext->name; ext++) {
59                int elen = strlen(ext->name);
60
61                if (!strncmp(kernel + len - elen, ext->name, elen))
62                        return ext->type;
63        }
64
65        /* use IMAGE_TYPE_KERNEL as default */
66        return IMAGE_TYPE_KERNEL;
67}
68
69/*
70 * Returns the kernel name with file extension if one wasn't present.
71 */
72static const char *get_extension(const char *kernel)
73{
74        const struct file_ext *ext;
75        const char *p;
76        int len;
77
78        /* Find the end of the command */
79        p = find_command(kernel);
80        len = p - kernel;
81
82        for (ext = file_extensions; ext->name; ext++) {
83                char *str;
84                int elen = strlen(ext->name);
85                FILE *f;
86
87                str = malloc(len + elen + 1);
88
89                strncpy(str, kernel, len);
90                strncpy(str + len, ext->name, elen);
91                str[len + elen] = '\0';
92                f = findpath(str);
93                free(str);
94
95                if (f) {
96                        fclose(f);
97                        return ext->name;
98                }
99        }
100
101        return NULL;
102}
103
104const char *apply_extension(const char *kernel, const char *ext)
105{
106        const char *p;
107        char *k;
108        int len = strlen(kernel);
109        int elen = strlen(ext);
110
111        k = malloc(len + elen + 1);
112        if (!k)
113                return NULL;
114
115        p = find_command(kernel);
116
117        len = p - kernel;
118
119        /* Copy just the kernel name */
120        memcpy(k, kernel, len);
121
122        /* Append the extension */
123        if (strncmp(p - elen, ext, elen)) {
124                memcpy(k + len, ext, elen);
125                len += elen;
126        }
127
128        /* Copy the rest of the command line */
129        strcpy(k + len, p);
130
131        k[len + strlen(p)] = '\0';
132
133        return k;
134}
135
136/*
137 * Attempt to load a kernel after deciding what type of image it is.
138 *
139 * We only return from this function if something went wrong loading
140 * the the kernel. If we return the caller should call enter_cmdline()
141 * so that the user can help us out.
142 */
143__export void load_kernel(const char *command_line)
144{
145        struct menu_entry *me;
146        const char *cmdline;
147        const char *kernel;
148        uint32_t type;
149
150        kernel = strdup(command_line);
151        if (!kernel)
152                goto bad_kernel;
153
154        /* Virtual kernel? */
155        me = find_label(kernel);
156        if (me) {
157                const char *args;
158                char *cmd;
159                size_t len = strlen(me->cmdline) + 1;
160
161                /* Find the end of the command */
162                args = find_command(kernel);
163                while(*args && my_isspace(*args))
164                        args++;
165
166                if (strlen(args))
167                        len += strlen(args) + 1; /* +1 for space (' ') */
168
169                cmd = malloc(len);
170                if (!cmd)
171                        goto bad_kernel;
172
173                if (strlen(args))
174                        snprintf(cmd, len, "%s %s", me->cmdline, args);
175                else
176                        strncpy(cmd, me->cmdline, len);
177
178                type = parse_image_type(cmd);
179                execute(cmd, type, false);
180                /* We shouldn't return */
181                goto bad_kernel;
182        }
183
184        if (!allowimplicit)
185                goto bad_implicit;
186
187        /* Insert a null character to ignore any user-specified options */
188        if (!allowoptions) {
189                char *p = (char *)find_command(kernel);
190                *p = '\0';
191        }
192
193        type = parse_image_type(kernel);
194        if (type == IMAGE_TYPE_KERNEL) {
195                const char *ext;
196
197                /*
198                 * Automatically lookup the extension if one wasn't
199                 * supplied by the user.
200                 */
201                ext = get_extension(kernel);
202                if (ext) {
203                        const char *k;
204
205                        k = apply_extension(kernel, ext);
206                        if (!k)
207                                goto bad_kernel;
208
209                        free((void *)kernel);
210                        kernel = k;
211
212                        type = parse_image_type(kernel);
213                }
214        }
215
216        execute(kernel, type, true);
217        free((void *)kernel);
218
219bad_implicit:
220bad_kernel:
221        /*
222         * If we fail to boot the kernel execute the "onerror" command
223         * line.
224         */
225        if (onerrorlen) {
226                me = find_label(onerror);
227                if (me)
228                        rsprintf(&cmdline, "%s %s", me->cmdline, default_cmd);
229                else
230                        rsprintf(&cmdline, "%s %s", onerror, default_cmd);
231
232                type = parse_image_type(cmdline);
233                execute(cmdline, type, true);
234        }
235}
236
237/*
238 * If this function returns you must call ldinux_enter_command() to
239 * preserve the 4.0x behaviour.
240 */
241void ldlinux_auto_boot(void)
242{
243        if (!defaultlevel) {
244                if (strlen(ConfigName))
245                        printf("No DEFAULT or UI configuration directive found!\n");
246                if (noescape)
247                        kaboom();
248        } else
249                load_kernel(default_cmd);
250}
251
252static void enter_cmdline(void)
253{
254        const char *cmdline;
255
256        /* Enter endless command line prompt, should support "exit" */
257        while (1) {
258                bool to = false;
259
260                if (noescape) {
261                        ldlinux_auto_boot();
262                        continue;
263                }
264
265                cmdline = edit_cmdline("boot:", 1, NULL, cat_help_file, &to);
266                printf("\n");
267
268                /* return if user only press enter or we timed out */
269                if (!cmdline || cmdline[0] == '\0') {
270                        if (to && ontimeoutlen)
271                                load_kernel(ontimeout);
272                        else
273                                ldlinux_auto_boot();
274                } else
275                        load_kernel(cmdline);
276        }
277}
278
279void ldlinux_enter_command(void)
280{
281        enter_cmdline();
282}
283
284/*
285 * Undo the work we did in openconsole().
286 */
287static void __destructor close_console(void)
288{
289        int i;
290
291        for (i = 0; i <= 2; i++)
292                close(i);
293}
294
295void ldlinux_console_init(void)
296{
297        openconsole(&dev_stdcon_r, &dev_ansiserial_w);
298}
299
300__export int main(int argc __unused, char **argv)
301{
302        const void *adv;
303        const char *cmdline;
304        size_t count = 0;
305
306        ldlinux_console_init();
307
308        parse_configs(&argv[1]);
309
310        __syslinux_set_serial_console_info();
311
312        adv = syslinux_getadv(ADV_BOOTONCE, &count);
313        if (adv && count) {
314                /*
315                 * We apparently have a boot-once set; clear it and
316                 * then execute the boot-once.
317                 */
318                char *src, *dst;
319                size_t i;
320
321                src = (char *)adv;
322                cmdline = dst = malloc(count + 1);
323                if (!dst) {
324                        printf("Failed to allocate memory for ADV\n");
325                        ldlinux_enter_command();
326                }
327
328                for (i = 0; i < count; i++)
329                        *dst++ = *src++;
330                *dst = '\0';    /* Null-terminate */
331
332                /* Clear the boot-once data from the ADV */
333                if (!syslinux_setadv(ADV_BOOTONCE, 0, NULL))
334                        syslinux_adv_write();
335
336                load_kernel(cmdline); /* Shouldn't return */
337                ldlinux_enter_command();
338        }
339
340        if (!forceprompt && !shift_is_held())
341                ldlinux_auto_boot();
342
343        if (defaultlevel > 1)
344                ldlinux_auto_boot();
345
346        ldlinux_enter_command();
347        return 0;
348}
Note: See TracBrowser for help on using the repository browser.