[PATCH v2 3/3] test: bootdev: scan with a broken high-priority device

dmukhin at ford.com dmukhin at ford.com
Tue Jun 16 08:36:06 CEST 2026


From: Denis Mukhin <dmukhin at ford.com> 

Add bootdev_hunt_fallthrough() test to verify that 'bootflow scan -l'
falls back to a lower-priority bootdev when a higher-priority hunter
fails.

Introduce a simple 'sandbox-bootdev' device for the test. The new
bootdev can be configured to produce an error at the hunting stage.

Signed-off-by: Denis Mukhin <dmukhin at ford.com>
---
Changes since v1:
- new patch
---
 drivers/block/Makefile          |  2 +-
 drivers/block/host-uclass.c     | 18 ++++++++++
 drivers/block/sandbox-bootdev.c | 64 +++++++++++++++++++++++++++++++++
 include/sandbox_host.h          | 17 +++++++++
 test/boot/bootflow.c            | 51 ++++++++++++++++++++++++++
 5 files changed, 151 insertions(+), 1 deletion(-)
 create mode 100644 drivers/block/sandbox-bootdev.c

diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index f5a9d8637a3c..c827fa81a2d8 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -13,7 +13,7 @@ ifndef CONFIG_XPL_BUILD
 obj-$(CONFIG_IDE) += ide.o
 obj-$(CONFIG_RKMTD) += rkmtd.o
 endif
-obj-$(CONFIG_SANDBOX) += sandbox.o host-uclass.o host_dev.o
+obj-$(CONFIG_SANDBOX) += sandbox.o sandbox-bootdev.o host-uclass.o host_dev.o
 obj-$(CONFIG_$(PHASE_)BLOCK_CACHE) += blkcache.o
 obj-$(CONFIG_$(PHASE_)BLKMAP) += blkmap.o
 obj-$(CONFIG_$(PHASE_)BLKMAP) += blkmap_helper.o
diff --git a/drivers/block/host-uclass.c b/drivers/block/host-uclass.c
index cf42bd1e07ac..47d1ac6773b4 100644
--- a/drivers/block/host-uclass.c
+++ b/drivers/block/host-uclass.c
@@ -27,6 +27,7 @@ DECLARE_GLOBAL_DATA_PTR;
  */
 struct host_priv {
 	struct udevice *cur_dev;
+	unsigned int flags;
 };
 
 int host_create_device(const char *label, bool removable, unsigned long blksz,
@@ -150,6 +151,23 @@ struct udevice *host_find_by_label(const char *label)
 	return NULL;
 }
 
