bootstd: Add a return code to bootflow menu

Return an error when the user does not select an OS, so we know whether
to boot or not.

Move calling of bootflow_menu_run() into a separate function so we can
call it from other places.

Expand the test to cover these cases.

Add some documentation also, while we are here.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2023-10-01 19:14:38 -06:00
parent baea7ec6a6
commit 3fa53b9531
3 changed files with 123 additions and 12 deletions

View file

@ -89,6 +89,44 @@ static void show_footer(int count, int num_valid)
num_valid); num_valid);
} }
/**
* bootflow_handle_menu() - Handle running the menu and updating cur bootflow
*
* This shows the menu, allows the user to select something and then prints
* what happened
*
* @std: bootstd information
* @text_mode: true to run the menu in text mode
* @bflowp: Returns selected bootflow, on success
* Return: 0 on success (a bootflow was selected), -EAGAIN if nothing was
* chosen, other -ve value on other error
*/
__maybe_unused static int bootflow_handle_menu(struct bootstd_priv *std,
bool text_mode,
struct bootflow **bflowp)
{
struct bootflow *bflow;
int ret;
ret = bootflow_menu_run(std, text_mode, &bflow);
if (ret) {
if (ret == -EAGAIN) {
printf("Nothing chosen\n");
std->cur_bootflow = NULL;
} else {
printf("Menu failed (err=%d)\n", ret);
}
return ret;
}
printf("Selected: %s\n", bflow->os_name ? bflow->os_name : bflow->name);
std->cur_bootflow = bflow;
*bflowp = bflow;
return 0;
}
static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]) char *const argv[])
{ {
@ -455,18 +493,9 @@ static int do_bootflow_menu(struct cmd_tbl *cmdtp, int flag, int argc,
if (ret) if (ret)
return CMD_RET_FAILURE; return CMD_RET_FAILURE;
ret = bootflow_menu_run(std, text_mode, &bflow); ret = bootflow_handle_menu(std, text_mode, &bflow);
if (ret) { if (ret)
if (ret == -EAGAIN) return CMD_RET_FAILURE;
printf("Nothing chosen\n");
else {
printf("Menu failed (err=%d)\n", ret);
return CMD_RET_FAILURE;
}
}
printf("Selected: %s\n", bflow->os_name ? bflow->os_name : bflow->name);
std->cur_bootflow = bflow;
return 0; return 0;
} }

View file

@ -15,6 +15,7 @@ Synopis
bootflow read bootflow read
bootflow boot bootflow boot
bootflow cmdline [set|get|clear|delete|auto] <param> [<value>] bootflow cmdline [set|get|clear|delete|auto] <param> [<value>]
bootfloe menu [-t]
Description Description
----------- -----------
@ -24,6 +25,9 @@ locate bootflows, list them and boot them.
See :doc:`../../develop/bootstd` for more information. See :doc:`../../develop/bootstd` for more information.
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.
bootflow scan bootflow scan
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
@ -247,6 +251,16 @@ can be used to set the early console (or console) to a suitable value so that
output appears on the serial port. This is only supported by the 16550 serial output appears on the serial port. This is only supported by the 16550 serial
driver so far. driver so far.
bootflow menu
~~~~~~~~~~~~~
This shows a menu with available bootflows. The user can select a particular
bootflow, which then becomes the current one.
The `-t` flag requests a text menu. Otherwise, if a display is available, a
graphical menu is shown.
Example Example
------- -------
@ -658,6 +672,56 @@ Now the buffer can be accessed::
77b7e4e0: 320fc000 08e8ba0f c031300f b8d0000f ...2.....01..... 77b7e4e0: 320fc000 08e8ba0f c031300f b8d0000f ...2.....01.....
77b7e4f0: 00000020 6ad8000f 00858d10 50000002 ......j.......P 77b7e4f0: 00000020 6ad8000f 00858d10 50000002 ......j.......P
This shows using a text menu to boot an OS::
=> bootflow scan
=> bootfl list
=> bootfl menu -t
U-Boot : Boot Menu
UP and DOWN to choose, ENTER to select
> 0 mmc1 mmc1.bootdev.whole
1 mmc1 Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
2 mmc1 mmc1.bootdev.part_1
3 mmc4 mmc4.bootdev.whole
4 mmc4 Armbian
5 mmc4 mmc4.bootdev.part_1
6 mmc5 mmc5.bootdev.whole
7 mmc5 ChromeOS
8 mmc5 ChromeOS
U-Boot : Boot Menu
UP and DOWN to choose, ENTER to select
0 mmc1 mmc1.bootdev.whole
> 1 mmc1 Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
2 mmc1 mmc1.bootdev.part_1
3 mmc4 mmc4.bootdev.whole
4 mmc4 Armbian
5 mmc4 mmc4.bootdev.part_1
6 mmc5 mmc5.bootdev.whole
7 mmc5 ChromeOS
8 mmc5 ChromeOS
U-Boot : Boot Menu
Selected: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
=> bootfl boot
** Booting bootflow 'mmc1.bootdev.part_1' with extlinux
Ignoring unknown command: ui
Ignoring malformed menu command: autoboot
Ignoring malformed menu command: hidden
Ignoring unknown command: totaltimeout
Fedora-Workstation-armhfp-31-1.9 Boot Options.
1: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
Enter choice: 1
1: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
Retrieving file: /vmlinuz-5.3.7-301.fc31.armv7hl
Retrieving file: /initramfs-5.3.7-301.fc31.armv7hl.img
append: ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB
Retrieving file: /dtb-5.3.7-301.fc31.armv7hl/sandbox.dtb
...
Return value Return value
------------ ------------
@ -667,6 +731,9 @@ return to U-Boot. If something about the U-Boot processing fails, then the
return value $? is 1. If the boot succeeds but for some reason the Operating return value $? is 1. If the boot succeeds but for some reason the Operating
System returns, then $? is 0, indicating success. System returns, then $? is 0, indicating success.
For `bootflow menu` the return value is $? is 0 (true) if an option was choses,
else 1.
For other subcommands, the return value $? is always 0 (true). For other subcommands, the return value $? is always 0 (true).

View file

@ -604,8 +604,12 @@ static int scan_mmc4_bootdev(struct unit_test_state *uts)
/* Check 'bootflow menu' to select a bootflow */ /* Check 'bootflow menu' to select a bootflow */
static int bootflow_cmd_menu(struct unit_test_state *uts) static int bootflow_cmd_menu(struct unit_test_state *uts)
{ {
struct bootstd_priv *std;
char prev[3]; char prev[3];
/* get access to the current bootflow */
ut_assertok(bootstd_get_priv(&std));
ut_assertok(scan_mmc4_bootdev(uts)); ut_assertok(scan_mmc4_bootdev(uts));
/* Add keypresses to move to and select the second one in the list */ /* Add keypresses to move to and select the second one in the list */
@ -616,6 +620,17 @@ static int bootflow_cmd_menu(struct unit_test_state *uts)
ut_assertok(run_command("bootflow menu", 0)); ut_assertok(run_command("bootflow menu", 0));
ut_assert_nextline("Selected: Armbian"); ut_assert_nextline("Selected: Armbian");
ut_assertnonnull(std->cur_bootflow);
ut_assert_console_end();
/* Check not selecting anything */
prev[0] = '\e';
prev[1] = '\0';
ut_asserteq(1, console_in_puts(prev));
ut_asserteq(1, run_command("bootflow menu", 0));
ut_assertnull(std->cur_bootflow);
ut_assert_nextline("Nothing chosen");
ut_assert_console_end(); ut_assert_console_end();
return 0; return 0;