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];
55 static int g_vt_key_num
= 0;
56 static int g_vt_key_code
[128];
58 static int ventoy_menu_pop_key(void)
60 if (g_vt_key_num
> 0 && g_vt_key_num
< (int)(sizeof(g_vt_key_code
) / sizeof(g_vt_key_code
[0])))
63 return g_vt_key_code
[g_vt_key_num
];
68 int ventoy_menu_push_key(int code
)
70 if (g_vt_key_num
>= 0 && g_vt_key_num
< (int)(sizeof(g_vt_key_code
) / sizeof(g_vt_key_code
[0])))
72 g_vt_key_code
[g_vt_key_num
++] = code
;
78 #define VTOY_COMM_HOTKEY(cmdkey) \
79 if (0 == g_ventoy_fn_mutex && 0 == g_ventoy_secondary_menu_on) { \
80 cmdstr = grub_env_get(cmdkey); \
84 g_ventoy_fn_mutex = 1; \
85 grub_script_execute_sourcecode(cmdstr); \
86 g_ventoy_fn_mutex = 0; \
91 /* Time to delay after displaying an error message about a default/fallback
92 entry failing to boot. */
93 #define DEFAULT_ENTRY_ERROR_DELAY_MS 2500
95 grub_err_t (*grub_gfxmenu_try_hook
) (int entry
, grub_menu_t menu
,
100 TIMEOUT_STYLE_COUNTDOWN
,
104 struct timeout_style_name
{
106 enum timeout_style style
;
107 } timeout_style_names
[] = {
108 {"menu", TIMEOUT_STYLE_MENU
},
109 {"countdown", TIMEOUT_STYLE_COUNTDOWN
},
110 {"hidden", TIMEOUT_STYLE_HIDDEN
},
114 /* Wait until the user pushes any key so that the user
115 can see what happened. */
117 grub_wait_after_message (void)
119 grub_uint64_t endtime
;
121 grub_printf_ (N_("Press any key to continue..."));
124 endtime
= grub_get_time_ms () + 10000;
126 while (grub_get_time_ms () < endtime
127 && grub_getkey_noblock () == GRUB_TERM_NO_KEY
);
132 /* Get a menu entry by its index in the entry list. */
134 grub_menu_get_entry (grub_menu_t menu
, int no
)
138 for (e
= menu
->entry_list
; e
&& no
> 0; e
= e
->next
, no
--)
144 /* Get the index of a menu entry associated with a given hotkey, or -1. */
146 get_entry_index_by_hotkey (grub_menu_t menu
, int hotkey
)
148 grub_menu_entry_t entry
;
151 for (i
= 0, entry
= menu
->entry_list
; i
< menu
->size
;
152 i
++, entry
= entry
->next
)
153 if (entry
->hotkey
== hotkey
)
159 /* Return the timeout style. If the variable "timeout_style" is not set or
160 invalid, default to TIMEOUT_STYLE_MENU. */
161 static enum timeout_style
162 get_timeout_style (void)
165 struct timeout_style_name
*style_name
;
167 val
= grub_env_get ("timeout_style");
169 return TIMEOUT_STYLE_MENU
;
171 for (style_name
= timeout_style_names
; style_name
->name
; style_name
++)
172 if (grub_strcmp (style_name
->name
, val
) == 0)
173 return style_name
->style
;
175 return TIMEOUT_STYLE_MENU
;
178 /* Return the current timeout. If the variable "timeout" is not set or
179 invalid, return -1. */
181 grub_menu_get_timeout (void)
186 val
= grub_env_get ("timeout");
192 timeout
= (int) grub_strtoul (val
, 0, 0);
194 /* If the value is invalid, unset the variable. */
195 if (grub_errno
!= GRUB_ERR_NONE
)
197 grub_env_unset ("timeout");
198 grub_errno
= GRUB_ERR_NONE
;
207 /* Set current timeout in the variable "timeout". */
209 grub_menu_set_timeout (int timeout
)
211 /* Ignore TIMEOUT if it is zero, because it will be unset really soon. */
216 grub_snprintf (buf
, sizeof (buf
), "%d", timeout
);
217 grub_env_set ("timeout", buf
);
221 /* Get the first entry number from the value of the environment variable NAME,
222 which is a space-separated list of non-negative integers. The entry number
223 which is returned is stripped from the value of NAME. If no entry number
224 can be found, -1 is returned. */
226 get_and_remove_first_entry_number (const char *name
)
232 val
= grub_env_get (name
);
238 entry
= (int) grub_strtoul (val
, &tail
, 0);
240 if (grub_errno
== GRUB_ERR_NONE
)
242 /* Skip whitespace to find the next digit. */
243 while (*tail
&& grub_isspace (*tail
))
245 grub_env_set (name
, tail
);
249 grub_env_unset (name
);
250 grub_errno
= GRUB_ERR_NONE
;
259 /* Run a menu entry. */
261 grub_menu_execute_entry(grub_menu_entry_t entry
, int auto_boot
)
263 grub_err_t err
= GRUB_ERR_NONE
;
265 grub_menu_t menu
= NULL
;
266 char *optr
, *buf
, *oldchosen
= NULL
, *olddefault
= NULL
;
267 const char *ptr
, *chosen
, *def
;
270 if (entry
->restricted
)
271 err
= grub_auth_check_authentication (entry
->users
);
276 grub_errno
= GRUB_ERR_NONE
;
280 errs_before
= grub_err_printed_errors
;
282 chosen
= grub_env_get ("chosen");
283 def
= grub_env_get ("default");
287 grub_env_context_open ();
288 menu
= grub_zalloc (sizeof (*menu
));
291 grub_env_set_menu (menu
);
293 grub_env_set ("timeout", "0");
296 for (ptr
= entry
->id
; *ptr
; ptr
++)
297 sz
+= (*ptr
== '>') ? 2 : 1;
300 oldchosen
= grub_strdup (chosen
);
306 olddefault
= grub_strdup (def
);
312 sz
+= grub_strlen (chosen
);
314 buf
= grub_malloc (sz
);
322 optr
= grub_stpcpy (optr
, chosen
);
325 for (ptr
= entry
->id
; *ptr
; ptr
++)
332 grub_env_set ("chosen", buf
);
333 grub_env_export ("chosen");
337 for (ptr
= def
; ptr
&& *ptr
; ptr
++)
339 if (ptr
[0] == '>' && ptr
[1] == '>')
348 if (ptr
&& ptr
[0] && ptr
[1])
349 grub_env_set ("default", ptr
+ 1);
351 grub_env_unset ("default");
353 grub_script_execute_new_scope (entry
->sourcecode
, entry
->argc
, entry
->args
);
355 if (errs_before
!= grub_err_printed_errors
)
356 grub_wait_after_message ();
358 errs_before
= grub_err_printed_errors
;
360 if (grub_errno
== GRUB_ERR_NONE
&& grub_loader_is_loaded ())
361 /* Implicit execution of boot, only if something is loaded. */
362 grub_command_execute ("boot", 0, 0);
364 if (errs_before
!= grub_err_printed_errors
)
365 grub_wait_after_message ();
369 if (menu
&& menu
->size
)
371 grub_show_menu (menu
, 1, auto_boot
);
372 grub_normal_free_menu (menu
);
374 grub_env_context_close ();
377 grub_env_set ("chosen", oldchosen
);
379 grub_env_unset ("chosen");
381 grub_env_set ("default", olddefault
);
383 grub_env_unset ("default");
384 grub_env_unset ("timeout");
387 /* Execute ENTRY from the menu MENU, falling back to entries specified
388 in the environment variable "fallback" if it fails. CALLBACK is a
389 pointer to a struct of function pointers which are used to allow the
390 caller provide feedback to the user. */
392 grub_menu_execute_with_fallback (grub_menu_t menu
,
393 grub_menu_entry_t entry
,
395 grub_menu_execute_callback_t callback
,
400 callback
->notify_booting (entry
, callback_data
);
402 grub_menu_execute_entry (entry
, 1);
404 /* Deal with fallback entries. */
405 while ((fallback_entry
= get_and_remove_first_entry_number ("fallback"))
409 grub_errno
= GRUB_ERR_NONE
;
411 entry
= grub_menu_get_entry (menu
, fallback_entry
);
412 callback
->notify_fallback (entry
, callback_data
);
413 grub_menu_execute_entry (entry
, 1);
414 /* If the function call to execute the entry returns at all, then this is
415 taken to indicate a boot failure. For menu entries that do something
416 other than actually boot an operating system, this could assume
417 incorrectly that something failed. */
421 callback
->notify_failure (callback_data
);
424 static struct grub_menu_viewer
*viewers
;
426 int g_menu_update_mode
= 0;
427 int g_ventoy_tip_label_enable
= 0;
428 const char * g_ventoy_tip_msg1
= NULL
;
429 const char * g_ventoy_tip_msg2
= NULL
;
430 char g_ventoy_theme_path
[256] = {0};
431 static const char *g_ventoy_cur_img_path
= NULL
;
432 static void menu_set_chosen_tip(grub_menu_t menu
, int entry
)
437 grub_menu_entry_t e
= grub_menu_get_entry (menu
, entry
);
439 if (g_ventoy_theme_path
[0])
441 grub_env_set("theme", g_ventoy_theme_path
);
444 g_ventoy_tip_msg1
= g_ventoy_tip_msg2
= NULL
;
445 if (e
&& e
->id
&& grub_strncmp(e
->id
, "VID_", 4) == 0)
447 g_ventoy_theme_path
[0] = 0;
448 img
= (img_info
*)(void *)grub_strtoul(e
->id
+ 4, NULL
, 16);
451 g_ventoy_tip_msg1
= img
->tip1
;
452 g_ventoy_tip_msg2
= img
->tip2
;
453 g_ventoy_cur_img_path
= img
->path
;
456 else if (e
&& e
->id
&& grub_strncmp(e
->id
, "DIR_", 4) == 0)
458 g_ventoy_theme_path
[0] = 0;
459 for (i
= 0; i
< e
->argc
; i
++)
461 if (e
->args
[i
] && grub_strncmp(e
->args
[i
], "_VTIP_", 6) == 0)
469 tip
= (menu_tip
*)(void *)grub_strtoul(e
->args
[i
] + 6, NULL
, 16);
472 g_ventoy_tip_msg1
= tip
->tip1
;
473 g_ventoy_tip_msg2
= tip
->tip2
;
480 menu_set_chosen_entry (grub_menu_t menu
, int entry
)
482 struct grub_menu_viewer
*cur
;
484 menu_set_chosen_tip(menu
, entry
);
485 for (cur
= viewers
; cur
; cur
= cur
->next
)
486 cur
->set_chosen_entry (entry
, cur
->data
);
490 menu_scroll_chosen_entry (int diren
)
492 struct grub_menu_viewer
*cur
;
493 for (cur
= viewers
; cur
; cur
= cur
->next
)
494 if (cur
->scroll_chosen_entry
)
495 cur
->scroll_chosen_entry (cur
->data
, diren
);
499 menu_print_timeout (int timeout
)
501 struct grub_menu_viewer
*cur
;
502 for (cur
= viewers
; cur
; cur
= cur
->next
)
503 cur
->print_timeout (timeout
, cur
->data
);
509 struct grub_menu_viewer
*cur
, *next
;
510 for (cur
= viewers
; cur
; cur
= next
)
513 cur
->fini (cur
->data
);
520 menu_init (int entry
, grub_menu_t menu
, int nested
)
522 struct grub_term_output
*term
;
525 FOR_ACTIVE_TERM_OUTPUTS(term
)
526 if (term
->fullscreen
)
528 if (grub_env_get ("theme"))
530 if (!grub_gfxmenu_try_hook
)
532 grub_dl_load ("gfxmenu");
535 if (grub_gfxmenu_try_hook
)
538 err
= grub_gfxmenu_try_hook (entry
, menu
, nested
);
546 grub_error (GRUB_ERR_BAD_MODULE
,
547 N_("module `%s' isn't loaded"),
550 grub_wait_after_message ();
552 grub_errno
= GRUB_ERR_NONE
;
557 FOR_ACTIVE_TERM_OUTPUTS(term
)
561 if (grub_strcmp (term
->name
, "gfxterm") == 0 && gfxmenu
)
564 err
= grub_menu_try_text (term
, entry
, menu
, nested
);
568 grub_errno
= GRUB_ERR_NONE
;
575 struct grub_menu_viewer
*cur
;
576 for (cur
= viewers
; cur
; cur
= cur
->next
)
577 cur
->clear_timeout (cur
->data
);
581 grub_menu_register_viewer (struct grub_menu_viewer
*viewer
)
583 viewer
->next
= viewers
;
588 menuentry_eq (const char *id
, const char *spec
)
590 const char *ptr1
, *ptr2
;
595 if (*ptr2
== '>' && ptr2
[1] != '>' && *ptr1
== 0)
597 if (*ptr2
== '>' && ptr2
[1] != '>')
611 /* Get the entry number from the variable NAME. */
613 get_entry_number (grub_menu_t menu
, const char *name
)
618 val
= grub_env_get (name
);
624 entry
= (int) grub_strtoul (val
, 0, 0);
626 if (grub_errno
== GRUB_ERR_BAD_NUMBER
)
628 /* See if the variable matches the title of a menu entry. */
629 grub_menu_entry_t e
= menu
->entry_list
;
632 grub_errno
= GRUB_ERR_NONE
;
636 if (menuentry_eq (e
->title
, val
)
637 || menuentry_eq (e
->id
, val
))
649 if (grub_errno
!= GRUB_ERR_NONE
)
651 grub_errno
= GRUB_ERR_NONE
;
660 /* Check whether a second has elapsed since the last tick. If so, adjust
661 the timer and return 1; otherwise, return 0. */
663 has_second_elapsed (grub_uint64_t
*saved_time
)
665 grub_uint64_t current_time
;
667 current_time
= grub_get_time_ms ();
668 if (current_time
- *saved_time
>= 1000)
670 *saved_time
= current_time
;
678 print_countdown (struct grub_term_coordinate
*pos
, int n
)
680 grub_term_restore_pos (pos
);
681 /* NOTE: Do not remove the trailing space characters.
682 They are required to clear the line. */
683 grub_printf ("%d ", n
);
687 #define GRUB_MENU_PAGE_SIZE 10
689 /* Show the menu and handle menu entry selection. Returns the menu entry
690 index that should be executed or -1 if no entry should be executed (e.g.,
691 Esc pressed to exit a sub-menu or switching menu viewers).
692 If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu
693 entry to be executed is a result of an automatic default selection because
696 run_menu (grub_menu_t menu
, int nested
, int *auto_boot
)
699 grub_uint64_t saved_time
;
700 int default_entry
,current_entry
;
702 enum timeout_style timeout_style
;
704 default_entry
= get_entry_number (menu
, "default");
706 if (g_ventoy_suppress_esc
)
707 default_entry
= g_ventoy_suppress_esc_default
;
709 /* If DEFAULT_ENTRY is not within the menu entries, fall back to
711 else if (default_entry
< 0 || default_entry
>= menu
->size
)
714 timeout
= grub_menu_get_timeout ();
716 /* If there is no timeout, the "countdown" and "hidden" styles result in
717 the system doing nothing and providing no or very little indication
718 why. Technically this is what the user asked for, but it's not very
719 useful and likely to be a source of confusion, so we disallow this. */
720 grub_env_unset ("timeout_style");
722 timeout_style
= get_timeout_style ();
724 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
725 || timeout_style
== TIMEOUT_STYLE_HIDDEN
)
727 static struct grub_term_coordinate
*pos
;
730 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
&& timeout
)
732 pos
= grub_term_save_pos ();
733 print_countdown (pos
, timeout
);
736 /* Enter interruptible sleep until Escape or a menu hotkey is pressed,
737 or the timeout expires. */
738 saved_time
= grub_get_time_ms ();
743 key
= grub_getkey_noblock ();
744 if (key
!= GRUB_TERM_NO_KEY
)
746 entry
= get_entry_index_by_hotkey (menu
, key
);
750 if (key
== GRUB_TERM_ESC
)
756 if (timeout
> 0 && has_second_elapsed (&saved_time
))
759 if (timeout_style
== TIMEOUT_STYLE_COUNTDOWN
)
760 print_countdown (pos
, timeout
);
764 /* We will fall through to auto-booting the default entry. */
768 grub_env_unset ("timeout");
769 grub_env_unset ("timeout_style");
777 /* If timeout is 0, drawing is pointless (and ugly). */
781 return default_entry
;
784 current_entry
= default_entry
;
787 menu_set_chosen_tip(menu
, current_entry
);
788 menu_init (current_entry
, menu
, nested
);
790 /* Initialize the time. */
791 saved_time
= grub_get_time_ms ();
793 timeout
= grub_menu_get_timeout ();
796 menu_print_timeout (timeout
);
803 timeout
= grub_menu_get_timeout ();
805 if (grub_normal_exit_level
)
808 if (timeout
> 0 && has_second_elapsed (&saved_time
))
811 grub_menu_set_timeout (timeout
);
812 menu_print_timeout (timeout
);
817 grub_env_unset ("timeout");
820 return default_entry
;
823 if (g_vt_key_num
> 0) {
824 c
= ventoy_menu_pop_key();
826 c
= grub_getkey_noblock ();
829 /* Negative values are returned on error. */
830 if ((c
!= GRUB_TERM_NO_KEY
) && (c
> 0))
834 grub_env_unset ("timeout");
835 grub_env_unset ("fallback");
841 case GRUB_TERM_KEY_HOME
:
842 case GRUB_TERM_CTRL
| 'a':
844 menu_set_chosen_entry (menu
, current_entry
);
847 case GRUB_TERM_KEY_END
:
848 case GRUB_TERM_CTRL
| 'e':
849 current_entry
= menu
->size
- 1;
850 menu_set_chosen_entry (menu
, current_entry
);
853 case GRUB_TERM_KEY_UP
:
854 case GRUB_TERM_CTRL
| 'p':
856 if (current_entry
> 0)
858 menu_set_chosen_entry (menu
, current_entry
);
861 case GRUB_TERM_CTRL
| 'n':
862 case GRUB_TERM_KEY_DOWN
:
864 if (current_entry
< menu
->size
- 1)
866 menu_set_chosen_entry (menu
, current_entry
);
869 case GRUB_TERM_CTRL
| 'g':
870 case GRUB_TERM_KEY_PPAGE
:
871 if (current_entry
< GRUB_MENU_PAGE_SIZE
)
874 current_entry
-= GRUB_MENU_PAGE_SIZE
;
875 menu_set_chosen_entry (menu
, current_entry
);
878 case GRUB_TERM_CTRL
| 'c':
879 case GRUB_TERM_KEY_NPAGE
:
880 if (current_entry
+ GRUB_MENU_PAGE_SIZE
< menu
->size
)
881 current_entry
+= GRUB_MENU_PAGE_SIZE
;
883 current_entry
= menu
->size
- 1;
884 menu_set_chosen_entry (menu
, current_entry
);
887 case GRUB_TERM_KEY_RIGHT
:
888 menu_scroll_chosen_entry (1);
890 case GRUB_TERM_KEY_LEFT
:
891 menu_scroll_chosen_entry (-1);
893 case GRUB_TERM_CTRL
| GRUB_TERM_KEY_RIGHT
:
894 menu_scroll_chosen_entry (1000000);
896 case GRUB_TERM_CTRL
| GRUB_TERM_KEY_LEFT
:
897 menu_scroll_chosen_entry (-1000000);
902 // case GRUB_TERM_KEY_RIGHT:
903 case GRUB_TERM_CTRL
| 'f':
906 return current_entry
;
909 if (nested
&& 0 == g_ventoy_suppress_esc
)
918 grub_cmdline_run (1, 0);
924 grub_menu_entry_t e
= grub_menu_get_entry (menu
, current_entry
);
926 grub_menu_entry_run (e
);
930 case GRUB_TERM_KEY_F2
:
932 VTOY_COMM_HOTKEY("VTOY_F2_CMD");
934 case GRUB_TERM_KEY_F3
:
936 VTOY_COMM_HOTKEY("VTOY_F3_CMD");
938 case GRUB_TERM_KEY_F4
:
940 VTOY_COMM_HOTKEY("VTOY_F4_CMD");
942 case GRUB_TERM_KEY_F5
:
944 VTOY_COMM_HOTKEY("VTOY_F5_CMD");
946 case GRUB_TERM_KEY_F6
:
948 VTOY_COMM_HOTKEY("VTOY_F6_CMD");
950 case GRUB_TERM_KEY_F7
:
952 if (g_ventoy_terminal_output
== 0)
954 grub_script_execute_sourcecode("terminal_output console");
955 g_ventoy_terminal_output
= 1;
959 grub_script_execute_sourcecode("terminal_output gfxterm");
960 g_ventoy_terminal_output
= 0;
963 case GRUB_TERM_KEY_F1
:
965 if (0 == g_ventoy_secondary_menu_on
)
967 cmdstr
= grub_env_get("VTOY_HELP_CMD");
970 grub_script_execute_sourcecode(cmdstr
);
971 while (grub_getkey() != GRUB_TERM_ESC
)
978 case (GRUB_TERM_CTRL
| 'd'):
980 if (0 == g_ventoy_secondary_menu_on
)
983 g_ventoy_memdisk_mode
= 1 - g_ventoy_memdisk_mode
;
984 g_ventoy_menu_refresh
= 1;
988 case (GRUB_TERM_CTRL
| 'i'):
990 if (0 == g_ventoy_secondary_menu_on
)
993 g_ventoy_iso_raw
= 1 - g_ventoy_iso_raw
;
994 g_ventoy_menu_refresh
= 1;
998 case (GRUB_TERM_CTRL
| 'r'):
1000 if (0 == g_ventoy_secondary_menu_on
)
1003 g_ventoy_grub2_mode
= 1 - g_ventoy_grub2_mode
;
1004 g_ventoy_menu_refresh
= 1;
1008 case (GRUB_TERM_CTRL
| 'w'):
1010 if (0 == g_ventoy_secondary_menu_on
)
1013 g_ventoy_wimboot_mode
= 1 - g_ventoy_wimboot_mode
;
1014 g_ventoy_menu_refresh
= 1;
1018 case (GRUB_TERM_CTRL
| 'u'):
1020 if (0 == g_ventoy_secondary_menu_on
)
1023 g_ventoy_iso_uefi_drv
= 1 - g_ventoy_iso_uefi_drv
;
1024 g_ventoy_menu_refresh
= 1;
1028 case (GRUB_TERM_CTRL
| 'l'):
1029 case (GRUB_TERM_CTRL
| 'L'):
1030 case (GRUB_TERM_SHIFT
| 'l'):
1031 case (GRUB_TERM_SHIFT
| 'L'):
1035 VTOY_COMM_HOTKEY("VTOY_LANG_CMD");
1038 case (GRUB_TERM_CTRL
| 'm'):
1041 if (0 == g_ventoy_secondary_menu_on
)
1043 if (g_ventoy_cur_img_path
)
1045 grub_env_set("VTOY_CHKSUM_FILE_PATH", g_ventoy_cur_img_path
);
1046 cmdstr
= grub_env_get("VTOY_CHKSUM_CMD");
1050 grub_script_execute_sourcecode(cmdstr
);
1056 grub_env_set("VTOY_CHKSUM_FILE_PATH", "X");
1065 entry
= get_entry_index_by_hotkey (menu
, c
);
1078 /* Never reach here. */
1081 /* Callback invoked immediately before a menu entry is executed. */
1083 notify_booting (grub_menu_entry_t entry
,
1084 void *userdata
__attribute__((unused
)))
1087 grub_printf_ (N_("Booting `%s'"), entry
->title
);
1088 grub_printf ("\n\n");
1091 /* Callback invoked when a default menu entry executed because of a timeout
1092 has failed and an attempt will be made to execute the next fallback
1095 notify_fallback (grub_menu_entry_t entry
,
1096 void *userdata
__attribute__((unused
)))
1098 grub_printf ("\n ");
1099 grub_printf_ (N_("Falling back to `%s'"), entry
->title
);
1100 grub_printf ("\n\n");
1101 grub_millisleep (DEFAULT_ENTRY_ERROR_DELAY_MS
);
1104 /* Callback invoked when a menu entry has failed and there is no remaining
1105 fallback entry to attempt. */
1107 notify_execution_failure (void *userdata
__attribute__((unused
)))
1109 if (grub_errno
!= GRUB_ERR_NONE
)
1111 grub_print_error ();
1112 grub_errno
= GRUB_ERR_NONE
;
1114 grub_printf ("\n ");
1115 grub_printf_ (N_("Failed to boot both default and fallback entries.\n"));
1116 grub_wait_after_message ();
1119 /* Callbacks used by the text menu to provide user feedback when menu entries
1121 static struct grub_menu_execute_callback execution_callback
=
1123 .notify_booting
= notify_booting
,
1124 .notify_fallback
= notify_fallback
,
1125 .notify_failure
= notify_execution_failure
1129 show_menu (grub_menu_t menu
, int nested
, int autobooted
)
1132 def
= grub_env_get("VTOY_DEFAULT_IMAGE");
1137 grub_menu_entry_t e
;
1140 boot_entry
= run_menu (menu
, nested
, &auto_boot
);
1144 if (auto_boot
&& def
&& grub_strcmp(def
, "VTOY_EXIT") == 0) {
1148 if (autobooted
== 0 && auto_boot
== 0) {
1149 g_ventoy_last_entry
= boot_entry
;
1150 if (g_ventoy_menu_esc
)
1154 if (autobooted
== 0 && g_ventoy_menu_esc
&& auto_boot
) {
1155 g_ventoy_last_entry
= boot_entry
;
1159 e
= grub_menu_get_entry (menu
, boot_entry
);
1161 continue; /* Menu is empty. */
1163 if (2 == e
->argc
&& e
->args
&& e
->args
[1] && grub_strncmp(e
->args
[1], "VTOY_RET", 8) == 0)
1169 grub_menu_execute_with_fallback (menu
, e
, autobooted
,
1170 &execution_callback
, 0);
1172 grub_menu_execute_entry (e
, 0);
1176 if (2 == e
->argc
&& e
->args
&& e
->args
[1] && grub_strncmp(e
->args
[1], "VTOY_RUN_RET", 12) == 0)
1180 return GRUB_ERR_NONE
;
1184 grub_show_menu (grub_menu_t menu
, int nested
, int autoboot
)
1186 grub_err_t err1
, err2
;
1190 err1
= show_menu (menu
, nested
, autoboot
);
1192 grub_print_error ();
1194 if (grub_normal_exit_level
)
1197 err2
= grub_auth_check_authentication (NULL
);
1200 grub_print_error ();
1201 grub_errno
= GRUB_ERR_NONE
;