@@ -18,6 +18,10 @@
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
+/* ensure BOOTMETH_MAX_COUNT fits in method_flags field */
+static_assert(BOOTMETH_MAX_COUNT <=
+ (sizeof(((struct bootflow_iter *)NULL)->method_flags) * 8));
+
/* error codes used to signal running out of things */
enum {
BF_NO_MORE_PARTS = -ESHUTDOWN,
@@ -491,6 +495,10 @@ int bootflow_scan_first(struct udevice *dev, const char *label,
bootflow_iter_set_dev(iter, dev, method_flags);
}
+ if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL)) {
+ iter->methods_done |= BIT(iter->cur_method);
+ log_debug("methods_done now %x\n", iter->cur_method);
+ }
ret = bootflow_check(iter, bflow);
if (ret) {
log_debug("check - ret=%d\n", ret);
@@ -518,6 +526,11 @@ int bootflow_scan_next(struct bootflow_iter *iter, struct bootflow *bflow)
return log_msg_ret("done", ret);
if (!ret) {
+ if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL)) {
+ iter->methods_done |= BIT(iter->cur_method);
+ log_debug("methods_done now %x\n",
+ iter->cur_method);
+ }
ret = bootflow_check(iter, bflow);
log_debug("check - ret=%d\n", ret);
if (!ret)
@@ -199,6 +199,16 @@ int bootmeth_setup_iter_order(struct bootflow_iter *iter, bool include_global)
iter->doing_global = true;
iter->have_global = true;
}
+
+ /*
+ * check we don't exceed the maximum bits in methods_done when tracking
+ * which global bootmeths have run
+ */
+ if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && count > BOOTMETH_MAX_COUNT) {
+ free(order);
+ return log_msg_ret("tmb", -ENOSPC);
+ }
+
iter->method_order = order;
iter->num_methods = count;
@@ -12,6 +12,7 @@
#include <image.h>
#include <dm/ofnode_decl.h>
#include <linux/list.h>
+#include <linux/build_bug.h>
struct bootstd_priv;
struct expo;
@@ -226,6 +227,10 @@ enum bootflow_meth_flags_t {
BOOTFLOW_METHF_SINGLE_UCLASS = 1 << 3,
};
+enum {
+ BOOTMETH_MAX_COUNT = 32,
+};
+
/**
* struct bootflow_iter - state for iterating through bootflows
*
@@ -273,6 +278,8 @@ enum bootflow_meth_flags_t {
* happens before the normal ones)
* @method_flags: flags controlling which methods should be used for this @dev
* (enum bootflow_meth_flags_t)
+ * @methods_done: indicates which methods have been processed, one bit for
+ * each method in @method_order[]
*/
struct bootflow_iter {
int flags;
@@ -295,6 +302,7 @@ struct bootflow_iter {
bool have_global;
bool doing_global;
int method_flags;
+ uint methods_done;
};
/**
@@ -316,6 +316,7 @@ static int bootflow_iter(struct unit_test_state *uts)
ut_assert(!iter.doing_global);
ut_assert(!iter.have_global);
ut_asserteq(-1, iter.first_glob_method);
+ ut_asserteq(BIT(0), iter.methods_done);
/*
* This shows MEDIA even though there is none, since in
@@ -324,6 +325,7 @@ static int bootflow_iter(struct unit_test_state *uts)
* know.
*/
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
+ bootflow_free(&bflow);
ut_asserteq(-EPROTONOSUPPORT, bootflow_scan_next(&iter, &bflow));
ut_asserteq(3, iter.num_methods);
@@ -333,6 +335,7 @@ static int bootflow_iter(struct unit_test_state *uts)
ut_asserteq_str("efi", iter.method->name);
ut_asserteq(0, bflow.err);
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
+ ut_asserteq(BIT(0) | BIT(1), iter.methods_done);
bootflow_free(&bflow);
/* now the VBE boothmeth */
@@ -344,6 +347,7 @@ static int bootflow_iter(struct unit_test_state *uts)
ut_asserteq_str("vbe", iter.method->name);
ut_asserteq(0, bflow.err);
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
+ ut_asserteq(BIT(0) | BIT(1) | BIT(2), iter.methods_done);
bootflow_free(&bflow);
/* The next device is mmc1.bootdev - at first we use the whole device */
@@ -355,6 +359,7 @@ static int bootflow_iter(struct unit_test_state *uts)
ut_asserteq_str("extlinux", iter.method->name);
ut_asserteq(0, bflow.err);
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
+ ut_asserteq(BIT(0) | BIT(1) | BIT(2), iter.methods_done);
bootflow_free(&bflow);
ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
@@ -365,6 +370,7 @@ static int bootflow_iter(struct unit_test_state *uts)
ut_asserteq_str("efi", iter.method->name);
ut_asserteq(0, bflow.err);
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
+ ut_asserteq(BIT(0) | BIT(1) | BIT(2), iter.methods_done);
bootflow_free(&bflow);
/* now the VBE boothmeth */
@@ -376,6 +382,7 @@ static int bootflow_iter(struct unit_test_state *uts)
ut_asserteq_str("vbe", iter.method->name);
ut_asserteq(0, bflow.err);
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
+ ut_asserteq(BIT(0) | BIT(1) | BIT(2), iter.methods_done);
bootflow_free(&bflow);
/* Then move to partition 1 where we find something */
@@ -418,6 +425,7 @@ static int bootflow_iter(struct unit_test_state *uts)
ut_asserteq_str("extlinux", iter.method->name);
ut_asserteq(0, bflow.err);
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
+ ut_asserteq(BIT(0) | BIT(1) | BIT(2), iter.methods_done);
bootflow_free(&bflow);
bootflow_iter_uninit(&iter);