mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-18 02:44:37 +00:00
bootstd: Allow iterating to the next bootdev priortiy
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>
This commit is contained in:
parent
e4b694893f
commit
43e89a3069
4 changed files with 165 additions and 0 deletions
|
@ -585,6 +585,70 @@ int bootdev_next_label(struct bootflow_iter *iter, struct udevice **devp,
|
|||
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
|
||||
*
|
||||
|
|
|
@ -349,6 +349,20 @@ int bootdev_hunt_and_find_by_label(const char *label, struct udevice **devp,
|
|||
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)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#ifndef __bootflow_h
|
||||
#define __bootflow_h
|
||||
|
||||
#include <bootdev.h>
|
||||
#include <dm/ofnode_decl.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
|
@ -180,6 +181,7 @@ enum bootflow_meth_flags_t {
|
|||
* @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
|
||||
|
@ -203,6 +205,7 @@ struct bootflow_iter {
|
|||
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;
|
||||
|
|
|
@ -588,3 +588,87 @@ static int bootdev_test_next_label(struct unit_test_state *uts)
|
|||
}
|
||||
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);
|
||||
|
|
Loading…
Add table
Reference in a new issue