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;
53 char g_ventoy_hotkey_tip
[256];
54 int g_ventoy_virt_esc
= 0;
56 #define VTOY_COMM_HOTKEY(cmdkey) \
57 if (0 == g_ventoy_fn_mutex && 0 == g_ventoy_secondary_menu_on) { \
58 cmdstr = grub_env_get(cmdkey); \
62 g_ventoy_fn_mutex = 1; \
63 grub_script_execute_sourcecode(cmdstr); \
64 g_ventoy_fn_mutex = 0; \
69 /* Time to delay after displaying an error message about a default/fallback
70 entry failing to boot. */
71 #define DEFAULT_ENTRY_ERROR_DELAY_MS 2500
73 grub_err_t (*grub_gfxmenu_try_hook
) (int entry
, grub_menu_t menu
,
78 TIMEOUT_STYLE_COUNTDOWN
,
82 struct timeout_style_name
{
84 enum timeout_style style
;
85 } timeout_style_names
[] = {
86 {"menu", TIMEOUT_STYLE_MENU
},
87 {"countdown", TIMEOUT_STYLE_COUNTDOWN
},
88 {"hidden", TIMEOUT_STYLE_HIDDEN
},
92 /* Wait until the user pushes any key so that the user
93 can see what happened. */
95 grub_wait_after_message (void)
97 grub_uint64_t endtime
;
99 grub_printf_ (N_("Press any key to continue..."));
102 endtime
= grub_get_time_ms () + 10000;
104 while (grub_get_time_ms () < endtime
105 && grub_getkey_noblock () == GRUB_TERM_NO_KEY
);
110 /* Get a menu entry by its index in the entry list. */
112 grub_menu_get_entry (grub_menu_t menu
, int no
)
116 for (e
= menu
->entry_list
; e
&& no
> 0; e
= e
->next
, no
--)
122 /* Get the index of a menu entry associated with a given hotkey, or -1. */
124 get_entry_index_by_hotkey (grub_menu_t menu
, int hotkey
)
126 grub_menu_entry_t entry
;
129 for (i
= 0, entry
= menu
->entry_list
; i
< menu
->size
;
130 i
++, entry
= entry
->next
)
131 if (entry
->hotkey
== hotkey
)
137 /* Return the timeout style. If the variable "timeout_style" is not set or
138 invalid, default to TIMEOUT_STYLE_MENU. */
139 static enum timeout_style
140 get_timeout_style (void)
143 struct timeout_style_name
*style_name
;
145 val
= grub_env_get ("timeout_style");
147 return TIMEOUT_STYLE_MENU
;
149 for (style_name
= timeout_style_names
; style_name
->name
; style_name
++)
150 if (grub_strcmp (style_name
->name
, val
) == 0)
151 return style_name
->style
;
153 return TIMEOUT_STYLE_MENU
;
156 /* Return the current timeout. If the variable "timeout" is not set or
157 invalid, return -1. */
159 grub_menu_get_timeout (void)
164 val
= grub_env_get ("timeout");
170 timeout
= (int) grub_strtoul (val
, 0, 0);
172 /* If the value is invalid, unset the variable. */
173 if (grub_errno
!= GRUB_ERR_NONE
)
175 grub_env_unset ("timeout");
176 grub_errno
= GRUB_ERR_NONE
;
185 /* Set current timeout in the variable "timeout". */
187 grub_menu_set_timeout (int timeout
)
189 /* Ignore TIMEOUT if it is zero, because it will be unset really soon. */
194 grub_snprintf (buf
, sizeof (buf
), "%d", timeout
);
195 grub_env_set ("timeout", buf
);
199 /* Get the first entry number from the value of the environment variable NAME,
200 which is a space-separated list of non-negative integers. The entry number
201 which is returned is stripped from the value of NAME. If no entry number
202 can be found, -1 is returned. */
204 get_and_remove_first_entry_number (const char *name
)
210 val
= grub_env_get (name
);
216 entry
= (int) grub_strtoul (val
, &tail
, 0);
218 if (grub_errno
== GRUB_ERR_NONE
)
220 /* Skip whitespace to find the next digit. */
221 while (*tail
&& grub_isspace (*tail
))
223 grub_env_set (name
, tail
);
227 grub_env_unset (name
);
228 grub_errno
= GRUB_ERR_NONE
;
237 /* Run a menu entry. */
239 grub_menu_execute_entry(grub_menu_entry_t entry
, int auto_boot
)
241 grub_err_t err
= GRUB_ERR_NONE
;
243 grub_menu_t menu
= NULL
;
244 char *optr
, *buf
, *oldchosen
= NULL
, *olddefault
= NULL
;
245 const char *ptr
, *chosen
, *def
;
248 if (entry
->restricted
)
249 err
= grub_auth_check_authentication (entry
->users
);
254 grub_errno
= GRUB_ERR_NONE
;
258 errs_before
= grub_err_printed_errors
;
260 chosen
= grub_env_get ("chosen");
261 def
= grub_env_get ("default");
265 grub_env_context_open ();
266 menu
= grub_zalloc (sizeof (*menu
));
269 grub_env_set_menu (menu
);
271 grub_env_set ("timeout", "0");
274 for (ptr
= entry
->id
; *ptr
; ptr
++)
275 sz
+= (*ptr
== '>') ? 2 : 1;
278 oldchosen
= grub_strdup (chosen
);
284 olddefault
= grub_strdup (def
);
290 sz
+= grub_strlen (chosen
);
292 buf
= grub_malloc (sz
);
300 optr
= grub_stpcpy (optr
, chosen
);
303 for (ptr
= entry
->id
; *ptr
; ptr
++)
310 grub_env_set ("chosen", buf
);
311 grub_env_export ("chosen");
315 for (ptr
= def
; ptr
&& *ptr
; ptr
++)
317 if (ptr
[0] == '>' && ptr
[1] == '>')
326 if (ptr
&& ptr
[0] && ptr
[1])
327 grub_env_set ("default", ptr
+ 1);
329 grub_env_unset ("default");
331 grub_script_execute_new_scope (entry
->sourcecode
, entry
->argc
, entry
->args
);
333 if (errs_before
!= grub_err_printed_errors
)
334 grub_wait_after_message ();
336 errs_before
= grub_err_printed_errors
;
338 if (grub_errno
== GRUB_ERR_NONE
&& grub_loader_is_loaded ())
339 /* Implicit execution of boot, only if something is loaded. */
340 grub_command_execute ("boot", 0, 0);
342 if (errs_before
!= grub_err_printed_errors
)
343 grub_wait_after_message ();
347 if (menu
&& menu
->size
)
349 grub_show_menu (menu
, 1, auto_boot
);
350 grub_normal_free_menu (menu
);
352 grub_env_context_close ();
355 grub_env_set ("chosen", oldchosen
);
357 grub_env_unset ("chosen");
359 grub_env_set ("default", olddefault
);
361 grub_env_unset ("default");
362 grub_env_unset ("timeout");
365 /* Execute ENTRY from the menu MENU, falling back to entries specified
366 in the environment variable "fallback" if it fails. CALLBACK is a
367 pointer to a struct of function pointers which are used to allow the
368 caller provide feedback to the user. */
370 grub_menu_execute_with_fallback (grub_menu_t menu
,
371 grub_menu_entry_t entry
,
373 grub_menu_execute_callback_t callback
,
378 callback
->notify_booting (entry
, callback_data
);
380 grub_menu_execute_entry (entry
, 1);
382 /* Deal with fallback entries. */
383 while ((fallback_entry
= get_and_remove_first_entry_number ("fallback"))
387 grub_errno
= GRUB_ERR_NONE
;
389 entry
= grub_menu_get_entry (menu
, fallback_entry
);
390 callback
->notify_fallback (entry
, callback_data
);
391 grub_menu_execute_entry (entry
, 1);
392 /* If the function call to execute the entry returns at all, then this is
393 taken to indicate a boot failure. For menu entries that do something
394 other than actually boot an operating system, this could assume
395 incorrectly that something failed. */
399 callback
->notify_failure (callback_data
);
402 static struct grub_menu_viewer
*viewers
;
404 int g_menu_update_mode
= 0;
405 int g_ventoy_tip_label_enable
= 0;
406 const char * g_ventoy_tip_msg1
= NULL
;
407 const char * g_ventoy_tip_msg2
= NULL
;
408 char g_ventoy_theme_path
[256] = {0};
409 static const char *g_ventoy_cur_img_path
= NULL
;
410 static void menu_set_chosen_tip(grub_menu_t menu
, int entry
)
415 grub_menu_entry_t e
= grub_menu_get_entry (menu
, entry
);
417 if (g_ventoy_theme_path
[0])
419 grub_env_set("theme", g_ventoy_theme_path
);
422 g_ventoy_tip_msg1
= g_ventoy_tip_msg2
= NULL
;
423 if (e
&& e
->id
&& grub_strncmp(e
->id
, "VID_", 4) == 0)
425 g_ventoy_theme_path
[0] = 0;
426 img
= (img_info
*)(void *)grub_strtoul(e
->id
+ 4, NULL
, 16);
429 g_ventoy_tip_msg1
= img
->tip1
;
430 g_ventoy_tip_msg2
= img
->tip2
;
431 g_ventoy_cur_img_path
= img
->path
;
434 else if (e
&& e
->id
&& grub_strncmp(e
->id
, "DIR_", 4) == 0)
436 g_ventoy_theme_path
[0] = 0;
437 for (i
= 0; i
< e
->argc
; i
++)
439 if (e
->args
[i
] && grub_strncmp(e
->args
[i
], "_VTIP_", 6) == 0)
447 tip
= (menu_tip
*)(void *)grub_strtoul(e
->args
[i
] + 6, NULL
, 16);
450 g_ventoy_tip_msg1
= tip
->tip1
;
451 g_ventoy_tip_msg2
= tip
->tip2
;
458 menu_set_chosen_entry (grub_menu_t menu
, int entry
)
460 struct grub_menu_viewer
*cur
;
462 menu_set_chosen_tip(menu
, entry
);
463 for (cur
= viewers
; cur
; cur
= cur
->next
)
464 cur
->set_chosen_entry (entry
, cur
->data
);
468 menu_scroll_chosen_entry (int diren
)
470 struct grub_menu_viewer
*cur
;
471 for (cur
= viewers
; cur
; cur
= cur
->next
)
472 if (cur
->scroll_chosen_entry
)
473 cur
->scroll_chosen_entry (cur
->data
, diren
);
477 menu_print_timeout (int timeout
)
479 struct grub_menu_viewer
*cur
;
480 for (cur
= viewers
; cur
; cur
= cur
->next
)
481 cur
->print_timeout (timeout
, cur
->data
);
487 struct grub_menu_viewer
*cur
, *next
;
488 for (cur
= viewers
; cur
; cur
= next
)
491 cur
->fini (cur
->data
);
498 menu_init (int entry
, grub_menu_t menu
, int nested
)
500 struct grub_term_output
*term
;
503 FOR_ACTIVE_TERM_OUTPUTS(term
)
504 if (term
->fullscreen
)
506 if (grub_env_get ("theme"))
508 if (!grub_gfxmenu_try_hook
)
510 grub_dl_load ("gfxmenu");
513 if (grub_gfxmenu_try_hook
)
516 err
= grub_gfxmenu_try_hook (entry
, menu
, nested
);
524 grub_error (GRUB_ERR_BAD_MODULE
,
525 N_("module `%s' isn't loaded"),
528 grub_wait_after_message ();
530 grub_errno
= GRUB_ERR_NONE
;
535 FOR_ACTIVE_TERM_OUTPUTS(term
)
539 if (grub_strcmp (term
->name
, "gfxterm") == 0 && gfxmenu
)
542 err
= grub_menu_try_text (term
, entry
, menu
, nested
);
546 grub_errno
= GRUB_ERR_NONE
;
553 struct grub_menu_viewer
*cur
;
554 for (cur
= viewers
; cur
; cur
= cur
->next
)
555 cur
->clear_timeout (cur
->data
);
559 grub_menu_register_viewer (struct grub_menu_viewer
*viewer
)
561 viewer
->next
= viewers
;
566 menuentry_eq (const char *id
, const char *spec
)
568 const char *ptr1
, *ptr2
;
573 if (*ptr2
== '>' && ptr2
[1] != '>' && *ptr1
== 0)
575 if (*ptr2
== '>' && ptr2
[1] != '>')
589 /* Get the entry number from the variable NAME. */
591 get_entry_number (grub_menu_t menu
, const char *name
)
596 val
= grub_env_get (name
);
602 entry
= (int) grub_strtoul (val
, 0, 0);
604 if (grub_errno
== GRUB_ERR_BAD_NUMBER
)
606 /* See if the variable matches the title of a menu entry. */
607 grub_menu_entry_t e
= menu
->entry_list
;
610 grub_errno
= GRUB_ERR_NONE
;
614 if (menuentry_eq (e
->title
, val
)
615 || menuentry_eq (e
->id
, val
))
627 if (grub_errno
!= GRUB_ERR_NONE
)
629 grub_errno
= GRUB_ERR_NONE
;
638 /* Check whether a second has elapsed since the last tick. If so, adjust
639 the timer and return 1; otherwise, return 0. */
641 has_second_elapsed (grub_uint64_t
*saved_time
)
643 grub_uint64_t current_time
;
645 current_time
= grub_get_time_ms ();
646 if (current_time
- *saved_time
>= 1000)
648 *saved_time
= current_time
;
656 print_countdown (struct grub_term_coordinate
*pos
, int n
)
658 grub_term_restore_pos (pos
);
659 /* NOTE: Do not remove the trailing space characters.
660 They are required to clear the line. */
661 grub_printf ("%d ", n
);
665 #define GRUB_MENU_PAGE_SIZE 10
667 /* Show the menu and handle menu entry selection. Returns the menu entry
668 index that should be executed or -1 if no entry should be executed (e.g.,
669 Esc pressed to exit a sub-menu or switching menu viewers).
670 If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu
671 entry to be executed is a result of an automatic default selection because
674 run_menu (grub_menu_t menu
, int nested
, int *auto_boot
)
677 grub_uint64_t saved_time
;
678 int default_entry
,current_entry
;
680 enum timeout_style timeout_style
;
682 default_entry
= get_entry_number (menu
, "default");
684 if (g_ventoy_suppress_esc
)
685 default_entry
= g_ventoy_suppress_esc_default
;
687 /* If DEFAULT_ENTRY is not within the menu entries, fall back to
689 else if (default_entry
< 0 || default_entry
>= menu
->size
)
692 timeout
= grub_menu_get_timeout ();
694 /* If there is no timeout, the "countdown" and "hidden" styles result in
695 the system doing nothing and providing no or very little indication
696 why. Technically this is what the user asked for, but it's not very
697 useful and likely to be a source of confusion, so we disallow this. */
698 grub_env_unset ("timeout_style");
700 timeout_style
= get_timeout_style ();
702 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
703 || timeout_style
== TIMEOUT_STYLE_HIDDEN
)
705 static struct grub_term_coordinate
*pos
;
708 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
&& timeout
)
710 pos
= grub_term_save_pos ();
711 print_countdown (pos
, timeout
);
714 /* Enter interruptible sleep until Escape or a menu hotkey is pressed,
715 or the timeout expires. */
716 saved_time
= grub_get_time_ms ();
721 key
= grub_getkey_noblock ();
722 if (key
!= GRUB_TERM_NO_KEY
)
724 entry
= get_entry_index_by_hotkey (menu
, key
);
728 if (key
== GRUB_TERM_ESC
)
734 if (timeout
> 0 && has_second_elapsed (&saved_time
))
737 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
)
738 print_countdown (pos
, timeout
);
742 /* We will fall through to auto-booting the default entry. */
746 grub_env_unset ("timeout");
747 grub_env_unset ("timeout_style");
755 /* If timeout is 0, drawing is pointless (and ugly). */
759 return default_entry
;
762 current_entry
= default_entry
;
765 menu_set_chosen_tip(menu
, current_entry
);
766 menu_init (current_entry
, menu
, nested
);
768 /* Initialize the time. */
769 saved_time
= grub_get_time_ms ();
771 timeout
= grub_menu_get_timeout ();
774 menu_print_timeout (timeout
);
781 timeout
= grub_menu_get_timeout ();
783 if (grub_normal_exit_level
)
786 if (timeout
> 0 && has_second_elapsed (&saved_time
))
789 grub_menu_set_timeout (timeout
);
790 menu_print_timeout (timeout
);
795 grub_env_unset ("timeout");
798 return default_entry
;
801 if (g_ventoy_virt_esc
> 0) {
805 c
= grub_getkey_noblock ();
808 /* Negative values are returned on error. */
809 if ((c
!= GRUB_TERM_NO_KEY
) && (c
> 0))
813 grub_env_unset ("timeout");
814 grub_env_unset ("fallback");
820 case GRUB_TERM_KEY_HOME
:
821 case GRUB_TERM_CTRL
| 'a':
823 menu_set_chosen_entry (menu
, current_entry
);
826 case GRUB_TERM_KEY_END
:
827 case GRUB_TERM_CTRL
| 'e':
828 current_entry
= menu
->size
- 1;
829 menu_set_chosen_entry (menu
, current_entry
);
832 case GRUB_TERM_KEY_UP
:
833 case GRUB_TERM_CTRL
| 'p':
835 if (current_entry
> 0)
837 menu_set_chosen_entry (menu
, current_entry
);
840 case GRUB_TERM_CTRL
| 'n':
841 case GRUB_TERM_KEY_DOWN
:
843 if (current_entry
< menu
->size
- 1)
845 menu_set_chosen_entry (menu
, current_entry
);
848 case GRUB_TERM_CTRL
| 'g':
849 case GRUB_TERM_KEY_PPAGE
:
850 if (current_entry
< GRUB_MENU_PAGE_SIZE
)
853 current_entry
-= GRUB_MENU_PAGE_SIZE
;
854 menu_set_chosen_entry (menu
, current_entry
);
857 case GRUB_TERM_CTRL
| 'c':
858 case GRUB_TERM_KEY_NPAGE
:
859 if (current_entry
+ GRUB_MENU_PAGE_SIZE
< menu
->size
)
860 current_entry
+= GRUB_MENU_PAGE_SIZE
;
862 current_entry
= menu
->size
- 1;
863 menu_set_chosen_entry (menu
, current_entry
);
866 case GRUB_TERM_KEY_RIGHT
:
867 menu_scroll_chosen_entry (1);
869 case GRUB_TERM_KEY_LEFT
:
870 menu_scroll_chosen_entry (-1);
872 case GRUB_TERM_CTRL
| GRUB_TERM_KEY_RIGHT
:
873 menu_scroll_chosen_entry (1000000);
875 case GRUB_TERM_CTRL
| GRUB_TERM_KEY_LEFT
:
876 menu_scroll_chosen_entry (-1000000);
881 // case GRUB_TERM_KEY_RIGHT:
882 case GRUB_TERM_CTRL
| 'f':
885 return current_entry
;
888 if (nested
&& 0 == g_ventoy_suppress_esc
)
897 grub_cmdline_run (1, 0);
903 grub_menu_entry_t e
= grub_menu_get_entry (menu
, current_entry
);
905 grub_menu_entry_run (e
);
909 case GRUB_TERM_KEY_F2
:
911 VTOY_COMM_HOTKEY("VTOY_F2_CMD");
913 case GRUB_TERM_KEY_F3
:
915 VTOY_COMM_HOTKEY("VTOY_F3_CMD");
917 case GRUB_TERM_KEY_F4
:
919 VTOY_COMM_HOTKEY("VTOY_F4_CMD");
921 case GRUB_TERM_KEY_F5
:
923 VTOY_COMM_HOTKEY("VTOY_F5_CMD");
925 case GRUB_TERM_KEY_F6
:
927 VTOY_COMM_HOTKEY("VTOY_F6_CMD");
929 case GRUB_TERM_KEY_F7
:
931 if (g_ventoy_terminal_output
== 0)
933 grub_script_execute_sourcecode("terminal_output console");
934 g_ventoy_terminal_output
= 1;
938 grub_script_execute_sourcecode("terminal_output gfxterm");
939 g_ventoy_terminal_output
= 0;
942 case GRUB_TERM_KEY_F1
:
944 if (0 == g_ventoy_secondary_menu_on
)
947 g_ventoy_memdisk_mode
= 1 - g_ventoy_memdisk_mode
;
948 g_ventoy_menu_refresh
= 1;
952 case (GRUB_TERM_CTRL
| 'i'):
954 if (0 == g_ventoy_secondary_menu_on
)
957 g_ventoy_iso_raw
= 1 - g_ventoy_iso_raw
;
958 g_ventoy_menu_refresh
= 1;
962 case (GRUB_TERM_CTRL
| 'r'):
964 if (0 == g_ventoy_secondary_menu_on
)
967 g_ventoy_grub2_mode
= 1 - g_ventoy_grub2_mode
;
968 g_ventoy_menu_refresh
= 1;
972 case (GRUB_TERM_CTRL
| 'w'):
974 if (0 == g_ventoy_secondary_menu_on
)
977 g_ventoy_wimboot_mode
= 1 - g_ventoy_wimboot_mode
;
978 g_ventoy_menu_refresh
= 1;
982 case (GRUB_TERM_CTRL
| 'u'):
984 if (0 == g_ventoy_secondary_menu_on
)
987 g_ventoy_iso_uefi_drv
= 1 - g_ventoy_iso_uefi_drv
;
988 g_ventoy_menu_refresh
= 1;
992 case (GRUB_TERM_CTRL
| 'h'):
995 if (0 == g_ventoy_secondary_menu_on
)
997 cmdstr
= grub_env_get("VTOY_HELP_CMD");
1000 grub_script_execute_sourcecode(cmdstr
);
1001 while (grub_getkey() != GRUB_TERM_ESC
)
1009 case (GRUB_TERM_CTRL
| 'm'):
1012 if (0 == g_ventoy_secondary_menu_on
)
1014 if (g_ventoy_cur_img_path
)
1016 grub_env_set("VTOY_CHKSUM_FILE_PATH", g_ventoy_cur_img_path
);
1017 cmdstr
= grub_env_get("VTOY_CHKSUM_CMD");
1021 grub_script_execute_sourcecode(cmdstr
);
1027 grub_env_set("VTOY_CHKSUM_FILE_PATH", "X");
1036 entry
= get_entry_index_by_hotkey (menu
, c
);
1049 /* Never reach here. */
1052 /* Callback invoked immediately before a menu entry is executed. */
1054 notify_booting (grub_menu_entry_t entry
,
1055 void *userdata
__attribute__((unused
)))
1058 grub_printf_ (N_("Booting `%s'"), entry
->title
);
1059 grub_printf ("\n\n");
1062 /* Callback invoked when a default menu entry executed because of a timeout
1063 has failed and an attempt will be made to execute the next fallback
1066 notify_fallback (grub_menu_entry_t entry
,
1067 void *userdata
__attribute__((unused
)))
1069 grub_printf ("\n ");
1070 grub_printf_ (N_("Falling back to `%s'"), entry
->title
);
1071 grub_printf ("\n\n");
1072 grub_millisleep (DEFAULT_ENTRY_ERROR_DELAY_MS
);
1075 /* Callback invoked when a menu entry has failed and there is no remaining
1076 fallback entry to attempt. */
1078 notify_execution_failure (void *userdata
__attribute__((unused
)))
1080 if (grub_errno
!= GRUB_ERR_NONE
)
1082 grub_print_error ();
1083 grub_errno
= GRUB_ERR_NONE
;
1085 grub_printf ("\n ");
1086 grub_printf_ (N_("Failed to boot both default and fallback entries.\n"));
1087 grub_wait_after_message ();
1090 /* Callbacks used by the text menu to provide user feedback when menu entries
1092 static struct grub_menu_execute_callback execution_callback
=
1094 .notify_booting
= notify_booting
,
1095 .notify_fallback
= notify_fallback
,
1096 .notify_failure
= notify_execution_failure
1100 show_menu (grub_menu_t menu
, int nested
, int autobooted
)
1103 def
= grub_env_get("VTOY_DEFAULT_IMAGE");
1108 grub_menu_entry_t e
;
1111 boot_entry
= run_menu (menu
, nested
, &auto_boot
);
1115 if (auto_boot
&& def
&& grub_strcmp(def
, "VTOY_EXIT") == 0) {
1119 if (autobooted
== 0 && auto_boot
== 0) {
1120 g_ventoy_last_entry
= boot_entry
;
1121 if (g_ventoy_menu_esc
)
1125 if (autobooted
== 0 && g_ventoy_menu_esc
&& auto_boot
) {
1126 g_ventoy_last_entry
= boot_entry
;
1130 e
= grub_menu_get_entry (menu
, boot_entry
);
1132 continue; /* Menu is empty. */
1134 if (2 == e
->argc
&& e
->args
&& e
->args
[1] && grub_strncmp(e
->args
[1], "VTOY_RET", 8) == 0)
1140 grub_menu_execute_with_fallback (menu
, e
, autobooted
,
1141 &execution_callback
, 0);
1143 grub_menu_execute_entry (e
, 0);
1147 if (2 == e
->argc
&& e
->args
&& e
->args
[1] && grub_strncmp(e
->args
[1], "VTOY_RUN_RET", 12) == 0)
1151 return GRUB_ERR_NONE
;
1155 grub_show_menu (grub_menu_t menu
, int nested
, int autoboot
)
1157 grub_err_t err1
, err2
;
1161 err1
= show_menu (menu
, nested
, autoboot
);
1163 grub_print_error ();
1165 if (grub_normal_exit_level
)
1168 err2
= grub_auth_check_authentication (NULL
);
1171 grub_print_error ();
1172 grub_errno
= GRUB_ERR_NONE
;