[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>
This commit is contained in:
Michael Brown
2025-02-19 13:12:29 +00:00
parent ccd6200549
commit e7595fe88d
3 changed files with 20 additions and 9 deletions

View File

@@ -207,8 +207,10 @@ static int item_exec ( int argc, char **argv ) {
struct choose_options { struct choose_options {
/** Dynamic user interface name */ /** Dynamic user interface name */
char *dynui; char *dynui;
/** Timeout */ /** Initial timeout */
unsigned long timeout; unsigned long timeout;
/** Post-activity timeout */
unsigned long retimeout;
/** Default selection */ /** Default selection */
char *select; char *select;
/** Keep dynamic user interface */ /** Keep dynamic user interface */
@@ -223,6 +225,8 @@ static struct option_descriptor choose_opts[] = {
struct choose_options, select, parse_string ), struct choose_options, select, parse_string ),
OPTION_DESC ( "timeout", 't', required_argument, OPTION_DESC ( "timeout", 't', required_argument,
struct choose_options, timeout, parse_timeout ), struct choose_options, timeout, parse_timeout ),
OPTION_DESC ( "retimeout", 'r', required_argument,
struct choose_options, retimeout, parse_timeout ),
OPTION_DESC ( "keep", 'k', no_argument, OPTION_DESC ( "keep", 'k', no_argument,
struct choose_options, keep, parse_flag ), struct choose_options, keep, parse_flag ),
}; };
@@ -259,8 +263,8 @@ static int choose_exec ( int argc, char **argv ) {
goto err_parse_dynui; goto err_parse_dynui;
/* Show as menu */ /* Show as menu */
if ( ( rc = show_menu ( dynui, opts.timeout, opts.select, if ( ( rc = show_menu ( dynui, opts.timeout, opts.retimeout,
&item ) ) != 0 ) opts.select, &item ) ) != 0 )
goto err_show_menu; goto err_show_menu;
/* Apply default type if necessary */ /* Apply default type if necessary */

View File

@@ -53,8 +53,10 @@ struct menu_ui {
struct dynamic_ui *dynui; struct dynamic_ui *dynui;
/** Jump scroller */ /** Jump scroller */
struct jump_scroller scroll; struct jump_scroller scroll;
/** Timeout (0=indefinite) */ /** Remaining timeout (0=indefinite) */
unsigned long timeout; unsigned long timeout;
/** Post-activity timeout (0=indefinite) */
unsigned long retimeout;
}; };
/** /**
@@ -180,8 +182,8 @@ static int menu_loop ( struct menu_ui *ui, struct dynamic_item **selected ) {
if ( ui->timeout == 0 ) if ( ui->timeout == 0 )
chosen = 1; chosen = 1;
} else { } else {
/* Cancel any timeout */ /* Reset timeout after activity */
ui->timeout = 0; ui->timeout = ui->retimeout;
/* Handle scroll keys */ /* Handle scroll keys */
move = jump_scroll_key ( &ui->scroll, key ); move = jump_scroll_key ( &ui->scroll, key );
@@ -241,12 +243,14 @@ static int menu_loop ( struct menu_ui *ui, struct dynamic_item **selected ) {
* Show menu * Show menu
* *
* @v dynui Dynamic user interface * @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 selected Selected item
* @ret rc Return status code * @ret rc Return status code
*/ */
int show_menu ( struct dynamic_ui *dynui, unsigned long timeout, 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 dynamic_item *item;
struct menu_ui ui; struct menu_ui ui;
char buf[ MENU_COLS + 1 /* NUL */ ]; char buf[ MENU_COLS + 1 /* NUL */ ];
@@ -258,6 +262,8 @@ int show_menu ( struct dynamic_ui *dynui, unsigned long timeout,
ui.dynui = dynui; ui.dynui = dynui;
ui.scroll.rows = MENU_ROWS; ui.scroll.rows = MENU_ROWS;
ui.timeout = timeout; ui.timeout = timeout;
ui.retimeout = retimeout;
list_for_each_entry ( item, &dynui->items, list ) { list_for_each_entry ( item, &dynui->items, list ) {
if ( item->name ) { if ( item->name ) {
if ( ! named_count ) if ( ! named_count )

View File

@@ -60,7 +60,8 @@ extern struct dynamic_item * dynui_item ( struct dynamic_ui *dynui,
extern struct dynamic_item * dynui_shortcut ( struct dynamic_ui *dynui, extern struct dynamic_item * dynui_shortcut ( struct dynamic_ui *dynui,
int key ); int key );
extern int show_menu ( struct dynamic_ui *dynui, unsigned long timeout, 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 ); extern int show_form ( struct dynamic_ui *dynui );
#endif /* _IPXE_DYNUI_H */ #endif /* _IPXE_DYNUI_H */