summaryrefslogtreecommitdiff
path: root/boot/bootdev-uclass.c
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2023-01-17 10:48:14 -0700
committerTom Rini <trini@konsulko.com>2023-01-23 18:11:41 -0500
commit47aedc29dcb9871e076f6e4aa82004633af513ef (patch)
tree0a7d94b5f9dc82da793ec6e49388c8527754d732 /boot/bootdev-uclass.c
parent18552d2a7288afd6f125b4ac99e5c27690c129b4 (diff)
bootstd: Switch bootdev scanning to use labels
At present we set up the bootdev order at the start, then scan the bootdevs one by one. However this approach cannot be used with hunters, since the bootdevs may not exist until the hunter is used. Nor can we just run all the hunters at the start, since that violate's U-Boot's 'lazy init' requirement. It also increases boot time. So we need to adjust the algorithm to scan by labels instead. As a first step, drop the dev_order[] array in favour of a list of labels. Update the name of bootdev_setup_iter_order() to better reflect what it does. Update some related comments and log messages. Also disable a few tests until a later commit where we can use them. Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'boot/bootdev-uclass.c')
-rw-r--r--boot/bootdev-uclass.c142
1 files changed, 26 insertions, 116 deletions
diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index 63005140061..334be7662a1 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -649,96 +649,12 @@ int bootdev_next_prio(struct bootflow_iter *iter, struct udevice **devp)
return 0;
}
-/**
- * h_cmp_bootdev() - Compare two bootdevs to find out which should go first
- *
- * @v1: struct udevice * of first bootdev device
- * @v2: struct udevice * of second bootdev device
- * Return: sort order (<0 if dev1 < dev2, ==0 if equal, >0 if dev1 > dev2)
- */
-static int h_cmp_bootdev(const void *v1, const void *v2)
-{
- const struct udevice *dev1 = *(struct udevice **)v1;
- const struct udevice *dev2 = *(struct udevice **)v2;
- const struct bootdev_uc_plat *ucp1 = dev_get_uclass_plat(dev1);
- const struct bootdev_uc_plat *ucp2 = dev_get_uclass_plat(dev2);
- int diff;
-
- /* Use priority first */
- diff = ucp1->prio - ucp2->prio;
- if (diff)
- return diff;
-
- /* Fall back to seq for devices of the same priority */
- diff = dev_seq(dev1) - dev_seq(dev2);
-
- return diff;
-}
-
-/**
- * build_order() - Build the ordered list of bootdevs to use
- *
- * This builds an ordered list of devices by one of three methods:
- * - using the boot_targets environment variable, if non-empty
- * - using the bootdev-order devicetree property, if present
- * - sorted by priority and sequence number
- *
- * @bootstd: BOOTSTD device to use
- * @order: Bootdevs listed in default order
- * @max_count: Number of entries in @order
- * Return: number of bootdevs found in the ordering, or -E2BIG if the
- * boot_targets string is too long, or -EXDEV if the ordering produced 0 results
- */
-static int build_order(struct udevice *bootstd, struct udevice **order,
- int max_count)
-{
- const char *overflow_target = NULL;
- const char *const *labels;
- struct udevice *dev;
- int i, ret, count;
- bool ok;
-
- labels = bootstd_get_bootdev_order(bootstd, &ok);
- if (!ok)
- return log_msg_ret("ord", -ENOMEM);
- if (labels) {
- int upto;
-
- upto = 0;
- for (i = 0; labels[i]; i++) {
- ret = bootdev_find_by_label(labels[i], &dev, NULL);
- if (!ret) {
- if (upto == max_count) {
- overflow_target = labels[i];
- break;
- }
- order[upto++] = dev;
- }
- }
- count = upto;
- } else {
- /* sort them into priority order */
- count = max_count;
- qsort(order, count, sizeof(struct udevice *), h_cmp_bootdev);
- }
-
- if (overflow_target) {
- log_warning("Expected at most %d bootdevs, but overflowed with boot_target '%s'\n",
- max_count, overflow_target);
- }
-
- if (!count)
- return log_msg_ret("targ", -EXDEV);
-
- return count;
-}
-
-int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp)
+int bootdev_setup_iter(struct bootflow_iter *iter, struct udevice **devp,
+ int *method_flagsp)
{
- struct udevice *bootstd, *dev = *devp, **order;
+ struct udevice *bootstd, *dev = *devp;
bool show = iter->flags & BOOTFLOWF_SHOW;
- struct uclass *uc;
- int count, upto;
+ int method_flags;
int ret;
ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd);
@@ -757,39 +673,33 @@ int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp)
/* Handle scanning a single device */
if (dev) {
iter->flags |= BOOTFLOWF_SINGLE_DEV;
- return 0;
- }
-
- count = uclass_id_count(UCLASS_BOOTDEV);
- if (!count)
- return log_msg_ret("count", -ENOENT);
-
- order = calloc(count, sizeof(struct udevice *));
- if (!order)
- return log_msg_ret("order", -ENOMEM);
-
- /* Get the list of bootdevs */
- uclass_id_foreach_dev(UCLASS_BOOTDEV, dev, uc)
- order[upto++] = dev;
- log_debug("Found %d bootdevs\n", count);
- if (upto != count)
- log_debug("Expected %d bootdevs, found %d using aliases\n",
- count, upto);
-
- ret = build_order(bootstd, order, upto);
- if (ret < 0) {
- free(order);
- return log_msg_ret("build", ret);
+ log_debug("Selected boodev: %s\n", dev->name);
+ method_flags = 0;
+ } else {
+ bool ok;
+
+ /* This either returns a non-empty list or NULL */
+ iter->labels = bootstd_get_bootdev_order(bootstd, &ok);
+ if (!ok)
+ return log_msg_ret("ord", -ENOMEM);
+ log_debug("setup labels %p\n", iter->labels);
+ if (iter->labels) {
+ iter->cur_label = -1;
+ ret = bootdev_next_label(iter, &dev, &method_flags);
+ } else {
+ ret = bootdev_next_prio(iter, &dev);
+ method_flags = 0;
+ }
+ if (!dev)
+ return log_msg_ret("fin", -ENOENT);
+ log_debug("Selected bootdev: %s\n", dev->name);
}
- iter->num_devs = ret;
- iter->dev_order = order;
- iter->cur_dev = 0;
-
- dev = *order;
ret = device_probe(dev);
if (ret)
return log_msg_ret("probe", ret);
+ if (method_flagsp)
+ *method_flagsp = method_flags;
*devp = dev;
return 0;