From: Colin Watson Date: Thu, 14 Jan 2010 14:04:44 +0000 (+0000) Subject: merge from trunk X-Git-Tag: 1.98~187^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7d1468e4b675037f59cc246fe39ab19dcee54ade;p=thirdparty%2Fgrub.git merge from trunk --- 7d1468e4b675037f59cc246fe39ab19dcee54ade diff --cc normal/menu.c index b9f74b7d7,24c1588d8..17730eff3 --- a/normal/menu.c +++ b/normal/menu.c @@@ -180,3 -198,378 +200,400 @@@ grub_menu_execute_with_fallback (grub_m callback->notify_failure (callback_data); } + + static struct grub_menu_viewer *viewers; + + static void + menu_set_chosen_entry (int entry) + { + struct grub_menu_viewer *cur; + for (cur = viewers; cur; cur = cur->next) + cur->set_chosen_entry (entry, cur->data); + } + + static void + menu_print_timeout (int timeout) + { + struct grub_menu_viewer *cur; + for (cur = viewers; cur; cur = cur->next) + cur->print_timeout (timeout, cur->data); + } + + static void + menu_fini (void) + { + struct grub_menu_viewer *cur, *next; + for (cur = viewers; cur; cur = next) + { + next = cur->next; + cur->fini (cur->data); + grub_free (cur); + } + viewers = NULL; + } + + static void + menu_init (int entry, grub_menu_t menu, int nested) + { + struct grub_term_output *term; + + FOR_ACTIVE_TERM_OUTPUTS(term) + { + grub_err_t err; + + if (grub_gfxmenu_try_hook && grub_strcmp (term->name, "gfxterm") == 0) + { + err = grub_gfxmenu_try_hook (entry, menu, nested); + if(!err) + continue; + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + + err = grub_menu_try_text (term, entry, menu, nested); + if(!err) + continue; + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + } + + static void + clear_timeout (void) + { + struct grub_menu_viewer *cur; + for (cur = viewers; cur; cur = cur->next) + cur->clear_timeout (cur->data); + } + + void + grub_menu_register_viewer (struct grub_menu_viewer *viewer) + { + viewer->next = viewers; + viewers = viewer; + } + + /* Get the entry number from the variable NAME. */ + static int -get_entry_number (const char *name) ++get_entry_number (grub_menu_t menu, 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_BAD_NUMBER) ++ { ++ /* See if the variable matches the title of a menu entry. */ ++ grub_menu_entry_t e = menu->entry_list; ++ int i; ++ ++ grub_errno = GRUB_ERR_NONE; ++ ++ for (i = 0; e; i++) ++ { ++ if (grub_strcmp (e->title, val) == 0) ++ { ++ entry = i; ++ break; ++ } ++ e = e->next; ++ } ++ ++ if (! e) ++ entry = -1; ++ } ++ + if (grub_errno != GRUB_ERR_NONE) + { + grub_errno = GRUB_ERR_NONE; + entry = -1; + } + + grub_error_pop (); + + return entry; + } + + #define GRUB_MENU_PAGE_SIZE 10 + + /* Show the menu and handle menu entry selection. Returns the menu entry + index that should be executed or -1 if no entry should be executed (e.g., + Esc pressed to exit a sub-menu or switching menu viewers). + If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu + entry to be executed is a result of an automatic default selection because + of the timeout. */ + static int + run_menu (grub_menu_t menu, int nested, int *auto_boot) + { + grub_uint64_t saved_time; + int default_entry, current_entry; + int timeout; + - default_entry = get_entry_number ("default"); ++ default_entry = get_entry_number (menu, "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) + { + *auto_boot = 1; + return default_entry; + } + + current_entry = default_entry; + + /* Initialize the time. */ + saved_time = grub_get_time_ms (); + + refresh: + menu_init (current_entry, menu, nested); + + timeout = grub_menu_get_timeout (); + + if (timeout > 0) + menu_print_timeout (timeout); + + while (1) + { + int c; + timeout = grub_menu_get_timeout (); + + if (grub_normal_exit_level) + return -1; + + 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; + menu_print_timeout (timeout); + } + } + + if (timeout == 0) + { + grub_env_unset ("timeout"); + *auto_boot = 1; + menu_fini (); + return default_entry; + } + + if (grub_checkkey () >= 0 || timeout < 0) + { + c = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + + if (timeout >= 0) + { + grub_env_unset ("timeout"); + grub_env_unset ("fallback"); + clear_timeout (); + } + + switch (c) + { + case GRUB_TERM_HOME: + current_entry = 0; + menu_set_chosen_entry (current_entry); + break; + + case GRUB_TERM_END: + current_entry = menu->size - 1; + menu_set_chosen_entry (current_entry); + break; + + case GRUB_TERM_UP: + case '^': + if (current_entry > 0) + current_entry--; + menu_set_chosen_entry (current_entry); + break; + + case GRUB_TERM_DOWN: + case 'v': + if (current_entry < menu->size - 1) + current_entry++; + menu_set_chosen_entry (current_entry); + break; + + case GRUB_TERM_PPAGE: + if (current_entry < GRUB_MENU_PAGE_SIZE) + current_entry = 0; + else + current_entry -= GRUB_MENU_PAGE_SIZE; + menu_set_chosen_entry (current_entry); + break; + + case GRUB_TERM_NPAGE: + if (current_entry + GRUB_MENU_PAGE_SIZE < menu->size) + current_entry += GRUB_MENU_PAGE_SIZE; + else + current_entry = menu->size - 1; + menu_set_chosen_entry (current_entry); + break; + + case '\n': + case '\r': + case 6: + menu_fini (); + *auto_boot = 0; + return current_entry; + + case '\e': + if (nested) + { + menu_fini (); + return -1; + } + break; + + case 'c': + menu_fini (); + grub_cmdline_run (1); + goto refresh; + + case 'e': + menu_fini (); + { + grub_menu_entry_t e = grub_menu_get_entry (menu, current_entry); + if (e) + grub_menu_entry_run (e); + } + goto refresh; + + default: + break; + } + } + } + + /* 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 (" "); + grub_printf_ (N_("Booting \'%s\'"), entry->title); + grub_printf ("\n\n"); + } + + /* 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 "); + grub_printf_ (N_("Falling back to \'%s\'"), entry->title); + grub_printf ("\n\n"); + grub_millisleep (DEFAULT_ENTRY_ERROR_DELAY_MS); + } + + /* 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_printf ("\n "); + grub_printf_ (N_("Failed to boot default entries.\n")); + 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_menu (grub_menu_t menu, int nested) + { + while (1) + { + int boot_entry; + grub_menu_entry_t e; + int auto_boot; + + boot_entry = run_menu (menu, nested, &auto_boot); + if (boot_entry < 0) + break; + + e = grub_menu_get_entry (menu, boot_entry); + if (! e) + continue; /* Menu is empty. */ + + grub_cls (); + + if (auto_boot) + { + grub_menu_execute_with_fallback (menu, e, &execution_callback, 0); + } + else + { + grub_errno = GRUB_ERR_NONE; + grub_menu_execute_entry (e); + if (grub_errno != GRUB_ERR_NONE) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + grub_wait_after_message (); + } + } + } + + return GRUB_ERR_NONE; + } + + grub_err_t + grub_show_menu (grub_menu_t menu, int nested) + { + grub_err_t err1, err2; + + while (1) + { + err1 = show_menu (menu, nested); + grub_print_error (); + + if (grub_normal_exit_level) + break; + + err2 = grub_auth_check_authentication (NULL); + if (err2) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + continue; + } + + break; + } + + return err1; + } diff --cc util/grub.d/10_hurd.in index c1871e07a,ff883f461..65a9a70b1 --- a/util/grub.d/10_hurd.in +++ b/util/grub.d/10_hurd.in @@@ -73,12 -73,13 +73,14 @@@ menuentry "${OS}" EOF prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" cat << EOF - multiboot ${kernel} root=device:${GRUB_DEVICE#/dev/} + echo $(gettext "Loading GNU Mach ...") + multiboot ${kernel} root=device:${GRUB_DEVICE#/dev/} EOF +save_default_entry | sed -e "s/^/\t/" prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/" cat << EOF - module /hurd/${hurd_fs}.static ${hurd_fs} --readonly \\ + echo $(gettext "Loading the Hurd ...") + module /hurd/${hurd_fs}.static ${hurd_fs} --readonly \\ --multiboot-command-line='\${kernel-command-line}' \\ --host-priv-port='\${host-port}' \\ --device-master-port='\${device-port}' \\