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 <sjg@chromium.org>
This commit is contained in:
@@ -17,6 +17,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,
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user