[PATCH 62/71] bootstd: Allow iterating to the next bootdev priortiy

Simon Glass sjg at chromium.org
Wed Dec 7 09:51:28 CET 2022


Add a function which moves to the next priority to be processed.

This works by storing the current priority in the bootflow iterator. The
logic to set this up is included in a subsequent commit.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 boot/bootdev-uclass.c | 64 +++++++++++++++++++++++++++++++++
 include/bootdev.h     | 14 ++++++++
 include/bootflow.h    |  3 ++
 test/boot/bootdev.c   | 84 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 165 insertions(+)

diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index ae08430ca8c..63005140061 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -585,6 +585,70 @@ int bootdev_next_label(struct bootflow_iter *iter, struct udevice **devp,
 	return 0;
 }
 
+int bootdev_next_prio(struct bootflow_iter *iter, struct udevice **devp)
+{
+	struct udevice *dev = *devp;
+	bool found;
+	int ret;
+
+	/* find the next device with this priority */
+	*devp = NULL;
+	log_debug("next prio %d: dev=%p/%s\n", iter->cur_prio, dev,
+		  dev ? dev->name : "none");
+	do {
+		/*
+		 * Don't probe devices here since they may not be of the
+		 * required priority
+		 */
+		if (!dev)
+			uclass_find_first_device(UCLASS_BOOTDEV, &dev);
+		else
+			uclass_find_next_device(&dev);
+		found = false;
+
+		/* scan for the next device with the correct priority */
+		while (dev) {
+			struct bootdev_uc_plat *plat;
+
+			plat = dev_get_uclass_plat(dev);
+			log_debug("- %s: %d, want %d\n", dev->name, plat->prio,
+				  iter->cur_prio);
+			if (plat->prio == iter->cur_prio)
+				break;
+			uclass_find_next_device(&dev);
+		}
+
+		/* none found for this priority, so move to the next */
+		if (!dev) {
+			log_debug("None found at prio %d, moving to %d\n",
+				  iter->cur_prio, iter->cur_prio + 1);
+			if (++iter->cur_prio == BOOTDEVP_COUNT)
+				return log_msg_ret("fin", -ENODEV);
+
+			if (iter->flags & BOOTFLOWF_HUNT) {
+				/* hunt to find new bootdevs */
+				ret = bootdev_hunt_prio(iter->cur_prio,
+							iter->flags &
+							BOOTFLOWF_SHOW);
+				log_debug("- hunt ret %d\n", ret);
+				if (ret)
+					return log_msg_ret("hun", ret);
+			}
+		} else {
+			ret = device_probe(dev);
+			if (ret) {
+				log_debug("Device '%s' failed to probe\n",
+					  dev->name);
+				dev = NULL;
+			}
+		}
+	} while (!dev);
+
+	*devp = dev;
+
+	return 0;
+}
+
 /**
  * h_cmp_bootdev() - Compare two bootdevs to find out which should go first
  *
diff --git a/include/bootdev.h b/include/bootdev.h
index 300bc736427..4b6a8eb8d8f 100644
--- a/include/bootdev.h
+++ b/include/bootdev.h
@@ -349,6 +349,20 @@ int bootdev_hunt_and_find_by_label(const char *label, struct udevice **devp,
 int bootdev_next_label(struct bootflow_iter *iter, struct udevice **devp,
 		       int *method_flagsp);
 
+/**
+ * bootdev_next_prio() - Find the next bootdev in priority order
+ *
+ * This moves @devp to the next bootdev with the current priority. If there is
+ * none, then it moves to the next priority and scans for new bootdevs there.
+ *
+ * @iter: Interation info, containing iter->cur_prio
+ * @devp: On entry this is the previous bootdev that was considered. On exit
+ *	this is the new bootdev, if any was found
+ * Returns 0 on success (*devp is updated), -ENODEV if there are no more
+ * bootdevs at any priority
+ */
+int bootdev_next_prio(struct bootflow_iter *iter, struct udevice **devp);
+
 #if CONFIG_IS_ENABLED(BOOTSTD)
 /**
  * bootdev_setup_for_dev() - Bind a new bootdev device (deprecated)
diff --git a/include/bootflow.h b/include/bootflow.h
index 5d845b3a6f0..953a9776a29 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -7,6 +7,7 @@
 #ifndef __bootflow_h
 #define __bootflow_h
 
+#include <bootdev.h>
 #include <linux/list.h>
 
 /**
@@ -169,6 +170,7 @@ enum bootflow_meth_flags_t {
  * @num_methods: Number of bootmeth devices in @method_order
  * @cur_method: Current method number, an index into @method_order
  * @first_glob_method: First global method, if any, else -1
+ * @cur_prio: Current priority being scanned
  * @method_order: List of bootmeth devices to use, in order. The normal methods
  *	appear first, then the global ones, if any
  * @doing_global: true if we are iterating through the global bootmeths (which
@@ -192,6 +194,7 @@ struct bootflow_iter {
 	int num_methods;
 	int cur_method;
 	int first_glob_method;
+	enum bootdev_prio_t cur_prio;
 	struct udevice **method_order;
 	bool doing_global;
 	int method_flags;
diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c
index 608aef15265..1090b92e510 100644
--- a/test/boot/bootdev.c
+++ b/test/boot/bootdev.c
@@ -588,3 +588,87 @@ static int bootdev_test_next_label(struct unit_test_state *uts)
 }
 BOOTSTD_TEST(bootdev_test_next_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
 	     UT_TESTF_ETH_BOOTDEV | UT_TESTF_SF_BOOTDEV);
+
+
+/* Check iterating to the next prioirty in a list */
+static int bootdev_test_next_prio(struct unit_test_state *uts)
+{
+	struct bootflow_iter iter;
+	struct bootstd_priv *std;
+	struct bootflow bflow;
+	struct udevice *dev;
+	int ret;
+
+	sandbox_set_eth_enable(false);
+	test_set_skip_delays(true);
+
+	/* get access to the used hunters */
+	ut_assertok(bootstd_get_priv(&std));
+
+	memset(&iter, '\0', sizeof(iter));
+	memset(&bflow, '\0', sizeof(bflow));
+	iter.part = 0;
+	uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
+	iter.cur_prio = 0;
+	iter.flags = BOOTFLOWF_SHOW;
+
+	dev = NULL;
+	console_record_reset_enable();
+	ut_assertok(bootdev_next_prio(&iter, &dev));
+	ut_assertnonnull(dev);
+	ut_asserteq_str("mmc2.bootdev", dev->name);
+
+	/* hunt flag not set, so this should not use any hunters */
+	ut_asserteq(0, std->hunters_used);
+	ut_assert_console_end();
+
+	/* now try again with hunting enabled */
+	iter.flags = BOOTFLOWF_SHOW | BOOTFLOWF_HUNT;
+	iter.cur_prio = 0;
+	iter.part = 0;
+
+	ut_assertok(bootdev_next_prio(&iter, &dev));
+	ut_asserteq_str("mmc2.bootdev", dev->name);
+	ut_assert_nextline("Hunting with: mmc");
+	ut_assert_console_end();
+
+	ut_assertok(bootstd_test_check_mmc_hunter(uts));
+
+	ut_assertok(bootdev_next_prio(&iter, &dev));
+	ut_asserteq_str("mmc1.bootdev", dev->name);
+
+	ut_assertok(bootdev_next_prio(&iter, &dev));
+	ut_asserteq_str("mmc0.bootdev", dev->name);
+	ut_assert_console_end();
+
+	ut_assertok(bootdev_next_prio(&iter, &dev));
+	ut_asserteq_str("spi.bin at 0.bootdev", dev->name);
+	ut_assert_skip_to_line("Hunting with: spi_flash");
+
+	/*
+	 * this scans all bootdevs of priority BOOTDEVP_4_SCAN_FAST before it
+	 * starts looking at the devices, so we se virtio as well
+	 */
+	ut_assert_nextline("Hunting with: virtio");
+	ut_assert_nextlinen("SF: Detected m25p16");
+
+	ut_assertok(bootdev_next_prio(&iter, &dev));
+	ut_asserteq_str("spi.bin at 1.bootdev", dev->name);
+	ut_assert_nextlinen("SF: Detected m25p16");
+	ut_assert_console_end();
+
+	/* keep going until there are no more bootdevs */
+	do {
+		ret = bootdev_next_prio(&iter, &dev);
+	} while (!ret);
+	ut_asserteq(-ENODEV, ret);
+	ut_assertnull(dev);
+	ut_asserteq(GENMASK(7, 0), std->hunters_used);
+
+	ut_assert_skip_to_line("Hunting with: ethernet");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootdev_test_next_prio, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
+	     UT_TESTF_SF_BOOTDEV);
-- 
2.39.0.rc0.267.gcb52ba06e7-goog



More information about the U-Boot mailing list