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>
diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index 6300514..334be76 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -649,96 +649,12 @@
 	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)
+int bootdev_setup_iter(struct bootflow_iter *iter, struct udevice **devp,
+		       int *method_flagsp)
 {
-	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)
-{
-	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 @@
 	/* 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);
+		log_debug("Selected boodev: %s\n", dev->name);
+		method_flags = 0;
+	} else {
+		bool ok;
 
-	ret = build_order(bootstd, order, upto);
-	if (ret < 0) {
-		free(order);
-		return log_msg_ret("build", ret);
+		/* 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;