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);
426 return GRUB_ERR_NONE
;
430 cmd_menudefault (const char *line
__attribute__ ((unused
)),
431 struct syslinux_menu
*menu
)
434 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "kernel without label");
436 menu
->entries
->make_default
= 1;
437 return GRUB_ERR_NONE
;
441 cmd_menubackground (const char *line
,
442 struct syslinux_menu
*menu
)
444 menu
->background
= grub_strdup (line
);
445 return GRUB_ERR_NONE
;
449 cmd_localboot (const char *line
,
450 struct syslinux_menu
*menu
)
453 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "kernel without label");
455 menu
->entries
->kernel_file
= grub_strdup (line
);
456 if (!menu
->entries
->kernel_file
)
458 menu
->entries
->entry_type
= LOCALBOOT
;
460 return GRUB_ERR_NONE
;
464 cmd_extlabel (const char *line
, struct syslinux_menu
*menu
)
470 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "kernel without label");
472 menu
->entries
->extlabel
= grub_malloc (grub_strlen (line
) + 1);
473 if (!menu
->entries
->extlabel
)
476 out
= menu
->entries
->extlabel
;
479 if (in
[0] == '^' && in
[1])
481 menu
->entries
->hotkey
= grub_tolower (in
[1]);
488 return GRUB_ERR_NONE
;
493 cmd_say (const char *line
, struct syslinux_menu
*menu
)
495 struct syslinux_say
*nsay
;
496 nsay
= grub_malloc (sizeof (*nsay
) + grub_strlen (line
) + 1);
502 nsay
->next
= menu
->entries
->say
;
503 menu
->entries
->say
= nsay
;
507 nsay
->next
= menu
->say
;
512 nsay
->next
->prev
= nsay
;
514 grub_memcpy (nsay
->msg
, line
, grub_strlen (line
) + 1);
515 return GRUB_ERR_NONE
;
519 get_read_filename (struct syslinux_menu
*menu
,
520 const char *filename
)
522 return grub_xasprintf ("%s/%s",
523 filename
[0] == '/' ? menu
->root_read_directory
524 : menu
->current_read_directory
, filename
);
528 get_target_filename (struct syslinux_menu
*menu
,
529 const char *filename
)
531 return grub_xasprintf ("%s/%s",
532 filename
[0] == '/' ? menu
->root_target_directory
533 : menu
->current_target_directory
, filename
);
537 syslinux_parse (const char *filename
,
538 struct syslinux_menu
*menu
)
540 const char *old_filename
= menu
->filename
;
543 nf
= get_read_filename (menu
, filename
);
547 ret
= syslinux_parse_real (menu
);
548 if (ret
== GRUB_ERR_FILE_NOT_FOUND
549 || ret
== GRUB_ERR_BAD_FILENAME
)
551 grub_errno
= ret
= GRUB_ERR_NONE
;
552 add_comment (menu
, "# File ", 0);
553 add_comment (menu
, nf
, 0);
554 add_comment (menu
, " not found", 1);
557 menu
->filename
= old_filename
;
565 grub_err_t (*parse
) (const char *line
, struct syslinux_menu
*menu
);
567 /* FIXME: support tagname. */
568 {"include", NULL
, syslinux_parse
},
569 {"menu", "include", syslinux_parse
},
570 {"label", NULL
, label
},
571 {"kernel", NULL
, kernel
},
572 {"linux", NULL
, cmd_linux
},
573 {"boot", NULL
, cmd_boot
},
574 {"bss", NULL
, cmd_bss
},
575 {"pxe", NULL
, cmd_pxe
},
576 {"fdimage", NULL
, cmd_fdimage
},
577 {"comboot", NULL
, cmd_comboot
},
578 {"com32", NULL
, cmd_com32
},
579 {"config", NULL
, cmd_config
},
580 {"append", NULL
, cmd_append
},
581 /* FIXME: ipappend not supported. */
582 {"localboot", NULL
, cmd_localboot
},
583 {"initrd", NULL
, cmd_initrd
},
584 {"default", NULL
, cmd_default
},
585 {"menu", "label", cmd_extlabel
},
586 /* FIXME: MENU LABEL not supported. */
587 /* FIXME: MENU HIDDEN not supported. */
588 /* FIXME: MENU SEPARATOR not supported. */
589 /* FIXME: MENU INDENT not supported. */
590 /* FIXME: MENU DISABLE not supported. */
591 /* FIXME: MENU HIDE not supported. */
592 {"menu", "default", cmd_menudefault
},
593 /* FIXME: MENU PASSWD not supported. */
594 /* FIXME: MENU MASTER PASSWD not supported. */
595 {"menu", "background", cmd_menubackground
},
596 /* FIXME: MENU BEGIN not supported. */
597 /* FIXME: MENU GOTO not supported. */
598 /* FIXME: MENU EXIT not supported. */
599 /* FIXME: MENU QUIT not supported. */
600 /* FIXME: MENU START not supported. */
601 /* FIXME: MENU AUTOBOOT not supported. */
602 /* FIXME: MENU TABMSG not supported. */
603 /* FIXME: MENU NOTABMSG not supported. */
604 /* FIXME: MENU PASSPROMPT not supported. */
605 /* FIXME: MENU COLOR not supported. */
606 /* FIXME: MENU MSGCOLOR not supported. */
607 /* FIXME: MENU WIDTH not supported. */
608 /* FIXME: MENU MARGIN not supported. */
609 /* FIXME: MENU PASSWORDMARGIN not supported. */
610 /* FIXME: MENU ROWS not supported. */
611 /* FIXME: MENU TABMSGROW not supported. */
612 /* FIXME: MENU CMDLINEROW not supported. */
613 /* FIXME: MENU ENDROW not supported. */
614 /* FIXME: MENU PASSWORDROW not supported. */
615 /* FIXME: MENU TIMEOUTROW not supported. */
616 /* FIXME: MENU HELPMSGROW not supported. */
617 /* FIXME: MENU HELPMSGENDROW not supported. */
618 /* FIXME: MENU HIDDENROW not supported. */
619 /* FIXME: MENU HSHIFT not supported. */
620 /* FIXME: MENU VSHIFT not supported. */
621 {"timeout", NULL
, cmd_timeout
},
622 /* FIXME: TOTALTIMEOUT not supported. */
623 /* FIXME: ONTIMEOUT not supported. */
624 /* FIXME: ONERROR not supported. */
625 /* FIXME: SERIAL not supported. */
626 /* FIXME: CONSOLE not supported. */
627 /* FIXME: FONT not supported. */
628 /* FIXME: KBDMAP not supported. */
629 {"say", NULL
, cmd_say
},
630 /* FIXME: DISPLAY not supported. */
631 /* FIXME: F* not supported. */
633 /* Commands to control interface behaviour which aren't needed with GRUB.
634 If they are important in your environment please contact GRUB team.
636 {"prompt", NULL
, NULL
},
637 {"nocomplete", NULL
, NULL
},
638 {"noescape", NULL
, NULL
},
639 {"implicit", NULL
, NULL
},
640 {"allowoptions", NULL
, NULL
}
644 helptext (const char *line
, grub_file_t file
, struct syslinux_menu
*menu
)
648 grub_size_t helplen
, alloclen
= 0;
650 help
= grub_strdup (line
);
653 helplen
= grub_strlen (line
);
654 while ((grub_free (buf
), buf
= grub_file_getline (file
)))
658 for (ptr
= buf
; *ptr
&& grub_isspace (*ptr
); ptr
++);
659 if (grub_strncasecmp (ptr
, "endtext", sizeof ("endtext") - 1) == 0)
661 ptr
+= sizeof ("endtext") - 1;
662 for (; *ptr
&& (grub_isspace (*ptr
) || *ptr
== '\n' || *ptr
== '\r');
666 menu
->entries
->help
= help
;
668 return GRUB_ERR_NONE
;
671 needlen
= helplen
+ 1 + grub_strlen (buf
);
672 if (alloclen
< needlen
)
674 alloclen
= 2 * needlen
;
675 help
= grub_realloc (help
, alloclen
);
682 helplen
+= grub_stpcpy (help
+ helplen
, buf
) - (help
+ helplen
);
692 syslinux_parse_real (struct syslinux_menu
*menu
)
696 grub_err_t err
= GRUB_ERR_NONE
;
698 file
= grub_file_open (menu
->filename
, GRUB_FILE_TYPE_CONFIG
);
701 while ((grub_free (buf
), buf
= grub_file_getline (file
)))
703 const char *ptr1
, *ptr2
, *ptr3
, *ptr4
, *ptr5
;
706 end
= buf
+ grub_strlen (buf
);
707 while (end
> buf
&& (end
[-1] == '\n' || end
[-1] == '\r'))
710 for (ptr1
= buf
; *ptr1
&& grub_isspace (*ptr1
); ptr1
++);
711 if (*ptr1
== '#' || *ptr1
== 0)
713 err
= add_comment (menu
, ptr1
, 1);
718 for (ptr2
= ptr1
; !grub_isspace (*ptr2
) && *ptr2
; ptr2
++);
719 for (ptr3
= ptr2
; grub_isspace (*ptr3
) && *ptr3
; ptr3
++);
720 for (ptr4
= ptr3
; !grub_isspace (*ptr4
) && *ptr4
; ptr4
++);
721 for (ptr5
= ptr4
; grub_isspace (*ptr5
) && *ptr5
; ptr5
++);
722 for (i
= 0; i
< ARRAY_SIZE(commands
); i
++)
723 if (grub_strlen (commands
[i
].name1
) == (grub_size_t
) (ptr2
- ptr1
)
724 && grub_strncasecmp (commands
[i
].name1
, ptr1
, ptr2
- ptr1
) == 0
725 && (commands
[i
].name2
== NULL
726 || (grub_strlen (commands
[i
].name2
)
727 == (grub_size_t
) (ptr4
- ptr3
)
728 && grub_strncasecmp (commands
[i
].name2
, ptr3
, ptr4
- ptr3
)
731 if (i
== ARRAY_SIZE(commands
))
733 if (sizeof ("text") - 1 == ptr2
- ptr1
734 && grub_strncasecmp ("text", ptr1
, ptr2
- ptr1
) == 0
735 && (sizeof ("help") - 1 == ptr4
- ptr3
736 && grub_strncasecmp ("help", ptr3
, ptr4
- ptr3
) == 0))
738 if (helptext (ptr5
, file
, menu
))
743 add_comment (menu
, " # UNSUPPORTED command '", 0);
744 add_comment (menu
, ptr1
, 0);
745 add_comment (menu
, "'", 1);
749 if (commands
[i
].parse
)
751 err
= commands
[i
].parse (commands
[i
].name2
752 ? ptr5
: ptr3
, menu
);
758 grub_file_close (file
);
763 print_escaped (struct output_buffer
*outbuf
,
764 const char *from
, const char *to
)
769 to
= from
+ grub_strlen (from
);
770 err
= ensure_space (outbuf
, (to
- from
) * 4 + 2);
773 outbuf
->buf
[outbuf
->ptr
++] = '\'';
774 for (ptr
= from
; *ptr
&& ptr
< to
; ptr
++)
778 outbuf
->buf
[outbuf
->ptr
++] = '\'';
779 outbuf
->buf
[outbuf
->ptr
++] = '\\';
780 outbuf
->buf
[outbuf
->ptr
++] = '\'';
781 outbuf
->buf
[outbuf
->ptr
++] = '\'';
784 outbuf
->buf
[outbuf
->ptr
++] = *ptr
;
786 outbuf
->buf
[outbuf
->ptr
++] = '\'';
787 return GRUB_ERR_NONE
;
791 print_file (struct output_buffer
*outbuf
,
792 struct syslinux_menu
*menu
, const char *from
, const char *to
)
796 to
= from
+ grub_strlen (from
);
797 err
= print_escaped (outbuf
, from
[0] == '/'
798 ? menu
->root_target_directory
799 : menu
->current_target_directory
, NULL
);
803 err
= print (outbuf
, "/", 1);
806 return print_escaped (outbuf
, from
, to
);
810 * Makefile.am mimics this when generating tests/syslinux/ubuntu10.04_grub.cfg,
811 * so changes here may need to be reflected there too.
814 simplify_filename (char *str
)
816 char *iptr
, *optr
= str
;
817 for (iptr
= str
; *iptr
; iptr
++)
819 if (*iptr
== '/' && optr
!= str
&& optr
[-1] == '/')
821 if (iptr
[0] == '/' && iptr
[1] == '.' && iptr
[2] == '/')
826 if (iptr
[0] == '/' && iptr
[1] == '.' && iptr
[2] == '.'
830 while (optr
>= str
&& *optr
!= '/')
846 print_config (struct output_buffer
*outbuf
,
847 struct syslinux_menu
*menu
,
848 const char *filename
, const char *basedir
)
850 struct syslinux_menu
*menuptr
;
851 grub_err_t err
= GRUB_ERR_NONE
;
852 char *new_cwd
= NULL
;
853 char *new_target_cwd
= NULL
;
854 char *newname
= NULL
;
857 new_cwd
= get_read_filename (menu
, basedir
);
863 new_target_cwd
= get_target_filename (menu
, basedir
);
869 newname
= get_read_filename (menu
, filename
);
875 simplify_filename (newname
);
878 print_file (outbuf
, menu
, filename
, NULL
);
880 err
= print (outbuf
, newname
, grub_strlen (newname
));
883 print_string (":\n");
885 for (menuptr
= menu
; menuptr
; menuptr
= menuptr
->parent
, depth
++)
886 if (grub_strcmp (menuptr
->filename
, newname
) == 0
891 print_string (" syslinux_configfile -r ");
892 print_file (outbuf
, menu
, "/", NULL
);
893 print_string (" -c ");
894 print_file (outbuf
, menu
, basedir
, NULL
);
896 print_file (outbuf
, menu
, filename
, NULL
);
901 err
= config_file (outbuf
, menu
->root_read_directory
,
902 menu
->root_target_directory
, new_cwd
, new_target_cwd
,
903 newname
, menu
, menu
->flavour
);
904 if (err
== GRUB_ERR_FILE_NOT_FOUND
905 || err
== GRUB_ERR_BAD_FILENAME
)
907 grub_errno
= err
= GRUB_ERR_NONE
;
908 print_string ("# File ");
909 err
= print (outbuf
, newname
, grub_strlen (newname
));
912 print_string (" not found\n");
919 grub_free (new_target_cwd
);
924 write_entry (struct output_buffer
*outbuf
,
925 struct syslinux_menu
*menu
,
926 struct syslinux_menuentry
*curentry
)
929 if (curentry
->comments
)
931 err
= print (outbuf
, curentry
->comments
,
932 grub_strlen (curentry
->comments
));
937 struct syslinux_say
*say
;
938 for (say
= curentry
->say
; say
&& say
->next
; say
= say
->next
);
939 for (; say
&& say
->prev
; say
= say
->prev
)
941 print_string ("echo ");
942 if (print_escaped (outbuf
, say
->msg
, NULL
)) return grub_errno
;
947 /* FIXME: support help text. */
948 switch (curentry
->entry_type
)
953 const char *initrd
= NULL
, *initrde
= NULL
;
954 for (ptr
= curentry
->append
; ptr
&& *ptr
; ptr
++)
955 if ((ptr
== curentry
->append
|| grub_isspace (ptr
[-1]))
956 && grub_strncasecmp (ptr
, "initrd=", sizeof ("initrd=") - 1)
961 initrd
= ptr
+ sizeof ("initrd=") - 1;
962 for (initrde
= initrd
; *initrde
&& !grub_isspace (*initrde
); initrde
++);
964 print_string (" if test x$ventoy_linux_16 = x1; then "
965 "linux_suffix=16; else linux_suffix= ; fi\n");
966 print_string (" linux$linux_suffix ");
967 print_file (outbuf
, menu
, curentry
->kernel_file
, NULL
);
969 if (curentry
->append
)
971 err
= print (outbuf
, curentry
->append
, grub_strlen (curentry
->append
));
976 if (initrd
|| curentry
->initrds
)
978 struct initrd_list
*lst
;
979 print_string (" initrd$linux_suffix ");
982 print_file (outbuf
, menu
, initrd
, initrde
);
985 for (lst
= curentry
->initrds
; lst
; lst
= lst
->next
)
987 print_file (outbuf
, menu
, lst
->file
, NULL
);
993 print_string ("boot\n");
996 case KERNEL_CHAINLOADER
:
997 print_string (" chainloader ");
998 print_file (outbuf
, menu
, curentry
->kernel_file
, NULL
);
1001 case KERNEL_CHAINLOADER_BPB
:
1002 print_string (" chainloader --bpb ");
1003 print_file (outbuf
, menu
, curentry
->kernel_file
, NULL
);
1004 print_string ("\n");
1007 /* FIXME: support -1. */
1008 /* FIXME: PXELINUX. */
1010 int n
= grub_strtol (curentry
->kernel_file
, NULL
, 0);
1011 if (n
>= 0 && n
<= 0x02)
1013 print_string (" root=fd");
1014 if (print_num (outbuf
, n
))
1016 print_string (";\n chainloader +1;\n");
1020 if (n
>= 0x80 && n
< 0x8a)
1022 print_string (" root=hd");
1023 if (print_num (outbuf
, n
- 0x80))
1025 print_string (";\n chainloader +1;\n");
1028 print_string (" # UNSUPPORTED localboot type ");
1029 print_string ("\ntrue;\n");
1030 if (print_num (outbuf
, n
))
1032 print_string ("\n");
1038 char *basename
= NULL
;
1042 for (ptr
= curentry
->kernel_file
; *ptr
; ptr
++)
1043 if (*ptr
== '/' || *ptr
== '\\')
1047 basename
= curentry
->kernel_file
;
1050 if (grub_strcasecmp (basename
, "chain.c32") == 0)
1053 int is_fd
= -1, devn
= 0;
1057 for (ptr
= curentry
->append
; *ptr
; )
1059 while (grub_isspace (*ptr
))
1061 /* FIXME: support mbr: and boot. */
1062 if (ptr
[0] == 'h' && ptr
[1] == 'd')
1065 devn
= grub_strtoul (ptr
+ 2, &ptr
, 0);
1068 if (grub_strncasecmp (ptr
, "file=", 5) == 0)
1071 for (ptr
= file
; *ptr
&& !grub_isspace (*ptr
); ptr
++);
1079 if (grub_strncasecmp (ptr
, "swap", sizeof ("swap") - 1) == 0)
1082 ptr
+= sizeof ("swap") - 1;
1086 if (ptr
[0] == 'f' && ptr
[1] == 'd')
1089 devn
= grub_strtoul (ptr
+ 2, &ptr
, 0);
1092 if (grub_isdigit (ptr
[0]))
1094 part
= grub_strtoul (ptr
, &ptr
, 0);
1097 /* FIXME: isolinux, ntldr, cmldr, *dos, seg, hide
1098 FIXME: sethidden. */
1099 print_string (" # UNSUPPORTED option ");
1100 if (print (outbuf
, ptr
, grub_strlen (ptr
)))
1102 print_string ("\n");
1107 print_string (" # no drive specified\n");
1112 print_string (is_fd
? " root=fd": " root=hd");
1113 if (print_num (outbuf
, devn
))
1118 if (print_num (outbuf
, part
+ 1))
1121 print_string (";\n");
1124 print_string (" chainloader ");
1125 print_file (outbuf
, menu
, file
, NULL
);
1126 print_string (";\n");
1129 print_string (" chainloader +1;\n");
1131 print_string (" drivemap -s hd0 \"root\";\n");
1136 if (grub_strcasecmp (basename
, "mboot.c32") == 0)
1141 for (ptr
= curentry
->append
; *ptr
; )
1144 while (*ptr
&& !grub_isspace (*ptr
))
1146 if (ptrr
+ 2 == ptr
&& ptrr
[0] == '-' && ptrr
[1] == '-')
1148 print_string ("\n");
1155 print_string (" multiboot ");
1157 print_string (" module ");
1160 if (print_file (outbuf
, menu
, ptrr
, ptr
))
1164 if (print_escaped (outbuf
, ptrr
, ptr
))
1170 if (grub_strcasecmp (basename
, "ifcpu64.c32") == 0)
1172 char *lm
, *lme
, *pae
= 0, *paee
= 0, *i386s
= 0, *i386e
= 0;
1174 ptr
= curentry
->append
;
1175 while (grub_isspace (*ptr
))
1178 while (*ptr
&& !grub_isspace (*ptr
))
1181 while (grub_isspace (*ptr
))
1183 if (ptr
[0] == '-' && ptr
[1] == '-')
1186 while (grub_isspace (*ptr
))
1189 while (*ptr
&& !grub_isspace (*ptr
))
1193 while (grub_isspace (*ptr
))
1195 if (ptr
[0] == '-' && ptr
[1] == '-')
1198 while (grub_isspace (*ptr
))
1201 while (*ptr
&& !grub_isspace (*ptr
))
1215 print_string ("if cpuid --long-mode; then true;\n");
1216 if (print_entry (outbuf
, menu
, lm
))
1220 print_string ("elif cpuid --pae; then true;\n");
1221 if (print_entry (outbuf
, menu
, pae
))
1224 print_string ("else\n");
1225 if (print_entry (outbuf
, menu
, i386s
))
1227 print_string ("fi\n");
1231 if (grub_strcasecmp (basename
, "reboot.c32") == 0)
1233 print_string (" reboot\n");
1237 if (grub_strcasecmp (basename
, "poweroff.com") == 0)
1239 print_string (" halt\n");
1243 if (grub_strcasecmp (basename
, "whichsys.c32") == 0)
1245 grub_syslinux_flavour_t flavour
= GRUB_SYSLINUX_ISOLINUX
;
1246 const char *flav
[] =
1248 [GRUB_SYSLINUX_ISOLINUX
] = "iso",
1249 [GRUB_SYSLINUX_PXELINUX
] = "pxe",
1250 [GRUB_SYSLINUX_SYSLINUX
] = "sys"
1253 for (ptr
= curentry
->append
; *ptr
; )
1256 while (grub_isspace (*ptr
))
1258 if (grub_strncasecmp (ptr
, "-iso-", 5) == 0)
1260 ptr
+= sizeof ("-iso-") - 1;
1261 flavour
= GRUB_SYSLINUX_ISOLINUX
;
1264 if (grub_strncasecmp (ptr
, "-pxe-", 5) == 0)
1266 ptr
+= sizeof ("-pxe-") - 1;
1267 flavour
= GRUB_SYSLINUX_PXELINUX
;
1270 if (grub_strncasecmp (ptr
, "-sys-", 5) == 0)
1272 ptr
+= sizeof ("-sys-") - 1;
1273 flavour
= GRUB_SYSLINUX_SYSLINUX
;
1277 while (*ptr
&& !grub_isspace (*ptr
))
1281 if (menu
->flavour
== GRUB_SYSLINUX_UNKNOWN
1282 && flavour
== GRUB_SYSLINUX_ISOLINUX
)
1284 print_string ("if [ x$syslinux_flavour = xiso -o x$syslinux_flavour = x ]; then true;\n");
1285 menu
->flavour
= GRUB_SYSLINUX_ISOLINUX
;
1286 print_entry (outbuf
, menu
, bptr
);
1287 menu
->flavour
= GRUB_SYSLINUX_UNKNOWN
;
1288 print_string ("fi\n");
1290 else if (menu
->flavour
== GRUB_SYSLINUX_UNKNOWN
)
1292 print_string ("if [ x$syslinux_flavour = x");
1293 err
= print (outbuf
, flav
[flavour
], grub_strlen (flav
[flavour
]));
1296 print_string (" ]; then true;\n");
1297 menu
->flavour
= flavour
;
1298 print_entry (outbuf
, menu
, bptr
);
1299 menu
->flavour
= GRUB_SYSLINUX_UNKNOWN
;
1300 print_string ("fi\n");
1302 if (menu
->flavour
!= GRUB_SYSLINUX_UNKNOWN
1303 && menu
->flavour
== flavour
)
1304 print_entry (outbuf
, menu
, bptr
);
1310 if (grub_strcasecmp (basename
, "menu.c32") == 0 ||
1311 grub_strcasecmp (basename
, "vesamenu.c32") == 0)
1316 ptr
= curentry
->append
;
1323 for (end
= ptr
; *end
&& !grub_isspace (*end
); end
++);
1327 /* "~" is supposed to be current file, so let's skip it */
1328 if (grub_strcmp (ptr
, "~") != 0)
1330 err
= print_config (outbuf
, menu
, ptr
, "");
1331 if (err
!= GRUB_ERR_NONE
)
1334 for (ptr
= end
; *ptr
&& grub_isspace (*ptr
); ptr
++);
1336 err
= GRUB_ERR_NONE
;
1340 /* FIXME: gdb, GFXBoot, Hdt, Ifcpu, Ifplop, Kbdmap,
1341 FIXME: Linux, Lua, Meminfo, rosh, Sanbboot */
1343 print_string (" # UNSUPPORTED com(32) ");
1344 err
= print (outbuf
, basename
, grub_strlen (basename
));
1347 print_string ("\ntrue;\n");
1353 ap
= curentry
->append
;
1355 ap
= curentry
->argument
;
1358 print_config (outbuf
, menu
, curentry
->kernel_file
, ap
);
1361 case KERNEL_NO_KERNEL
:
1362 /* FIXME: support this. */
1366 print_string (" # UNSUPPORTED entry type ");
1367 if (print_num (outbuf
, curentry
->entry_type
))
1369 print_string ("\ntrue;\n");
1372 return GRUB_ERR_NONE
;
1376 print_entry (struct output_buffer
*outbuf
,
1377 struct syslinux_menu
*menu
,
1380 struct syslinux_menuentry
*curentry
;
1381 for (curentry
= menu
->entries
; curentry
; curentry
= curentry
->next
)
1382 if (grub_strcasecmp (curentry
->label
, str
) == 0)
1385 err
= write_entry (outbuf
, menu
, curentry
);
1389 return GRUB_ERR_NONE
;
1393 free_menu (struct syslinux_menu
*menu
)
1395 struct syslinux_say
*say
, *nsay
;
1396 struct syslinux_menuentry
*entry
, *nentry
;
1398 grub_free (menu
->def
);
1399 grub_free (menu
->comments
);
1400 grub_free (menu
->background
);
1401 for (say
= menu
->say
; say
; say
= nsay
)
1407 for (entry
= menu
->entries
; entry
; entry
= nentry
)
1409 nentry
= entry
->next
;
1410 struct initrd_list
*initrd
, *ninitrd
;
1412 for (initrd
= entry
->initrds
; initrd
; initrd
= ninitrd
)
1414 ninitrd
= initrd
->next
;
1415 grub_free (initrd
->file
);
1419 grub_free (entry
->comments
);
1420 grub_free (entry
->kernel_file
);
1421 grub_free (entry
->label
);
1422 grub_free (entry
->extlabel
);
1423 grub_free (entry
->append
);
1424 grub_free (entry
->help
);
1430 config_file (struct output_buffer
*outbuf
,
1431 const char *root
, const char *target_root
,
1432 const char *cwd
, const char *target_cwd
,
1433 const char *fname
, struct syslinux_menu
*parent
,
1434 grub_syslinux_flavour_t flav
)
1438 struct syslinux_menu menu
;
1439 struct syslinux_menuentry
*curentry
, *lentry
;
1440 struct syslinux_say
*say
;
1442 grub_memset (&menu
, 0, sizeof (menu
));
1443 menu
.flavour
= flav
;
1444 menu
.root_read_directory
= root
;
1445 menu
.root_target_directory
= target_root
;
1446 menu
.current_read_directory
= cwd
;
1447 menu
.current_target_directory
= target_cwd
;
1449 menu
.filename
= fname
;
1450 menu
.parent
= parent
;
1452 data
= grub_env_get("vtdebug_flag");
1453 if (data
&& data
[0])
1458 err
= syslinux_parse_real (&menu
);
1462 for (say
= menu
.say
; say
&& say
->next
; say
= say
->next
);
1463 for (; say
&& say
->prev
; say
= say
->prev
)
1465 print_string ("echo ");
1466 err
= print_escaped (outbuf
, say
->msg
, NULL
);
1469 print_string ("\n");
1472 if (menu
.background
)
1474 print_string (" background_image ");
1475 err
= print_file (outbuf
, &menu
, menu
.background
, NULL
);
1478 print_string ("\n");
1483 err
= print (outbuf
, menu
.comments
, grub_strlen (menu
.comments
));
1488 if (menu
.timeout
== 0 && menu
.entries
&& menu
.def
)
1490 err
= print_entry (outbuf
, &menu
, menu
.def
);
1494 else if (menu
.entries
)
1496 for (curentry
= menu
.entries
; curentry
->next
; curentry
= curentry
->next
);
1499 print_string ("set timeout=");
1500 err
= print_num (outbuf
, (menu
.timeout
+ 9) / 10);
1503 print_string ("\n");
1507 print_string (" default=");
1508 err
= print_escaped (outbuf
, menu
.def
, NULL
);
1511 print_string ("\n");
1513 for (curentry
= lentry
; curentry
; curentry
= curentry
->prev
)
1515 print_string ("menuentry ");
1516 err
= print_escaped (outbuf
,
1517 curentry
->extlabel
? : curentry
->label
, NULL
);
1520 if (curentry
->hotkey
)
1522 char hk
[] = { curentry
->hotkey
, '\0' };
1523 print_string (" --hotkey '");
1527 print_string (" --id ");
1528 err
= print_escaped (outbuf
, curentry
->label
, NULL
);
1531 print_string (" {\n");
1533 err
= write_entry (outbuf
, &menu
, curentry
);
1537 print_string ("}\n");
1541 return GRUB_ERR_NONE
;
1545 grub_syslinux_config_file (const char *base
, const char *target_base
,
1546 const char *cwd
, const char *target_cwd
,
1547 const char *fname
, grub_syslinux_flavour_t flav
)
1549 struct output_buffer outbuf
= { 0, 0, 0 };
1551 err
= config_file (&outbuf
, base
, target_base
, cwd
, target_cwd
,
1555 err
= print (&outbuf
, "\0", 1);