123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- From d9371422ac74ea73d1620f01300a7136a7649754 Mon Sep 17 00:00:00 2001
- From: Leah Rowe <info@minifree.org>
- Date: Wed, 4 Dec 2024 06:52:39 +0000
- Subject: [PATCH 1/1] Support auto-boot timeout delay bootflow menu
- The bootflow menu cannot currently auto-boot a selected entry,
- which means that the user must press enter to boot their system.
- This can be a problem on headless setups; for example, it is not
- currently feasible to set up a headless server with U-Boot, when
- using it to boot via UEFI on a coreboot setup.
- This patch adds the following build-time configuration option:
- CONFIG_CMD_BOOTFLOW_BOOTDELAY
- This creates a timeout delay in the given number of seconds.
- If an arrow key is press to navigate the menu, the timer is
- disabled and the user must then press enter to boot the selected
- option. When this happens, the timeout display is replaced by
- the old message indicating that the user should press enter.
- The default boot delay is 30 seconds, and the timeout is enabled
- by default. Setting it to zero will restore the old behaviour,
- whereby no timeout is provided and the user must press enter.
- If a negative integer is provided, the timer will default to
- zero. The timer value is further filtered by modulus of 100,
- so that the maximum number of seconds allowed is 99 seconds.
- Signed-off-by: Leah Rowe <info@minifree.org>
- ---
- boot/bootflow_menu.c | 117 +++++++++++++++++++++++++++++++++++--
- cmd/Kconfig | 12 ++++
- doc/usage/cmd/bootflow.rst | 11 ++++
- include/bootflow.h | 10 +++-
- 4 files changed, 143 insertions(+), 7 deletions(-)
- diff --git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
- index 9d0dc352f9..172139b187 100644
- --- a/boot/bootflow_menu.c
- +++ b/boot/bootflow_menu.c
- @@ -30,7 +30,7 @@ struct menu_priv {
- int num_bootflows;
- };
-
- -int bootflow_menu_new(struct expo **expp)
- +int bootflow_menu_new(struct expo **expp, const char *prompt)
- {
- struct udevice *last_bootdev;
- struct scene_obj_menu *menu;
- @@ -54,7 +54,7 @@ int bootflow_menu_new(struct expo **expp)
- return log_msg_ret("scn", ret);
-
- ret |= scene_txt_str(scn, "prompt", OBJ_PROMPT, STR_PROMPT,
- - "UP and DOWN to choose, ENTER to select", NULL);
- + prompt, NULL);
-
- ret = scene_menu(scn, "main", OBJ_MENU, &menu);
- ret |= scene_obj_set_pos(scn, OBJ_MENU, MARGIN_LEFT, 100);
- @@ -138,6 +138,29 @@ int bootflow_menu_new(struct expo **expp)
- return 0;
- }
-
- +int bootflow_menu_show_countdown(struct expo *exp, char *prompt,
- + char bootflow_delay)
- +{
- + char *i;
- +
- + if (prompt == NULL)
- + return 0;
- + if (strlen(prompt) < 2)
- + return 0;
- +
- + i = prompt + strlen(prompt) - 2;
- +
- + if (bootflow_delay >= 10) {
- + *(i) = 48 + (bootflow_delay / 10);
- + *(i + 1) = 48 + (bootflow_delay % 10);
- + } else {
- + *(i) = 48 + bootflow_delay;
- + *(i + 1) = ' ';
- + }
- +
- + return expo_render(exp);
- +}
- +
- int bootflow_menu_apply_theme(struct expo *exp, ofnode node)
- {
- struct menu_priv *priv = exp->priv;
- @@ -184,14 +207,62 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
- struct expo *exp;
- uint sel_id;
- bool done;
- - int ret;
- + int i, ret;
- +
- + /* Auto-boot countdown */
- + char bootflow_delay_secs, *prompt;
- + int bootflow_time, bootflow_delay;
- + bool skip_render_once = false;
- + bool bootflow_countdown = false;
- +
- + /* TODO: perhaps set based on defconfig? */
- + /* WARNING: These two strings must be of the same length. */
- + char promptChoice[] = "UP and DOWN to choose, ENTER to select";
- + char promptTimeout[] = "UP and DOWN to choose. Auto-boot in ";
- +/*
- + // Uncomment if the strings become configurable (defconfig):
- + // (to prevent buffer overflows)
- + char promptDefault[] = "UP and DOWN to choose, ENTER to select";
- + if (promptTimeout = NULL)
- + promptTimeout = promptDefault;
- + if (promptChoice = NULL)
- + promptChoice = promptDefault;
- + if (strlen(promptChoice) < 2)
- + promptChoice = promptDefault;
- + if (strlen(promptTimeout) < 2)
- + promptTimeout = promptDefault;
- + if (strlen(promptChoice) != strlen(promptTimeout))
- + promptChoice = promptTimeout;
- +*/
- + prompt = promptChoice;
- +
- + bootflow_delay_secs = 15; /* TODO: set based on defconfig. */
- +
- +#if defined(CONFIG_CMD_BOOTFLOW_BOOTDELAY)
- + /* If set to zero, the auto-boot timeout is disabled. */
- + bootflow_delay_secs = CONFIG_CMD_BOOTFLOW_BOOTDELAY;
- +#else
- + bootflow_delay_secs = 30;
- +#endif
- +
- + if (bootflow_delay_secs < 0)
- + bootflow_delay_secs = 0; /* disable countdown if negative */
- + bootflow_delay_secs %= 100; /* No higher than 99 seconds */
- +
- + if (bootflow_delay_secs > 0) {
- + bootflow_countdown = true; /* enable auto-boot countdown */
- + prompt = promptTimeout;
- + bootflow_time = 0; /* Time elapsed in milliseconds */
- + bootflow_delay =
- + (int)bootflow_delay_secs * 1000; /* milliseconds */
- + }
-
- cli_ch_init(cch);
-
- sel_bflow = NULL;
- *bflowp = NULL;
-
- - ret = bootflow_menu_new(&exp);
- + ret = bootflow_menu_new(&exp, prompt);
- if (ret)
- return log_msg_ret("exp", ret);
-
- @@ -216,12 +287,20 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
- if (text_mode)
- expo_set_text_mode(exp, text_mode);
-
- + if (bootflow_countdown) {
- + ret = bootflow_menu_show_countdown(exp, prompt,
- + bootflow_delay_secs);
- + skip_render_once = true; /* Don't print menu twice on start */
- + }
- done = false;
- do {
- struct expo_action act;
- int ichar, key;
-
- - ret = expo_render(exp);
- + if (skip_render_once)
- + skip_render_once = false;
- + else
- + ret = expo_render(exp);
- if (ret)
- break;
-
- @@ -231,7 +310,23 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
- schedule();
- mdelay(2);
- ichar = cli_ch_process(cch, -ETIMEDOUT);
- + if (bootflow_countdown) {
- + bootflow_delay -= 2;
- + bootflow_time += 2;
- + if (bootflow_delay <= 0)
- + ichar='\n';
- + if (bootflow_time < 1000)
- + continue;
- + bootflow_time = 0;
- + --bootflow_delay_secs;
- + ret = bootflow_menu_show_countdown(exp,
- + prompt, bootflow_delay_secs);
- + if (ret)
- + break;
- + }
- }
- + if (ret)
- + break;
- if (!ichar) {
- ichar = getchar();
- ichar = cli_ch_process(cch, ichar);
- @@ -265,6 +360,17 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
- break;
- }
- }
- + if (bootflow_countdown) {
- + /* A key press interrupted the auto-boot timeout */
- + bootflow_countdown = false;
- + if (strlen(prompt) == strlen(promptChoice)) {
- + /* "Auto-boot in" becomes "Press ENTER" */
- + (void) memcpy(prompt, promptChoice,
- + strlen(promptChoice));
- + ret = expo_render(exp);
- + skip_render_once = true;
- + }
- + }
- } while (!done);
-
- if (ret)
- @@ -272,7 +378,6 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
-
- if (sel_id) {
- struct bootflow *bflow;
- - int i;
-
- for (ret = bootflow_first_glob(&bflow), i = 0; !ret && i < 36;
- ret = bootflow_next_glob(&bflow), i++) {
- diff --git a/cmd/Kconfig b/cmd/Kconfig
- index 978f44eda4..0303869625 100644
- --- a/cmd/Kconfig
- +++ b/cmd/Kconfig
- @@ -288,6 +288,7 @@ config CMD_BOOTDEV
- config CMD_BOOTFLOW
- bool "bootflow"
- depends on BOOTSTD
- + select CMD_BOOTFLOW_BOOTDELAY
- default y
- help
- Support scanning for bootflows available with the bootdevs. The
- @@ -303,6 +304,17 @@ config CMD_BOOTFLOW_FULL
-
- This command is not necessary for bootstd to work.
-
- +config CMD_BOOTFLOW_BOOTDELAY
- + int "bootflow - delay in seconds before booting the first menu option"
- + depends on CMD_BOOTFLOW
- + default 30
- + help
- + On the bootflow menu, wait for the defined number of seconds before
- + automatically booting. Unless interrupted, this will auto-boot the
- + first option in the generated list of boot options.
- +
- + Set this to zero if you wish to disable the auto-boot timeout.
- +
- config CMD_BOOTMETH
- bool "bootmeth"
- depends on BOOTSTD
- diff --git a/doc/usage/cmd/bootflow.rst b/doc/usage/cmd/bootflow.rst
- index 5d41fe37a7..728f294274 100644
- --- a/doc/usage/cmd/bootflow.rst
- +++ b/doc/usage/cmd/bootflow.rst
- @@ -32,6 +32,17 @@ Note that `CONFIG_BOOTSTD_FULL` (which enables `CONFIG_CMD_BOOTFLOW_FULL) must
- be enabled to obtain full functionality with this command. Otherwise, it only
- supports `bootflow scan` which scans and boots the first available bootflow.
-
- +The `CONFIG_CMD_BOOTFLOW_BOOTDELAY` option can be set, defining (in seconds) the
- +amount of time that U-Boot will wait; after this time passes, it will
- +automatically boot the first item when generating a bootflow menu. If the value
- +is set to zero, the timeout is disabled and the user must press enter; if it's
- +negative, the timeout is disabled, and the maximum number of seconds is 99
- +seconds. If a value higher than 100 is provided, the value is changed to a
- +modulus of 100 (remainder of the value divided by 100).
- +
- +If the `CONFIG_BOOTFLOW_BOOTFLOW` option is undefined, the timeout will default
- +to 30 seconds.
- +
- bootflow scan
- ~~~~~~~~~~~~~
-
- diff --git a/include/bootflow.h b/include/bootflow.h
- index 4d2fc7b69b..9f4245caa7 100644
- --- a/include/bootflow.h
- +++ b/include/bootflow.h
- @@ -452,7 +452,15 @@ int bootflow_iter_check_system(const struct bootflow_iter *iter);
- * @expp: Returns the expo created
- * Returns 0 on success, -ve on error
- */
- -int bootflow_menu_new(struct expo **expp);
- +int bootflow_menu_new(struct expo **expp, const char *prompt);
- +
- +/**
- + * bootflow_menu_show_countdown() - Show countdown timer for auto-boot
- + *
- + * Returns the value of expo_render()
- + */
- +int bootflow_menu_show_countdown(struct expo *exp, char *prompt,
- + char bootflow_delay);
-
- /**
- * bootflow_menu_apply_theme() - Apply a theme to a bootmenu
- --
- 2.39.5
|