From: Denis Mukhin <[email protected]> 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 <[email protected]> --- 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@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

