From: Simon Glass Date: Wed, 15 Oct 2025 15:44:08 +0000 (+0100) Subject: boot: Keep track of which bootmeths have been used X-Git-Tag: v2026.01-rc1~10^2~6 X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bef963cb751049cacc86f2754452efadd03ae2f0;p=pandora-u-boot.git boot: Keep track of which bootmeths have been used 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 --- diff --git a/boot/bootflow.c b/boot/bootflow.c index 62634a59a94..2e4d1a345cd 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -17,6 +17,10 @@ #include #include +/* 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, @@ -433,6 +437,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); @@ -460,6 +468,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 a0aa6336c9b..a9709465f6e 100644 --- a/boot/bootmeth-uclass.c +++ b/boot/bootmeth-uclass.c @@ -211,6 +211,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 b18baebb4ba..58a4ab9f811 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -11,7 +11,8 @@ #include #include #include -#include +#include +#include struct bootstd_priv; struct expo; @@ -213,6 +214,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 * @@ -260,6 +265,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; @@ -282,6 +289,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 83fb646babf..8317dee1e20 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -310,6 +310,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 @@ -318,6 +319,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(2, iter.num_methods); @@ -327,6 +329,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); /* The next device is mmc1.bootdev - at first we use the whole device */ @@ -338,6 +341,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), iter.methods_done); bootflow_free(&bflow); ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow)); @@ -348,9 +352,10 @@ 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); - /* Then more to partition 1 where we find something */ + /* Then move to partition 1 where we find something */ ut_assertok(bootflow_scan_next(&iter, &bflow)); ut_asserteq(2, iter.num_methods); ut_asserteq(0, iter.cur_method); @@ -380,6 +385,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), iter.methods_done); bootflow_free(&bflow); bootflow_iter_uninit(&iter);