]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
boot: Keep track of which bootmeths have been used
authorSimon Glass <sjg@chromium.org>
Wed, 15 Oct 2025 15:44:08 +0000 (16:44 +0100)
committerTom Rini <trini@konsulko.com>
Wed, 22 Oct 2025 20:16:56 +0000 (14:16 -0600)
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>
boot/bootflow.c
boot/bootmeth-uclass.c
include/bootflow.h
test/boot/bootflow.c

index 62634a59a94a0b39500de0815c1d6f40111e2e5c..2e4d1a345cd8beac8a263ff650179b2c5b93272c 100644 (file)
 #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,
@@ -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)
index a0aa6336c9bad51b4c8c5c22b9ca7ede020ec981..a9709465f6e75690cc06510de38bac3eba8f04bf 100644 (file)
@@ -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;
 
index b18baebb4ba25540cfab60f93b27cbc9611aea23..58a4ab9f8110f1bfa8a411c6f604f3b2503eb685 100644 (file)
@@ -11,7 +11,8 @@
 #include <bootdev.h>
 #include <image.h>
 #include <dm/ofnode_decl.h>
-#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/build_bug.h>
 
 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;
 };
 
 /**
index 83fb646babf62bcc574172f79696d0140d65d3d2..8317dee1e20ad471f977a8d19dd7bbc6036a3df1 100644 (file)
@@ -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);