bootstd: Record the bootdevs used during scanning
Add a way to record the bootdevs used when scanning for bootflows. This is
useful for testing.
Enable this only with BOOTSTD_FULL and do the same for the progress
reporting.
Re-enable and update the affected tests now that we have this feature.
For bootdev_test_order_default() there is no-longer any support for using
the bootdev aliases to specify an ordering, so drop that part of the test.
Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/boot/bootflow.c b/boot/bootflow.c
index 750732f..03a180b 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -88,6 +88,9 @@
memset(iter, '\0', sizeof(*iter));
iter->first_glob_method = -1;
iter->flags = flags;
+
+ /* remember the first bootdevs we see */
+ iter->max_devs = BOOTFLOW_MAX_USED_DEVS;
}
void bootflow_iter_uninit(struct bootflow_iter *iter)
@@ -131,16 +134,22 @@
iter->dev = dev;
iter->method_flags = method_flags;
- if ((iter->flags & (BOOTFLOWF_SHOW | BOOTFLOWF_SINGLE_DEV)) ==
- BOOTFLOWF_SHOW) {
- if (dev)
- printf("Scanning bootdev '%s':\n", dev->name);
- else if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) &&
- ucp->flags & BOOTMETHF_GLOBAL)
- printf("Scanning global bootmeth '%s':\n",
- iter->method->name);
- else
- printf("No more bootdevs\n");
+ if (IS_ENABLED(CONFIG_BOOTSTD_FULL)) {
+ /* record the device for later */
+ if (dev && iter->num_devs < iter->max_devs)
+ iter->dev_used[iter->num_devs++] = dev;
+
+ if ((iter->flags & (BOOTFLOWF_SHOW | BOOTFLOWF_SINGLE_DEV)) ==
+ BOOTFLOWF_SHOW) {
+ if (dev)
+ printf("Scanning bootdev '%s':\n", dev->name);
+ else if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) &&
+ ucp->flags & BOOTMETHF_GLOBAL)
+ printf("Scanning global bootmeth '%s':\n",
+ iter->method->name);
+ else
+ printf("No more bootdevs\n");
+ }
}
}
diff --git a/include/bootflow.h b/include/bootflow.h
index c236891..f516bf8 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -14,6 +14,10 @@
struct bootstd_priv;
struct expo;
+enum {
+ BOOTFLOW_MAX_USED_DEVS = 16,
+};
+
/**
* enum bootflow_state_t - states that a particular bootflow can be in
*
@@ -173,7 +177,9 @@
* @err: Error obtained from checking the last iteration. This is used to skip
* forward (e.g. to skip the current partition because it is not valid)
* -ESHUTDOWN: try next bootdev
- * @num_devs: Number of bootdevs in @dev_order
+ * @num_devs: Number of bootdevs in @dev_used
+ * @max_devs: Maximum number of entries in @dev_used
+ * @dev_used: List of bootdevs used during iteration
* @labels: List of labels to scan for bootdevs
* @cur_label: Current label being processed
* @num_methods: Number of bootmeth devices in @method_order
@@ -196,6 +202,8 @@
int first_bootable;
int err;
int num_devs;
+ int max_devs;
+ struct udevice *dev_used[BOOTFLOW_MAX_USED_DEVS];
const char *const *labels;
int cur_label;
int num_methods;
diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c
index 5d5ce7f..ef5215b 100644
--- a/test/boot/bootdev.c
+++ b/test/boot/bootdev.c
@@ -186,7 +186,6 @@
BOOTSTD_TEST(bootdev_test_any, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
UT_TESTF_ETH_BOOTDEV);
-#if 0 /* disable for now */
/* Check bootdev ordering with the bootdev-order property */
static int bootdev_test_order(struct unit_test_state *uts)
{
@@ -205,18 +204,29 @@
ut_assertok(env_set("boot_targets", NULL));
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(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
@@ -225,30 +235,18 @@
ut_assertok(bootstd_test_drop_bootdev_order(uts));
ut_assertok(bootflow_scan_first(NULL, NULL, &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);
+ 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);
- /*
- * 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(-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)
@@ -260,6 +258,9 @@
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));
@@ -269,30 +270,32 @@
/* 3 MMC and 3 USB bootdevs: MMC should come before USB */
console_record_reset_enable();
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(NULL, NULL, &iter, BOOTFLOWF_HUNT,
&bflow));
- ut_asserteq(6, iter.num_devs);
+ 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);
-#endif
/* Check listing hunters */
static int bootdev_test_hunter(struct unit_test_state *uts)