1 #include <linux/list.h>
13 #include "syslinux/adv.h"
14 #include "syslinux/boot.h"
15 #include "syslinux/config.h"
17 #include <sys/module.h>
21 enum kernel_type type
;
24 static 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
},
34 jmp_buf __return_to_command_prompt
;
37 * Return a pointer to one byte after the last character of the
40 static inline const char *find_command(const char *str
)
45 while (*p
&& !my_isspace(*p
))
50 __export
uint32_t parse_image_type(const char *kernel
)
52 const struct file_ext
*ext
;
56 /* Find the end of the command */
57 p
= find_command(kernel
);
60 for (ext
= file_extensions
; ext
->name
; ext
++) {
61 int elen
= strlen(ext
->name
);
63 if (!strncmp(kernel
+ len
- elen
, ext
->name
, elen
))
67 /* use IMAGE_TYPE_KERNEL as default */
68 return IMAGE_TYPE_KERNEL
;
72 * Returns the kernel name with file extension if one wasn't present.
74 static const char *get_extension(const char *kernel
)
76 const struct file_ext
*ext
;
80 /* Find the end of the command */
81 p
= find_command(kernel
);
84 for (ext
= file_extensions
; ext
->name
; ext
++) {
86 int elen
= strlen(ext
->name
);
89 str
= malloc(len
+ elen
+ 1);
91 strncpy(str
, kernel
, len
);
92 strncpy(str
+ len
, ext
->name
, elen
);
93 str
[len
+ elen
] = '\0';
106 const char *apply_extension(const char *kernel
, const char *ext
)
110 int len
= strlen(kernel
);
111 int elen
= strlen(ext
);
113 k
= malloc(len
+ elen
+ 1);
117 p
= find_command(kernel
);
121 /* Copy just the kernel name */
122 memcpy(k
, kernel
, len
);
124 /* Append the extension */
125 if (strncmp(p
- elen
, ext
, elen
)) {
126 memcpy(k
+ len
, ext
, elen
);
130 /* Copy the rest of the command line */
133 k
[len
+ strlen(p
)] = '\0';
139 * Attempt to load a kernel after deciding what type of image it is.
141 * We only return from this function if something went wrong loading
142 * the the kernel. If we return the caller should call enter_cmdline()
143 * so that the user can help us out.
145 __export
void load_kernel(const char *command_line
)
147 struct menu_entry
*me
;
152 kernel
= strdup(command_line
);
156 /* Virtual kernel? */
157 me
= find_label(kernel
);
161 size_t len
= strlen(me
->cmdline
) + 1;
163 /* Find the end of the command */
164 args
= find_command(kernel
);
165 while(*args
&& my_isspace(*args
))
169 len
+= strlen(args
) + 1; /* +1 for space (' ') */
176 snprintf(cmd
, len
, "%s %s", me
->cmdline
, args
);
178 strncpy(cmd
, me
->cmdline
, len
);
180 type
= parse_image_type(cmd
);
181 execute(cmd
, type
, false);
182 /* We shouldn't return */
189 /* Insert a null character to ignore any user-specified options */
191 char *p
= (char *)find_command(kernel
);
195 type
= parse_image_type(kernel
);
196 if (type
== IMAGE_TYPE_KERNEL
) {
200 * Automatically lookup the extension if one wasn't
201 * supplied by the user.
203 ext
= get_extension(kernel
);
207 k
= apply_extension(kernel
, ext
);
211 free((void *)kernel
);
214 type
= parse_image_type(kernel
);
218 execute(kernel
, type
, true);
219 free((void *)kernel
);
224 * If we fail to boot the kernel execute the "onerror" command
228 me
= find_label(onerror
);
230 rsprintf(&cmdline
, "%s %s", me
->cmdline
, default_cmd
);
232 rsprintf(&cmdline
, "%s %s", onerror
, default_cmd
);
234 type
= parse_image_type(cmdline
);
235 execute(cmdline
, type
, true);
240 * If this function returns you must call ldinux_enter_command() to
241 * preserve the 4.0x behaviour.
243 void ldlinux_auto_boot(void)
246 if (strlen(ConfigName
))
247 printf("No DEFAULT or UI configuration directive found!\n");
251 load_kernel(default_cmd
);
254 static void enter_cmdline(void)
258 /* Enter endless command line prompt, should support "exit" */
267 cmdline
= edit_cmdline("boot:", 1, NULL
, cat_help_file
, &to
);
270 /* return if user only press enter or we timed out */
271 if (!cmdline
|| cmdline
[0] == '\0') {
272 if (to
&& ontimeoutlen
)
273 load_kernel(ontimeout
);
277 load_kernel(cmdline
);
281 void ldlinux_enter_command(void)
287 * Undo the work we did in openconsole().
289 static void __destructor
close_console(void)
293 for (i
= 0; i
<= 2; i
++)
297 void ldlinux_console_init(void)
299 openconsole(&dev_stdcon_r
, &dev_ansiserial_w
);
302 __export
int main(int argc __unused
, char **argv
)
309 ldlinux_console_init();
311 parse_configs(&argv
[1]);
313 __syslinux_set_serial_console_info();
315 adv
= syslinux_getadv(ADV_BOOTONCE
, &count
);
318 * We apparently have a boot-once set; clear it and
319 * then execute the boot-once.
325 cmdline
= dst
= malloc(count
+ 1);
327 printf("Failed to allocate memory for ADV\n");
328 ldlinux_enter_command();
331 for (i
= 0; i
< count
; i
++)
333 *dst
= '\0'; /* Null-terminate */
335 /* Clear the boot-once data from the ADV */
336 if (!syslinux_setadv(ADV_BOOTONCE
, 0, NULL
))
337 syslinux_adv_write();
340 * The corresponding longjmp is located in the execute function
341 * after a COM32 module has returned.
343 retval
= setjmp(__return_to_command_prompt
);
345 load_kernel(cmdline
); /* Shouldn't return */
347 retval
= setjmp(__return_to_command_prompt
);
349 if (!forceprompt
&& !shift_is_held())
352 if (defaultlevel
> 1)
357 retval
= setjmp(__return_to_command_prompt
);
358 ldlinux_enter_command();