bootstd: Support running bootdev hunters
authorSimon Glass <sjg@chromium.org>
Tue, 17 Jan 2023 17:47:34 +0000 (10:47 -0700)
committerTom Rini <trini@konsulko.com>
Mon, 23 Jan 2023 23:11:40 +0000 (18:11 -0500)
Add a way to run a bootdev hunter to find bootdevs of a certain type. Add
this to the 'bootdev hunt' command. Test for this are added in a later
patch, since a useful test needs some hunters to work with.

Signed-off-by: Simon Glass <sjg@chromium.org>
boot/bootdev-uclass.c
cmd/bootdev.c
include/bootdev.h
test/boot/bootdev.c

index 62eb0b6..081b94c 100644 (file)
@@ -636,6 +636,67 @@ int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp)
        return 0;
 }
 
+static int bootdev_hunt_drv(struct bootdev_hunter *info, uint seq, bool show)
+{
+       const char *name = uclass_get_name(info->uclass);
+       struct bootstd_priv *std;
+       int ret;
+
+       ret = bootstd_get_priv(&std);
+       if (ret)
+               return log_msg_ret("std", ret);
+
+       if (!(std->hunters_used & BIT(seq))) {
+               if (show)
+                       printf("Hunting with: %s\n",
+                              uclass_get_name(info->uclass));
+               log_debug("Hunting with: %s\n", name);
+               if (info->hunt) {
+                       ret = info->hunt(info, show);
+                       if (ret)
+                               return ret;
+               }
+               std->hunters_used |= BIT(seq);
+       }
+
+       return 0;
+}
+
+int bootdev_hunt(const char *spec, bool show)
+{
+       struct bootdev_hunter *start;
+       const char *end;
+       int n_ent, i;
+       int result;
+       size_t len;
+
+       start = ll_entry_start(struct bootdev_hunter, bootdev_hunter);
+       n_ent = ll_entry_count(struct bootdev_hunter, bootdev_hunter);
+       result = 0;
+
+       len = SIZE_MAX;
+       if (spec) {
+               trailing_strtoln_end(spec, NULL, &end);
+               len = end - spec;
+       }
+
+       for (i = 0; i < n_ent; i++) {
+               struct bootdev_hunter *info = start + i;
+               const char *name = uclass_get_name(info->uclass);
+               int ret;
+
+               log_debug("looking at %.*s for %s\n",
+                         (int)max(strlen(name), len), spec, name);
+               if (spec && strncmp(spec, name, max(strlen(name), len)))
+                       continue;
+               ret = bootdev_hunt_drv(info, i, show);
+               if (ret)
+                       result = ret;
+       }
+
+       return result;
+}
+
 void bootdev_list_hunters(struct bootstd_priv *std)
 {
        struct bootdev_hunter *orig, *start;
index 80bfe28..28866fa 100644 (file)
@@ -128,7 +128,12 @@ static int do_bootdev_hunt(struct cmd_tbl *cmdtp, int flag, int argc,
        if (list) {
                bootdev_list_hunters(priv);
        } else {
-               /* TODO: implement hunting */
+               ret = bootdev_hunt(spec, true);
+               if (ret) {
+                       printf("Failed (err=%dE)\n", ret);
+
+                       return CMD_RET_FAILURE;
+               }
        }
 
        return 0;
index cafb528..deef789 100644 (file)
@@ -263,6 +263,20 @@ int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp);
  */
 void bootdev_list_hunters(struct bootstd_priv *std);
 
+/**
+ * bootdev_hunt() - Hunt for bootdevs matching a particular spec
+ *
+ * This runs the selected hunter (or all if @spec is NULL) to try to find new
+ * bootdevs.
+ *
+ * @spec: Spec to match, e.g. "mmc0", or NULL for any. If provided, this must
+ * match a uclass name so that the hunter can be determined. Any trailing number
+ * is ignored
+ * @show: true to show each hunter before using it
+ * Returns: 0 if OK, -ve on error
+ */
+int bootdev_hunt(const char *spec, bool show);
+
 #if CONFIG_IS_ENABLED(BOOTSTD)
 /**
  * bootdev_setup_for_dev() - Bind a new bootdev device (deprecated)
index a8ca12a..45a00c3 100644 (file)
@@ -237,6 +237,9 @@ static int bootdev_test_hunter(struct unit_test_state *uts)
        ut_assert_nextline("(total hunters: 0)");
        ut_assert_console_end();
 
+       ut_assertok(bootdev_hunt("mmc1", false));
+       ut_assert_console_end();
+
        return 0;
 }
 BOOTSTD_TEST(bootdev_test_hunter, UT_TESTF_DM | UT_TESTF_SCAN_FDT);