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@chromium.org>
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
*
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)
#ifndef __bootflow_h
#define __bootflow_h
+#include <bootdev.h>
#include <dm/ofnode_decl.h>
#include <linux/list.h>
* @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
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;
}
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@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(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);