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 #define VTOY_COMM_HOTKEY(cmdkey) \
53 if (0 == g_ventoy_fn_mutex) { \
54 cmdstr = grub_env_get(cmdkey); \
58 g_ventoy_fn_mutex = 1; \
59 grub_script_execute_sourcecode(cmdstr); \
60 g_ventoy_fn_mutex = 0; \
65 /* Time to delay after displaying an error message about a default/fallback
66 entry failing to boot. */
67 #define DEFAULT_ENTRY_ERROR_DELAY_MS 2500
69 grub_err_t (*grub_gfxmenu_try_hook
) (int entry
, grub_menu_t menu
,
74 TIMEOUT_STYLE_COUNTDOWN
,
78 struct timeout_style_name
{
80 enum timeout_style style
;
81 } timeout_style_names
[] = {
82 {"menu", TIMEOUT_STYLE_MENU
},
83 {"countdown", TIMEOUT_STYLE_COUNTDOWN
},
84 {"hidden", TIMEOUT_STYLE_HIDDEN
},
88 /* Wait until the user pushes any key so that the user
89 can see what happened. */
91 grub_wait_after_message (void)
93 grub_uint64_t endtime
;
95 grub_printf_ (N_("Press any key to continue..."));
98 endtime
= grub_get_time_ms () + 10000;
100 while (grub_get_time_ms () < endtime
101 && grub_getkey_noblock () == GRUB_TERM_NO_KEY
);
106 /* Get a menu entry by its index in the entry list. */
108 grub_menu_get_entry (grub_menu_t menu
, int no
)
112 for (e
= menu
->entry_list
; e
&& no
> 0; e
= e
->next
, no
--)
118 /* Get the index of a menu entry associated with a given hotkey, or -1. */
120 get_entry_index_by_hotkey (grub_menu_t menu
, int hotkey
)
122 grub_menu_entry_t entry
;
125 for (i
= 0, entry
= menu
->entry_list
; i
< menu
->size
;
126 i
++, entry
= entry
->next
)
127 if (entry
->hotkey
== hotkey
)
133 /* Return the timeout style. If the variable "timeout_style" is not set or
134 invalid, default to TIMEOUT_STYLE_MENU. */
135 static enum timeout_style
136 get_timeout_style (void)
139 struct timeout_style_name
*style_name
;
141 val
= grub_env_get ("timeout_style");
143 return TIMEOUT_STYLE_MENU
;
145 for (style_name
= timeout_style_names
; style_name
->name
; style_name
++)
146 if (grub_strcmp (style_name
->name
, val
) == 0)
147 return style_name
->style
;
149 return TIMEOUT_STYLE_MENU
;
152 /* Return the current timeout. If the variable "timeout" is not set or
153 invalid, return -1. */
155 grub_menu_get_timeout (void)
160 val
= grub_env_get ("timeout");
166 timeout
= (int) grub_strtoul (val
, 0, 0);
168 /* If the value is invalid, unset the variable. */
169 if (grub_errno
!= GRUB_ERR_NONE
)
171 grub_env_unset ("timeout");
172 grub_errno
= GRUB_ERR_NONE
;
181 /* Set current timeout in the variable "timeout". */
183 grub_menu_set_timeout (int timeout
)
185 /* Ignore TIMEOUT if it is zero, because it will be unset really soon. */
190 grub_snprintf (buf
, sizeof (buf
), "%d", timeout
);
191 grub_env_set ("timeout", buf
);
195 /* Get the first entry number from the value of the environment variable NAME,
196 which is a space-separated list of non-negative integers. The entry number
197 which is returned is stripped from the value of NAME. If no entry number
198 can be found, -1 is returned. */
200 get_and_remove_first_entry_number (const char *name
)
206 val
= grub_env_get (name
);
212 entry
= (int) grub_strtoul (val
, &tail
, 0);
214 if (grub_errno
== GRUB_ERR_NONE
)
216 /* Skip whitespace to find the next digit. */
217 while (*tail
&& grub_isspace (*tail
))
219 grub_env_set (name
, tail
);
223 grub_env_unset (name
);
224 grub_errno
= GRUB_ERR_NONE
;
233 /* Run a menu entry. */
235 grub_menu_execute_entry(grub_menu_entry_t entry
, int auto_boot
)
237 grub_err_t err
= GRUB_ERR_NONE
;
239 grub_menu_t menu
= NULL
;
240 char *optr
, *buf
, *oldchosen
= NULL
, *olddefault
= NULL
;
241 const char *ptr
, *chosen
, *def
;
244 if (entry
->restricted
)
245 err
= grub_auth_check_authentication (entry
->users
);
250 grub_errno
= GRUB_ERR_NONE
;
254 errs_before
= grub_err_printed_errors
;
256 chosen
= grub_env_get ("chosen");
257 def
= grub_env_get ("default");
261 grub_env_context_open ();
262 menu
= grub_zalloc (sizeof (*menu
));
265 grub_env_set_menu (menu
);
267 grub_env_set ("timeout", "0");
270 for (ptr
= entry
->id
; *ptr
; ptr
++)
271 sz
+= (*ptr
== '>') ? 2 : 1;
274 oldchosen
= grub_strdup (chosen
);
280 olddefault
= grub_strdup (def
);
286 sz
+= grub_strlen (chosen
);
288 buf
= grub_malloc (sz
);
296 optr
= grub_stpcpy (optr
, chosen
);
299 for (ptr
= entry
->id
; *ptr
; ptr
++)
306 grub_env_set ("chosen", buf
);
307 grub_env_export ("chosen");
311 for (ptr
= def
; ptr
&& *ptr
; ptr
++)
313 if (ptr
[0] == '>' && ptr
[1] == '>')
322 if (ptr
&& ptr
[0] && ptr
[1])
323 grub_env_set ("default", ptr
+ 1);
325 grub_env_unset ("default");
327 grub_script_execute_new_scope (entry
->sourcecode
, entry
->argc
, entry
->args
);
329 if (errs_before
!= grub_err_printed_errors
)
330 grub_wait_after_message ();
332 errs_before
= grub_err_printed_errors
;
334 if (grub_errno
== GRUB_ERR_NONE
&& grub_loader_is_loaded ())
335 /* Implicit execution of boot, only if something is loaded. */
336 grub_command_execute ("boot", 0, 0);
338 if (errs_before
!= grub_err_printed_errors
)
339 grub_wait_after_message ();
343 if (menu
&& menu
->size
)
345 grub_show_menu (menu
, 1, auto_boot
);
346 grub_normal_free_menu (menu
);
348 grub_env_context_close ();
351 grub_env_set ("chosen", oldchosen
);
353 grub_env_unset ("chosen");
355 grub_env_set ("default", olddefault
);
357 grub_env_unset ("default");
358 grub_env_unset ("timeout");
361 /* Execute ENTRY from the menu MENU, falling back to entries specified
362 in the environment variable "fallback" if it fails. CALLBACK is a
363 pointer to a struct of function pointers which are used to allow the
364 caller provide feedback to the user. */
366 grub_menu_execute_with_fallback (grub_menu_t menu
,
367 grub_menu_entry_t entry
,
369 grub_menu_execute_callback_t callback
,
374 callback
->notify_booting (entry
, callback_data
);
376 grub_menu_execute_entry (entry
, 1);
378 /* Deal with fallback entries. */
379 while ((fallback_entry
= get_and_remove_first_entry_number ("fallback"))
383 grub_errno
= GRUB_ERR_NONE
;
385 entry
= grub_menu_get_entry (menu
, fallback_entry
);
386 callback
->notify_fallback (entry
, callback_data
);
387 grub_menu_execute_entry (entry
, 1);
388 /* If the function call to execute the entry returns at all, then this is
389 taken to indicate a boot failure. For menu entries that do something
390 other than actually boot an operating system, this could assume
391 incorrectly that something failed. */
395 callback
->notify_failure (callback_data
);
398 static struct grub_menu_viewer
*viewers
;
400 int g_menu_update_mode
= 0;
401 int g_ventoy_tip_label_enable
= 0;
402 const char * g_ventoy_tip_msg1
= NULL
;
403 const char * g_ventoy_tip_msg2
= NULL
;
404 static const char *g_ventoy_cur_img_path
= NULL
;
405 static void menu_set_chosen_tip(grub_menu_t menu
, int entry
)
408 grub_menu_entry_t e
= grub_menu_get_entry (menu
, entry
);
410 g_ventoy_tip_msg1
= g_ventoy_tip_msg2
= NULL
;
411 if (e
&& e
->id
&& grub_strncmp(e
->id
, "VID_", 4) == 0)
413 img
= (img_info
*)(void *)grub_strtoul(e
->id
+ 4, NULL
, 16);
416 g_ventoy_tip_msg1
= img
->tip1
;
417 g_ventoy_tip_msg2
= img
->tip2
;
418 g_ventoy_cur_img_path
= img
->path
;
424 menu_set_chosen_entry (grub_menu_t menu
, int entry
)
426 struct grub_menu_viewer
*cur
;
428 menu_set_chosen_tip(menu
, entry
);
429 for (cur
= viewers
; cur
; cur
= cur
->next
)
430 cur
->set_chosen_entry (entry
, cur
->data
);
434 menu_print_timeout (int timeout
)
436 struct grub_menu_viewer
*cur
;
437 for (cur
= viewers
; cur
; cur
= cur
->next
)
438 cur
->print_timeout (timeout
, cur
->data
);
444 struct grub_menu_viewer
*cur
, *next
;
445 for (cur
= viewers
; cur
; cur
= next
)
448 cur
->fini (cur
->data
);
455 menu_init (int entry
, grub_menu_t menu
, int nested
)
457 struct grub_term_output
*term
;
460 FOR_ACTIVE_TERM_OUTPUTS(term
)
461 if (term
->fullscreen
)
463 if (grub_env_get ("theme"))
465 if (!grub_gfxmenu_try_hook
)
467 grub_dl_load ("gfxmenu");
470 if (grub_gfxmenu_try_hook
)
473 err
= grub_gfxmenu_try_hook (entry
, menu
, nested
);
481 grub_error (GRUB_ERR_BAD_MODULE
,
482 N_("module `%s' isn't loaded"),
485 grub_wait_after_message ();
487 grub_errno
= GRUB_ERR_NONE
;
492 FOR_ACTIVE_TERM_OUTPUTS(term
)
496 if (grub_strcmp (term
->name
, "gfxterm") == 0 && gfxmenu
)
499 err
= grub_menu_try_text (term
, entry
, menu
, nested
);
503 grub_errno
= GRUB_ERR_NONE
;
510 struct grub_menu_viewer
*cur
;
511 for (cur
= viewers
; cur
; cur
= cur
->next
)
512 cur
->clear_timeout (cur
->data
);
516 grub_menu_register_viewer (struct grub_menu_viewer
*viewer
)
518 viewer
->next
= viewers
;
523 menuentry_eq (const char *id
, const char *spec
)
525 const char *ptr1
, *ptr2
;
530 if (*ptr2
== '>' && ptr2
[1] != '>' && *ptr1
== 0)
532 if (*ptr2
== '>' && ptr2
[1] != '>')
546 /* Get the entry number from the variable NAME. */
548 get_entry_number (grub_menu_t menu
, const char *name
)
553 val
= grub_env_get (name
);
559 entry
= (int) grub_strtoul (val
, 0, 0);
561 if (grub_errno
== GRUB_ERR_BAD_NUMBER
)
563 /* See if the variable matches the title of a menu entry. */
564 grub_menu_entry_t e
= menu
->entry_list
;
567 grub_errno
= GRUB_ERR_NONE
;
571 if (menuentry_eq (e
->title
, val
)
572 || menuentry_eq (e
->id
, val
))
584 if (grub_errno
!= GRUB_ERR_NONE
)
586 grub_errno
= GRUB_ERR_NONE
;
595 /* Check whether a second has elapsed since the last tick. If so, adjust
596 the timer and return 1; otherwise, return 0. */
598 has_second_elapsed (grub_uint64_t
*saved_time
)
600 grub_uint64_t current_time
;
602 current_time
= grub_get_time_ms ();
603 if (current_time
- *saved_time
>= 1000)
605 *saved_time
= current_time
;
613 print_countdown (struct grub_term_coordinate
*pos
, int n
)
615 grub_term_restore_pos (pos
);
616 /* NOTE: Do not remove the trailing space characters.
617 They are required to clear the line. */
618 grub_printf ("%d ", n
);
622 #define GRUB_MENU_PAGE_SIZE 10
624 /* Show the menu and handle menu entry selection. Returns the menu entry
625 index that should be executed or -1 if no entry should be executed (e.g.,
626 Esc pressed to exit a sub-menu or switching menu viewers).
627 If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu
628 entry to be executed is a result of an automatic default selection because
631 run_menu (grub_menu_t menu
, int nested
, int *auto_boot
)
634 grub_uint64_t saved_time
;
635 int default_entry
,current_entry
;
637 enum timeout_style timeout_style
;
639 default_entry
= get_entry_number (menu
, "default");
641 if (g_ventoy_suppress_esc
)
643 else if (g_ventoy_last_entry
>= 0 && g_ventoy_last_entry
< menu
->size
) {
644 default_entry
= g_ventoy_last_entry
;
646 /* If DEFAULT_ENTRY is not within the menu entries, fall back to
648 else if (default_entry
< 0 || default_entry
>= menu
->size
)
651 timeout
= grub_menu_get_timeout ();
653 /* If there is no timeout, the "countdown" and "hidden" styles result in
654 the system doing nothing and providing no or very little indication
655 why. Technically this is what the user asked for, but it's not very
656 useful and likely to be a source of confusion, so we disallow this. */
657 grub_env_unset ("timeout_style");
659 timeout_style
= get_timeout_style ();
661 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
662 || timeout_style
== TIMEOUT_STYLE_HIDDEN
)
664 static struct grub_term_coordinate
*pos
;
667 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
&& timeout
)
669 pos
= grub_term_save_pos ();
670 print_countdown (pos
, timeout
);
673 /* Enter interruptible sleep until Escape or a menu hotkey is pressed,
674 or the timeout expires. */
675 saved_time
= grub_get_time_ms ();
680 key
= grub_getkey_noblock ();
681 if (key
!= GRUB_TERM_NO_KEY
)
683 entry
= get_entry_index_by_hotkey (menu
, key
);
687 if (key
== GRUB_TERM_ESC
)
693 if (timeout
> 0 && has_second_elapsed (&saved_time
))
696 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
)
697 print_countdown (pos
, timeout
);
701 /* We will fall through to auto-booting the default entry. */
705 grub_env_unset ("timeout");
706 grub_env_unset ("timeout_style");
714 /* If timeout is 0, drawing is pointless (and ugly). */
718 return default_entry
;
721 current_entry
= default_entry
;
724 menu_set_chosen_tip(menu
, current_entry
);
725 menu_init (current_entry
, menu
, nested
);
727 /* Initialize the time. */
728 saved_time
= grub_get_time_ms ();
730 timeout
= grub_menu_get_timeout ();
733 menu_print_timeout (timeout
);
740 timeout
= grub_menu_get_timeout ();
742 if (grub_normal_exit_level
)
745 if (timeout
> 0 && has_second_elapsed (&saved_time
))
748 grub_menu_set_timeout (timeout
);
749 menu_print_timeout (timeout
);
754 grub_env_unset ("timeout");
757 return default_entry
;
760 c
= grub_getkey_noblock ();
762 /* Negative values are returned on error. */
763 if ((c
!= GRUB_TERM_NO_KEY
) && (c
> 0))
767 grub_env_unset ("timeout");
768 grub_env_unset ("fallback");
774 case GRUB_TERM_KEY_HOME
:
775 case GRUB_TERM_CTRL
| 'a':
777 menu_set_chosen_entry (menu
, current_entry
);
780 case GRUB_TERM_KEY_END
:
781 case GRUB_TERM_CTRL
| 'e':
782 current_entry
= menu
->size
- 1;
783 menu_set_chosen_entry (menu
, current_entry
);
786 case GRUB_TERM_KEY_UP
:
787 case GRUB_TERM_CTRL
| 'p':
789 if (current_entry
> 0)
791 menu_set_chosen_entry (menu
, current_entry
);
794 case GRUB_TERM_CTRL
| 'n':
795 case GRUB_TERM_KEY_DOWN
:
797 if (current_entry
< menu
->size
- 1)
799 menu_set_chosen_entry (menu
, current_entry
);
802 case GRUB_TERM_CTRL
| 'g':
803 case GRUB_TERM_KEY_PPAGE
:
804 if (current_entry
< GRUB_MENU_PAGE_SIZE
)
807 current_entry
-= GRUB_MENU_PAGE_SIZE
;
808 menu_set_chosen_entry (menu
, current_entry
);
811 case GRUB_TERM_CTRL
| 'c':
812 case GRUB_TERM_KEY_NPAGE
:
813 if (current_entry
+ GRUB_MENU_PAGE_SIZE
< menu
->size
)
814 current_entry
+= GRUB_MENU_PAGE_SIZE
;
816 current_entry
= menu
->size
- 1;
817 menu_set_chosen_entry (menu
, current_entry
);
822 // case GRUB_TERM_KEY_RIGHT:
823 case GRUB_TERM_CTRL
| 'f':
826 return current_entry
;
829 if (nested
&& 0 == g_ventoy_suppress_esc
)
838 grub_cmdline_run (1, 0);
844 grub_menu_entry_t e
= grub_menu_get_entry (menu
, current_entry
);
846 grub_menu_entry_run (e
);
850 case GRUB_TERM_KEY_F2
:
852 VTOY_COMM_HOTKEY("VTOY_F2_CMD");
854 case GRUB_TERM_KEY_F3
:
856 VTOY_COMM_HOTKEY("VTOY_F3_CMD");
858 case GRUB_TERM_KEY_F4
:
860 VTOY_COMM_HOTKEY("VTOY_F4_CMD");
862 case GRUB_TERM_KEY_F5
:
864 VTOY_COMM_HOTKEY("VTOY_F5_CMD");
866 case GRUB_TERM_KEY_F6
:
868 VTOY_COMM_HOTKEY("VTOY_F6_CMD");
870 case GRUB_TERM_KEY_F7
:
872 if (g_ventoy_terminal_output
== 0)
874 grub_script_execute_sourcecode("terminal_output console");
875 g_ventoy_terminal_output
= 1;
879 grub_script_execute_sourcecode("terminal_output gfxterm");
880 g_ventoy_terminal_output
= 0;
883 case GRUB_TERM_KEY_F1
:
886 g_ventoy_memdisk_mode
= 1 - g_ventoy_memdisk_mode
;
887 g_ventoy_menu_refresh
= 1;
890 case (GRUB_TERM_CTRL
| 'i'):
892 g_ventoy_iso_raw
= 1 - g_ventoy_iso_raw
;
893 g_ventoy_menu_refresh
= 1;
896 case (GRUB_TERM_CTRL
| 'r'):
898 g_ventoy_grub2_mode
= 1 - g_ventoy_grub2_mode
;
899 g_ventoy_menu_refresh
= 1;
902 case (GRUB_TERM_CTRL
| 'w'):
904 g_ventoy_wimboot_mode
= 1 - g_ventoy_wimboot_mode
;
905 g_ventoy_menu_refresh
= 1;
908 case (GRUB_TERM_CTRL
| 'u'):
910 g_ventoy_iso_uefi_drv
= 1 - g_ventoy_iso_uefi_drv
;
911 g_ventoy_menu_refresh
= 1;
914 case (GRUB_TERM_CTRL
| 'h'):
916 cmdstr
= grub_env_get("VTOY_HELP_CMD");
919 grub_script_execute_sourcecode(cmdstr
);
920 while (grub_getkey() != GRUB_TERM_ESC
)
927 case (GRUB_TERM_CTRL
| 'm'):
929 if (g_ventoy_cur_img_path
)
931 grub_env_set("VTOY_CHKSUM_FILE_PATH", g_ventoy_cur_img_path
);
932 cmdstr
= grub_env_get("VTOY_CHKSUM_CMD");
936 grub_script_execute_sourcecode(cmdstr
);
942 grub_env_set("VTOY_CHKSUM_FILE_PATH", "X");
950 entry
= get_entry_index_by_hotkey (menu
, c
);
963 /* Never reach here. */
966 /* Callback invoked immediately before a menu entry is executed. */
968 notify_booting (grub_menu_entry_t entry
,
969 void *userdata
__attribute__((unused
)))
972 grub_printf_ (N_("Booting `%s'"), entry
->title
);
973 grub_printf ("\n\n");
976 /* Callback invoked when a default menu entry executed because of a timeout
977 has failed and an attempt will be made to execute the next fallback
980 notify_fallback (grub_menu_entry_t entry
,
981 void *userdata
__attribute__((unused
)))
984 grub_printf_ (N_("Falling back to `%s'"), entry
->title
);
985 grub_printf ("\n\n");
986 grub_millisleep (DEFAULT_ENTRY_ERROR_DELAY_MS
);
989 /* Callback invoked when a menu entry has failed and there is no remaining
990 fallback entry to attempt. */
992 notify_execution_failure (void *userdata
__attribute__((unused
)))
994 if (grub_errno
!= GRUB_ERR_NONE
)
997 grub_errno
= GRUB_ERR_NONE
;
1000 grub_printf_ (N_("Failed to boot both default and fallback entries.\n"));
1001 grub_wait_after_message ();
1004 /* Callbacks used by the text menu to provide user feedback when menu entries
1006 static struct grub_menu_execute_callback execution_callback
=
1008 .notify_booting
= notify_booting
,
1009 .notify_fallback
= notify_fallback
,
1010 .notify_failure
= notify_execution_failure
1014 show_menu (grub_menu_t menu
, int nested
, int autobooted
)
1017 def
= grub_env_get("VTOY_DEFAULT_IMAGE");
1022 grub_menu_entry_t e
;
1025 boot_entry
= run_menu (menu
, nested
, &auto_boot
);
1029 if (auto_boot
&& def
&& grub_strcmp(def
, "VTOY_EXIT") == 0) {
1033 if (autobooted
== 0 && auto_boot
== 0) {
1034 g_ventoy_last_entry
= boot_entry
;
1035 if (g_ventoy_menu_esc
)
1039 e
= grub_menu_get_entry (menu
, boot_entry
);
1041 continue; /* Menu is empty. */
1043 if (2 == e
->argc
&& e
->args
&& e
->args
[1] && grub_strncmp(e
->args
[1], "VTOY_RET", 8) == 0)
1049 grub_menu_execute_with_fallback (menu
, e
, autobooted
,
1050 &execution_callback
, 0);
1052 grub_menu_execute_entry (e
, 0);
1056 if (2 == e
->argc
&& e
->args
&& e
->args
[1] && grub_strncmp(e
->args
[1], "VTOY_RUN_RET", 12) == 0)
1060 return GRUB_ERR_NONE
;
1064 grub_show_menu (grub_menu_t menu
, int nested
, int autoboot
)
1066 grub_err_t err1
, err2
;
1070 err1
= show_menu (menu
, nested
, autoboot
);
1072 grub_print_error ();
1074 if (grub_normal_exit_level
)
1077 err2
= grub_auth_check_authentication (NULL
);
1080 grub_print_error ();
1081 grub_errno
= GRUB_ERR_NONE
;