1 /* menu.c - General supporting functionality for menus. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/normal.h>
21 #include <grub/misc.h>
22 #include <grub/loader.h>
24 #include <grub/time.h>
26 #include <grub/menu_viewer.h>
27 #include <grub/command.h>
28 #include <grub/parser.h>
29 #include <grub/auth.h>
30 #include <grub/i18n.h>
31 #include <grub/term.h>
32 #include <grub/script_sh.h>
33 #include <grub/gfxterm.h>
36 #include <grub/extcmd.h>
37 #include <grub/ventoy.h>
38 #include "ventoy/ventoy_def.h"
40 int g_ventoy_menu_refresh
= 0;
41 int g_ventoy_memdisk_mode
= 0;
42 int g_ventoy_iso_raw
= 0;
43 int g_ventoy_grub2_mode
= 0;
44 int g_ventoy_wimboot_mode
= 0;
45 int g_ventoy_iso_uefi_drv
= 0;
46 int g_ventoy_last_entry
= -1;
47 int g_ventoy_suppress_esc
= 0;
48 int g_ventoy_menu_esc
= 0;
49 int g_ventoy_fn_mutex
= 0;
50 int g_ventoy_terminal_output
= 0;
52 /* Time to delay after displaying an error message about a default/fallback
53 entry failing to boot. */
54 #define DEFAULT_ENTRY_ERROR_DELAY_MS 2500
56 grub_err_t (*grub_gfxmenu_try_hook
) (int entry
, grub_menu_t menu
,
61 TIMEOUT_STYLE_COUNTDOWN
,
65 struct timeout_style_name
{
67 enum timeout_style style
;
68 } timeout_style_names
[] = {
69 {"menu", TIMEOUT_STYLE_MENU
},
70 {"countdown", TIMEOUT_STYLE_COUNTDOWN
},
71 {"hidden", TIMEOUT_STYLE_HIDDEN
},
75 /* Wait until the user pushes any key so that the user
76 can see what happened. */
78 grub_wait_after_message (void)
80 grub_uint64_t endtime
;
82 grub_printf_ (N_("Press any key to continue..."));
85 endtime
= grub_get_time_ms () + 10000;
87 while (grub_get_time_ms () < endtime
88 && grub_getkey_noblock () == GRUB_TERM_NO_KEY
);
93 /* Get a menu entry by its index in the entry list. */
95 grub_menu_get_entry (grub_menu_t menu
, int no
)
99 for (e
= menu
->entry_list
; e
&& no
> 0; e
= e
->next
, no
--)
105 /* Get the index of a menu entry associated with a given hotkey, or -1. */
107 get_entry_index_by_hotkey (grub_menu_t menu
, int hotkey
)
109 grub_menu_entry_t entry
;
112 for (i
= 0, entry
= menu
->entry_list
; i
< menu
->size
;
113 i
++, entry
= entry
->next
)
114 if (entry
->hotkey
== hotkey
)
120 /* Return the timeout style. If the variable "timeout_style" is not set or
121 invalid, default to TIMEOUT_STYLE_MENU. */
122 static enum timeout_style
123 get_timeout_style (void)
126 struct timeout_style_name
*style_name
;
128 val
= grub_env_get ("timeout_style");
130 return TIMEOUT_STYLE_MENU
;
132 for (style_name
= timeout_style_names
; style_name
->name
; style_name
++)
133 if (grub_strcmp (style_name
->name
, val
) == 0)
134 return style_name
->style
;
136 return TIMEOUT_STYLE_MENU
;
139 /* Return the current timeout. If the variable "timeout" is not set or
140 invalid, return -1. */
142 grub_menu_get_timeout (void)
147 val
= grub_env_get ("timeout");
153 timeout
= (int) grub_strtoul (val
, 0, 0);
155 /* If the value is invalid, unset the variable. */
156 if (grub_errno
!= GRUB_ERR_NONE
)
158 grub_env_unset ("timeout");
159 grub_errno
= GRUB_ERR_NONE
;
168 /* Set current timeout in the variable "timeout". */
170 grub_menu_set_timeout (int timeout
)
172 /* Ignore TIMEOUT if it is zero, because it will be unset really soon. */
177 grub_snprintf (buf
, sizeof (buf
), "%d", timeout
);
178 grub_env_set ("timeout", buf
);
182 /* Get the first entry number from the value of the environment variable NAME,
183 which is a space-separated list of non-negative integers. The entry number
184 which is returned is stripped from the value of NAME. If no entry number
185 can be found, -1 is returned. */
187 get_and_remove_first_entry_number (const char *name
)
193 val
= grub_env_get (name
);
199 entry
= (int) grub_strtoul (val
, &tail
, 0);
201 if (grub_errno
== GRUB_ERR_NONE
)
203 /* Skip whitespace to find the next digit. */
204 while (*tail
&& grub_isspace (*tail
))
206 grub_env_set (name
, tail
);
210 grub_env_unset (name
);
211 grub_errno
= GRUB_ERR_NONE
;
220 /* Run a menu entry. */
222 grub_menu_execute_entry(grub_menu_entry_t entry
, int auto_boot
)
224 grub_err_t err
= GRUB_ERR_NONE
;
226 grub_menu_t menu
= NULL
;
227 char *optr
, *buf
, *oldchosen
= NULL
, *olddefault
= NULL
;
228 const char *ptr
, *chosen
, *def
;
231 if (entry
->restricted
)
232 err
= grub_auth_check_authentication (entry
->users
);
237 grub_errno
= GRUB_ERR_NONE
;
241 errs_before
= grub_err_printed_errors
;
243 chosen
= grub_env_get ("chosen");
244 def
= grub_env_get ("default");
248 grub_env_context_open ();
249 menu
= grub_zalloc (sizeof (*menu
));
252 grub_env_set_menu (menu
);
254 grub_env_set ("timeout", "0");
257 for (ptr
= entry
->id
; *ptr
; ptr
++)
258 sz
+= (*ptr
== '>') ? 2 : 1;
261 oldchosen
= grub_strdup (chosen
);
267 olddefault
= grub_strdup (def
);
273 sz
+= grub_strlen (chosen
);
275 buf
= grub_malloc (sz
);
283 optr
= grub_stpcpy (optr
, chosen
);
286 for (ptr
= entry
->id
; *ptr
; ptr
++)
293 grub_env_set ("chosen", buf
);
294 grub_env_export ("chosen");
298 for (ptr
= def
; ptr
&& *ptr
; ptr
++)
300 if (ptr
[0] == '>' && ptr
[1] == '>')
309 if (ptr
&& ptr
[0] && ptr
[1])
310 grub_env_set ("default", ptr
+ 1);
312 grub_env_unset ("default");
314 grub_script_execute_new_scope (entry
->sourcecode
, entry
->argc
, entry
->args
);
316 if (errs_before
!= grub_err_printed_errors
)
317 grub_wait_after_message ();
319 errs_before
= grub_err_printed_errors
;
321 if (grub_errno
== GRUB_ERR_NONE
&& grub_loader_is_loaded ())
322 /* Implicit execution of boot, only if something is loaded. */
323 grub_command_execute ("boot", 0, 0);
325 if (errs_before
!= grub_err_printed_errors
)
326 grub_wait_after_message ();
330 if (menu
&& menu
->size
)
332 grub_show_menu (menu
, 1, auto_boot
);
333 grub_normal_free_menu (menu
);
335 grub_env_context_close ();
338 grub_env_set ("chosen", oldchosen
);
340 grub_env_unset ("chosen");
342 grub_env_set ("default", olddefault
);
344 grub_env_unset ("default");
345 grub_env_unset ("timeout");
348 /* Execute ENTRY from the menu MENU, falling back to entries specified
349 in the environment variable "fallback" if it fails. CALLBACK is a
350 pointer to a struct of function pointers which are used to allow the
351 caller provide feedback to the user. */
353 grub_menu_execute_with_fallback (grub_menu_t menu
,
354 grub_menu_entry_t entry
,
356 grub_menu_execute_callback_t callback
,
361 callback
->notify_booting (entry
, callback_data
);
363 grub_menu_execute_entry (entry
, 1);
365 /* Deal with fallback entries. */
366 while ((fallback_entry
= get_and_remove_first_entry_number ("fallback"))
370 grub_errno
= GRUB_ERR_NONE
;
372 entry
= grub_menu_get_entry (menu
, fallback_entry
);
373 callback
->notify_fallback (entry
, callback_data
);
374 grub_menu_execute_entry (entry
, 1);
375 /* If the function call to execute the entry returns at all, then this is
376 taken to indicate a boot failure. For menu entries that do something
377 other than actually boot an operating system, this could assume
378 incorrectly that something failed. */
382 callback
->notify_failure (callback_data
);
385 static struct grub_menu_viewer
*viewers
;
387 int g_menu_update_mode
= 0;
388 int g_ventoy_tip_label_enable
= 0;
389 const char * g_ventoy_tip_msg1
= NULL
;
390 const char * g_ventoy_tip_msg2
= NULL
;
392 static void menu_set_chosen_tip(grub_menu_t menu
, int entry
)
395 grub_menu_entry_t e
= grub_menu_get_entry (menu
, entry
);
397 g_ventoy_tip_msg1
= g_ventoy_tip_msg2
= NULL
;
398 if (e
&& e
->id
&& grub_strncmp(e
->id
, "VID_", 4) == 0)
400 img
= (img_info
*)(void *)grub_strtoul(e
->id
+ 4, NULL
, 16);
403 g_ventoy_tip_msg1
= img
->tip1
;
404 g_ventoy_tip_msg2
= img
->tip2
;
410 menu_set_chosen_entry (grub_menu_t menu
, int entry
)
412 struct grub_menu_viewer
*cur
;
414 menu_set_chosen_tip(menu
, entry
);
415 for (cur
= viewers
; cur
; cur
= cur
->next
)
416 cur
->set_chosen_entry (entry
, cur
->data
);
420 menu_print_timeout (int timeout
)
422 struct grub_menu_viewer
*cur
;
423 for (cur
= viewers
; cur
; cur
= cur
->next
)
424 cur
->print_timeout (timeout
, cur
->data
);
430 struct grub_menu_viewer
*cur
, *next
;
431 for (cur
= viewers
; cur
; cur
= next
)
434 cur
->fini (cur
->data
);
441 menu_init (int entry
, grub_menu_t menu
, int nested
)
443 struct grub_term_output
*term
;
446 FOR_ACTIVE_TERM_OUTPUTS(term
)
447 if (term
->fullscreen
)
449 if (grub_env_get ("theme"))
451 if (!grub_gfxmenu_try_hook
)
453 grub_dl_load ("gfxmenu");
456 if (grub_gfxmenu_try_hook
)
459 err
= grub_gfxmenu_try_hook (entry
, menu
, nested
);
467 grub_error (GRUB_ERR_BAD_MODULE
,
468 N_("module `%s' isn't loaded"),
471 grub_wait_after_message ();
473 grub_errno
= GRUB_ERR_NONE
;
478 FOR_ACTIVE_TERM_OUTPUTS(term
)
482 if (grub_strcmp (term
->name
, "gfxterm") == 0 && gfxmenu
)
485 err
= grub_menu_try_text (term
, entry
, menu
, nested
);
489 grub_errno
= GRUB_ERR_NONE
;
496 struct grub_menu_viewer
*cur
;
497 for (cur
= viewers
; cur
; cur
= cur
->next
)
498 cur
->clear_timeout (cur
->data
);
502 grub_menu_register_viewer (struct grub_menu_viewer
*viewer
)
504 viewer
->next
= viewers
;
509 menuentry_eq (const char *id
, const char *spec
)
511 const char *ptr1
, *ptr2
;
516 if (*ptr2
== '>' && ptr2
[1] != '>' && *ptr1
== 0)
518 if (*ptr2
== '>' && ptr2
[1] != '>')
532 /* Get the entry number from the variable NAME. */
534 get_entry_number (grub_menu_t menu
, const char *name
)
539 val
= grub_env_get (name
);
545 entry
= (int) grub_strtoul (val
, 0, 0);
547 if (grub_errno
== GRUB_ERR_BAD_NUMBER
)
549 /* See if the variable matches the title of a menu entry. */
550 grub_menu_entry_t e
= menu
->entry_list
;
553 grub_errno
= GRUB_ERR_NONE
;
557 if (menuentry_eq (e
->title
, val
)
558 || menuentry_eq (e
->id
, val
))
570 if (grub_errno
!= GRUB_ERR_NONE
)
572 grub_errno
= GRUB_ERR_NONE
;
581 /* Check whether a second has elapsed since the last tick. If so, adjust
582 the timer and return 1; otherwise, return 0. */
584 has_second_elapsed (grub_uint64_t
*saved_time
)
586 grub_uint64_t current_time
;
588 current_time
= grub_get_time_ms ();
589 if (current_time
- *saved_time
>= 1000)
591 *saved_time
= current_time
;
599 print_countdown (struct grub_term_coordinate
*pos
, int n
)
601 grub_term_restore_pos (pos
);
602 /* NOTE: Do not remove the trailing space characters.
603 They are required to clear the line. */
604 grub_printf ("%d ", n
);
608 #define GRUB_MENU_PAGE_SIZE 10
610 /* Show the menu and handle menu entry selection. Returns the menu entry
611 index that should be executed or -1 if no entry should be executed (e.g.,
612 Esc pressed to exit a sub-menu or switching menu viewers).
613 If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu
614 entry to be executed is a result of an automatic default selection because
617 run_menu (grub_menu_t menu
, int nested
, int *auto_boot
)
620 grub_uint64_t saved_time
;
621 int default_entry
,current_entry
;
623 enum timeout_style timeout_style
;
625 default_entry
= get_entry_number (menu
, "default");
627 if (g_ventoy_suppress_esc
)
629 else if (g_ventoy_last_entry
>= 0 && g_ventoy_last_entry
< menu
->size
) {
630 default_entry
= g_ventoy_last_entry
;
632 /* If DEFAULT_ENTRY is not within the menu entries, fall back to
634 else if (default_entry
< 0 || default_entry
>= menu
->size
)
637 timeout
= grub_menu_get_timeout ();
639 /* If there is no timeout, the "countdown" and "hidden" styles result in
640 the system doing nothing and providing no or very little indication
641 why. Technically this is what the user asked for, but it's not very
642 useful and likely to be a source of confusion, so we disallow this. */
643 grub_env_unset ("timeout_style");
645 timeout_style
= get_timeout_style ();
647 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
648 || timeout_style
== TIMEOUT_STYLE_HIDDEN
)
650 static struct grub_term_coordinate
*pos
;
653 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
&& timeout
)
655 pos
= grub_term_save_pos ();
656 print_countdown (pos
, timeout
);
659 /* Enter interruptible sleep until Escape or a menu hotkey is pressed,
660 or the timeout expires. */
661 saved_time
= grub_get_time_ms ();
666 key
= grub_getkey_noblock ();
667 if (key
!= GRUB_TERM_NO_KEY
)
669 entry
= get_entry_index_by_hotkey (menu
, key
);
673 if (key
== GRUB_TERM_ESC
)
679 if (timeout
> 0 && has_second_elapsed (&saved_time
))
682 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
)
683 print_countdown (pos
, timeout
);
687 /* We will fall through to auto-booting the default entry. */
691 grub_env_unset ("timeout");
692 grub_env_unset ("timeout_style");
700 /* If timeout is 0, drawing is pointless (and ugly). */
704 return default_entry
;
707 current_entry
= default_entry
;
710 menu_set_chosen_tip(menu
, current_entry
);
711 menu_init (current_entry
, menu
, nested
);
713 /* Initialize the time. */
714 saved_time
= grub_get_time_ms ();
716 timeout
= grub_menu_get_timeout ();
719 menu_print_timeout (timeout
);
726 timeout
= grub_menu_get_timeout ();
728 if (grub_normal_exit_level
)
731 if (timeout
> 0 && has_second_elapsed (&saved_time
))
734 grub_menu_set_timeout (timeout
);
735 menu_print_timeout (timeout
);
740 grub_env_unset ("timeout");
743 return default_entry
;
746 c
= grub_getkey_noblock ();
748 /* Negative values are returned on error. */
749 if ((c
!= GRUB_TERM_NO_KEY
) && (c
> 0))
753 grub_env_unset ("timeout");
754 grub_env_unset ("fallback");
760 case GRUB_TERM_KEY_HOME
:
761 case GRUB_TERM_CTRL
| 'a':
763 menu_set_chosen_entry (menu
, current_entry
);
766 case GRUB_TERM_KEY_END
:
767 case GRUB_TERM_CTRL
| 'e':
768 current_entry
= menu
->size
- 1;
769 menu_set_chosen_entry (menu
, current_entry
);
772 case GRUB_TERM_KEY_UP
:
773 case GRUB_TERM_CTRL
| 'p':
775 if (current_entry
> 0)
777 menu_set_chosen_entry (menu
, current_entry
);
780 case GRUB_TERM_CTRL
| 'n':
781 case GRUB_TERM_KEY_DOWN
:
783 if (current_entry
< menu
->size
- 1)
785 menu_set_chosen_entry (menu
, current_entry
);
788 case GRUB_TERM_CTRL
| 'g':
789 case GRUB_TERM_KEY_PPAGE
:
790 if (current_entry
< GRUB_MENU_PAGE_SIZE
)
793 current_entry
-= GRUB_MENU_PAGE_SIZE
;
794 menu_set_chosen_entry (menu
, current_entry
);
797 case GRUB_TERM_CTRL
| 'c':
798 case GRUB_TERM_KEY_NPAGE
:
799 if (current_entry
+ GRUB_MENU_PAGE_SIZE
< menu
->size
)
800 current_entry
+= GRUB_MENU_PAGE_SIZE
;
802 current_entry
= menu
->size
- 1;
803 menu_set_chosen_entry (menu
, current_entry
);
808 // case GRUB_TERM_KEY_RIGHT:
809 case GRUB_TERM_CTRL
| 'f':
812 return current_entry
;
815 if (nested
&& 0 == g_ventoy_suppress_esc
)
824 grub_cmdline_run (1, 0);
830 grub_menu_entry_t e
= grub_menu_get_entry (menu
, current_entry
);
832 grub_menu_entry_run (e
);
836 case GRUB_TERM_KEY_F2
:
838 if (0 == g_ventoy_fn_mutex
) {
839 cmdstr
= grub_env_get("VTOY_F2_CMD");
843 g_ventoy_fn_mutex
= 1;
844 grub_script_execute_sourcecode(cmdstr
);
845 g_ventoy_fn_mutex
= 0;
850 case GRUB_TERM_KEY_F3
:
852 if (0 == g_ventoy_fn_mutex
) {
853 cmdstr
= grub_env_get("VTOY_F3_CMD");
857 grub_script_execute_sourcecode(cmdstr
);
862 case GRUB_TERM_KEY_F4
:
864 if (0 == g_ventoy_fn_mutex
) {
865 cmdstr
= grub_env_get("VTOY_F4_CMD");
869 g_ventoy_fn_mutex
= 1;
870 grub_script_execute_sourcecode(cmdstr
);
871 g_ventoy_fn_mutex
= 0;
876 case GRUB_TERM_KEY_F5
:
878 if (0 == g_ventoy_fn_mutex
) {
879 cmdstr
= grub_env_get("VTOY_F5_CMD");
883 g_ventoy_fn_mutex
= 1;
884 grub_script_execute_sourcecode(cmdstr
);
885 g_ventoy_fn_mutex
= 0;
890 case GRUB_TERM_KEY_F6
:
892 if (0 == g_ventoy_fn_mutex
) {
893 cmdstr
= grub_env_get("VTOY_F6_CMD");
897 g_ventoy_fn_mutex
= 1;
898 grub_script_execute_sourcecode(cmdstr
);
899 g_ventoy_fn_mutex
= 0;
904 case GRUB_TERM_KEY_F7
:
906 if (g_ventoy_terminal_output
== 0)
908 grub_script_execute_sourcecode("terminal_output console");
909 g_ventoy_terminal_output
= 1;
913 grub_script_execute_sourcecode("terminal_output gfxterm");
914 g_ventoy_terminal_output
= 0;
917 case GRUB_TERM_KEY_F1
:
920 g_ventoy_memdisk_mode
= 1 - g_ventoy_memdisk_mode
;
921 g_ventoy_menu_refresh
= 1;
924 case (GRUB_TERM_CTRL
| 'i'):
926 g_ventoy_iso_raw
= 1 - g_ventoy_iso_raw
;
927 g_ventoy_menu_refresh
= 1;
930 case (GRUB_TERM_CTRL
| 'r'):
932 g_ventoy_grub2_mode
= 1 - g_ventoy_grub2_mode
;
933 g_ventoy_menu_refresh
= 1;
936 case (GRUB_TERM_CTRL
| 'w'):
938 g_ventoy_wimboot_mode
= 1 - g_ventoy_wimboot_mode
;
939 g_ventoy_menu_refresh
= 1;
942 case (GRUB_TERM_CTRL
| 'u'):
944 g_ventoy_iso_uefi_drv
= 1 - g_ventoy_iso_uefi_drv
;
945 g_ventoy_menu_refresh
= 1;
952 entry
= get_entry_index_by_hotkey (menu
, c
);
965 /* Never reach here. */
968 /* Callback invoked immediately before a menu entry is executed. */
970 notify_booting (grub_menu_entry_t entry
,
971 void *userdata
__attribute__((unused
)))
974 grub_printf_ (N_("Booting `%s'"), entry
->title
);
975 grub_printf ("\n\n");
978 /* Callback invoked when a default menu entry executed because of a timeout
979 has failed and an attempt will be made to execute the next fallback
982 notify_fallback (grub_menu_entry_t entry
,
983 void *userdata
__attribute__((unused
)))
986 grub_printf_ (N_("Falling back to `%s'"), entry
->title
);
987 grub_printf ("\n\n");
988 grub_millisleep (DEFAULT_ENTRY_ERROR_DELAY_MS
);
991 /* Callback invoked when a menu entry has failed and there is no remaining
992 fallback entry to attempt. */
994 notify_execution_failure (void *userdata
__attribute__((unused
)))
996 if (grub_errno
!= GRUB_ERR_NONE
)
999 grub_errno
= GRUB_ERR_NONE
;
1001 grub_printf ("\n ");
1002 grub_printf_ (N_("Failed to boot both default and fallback entries.\n"));
1003 grub_wait_after_message ();
1006 /* Callbacks used by the text menu to provide user feedback when menu entries
1008 static struct grub_menu_execute_callback execution_callback
=
1010 .notify_booting
= notify_booting
,
1011 .notify_fallback
= notify_fallback
,
1012 .notify_failure
= notify_execution_failure
1016 show_menu (grub_menu_t menu
, int nested
, int autobooted
)
1019 def
= grub_env_get("VTOY_DEFAULT_IMAGE");
1024 grub_menu_entry_t e
;
1027 boot_entry
= run_menu (menu
, nested
, &auto_boot
);
1031 if (auto_boot
&& def
&& grub_strcmp(def
, "VTOY_EXIT") == 0) {
1035 if (autobooted
== 0 && auto_boot
== 0) {
1036 g_ventoy_last_entry
= boot_entry
;
1037 if (g_ventoy_menu_esc
)
1041 e
= grub_menu_get_entry (menu
, boot_entry
);
1043 continue; /* Menu is empty. */
1045 if (2 == e
->argc
&& e
->args
&& e
->args
[1] && grub_strncmp(e
->args
[1], "VTOY_RET", 8) == 0)
1051 grub_menu_execute_with_fallback (menu
, e
, autobooted
,
1052 &execution_callback
, 0);
1054 grub_menu_execute_entry (e
, 0);
1058 if (2 == e
->argc
&& e
->args
&& e
->args
[1] && grub_strncmp(e
->args
[1], "VTOY_RUN_RET", 12) == 0)
1062 return GRUB_ERR_NONE
;
1066 grub_show_menu (grub_menu_t menu
, int nested
, int autoboot
)
1068 grub_err_t err1
, err2
;
1072 err1
= show_menu (menu
, nested
, autoboot
);
1074 grub_print_error ();
1076 if (grub_normal_exit_level
)
1079 err2
= grub_auth_check_authentication (NULL
);
1082 grub_print_error ();
1083 grub_errno
= GRUB_ERR_NONE
;