[menu] Allow a post-activity timeout to be defined

Allow the "--retimeout" option to be used to specify a timeout value
that will be (re)applied after each keypress activity.  This allows
script authors to ensure that a single (potentially accidental)
keypress will not pause the boot process indefinitely.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
diff --git a/src/hci/commands/dynui_cmd.c b/src/hci/commands/dynui_cmd.c
index d4446dc..6cad638 100644
--- a/src/hci/commands/dynui_cmd.c
+++ b/src/hci/commands/dynui_cmd.c
@@ -207,8 +207,10 @@
 struct choose_options {
 	/** Dynamic user interface name */
 	char *dynui;
-	/** Timeout */
+	/** Initial timeout */
 	unsigned long timeout;
+	/** Post-activity timeout */
+	unsigned long retimeout;
 	/** Default selection */
 	char *select;
 	/** Keep dynamic user interface */
@@ -223,6 +225,8 @@
 		      struct choose_options, select, parse_string ),
 	OPTION_DESC ( "timeout", 't', required_argument,
 		      struct choose_options, timeout, parse_timeout ),
+	OPTION_DESC ( "retimeout", 'r', required_argument,
+		      struct choose_options, retimeout, parse_timeout ),
 	OPTION_DESC ( "keep", 'k', no_argument,
 		      struct choose_options, keep, parse_flag ),
 };
@@ -259,8 +263,8 @@
 		goto err_parse_dynui;
 
 	/* Show as menu */
-	if ( ( rc = show_menu ( dynui, opts.timeout, opts.select,
-				&item ) ) != 0 )
+	if ( ( rc = show_menu ( dynui, opts.timeout, opts.retimeout,
+				opts.select, &item ) ) != 0 )
 		goto err_show_menu;
 
 	/* Apply default type if necessary */
diff --git a/src/hci/tui/menu_ui.c b/src/hci/tui/menu_ui.c
index b7b52ee..c7fad4a 100644
--- a/src/hci/tui/menu_ui.c
+++ b/src/hci/tui/menu_ui.c
@@ -53,8 +53,10 @@
 	struct dynamic_ui *dynui;
 	/** Jump scroller */
 	struct jump_scroller scroll;
-	/** Timeout (0=indefinite) */
+	/** Remaining timeout (0=indefinite) */
 	unsigned long timeout;
+	/** Post-activity timeout (0=indefinite) */
+	unsigned long retimeout;
 };
 
 /**
@@ -180,8 +182,8 @@
 			if ( ui->timeout == 0 )
 				chosen = 1;
 		} else {
-			/* Cancel any timeout */
-			ui->timeout = 0;
+			/* Reset timeout after activity */
+			ui->timeout = ui->retimeout;
 
 			/* Handle scroll keys */
 			move = jump_scroll_key ( &ui->scroll, key );
@@ -241,12 +243,14 @@
  * Show menu
  *
  * @v dynui		Dynamic user interface
- * @v timeout		Timeout period, in ticks (0=indefinite)
+ * @v timeout		Initial timeout period, in ticks (0=indefinite)
+ * @v retimeout		Post-activity timeout period, in ticks (0=indefinite)
  * @ret selected	Selected item
  * @ret rc		Return status code
  */
 int show_menu ( struct dynamic_ui *dynui, unsigned long timeout,
-		const char *select, struct dynamic_item **selected ) {
+		unsigned long retimeout, const char *select,
+		struct dynamic_item **selected ) {
 	struct dynamic_item *item;
 	struct menu_ui ui;
 	char buf[ MENU_COLS + 1 /* NUL */ ];
@@ -258,6 +262,8 @@
 	ui.dynui = dynui;
 	ui.scroll.rows = MENU_ROWS;
 	ui.timeout = timeout;
+	ui.retimeout = retimeout;
+
 	list_for_each_entry ( item, &dynui->items, list ) {
 		if ( item->name ) {
 			if ( ! named_count )
diff --git a/src/include/ipxe/dynui.h b/src/include/ipxe/dynui.h
index 67eb8b8..f47f5cb 100644
--- a/src/include/ipxe/dynui.h
+++ b/src/include/ipxe/dynui.h
@@ -60,7 +60,8 @@
 extern struct dynamic_item * dynui_shortcut ( struct dynamic_ui *dynui,
 					      int key );
 extern int show_menu ( struct dynamic_ui *dynui, unsigned long timeout,
-		       const char *select, struct dynamic_item **selected );
+		       unsigned long retimeout, const char *select,
+		       struct dynamic_item **selected );
 extern int show_form ( struct dynamic_ui *dynui );
 
 #endif /* _IPXE_DYNUI_H */