+int host_set_flags_by_label(const char *label, unsigned int flags)
+{
+	struct udevice *dev;
+	struct uclass *uc;
+
+	uclass_id_foreach_dev(UCLASS_HOST, dev, uc) {
+		struct host_sb_plat *plat = dev_get_plat(dev);
+
+		if (plat->label && !strcmp(label, plat->label)) {
+			plat->flags = flags;
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
 struct udevice *host_get_cur_dev(void)
 {
 	struct uclass *uc = uclass_find(UCLASS_HOST);
diff --git a/drivers/block/sandbox-bootdev.c b/drivers/block/sandbox-bootdev.c
new file mode 100644
index 000000000000..61384834e879
--- /dev/null
+++ b/drivers/block/sandbox-bootdev.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#define LOG_CATEGORY	UCLASS_HOST
+
+#include <bootdev.h>
+#include <dm.h>
+#include <log.h>
+#include <sandbox_host.h>
+
+static int sandbox_bootdev_bind(struct udevice *dev)
+{
+	struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+	ucp->prio = BOOTDEVP_4_SCAN_FAST; /* at least priority 4 */
+
+	return 0;
+}
+
+static int sandbox_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+	struct udevice *dev;
+	struct uclass *uc;
+	int ret;
+
+	uclass_id_foreach_dev(UCLASS_HOST, dev, uc) {
+		struct host_sb_plat *plat = dev_get_plat(dev);
+
+		pr_debug("hunting %s\n", plat->label);
+
+		if (plat->flags & BLK_HOST_BROKEN) {
+			ret = -ETIME;
+			pr_err("cannot hunt sandbox device '%s': %d\n",
+			       plat->label, ret);
+			return ret;
+		}
+
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
+struct bootdev_ops sandbox_bootdev_ops = {
+};
+
+static const struct udevice_id sandbox_bootdev_ids[] = {
+	{ .compatible = "u-boot,bootdev-sandbox" },
+	{ }
+};
+
+U_BOOT_DRIVER(sandbox_bootdev) = {
+	.name		= "sandbox_bootdev",
+	.id		= UCLASS_BOOTDEV,
+	.ops		= &sandbox_bootdev_ops,
+	.bind		= sandbox_bootdev_bind,
+	.of_match	= sandbox_bootdev_ids,
+};
+
+BOOTDEV_HUNTER(sandbox_bootdev_hunter) = {
+	.prio		= BOOTDEVP_4_SCAN_FAST,
+	.uclass		= UCLASS_HOST,
+	.hunt		= sandbox_bootdev_hunt,
+	.drv		= DM_DRIVER_REF(sandbox_bootdev),
+};
diff --git a/include/sandbox_host.h b/include/sandbox_host.h
index f7a5fc672300..b1417903aa41 100644
--- a/include/sandbox_host.h
+++ b/include/sandbox_host.h
@@ -8,6 +8,13 @@
 #ifndef __SANDBOX_HOST__
 #define __SANDBOX_HOST__
 
+/**
+ * Device flags.
+ */
+enum {
+	BLK_HOST_BROKEN			= BIT(0), /* Simulate broken device */
+};
+
 /**
  * struct host_sb_plat - platform data for a host device
  *
@@ -19,6 +26,7 @@ struct host_sb_plat {
 	char *label;
 	char *filename;
 	int fd;
+	unsigned int flags;
 };
 
 /**
@@ -122,4 +130,13 @@ struct udevice *host_get_cur_dev(void);
  */
 void host_set_cur_dev(struct udevice *dev);
 
+/**
+ * host_set_flags_by_label() - Set the host device test flags
+ *
+ * @label: Label of the attachment, e.g. "test1"
+ * @flags: Device flags
+ * Returns: 0 if OK, -ve on error
+ */
+int host_set_flags_by_label(const char *label, unsigned int flags);
+
 #endif /* __SANDBOX_HOST__ */
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 56ee1952357b..65ad72e0d6bf 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -19,6 +19,8 @@
 #include <mapmem.h>
 #ifdef CONFIG_SANDBOX
 #include <asm/test.h>
+#include <sandbox_host.h>
+#include <os.h>
 #endif
 #include <dm/device-internal.h>
 #include <dm/lists.h>
@@ -1532,3 +1534,52 @@ static int bootstd_images(struct unit_test_state *uts)
 	return 0;
 }
 BOOTSTD_TEST(bootstd_images, UTF_CONSOLE);
+
+#ifdef CONFIG_SANDBOX
+/*
+ * Check that bootdev scanning does not stop if higher-priority bootdevs
+ * are failed to be hunted.
+ */
+static int bootdev_hunt_fallthrough(struct unit_test_state *uts)
+{
+	struct bootstd_priv *std;
+	struct udevice *dev;
+	const char **old_order;
+
+	test_set_skip_delays(true);
+	bootstd_reset_usb();
+	console_record_reset_enable();
+
+	/* Reset bootstd state */
+	ut_assertok(bootstd_get_priv(&std));
+	old_order = std->bootdev_order;
+	std->bootdev_order = NULL;
+	std->hunters_used = 0;
+
+	/*
+	 * Create a sandbox block device (BOOTDEVP_4_SCAN_FAST) and mark it as
+	 * broken so that bootdev_hunt_prio() returns an error.
+	 */
+	ut_asserteq(0, uclass_id_count(UCLASS_HOST));
+	ut_assertok(host_create_device("test", true, DEFAULT_BLKSZ, &dev));
+	ut_assertok(host_set_flags_by_label("test", BLK_HOST_BROKEN));
+	ut_asserteq(1, uclass_id_count(UCLASS_HOST));
+
+	/*
+	 * Scan with hunting.
+	 * The sandbox hunter at priority 4 must fail, but the USB hunter at
+	 * priority 5 must still be reached.
+	 */
+	ut_assertok(run_command("bootflow scan -l", 0));
+
+	/* USB was hunted despite the sandbox hunter failure */
+	ut_assert_skip_to_line("Bus usb at 1: 5 USB Device(s) found");
+
+	/* Clean up */
+	std->bootdev_order = old_order;
+
+	return 0;
+}
+BOOTSTD_TEST(bootdev_hunt_fallthrough,
+             UTF_DM | UTF_SCAN_FDT | UTF_SF_BOOTDEV | UTF_CONSOLE);
+#endif /* CONFIG_SANDBOX */
-- 
2.54.0



More information about the U-Boot mailing list