diff --git a/include/grub/menu.h b/include/grub/menu.h index 3bd25e8..bc04e43 100644 --- a/include/grub/menu.h +++ b/include/grub/menu.h @@ -81,7 +81,7 @@ typedef struct grub_menu_execute_callback grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no); int grub_menu_get_timeout (void); void grub_menu_set_timeout (int timeout); -void grub_menu_execute_entry (grub_menu_entry_t entry); +void grub_menu_execute_entry(grub_menu_t menu, grub_menu_entry_t entry); void grub_menu_execute_with_fallback (grub_menu_t menu, grub_menu_entry_t entry, grub_menu_execute_callback_t callback, diff --git a/normal/menu.c b/normal/menu.c index 59ad83f..df67973 100644 --- a/normal/menu.c +++ b/normal/menu.c @@ -122,8 +122,22 @@ get_and_remove_first_entry_number (const char *name) /* Run a menu entry. */ void -grub_menu_execute_entry(grub_menu_entry_t entry) +grub_menu_execute_entry(grub_menu_t menu, grub_menu_entry_t entry) { + grub_menu_entry_t e; + int no = 0; + char buf[64]; + + for (e = menu->entry_list; e && e != entry; e = e->next, no++); + + if (e) + { + grub_sprintf (buf, "%d", no); + grub_env_set ("chosen_entry", buf); + } + else + grub_env_unset ("chosen_entry"); + grub_parser_execute ((char *) entry->sourcecode); if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ()) @@ -145,7 +159,7 @@ grub_menu_execute_with_fallback (grub_menu_t menu, callback->notify_booting (entry, callback_data); - grub_menu_execute_entry (entry); + grub_menu_execute_entry (menu, entry); /* Deal with fallback entries. */ while ((fallback_entry = get_and_remove_first_entry_number ("fallback")) @@ -156,7 +170,7 @@ grub_menu_execute_with_fallback (grub_menu_t menu, entry = grub_menu_get_entry (menu, fallback_entry); callback->notify_fallback (entry, callback_data); - grub_menu_execute_entry (entry); + grub_menu_execute_entry (menu, entry); /* If the function call to execute the entry returns at all, then this is taken to indicate a boot failure. For menu entries that do something other than actually boot an operating system, this could assume diff --git a/normal/menu_text.c b/normal/menu_text.c index e0d96c4..dd154e4 100644 --- a/normal/menu_text.c +++ b/normal/menu_text.c @@ -580,7 +580,7 @@ show_text_menu (grub_menu_t menu, int nested) else { grub_errno = GRUB_ERR_NONE; - grub_menu_execute_entry (e); + grub_menu_execute_entry (menu, e); if (grub_errno != GRUB_ERR_NONE) { grub_print_error (); diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index d8fa416..a019b36 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -32,10 +32,13 @@ for i in ${GRUB_PRELOAD_MODULES} ; do done if [ "x${GRUB_DEFAULT}" = "x" ] ; then GRUB_DEFAULT=0 ; fi +if [ "x${GRUB_DEFAULT}" = "xsaved" ] ; then GRUB_DEFAULT='${saved_entry}' ; fi + if [ "x${GRUB_TIMEOUT}" = "x" ] ; then GRUB_TIMEOUT=5 ; fi if [ "x${GRUB_GFXMODE}" = "x" ] ; then GRUB_GFXMODE=640x480 ; fi cat << EOF +load_env set default=${GRUB_DEFAULT} set timeout=${GRUB_TIMEOUT} EOF diff --git a/util/grub.d/10_freebsd.in b/util/grub.d/10_freebsd.in index 11e3a25..444fc42 100644 --- a/util/grub.d/10_freebsd.in +++ b/util/grub.d/10_freebsd.in @@ -57,6 +57,8 @@ if [ "x$kfreebsd" != "x" ] ; then cat << EOF menuentry "${OS}" { + saved_entry=\${chosen_entry} + save_env saved_entry EOF prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" cat << EOF diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in index 12d61b0..114017b 100644 --- a/util/grub.d/10_hurd.in +++ b/util/grub.d/10_hurd.in @@ -70,6 +70,8 @@ fi cat << EOF menuentry "${OS}" { + saved_entry=\${chosen_entry} + save_env saved_entry EOF prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/" cat << EOF diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index c2da413..93d141b 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -97,6 +97,8 @@ linux_entry () { cat << EOF menuentry "$1" { + saved_entry=\${chosen_entry} + save_env saved_entry EOF prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" cat << EOF diff --git a/util/grub.d/10_windows.in b/util/grub.d/10_windows.in index 8877b15..fc70e59 100644 --- a/util/grub.d/10_windows.in +++ b/util/grub.d/10_windows.in @@ -71,6 +71,8 @@ for dir in $dirlist ; do echo "Found $OS on $dir ($dev)" >&2 cat << EOF menuentry "$OS" { + saved_entry=\${chosen_entry} + save_env saved_entry EOF prepare_grub_to_access_device "$dev" | sed 's,^,\t,' diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in index a145277..352e464 100644 --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in @@ -45,6 +45,8 @@ for OS in ${OSPROBED} ; do cat << EOF menuentry "${LONGNAME} (on ${DEVICE})" { + saved_entry=\${chosen_entry} + save_env saved_entry set root=${CHAINROOT} chainloader +1 } @@ -69,6 +71,8 @@ EOF cat << EOF menuentry "${LLABEL} (on ${DEVICE})" { + saved_entry=\${chosen_entry} + save_env saved_entry set root=${LINUXROOT} linux ${LKERNEL} ${LPARAMS} EOF @@ -88,6 +92,8 @@ EOF OSXDISK=disk"`echo ${OSXROOT} | awk -F , '{ print $1 ; }' | sed 's/(hd//;'`"s"`echo ${OSXROOT} | awk -F , '{ print $2 ; }' | sed 's/)//;'`" cat << EOF menuentry "${LONGNAME} (on ${DEVICE})" { + saved_entry=\${chosen_entry} + save_env saved_entry set root=${OSXROOT} insmod vbe insmod gfxterm diff --git a/util/i386/pc/grub-install.in b/util/i386/pc/grub-install.in index 468a72e..0b9572b 100644 --- a/util/i386/pc/grub-install.in +++ b/util/i386/pc/grub-install.in @@ -39,6 +39,7 @@ else fi grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` +grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` rootdir= grub_prefix=`echo /boot/grub | sed ${transform}` modules= @@ -230,6 +231,10 @@ if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then done fi +if ! test -f ${grubdir}/grubenv; then + $grub_editenv ${grubdir}/grubenv create +fi + # Write device to a variable so we don't have to traverse /dev every time. grub_device=`$grub_probe --target=device ${grubdir}`