Add auto-boot timeout for U-Boot's bootflow menu
Otherwise, you have to press enter to boot your distro. With this, a timeout is created. After a number of seconds, which can be reconfigured, the first option selected will be booted, when generating a bootflow menu. The timeout is disabled when you navigate the menu; it only kicks in if you don't input anything on the keyboard. More information about how this works is in the U-Boot patches, within this patch. I've set the timeout to 8 seconds. Signed-off-by: Leah Rowe <leah@libreboot.org>20241206-t480-thunderbolt-unstable
parent
7a6e47c24f
commit
c038b653ac
|
@ -500,6 +500,7 @@ CONFIG_CMD_BOOTM=y
|
|||
CONFIG_CMD_BOOTDEV=y
|
||||
CONFIG_CMD_BOOTFLOW=y
|
||||
CONFIG_CMD_BOOTFLOW_FULL=y
|
||||
CONFIG_CMD_BOOTFLOW_BOOTDELAY=8
|
||||
CONFIG_CMD_BOOTMETH=y
|
||||
CONFIG_BOOTM_EFI=y
|
||||
CONFIG_BOOTM_ELF=y
|
||||
|
|
|
@ -390,6 +390,7 @@ CONFIG_CMD_BOOTM=y
|
|||
CONFIG_CMD_BOOTDEV=y
|
||||
CONFIG_CMD_BOOTFLOW=y
|
||||
CONFIG_CMD_BOOTFLOW_FULL=y
|
||||
CONFIG_CMD_BOOTFLOW_BOOTDELAY=8
|
||||
CONFIG_CMD_BOOTMETH=y
|
||||
CONFIG_BOOTM_EFI=y
|
||||
CONFIG_BOOTM_ELF=y
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
From 1b1673e76dae73885089415132284e9a14ecd4ac Mon Sep 17 00:00:00 2001
|
||||
From: Leah Rowe <info@minifree.org>
|
||||
Date: Tue, 3 Dec 2024 20:31:32 +0000
|
||||
Subject: [PATCH 1/1] Add an 8sec autoboot timeout on the bootflow menu
|
||||
|
||||
Otherwise, you have to press enter to load from a boot option,
|
||||
which is unacceptable on headless setups.
|
||||
|
||||
If you press the arrow keys to interrupt it, the timer will stop
|
||||
and you must then press enter to boot an option.
|
||||
|
||||
Otherwise, if you just leave U-Boot to do its thing, it will
|
||||
automatically boot what was selected, e.g. installed OS.
|
||||
|
||||
Signed-off-by: Leah Rowe <info@minifree.org>
|
||||
---
|
||||
boot/bootflow_menu.c | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
|
||||
index 9d0dc352f9..c788b86cdc 100644
|
||||
--- a/boot/bootflow_menu.c
|
||||
+++ b/boot/bootflow_menu.c
|
||||
@@ -59,7 +59,7 @@ int bootflow_menu_new(struct expo **expp)
|
||||
ret = scene_menu(scn, "main", OBJ_MENU, &menu);
|
||||
ret |= scene_obj_set_pos(scn, OBJ_MENU, MARGIN_LEFT, 100);
|
||||
ret |= scene_txt_str(scn, "title", OBJ_MENU_TITLE, STR_MENU_TITLE,
|
||||
- "U-Boot - Boot Menu", NULL);
|
||||
+ "**** The selected menu item will autoboot in a few seconds unless interrupted! ****", NULL);
|
||||
ret |= scene_menu_set_title(scn, OBJ_MENU, OBJ_PROMPT);
|
||||
|
||||
logo = video_get_u_boot_logo();
|
||||
@@ -185,6 +185,8 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
|
||||
uint sel_id;
|
||||
bool done;
|
||||
int ret;
|
||||
+ int bootflow_delay=8000;
|
||||
+ bool bootflow_countdown=true;
|
||||
|
||||
cli_ch_init(cch);
|
||||
|
||||
@@ -231,6 +233,12 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
|
||||
schedule();
|
||||
mdelay(2);
|
||||
ichar = cli_ch_process(cch, -ETIMEDOUT);
|
||||
+ if (bootflow_countdown == true) {
|
||||
+ bootflow_delay -= 2;
|
||||
+ if (bootflow_delay <= 0) {
|
||||
+ ichar='\n';
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
if (!ichar) {
|
||||
ichar = getchar();
|
||||
@@ -265,6 +273,7 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
|
||||
break;
|
||||
}
|
||||
}
|
||||
+ bootflow_countdown = false;
|
||||
} while (!done);
|
||||
|
||||
if (ret)
|
||||
--
|
||||
2.39.5
|
||||
|
|
@ -0,0 +1,302 @@
|
|||
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
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
From 1b1673e76dae73885089415132284e9a14ecd4ac Mon Sep 17 00:00:00 2001
|
||||
From: Leah Rowe <info@minifree.org>
|
||||
Date: Tue, 3 Dec 2024 20:31:32 +0000
|
||||
Subject: [PATCH 1/1] Add an 8sec autoboot timeout on the bootflow menu
|
||||
|
||||
Otherwise, you have to press enter to load from a boot option,
|
||||
which is unacceptable on headless setups.
|
||||
|
||||
If you press the arrow keys to interrupt it, the timer will stop
|
||||
and you must then press enter to boot an option.
|
||||
|
||||
Otherwise, if you just leave U-Boot to do its thing, it will
|
||||
automatically boot what was selected, e.g. installed OS.
|
||||
|
||||
Signed-off-by: Leah Rowe <info@minifree.org>
|
||||
---
|
||||
boot/bootflow_menu.c | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
|
||||
index 9d0dc352f9..c788b86cdc 100644
|
||||
--- a/boot/bootflow_menu.c
|
||||
+++ b/boot/bootflow_menu.c
|
||||
@@ -59,7 +59,7 @@ int bootflow_menu_new(struct expo **expp)
|
||||
ret = scene_menu(scn, "main", OBJ_MENU, &menu);
|
||||
ret |= scene_obj_set_pos(scn, OBJ_MENU, MARGIN_LEFT, 100);
|
||||
ret |= scene_txt_str(scn, "title", OBJ_MENU_TITLE, STR_MENU_TITLE,
|
||||
- "U-Boot - Boot Menu", NULL);
|
||||
+ "**** The selected menu item will autoboot in a few seconds unless interrupted! ****", NULL);
|
||||
ret |= scene_menu_set_title(scn, OBJ_MENU, OBJ_PROMPT);
|
||||
|
||||
logo = video_get_u_boot_logo();
|
||||
@@ -185,6 +185,8 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
|
||||
uint sel_id;
|
||||
bool done;
|
||||
int ret;
|
||||
+ int bootflow_delay=8000;
|
||||
+ bool bootflow_countdown=true;
|
||||
|
||||
cli_ch_init(cch);
|
||||
|
||||
@@ -231,6 +233,12 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
|
||||
schedule();
|
||||
mdelay(2);
|
||||
ichar = cli_ch_process(cch, -ETIMEDOUT);
|
||||
+ if (bootflow_countdown == true) {
|
||||
+ bootflow_delay -= 2;
|
||||
+ if (bootflow_delay <= 0) {
|
||||
+ ichar='\n';
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
if (!ichar) {
|
||||
ichar = getchar();
|
||||
@@ -265,6 +273,7 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
|
||||
break;
|
||||
}
|
||||
}
|
||||
+ bootflow_countdown = false;
|
||||
} while (!done);
|
||||
|
||||
if (ret)
|
||||
--
|
||||
2.39.5
|
||||
|
|
@ -0,0 +1,302 @@
|
|||
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
|
||||
|
Loading…
Reference in New Issue