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_suppress_esc_default
= 1;
49 int g_ventoy_menu_esc
= 0;
50 int g_ventoy_fn_mutex
= 0;
51 int g_ventoy_secondary_menu_on
= 0;
52 int g_ventoy_terminal_output
= 0;
54 #define VTOY_COMM_HOTKEY(cmdkey) \
55 if (0 == g_ventoy_fn_mutex && 0 == g_ventoy_secondary_menu_on) { \
56 cmdstr = grub_env_get(cmdkey); \
60 g_ventoy_fn_mutex = 1; \
61 grub_script_execute_sourcecode(cmdstr); \
62 g_ventoy_fn_mutex = 0; \
67 /* Time to delay after displaying an error message about a default/fallback
68 entry failing to boot. */
69 #define DEFAULT_ENTRY_ERROR_DELAY_MS 2500
71 grub_err_t (*grub_gfxmenu_try_hook
) (int entry
, grub_menu_t menu
,
76 TIMEOUT_STYLE_COUNTDOWN
,
80 struct timeout_style_name
{
82 enum timeout_style style
;
83 } timeout_style_names
[] = {
84 {"menu", TIMEOUT_STYLE_MENU
},
85 {"countdown", TIMEOUT_STYLE_COUNTDOWN
},
86 {"hidden", TIMEOUT_STYLE_HIDDEN
},
90 /* Wait until the user pushes any key so that the user
91 can see what happened. */
93 grub_wait_after_message (void)
95 grub_uint64_t endtime
;
97 grub_printf_ (N_("Press any key to continue..."));
100 endtime
= grub_get_time_ms () + 10000;
102 while (grub_get_time_ms () < endtime
103 && grub_getkey_noblock () == GRUB_TERM_NO_KEY
);
108 /* Get a menu entry by its index in the entry list. */
110 grub_menu_get_entry (grub_menu_t menu
, int no
)
114 for (e
= menu
->entry_list
; e
&& no
> 0; e
= e
->next
, no
--)
120 /* Get the index of a menu entry associated with a given hotkey, or -1. */
122 get_entry_index_by_hotkey (grub_menu_t menu
, int hotkey
)
124 grub_menu_entry_t entry
;
127 for (i
= 0, entry
= menu
->entry_list
; i
< menu
->size
;
128 i
++, entry
= entry
->next
)
129 if (entry
->hotkey
== hotkey
)
135 /* Return the timeout style. If the variable "timeout_style" is not set or
136 invalid, default to TIMEOUT_STYLE_MENU. */
137 static enum timeout_style
138 get_timeout_style (void)
141 struct timeout_style_name
*style_name
;
143 val
= grub_env_get ("timeout_style");
145 return TIMEOUT_STYLE_MENU
;
147 for (style_name
= timeout_style_names
; style_name
->name
; style_name
++)
148 if (grub_strcmp (style_name
->name
, val
) == 0)
149 return style_name
->style
;
151 return TIMEOUT_STYLE_MENU
;
154 /* Return the current timeout. If the variable "timeout" is not set or
155 invalid, return -1. */
157 grub_menu_get_timeout (void)
162 val
= grub_env_get ("timeout");
168 timeout
= (int) grub_strtoul (val
, 0, 0);
170 /* If the value is invalid, unset the variable. */
171 if (grub_errno
!= GRUB_ERR_NONE
)
173 grub_env_unset ("timeout");
174 grub_errno
= GRUB_ERR_NONE
;
183 /* Set current timeout in the variable "timeout". */
185 grub_menu_set_timeout (int timeout
)
187 /* Ignore TIMEOUT if it is zero, because it will be unset really soon. */
192 grub_snprintf (buf
, sizeof (buf
), "%d", timeout
);
193 grub_env_set ("timeout", buf
);
197 /* Get the first entry number from the value of the environment variable NAME,
198 which is a space-separated list of non-negative integers. The entry number
199 which is returned is stripped from the value of NAME. If no entry number
200 can be found, -1 is returned. */
202 get_and_remove_first_entry_number (const char *name
)
208 val
= grub_env_get (name
);
214 entry
= (int) grub_strtoul (val
, &tail
, 0);
216 if (grub_errno
== GRUB_ERR_NONE
)
218 /* Skip whitespace to find the next digit. */
219 while (*tail
&& grub_isspace (*tail
))
221 grub_env_set (name
, tail
);
225 grub_env_unset (name
);
226 grub_errno
= GRUB_ERR_NONE
;
235 /* Run a menu entry. */
237 grub_menu_execute_entry(grub_menu_entry_t entry
, int auto_boot
)
239 grub_err_t err
= GRUB_ERR_NONE
;
241 grub_menu_t menu
= NULL
;
242 char *optr
, *buf
, *oldchosen
= NULL
, *olddefault
= NULL
;
243 const char *ptr
, *chosen
, *def
;
246 if (entry
->restricted
)
247 err
= grub_auth_check_authentication (entry
->users
);
252 grub_errno
= GRUB_ERR_NONE
;
256 errs_before
= grub_err_printed_errors
;
258 chosen
= grub_env_get ("chosen");
259 def
= grub_env_get ("default");
263 grub_env_context_open ();
264 menu
= grub_zalloc (sizeof (*menu
));
267 grub_env_set_menu (menu
);
269 grub_env_set ("timeout", "0");
272 for (ptr
= entry
->id
; *ptr
; ptr
++)
273 sz
+= (*ptr
== '>') ? 2 : 1;
276 oldchosen
= grub_strdup (chosen
);
282 olddefault
= grub_strdup (def
);
288 sz
+= grub_strlen (chosen
);
290 buf
= grub_malloc (sz
);
298 optr
= grub_stpcpy (optr
, chosen
);
301 for (ptr
= entry
->id
; *ptr
; ptr
++)
308 grub_env_set ("chosen", buf
);
309 grub_env_export ("chosen");
313 for (ptr
= def
; ptr
&& *ptr
; ptr
++)
315 if (ptr
[0] == '>' && ptr
[1] == '>')
324 if (ptr
&& ptr
[0] && ptr
[1])
325 grub_env_set ("default", ptr
+ 1);
327 grub_env_unset ("default");
329 grub_script_execute_new_scope (entry
->sourcecode
, entry
->argc
, entry
->args
);
331 if (errs_before
!= grub_err_printed_errors
)
332 grub_wait_after_message ();
334 errs_before
= grub_err_printed_errors
;
336 if (grub_errno
== GRUB_ERR_NONE
&& grub_loader_is_loaded ())
337 /* Implicit execution of boot, only if something is loaded. */
338 grub_command_execute ("boot", 0, 0);
340 if (errs_before
!= grub_err_printed_errors
)
341 grub_wait_after_message ();
345 if (menu
&& menu
->size
)
347 grub_show_menu (menu
, 1, auto_boot
);
348 grub_normal_free_menu (menu
);
350 grub_env_context_close ();
353 grub_env_set ("chosen", oldchosen
);
355 grub_env_unset ("chosen");
357 grub_env_set ("default", olddefault
);
359 grub_env_unset ("default");
360 grub_env_unset ("timeout");
363 /* Execute ENTRY from the menu MENU, falling back to entries specified
364 in the environment variable "fallback" if it fails. CALLBACK is a
365 pointer to a struct of function pointers which are used to allow the
366 caller provide feedback to the user. */
368 grub_menu_execute_with_fallback (grub_menu_t menu
,
369 grub_menu_entry_t entry
,
371 grub_menu_execute_callback_t callback
,
376 callback
->notify_booting (entry
, callback_data
);
378 grub_menu_execute_entry (entry
, 1);
380 /* Deal with fallback entries. */
381 while ((fallback_entry
= get_and_remove_first_entry_number ("fallback"))
385 grub_errno
= GRUB_ERR_NONE
;
387 entry
= grub_menu_get_entry (menu
, fallback_entry
);
388 callback
->notify_fallback (entry
, callback_data
);
389 grub_menu_execute_entry (entry
, 1);
390 /* If the function call to execute the entry returns at all, then this is
391 taken to indicate a boot failure. For menu entries that do something
392 other than actually boot an operating system, this could assume
393 incorrectly that something failed. */
397 callback
->notify_failure (callback_data
);
400 static struct grub_menu_viewer
*viewers
;
402 int g_menu_update_mode
= 0;
403 int g_ventoy_tip_label_enable
= 0;
404 const char * g_ventoy_tip_msg1
= NULL
;
405 const char * g_ventoy_tip_msg2
= NULL
;
406 char g_ventoy_theme_path
[256] = {0};
407 static const char *g_ventoy_cur_img_path
= NULL
;
408 static void menu_set_chosen_tip(grub_menu_t menu
, int entry
)
413 grub_menu_entry_t e
= grub_menu_get_entry (menu
, entry
);
415 if (g_ventoy_theme_path
[0])
417 grub_env_set("theme", g_ventoy_theme_path
);
420 g_ventoy_tip_msg1
= g_ventoy_tip_msg2
= NULL
;
421 if (e
&& e
->id
&& grub_strncmp(e
->id
, "VID_", 4) == 0)
423 g_ventoy_theme_path
[0] = 0;
424 img
= (img_info
*)(void *)grub_strtoul(e
->id
+ 4, NULL
, 16);
427 g_ventoy_tip_msg1
= img
->tip1
;
428 g_ventoy_tip_msg2
= img
->tip2
;
429 g_ventoy_cur_img_path
= img
->path
;
432 else if (e
&& e
->id
&& grub_strncmp(e
->id
, "DIR_", 4) == 0)
434 g_ventoy_theme_path
[0] = 0;
435 for (i
= 0; i
< e
->argc
; i
++)
437 if (e
->args
[i
] && grub_strncmp(e
->args
[i
], "_VTIP_", 6) == 0)
445 tip
= (menu_tip
*)(void *)grub_strtoul(e
->args
[i
] + 6, NULL
, 16);
448 g_ventoy_tip_msg1
= tip
->tip1
;
449 g_ventoy_tip_msg2
= tip
->tip2
;
456 menu_set_chosen_entry (grub_menu_t menu
, int entry
)
458 struct grub_menu_viewer
*cur
;
460 menu_set_chosen_tip(menu
, entry
);
461 for (cur
= viewers
; cur
; cur
= cur
->next
)
462 cur
->set_chosen_entry (entry
, cur
->data
);
466 menu_scroll_chosen_entry (int diren
)
468 struct grub_menu_viewer
*cur
;
469 for (cur
= viewers
; cur
; cur
= cur
->next
)
470 if (cur
->scroll_chosen_entry
)
471 cur
->scroll_chosen_entry (cur
->data
, diren
);
475 menu_print_timeout (int timeout
)
477 struct grub_menu_viewer
*cur
;
478 for (cur
= viewers
; cur
; cur
= cur
->next
)
479 cur
->print_timeout (timeout
, cur
->data
);
485 struct grub_menu_viewer
*cur
, *next
;
486 for (cur
= viewers
; cur
; cur
= next
)
489 cur
->fini (cur
->data
);
496 menu_init (int entry
, grub_menu_t menu
, int nested
)
498 struct grub_term_output
*term
;
501 FOR_ACTIVE_TERM_OUTPUTS(term
)
502 if (term
->fullscreen
)
504 if (grub_env_get ("theme"))
506 if (!grub_gfxmenu_try_hook
)
508 grub_dl_load ("gfxmenu");
511 if (grub_gfxmenu_try_hook
)
514 err
= grub_gfxmenu_try_hook (entry
, menu
, nested
);
522 grub_error (GRUB_ERR_BAD_MODULE
,
523 N_("module `%s' isn't loaded"),
526 grub_wait_after_message ();
528 grub_errno
= GRUB_ERR_NONE
;
533 FOR_ACTIVE_TERM_OUTPUTS(term
)
537 if (grub_strcmp (term
->name
, "gfxterm") == 0 && gfxmenu
)
540 err
= grub_menu_try_text (term
, entry
, menu
, nested
);
544 grub_errno
= GRUB_ERR_NONE
;
551 struct grub_menu_viewer
*cur
;
552 for (cur
= viewers
; cur
; cur
= cur
->next
)
553 cur
->clear_timeout (cur
->data
);
557 grub_menu_register_viewer (struct grub_menu_viewer
*viewer
)
559 viewer
->next
= viewers
;
564 menuentry_eq (const char *id
, const char *spec
)
566 const char *ptr1
, *ptr2
;
571 if (*ptr2
== '>' && ptr2
[1] != '>' && *ptr1
== 0)
573 if (*ptr2
== '>' && ptr2
[1] != '>')
587 /* Get the entry number from the variable NAME. */
589 get_entry_number (grub_menu_t menu
, const char *name
)
594 val
= grub_env_get (name
);
600 entry
= (int) grub_strtoul (val
, 0, 0);
602 if (grub_errno
== GRUB_ERR_BAD_NUMBER
)
604 /* See if the variable matches the title of a menu entry. */
605 grub_menu_entry_t e
= menu
->entry_list
;
608 grub_errno
= GRUB_ERR_NONE
;
612 if (menuentry_eq (e
->title
, val
)
613 || menuentry_eq (e
->id
, val
))
625 if (grub_errno
!= GRUB_ERR_NONE
)
627 grub_errno
= GRUB_ERR_NONE
;
636 /* Check whether a second has elapsed since the last tick. If so, adjust
637 the timer and return 1; otherwise, return 0. */
639 has_second_elapsed (grub_uint64_t
*saved_time
)
641 grub_uint64_t current_time
;
643 current_time
= grub_get_time_ms ();
644 if (current_time
- *saved_time
>= 1000)
646 *saved_time
= current_time
;
654 print_countdown (struct grub_term_coordinate
*pos
, int n
)
656 grub_term_restore_pos (pos
);
657 /* NOTE: Do not remove the trailing space characters.
658 They are required to clear the line. */
659 grub_printf ("%d ", n
);
663 #define GRUB_MENU_PAGE_SIZE 10
665 /* Show the menu and handle menu entry selection. Returns the menu entry
666 index that should be executed or -1 if no entry should be executed (e.g.,
667 Esc pressed to exit a sub-menu or switching menu viewers).
668 If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu
669 entry to be executed is a result of an automatic default selection because
672 run_menu (grub_menu_t menu
, int nested
, int *auto_boot
)
675 grub_uint64_t saved_time
;
676 int default_entry
,current_entry
;
678 enum timeout_style timeout_style
;
680 default_entry
= get_entry_number (menu
, "default");
682 if (g_ventoy_suppress_esc
)
683 default_entry
= g_ventoy_suppress_esc_default
;
685 /* If DEFAULT_ENTRY is not within the menu entries, fall back to
687 else if (default_entry
< 0 || default_entry
>= menu
->size
)
690 timeout
= grub_menu_get_timeout ();
692 /* If there is no timeout, the "countdown" and "hidden" styles result in
693 the system doing nothing and providing no or very little indication
694 why. Technically this is what the user asked for, but it's not very
695 useful and likely to be a source of confusion, so we disallow this. */
696 grub_env_unset ("timeout_style");
698 timeout_style
= get_timeout_style ();
700 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
701 || timeout_style
== TIMEOUT_STYLE_HIDDEN
)
703 static struct grub_term_coordinate
*pos
;
706 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
&& timeout
)
708 pos
= grub_term_save_pos ();
709 print_countdown (pos
, timeout
);
712 /* Enter interruptible sleep until Escape or a menu hotkey is pressed,
713 or the timeout expires. */
714 saved_time
= grub_get_time_ms ();
719 key
= grub_getkey_noblock ();
720 if (key
!= GRUB_TERM_NO_KEY
)
722 entry
= get_entry_index_by_hotkey (menu
, key
);
726 if (key
== GRUB_TERM_ESC
)
732 if (timeout
> 0 && has_second_elapsed (&saved_time
))
735 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
)
736 print_countdown (pos
, timeout
);
740 /* We will fall through to auto-booting the default entry. */
744 grub_env_unset ("timeout");
745 grub_env_unset ("timeout_style");
753 /* If timeout is 0, drawing is pointless (and ugly). */
757 return default_entry
;
760 current_entry
= default_entry
;
763 menu_set_chosen_tip(menu
, current_entry
);
764 menu_init (current_entry
, menu
, nested
);
766 /* Initialize the time. */
767 saved_time
= grub_get_time_ms ();
769 timeout
= grub_menu_get_timeout ();
772 menu_print_timeout (timeout
);
779 timeout
= grub_menu_get_timeout ();
781 if (grub_normal_exit_level
)
784 if (timeout
> 0 && has_second_elapsed (&saved_time
))
787 grub_menu_set_timeout (timeout
);
788 menu_print_timeout (timeout
);
793 grub_env_unset ("timeout");
796 return default_entry
;
799 c
= grub_getkey_noblock ();
801 /* Negative values are returned on error. */
802 if ((c
!= GRUB_TERM_NO_KEY
) && (c
> 0))
806 grub_env_unset ("timeout");
807 grub_env_unset ("fallback");
813 case GRUB_TERM_KEY_HOME
:
814 case GRUB_TERM_CTRL
| 'a':
816 menu_set_chosen_entry (menu
, current_entry
);
819 case GRUB_TERM_KEY_END
:
820 case GRUB_TERM_CTRL
| 'e':
821 current_entry
= menu
->size
- 1;
822 menu_set_chosen_entry (menu
, current_entry
);
825 case GRUB_TERM_KEY_UP
:
826 case GRUB_TERM_CTRL
| 'p':
828 if (current_entry
> 0)
830 menu_set_chosen_entry (menu
, current_entry
);
833 case GRUB_TERM_CTRL
| 'n':
834 case GRUB_TERM_KEY_DOWN
:
836 if (current_entry
< menu
->size
- 1)
838 menu_set_chosen_entry (menu
, current_entry
);
841 case GRUB_TERM_CTRL
| 'g':
842 case GRUB_TERM_KEY_PPAGE
:
843 if (current_entry
< GRUB_MENU_PAGE_SIZE
)
846 current_entry
-= GRUB_MENU_PAGE_SIZE
;
847 menu_set_chosen_entry (menu
, current_entry
);
850 case GRUB_TERM_CTRL
| 'c':
851 case GRUB_TERM_KEY_NPAGE
:
852 if (current_entry
+ GRUB_MENU_PAGE_SIZE
< menu
->size
)
853 current_entry
+= GRUB_MENU_PAGE_SIZE
;
855 current_entry
= menu
->size
- 1;
856 menu_set_chosen_entry (menu
, current_entry
);
859 case GRUB_TERM_KEY_RIGHT
:
860 menu_scroll_chosen_entry (1);
862 case GRUB_TERM_KEY_LEFT
:
863 menu_scroll_chosen_entry (-1);
865 case GRUB_TERM_CTRL
| GRUB_TERM_KEY_RIGHT
:
866 menu_scroll_chosen_entry (1000000);
868 case GRUB_TERM_CTRL
| GRUB_TERM_KEY_LEFT
:
869 menu_scroll_chosen_entry (-1000000);
874 // case GRUB_TERM_KEY_RIGHT:
875 case GRUB_TERM_CTRL
| 'f':
878 return current_entry
;
881 if (nested
&& 0 == g_ventoy_suppress_esc
)
890 grub_cmdline_run (1, 0);
896 grub_menu_entry_t e
= grub_menu_get_entry (menu
, current_entry
);
898 grub_menu_entry_run (e
);
902 case GRUB_TERM_KEY_F2
:
904 VTOY_COMM_HOTKEY("VTOY_F2_CMD");
906 case GRUB_TERM_KEY_F3
:
908 VTOY_COMM_HOTKEY("VTOY_F3_CMD");
910 case GRUB_TERM_KEY_F4
:
912 VTOY_COMM_HOTKEY("VTOY_F4_CMD");
914 case GRUB_TERM_KEY_F5
:
916 VTOY_COMM_HOTKEY("VTOY_F5_CMD");
918 case GRUB_TERM_KEY_F6
:
920 VTOY_COMM_HOTKEY("VTOY_F6_CMD");
922 case GRUB_TERM_KEY_F7
:
924 if (g_ventoy_terminal_output
== 0)
926 grub_script_execute_sourcecode("terminal_output console");
927 g_ventoy_terminal_output
= 1;
931 grub_script_execute_sourcecode("terminal_output gfxterm");
932 g_ventoy_terminal_output
= 0;
935 case GRUB_TERM_KEY_F1
:
937 if (0 == g_ventoy_secondary_menu_on
)
940 g_ventoy_memdisk_mode
= 1 - g_ventoy_memdisk_mode
;
941 g_ventoy_menu_refresh
= 1;
945 case (GRUB_TERM_CTRL
| 'i'):
947 if (0 == g_ventoy_secondary_menu_on
)
950 g_ventoy_iso_raw
= 1 - g_ventoy_iso_raw
;
951 g_ventoy_menu_refresh
= 1;
955 case (GRUB_TERM_CTRL
| 'r'):
957 if (0 == g_ventoy_secondary_menu_on
)
960 g_ventoy_grub2_mode
= 1 - g_ventoy_grub2_mode
;
961 g_ventoy_menu_refresh
= 1;
965 case (GRUB_TERM_CTRL
| 'w'):
967 if (0 == g_ventoy_secondary_menu_on
)
970 g_ventoy_wimboot_mode
= 1 - g_ventoy_wimboot_mode
;
971 g_ventoy_menu_refresh
= 1;
975 case (GRUB_TERM_CTRL
| 'u'):
977 if (0 == g_ventoy_secondary_menu_on
)
980 g_ventoy_iso_uefi_drv
= 1 - g_ventoy_iso_uefi_drv
;
981 g_ventoy_menu_refresh
= 1;
985 case (GRUB_TERM_CTRL
| 'h'):
988 if (0 == g_ventoy_secondary_menu_on
)
990 cmdstr
= grub_env_get("VTOY_HELP_CMD");
993 grub_script_execute_sourcecode(cmdstr
);
994 while (grub_getkey() != GRUB_TERM_ESC
)
1002 case (GRUB_TERM_CTRL
| 'm'):
1005 if (0 == g_ventoy_secondary_menu_on
)
1007 if (g_ventoy_cur_img_path
)
1009 grub_env_set("VTOY_CHKSUM_FILE_PATH", g_ventoy_cur_img_path
);
1010 cmdstr
= grub_env_get("VTOY_CHKSUM_CMD");
1014 grub_script_execute_sourcecode(cmdstr
);
1020 grub_env_set("VTOY_CHKSUM_FILE_PATH", "X");
1029 entry
= get_entry_index_by_hotkey (menu
, c
);
1042 /* Never reach here. */
1045 /* Callback invoked immediately before a menu entry is executed. */
1047 notify_booting (grub_menu_entry_t entry
,
1048 void *userdata
__attribute__((unused
)))
1051 grub_printf_ (N_("Booting `%s'"), entry
->title
);
1052 grub_printf ("\n\n");
1055 /* Callback invoked when a default menu entry executed because of a timeout
1056 has failed and an attempt will be made to execute the next fallback
1059 notify_fallback (grub_menu_entry_t entry
,
1060 void *userdata
__attribute__((unused
)))
1062 grub_printf ("\n ");
1063 grub_printf_ (N_("Falling back to `%s'"), entry
->title
);
1064 grub_printf ("\n\n");
1065 grub_millisleep (DEFAULT_ENTRY_ERROR_DELAY_MS
);
1068 /* Callback invoked when a menu entry has failed and there is no remaining
1069 fallback entry to attempt. */
1071 notify_execution_failure (void *userdata
__attribute__((unused
)))
1073 if (grub_errno
!= GRUB_ERR_NONE
)
1075 grub_print_error ();
1076 grub_errno
= GRUB_ERR_NONE
;
1078 grub_printf ("\n ");
1079 grub_printf_ (N_("Failed to boot both default and fallback entries.\n"));
1080 grub_wait_after_message ();
1083 /* Callbacks used by the text menu to provide user feedback when menu entries
1085 static struct grub_menu_execute_callback execution_callback
=
1087 .notify_booting
= notify_booting
,
1088 .notify_fallback
= notify_fallback
,
1089 .notify_failure
= notify_execution_failure
1093 show_menu (grub_menu_t menu
, int nested
, int autobooted
)
1096 def
= grub_env_get("VTOY_DEFAULT_IMAGE");
1101 grub_menu_entry_t e
;
1104 boot_entry
= run_menu (menu
, nested
, &auto_boot
);
1108 if (auto_boot
&& def
&& grub_strcmp(def
, "VTOY_EXIT") == 0) {
1112 if (autobooted
== 0 && auto_boot
== 0) {
1113 g_ventoy_last_entry
= boot_entry
;
1114 if (g_ventoy_menu_esc
)
1118 if (autobooted
== 0 && g_ventoy_menu_esc
&& auto_boot
) {
1119 g_ventoy_last_entry
= boot_entry
;
1123 e
= grub_menu_get_entry (menu
, boot_entry
);
1125 continue; /* Menu is empty. */
1127 if (2 == e
->argc
&& e
->args
&& e
->args
[1] && grub_strncmp(e
->args
[1], "VTOY_RET", 8) == 0)
1133 grub_menu_execute_with_fallback (menu
, e
, autobooted
,
1134 &execution_callback
, 0);
1136 grub_menu_execute_entry (e
, 0);
1140 if (2 == e
->argc
&& e
->args
&& e
->args
[1] && grub_strncmp(e
->args
[1], "VTOY_RUN_RET", 12) == 0)
1144 return GRUB_ERR_NONE
;
1148 grub_show_menu (grub_menu_t menu
, int nested
, int autoboot
)
1150 grub_err_t err1
, err2
;
1154 err1
= show_menu (menu
, nested
, autoboot
);
1156 grub_print_error ();
1158 if (grub_normal_exit_level
)
1161 err2
= grub_auth_check_authentication (NULL
);
1164 grub_print_error ();
1165 grub_errno
= GRUB_ERR_NONE
;