summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boot/bootflow.c2
-rw-r--r--boot/bootmeth-uclass.c79
-rw-r--r--include/bootmeth.h4
-rw-r--r--test/boot/bootflow.c5
4 files changed, 64 insertions, 26 deletions
diff --git a/boot/bootflow.c b/boot/bootflow.c
index 08ea0336324..5d94a27ff84 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -278,7 +278,7 @@ int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter,
if (ret)
return log_msg_ret("obdev", -ENODEV);
- ret = bootmeth_setup_iter_order(iter);
+ ret = bootmeth_setup_iter_order(iter, !(flags & BOOTFLOWF_SKIP_GLOBAL));
if (ret)
return log_msg_ret("obmeth", -ENODEV);
diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c
index 88bbb32c47f..2d7652edeab 100644
--- a/boot/bootmeth-uclass.c
+++ b/boot/bootmeth-uclass.c
@@ -85,18 +85,7 @@ int bootmeth_get_bootflow(struct udevice *dev, struct bootflow *bflow)
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;
@@ -119,31 +108,77 @@ int bootmeth_setup_iter_order(struct bootflow_iter *iter)
/* 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;
}
diff --git a/include/bootmeth.h b/include/bootmeth.h
index c93367b0995..50ded055f3f 100644
--- a/include/bootmeth.h
+++ b/include/bootmeth.h
@@ -209,10 +209,12 @@ int bootmeth_boot(struct udevice *dev, struct bootflow *bflow);
* ordering there, then all bootmethods are added
*
* @iter: Iterator to update with the order
+ * @include_global: true to add the global bootmeths, in which case they appear
+ * first
* 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);
/**
* bootmeth_set_order() - Set the bootmeth order
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 22eef40c0e3..07b0517718e 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -343,8 +343,9 @@ static int bootflow_system(struct unit_test_state *uts)
bootstd_clear_glob();
console_record_reset_enable();
ut_assertok(run_command("bootflow scan -l", 0));
- ut_assert_skip_to_line(" 1 bootmgr ready bootstd 0 <NULL> <NULL>");
- ut_assert_nextline("No more bootdevs");
+ ut_assert_skip_to_line(
+ " 0 bootmgr ready (none) 0 <NULL> <NULL>");
+ ut_assert_skip_to_line("No more bootdevs");
ut_assert_skip_to_line("(2 bootflows, 2 valid)");
ut_assert_console_end();