From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1LTLyV-000405-Vu for mharc-grub-devel@gnu.org; Sat, 31 Jan 2009 14:57:56 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LTLyU-0003zy-Em for grub-devel@gnu.org; Sat, 31 Jan 2009 14:57:54 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LTLyQ-0003zm-3O for grub-devel@gnu.org; Sat, 31 Jan 2009 14:57:53 -0500 Received: from [199.232.76.173] (port=55863 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LTLyP-0003zj-Ue for grub-devel@gnu.org; Sat, 31 Jan 2009 14:57:49 -0500 Received: from gateway12.websitewelcome.com ([67.18.55.9]:45377) by monty-python.gnu.org with smtp (Exim 4.60) (envelope-from ) id 1LTLyP-0000Ss-9g for grub-devel@gnu.org; Sat, 31 Jan 2009 14:57:49 -0500 Received: (qmail 31287 invoked from network); 31 Jan 2009 20:13:21 -0000 Received: from gator297.hostgator.com (74.53.228.114) by gateway12.websitewelcome.com with SMTP; 31 Jan 2009 20:13:21 -0000 Received: from [67.185.177.95] (port=55757 helo=localhost) by gator297.hostgator.com with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.69) (envelope-from ) id 1LTLyJ-0005RZ-Oa for grub-devel@gnu.org; Sat, 31 Jan 2009 13:57:44 -0600 Date: Sat, 31 Jan 2009 11:57:43 -0800 From: Colin D Bennett To: grub-devel@gnu.org Message-ID: <20090131115743.34bb6762@gibibit.com> X-Mailer: Claws Mail 3.7.0 (GTK+ 2.14.7; i686-pc-linux-gnu) Mime-Version: 1.0 Content-Type: multipart/signed; boundary="Sig_//K5Ai=cV7XMgNpFU_0YuSVa"; protocol="application/pgp-signature"; micalg=PGP-SHA1 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - gator297.hostgator.com X-AntiAbuse: Original Domain - gnu.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - gibibit.com X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 3) Subject: [PATCH] 1/5 Multiple fallback entries X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GRUB 2 List-Id: The development of GRUB 2 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 31 Jan 2009 19:57:54 -0000 --Sig_//K5Ai=cV7XMgNpFU_0YuSVa Content-Type: multipart/mixed; boundary="MP_/FR2YJt=S=KdaWBVDeqc6ANd" --MP_/FR2YJt=S=KdaWBVDeqc6ANd Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline This patch adds support for multiple fallback entries in grub.cfg. I'll prepare the ChangeLog entry when the patch is approved to be committed. The patch is against GRUB trunk revision 1964. Regards, Colin --MP_/FR2YJt=S=KdaWBVDeqc6ANd Content-Type: text/x-patch Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename=01_multiple-fallback.patch =3D=3D=3D modified file 'include/grub/normal.h' --- include/grub/normal.h 2009-01-31 09:15:43 +0000 +++ include/grub/normal.h 2009-01-31 17:47:55 +0000 @@ -98,10 +98,24 @@ =20 extern struct grub_menu_viewer grub_normal_terminal_menu_viewer; =20 +typedef struct grub_menu_execute_callback +{ + void (*notify_booting) (void *userdata, grub_menu_entry_t entry); + void (*notify_fallback) (void *userdata, grub_menu_entry_t entry); + void (*notify_failure) (void *userdata); +}=20 +*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 callbac= k, + 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); =3D=3D=3D modified file 'normal/menu.c' --- normal/menu.c 2009-01-31 09:15:43 +0000 +++ normal/menu.c 2009-01-31 17:47:55 +0000 @@ -244,8 +244,8 @@ =20 /* 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 +272,8 @@ } =20 /* 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) @@ -311,6 +311,44 @@ return entry; } =20 +/* Get the first entry number from the 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, returns -1. */ +static int +get_and_remove_first_entry_number (const char *name) +{ + char *val; + char *tail; + int entry; + + val =3D grub_env_get (name); + if (! val) + return -1; + + grub_error_push (); + + entry =3D (int) grub_strtoul (val, &tail, 0); + + if (grub_errno =3D=3D 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 =3D GRUB_ERR_NONE; + entry =3D -1; + } + + grub_error_pop (); + + return entry; +} + static void print_timeout (int timeout, int offset, int second_stage) { @@ -343,7 +381,7 @@ default_entry =3D 0; =20 /* If timeout is 0, drawing is pointless (and ugly). */ - if (get_timeout () =3D=3D 0) + if (grub_menu_get_timeout () =3D=3D 0) return default_entry; =20 offset =3D default_entry; @@ -362,7 +400,7 @@ print_entries (menu, first, offset); grub_refresh (); =20 - timeout =3D get_timeout (); + timeout =3D grub_menu_get_timeout (); =20 if (timeout > 0) print_timeout (timeout, offset, 0); @@ -370,7 +408,7 @@ while (1) { int c; - timeout =3D get_timeout (); + timeout =3D grub_menu_get_timeout (); =20 if (timeout > 0) { @@ -380,7 +418,7 @@ if (current_time - saved_time >=3D 1000) { timeout--; - set_timeout (timeout); + grub_menu_set_timeout (timeout); saved_time =3D current_time; print_timeout (timeout, offset, 1); } @@ -498,12 +536,12 @@ offset +=3D GRUB_TERM_NUM_ENTRIES; =20 if (offset > menu->size - 1 || - offset > GRUB_TERM_NUM_ENTRIES - 1) + offset > GRUB_TERM_NUM_ENTRIES - 1) { offset =3D menu->size - first - 1; } if (offset > GRUB_TERM_NUM_ENTRIES) - { + { first +=3D offset - GRUB_TERM_NUM_ENTRIES + 1; offset =3D GRUB_TERM_NUM_ENTRIES - 1; } @@ -561,6 +599,74 @@ grub_command_execute ("boot", 0); } =20 +/* 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) +{ + int fallback_entry; + + callback->notify_booting (callback_data, entry); + + grub_menu_execute_entry (entry); + + /* Deal with fallback entries. */ + while ((fallback_entry =3D get_and_remove_first_entry_number ("fallback"= )) + >=3D 0) + { + grub_print_error (); + grub_errno =3D GRUB_ERR_NONE; + + entry =3D get_entry (menu, fallback_entry); + callback->notify_fallback (callback_data, entry); + grub_menu_execute_entry (entry); + } + + if (grub_errno !=3D GRUB_ERR_NONE) + callback->notify_failure (callback_data); +} + +/* Callbacks for grub_menu_execute_with_fallback() for the text menu. */ + +static void +notify_booting (void *userdata __attribute__((unused)), + grub_menu_entry_t entry) +{ + grub_printf (" Booting \'%s\'\n\n", entry->title); +} + +static void +notify_fallback (void *userdata __attribute__((unused)), + grub_menu_entry_t entry) +{ + grub_printf ("\n Falling back to \'%s\'\n\n", entry->title); + grub_millisleep (2000); +} + +static void +notify_execution_failure (void *userdata __attribute__((unused))) +{ + if (grub_errno !=3D GRUB_ERR_NONE) + { + grub_print_error (); + grub_errno =3D GRUB_ERR_NONE; + + grub_wait_after_message (); + } +} + +static struct grub_menu_execute_callback execution_callback =3D +{ + .notify_booting =3D notify_booting, + .notify_fallback =3D notify_fallback, + .notify_failure =3D notify_execution_failure +}; + static grub_err_t show_text_menu (grub_menu_t menu, int nested) { @@ -568,7 +674,6 @@ { int boot_entry; grub_menu_entry_t e; - int fallback_entry; =20 boot_entry =3D run_menu (menu, nested); if (boot_entry < 0) @@ -581,31 +686,7 @@ grub_cls (); grub_setcursor (1); =20 - 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 =3D get_entry_number ("fallback"); - if (fallback_entry >=3D 0) - { - grub_print_error (); - grub_errno =3D GRUB_ERR_NONE; - - e =3D 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 !=3D GRUB_ERR_NONE) - { - grub_print_error (); - grub_errno =3D GRUB_ERR_NONE; - - grub_wait_after_message (); - } + grub_menu_execute_with_fallback (menu, e, &execution_callback, 0); } =20 return GRUB_ERR_NONE; --MP_/FR2YJt=S=KdaWBVDeqc6ANd-- --Sig_//K5Ai=cV7XMgNpFU_0YuSVa Content-Type: application/pgp-signature; name=signature.asc Content-Disposition: attachment; filename=signature.asc -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.9 (GNU/Linux) iEYEARECAAYFAkmErTkACgkQokx8fzcGbYfqVgCeIP71UUUYNA+XU41t6548NmKz tccAnjFVN5cjxYlDMU20nI4h177E/kym =4UWC -----END PGP SIGNATURE----- --Sig_//K5Ai=cV7XMgNpFU_0YuSVa--