diff options
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/bootdev-uclass.c | 140 | ||||
| -rw-r--r-- | boot/bootflow.c | 72 |
2 files changed, 80 insertions, 132 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); + 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; diff --git a/boot/bootflow.c b/boot/bootflow.c index d2dbc9d4450..32e2aad470d 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -92,7 +92,6 @@ void bootflow_iter_init(struct bootflow_iter *iter, int flags) void bootflow_iter_uninit(struct bootflow_iter *iter) { - free(iter->dev_order); free(iter->method_order); } @@ -113,12 +112,25 @@ int bootflow_iter_drop_bootmeth(struct bootflow_iter *iter, return 0; } +/** + * bootflow_iter_set_dev() - switch to the next bootdev when iterating + * + * This sets iter->dev, records the device in the dev_used[] list and shows a + * message if required + * + * @iter: Iterator to update + * @dev: Bootdev to use, or NULL if there are no more + */ static void bootflow_iter_set_dev(struct bootflow_iter *iter, - struct udevice *dev) + struct udevice *dev, int method_flags) { struct bootmeth_uc_plat *ucp = dev_get_uclass_plat(iter->method); + log_debug("iter: Setting dev to %s, flags %x\n", + dev ? dev->name : "(none)", method_flags); iter->dev = dev; + iter->method_flags = method_flags; + if ((iter->flags & (BOOTFLOWF_SHOW | BOOTFLOWF_SINGLE_DEV)) == BOOTFLOWF_SHOW) { if (dev) @@ -144,6 +156,7 @@ static int iter_incr(struct bootflow_iter *iter) bool global; int ret; + log_debug("entry: err=%d\n", iter->err); global = iter->doing_global; if (iter->err == BF_NO_MORE_DEVICES) @@ -182,7 +195,7 @@ static int iter_incr(struct bootflow_iter *iter) return 0; } - /* No more partitions; start at the first one and...*/ + /* No more partitions; start at the first one and... */ iter->part = 0; /* @@ -196,16 +209,32 @@ static int iter_incr(struct bootflow_iter *iter) if (iter->flags & BOOTFLOWF_SINGLE_DEV) { ret = -ENOENT; } else { - if (inc_dev) - iter->cur_dev++; - if (iter->cur_dev == iter->num_devs) { - ret = -ENOENT; - bootflow_iter_set_dev(iter, NULL); + int method_flags; + + ret = 0; + dev = iter->dev; + log_debug("inc_dev=%d\n", inc_dev); + if (!inc_dev) { + ret = bootdev_setup_iter(iter, &dev, &method_flags); + } else { + log_debug("labels %p\n", iter->labels); + if (iter->labels) { + ret = bootdev_next_label(iter, &dev, + &method_flags); + } else { + ret = bootdev_next_prio(iter, &dev); + method_flags = 0; + } + } + log_debug("ret=%d, dev=%p %s\n", ret, dev, + dev ? dev->name : "none"); + if (ret) { + bootflow_iter_set_dev(iter, NULL, 0); } else { - dev = iter->dev_order[iter->cur_dev]; ret = device_probe(dev); + log_debug("probe %s %d\n", dev->name, ret); if (!log_msg_ret("probe", ret)) - bootflow_iter_set_dev(iter, dev); + bootflow_iter_set_dev(iter, dev, method_flags); } } @@ -230,7 +259,7 @@ static int bootflow_check(struct bootflow_iter *iter, struct bootflow *bflow) int ret; if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && iter->doing_global) { - bootflow_iter_set_dev(iter, NULL); + bootflow_iter_set_dev(iter, NULL, 0); ret = bootmeth_get_bootflow(iter->method, bflow); if (ret) return log_msg_ret("glob", ret); @@ -274,18 +303,27 @@ int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter, flags |= BOOTFLOWF_SKIP_GLOBAL; bootflow_iter_init(iter, flags); - ret = bootdev_setup_iter_order(iter, &dev); - if (ret) - return log_msg_ret("obdev", -ENODEV); - + /* + * Set up the ordering of bootmeths. This sets iter->doing_global and + * iter->first_glob_method if we are starting with the global bootmeths + */ ret = bootmeth_setup_iter_order(iter, !(flags & BOOTFLOWF_SKIP_GLOBAL)); if (ret) return log_msg_ret("obmeth", -ENODEV); /* Find the first bootmeth (there must be at least one!) */ iter->method = iter->method_order[iter->cur_method]; - if (!IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) || !iter->doing_global) - bootflow_iter_set_dev(iter, dev); + + if (!IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) || !iter->doing_global) { + struct udevice *dev = NULL; + int method_flags; + + ret = bootdev_setup_iter(iter, &dev, &method_flags); + if (ret) + return log_msg_ret("obdev", -ENODEV); + + bootflow_iter_set_dev(iter, dev, method_flags); + } ret = bootflow_check(iter, bflow); if (ret) { |
