2
* GRUB -- GRand Unified Bootloader
3
* Copyright (C) 2013 Free Software Foundation, Inc.
5
* GRUB 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, either version 3 of the License, or
8
* (at your option) any later version.
10
* GRUB is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20
#include <grub/file.h>
21
#include <grub/normal.h>
22
#include <grub/syslinux_parse.h>
26
struct syslinux_say *next;
27
struct syslinux_say *prev;
33
struct initrd_list *next;
37
struct syslinux_menuentry
39
struct syslinux_menuentry *next;
40
struct syslinux_menuentry *prev;
44
struct initrd_list *initrds;
45
struct initrd_list *initrds_last;
50
grub_size_t commentslen;
53
struct syslinux_say *say;
55
enum { KERNEL_NO_KERNEL, KERNEL_LINUX, KERNEL_CHAINLOADER,
56
KERNEL_BIN, KERNEL_PXE, KERNEL_CHAINLOADER_BPB,
57
KERNEL_COM32, KERNEL_COM, KERNEL_IMG, KERNEL_CONFIG, LOCALBOOT }
63
struct syslinux_menu *parent;
64
struct syslinux_menuentry *entries;
68
const char *root_read_directory;
69
const char *root_target_directory;
70
const char *current_read_directory;
71
const char *current_target_directory;
73
grub_size_t commentslen;
74
unsigned long timeout;
75
struct syslinux_say *say;
76
grub_syslinux_flavour_t flavour;
87
syslinux_parse_real (struct syslinux_menu *menu);
89
config_file (struct output_buffer *outbuf,
90
const char *root, const char *target_root,
91
const char *cwd, const char *target_cwd,
92
const char *fname, struct syslinux_menu *parent,
93
grub_syslinux_flavour_t flav);
95
print_entry (struct output_buffer *outbuf,
96
struct syslinux_menu *menu,
100
ensure_space (struct output_buffer *outbuf, grub_size_t len)
104
if (len < outbuf->alloc - outbuf->ptr)
105
return GRUB_ERR_NONE;
106
newlen = (outbuf->ptr + len + 10) * 2;
107
newbuf = grub_realloc (outbuf->buf, newlen);
110
outbuf->alloc = newlen;
111
outbuf->buf = newbuf;
112
return GRUB_ERR_NONE;
116
print (struct output_buffer *outbuf, const char *str, grub_size_t len)
119
err = ensure_space (outbuf, len);
122
grub_memcpy (&outbuf->buf[outbuf->ptr], str, len);
124
return GRUB_ERR_NONE;
128
add_comment (struct syslinux_menu *menu, const char *comment, int nl)
132
if (menu->entries->commentslen == 0 && *comment == 0)
133
return GRUB_ERR_NONE;
134
menu->entries->comments = grub_realloc (menu->entries->comments,
135
menu->entries->commentslen
136
+ 2 + grub_strlen (comment));
137
if (!menu->entries->comments)
139
menu->entries->commentslen
140
+= grub_stpcpy (menu->entries->comments + menu->entries->commentslen,
142
- (menu->entries->comments + menu->entries->commentslen);
144
menu->entries->comments[menu->entries->commentslen++] = '\n';
145
menu->entries->comments[menu->entries->commentslen] = '\0';
149
if (menu->commentslen == 0 && *comment == 0)
150
return GRUB_ERR_NONE;
151
menu->comments = grub_realloc (menu->comments, menu->commentslen
152
+ 2 + grub_strlen (comment));
155
menu->commentslen += grub_stpcpy (menu->comments + menu->commentslen,
157
- (menu->comments + menu->commentslen);
159
menu->comments[menu->commentslen++] = '\n';
160
menu->comments[menu->commentslen] = '\0';
162
return GRUB_ERR_NONE;
166
#define print_string(x) do { err = print (outbuf, x, sizeof (x) - 1); if (err) return err; } while (0)
169
print_num (struct output_buffer *outbuf, int n)
172
grub_snprintf (buf, sizeof (buf), "%d", n);
173
return print (outbuf, buf, grub_strlen (buf));
177
label (const char *line, struct syslinux_menu *menu)
179
struct syslinux_menuentry *entry;
181
entry = grub_malloc (sizeof (*entry));
184
grub_memset (entry, 0, sizeof (*entry));
185
entry->label = grub_strdup (line);
191
entry->next = menu->entries;
194
menu->entries->prev = entry;
195
menu->entries = entry;
196
return GRUB_ERR_NONE;
200
kernel (const char *line, struct syslinux_menu *menu)
202
const char *end = line + grub_strlen (line);
205
return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
207
menu->entries->kernel_file = grub_strdup (line);
208
if (!menu->entries->kernel_file)
211
menu->entries->entry_type = KERNEL_LINUX;
213
if (end - line >= 2 && grub_strcmp (end - 2, ".0") == 0)
214
menu->entries->entry_type = KERNEL_PXE;
216
if (end - line >= 4 && grub_strcasecmp (end - 4, ".bin") == 0)
217
menu->entries->entry_type = KERNEL_BIN;
219
if (end - line >= 3 && grub_strcasecmp (end - 3, ".bs") == 0)
220
menu->entries->entry_type = KERNEL_CHAINLOADER;
222
if (end - line >= 4 && grub_strcasecmp (end - 4, ".bss") == 0)
223
menu->entries->entry_type = KERNEL_CHAINLOADER_BPB;
225
if (end - line >= 4 && grub_strcasecmp (end - 4, ".c32") == 0)
226
menu->entries->entry_type = KERNEL_COM32;
228
if (end - line >= 4 && grub_strcasecmp (end - 4, ".cbt") == 0)
229
menu->entries->entry_type = KERNEL_COM;
231
if (end - line >= 4 && grub_strcasecmp (end - 4, ".com") == 0)
232
menu->entries->entry_type = KERNEL_COM;
234
if (end - line >= 4 && grub_strcasecmp (end - 4, ".img") == 0)
235
menu->entries->entry_type = KERNEL_IMG;
237
return GRUB_ERR_NONE;
241
cmd_linux (const char *line, struct syslinux_menu *menu)
244
return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
246
menu->entries->kernel_file = grub_strdup (line);
247
if (!menu->entries->kernel_file)
249
menu->entries->entry_type = KERNEL_LINUX;
251
return GRUB_ERR_NONE;
255
cmd_boot (const char *line, struct syslinux_menu *menu)
258
return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
260
menu->entries->kernel_file = grub_strdup (line);
261
if (!menu->entries->kernel_file)
263
menu->entries->entry_type = KERNEL_CHAINLOADER;
265
return GRUB_ERR_NONE;
269
cmd_bss (const char *line, struct syslinux_menu *menu)
272
return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
274
menu->entries->kernel_file = grub_strdup (line);
275
if (!menu->entries->kernel_file)
277
menu->entries->entry_type = KERNEL_CHAINLOADER_BPB;
279
return GRUB_ERR_NONE;
283
cmd_pxe (const char *line, struct syslinux_menu *menu)
286
return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
288
menu->entries->kernel_file = grub_strdup (line);
289
if (!menu->entries->kernel_file)
291
menu->entries->entry_type = KERNEL_PXE;
293
return GRUB_ERR_NONE;
297
cmd_fdimage (const char *line, struct syslinux_menu *menu)
300
return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
302
menu->entries->kernel_file = grub_strdup (line);
303
if (!menu->entries->kernel_file)
305
menu->entries->entry_type = KERNEL_IMG;
307
return GRUB_ERR_NONE;
311
cmd_comboot (const char *line, struct syslinux_menu *menu)
314
return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
316
menu->entries->kernel_file = grub_strdup (line);
317
if (!menu->entries->kernel_file)
319
menu->entries->entry_type = KERNEL_COM;
321
return GRUB_ERR_NONE;
325
cmd_com32 (const char *line, struct syslinux_menu *menu)
328
return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
330
menu->entries->kernel_file = grub_strdup (line);
331
if (!menu->entries->kernel_file)
333
menu->entries->entry_type = KERNEL_COM32;
335
return GRUB_ERR_NONE;
339
cmd_config (const char *line, struct syslinux_menu *menu)
343
return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
345
for (space = line; *space && !grub_isspace (*space); space++);
346
menu->entries->kernel_file = grub_strndup (line, space - line);
347
if (!menu->entries->kernel_file)
349
for (; *space && grub_isspace (*space); space++);
352
menu->entries->argument = grub_strdup (space);
353
if (!menu->entries->argument)
356
menu->entries->entry_type = KERNEL_CONFIG;
358
return GRUB_ERR_NONE;
362
cmd_append (const char *line, struct syslinux_menu *menu)
365
return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
367
menu->entries->append = grub_strdup (line);
368
if (!menu->entries->append)
371
return GRUB_ERR_NONE;
375
cmd_initrd (const char *line, struct syslinux_menu *menu)
377
struct initrd_list *ninitrd;
380
return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
384
for (comma = line; *comma && *comma != ','; comma++);
386
ninitrd = grub_malloc (sizeof (*ninitrd));
389
ninitrd->file = grub_strndup (line, comma - line);
395
ninitrd->next = NULL;
396
if (menu->entries->initrds_last)
397
menu->entries->initrds_last->next = ninitrd;
400
menu->entries->initrds_last = ninitrd;
401
menu->entries->initrds = ninitrd;
409
return GRUB_ERR_NONE;
413
cmd_default (const char *line, struct syslinux_menu *menu)
415
menu->def = grub_strdup (line);
419
return GRUB_ERR_NONE;
423
cmd_timeout (const char *line, struct syslinux_menu *menu)
425
menu->timeout = grub_strtoul (line, NULL, 0);
427
return GRUB_ERR_NONE;
431
cmd_menudefault (const char *line __attribute__ ((unused)),
432
struct syslinux_menu *menu)
435
return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
437
menu->entries->make_default = 1;
438
return GRUB_ERR_NONE;
442
cmd_menubackground (const char *line,
443
struct syslinux_menu *menu)
445
menu->background = grub_strdup (line);
446
return GRUB_ERR_NONE;
450
cmd_localboot (const char *line,
451
struct syslinux_menu *menu)
454
return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
456
menu->entries->kernel_file = grub_strdup (line);
457
if (!menu->entries->kernel_file)
459
menu->entries->entry_type = LOCALBOOT;
461
return GRUB_ERR_NONE;
465
cmd_extlabel (const char *line, struct syslinux_menu *menu)
471
return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
473
menu->entries->extlabel = grub_malloc (grub_strlen (line) + 1);
474
if (!menu->entries->extlabel)
477
out = menu->entries->extlabel;
480
if (in[0] == '^' && in[1])
482
menu->entries->hotkey = grub_tolower (in[1]);
489
return GRUB_ERR_NONE;
494
cmd_say (const char *line, struct syslinux_menu *menu)
496
struct syslinux_say *nsay;
497
nsay = grub_malloc (sizeof (*nsay) + grub_strlen (line) + 1);
503
nsay->next = menu->entries->say;
504
menu->entries->say = nsay;
508
nsay->next = menu->say;
513
nsay->next->prev = nsay;
515
grub_memcpy (nsay->msg, line, grub_strlen (line) + 1);
516
return GRUB_ERR_NONE;
520
get_read_filename (struct syslinux_menu *menu,
521
const char *filename)
523
return grub_xasprintf ("%s/%s",
524
filename[0] == '/' ? menu->root_read_directory
525
: menu->current_read_directory, filename);
529
get_target_filename (struct syslinux_menu *menu,
530
const char *filename)
532
return grub_xasprintf ("%s/%s",
533
filename[0] == '/' ? menu->root_target_directory
534
: menu->current_target_directory, filename);
538
syslinux_parse (const char *filename,
539
struct syslinux_menu *menu)
541
const char *old_filename = menu->filename;
544
nf = get_read_filename (menu, filename);
548
ret = syslinux_parse_real (menu);
549
if (ret == GRUB_ERR_FILE_NOT_FOUND
550
|| ret == GRUB_ERR_BAD_FILENAME)
552
grub_errno = ret = GRUB_ERR_NONE;
553
add_comment (menu, "# File ", 0);
554
add_comment (menu, nf, 0);
555
add_comment (menu, " not found", 1);
558
menu->filename = old_filename;
566
grub_err_t (*parse) (const char *line, struct syslinux_menu *menu);
568
/* FIXME: support tagname. */
569
{"include", NULL, syslinux_parse},
570
{"menu", "include", syslinux_parse},
571
{"label", NULL, label},
572
{"kernel", NULL, kernel},
573
{"linux", NULL, cmd_linux},
574
{"boot", NULL, cmd_boot},
575
{"bss", NULL, cmd_bss},
576
{"pxe", NULL, cmd_pxe},
577
{"fdimage", NULL, cmd_fdimage},
578
{"comboot", NULL, cmd_comboot},
579
{"com32", NULL, cmd_com32},
580
{"config", NULL, cmd_config},
581
{"append", NULL, cmd_append},
582
/* FIXME: ipappend not supported. */
583
{"localboot", NULL, cmd_localboot},
584
{"initrd", NULL, cmd_initrd},
585
{"default", NULL, cmd_default},
586
{"menu", "label", cmd_extlabel},
587
/* FIXME: MENU LABEL not supported. */
588
/* FIXME: MENU HIDDEN not supported. */
589
/* FIXME: MENU SEPARATOR not supported. */
590
/* FIXME: MENU INDENT not supported. */
591
/* FIXME: MENU DISABLE not supported. */
592
/* FIXME: MENU HIDE not supported. */
593
{"menu", "default", cmd_menudefault},
594
/* FIXME: MENU PASSWD not supported. */
595
/* FIXME: MENU MASTER PASSWD not supported. */
596
{"menu", "background", cmd_menubackground},
597
/* FIXME: MENU BEGIN not supported. */
598
/* FIXME: MENU GOTO not supported. */
599
/* FIXME: MENU EXIT not supported. */
600
/* FIXME: MENU QUIT not supported. */
601
/* FIXME: MENU START not supported. */
602
/* FIXME: MENU AUTOBOOT not supported. */
603
/* FIXME: MENU TABMSG not supported. */
604
/* FIXME: MENU NOTABMSG not supported. */
605
/* FIXME: MENU PASSPROMPT not supported. */
606
/* FIXME: MENU COLOR not supported. */
607
/* FIXME: MENU MSGCOLOR not supported. */
608
/* FIXME: MENU WIDTH not supported. */
609
/* FIXME: MENU MARGIN not supported. */
610
/* FIXME: MENU PASSWORDMARGIN not supported. */
611
/* FIXME: MENU ROWS not supported. */
612
/* FIXME: MENU TABMSGROW not supported. */
613
/* FIXME: MENU CMDLINEROW not supported. */
614
/* FIXME: MENU ENDROW not supported. */
615
/* FIXME: MENU PASSWORDROW not supported. */
616
/* FIXME: MENU TIMEOUTROW not supported. */
617
/* FIXME: MENU HELPMSGROW not supported. */
618
/* FIXME: MENU HELPMSGENDROW not supported. */
619
/* FIXME: MENU HIDDENROW not supported. */
620
/* FIXME: MENU HSHIFT not supported. */
621
/* FIXME: MENU VSHIFT not supported. */
622
{"timeout", NULL, cmd_timeout},
623
/* FIXME: TOTALTIMEOUT not supported. */
624
/* FIXME: ONTIMEOUT not supported. */
625
/* FIXME: ONERROR not supported. */
626
/* FIXME: SERIAL not supported. */
627
/* FIXME: CONSOLE not supported. */
628
/* FIXME: FONT not supported. */
629
/* FIXME: KBDMAP not supported. */
630
{"say", NULL, cmd_say},
631
/* FIXME: DISPLAY not supported. */
632
/* FIXME: F* not supported. */
634
/* Commands to control interface behaviour which aren't needed with GRUB.
635
If they are important in your environment please contact GRUB team.
637
{"prompt", NULL, NULL},
638
{"nocomplete", NULL, NULL},
639
{"noescape", NULL, NULL},
640
{"implicit", NULL, NULL},
641
{"allowoptions", NULL, NULL}
645
helptext (const char *line, grub_file_t file, struct syslinux_menu *menu)
649
grub_size_t helplen, alloclen = 0;
651
help = grub_strdup (line);
652
helplen = grub_strlen (line);
653
while ((grub_free (buf), buf = grub_file_getline (file)))
657
for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++);
658
if (grub_strncasecmp (ptr, "endtext", sizeof ("endtext") - 1) == 0)
660
ptr += sizeof ("endtext") - 1;
661
for (; *ptr && (grub_isspace (*ptr) || *ptr == '\n' || *ptr == '\r');
665
menu->entries->help = help;
667
return GRUB_ERR_NONE;
670
needlen = helplen + 1 + grub_strlen (buf);
671
if (alloclen < needlen)
673
alloclen = 2 * needlen;
674
help = grub_realloc (help, alloclen);
681
helplen += grub_stpcpy (help + helplen, buf) - (help + helplen);
690
syslinux_parse_real (struct syslinux_menu *menu)
694
grub_err_t err = GRUB_ERR_NONE;
696
file = grub_file_open (menu->filename);
699
while ((grub_free (buf), buf = grub_file_getline (file)))
701
const char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
704
end = buf + grub_strlen (buf);
705
while (end > buf && (end[-1] == '\n' || end[-1] == '\r'))
708
for (ptr1 = buf; *ptr1 && grub_isspace (*ptr1); ptr1++);
709
if (*ptr1 == '#' || *ptr1 == 0)
711
err = add_comment (menu, ptr1, 1);
716
for (ptr2 = ptr1; !grub_isspace (*ptr2) && *ptr2; ptr2++);
717
for (ptr3 = ptr2; grub_isspace (*ptr3) && *ptr3; ptr3++);
718
for (ptr4 = ptr3; !grub_isspace (*ptr4) && *ptr4; ptr4++);
719
for (ptr5 = ptr4; grub_isspace (*ptr5) && *ptr5; ptr5++);
720
for (i = 0; i < sizeof (commands) / sizeof (commands[0]); i++)
721
if (grub_strlen (commands[i].name1) == (grub_size_t) (ptr2 - ptr1)
722
&& grub_strncasecmp (commands[i].name1, ptr1, ptr2 - ptr1) == 0
723
&& (commands[i].name2 == NULL
724
|| (grub_strlen (commands[i].name2)
725
== (grub_size_t) (ptr4 - ptr3)
726
&& grub_strncasecmp (commands[i].name2, ptr3, ptr4 - ptr3)
729
if (i == sizeof (commands) / sizeof (commands[0]))
731
if (sizeof ("text") - 1 == ptr2 - ptr1
732
&& grub_strncasecmp ("text", ptr1, ptr2 - ptr1) == 0
733
&& (sizeof ("help") - 1 == ptr4 - ptr3
734
&& grub_strncasecmp ("help", ptr3, ptr4 - ptr3) == 0))
736
if (helptext (ptr5, file, menu))
741
add_comment (menu, " # UNSUPPORTED command '", 0);
742
add_comment (menu, ptr1, 0);
743
add_comment (menu, "'", 1);
747
if (commands[i].parse)
749
err = commands[i].parse (commands[i].name2
750
? ptr5 : ptr3, menu);
756
grub_file_close (file);
761
print_escaped (struct output_buffer *outbuf,
762
const char *from, const char *to)
767
to = from + grub_strlen (from);
768
err = ensure_space (outbuf, (to - from) * 4 + 2);
771
outbuf->buf[outbuf->ptr++] = '\'';
772
for (ptr = from; *ptr; ptr++)
776
outbuf->buf[outbuf->ptr++] = '\'';
777
outbuf->buf[outbuf->ptr++] = '\\';
778
outbuf->buf[outbuf->ptr++] = '\'';
779
outbuf->buf[outbuf->ptr++] = '\'';
782
outbuf->buf[outbuf->ptr++] = *ptr;
784
outbuf->buf[outbuf->ptr++] = '\'';
785
return GRUB_ERR_NONE;
789
print_file (struct output_buffer *outbuf,
790
struct syslinux_menu *menu, const char *from, const char *to)
794
to = from + grub_strlen (from);
795
err = print_escaped (outbuf, from[0] == '/'
796
? menu->root_target_directory
797
: menu->current_target_directory, NULL);
801
err = print (outbuf, "/", 1);
804
return print_escaped (outbuf, from, to);
808
simplify_filename (char *str)
810
char *iptr, *optr = str;
811
for (iptr = str; *iptr; iptr++)
813
if (*iptr == '/' && optr != str && optr[-1] == '/')
815
if (iptr[0] == '/' && iptr[1] == '.' && iptr[2] == '/')
820
if (iptr[0] == '/' && iptr[1] == '.' && iptr[2] == '.'
824
while (optr >= str && *optr != '/')
840
write_entry (struct output_buffer *outbuf,
841
struct syslinux_menu *menu,
842
struct syslinux_menuentry *curentry)
845
if (curentry->comments)
846
print (outbuf, curentry->comments, grub_strlen (curentry->comments));
848
struct syslinux_say *say;
849
for (say = curentry->say; say && say->next; say = say->next);
850
for (; say && say->prev; say = say->prev)
852
print_string ("echo ");
853
if (print_escaped (outbuf, say->msg, NULL)) return grub_errno;
858
/* FIXME: support help text. */
859
switch (curentry->entry_type)
866
for (ptr = curentry->append; ptr && *ptr; ptr++)
867
if ((ptr == curentry->append || grub_isspace (ptr[-1]))
868
&& grub_strncasecmp (ptr, "initrd=", sizeof ("initrd=") - 1)
874
grub_size_t totlen = grub_strlen (curentry->append);
875
initrd = ptr + sizeof ("initrd=") - 1;
876
for (ptr2 = ptr; *ptr2 && !grub_isspace (*ptr2); ptr2++);
882
cmdline = grub_malloc (totlen + 1 - (ptr2 - ptr));
885
grub_memcpy (cmdline, curentry->append, ptr - curentry->append);
886
grub_memcpy (cmdline + (ptr - curentry->append),
887
ptr2, totlen - (ptr2 - curentry->append));
888
*(cmdline + totlen - (ptr2 - ptr)) = 0;
891
cmdline = curentry->append;
892
print_string (" if test x$grub_platform = xpc; then "
893
"linux_suffix=16; else linux_suffix= ; fi\n");
894
print_string (" linux$linux_suffix ");
895
print_file (outbuf, menu, curentry->kernel_file, NULL);
898
print (outbuf, cmdline, grub_strlen (cmdline));
900
if (initrd || curentry->initrds)
902
struct initrd_list *lst;
903
print_string (" initrd$linux_suffix ");
906
print_file (outbuf, menu, initrd, NULL);
909
for (lst = curentry->initrds; lst; lst = lst->next)
911
print_file (outbuf, menu, lst->file, NULL);
919
case KERNEL_CHAINLOADER:
920
print_string (" chainloader ");
921
print_file (outbuf, menu, curentry->kernel_file, NULL);
924
case KERNEL_CHAINLOADER_BPB:
925
print_string (" chainloader --bpb ");
926
print_file (outbuf, menu, curentry->kernel_file, NULL);
930
/* FIXME: support -1. */
931
/* FIXME: PXELINUX. */
933
int n = grub_strtol (curentry->kernel_file, NULL, 0);
934
if (n >= 0 && n <= 0x02)
936
print_string (" root=fd");
937
if (print_num (outbuf, n))
939
print_string (";\n chainloader +1;\n");
943
if (n >= 0x80 && n < 0x8a)
945
print_string (" root=hd");
946
if (print_num (outbuf, n - 0x80))
948
print_string (";\n chainloader +1;\n");
951
print_string (" # UNSUPPORTED localboot type ");
952
if (print_num (outbuf, n))
960
char *basename = NULL;
964
for (ptr = curentry->kernel_file; *ptr; ptr++)
965
if (*ptr == '/' || *ptr == '\\')
969
basename = curentry->kernel_file;
972
if (grub_strcasecmp (basename, "chain.c32") == 0)
975
int is_fd = -1, devn = 0;
979
for (ptr = curentry->append; *ptr; )
981
while (grub_isspace (*ptr))
983
/* FIXME: support mbr: and boot. */
984
if (ptr[0] == 'h' && ptr[1] == 'd')
987
devn = grub_strtoul (ptr + 2, &ptr, 0);
990
if (grub_strncasecmp (ptr, "file=", 5) == 0)
993
for (ptr = file; *ptr && !grub_isspace (*ptr); ptr++);
1001
if (grub_strncasecmp (ptr, "swap", sizeof ("swap") - 1) == 0)
1004
ptr += sizeof ("swap") - 1;
1008
if (ptr[0] == 'f' && ptr[1] == 'd')
1011
devn = grub_strtoul (ptr + 2, &ptr, 0);
1014
if (grub_isdigit (ptr[0]))
1016
part = grub_strtoul (ptr, &ptr, 0);
1019
/* FIXME: isolinux, ntldr, cmldr, *dos, seg, hide
1020
FIXME: sethidden. */
1021
print_string (" # UNSUPPORTED option ");
1022
if (print (outbuf, ptr, grub_strlen (ptr)))
1024
print_string ("\n");
1029
print_string (" # no drive specified\n");
1034
print_string (is_fd ? " root=fd": " root=hd");
1035
if (print_num (outbuf, devn))
1040
if (print_num (outbuf, part + 1))
1043
print_string (";\n");
1046
print_string (" chainloader ");
1047
print_file (outbuf, menu, file, NULL);
1048
print_string (";\n");
1051
print_string (" chainloader +1;\n");
1053
print_string (" drivemap -s hd0 \"root\";\n");
1058
if (grub_strcasecmp (basename, "mboot.c32") == 0)
1063
for (ptr = curentry->append; *ptr; )
1066
while (*ptr && !grub_isspace (*ptr))
1068
if (ptrr + 2 == ptr && ptrr[0] == '-' && ptrr[1] == '-')
1070
print_string ("\n");
1077
print_string (" multiboot ");
1079
print_string (" module ");
1082
if (print_file (outbuf, menu, ptrr, ptr))
1086
if (print_escaped (outbuf, ptrr, ptr))
1092
if (grub_strcasecmp (basename, "ifcpu64.c32") == 0)
1094
char *lm, *lme, *pae = 0, *paee = 0, *i386s = 0, *i386e = 0;
1096
ptr = curentry->append;
1097
while (grub_isspace (*ptr))
1100
while (*ptr && !grub_isspace (*ptr))
1103
while (grub_isspace (*ptr))
1105
if (ptr[0] == '-' && ptr[1] == '-')
1108
while (grub_isspace (*ptr))
1111
while (*ptr && !grub_isspace (*ptr))
1115
while (grub_isspace (*ptr))
1117
if (ptr[0] == '-' && ptr[1] == '-')
1120
while (grub_isspace (*ptr))
1123
while (*ptr && !grub_isspace (*ptr))
1138
print_string ("if cpuid --long-mode; then true;\n");
1139
if (print_entry (outbuf, menu, lm))
1143
print_string ("elif cpuid --pae; then true;\n");
1144
if (print_entry (outbuf, menu, pae))
1147
print_string ("else\n");
1148
if (print_entry (outbuf, menu, i386s))
1150
print_string ("fi\n");
1154
if (grub_strcasecmp (basename, "reboot.c32") == 0)
1156
print_string (" reboot\n");
1160
if (grub_strcasecmp (basename, "poweroff.com") == 0)
1162
print_string (" halt\n");
1166
if (grub_strcasecmp (basename, "whichsys.c32") == 0)
1168
grub_syslinux_flavour_t flavour = GRUB_SYSLINUX_ISOLINUX;
1169
const char *flav[] =
1171
[GRUB_SYSLINUX_ISOLINUX] = "iso",
1172
[GRUB_SYSLINUX_PXELINUX] = "pxe",
1173
[GRUB_SYSLINUX_SYSLINUX] = "sys"
1176
for (ptr = curentry->append; *ptr; )
1179
while (grub_isspace (*ptr))
1181
if (grub_strncasecmp (ptr, "-iso-", 5) == 0)
1183
ptr += sizeof ("-iso-") - 1;
1184
flavour = GRUB_SYSLINUX_ISOLINUX;
1187
if (grub_strncasecmp (ptr, "-pxe-", 5) == 0)
1189
ptr += sizeof ("-pxe-") - 1;
1190
flavour = GRUB_SYSLINUX_PXELINUX;
1193
if (grub_strncasecmp (ptr, "-sys-", 5) == 0)
1195
ptr += sizeof ("-sys-") - 1;
1196
flavour = GRUB_SYSLINUX_SYSLINUX;
1200
while (*ptr && !grub_isspace (*ptr))
1204
if (menu->flavour == GRUB_SYSLINUX_UNKNOWN
1205
&& flavour == GRUB_SYSLINUX_ISOLINUX)
1207
print_string ("if [ x$syslinux_flavour = xiso -o x$syslinux_flavour = x ]; then true;\n");
1208
menu->flavour = GRUB_SYSLINUX_ISOLINUX;
1209
print_entry (outbuf, menu, bptr);
1210
menu->flavour = GRUB_SYSLINUX_UNKNOWN;
1211
print_string ("fi\n");
1213
else if (menu->flavour == GRUB_SYSLINUX_UNKNOWN)
1215
print_string ("if [ x$syslinux_flavour = x");
1216
err = print (outbuf, flav[flavour], grub_strlen (flav[flavour]));
1219
print_string (" ]; then true;\n");
1220
menu->flavour = flavour;
1221
print_entry (outbuf, menu, bptr);
1222
menu->flavour = GRUB_SYSLINUX_UNKNOWN;
1223
print_string ("fi\n");
1225
if (menu->flavour != GRUB_SYSLINUX_UNKNOWN
1226
&& menu->flavour == flavour)
1227
print_entry (outbuf, menu, bptr);
1233
/* FIXME: gdb, GFXBoot, Hdt, Ifcpu, Ifplop, Kbdmap,
1234
FIXME: Linux, Lua, Meminfo, rosh, Sanbboot */
1236
print_string (" # UNSUPPORTED com(32) ");
1237
err = print (outbuf, basename, grub_strlen (basename));
1240
print_string ("\ntrue;\n");
1245
char *new_cwd, *new_target_cwd;
1247
ap = curentry->append;
1249
ap = curentry->argument;
1252
new_cwd = get_read_filename (menu, ap);
1255
new_target_cwd = get_target_filename (menu, ap);
1256
if (!new_target_cwd)
1259
struct syslinux_menu *menuptr;
1263
newname = get_read_filename (menu, curentry->kernel_file);
1266
simplify_filename (newname);
1269
print_file (outbuf, menu, curentry->kernel_file, NULL);
1271
print (outbuf, newname, grub_strlen (newname));
1272
print_string (":\n");
1274
for (menuptr = menu; menuptr; menuptr = menuptr->parent, depth++)
1275
if (grub_strcmp (menuptr->filename, newname) == 0
1280
print_string (" syslinux_configfile -r ");
1281
print_file (outbuf, menu, "/", NULL);
1282
print_string (" -c ");
1283
print_file (outbuf, menu, ap, NULL);
1285
print_file (outbuf, menu, curentry->kernel_file, NULL);
1286
print_string ("\n");
1290
err = config_file (outbuf, menu->root_read_directory,
1291
menu->root_target_directory, new_cwd, new_target_cwd,
1292
newname, menu, menu->flavour);
1293
if (err == GRUB_ERR_FILE_NOT_FOUND
1294
|| err == GRUB_ERR_BAD_FILENAME)
1296
grub_errno = err = GRUB_ERR_NONE;
1297
print_string ("# File ");
1298
err = print (outbuf, newname, grub_strlen (newname));
1301
print_string (" not found\n");
1306
grub_free (newname);
1307
grub_free (new_cwd);
1308
grub_free (new_target_cwd);
1311
case KERNEL_NO_KERNEL:
1312
/* FIXME: support this. */
1316
print_string (" # UNSUPPORTED entry type ");
1317
if (print_num (outbuf, curentry->entry_type))
1319
print_string ("\ntrue;\n");
1322
return GRUB_ERR_NONE;
1326
print_entry (struct output_buffer *outbuf,
1327
struct syslinux_menu *menu,
1330
struct syslinux_menuentry *curentry;
1331
for (curentry = menu->entries; curentry; curentry = curentry->next)
1332
if (grub_strcasecmp (curentry->label, str) == 0)
1335
err = write_entry (outbuf, menu, curentry);
1339
return GRUB_ERR_NONE;
1343
free_menu (struct syslinux_menu *menu)
1345
struct syslinux_say *say, *nsay;
1346
struct syslinux_menuentry *entry, *nentry;
1348
grub_free (menu->def);
1349
grub_free (menu->comments);
1350
grub_free (menu->background);
1351
for (say = menu->say; say ; say = nsay)
1354
grub_free (say->msg);
1358
for (entry = menu->entries; entry ; entry = nentry)
1360
nentry = entry->next;
1361
struct initrd_list *initrd, *ninitrd;
1363
for (initrd = entry->initrds; initrd ; initrd = ninitrd)
1365
ninitrd = initrd->next;
1366
grub_free (initrd->file);
1370
grub_free (entry->comments);
1371
grub_free (entry->kernel_file);
1372
grub_free (entry->label);
1373
grub_free (entry->extlabel);
1374
grub_free (entry->append);
1375
grub_free (entry->help);
1381
config_file (struct output_buffer *outbuf,
1382
const char *root, const char *target_root,
1383
const char *cwd, const char *target_cwd,
1384
const char *fname, struct syslinux_menu *parent,
1385
grub_syslinux_flavour_t flav)
1388
struct syslinux_menu menu;
1389
struct syslinux_menuentry *curentry, *lentry;
1390
struct syslinux_say *say;
1392
grub_memset (&menu, 0, sizeof (menu));
1393
menu.flavour = flav;
1394
menu.root_read_directory = root;
1395
menu.root_target_directory = target_root;
1396
menu.current_read_directory = cwd;
1397
menu.current_target_directory = target_cwd;
1399
menu.filename = fname;
1400
menu.parent = parent;
1401
err = syslinux_parse_real (&menu);
1405
for (say = menu.say; say && say->next; say = say->next);
1406
for (; say && say->prev; say = say->prev)
1408
print_string ("echo ");
1409
err = print_escaped (outbuf, say->msg, NULL);
1412
print_string ("\n");
1415
if (menu.background)
1417
print_string (" background_image ");
1418
err = print_file (outbuf, &menu, menu.background, NULL);
1421
print_string ("\n");
1424
if (menu.timeout == 0 && menu.entries && menu.def)
1426
err = print_entry (outbuf, &menu, menu.def);
1430
else if (menu.entries)
1432
for (curentry = menu.entries; curentry->next; curentry = curentry->next);
1435
print_string ("set timeout='");
1436
err = print_num (outbuf, (menu.timeout + 9) / 10);
1439
print_string ("\n");
1442
err = print (outbuf, menu.comments, grub_strlen (menu.comments));
1449
print_string (" default=");
1450
err = print_escaped (outbuf, menu.def, NULL);
1453
print_string ("\n");
1455
for (curentry = lentry; curentry; curentry = curentry->prev)
1457
print_string ("menuentry ");
1458
err = print_escaped (outbuf,
1459
curentry->extlabel ? : curentry->label, NULL);
1462
if (curentry->hotkey)
1464
char hk[] = { curentry->hotkey, '\0' };
1465
print_string (" --hotkey '");
1469
print_string (" --id ");
1470
err = print_escaped (outbuf, curentry->label, NULL);
1473
print_string (" {\n");
1475
err = write_entry (outbuf, &menu, curentry);
1479
print_string ("}\n");
1483
return GRUB_ERR_NONE;
1487
grub_syslinux_config_file (const char *base, const char *target_base,
1488
const char *cwd, const char *target_cwd,
1489
const char *fname, grub_syslinux_flavour_t flav)
1491
struct output_buffer outbuf = { 0, 0, 0 };
1493
err = config_file (&outbuf, base, target_base, cwd, target_cwd,
1497
err = print (&outbuf, "\0", 1);