]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
bootstd: Add a menu option to bootflow scan
authorSimon Glass <sjg@chromium.org>
Mon, 2 Oct 2023 01:15:25 +0000 (19:15 -0600)
committerTom Rini <trini@konsulko.com>
Wed, 13 Dec 2023 23:39:05 +0000 (18:39 -0500)
Allow showing a menu and automatically booting, with 'bootflow scan'.
This is more convenient than using a script.

Signed-off-by: Simon Glass <sjg@chromium.org>
cmd/bootflow.c
doc/usage/cmd/bootflow.rst
test/boot/bootflow.c

index 3aeb40d690f4d4902b19bc844d8c60e9302bdf73..4a47265ebd5d25108d53ac0a20b681118ecd26e0 100644 (file)
@@ -135,7 +135,7 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
        struct udevice *dev = NULL;
        struct bootflow bflow;
        bool all = false, boot = false, errors = false, no_global = false;
-       bool list = false, no_hunter = false;
+       bool list = false, no_hunter = false, menu = false, text_mode = false;
        int num_valid = 0;
        const char *label = NULL;
        bool has_args;
@@ -155,6 +155,8 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
                        no_global = strchr(argv[1], 'G');
                        list = strchr(argv[1], 'l');
                        no_hunter = strchr(argv[1], 'H');
+                       menu = strchr(argv[1], 'm');
+                       text_mode = strchr(argv[1], 't');
                        argc--;
                        argv++;
                }
@@ -213,15 +215,32 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
                }
                if (list)
                        show_bootflow(i, &bflow, errors);
-               if (boot && !bflow.err)
+               if (!menu && boot && !bflow.err)
                        bootflow_run_boot(&iter, &bflow);
        }
        bootflow_iter_uninit(&iter);
        if (list)
                show_footer(i, num_valid);
 
-       if (IS_ENABLED(CONFIG_CMD_BOOTFLOW_FULL) && !num_valid && !list)
-               printf("No bootflows found; try again with -l\n");
+       if (IS_ENABLED(CONFIG_CMD_BOOTFLOW_FULL) && IS_ENABLED(CONFIG_EXPO)) {
+               if (!num_valid && !list) {
+                       printf("No bootflows found; try again with -l\n");
+               } else if (menu) {
+                       struct bootflow *sel_bflow;
+
+                       ret = bootflow_handle_menu(std, text_mode, &sel_bflow);
+                       if (!ret && boot) {
+                               ret = console_clear();
+                               if (ret) {
+                                       log_err("Failed to clear console: %dE\n",
+                                               ret);
+                                       return ret;
+                               }
+
+                               bootflow_run_boot(NULL, sel_bflow);
+                       }
+               }
+       }
 
        return 0;
 }
index 2198ff60493e8c09571cc0aa091d156baa1a22af..27e1330ad8a70f4a8f473ac55b821b26ae20cb9a 100644 (file)
@@ -52,6 +52,8 @@ Flags are:
     matters, since by then the system boots in the OS and U-Boot is no-longer
     running. `bootflow scan -b` is a quick way to boot the first available OS.
     A valid bootflow is one that made it all the way to the `loaded` state.
+    Note that if `-m` is provided as well, booting is delayed until the user
+    selects a bootflow.
 
 -e
     Used with -l to also show errors for each bootflow. The shows detailed error
@@ -71,6 +73,9 @@ Flags are:
     priority or label is tried, to see if more bootdevs can be discovered, but
     this flag disables that process.
 
+-m
+    Show a menu of available bootflows for the user to select. When used with
+    -b it then boots the one that was selected, if any.
 
 The optional argument specifies a particular bootdev to scan. This can either be
 the name of a bootdev or its sequence number (both shown with `bootdev list`).
index b97c566f000b9c0fa66257d2d2aa0c96021a4cea..597f624d0369bcd0b82a3ea493fe22c260c6a50b 100644 (file)
@@ -637,6 +637,88 @@ static int bootflow_cmd_menu(struct unit_test_state *uts)
 }
 BOOTSTD_TEST(bootflow_cmd_menu, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
 
+/* Check 'bootflow scan -m' to select a bootflow using a menu */
+static int bootflow_scan_menu(struct unit_test_state *uts)
+{
+       struct bootstd_priv *std;
+       const char **old_order, **new_order;
+       char prev[3];
+
+       /* get access to the current bootflow */
+       ut_assertok(bootstd_get_priv(&std));
+
+       ut_assertok(prep_mmc_bootdev(uts, "mmc4", false, &old_order));
+
+       /* Add keypresses to move to and select the second one in the list */
+       prev[0] = CTL_CH('n');
+       prev[1] = '\r';
+       prev[2] = '\0';
+       ut_asserteq(2, console_in_puts(prev));
+
+       ut_assertok(run_command("bootflow scan -lm", 0));
+       new_order = std->bootdev_order;
+       std->bootdev_order = old_order;
+
+       ut_assert_skip_to_line("No more bootdevs");
+       ut_assert_nextlinen("--");
+       ut_assert_nextline("(2 bootflows, 2 valid)");
+
+       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));
+
+       std->bootdev_order = new_order; /* Blue Monday */
+       ut_assertok(run_command("bootflow scan -lm", 0));
+       std->bootdev_order = old_order;
+
+       ut_assertnull(std->cur_bootflow);
+       ut_assert_skip_to_line("(2 bootflows, 2 valid)");
+       ut_assert_nextline("Nothing chosen");
+       ut_assert_console_end();
+
+       return 0;
+}
+BOOTSTD_TEST(bootflow_scan_menu,
+            UT_TESTF_DM | UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+/* Check 'bootflow scan -mb' to select and boot a bootflow using a menu */
+static int bootflow_scan_menu_boot(struct unit_test_state *uts)
+{
+       struct bootstd_priv *std;
+       const char **old_order;
+       char prev[3];
+
+       /* get access to the current bootflow */
+       ut_assertok(bootstd_get_priv(&std));
+
+       ut_assertok(prep_mmc_bootdev(uts, "mmc4", false, &old_order));
+
+       /* Add keypresses to move to and select the second one in the list */
+       prev[0] = CTL_CH('n');
+       prev[1] = '\r';
+       prev[2] = '\0';
+       ut_asserteq(2, console_in_puts(prev));
+
+       ut_assertok(run_command("bootflow scan -lmb", 0));
+       std->bootdev_order = old_order;
+
+       ut_assert_skip_to_line("(2 bootflows, 2 valid)");
+
+       ut_assert_nextline("Selected: Armbian");
+       ut_assert_skip_to_line("Boot failed (err=-14)");
+       ut_assertnonnull(std->cur_bootflow);
+       ut_assert_console_end();
+
+       return 0;
+}
+BOOTSTD_TEST(bootflow_scan_menu_boot,
+            UT_TESTF_DM | UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
 /* Check searching for a single bootdev using the hunters */
 static int bootflow_cmd_hunt_single(struct unit_test_state *uts)
 {