summaryrefslogtreecommitdiff
path: root/test/boot/bootdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/boot/bootdev.c')
-rw-r--r--test/boot/bootdev.c563
1 files changed, 524 insertions, 39 deletions
diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c
index 1c2a79fb108..ef5215bbcec 100644
--- a/test/boot/bootdev.c
+++ b/test/boot/bootdev.c
@@ -102,22 +102,89 @@ BOOTSTD_TEST(bootdev_test_cmd_select, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
static int bootdev_test_labels(struct unit_test_state *uts)
{
struct udevice *dev, *media;
+ int mflags = 0;
- ut_assertok(bootdev_find_by_label("mmc2", &dev));
+ ut_assertok(bootdev_find_by_label("mmc2", &dev, &mflags));
ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev));
+ ut_asserteq(0, mflags);
media = dev_get_parent(dev);
ut_asserteq(UCLASS_MMC, device_get_uclass_id(media));
ut_asserteq_str("mmc2", media->name);
+ /* Check method flags */
+ ut_assertok(bootdev_find_by_label("pxe", &dev, &mflags));
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
+ mflags);
+ ut_assertok(bootdev_find_by_label("dhcp", &dev, &mflags));
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY,
+ mflags);
+
/* Check invalid uclass */
- ut_asserteq(-EINVAL, bootdev_find_by_label("fred0", &dev));
+ ut_asserteq(-EINVAL, bootdev_find_by_label("fred0", &dev, &mflags));
/* Check unknown sequence number */
- ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev));
+ ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev, &mflags));
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
+ UT_TESTF_ETH_BOOTDEV);
+
+/* Check bootdev_find_by_any() */
+static int bootdev_test_any(struct unit_test_state *uts)
+{
+ struct udevice *dev, *media;
+ int mflags;
+
+ /*
+ * with ethernet enabled we have 8 devices ahead of the mmc ones:
+ *
+ * ut_assertok(run_command("bootdev list", 0));
+ * Seq Probed Status Uclass Name
+ * --- ------ ------ -------- ------------------
+ * 0 [ + ] OK ethernet eth@10002000.bootdev
+ * 1 [ ] OK ethernet eth@10003000.bootdev
+ * 2 [ ] OK ethernet sbe5.bootdev
+ * 3 [ ] OK ethernet eth@10004000.bootdev
+ * 4 [ ] OK ethernet phy-test-eth.bootdev
+ * 5 [ ] OK ethernet dsa-test-eth.bootdev
+ * 6 [ ] OK ethernet dsa-test@0.bootdev
+ * 7 [ ] OK ethernet dsa-test@1.bootdev
+ * 8 [ ] OK mmc mmc2.bootdev
+ * 9 [ + ] OK mmc mmc1.bootdev
+ * a [ ] OK mmc mmc0.bootdev
+ */
+ console_record_reset_enable();
+ ut_assertok(bootdev_find_by_any("8", &dev, &mflags));
+ ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev));
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_DEV, mflags);
+ media = dev_get_parent(dev);
+ ut_asserteq(UCLASS_MMC, device_get_uclass_id(media));
+ ut_asserteq_str("mmc2", media->name);
+ ut_assert_console_end();
+
+ /* there should not be this many bootdevs */
+ ut_asserteq(-ENODEV, bootdev_find_by_any("50", &dev, &mflags));
+ ut_assert_nextline("Cannot find '50' (err=-19)");
+ ut_assert_console_end();
+
+ /* Check method flags */
+ ut_assertok(bootdev_find_by_any("pxe", &dev, &mflags));
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
+ mflags);
+
+ /* Check invalid uclass */
+ mflags = 123;
+ ut_asserteq(-EINVAL, bootdev_find_by_any("fred0", &dev, &mflags));
+ ut_assert_nextline("Unknown uclass 'fred0' in label");
+ ut_assert_nextline("Cannot find bootdev 'fred0' (err=-22)");
+ ut_asserteq(123, mflags);
+ ut_assert_console_end();
return 0;
}
-BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+BOOTSTD_TEST(bootdev_test_any, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
+ UT_TESTF_ETH_BOOTDEV);
/* Check bootdev ordering with the bootdev-order property */
static int bootdev_test_order(struct unit_test_state *uts)
@@ -135,20 +202,31 @@ static int bootdev_test_order(struct unit_test_state *uts)
* mmc2 - nothing connected
*/
ut_assertok(env_set("boot_targets", NULL));
- ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
ut_asserteq(2, iter.num_devs);
- ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name);
- ut_asserteq_str("mmc1.bootdev", iter.dev_order[1]->name);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
+ ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
bootflow_iter_uninit(&iter);
/* Use the environment variable to override it */
ut_assertok(env_set("boot_targets", "mmc1 mmc2"));
- ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
+ ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
ut_asserteq(2, iter.num_devs);
- ut_asserteq_str("mmc1.bootdev", iter.dev_order[0]->name);
- ut_asserteq_str("mmc2.bootdev", iter.dev_order[1]->name);
+ ut_asserteq_str("mmc1.bootdev", iter.dev_used[0]->name);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name);
bootflow_iter_uninit(&iter);
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check default bootdev ordering */
+static int bootdev_test_order_default(struct unit_test_state *uts)
+{
+ struct bootflow_iter iter;
+ struct bootflow bflow;
+
/*
* Now drop both orderings, to check the default (prioriy/sequence)
* ordering
@@ -156,31 +234,19 @@ static int bootdev_test_order(struct unit_test_state *uts)
ut_assertok(env_set("boot_targets", NULL));
ut_assertok(bootstd_test_drop_bootdev_order(uts));
- ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
- ut_asserteq(3, iter.num_devs);
- ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name);
- ut_asserteq_str("mmc1.bootdev", iter.dev_order[1]->name);
- ut_asserteq_str("mmc0.bootdev", iter.dev_order[2]->name);
-
- /*
- * Check that adding aliases for the bootdevs works. We just fake it by
- * setting the sequence numbers directly.
- */
- iter.dev_order[0]->seq_ = 0;
- iter.dev_order[1]->seq_ = 3;
- iter.dev_order[2]->seq_ = 2;
- bootflow_iter_uninit(&iter);
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
+ ut_asserteq(2, iter.num_devs);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
+ ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
- ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+ ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
ut_asserteq(3, iter.num_devs);
- ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name);
- ut_asserteq_str("mmc0.bootdev", iter.dev_order[1]->name);
- ut_asserteq_str("mmc1.bootdev", iter.dev_order[2]->name);
+ ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
bootflow_iter_uninit(&iter);
return 0;
}
-BOOTSTD_TEST(bootdev_test_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+BOOTSTD_TEST(bootdev_test_order_default, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
/* Check bootdev ordering with the uclass priority */
static int bootdev_test_prio(struct unit_test_state *uts)
@@ -190,6 +256,11 @@ static int bootdev_test_prio(struct unit_test_state *uts)
struct bootflow bflow;
struct udevice *blk;
+ test_set_skip_delays(true);
+
+ /* disable ethernet since the hunter will run dhcp */
+ test_set_eth_enable(false);
+
/* Start up USB which gives us three additional bootdevs */
usb_started = false;
ut_assertok(run_command("usb start", 0));
@@ -198,26 +269,440 @@ static int bootdev_test_prio(struct unit_test_state *uts)
/* 3 MMC and 3 USB bootdevs: MMC should come before USB */
console_record_reset_enable();
- ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
+ ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
ut_asserteq(6, iter.num_devs);
- ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
ut_asserteq_str("usb_mass_storage.lun0.bootdev",
- iter.dev_order[3]->name);
+ iter.dev_used[3]->name);
- ut_assertok(bootdev_get_sibling_blk(iter.dev_order[3], &blk));
+ ut_assertok(bootdev_get_sibling_blk(iter.dev_used[3], &blk));
ut_asserteq_str("usb_mass_storage.lun0", blk->name);
/* adjust the priority of the first USB bootdev to the highest */
- ucp = dev_get_uclass_plat(iter.dev_order[3]);
- ucp->prio = 1;
+ ucp = dev_get_uclass_plat(iter.dev_used[3]);
+ ucp->prio = BOOTDEVP_1_PRE_SCAN;
+ /* try again but enable hunting, which brings in SCSI */
bootflow_iter_uninit(&iter);
- ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
- ut_asserteq(6, iter.num_devs);
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, BOOTFLOWF_HUNT,
+ &bflow));
+ ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
+ ut_asserteq(7, iter.num_devs);
ut_asserteq_str("usb_mass_storage.lun0.bootdev",
- iter.dev_order[0]->name);
- ut_asserteq_str("mmc2.bootdev", iter.dev_order[1]->name);
+ iter.dev_used[0]->name);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name);
return 0;
}
BOOTSTD_TEST(bootdev_test_prio, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check listing hunters */
+static int bootdev_test_hunter(struct unit_test_state *uts)
+{
+ struct bootstd_priv *std;
+
+ test_set_skip_delays(true);
+
+ /* get access to the used hunters */
+ ut_assertok(bootstd_get_priv(&std));
+
+ console_record_reset_enable();
+ bootdev_list_hunters(std);
+ ut_assert_nextline("Prio Used Uclass Hunter");
+ ut_assert_nextlinen("----");
+ ut_assert_nextline(" 6 ethernet eth_bootdev");
+ ut_assert_nextline(" 1 simple_bus (none)");
+ ut_assert_nextline(" 5 ide ide_bootdev");
+ ut_assert_nextline(" 2 mmc mmc_bootdev");
+ ut_assert_nextline(" 4 nvme nvme_bootdev");
+ ut_assert_nextline(" 4 scsi scsi_bootdev");
+ ut_assert_nextline(" 4 spi_flash sf_bootdev");
+ ut_assert_nextline(" 5 usb usb_bootdev");
+ ut_assert_nextline(" 4 virtio virtio_bootdev");
+ ut_assert_nextline("(total hunters: 9)");
+ ut_assert_console_end();
+
+ ut_assertok(bootdev_hunt("usb1", false));
+ ut_assert_nextline(
+ "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found");
+ ut_assert_console_end();
+
+ /* USB is sixth in the list, so bit 7 */
+ ut_asserteq(BIT(7), std->hunters_used);
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_hunter, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootdev hunt' command */
+static int bootdev_test_cmd_hunt(struct unit_test_state *uts)
+{
+ struct bootstd_priv *std;
+
+ test_set_skip_delays(true);
+
+ /* get access to the used hunters */
+ ut_assertok(bootstd_get_priv(&std));
+
+ console_record_reset_enable();
+ ut_assertok(run_command("bootdev hunt -l", 0));
+ ut_assert_nextline("Prio Used Uclass Hunter");
+ ut_assert_nextlinen("----");
+ ut_assert_nextline(" 6 ethernet eth_bootdev");
+ ut_assert_skip_to_line("(total hunters: 9)");
+ ut_assert_console_end();
+
+ /* Use the MMC hunter and see that it updates */
+ ut_assertok(run_command("bootdev hunt mmc", 0));
+ ut_assertok(run_command("bootdev hunt -l", 0));
+ ut_assert_skip_to_line(" 5 ide ide_bootdev");
+ ut_assert_nextline(" 2 * mmc mmc_bootdev");
+ ut_assert_skip_to_line("(total hunters: 9)");
+ ut_assert_console_end();
+
+ /* Scan all hunters */
+ test_set_eth_enable(false);
+ test_set_skip_delays(true);
+ ut_assertok(run_command("bootdev hunt", 0));
+ ut_assert_nextline("Hunting with: ethernet");
+
+ /* This is the extension feature which has no uclass at present */
+ ut_assert_nextline("Hunting with: simple_bus");
+ ut_assert_nextline("Found 2 extension board(s).");
+ ut_assert_nextline("Hunting with: ide");
+ ut_assert_nextline("Bus 0: not available ");
+
+ /* mmc hunter has already been used so should not run again */
+
+ ut_assert_nextline("Hunting with: nvme");
+ ut_assert_nextline("Hunting with: scsi");
+ ut_assert_nextline("scanning bus for devices...");
+ ut_assert_skip_to_line("Hunting with: spi_flash");
+ ut_assert_nextline("Hunting with: usb");
+ ut_assert_nextline(
+ "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found");
+ ut_assert_nextline("Hunting with: virtio");
+ ut_assert_console_end();
+
+ /* List available hunters */
+ ut_assertok(run_command("bootdev hunt -l", 0));
+ ut_assert_nextlinen("Prio");
+ ut_assert_nextlinen("----");
+ ut_assert_nextline(" 6 * ethernet eth_bootdev");
+ ut_assert_nextline(" 1 * simple_bus (none)");
+ ut_assert_nextline(" 5 * ide ide_bootdev");
+ ut_assert_nextline(" 2 * mmc mmc_bootdev");
+ ut_assert_nextline(" 4 * nvme nvme_bootdev");
+ ut_assert_nextline(" 4 * scsi scsi_bootdev");
+ ut_assert_nextline(" 4 * spi_flash sf_bootdev");
+ ut_assert_nextline(" 5 * usb usb_bootdev");
+ ut_assert_nextline(" 4 * virtio virtio_bootdev");
+ ut_assert_nextline("(total hunters: 9)");
+ ut_assert_console_end();
+
+ ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used);
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_cmd_hunt, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
+ UT_TESTF_ETH_BOOTDEV);
+
+/* Check searching for bootdevs using the hunters */
+static int bootdev_test_hunt_scan(struct unit_test_state *uts)
+{
+ struct bootflow_iter iter;
+ struct bootstd_priv *std;
+ struct bootflow bflow;
+
+ /* get access to the used hunters */
+ ut_assertok(bootstd_get_priv(&std));
+
+ ut_assertok(bootstd_test_drop_bootdev_order(uts));
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter,
+ BOOTFLOWF_SHOW | BOOTFLOWF_HUNT |
+ BOOTFLOWF_SKIP_GLOBAL, &bflow));
+ ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used);
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_hunt_scan, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check that only bootable partitions are processed */
+static int bootdev_test_bootable(struct unit_test_state *uts)
+{
+ struct bootflow_iter iter;
+ struct bootflow bflow;
+ struct udevice *blk;
+
+ memset(&iter, '\0', sizeof(iter));
+ memset(&bflow, '\0', sizeof(bflow));
+ iter.part = 0;
+ ut_assertok(uclass_get_device_by_name(UCLASS_BLK, "mmc1.blk", &blk));
+ iter.dev = blk;
+ ut_assertok(device_find_next_child(&iter.dev));
+ uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
+
+ /*
+ * initially we don't have any knowledge of which partitions are
+ * bootable, but mmc1 has two partitions, with the first one being
+ * bootable
+ */
+ iter.part = 2;
+ ut_asserteq(-EINVAL, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
+ ut_asserteq(0, iter.first_bootable);
+
+ /* scan with part == 0 to get the partition info */
+ iter.part = 0;
+ ut_asserteq(-ENOENT, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
+ ut_asserteq(1, iter.first_bootable);
+
+ /* now it will refuse to use non-bootable partitions */
+ iter.part = 2;
+ ut_asserteq(-EINVAL, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_bootable, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check hunting for bootdev of a particular priority */
+static int bootdev_test_hunt_prio(struct unit_test_state *uts)
+{
+ test_set_skip_delays(true);
+
+ console_record_reset_enable();
+ ut_assertok(bootdev_hunt_prio(BOOTDEVP_4_SCAN_FAST, false));
+ ut_assert_nextline("scanning bus for devices...");
+ ut_assert_skip_to_line(" Type: Hard Disk");
+ ut_assert_nextlinen(" Capacity:");
+ ut_assert_console_end();
+
+ /* now try a different priority, verbosely */
+ ut_assertok(bootdev_hunt_prio(BOOTDEVP_5_SCAN_SLOW, true));
+ ut_assert_nextline("Hunting with: ide");
+ ut_assert_nextline("Bus 0: not available ");
+ ut_assert_nextline("Hunting with: usb");
+ ut_assert_nextline(
+ "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found");
+ ut_assert_console_end();
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_hunt_prio, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check hunting for bootdevs with a particular label */
+static int bootdev_test_hunt_label(struct unit_test_state *uts)
+{
+ struct udevice *dev, *old;
+ struct bootstd_priv *std;
+ int mflags;
+
+ /* get access to the used hunters */
+ ut_assertok(bootstd_get_priv(&std));
+
+ /* scan an unknown uclass */
+ console_record_reset_enable();
+ old = (void *)&mflags; /* arbitrary pointer to check against dev */
+ dev = old;
+ mflags = 123;
+ ut_asserteq(-EINVAL,
+ bootdev_hunt_and_find_by_label("fred", &dev, &mflags));
+ ut_assert_nextline("Unknown uclass 'fred' in label");
+ ut_asserteq_ptr(old, dev);
+ ut_asserteq(123, mflags);
+ ut_assert_console_end();
+ ut_asserteq(0, std->hunters_used);
+
+ /* scan an invalid mmc controllers */
+ ut_asserteq(-ENOENT,
+ bootdev_hunt_and_find_by_label("mmc4", &dev, &mflags));
+ ut_asserteq_ptr(old, dev);
+ ut_asserteq(123, mflags);
+ ut_assert_nextline("Unknown seq 4 for label 'mmc4'");
+ ut_assert_console_end();
+
+ ut_assertok(bootstd_test_check_mmc_hunter(uts));
+
+ /* scan for a particular mmc controller */
+ ut_assertok(bootdev_hunt_and_find_by_label("mmc1", &dev, &mflags));
+ ut_assertnonnull(dev);
+ ut_asserteq_str("mmc1.bootdev", dev->name);
+ ut_asserteq(0, mflags);
+ ut_assert_console_end();
+
+ /* scan all of usb */
+ test_set_skip_delays(true);
+ ut_assertok(bootdev_hunt_and_find_by_label("usb", &dev, &mflags));
+ ut_assertnonnull(dev);
+ ut_asserteq_str("usb_mass_storage.lun0.bootdev", dev->name);
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags);
+ ut_assert_nextlinen("Bus usb@1: scanning bus usb@1");
+ ut_assert_console_end();
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_hunt_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check iterating to the next label in a list */
+static int bootdev_test_next_label(struct unit_test_state *uts)
+{
+ const char *const labels[] = {"mmc0", "scsi", "dhcp", "pxe", NULL};
+ struct bootflow_iter iter;
+ struct bootstd_priv *std;
+ struct bootflow bflow;
+ struct udevice *dev;
+ int mflags;
+
+ test_set_eth_enable(false);
+
+ /* 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_label = -1;
+ iter.labels = labels;
+
+ dev = NULL;
+ mflags = 123;
+ ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
+ console_record_reset_enable();
+ ut_assert_console_end();
+ ut_assertnonnull(dev);
+ ut_asserteq_str("mmc0.bootdev", dev->name);
+ ut_asserteq(0, mflags);
+
+ ut_assertok(bootstd_test_check_mmc_hunter(uts));
+
+ ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
+ ut_assert_nextline("scanning bus for devices...");
+ ut_assert_skip_to_line(
+ " Capacity: 1.9 MB = 0.0 GB (4095 x 512)");
+ ut_assert_console_end();
+ ut_assertnonnull(dev);
+ ut_asserteq_str("scsi.id0lun0.bootdev", dev->name);
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags);
+
+ /* SCSI is sixth in the list, so bit 5 */
+ ut_asserteq(BIT(MMC_HUNTER) | BIT(5), std->hunters_used);
+
+ ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
+ ut_assert_console_end();
+ ut_assertnonnull(dev);
+ ut_asserteq_str("eth@10002000.bootdev", dev->name);
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY,
+ mflags);
+
+ /* dhcp: Ethernet is first so bit 0 */
+ ut_asserteq(BIT(MMC_HUNTER) | BIT(5) | BIT(0), std->hunters_used);
+
+ ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
+ ut_assert_console_end();
+ ut_assertnonnull(dev);
+ ut_asserteq_str("eth@10002000.bootdev", dev->name);
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
+ mflags);
+
+ /* pxe: Ethernet is first so bit 0 */
+ ut_asserteq(BIT(MMC_HUNTER) | BIT(5) | BIT(0), std->hunters_used);
+
+ mflags = 123;
+ ut_asserteq(-ENODEV, bootdev_next_label(&iter, &dev, &mflags));
+ ut_asserteq(123, mflags);
+ ut_assert_console_end();
+
+ /* no change */
+ ut_asserteq(BIT(MMC_HUNTER) | BIT(5) | BIT(0), std->hunters_used);
+
+ return 0;
+}
+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;
+
+ test_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: simple_bus");
+ ut_assert_nextline("Found 2 extension board(s).");
+ ut_assert_nextline("Hunting with: mmc");
+ ut_assert_console_end();
+
+ ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used);
+
+ 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@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@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(MAX_HUNTER, 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);