=== modified file 'ChangeLog'
--- ChangeLog 2009-02-04 10:52:25 +0000
+++ ChangeLog 2009-02-05 17:23:08 +0000
@@ -1,3 +1,66 @@
+2009-02-05 Colin D Bennett
+
+ Support multiple fallback entries, and provide an API to support
+ executing default+fallback menu entries. Renamed the `terminal' menu
+ viewer to `text'.
+
+ * include/grub/normal.h (grub_normal_text_menu_viewer): New global
+ variable declaration.
+ (grub_menu_execute_callback): New structure declaration.
+ (grub_menu_execute_callback_t): New typedef.
+ (grub_menu_execute_with_fallback): New function declaration.
+ (grub_menu_get_timeout): Likewise.
+ (grub_menu_set_timeout): Likewise.
+
+ * normal/main.c (GRUB_MOD_INIT(normal)): Refer to new variable name.
+
+ * normal/menu.c (grub_wait_after_message): Moved to
+ `normal/menu_text.c'.
+ (draw_border): Likewise.
+ (print_message): Likewise.
+ (print_entry): Likewise.
+ (print_entries): Likewise.
+ (grub_menu_init_page): Likewise.
+ (get_entry_number): Likewise.
+ (print_timeout): Likewise.
+ (run_menu): Likewise.
+ (grub_menu_execute_entry): Likewise.
+ (show_text_menu): Likewise.
+ (get_and_remove_first_entry_number): New function.
+ (grub_menu_execute_with_fallback): Likewise.
+ (get_entry): Renamed to ...
+ (grub_menu_get_entry): .. this and made it global.
+ (get_timeout): Renamed to ...
+ (grub_menu_get_timeout): ... this and made it global.
+ (set_timeout): Renamed to ...
+ (grub_menu_set_timeout): ... this and made it global.
+ (grub_normal_terminal_menu_viewer): Renamed to ...
+ (grub_normal_text_menu_viewer): ... this.
+
+ * normal/menu_text.c: New file. Extracted text-menu-specific code
+ from normal/menu.c.
+
+ * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add `normal/menu_text.c'.
+ (normal_mod_SOURCES): Likewise.
+
+ * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise.
+ (normal_mod_SOURCES): Likewise.
+
+ * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+ (normal_mod_SOURCES): Likewise.
+
+ * conf/i386-pc.rmk, (grub_emu_SOURCES): Likewise.
+ (normal_mod_SOURCES): Likewise.
+
+ * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+ (normal_mod_SOURCES): Likewise.
+
+ * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+ (normal_mod_SOURCES): Likewise.
+
+ * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise.
+ (normal_mod_SOURCES): Likewise.
+
2009-02-04 Felix Zielcke
util/getroot.c (grub_util_get_grub_dev): Add support for /dev/mdNpN and
=== modified file 'conf/i386-coreboot.rmk'
--- conf/i386-coreboot.rmk 2009-02-03 13:22:26 +0000
+++ conf/i386-coreboot.rmk 2009-02-05 17:22:49 +0000
@@ -75,7 +75,7 @@
kern/loader.c kern/main.c kern/misc.c kern/parser.c \
grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c \
normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
- normal/completion.c normal/main.c \
+ normal/completion.c normal/main.c normal/menu_text.c \
normal/menu.c normal/menu_entry.c normal/menu_viewer.c \
normal/misc.c normal/script.c \
normal/color.c \
@@ -123,6 +123,7 @@
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/color.c \
normal/menu_viewer.c normal/menu_entry.c \
normal/misc.c grub_script.tab.c \
=== modified file 'conf/i386-efi.rmk'
--- conf/i386-efi.rmk 2009-02-03 13:22:26 +0000
+++ conf/i386-efi.rmk 2009-02-05 17:22:49 +0000
@@ -54,6 +54,7 @@
normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
normal/completion.c normal/context.c normal/main.c \
normal/menu.c normal/menu_entry.c normal/menu_viewer.c \
+ normal/menu_text.c \
normal/misc.c normal/script.c \
normal/color.c \
partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c \
@@ -120,6 +121,7 @@
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/color.c \
normal/menu_viewer.c normal/menu_entry.c \
normal/misc.c grub_script.tab.c \
=== modified file 'conf/i386-ieee1275.rmk'
--- conf/i386-ieee1275.rmk 2009-02-03 13:22:26 +0000
+++ conf/i386-ieee1275.rmk 2009-02-05 17:22:49 +0000
@@ -74,7 +74,7 @@
kern/loader.c kern/main.c kern/misc.c kern/parser.c \
grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c \
normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
- normal/completion.c normal/main.c \
+ normal/completion.c normal/main.c normal/menu_text.c \
normal/menu.c normal/menu_entry.c normal/menu_viewer.c \
normal/misc.c normal/script.c \
normal/color.c \
@@ -113,6 +113,7 @@
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/color.c \
normal/menu_viewer.c normal/menu_entry.c \
normal/misc.c grub_script.tab.c \
=== modified file 'conf/i386-pc.rmk'
--- conf/i386-pc.rmk 2009-02-03 13:22:26 +0000
+++ conf/i386-pc.rmk 2009-02-05 17:22:49 +0000
@@ -130,6 +130,7 @@
normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
normal/completion.c normal/main.c normal/color.c \
normal/menu.c normal/menu_entry.c normal/menu_viewer.c \
+ normal/menu_text.c \
normal/misc.c normal/script.c \
partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c \
partmap/acorn.c partmap/gpt.c \
@@ -203,6 +204,7 @@
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/color.c \
normal/menu_viewer.c normal/menu_entry.c \
normal/misc.c grub_script.tab.c \
=== modified file 'conf/powerpc-ieee1275.rmk'
--- conf/powerpc-ieee1275.rmk 2009-02-03 13:22:26 +0000
+++ conf/powerpc-ieee1275.rmk 2009-02-05 17:22:49 +0000
@@ -58,6 +58,7 @@
normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/menu_entry.c normal/menu_viewer.c normal/misc.c \
normal/script.c \
normal/color.c \
@@ -133,6 +134,7 @@
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/color.c \
normal/menu_viewer.c normal/menu_entry.c \
normal/misc.c grub_script.tab.c \
=== modified file 'conf/sparc64-ieee1275.rmk'
--- conf/sparc64-ieee1275.rmk 2009-02-03 13:34:52 +0000
+++ conf/sparc64-ieee1275.rmk 2009-02-05 17:22:49 +0000
@@ -59,6 +59,7 @@
# normal/completion.c normal/context.c normal/execute.c \
# normal/function.c normal/lexer.c \
# normal/main.c normal/menu.c normal/menu_entry.c \
+# normal/menu_text.c \
# normal/menu_viewer.c normal/misc.c \
# partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c \
# partmap/acorn.c \
@@ -166,6 +167,7 @@
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/color.c \
normal/menu_viewer.c normal/menu_entry.c \
normal/misc.c grub_script.tab.c \
=== modified file 'conf/x86_64-efi.rmk'
--- conf/x86_64-efi.rmk 2009-02-03 13:22:26 +0000
+++ conf/x86_64-efi.rmk 2009-02-05 17:22:49 +0000
@@ -56,6 +56,7 @@
normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
normal/completion.c normal/context.c normal/main.c \
normal/menu.c normal/menu_entry.c normal/menu_viewer.c \
+ normal/menu_text.c \
normal/misc.c normal/script.c \
normal/color.c \
partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c \
@@ -122,6 +123,7 @@
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/color.c \
normal/menu_viewer.c normal/menu_entry.c \
normal/misc.c grub_script.tab.c \
=== modified file 'include/grub/normal.h'
--- include/grub/normal.h 2009-01-31 09:15:43 +0000
+++ include/grub/normal.h 2009-02-05 17:22:49 +0000
@@ -79,7 +79,7 @@
/* The name of a module. Used for auto-loading. */
char *module_name;
-
+
/* The next element. */
struct grub_command *next;
};
@@ -96,12 +96,38 @@
/* To exit from the normal mode. */
extern grub_jmp_buf grub_exit_env;
-extern struct grub_menu_viewer grub_normal_terminal_menu_viewer;
+extern struct grub_menu_viewer grub_normal_text_menu_viewer;
+
+/* Callback structure menu viewers can use to provide user feedback when
+ default entries are executed, possibly including fallback entries. */
+typedef struct grub_menu_execute_callback
+{
+ /* Called immediately before ENTRY is booted. */
+ void (*notify_booting) (grub_menu_entry_t entry, void *userdata);
+
+ /* Called when executing one entry has failed, and another entry, ENTRY, will
+ be executed as a fallback. The implementation of this function should
+ delay for a period of at least 2 seconds before returning in order to
+ allow the user time to read the information before it can be lost by
+ executing ENTRY. */
+ void (*notify_fallback) (grub_menu_entry_t entry, void *userdata);
+
+ /* Called when an entry has failed to execute and there is no remaining
+ fallback entry to attempt. */
+ void (*notify_failure) (void *userdata);
+}
+*grub_menu_execute_callback_t;
void grub_enter_normal_mode (const char *config);
void grub_normal_execute (const char *config, int nested);
+void grub_menu_execute_with_fallback (grub_menu_t menu,
+ grub_menu_entry_t entry,
+ grub_menu_execute_callback_t callback,
+ void *callback_data);
void grub_menu_entry_run (grub_menu_entry_t entry);
void grub_menu_execute_entry(grub_menu_entry_t entry);
+int grub_menu_get_timeout (void);
+void grub_menu_set_timeout (int timeout);
void grub_cmdline_run (int nested);
int grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
int echo_char, int readline);
=== modified file 'normal/main.c'
--- normal/main.c 2009-01-31 09:15:43 +0000
+++ normal/main.c 2009-02-05 17:22:49 +0000
@@ -620,7 +620,7 @@
if (mod)
grub_dl_ref (mod);
- grub_menu_viewer_register (&grub_normal_terminal_menu_viewer);
+ grub_menu_viewer_register (&grub_normal_text_menu_viewer);
grub_set_history (GRUB_DEFAULT_HISTORY_SIZE);
=== modified file 'normal/menu.c'
--- normal/menu.c 2009-01-31 09:15:43 +0000
+++ normal/menu.c 2009-02-05 17:22:49 +0000
@@ -1,3 +1,4 @@
+/* menu.c - General supporting functionality for menus. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
@@ -17,7 +18,6 @@
*/
#include
-#include
#include
#include
#include
@@ -26,83 +26,9 @@
#include
#include
-static grub_uint8_t grub_color_menu_normal;
-static grub_uint8_t grub_color_menu_highlight;
-
-/* Wait until the user pushes any key so that the user
- can see what happened. */
-void
-grub_wait_after_message (void)
-{
- grub_printf ("\nPress any key to continue...");
- (void) grub_getkey ();
-}
-
-static void
-draw_border (void)
-{
- unsigned i;
-
- grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
-
- grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y);
- grub_putcode (GRUB_TERM_DISP_UL);
- for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++)
- grub_putcode (GRUB_TERM_DISP_HLINE);
- grub_putcode (GRUB_TERM_DISP_UR);
-
- for (i = 0; i < (unsigned) GRUB_TERM_NUM_ENTRIES; i++)
- {
- grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1);
- grub_putcode (GRUB_TERM_DISP_VLINE);
- grub_gotoxy (GRUB_TERM_MARGIN + GRUB_TERM_BORDER_WIDTH - 1,
- GRUB_TERM_TOP_BORDER_Y + i + 1);
- grub_putcode (GRUB_TERM_DISP_VLINE);
- }
-
- grub_gotoxy (GRUB_TERM_MARGIN,
- GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES + 1);
- grub_putcode (GRUB_TERM_DISP_LL);
- for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++)
- grub_putcode (GRUB_TERM_DISP_HLINE);
- grub_putcode (GRUB_TERM_DISP_LR);
-
- grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
-
- grub_gotoxy (GRUB_TERM_MARGIN,
- (GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES
- + GRUB_TERM_MARGIN + 1));
-}
-
-static void
-print_message (int nested, int edit)
-{
- grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
-
- if (edit)
- {
- grub_printf ("\n\
- Minimum Emacs-like screen editing is supported. TAB lists\n\
- completions. Press Ctrl-x to boot, Ctrl-c for a command-line\n\
- or ESC to return menu.");
- }
- else
- {
- grub_printf ("\n\
- Use the %C and %C keys to select which entry is highlighted.\n",
- (grub_uint32_t) GRUB_TERM_DISP_UP, (grub_uint32_t) GRUB_TERM_DISP_DOWN);
- grub_printf ("\
- Press enter to boot the selected OS, \'e\' to edit the\n\
- commands before booting or \'c\' for a command-line.");
- if (nested)
- grub_printf ("\n\
- ESC to return previous menu.");
- }
-
-}
-
-static grub_menu_entry_t
-get_entry (grub_menu_t menu, int no)
+/* Get a menu entry by its index in the entry list. */
+grub_menu_entry_t
+grub_menu_get_entry (grub_menu_t menu, int no)
{
grub_menu_entry_t e;
@@ -112,140 +38,10 @@
return e;
}
-static void
-print_entry (int y, int highlight, grub_menu_entry_t entry)
-{
- int x;
- const char *title;
- grub_size_t title_len;
- grub_ssize_t len;
- grub_uint32_t *unicode_title;
- grub_ssize_t i;
- grub_uint8_t old_color_normal, old_color_highlight;
-
- title = entry ? entry->title : "";
- title_len = grub_strlen (title);
- unicode_title = grub_malloc (title_len * sizeof (*unicode_title));
- if (! unicode_title)
- /* XXX How to show this error? */
- return;
-
- len = grub_utf8_to_ucs4 (unicode_title, title_len,
- (grub_uint8_t *) title, -1, 0);
- if (len < 0)
- {
- /* It is an invalid sequence. */
- grub_free (unicode_title);
- return;
- }
-
- grub_getcolor (&old_color_normal, &old_color_highlight);
- grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight);
- grub_setcolorstate (highlight
- ? GRUB_TERM_COLOR_HIGHLIGHT
- : GRUB_TERM_COLOR_NORMAL);
-
- grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN, y);
-
- for (x = GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1, i = 0;
- x < GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH - GRUB_TERM_MARGIN;
- i++)
- {
- if (i < len
- && x <= (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH
- - GRUB_TERM_MARGIN - 1))
- {
- grub_ssize_t width;
-
- width = grub_getcharwidth (unicode_title[i]);
-
- if (x + width > (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH
- - GRUB_TERM_MARGIN - 1))
- grub_putcode (GRUB_TERM_DISP_RIGHT);
- else
- grub_putcode (unicode_title[i]);
-
- x += width;
- }
- else
- {
- grub_putchar (' ');
- x++;
- }
- }
- grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
- grub_putchar (' ');
-
- grub_gotoxy (GRUB_TERM_CURSOR_X, y);
-
- grub_setcolor (old_color_normal, old_color_highlight);
- grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
- grub_free (unicode_title);
-}
-
-static void
-print_entries (grub_menu_t menu, int first, int offset)
-{
- grub_menu_entry_t e;
- int i;
-
- grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
- GRUB_TERM_FIRST_ENTRY_Y);
-
- if (first)
- grub_putcode (GRUB_TERM_DISP_UP);
- else
- grub_putchar (' ');
-
- e = get_entry (menu, first);
-
- for (i = 0; i < GRUB_TERM_NUM_ENTRIES; i++)
- {
- print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e);
- if (e)
- e = e->next;
- }
-
- grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
- GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES);
-
- if (e)
- grub_putcode (GRUB_TERM_DISP_DOWN);
- else
- grub_putchar (' ');
-
- grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
-}
-
-/* Initialize the screen. If NESTED is non-zero, assume that this menu
- is run from another menu or a command-line. If EDIT is non-zero, show
- a message for the menu entry editor. */
-void
-grub_menu_init_page (int nested, int edit)
-{
- grub_uint8_t old_color_normal, old_color_highlight;
-
- grub_getcolor (&old_color_normal, &old_color_highlight);
-
- /* By default, use the same colors for the menu. */
- grub_color_menu_normal = old_color_normal;
- grub_color_menu_highlight = old_color_highlight;
-
- /* Then give user a chance to replace them. */
- grub_parse_color_name_pair (&grub_color_menu_normal, grub_env_get ("menu_color_normal"));
- grub_parse_color_name_pair (&grub_color_menu_highlight, grub_env_get ("menu_color_highlight"));
-
- grub_normal_init_page ();
- grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight);
- draw_border ();
- grub_setcolor (old_color_normal, old_color_highlight);
- print_message (nested, edit);
-}
-
/* Return the current timeout. If the variable "timeout" is not set or
invalid, return -1. */
-static int
-get_timeout (void)
+int
+grub_menu_get_timeout (void)
{
char *val;
int timeout;
@@ -272,8 +68,8 @@
}
/* Set current timeout in the variable "timeout". */
-static void
-set_timeout (int timeout)
+void
+grub_menu_set_timeout (int timeout)
{
/* Ignore TIMEOUT if it is zero, because it will be unset really soon. */
if (timeout > 0)
@@ -285,11 +81,15 @@
}
}
-/* Get the entry number from the variable NAME. */
+/* Get the first entry number from the value of the environment variable NAME,
+ which is a space-separated list of nonnegative integers. The entry number
+ which is returned is stripped from the value of NAME. If no entry number
+ can be found, -1 is returned. */
static int
-get_entry_number (const char *name)
+get_and_remove_first_entry_number (const char *name)
{
char *val;
+ char *tail;
int entry;
val = grub_env_get (name);
@@ -298,10 +98,18 @@
grub_error_push ();
- entry = (int) grub_strtoul (val, 0, 0);
+ entry = (int) grub_strtoul (val, &tail, 0);
- if (grub_errno != GRUB_ERR_NONE)
- {
+ if (grub_errno == GRUB_ERR_NONE)
+ {
+ /* Skip whitespace to find the next digit. */
+ while (*tail && grub_isspace (*tail))
+ tail++;
+ grub_env_set (name, tail);
+ }
+ else
+ {
+ grub_env_unset (name);
grub_errno = GRUB_ERR_NONE;
entry = -1;
}
@@ -311,245 +119,6 @@
return entry;
}
-static void
-print_timeout (int timeout, int offset, int second_stage)
-{
- /* NOTE: Do not remove the trailing space characters.
- They are required to clear the line. */
- char *msg = " The highlighted entry will be booted automatically in %ds. ";
- char *msg_end = grub_strchr (msg, '%');
-
- grub_gotoxy (second_stage ? (msg_end - msg) : 0, GRUB_TERM_HEIGHT - 3);
- grub_printf (second_stage ? msg_end : msg, timeout);
- grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
- grub_refresh ();
-};
-
-static int
-run_menu (grub_menu_t menu, int nested)
-{
- int first, offset;
- grub_uint64_t saved_time;
- int default_entry;
- int timeout;
-
- first = 0;
-
- default_entry = get_entry_number ("default");
-
- /* If DEFAULT_ENTRY is not within the menu entries, fall back to
- the first entry. */
- if (default_entry < 0 || default_entry >= menu->size)
- default_entry = 0;
-
- /* If timeout is 0, drawing is pointless (and ugly). */
- if (get_timeout () == 0)
- return default_entry;
-
- offset = default_entry;
- if (offset > GRUB_TERM_NUM_ENTRIES - 1)
- {
- first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
- offset = GRUB_TERM_NUM_ENTRIES - 1;
- }
-
- /* Initialize the time. */
- saved_time = grub_get_time_ms ();
-
- refresh:
- grub_setcursor (0);
- grub_menu_init_page (nested, 0);
- print_entries (menu, first, offset);
- grub_refresh ();
-
- timeout = get_timeout ();
-
- if (timeout > 0)
- print_timeout (timeout, offset, 0);
-
- while (1)
- {
- int c;
- timeout = get_timeout ();
-
- if (timeout > 0)
- {
- grub_uint64_t current_time;
-
- current_time = grub_get_time_ms ();
- if (current_time - saved_time >= 1000)
- {
- timeout--;
- set_timeout (timeout);
- saved_time = current_time;
- print_timeout (timeout, offset, 1);
- }
- }
-
- if (timeout == 0)
- {
- grub_env_unset ("timeout");
- return default_entry;
- }
-
- if (grub_checkkey () >= 0 || timeout < 0)
- {
- c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
-
- if (timeout >= 0)
- {
- grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
- grub_printf ("\
- ");
- grub_env_unset ("timeout");
- grub_env_unset ("fallback");
- grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
- }
-
- switch (c)
- {
- case GRUB_TERM_HOME:
- first = 0;
- offset = 0;
- print_entries (menu, first, offset);
- break;
-
- case GRUB_TERM_END:
- offset = menu->size - 1;
- if (offset > GRUB_TERM_NUM_ENTRIES - 1)
- {
- first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
- offset = GRUB_TERM_NUM_ENTRIES - 1;
- }
- print_entries (menu, first, offset);
- break;
-
- case GRUB_TERM_UP:
- case '^':
- if (offset > 0)
- {
- print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
- get_entry (menu, first + offset));
- offset--;
- print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
- get_entry (menu, first + offset));
- }
- else if (first > 0)
- {
- first--;
- print_entries (menu, first, offset);
- }
- break;
-
- case GRUB_TERM_DOWN:
- case 'v':
- if (menu->size > first + offset + 1)
- {
- if (offset < GRUB_TERM_NUM_ENTRIES - 1)
- {
- print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
- get_entry (menu, first + offset));
- offset++;
- print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
- get_entry (menu, first + offset));
- }
- else
- {
- first++;
- print_entries (menu, first, offset);
- }
- }
- break;
-
- case GRUB_TERM_PPAGE:
- if (first == 0)
- {
- offset = 0;
- }
- else
- {
- first -= GRUB_TERM_NUM_ENTRIES;
-
- if (first < 0)
- {
- offset += first;
- first = 0;
- }
- }
- print_entries (menu, first, offset);
- break;
-
- case GRUB_TERM_NPAGE:
- if (offset == 0)
- {
- offset += GRUB_TERM_NUM_ENTRIES - 1;
- if (first + offset >= menu->size)
- {
- offset = menu->size - first - 1;
- }
- }
- else
- {
- first += GRUB_TERM_NUM_ENTRIES;
-
- if (first + offset >= menu->size)
- {
- first -= GRUB_TERM_NUM_ENTRIES;
- offset += GRUB_TERM_NUM_ENTRIES;
-
- if (offset > menu->size - 1 ||
- offset > GRUB_TERM_NUM_ENTRIES - 1)
- {
- offset = menu->size - first - 1;
- }
- if (offset > GRUB_TERM_NUM_ENTRIES)
- {
- first += offset - GRUB_TERM_NUM_ENTRIES + 1;
- offset = GRUB_TERM_NUM_ENTRIES - 1;
- }
- }
- }
- print_entries (menu, first, offset);
- break;
-
- case '\n':
- case '\r':
- case 6:
- grub_setcursor (1);
- return first + offset;
-
- case '\e':
- if (nested)
- {
- grub_setcursor (1);
- return -1;
- }
- break;
-
- case 'c':
- grub_cmdline_run (1);
- goto refresh;
-
- case 'e':
- {
- grub_menu_entry_t e = get_entry (menu, first + offset);
- if (e)
- grub_menu_entry_run (e);
- }
- goto refresh;
-
- default:
- break;
- }
-
- grub_refresh ();
- }
- }
-
- /* Never reach here. */
- return -1;
-}
-
/* Run a menu entry. */
void
grub_menu_execute_entry(grub_menu_entry_t entry)
@@ -561,58 +130,34 @@
grub_command_execute ("boot", 0);
}
-static grub_err_t
-show_text_menu (grub_menu_t menu, int nested)
+/* Execute ENTRY from the menu MENU, falling back to entries specified
+ in the environment variable "fallback" if it fails. CALLBACK is a
+ pointer to a struct of function pointers which are used to allow the
+ caller provide feedback to the user. */
+void
+grub_menu_execute_with_fallback (grub_menu_t menu,
+ grub_menu_entry_t entry,
+ grub_menu_execute_callback_t callback,
+ void *callback_data)
{
- while (1)
+ int fallback_entry;
+
+ callback->notify_booting (entry, callback_data);
+
+ grub_menu_execute_entry (entry);
+
+ /* Deal with fallback entries. */
+ while ((fallback_entry = get_and_remove_first_entry_number ("fallback"))
+ >= 0)
{
- int boot_entry;
- grub_menu_entry_t e;
- int fallback_entry;
-
- boot_entry = run_menu (menu, nested);
- if (boot_entry < 0)
- break;
-
- e = get_entry (menu, boot_entry);
- if (! e)
- continue; /* Menu is empty. */
-
- grub_cls ();
- grub_setcursor (1);
-
- grub_printf (" Booting \'%s\'\n\n", e->title);
-
- grub_menu_execute_entry (e);
-
- /* Deal with a fallback entry. */
- /* FIXME: Multiple fallback entries like GRUB Legacy. */
- fallback_entry = get_entry_number ("fallback");
- if (fallback_entry >= 0)
- {
- grub_print_error ();
- grub_errno = GRUB_ERR_NONE;
-
- e = get_entry (menu, fallback_entry);
- grub_env_unset ("fallback");
- grub_printf ("\n Falling back to \'%s\'\n\n", e->title);
- grub_menu_execute_entry (e);
- }
-
- if (grub_errno != GRUB_ERR_NONE)
- {
- grub_print_error ();
- grub_errno = GRUB_ERR_NONE;
-
- grub_wait_after_message ();
- }
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+
+ entry = grub_menu_get_entry (menu, fallback_entry);
+ callback->notify_fallback (entry, callback_data);
+ grub_menu_execute_entry (entry);
}
- return GRUB_ERR_NONE;
+ if (grub_errno != GRUB_ERR_NONE)
+ callback->notify_failure (callback_data);
}
-
-struct grub_menu_viewer grub_normal_terminal_menu_viewer =
-{
- .name = "terminal",
- .show_menu = show_text_menu
-};
=== added file 'normal/menu_text.c'
--- normal/menu_text.c 1970-01-01 00:00:00 +0000
+++ normal/menu_text.c 2009-02-05 17:22:49 +0000
@@ -0,0 +1,570 @@
+/* menu_text.c - Basic text menu implementation. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static grub_uint8_t grub_color_menu_normal;
+static grub_uint8_t grub_color_menu_highlight;
+
+/* Wait until the user pushes any key so that the user
+ can see what happened. */
+void
+grub_wait_after_message (void)
+{
+ grub_printf ("\nPress any key to continue...");
+ (void) grub_getkey ();
+}
+
+static void
+draw_border (void)
+{
+ unsigned i;
+
+ grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+
+ grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y);
+ grub_putcode (GRUB_TERM_DISP_UL);
+ for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++)
+ grub_putcode (GRUB_TERM_DISP_HLINE);
+ grub_putcode (GRUB_TERM_DISP_UR);
+
+ for (i = 0; i < (unsigned) GRUB_TERM_NUM_ENTRIES; i++)
+ {
+ grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1);
+ grub_putcode (GRUB_TERM_DISP_VLINE);
+ grub_gotoxy (GRUB_TERM_MARGIN + GRUB_TERM_BORDER_WIDTH - 1,
+ GRUB_TERM_TOP_BORDER_Y + i + 1);
+ grub_putcode (GRUB_TERM_DISP_VLINE);
+ }
+
+ grub_gotoxy (GRUB_TERM_MARGIN,
+ GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES + 1);
+ grub_putcode (GRUB_TERM_DISP_LL);
+ for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++)
+ grub_putcode (GRUB_TERM_DISP_HLINE);
+ grub_putcode (GRUB_TERM_DISP_LR);
+
+ grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+
+ grub_gotoxy (GRUB_TERM_MARGIN,
+ (GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES
+ + GRUB_TERM_MARGIN + 1));
+}
+
+static void
+print_message (int nested, int edit)
+{
+ grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+
+ if (edit)
+ {
+ grub_printf ("\n\
+ Minimum Emacs-like screen editing is supported. TAB lists\n\
+ completions. Press Ctrl-x to boot, Ctrl-c for a command-line\n\
+ or ESC to return menu.");
+ }
+ else
+ {
+ grub_printf ("\n\
+ Use the %C and %C keys to select which entry is highlighted.\n",
+ (grub_uint32_t) GRUB_TERM_DISP_UP, (grub_uint32_t) GRUB_TERM_DISP_DOWN);
+ grub_printf ("\
+ Press enter to boot the selected OS, \'e\' to edit the\n\
+ commands before booting or \'c\' for a command-line.");
+ if (nested)
+ grub_printf ("\n\
+ ESC to return previous menu.");
+ }
+}
+
+static void
+print_entry (int y, int highlight, grub_menu_entry_t entry)
+{
+ int x;
+ const char *title;
+ grub_size_t title_len;
+ grub_ssize_t len;
+ grub_uint32_t *unicode_title;
+ grub_ssize_t i;
+ grub_uint8_t old_color_normal, old_color_highlight;
+
+ title = entry ? entry->title : "";
+ title_len = grub_strlen (title);
+ unicode_title = grub_malloc (title_len * sizeof (*unicode_title));
+ if (! unicode_title)
+ /* XXX How to show this error? */
+ return;
+
+ len = grub_utf8_to_ucs4 (unicode_title, title_len,
+ (grub_uint8_t *) title, -1, 0);
+ if (len < 0)
+ {
+ /* It is an invalid sequence. */
+ grub_free (unicode_title);
+ return;
+ }
+
+ grub_getcolor (&old_color_normal, &old_color_highlight);
+ grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight);
+ grub_setcolorstate (highlight
+ ? GRUB_TERM_COLOR_HIGHLIGHT
+ : GRUB_TERM_COLOR_NORMAL);
+
+ grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN, y);
+
+ for (x = GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1, i = 0;
+ x < GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH - GRUB_TERM_MARGIN;
+ i++)
+ {
+ if (i < len
+ && x <= (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH
+ - GRUB_TERM_MARGIN - 1))
+ {
+ grub_ssize_t width;
+
+ width = grub_getcharwidth (unicode_title[i]);
+
+ if (x + width > (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH
+ - GRUB_TERM_MARGIN - 1))
+ grub_putcode (GRUB_TERM_DISP_RIGHT);
+ else
+ grub_putcode (unicode_title[i]);
+
+ x += width;
+ }
+ else
+ {
+ grub_putchar (' ');
+ x++;
+ }
+ }
+ grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+ grub_putchar (' ');
+
+ grub_gotoxy (GRUB_TERM_CURSOR_X, y);
+
+ grub_setcolor (old_color_normal, old_color_highlight);
+ grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+ grub_free (unicode_title);
+}
+
+static void
+print_entries (grub_menu_t menu, int first, int offset)
+{
+ grub_menu_entry_t e;
+ int i;
+
+ grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
+ GRUB_TERM_FIRST_ENTRY_Y);
+
+ if (first)
+ grub_putcode (GRUB_TERM_DISP_UP);
+ else
+ grub_putchar (' ');
+
+ e = grub_menu_get_entry (menu, first);
+
+ for (i = 0; i < GRUB_TERM_NUM_ENTRIES; i++)
+ {
+ print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e);
+ if (e)
+ e = e->next;
+ }
+
+ grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
+ GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES);
+
+ if (e)
+ grub_putcode (GRUB_TERM_DISP_DOWN);
+ else
+ grub_putchar (' ');
+
+ grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
+}
+
+/* Initialize the screen. If NESTED is non-zero, assume that this menu
+ is run from another menu or a command-line. If EDIT is non-zero, show
+ a message for the menu entry editor. */
+void
+grub_menu_init_page (int nested, int edit)
+{
+ grub_uint8_t old_color_normal, old_color_highlight;
+
+ grub_getcolor (&old_color_normal, &old_color_highlight);
+
+ /* By default, use the same colors for the menu. */
+ grub_color_menu_normal = old_color_normal;
+ grub_color_menu_highlight = old_color_highlight;
+
+ /* Then give user a chance to replace them. */
+ grub_parse_color_name_pair (&grub_color_menu_normal, grub_env_get ("menu_color_normal"));
+ grub_parse_color_name_pair (&grub_color_menu_highlight, grub_env_get ("menu_color_highlight"));
+
+ grub_normal_init_page ();
+ grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight);
+ draw_border ();
+ grub_setcolor (old_color_normal, old_color_highlight);
+ print_message (nested, edit);
+}
+
+/* Get the entry number from the variable NAME. */
+static int
+get_entry_number (const char *name)
+{
+ char *val;
+ int entry;
+
+ val = grub_env_get (name);
+ if (! val)
+ return -1;
+
+ grub_error_push ();
+
+ entry = (int) grub_strtoul (val, 0, 0);
+
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ entry = -1;
+ }
+
+ grub_error_pop ();
+
+ return entry;
+}
+
+static void
+print_timeout (int timeout, int offset, int second_stage)
+{
+ /* NOTE: Do not remove the trailing space characters.
+ They are required to clear the line. */
+ char *msg = " The highlighted entry will be booted automatically in %ds. ";
+ char *msg_end = grub_strchr (msg, '%');
+
+ grub_gotoxy (second_stage ? (msg_end - msg) : 0, GRUB_TERM_HEIGHT - 3);
+ grub_printf (second_stage ? msg_end : msg, timeout);
+ grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
+ grub_refresh ();
+};
+
+static int
+run_menu (grub_menu_t menu, int nested)
+{
+ int first, offset;
+ grub_uint64_t saved_time;
+ int default_entry;
+ int timeout;
+
+ first = 0;
+
+ default_entry = get_entry_number ("default");
+
+ /* If DEFAULT_ENTRY is not within the menu entries, fall back to
+ the first entry. */
+ if (default_entry < 0 || default_entry >= menu->size)
+ default_entry = 0;
+
+ /* If timeout is 0, drawing is pointless (and ugly). */
+ if (grub_menu_get_timeout () == 0)
+ return default_entry;
+
+ offset = default_entry;
+ if (offset > GRUB_TERM_NUM_ENTRIES - 1)
+ {
+ first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
+ offset = GRUB_TERM_NUM_ENTRIES - 1;
+ }
+
+ /* Initialize the time. */
+ saved_time = grub_get_time_ms ();
+
+ refresh:
+ grub_setcursor (0);
+ grub_menu_init_page (nested, 0);
+ print_entries (menu, first, offset);
+ grub_refresh ();
+
+ timeout = grub_menu_get_timeout ();
+
+ if (timeout > 0)
+ print_timeout (timeout, offset, 0);
+
+ while (1)
+ {
+ int c;
+ timeout = grub_menu_get_timeout ();
+
+ if (timeout > 0)
+ {
+ grub_uint64_t current_time;
+
+ current_time = grub_get_time_ms ();
+ if (current_time - saved_time >= 1000)
+ {
+ timeout--;
+ grub_menu_set_timeout (timeout);
+ saved_time = current_time;
+ print_timeout (timeout, offset, 1);
+ }
+ }
+
+ if (timeout == 0)
+ {
+ grub_env_unset ("timeout");
+ return default_entry;
+ }
+
+ if (grub_checkkey () >= 0 || timeout < 0)
+ {
+ c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
+
+ if (timeout >= 0)
+ {
+ grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
+ grub_printf ("\
+ ");
+ grub_env_unset ("timeout");
+ grub_env_unset ("fallback");
+ grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
+ }
+
+ switch (c)
+ {
+ case GRUB_TERM_HOME:
+ first = 0;
+ offset = 0;
+ print_entries (menu, first, offset);
+ break;
+
+ case GRUB_TERM_END:
+ offset = menu->size - 1;
+ if (offset > GRUB_TERM_NUM_ENTRIES - 1)
+ {
+ first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
+ offset = GRUB_TERM_NUM_ENTRIES - 1;
+ }
+ print_entries (menu, first, offset);
+ break;
+
+ case GRUB_TERM_UP:
+ case '^':
+ if (offset > 0)
+ {
+ print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
+ grub_menu_get_entry (menu, first + offset));
+ offset--;
+ print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
+ grub_menu_get_entry (menu, first + offset));
+ }
+ else if (first > 0)
+ {
+ first--;
+ print_entries (menu, first, offset);
+ }
+ break;
+
+ case GRUB_TERM_DOWN:
+ case 'v':
+ if (menu->size > first + offset + 1)
+ {
+ if (offset < GRUB_TERM_NUM_ENTRIES - 1)
+ {
+ print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
+ grub_menu_get_entry (menu, first + offset));
+ offset++;
+ print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
+ grub_menu_get_entry (menu, first + offset));
+ }
+ else
+ {
+ first++;
+ print_entries (menu, first, offset);
+ }
+ }
+ break;
+
+ case GRUB_TERM_PPAGE:
+ if (first == 0)
+ {
+ offset = 0;
+ }
+ else
+ {
+ first -= GRUB_TERM_NUM_ENTRIES;
+
+ if (first < 0)
+ {
+ offset += first;
+ first = 0;
+ }
+ }
+ print_entries (menu, first, offset);
+ break;
+
+ case GRUB_TERM_NPAGE:
+ if (offset == 0)
+ {
+ offset += GRUB_TERM_NUM_ENTRIES - 1;
+ if (first + offset >= menu->size)
+ {
+ offset = menu->size - first - 1;
+ }
+ }
+ else
+ {
+ first += GRUB_TERM_NUM_ENTRIES;
+
+ if (first + offset >= menu->size)
+ {
+ first -= GRUB_TERM_NUM_ENTRIES;
+ offset += GRUB_TERM_NUM_ENTRIES;
+
+ if (offset > menu->size - 1 ||
+ offset > GRUB_TERM_NUM_ENTRIES - 1)
+ {
+ offset = menu->size - first - 1;
+ }
+ if (offset > GRUB_TERM_NUM_ENTRIES)
+ {
+ first += offset - GRUB_TERM_NUM_ENTRIES + 1;
+ offset = GRUB_TERM_NUM_ENTRIES - 1;
+ }
+ }
+ }
+ print_entries (menu, first, offset);
+ break;
+
+ case '\n':
+ case '\r':
+ case 6:
+ grub_setcursor (1);
+ return first + offset;
+
+ case '\e':
+ if (nested)
+ {
+ grub_setcursor (1);
+ return -1;
+ }
+ break;
+
+ case 'c':
+ grub_cmdline_run (1);
+ goto refresh;
+
+ case 'e':
+ {
+ grub_menu_entry_t e = grub_menu_get_entry (menu, first + offset);
+ if (e)
+ grub_menu_entry_run (e);
+ }
+ goto refresh;
+
+ default:
+ break;
+ }
+
+ grub_refresh ();
+ }
+ }
+
+ /* Never reach here. */
+ return -1;
+}
+
+/* Callback invoked immediately before a menu entry is executed. */
+static void
+notify_booting (grub_menu_entry_t entry,
+ void *userdata __attribute__((unused)))
+{
+ grub_printf (" Booting \'%s\'\n\n", entry->title);
+}
+
+/* Callback invoked when a default menu entry executed because of a timeout
+ has failed and an attempt will be made to execute the next fallback
+ entry, ENTRY. */
+static void
+notify_fallback (grub_menu_entry_t entry,
+ void *userdata __attribute__((unused)))
+{
+ grub_printf ("\n Falling back to \'%s\'\n\n", entry->title);
+ grub_millisleep (2000);
+}
+
+/* Callback invoked when a menu entry has failed and there is no remaining
+ fallback entry to attempt. */
+static void
+notify_execution_failure (void *userdata __attribute__((unused)))
+{
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+
+ grub_wait_after_message ();
+ }
+}
+
+/* Callbacks used by the text menu to provide user feedback when menu entries
+ are executed. */
+static struct grub_menu_execute_callback execution_callback =
+{
+ .notify_booting = notify_booting,
+ .notify_fallback = notify_fallback,
+ .notify_failure = notify_execution_failure
+};
+
+static grub_err_t
+show_text_menu (grub_menu_t menu, int nested)
+{
+ while (1)
+ {
+ int boot_entry;
+ grub_menu_entry_t e;
+
+ boot_entry = run_menu (menu, nested);
+ if (boot_entry < 0)
+ break;
+
+ e = grub_menu_get_entry (menu, boot_entry);
+ if (! e)
+ continue; /* Menu is empty. */
+
+ grub_cls ();
+ grub_setcursor (1);
+
+ grub_menu_execute_with_fallback (menu, e, &execution_callback, 0);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+struct grub_menu_viewer grub_normal_text_menu_viewer =
+{
+ .name = "text",
+ .show_menu = show_text_menu
+};