return ops->read_bootflow(dev, bflow);
}
-/**
- * bootmeth_setup_iter_order() - Set up the ordering of bootmeths to scan
- *
- * This sets up the ordering information in @iter, based on the selected
- * ordering of the bootmethds in bootstd_priv->bootmeth_order. If there is no
- * ordering there, then all bootmethods are added
- *
- * @iter: Iterator to update with the order
- * Return: 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve
- * on other error
- */
-int bootmeth_setup_iter_order(struct bootflow_iter *iter)
+int bootmeth_setup_iter_order(struct bootflow_iter *iter, bool include_global)
{
struct bootstd_priv *std;
struct udevice **order;
/* If we have an ordering, copy it */
if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && std->bootmeth_count) {
+ int i;
+
+ /*
+ * We don't support skipping global bootmeths. Instead, the user
+ * should omit them from the ordering
+ */
+ if (!include_global)
+ return log_msg_ret("glob", -EPERM);
memcpy(order, std->bootmeth_order,
count * sizeof(struct bootmeth *));
+
+ if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL)) {
+ for (i = 0; i < count; i++) {
+ struct udevice *dev = order[i];
+ struct bootmeth_uc_plat *ucp;
+ bool is_global;
+
+ ucp = dev_get_uclass_plat(dev);
+ is_global = ucp->flags &
+ BOOTMETHF_GLOBAL;
+ if (is_global) {
+ iter->first_glob_method = i;
+ break;
+ }
+ }
+ }
} else {
struct udevice *dev;
- int i, upto;
+ int i, upto, pass;
/*
- * Get a list of bootmethods, in seq order (i.e. using aliases).
- * There may be gaps so try to count up high enough to find them
- * all.
+ * Do two passes, one to find the normal bootmeths and another
+ * to find the global ones, if required, The global ones go at
+ * the end.
*/
- for (i = 0, upto = 0; upto < count && i < 20 + count * 2; i++) {
- ret = uclass_get_device_by_seq(UCLASS_BOOTMETH, i,
- &dev);
- if (!ret)
- order[upto++] = dev;
+ for (pass = 0, upto = 0; pass < 1 + include_global; pass++) {
+ if (pass)
+ iter->first_glob_method = upto;
+ /*
+ * Get a list of bootmethods, in seq order (i.e. using
+ * aliases). There may be gaps so try to count up high
+ * enough to find them all.
+ */
+ for (i = 0; upto < count && i < 20 + count * 2; i++) {
+ struct bootmeth_uc_plat *ucp;
+ bool is_global;
+
+ ret = uclass_get_device_by_seq(UCLASS_BOOTMETH,
+ i, &dev);
+ if (ret)
+ continue;
+ ucp = dev_get_uclass_plat(dev);
+ is_global =
+ IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) &&
+ (ucp->flags & BOOTMETHF_GLOBAL);
+ if (pass ? is_global : !is_global)
+ order[upto++] = dev;
+ }
}
count = upto;
}
if (!count)
return log_msg_ret("count2", -ENOENT);
+ if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && include_global &&
+ iter->first_glob_method != -1 && iter->first_glob_method != count) {
+ iter->cur_method = iter->first_glob_method;
+ iter->doing_global = true;
+ }
iter->method_order = order;
iter->num_methods = count;
- iter->cur_method = 0;
return 0;
}