
From: Simon Glass <sjg@chromium.org> Add a bitfield which tracks when bootmeths have been used. This will be needed when global bootmeths can be used later in the iteration. Fix a missing bootflow_free() while here. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) boot/bootflow.c | 13 +++++++++++++ boot/bootmeth-uclass.c | 10 ++++++++++ include/bootflow.h | 8 ++++++++ test/boot/bootflow.c | 8 ++++++++ 4 files changed, 39 insertions(+) diff --git a/boot/bootflow.c b/boot/bootflow.c index dab4397e5eb..4e2a227c807 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -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, @@ -493,6 +497,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); @@ -520,6 +528,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) diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c index 0147b97fcb0..d71e4f001f1 100644 --- a/boot/bootmeth-uclass.c +++ b/boot/bootmeth-uclass.c @@ -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; diff --git a/include/bootflow.h b/include/bootflow.h index 0805d10e197..051158780e6 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -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; }; /** diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index a18afad0f72..af7f7391160 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -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); -- 2.43.0