Compare commits
15 Commits
cherry-91b
...
glob
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10ba4553b2 | ||
|
|
86701ac1e1 | ||
|
|
8ab3523505 | ||
|
|
e164e96b47 | ||
|
|
f05d8097ad | ||
|
|
15bb4b3074 | ||
|
|
e4c50815ab | ||
|
|
b6db0a6f48 | ||
|
|
cbf290a635 | ||
|
|
8d421a3214 | ||
|
|
f15b67db40 | ||
|
|
9c4a64b260 | ||
|
|
ed6cf4ee9a | ||
|
|
7d169c5625 | ||
|
|
305eefbcf0 |
275
boot/bootflow.c
275
boot/bootflow.c
@@ -18,6 +18,10 @@
|
|||||||
#include <dm/device-internal.h>
|
#include <dm/device-internal.h>
|
||||||
#include <dm/uclass-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 */
|
/* error codes used to signal running out of things */
|
||||||
enum {
|
enum {
|
||||||
BF_NO_MORE_PARTS = -ESHUTDOWN,
|
BF_NO_MORE_PARTS = -ESHUTDOWN,
|
||||||
@@ -56,6 +60,61 @@ const char *bootflow_state_get_name(enum bootflow_state_t state)
|
|||||||
return bootflow_state[state];
|
return bootflow_state[state];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* report_bootflow_err() - Report where a bootflow failed
|
||||||
|
*
|
||||||
|
* When a bootflow does not make it to the 'loaded' state, something went wrong.
|
||||||
|
* Print a helpful message if there is an error
|
||||||
|
*
|
||||||
|
* @bflow: Bootflow to process
|
||||||
|
* @err: Error code (0 if none)
|
||||||
|
*/
|
||||||
|
static void report_bootflow_err(struct bootflow *bflow, int err)
|
||||||
|
{
|
||||||
|
if (!err)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Indent out to 'Method' */
|
||||||
|
printf(" ** ");
|
||||||
|
|
||||||
|
switch (bflow->state) {
|
||||||
|
case BOOTFLOWST_BASE:
|
||||||
|
printf("No media/partition found");
|
||||||
|
break;
|
||||||
|
case BOOTFLOWST_MEDIA:
|
||||||
|
printf("No partition found");
|
||||||
|
break;
|
||||||
|
case BOOTFLOWST_PART:
|
||||||
|
printf("No filesystem found");
|
||||||
|
break;
|
||||||
|
case BOOTFLOWST_FS:
|
||||||
|
printf("File not found");
|
||||||
|
break;
|
||||||
|
case BOOTFLOWST_FILE:
|
||||||
|
printf("File cannot be loaded");
|
||||||
|
break;
|
||||||
|
case BOOTFLOWST_READY:
|
||||||
|
printf("Ready");
|
||||||
|
break;
|
||||||
|
case BOOTFLOWST_COUNT:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(", err=%dE\n", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bootflow_show(int index, struct bootflow *bflow, bool errors)
|
||||||
|
{
|
||||||
|
const char *name = bootflow_guess_label(bflow);
|
||||||
|
|
||||||
|
printf("%3x %-11s %-6s %-9.9s %4x %-25.25s %s\n", index,
|
||||||
|
bflow->method ? bflow->method->name : "(none)",
|
||||||
|
bootflow_state_get_name(bflow->state), name, bflow->part,
|
||||||
|
bflow->name, bflow->fname ?: "");
|
||||||
|
if (errors)
|
||||||
|
report_bootflow_err(bflow, bflow->err);
|
||||||
|
}
|
||||||
|
|
||||||
int bootflow_first_glob(struct bootflow **bflowp)
|
int bootflow_first_glob(struct bootflow **bflowp)
|
||||||
{
|
{
|
||||||
struct bootstd_priv *std;
|
struct bootstd_priv *std;
|
||||||
@@ -112,11 +171,17 @@ int bootflow_iter_drop_bootmeth(struct bootflow_iter *iter,
|
|||||||
iter->method_order[iter->cur_method] != bmeth)
|
iter->method_order[iter->cur_method] != bmeth)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
log_debug("Dropping bootmeth '%s'\n", bmeth->name);
|
||||||
|
|
||||||
memmove(&iter->method_order[iter->cur_method],
|
memmove(&iter->method_order[iter->cur_method],
|
||||||
&iter->method_order[iter->cur_method + 1],
|
&iter->method_order[iter->cur_method + 1],
|
||||||
(iter->num_methods - iter->cur_method - 1) * sizeof(void *));
|
(iter->num_methods - iter->cur_method - 1) * sizeof(void *));
|
||||||
|
|
||||||
iter->num_methods--;
|
iter->num_methods--;
|
||||||
|
if (iter->first_glob_method > 0) {
|
||||||
|
iter->first_glob_method--;
|
||||||
|
log_debug("first_glob_method %d\n", iter->first_glob_method);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -150,7 +215,7 @@ static void bootflow_iter_set_dev(struct bootflow_iter *iter,
|
|||||||
if (dev)
|
if (dev)
|
||||||
printf("Scanning bootdev '%s':\n", dev->name);
|
printf("Scanning bootdev '%s':\n", dev->name);
|
||||||
else if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) &&
|
else if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) &&
|
||||||
ucp->flags & BOOTMETHF_GLOBAL)
|
ucp->flags & BOOTMETHF_GLOBAL)
|
||||||
printf("Scanning global bootmeth '%s':\n",
|
printf("Scanning global bootmeth '%s':\n",
|
||||||
iter->method->name);
|
iter->method->name);
|
||||||
else
|
else
|
||||||
@@ -180,6 +245,101 @@ static void scan_next_in_uclass(struct udevice **devp)
|
|||||||
*devp = dev;
|
*devp = dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bootmeth_glob_allowed() - Check if a global bootmeth is usable at this point
|
||||||
|
*
|
||||||
|
* @iter: Bootflow iterator being used
|
||||||
|
* Return: true if the global bootmeth has a suitable priority and has not
|
||||||
|
* already been used
|
||||||
|
*/
|
||||||
|
static bool bootmeth_glob_allowed(struct bootflow_iter *iter, int meth_seq)
|
||||||
|
{
|
||||||
|
struct udevice *meth = iter->method_order[meth_seq];
|
||||||
|
bool done = iter->methods_done & BIT(meth_seq);
|
||||||
|
struct bootmeth_uc_plat *ucp;
|
||||||
|
|
||||||
|
ucp = dev_get_uclass_plat(meth);
|
||||||
|
log_debug("considering glob '%s': done %d glob_prio %d\n", meth->name,
|
||||||
|
done, ucp->glob_prio);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if this one has already been used, or its priority is too low, try
|
||||||
|
* the next
|
||||||
|
*/
|
||||||
|
if (done || ucp->glob_prio > iter->cur_prio)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* next_glob_bootmeth() - Find the next global bootmeth to use
|
||||||
|
*
|
||||||
|
* Scans the global bootmeths to find the first unused one whose priority has
|
||||||
|
* been reached. If found, iter->cur_method and iter->method are set up and
|
||||||
|
* doing_global is set to true
|
||||||
|
*
|
||||||
|
* @iter: Bootflow iterator being used
|
||||||
|
* Return 0 if found, -ENOENT if no more global bootmeths are available
|
||||||
|
*/
|
||||||
|
static int next_glob_bootmeth(struct bootflow_iter *iter)
|
||||||
|
{
|
||||||
|
log_debug("rescan global bootmeths have_global %d\n",
|
||||||
|
iter->have_global);
|
||||||
|
if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && iter->have_global) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* rescan the global bootmeths */
|
||||||
|
log_debug("first_glob_method %d num_methods %d methods_done %x\n",
|
||||||
|
iter->first_glob_method, iter->num_methods,
|
||||||
|
iter->methods_done);
|
||||||
|
for (i = iter->first_glob_method; i < iter->num_methods; i++) {
|
||||||
|
if (bootmeth_glob_allowed(iter, i)) {
|
||||||
|
iter->cur_method = i;
|
||||||
|
iter->method = iter->method_order[i];
|
||||||
|
iter->doing_global = true;
|
||||||
|
iter->dev = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prepare_bootdev() - Get ready to use a bootdev
|
||||||
|
*
|
||||||
|
* @iter: Bootflow iterator being used
|
||||||
|
* @dev: UCLASS_BOOTDEV device to use
|
||||||
|
* @method_flags: Method flag for the bootdev
|
||||||
|
* @check_global: true to check global bootmeths before processing @dev
|
||||||
|
* Return 0 if OK, -ve if the bootdev failed to probe
|
||||||
|
*/
|
||||||
|
static int prepare_bootdev(struct bootflow_iter *iter, struct udevice *dev,
|
||||||
|
int method_flags, bool check_global)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (check_global && !next_glob_bootmeth(iter)) {
|
||||||
|
iter->pending_bootdev = dev;
|
||||||
|
iter->pending_method_flags = method_flags;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Probe the bootdev. This does not probe any attached block device,
|
||||||
|
* since they are siblings
|
||||||
|
*/
|
||||||
|
ret = device_probe(dev);
|
||||||
|
log_debug("probe %s %d\n", dev->name, ret);
|
||||||
|
if (ret)
|
||||||
|
return log_msg_ret("probe", ret);
|
||||||
|
bootflow_iter_set_dev(iter, dev, method_flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iter_incr() - Move to the next item (method, part, bootdev)
|
* iter_incr() - Move to the next item (method, part, bootdev)
|
||||||
*
|
*
|
||||||
@@ -195,23 +355,80 @@ static int iter_incr(struct bootflow_iter *iter)
|
|||||||
log_debug("entry: err=%d\n", iter->err);
|
log_debug("entry: err=%d\n", iter->err);
|
||||||
global = iter->doing_global;
|
global = iter->doing_global;
|
||||||
|
|
||||||
if (iter->err == BF_NO_MORE_DEVICES)
|
if (iter->err == BF_NO_MORE_DEVICES) {
|
||||||
|
log_debug("-> err: no more devices1\n");
|
||||||
return BF_NO_MORE_DEVICES;
|
return BF_NO_MORE_DEVICES;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the next boothmethod */
|
/* Get the next boothmethod */
|
||||||
if (++iter->cur_method < iter->num_methods) {
|
for (iter->cur_method++; iter->cur_method < iter->num_methods;
|
||||||
|
iter->cur_method++) {
|
||||||
|
/* loop until we find a global bootmeth we haven't used */
|
||||||
|
if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && iter->doing_global) {
|
||||||
|
if (!bootmeth_glob_allowed(iter, iter->cur_method))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
iter->method = iter->method_order[iter->cur_method];
|
||||||
|
log_debug("-> next global method '%s'\n",
|
||||||
|
iter->method->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* at this point we are only considering non-global bootmeths */
|
||||||
|
if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && iter->have_global &&
|
||||||
|
iter->cur_method >= iter->first_glob_method)
|
||||||
|
break;
|
||||||
|
|
||||||
iter->method = iter->method_order[iter->cur_method];
|
iter->method = iter->method_order[iter->cur_method];
|
||||||
|
log_debug("-> next method '%s'\n", iter->method->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
log_debug("! no more methods: cur_method %d num_methods %d\n",
|
||||||
|
iter->cur_method, iter->num_methods);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have finished scanning the global bootmeths, start the
|
* If we have finished scanning the global bootmeths, start the
|
||||||
* normal bootdev scan
|
* normal bootdev scan
|
||||||
*/
|
*/
|
||||||
if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && global) {
|
if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && global) {
|
||||||
iter->num_methods = iter->first_glob_method;
|
|
||||||
iter->doing_global = false;
|
iter->doing_global = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we've come to the end, so see if we should use a pending
|
||||||
|
* bootdev from when we decided to rescan the global bootmeths
|
||||||
|
*/
|
||||||
|
if (iter->pending_bootdev) {
|
||||||
|
int meth_flags = iter->pending_method_flags;
|
||||||
|
|
||||||
|
dev = iter->pending_bootdev;
|
||||||
|
iter->pending_bootdev = NULL;
|
||||||
|
iter->pending_method_flags = 0;
|
||||||
|
|
||||||
|
ret = prepare_bootdev(iter, dev, meth_flags, false);
|
||||||
|
if (ret)
|
||||||
|
return log_msg_ret("ipb", ret);
|
||||||
|
|
||||||
|
iter->cur_method = 0;
|
||||||
|
iter->method = iter->method_order[iter->cur_method];
|
||||||
|
|
||||||
|
log_debug("-> using pending bootdev '%s' method '%s'\n",
|
||||||
|
dev->name, iter->method->name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if this was the final global bootmeth check, we are done */
|
||||||
|
if (iter->cur_prio == BOOTDEVP_COUNT) {
|
||||||
|
log_debug("-> done global bootmeths\n");
|
||||||
|
|
||||||
|
/* print the same message as bootflow_iter_set_dev() */
|
||||||
|
if ((iter->flags & (BOOTFLOWIF_SHOW |
|
||||||
|
BOOTFLOWIF_SINGLE_DEV)) ==
|
||||||
|
BOOTFLOWIF_SHOW)
|
||||||
|
printf("No more bootdevs\n");
|
||||||
|
return BF_NO_MORE_DEVICES;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't move to the next dev as we haven't tried this
|
* Don't move to the next dev as we haven't tried this
|
||||||
* one yet!
|
* one yet!
|
||||||
@@ -219,8 +436,10 @@ static int iter_incr(struct bootflow_iter *iter)
|
|||||||
inc_dev = false;
|
inc_dev = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iter->flags & BOOTFLOWIF_SINGLE_PARTITION)
|
if (iter->flags & BOOTFLOWIF_SINGLE_PARTITION) {
|
||||||
|
log_debug("-> single partition: no more devices\n");
|
||||||
return BF_NO_MORE_DEVICES;
|
return BF_NO_MORE_DEVICES;
|
||||||
|
}
|
||||||
|
|
||||||
/* No more bootmeths; start at the first one, and... */
|
/* No more bootmeths; start at the first one, and... */
|
||||||
iter->cur_method = 0;
|
iter->cur_method = 0;
|
||||||
@@ -228,11 +447,15 @@ static int iter_incr(struct bootflow_iter *iter)
|
|||||||
|
|
||||||
if (iter->err != BF_NO_MORE_PARTS) {
|
if (iter->err != BF_NO_MORE_PARTS) {
|
||||||
/* ...select next partition */
|
/* ...select next partition */
|
||||||
if (++iter->part <= iter->max_part)
|
if (++iter->part <= iter->max_part) {
|
||||||
|
log_debug("-> next partition %d max %d\n", iter->part,
|
||||||
|
iter->max_part);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No more partitions; start at the first one and... */
|
/* No more partitions; start at the first one and... */
|
||||||
|
log_debug("! no more partitions\n");
|
||||||
iter->part = 0;
|
iter->part = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -313,23 +536,31 @@ static int iter_incr(struct bootflow_iter *iter)
|
|||||||
}
|
}
|
||||||
log_debug("ret=%d, dev=%p %s\n", ret, dev,
|
log_debug("ret=%d, dev=%p %s\n", ret, dev,
|
||||||
dev ? dev->name : "none");
|
dev ? dev->name : "none");
|
||||||
if (ret) {
|
if (ret)
|
||||||
bootflow_iter_set_dev(iter, NULL, 0);
|
bootflow_iter_set_dev(iter, NULL, 0);
|
||||||
} else {
|
else
|
||||||
/*
|
ret = prepare_bootdev(iter, dev, method_flags, true);
|
||||||
* Probe the bootdev. This does not probe any attached
|
}
|
||||||
* block device, since they are siblings
|
|
||||||
*/
|
if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && ret) {
|
||||||
ret = device_probe(dev);
|
log_debug("no more bootdevs, trying global\n");
|
||||||
log_debug("probe %s %d\n", dev->name, ret);
|
|
||||||
if (!log_msg_ret("probe", ret))
|
/* allow global bootmeths with any priority */
|
||||||
bootflow_iter_set_dev(iter, dev, method_flags);
|
iter->cur_prio = BOOTDEVP_COUNT;
|
||||||
|
if (!next_glob_bootmeth(iter)) {
|
||||||
|
log_debug("-> next method '%s'\n", iter->method->name);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if there are no more bootdevs, give up */
|
/* if there are no more bootdevs, give up */
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
log_debug("-> no more bootdevs\n");
|
||||||
return log_msg_ret("incr", BF_NO_MORE_DEVICES);
|
return log_msg_ret("incr", BF_NO_MORE_DEVICES);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("-> bootdev '%s' method '%s'\n", dev->name,
|
||||||
|
iter->method->name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -347,6 +578,7 @@ static int bootflow_check(struct bootflow_iter *iter, struct bootflow *bflow)
|
|||||||
struct udevice *dev;
|
struct udevice *dev;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* handle global bootmeths if needed */
|
||||||
if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && iter->doing_global) {
|
if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && iter->doing_global) {
|
||||||
bootflow_iter_set_dev(iter, NULL, 0);
|
bootflow_iter_set_dev(iter, NULL, 0);
|
||||||
ret = bootmeth_get_bootflow(iter->method, bflow);
|
ret = bootmeth_get_bootflow(iter->method, bflow);
|
||||||
@@ -413,6 +645,10 @@ int bootflow_scan_first(struct udevice *dev, const char *label,
|
|||||||
bootflow_iter_set_dev(iter, dev, method_flags);
|
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);
|
ret = bootflow_check(iter, bflow);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
log_debug("check - ret=%d\n", ret);
|
log_debug("check - ret=%d\n", ret);
|
||||||
@@ -440,6 +676,11 @@ int bootflow_scan_next(struct bootflow_iter *iter, struct bootflow *bflow)
|
|||||||
return log_msg_ret("done", ret);
|
return log_msg_ret("done", ret);
|
||||||
|
|
||||||
if (!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);
|
ret = bootflow_check(iter, bflow);
|
||||||
log_debug("check - ret=%d\n", ret);
|
log_debug("check - ret=%d\n", ret);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
|||||||
@@ -147,8 +147,7 @@ int bootmeth_setup_iter_order(struct bootflow_iter *iter, bool include_global)
|
|||||||
bool is_global;
|
bool is_global;
|
||||||
|
|
||||||
ucp = dev_get_uclass_plat(dev);
|
ucp = dev_get_uclass_plat(dev);
|
||||||
is_global = ucp->flags &
|
is_global = ucp->flags & BOOTMETHF_GLOBAL;
|
||||||
BOOTMETHF_GLOBAL;
|
|
||||||
if (is_global) {
|
if (is_global) {
|
||||||
iter->first_glob_method = i;
|
iter->first_glob_method = i;
|
||||||
break;
|
break;
|
||||||
@@ -193,11 +192,23 @@ int bootmeth_setup_iter_order(struct bootflow_iter *iter, bool include_global)
|
|||||||
if (!count)
|
if (!count)
|
||||||
return log_msg_ret("count2", -ENOENT);
|
return log_msg_ret("count2", -ENOENT);
|
||||||
|
|
||||||
|
/* start with the global bootmeths */
|
||||||
if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && include_global &&
|
if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && include_global &&
|
||||||
iter->first_glob_method != -1 && iter->first_glob_method != count) {
|
iter->first_glob_method != -1 && iter->first_glob_method != count) {
|
||||||
iter->cur_method = iter->first_glob_method;
|
iter->cur_method = iter->first_glob_method;
|
||||||
iter->doing_global = true;
|
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->method_order = order;
|
||||||
iter->num_methods = count;
|
iter->num_methods = count;
|
||||||
|
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ static int bootmeth_efi_mgr_bind(struct udevice *dev)
|
|||||||
|
|
||||||
plat->desc = "EFI bootmgr flow";
|
plat->desc = "EFI bootmgr flow";
|
||||||
plat->flags = BOOTMETHF_GLOBAL;
|
plat->flags = BOOTMETHF_GLOBAL;
|
||||||
|
plat->glob_prio = BOOTDEVP_6_NET_BASE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,68 +18,6 @@
|
|||||||
#include <log.h>
|
#include <log.h>
|
||||||
#include <mapmem.h>
|
#include <mapmem.h>
|
||||||
|
|
||||||
/**
|
|
||||||
* report_bootflow_err() - Report where a bootflow failed
|
|
||||||
*
|
|
||||||
* When a bootflow does not make it to the 'loaded' state, something went wrong.
|
|
||||||
* Print a helpful message if there is an error
|
|
||||||
*
|
|
||||||
* @bflow: Bootflow to process
|
|
||||||
* @err: Error code (0 if none)
|
|
||||||
*/
|
|
||||||
static void report_bootflow_err(struct bootflow *bflow, int err)
|
|
||||||
{
|
|
||||||
if (!err)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Indent out to 'Method' */
|
|
||||||
printf(" ** ");
|
|
||||||
|
|
||||||
switch (bflow->state) {
|
|
||||||
case BOOTFLOWST_BASE:
|
|
||||||
printf("No media/partition found");
|
|
||||||
break;
|
|
||||||
case BOOTFLOWST_MEDIA:
|
|
||||||
printf("No partition found");
|
|
||||||
break;
|
|
||||||
case BOOTFLOWST_PART:
|
|
||||||
printf("No filesystem found");
|
|
||||||
break;
|
|
||||||
case BOOTFLOWST_FS:
|
|
||||||
printf("File not found");
|
|
||||||
break;
|
|
||||||
case BOOTFLOWST_FILE:
|
|
||||||
printf("File cannot be loaded");
|
|
||||||
break;
|
|
||||||
case BOOTFLOWST_READY:
|
|
||||||
printf("Ready");
|
|
||||||
break;
|
|
||||||
case BOOTFLOWST_COUNT:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf(", err=%dE\n", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* show_bootflow() - Show the status of a bootflow
|
|
||||||
*
|
|
||||||
* @seq: Bootflow index
|
|
||||||
* @bflow: Bootflow to show
|
|
||||||
* @errors: True to show the error received, if any
|
|
||||||
*/
|
|
||||||
static void show_bootflow(int index, struct bootflow *bflow, bool errors)
|
|
||||||
{
|
|
||||||
const char *name = bootflow_guess_label(bflow);
|
|
||||||
|
|
||||||
printf("%3x %-11s %-6s %-9.9s %4x %-25.25s %s\n", index,
|
|
||||||
bflow->method ? bflow->method->name : "(none)",
|
|
||||||
bootflow_state_get_name(bflow->state), name, bflow->part,
|
|
||||||
bflow->name, bflow->fname ?: "");
|
|
||||||
if (errors)
|
|
||||||
report_bootflow_err(bflow, bflow->err);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void show_header(void)
|
static void show_header(void)
|
||||||
{
|
{
|
||||||
printf("Seq Method State Uclass Part Name Filename\n");
|
printf("Seq Method State Uclass Part Name Filename\n");
|
||||||
@@ -240,7 +178,7 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||||||
return CMD_RET_FAILURE;
|
return CMD_RET_FAILURE;
|
||||||
}
|
}
|
||||||
if (list)
|
if (list)
|
||||||
show_bootflow(i, &bflow, errors);
|
bootflow_show(i, &bflow, errors);
|
||||||
if (!menu && boot && !bflow.err)
|
if (!menu && boot && !bflow.err)
|
||||||
bootflow_run_boot(&iter, &bflow);
|
bootflow_run_boot(&iter, &bflow);
|
||||||
}
|
}
|
||||||
@@ -298,7 +236,7 @@ static int do_bootflow_list(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||||||
!ret;
|
!ret;
|
||||||
ret = bootdev_next_bootflow(&bflow), i++) {
|
ret = bootdev_next_bootflow(&bflow), i++) {
|
||||||
num_valid += bflow->state == BOOTFLOWST_READY;
|
num_valid += bflow->state == BOOTFLOWST_READY;
|
||||||
show_bootflow(i, bflow, errors);
|
bootflow_show(i, bflow, errors);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("Showing all bootflows\n");
|
printf("Showing all bootflows\n");
|
||||||
@@ -307,7 +245,7 @@ static int do_bootflow_list(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||||||
!ret;
|
!ret;
|
||||||
ret = bootflow_next_glob(&bflow), i++) {
|
ret = bootflow_next_glob(&bflow), i++) {
|
||||||
num_valid += bflow->state == BOOTFLOWST_READY;
|
num_valid += bflow->state == BOOTFLOWST_READY;
|
||||||
show_bootflow(i, bflow, errors);
|
bootflow_show(i, bflow, errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
show_footer(i, num_valid);
|
show_footer(i, num_valid);
|
||||||
|
|||||||
@@ -133,7 +133,8 @@ which scans for available bootflows, optionally listing each find it finds (-l)
|
|||||||
and trying to boot it (-b).
|
and trying to boot it (-b).
|
||||||
|
|
||||||
When global bootmeths are available, these are typically checked before the
|
When global bootmeths are available, these are typically checked before the
|
||||||
above bootdev scanning.
|
above bootdev scanning, but it is possible provide a priority to make them
|
||||||
|
run later, by setting the glob_prio field in the driver's bind() method.
|
||||||
|
|
||||||
|
|
||||||
Controlling ordering
|
Controlling ordering
|
||||||
@@ -614,9 +615,9 @@ simply copied into the iterator. Either way, the `method_order` array it set up,
|
|||||||
along with `num_methods`.
|
along with `num_methods`.
|
||||||
|
|
||||||
Note that global bootmeths are always put at the end of the ordering. If any are
|
Note that global bootmeths are always put at the end of the ordering. If any are
|
||||||
present, `cur_method` is set to the first one, so that global bootmeths are done
|
present, `cur_method` is set to the first one, so that global bootmeths are
|
||||||
first. Once all have been used, these bootmeths are dropped from the iteration.
|
processed first, so long as their priority allows it. Bootstd keeps track of
|
||||||
When there are no global bootmeths, `cur_method` is set to 0.
|
which global bootmeths have been used, to make sure they are only used once.
|
||||||
|
|
||||||
At this point the iterator is ready to use, with the first bootmeth selected.
|
At this point the iterator is ready to use, with the first bootmeth selected.
|
||||||
Most of the other fields are 0. This means that the current partition
|
Most of the other fields are 0. This means that the current partition
|
||||||
@@ -719,6 +720,23 @@ When it sees `BF_NO_MORE_DEVICES` it knows that there is nothing more it can do
|
|||||||
so it should immediately return. The caller of `iter_incr()` is responsible for
|
so it should immediately return. The caller of `iter_incr()` is responsible for
|
||||||
updating the `err` field, based on the return value it sees.
|
updating the `err` field, based on the return value it sees.
|
||||||
|
|
||||||
|
Global bootmeths can have a non-zero priority, which indicates where in the
|
||||||
|
iteration sequence they should run. Each time a new bootdev is produced by a
|
||||||
|
hunter, all of the global bootmeths are first checked to see if they should run
|
||||||
|
before this new bootdev. For example, if the bootdev was produced by a hunter
|
||||||
|
with priority BOOTDEVP_6_NET_BASE, then a quick check is made for global
|
||||||
|
bootmeths with that priority or less. If there are any, they run before the new
|
||||||
|
bootdev is processed.
|
||||||
|
|
||||||
|
Assuming they are enabled and the iteration sequence runs right to the end, all
|
||||||
|
global bootmeths will be used. This is handled by a special case at the end of
|
||||||
|
iter_incr(), where it processes amy so-far-unused global bootmeths.
|
||||||
|
|
||||||
|
Of course if a specific bootmeth ordering is provided, then this overrides the
|
||||||
|
default ordering. Global bootmeths must be listed at the end, reflecting their
|
||||||
|
hybrid nature (they are bootmeths but operate on the system as a whole, not on
|
||||||
|
a particular bootdev).
|
||||||
|
|
||||||
The above describes the iteration process at a high level. It is basically a
|
The above describes the iteration process at a high level. It is basically a
|
||||||
very simple increment function with a checker called `bootflow_check()` that
|
very simple increment function with a checker called `bootflow_check()` that
|
||||||
checks the result of each iteration generated, to determine whether it can
|
checks the result of each iteration generated, to determine whether it can
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <image.h>
|
#include <image.h>
|
||||||
#include <dm/ofnode_decl.h>
|
#include <dm/ofnode_decl.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
#include <linux/build_bug.h>
|
||||||
|
|
||||||
struct bootstd_priv;
|
struct bootstd_priv;
|
||||||
struct expo;
|
struct expo;
|
||||||
@@ -226,6 +227,10 @@ enum bootflow_meth_flags_t {
|
|||||||
BOOTFLOW_METHF_SINGLE_UCLASS = 1 << 3,
|
BOOTFLOW_METHF_SINGLE_UCLASS = 1 << 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BOOTMETH_MAX_COUNT = 32,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct bootflow_iter - state for iterating through bootflows
|
* struct bootflow_iter - state for iterating through bootflows
|
||||||
*
|
*
|
||||||
@@ -263,14 +268,21 @@ enum bootflow_meth_flags_t {
|
|||||||
* @cur_label: Current label being processed
|
* @cur_label: Current label being processed
|
||||||
* @num_methods: Number of bootmeth devices in @method_order
|
* @num_methods: Number of bootmeth devices in @method_order
|
||||||
* @cur_method: Current method number, an index into @method_order
|
* @cur_method: Current method number, an index into @method_order
|
||||||
* @first_glob_method: First global method, if any, else -1
|
* @first_glob_method: Index of first global method within @method_order[], if
|
||||||
|
* any, else -1
|
||||||
* @cur_prio: Current priority being scanned
|
* @cur_prio: Current priority being scanned
|
||||||
* @method_order: List of bootmeth devices to use, in order. The normal methods
|
* @method_order: List of bootmeth devices to use, in order. The normal methods
|
||||||
* appear first, then the global ones, if any
|
* appear first, then the global ones, if any
|
||||||
|
* @have_global: true if we have global bootmeths in @method_order[]
|
||||||
* @doing_global: true if we are iterating through the global bootmeths (which
|
* @doing_global: true if we are iterating through the global bootmeths (which
|
||||||
* happens before the normal ones)
|
* generally happens before the normal ones)
|
||||||
* @method_flags: flags controlling which methods should be used for this @dev
|
* @method_flags: flags controlling which methods should be used for this @dev
|
||||||
* (enum bootflow_meth_flags_t)
|
* (enum bootflow_meth_flags_t)
|
||||||
|
* @methods_done: indicates which methods have been processed, one bit for
|
||||||
|
* each method in @method_order[]
|
||||||
|
* @pending_bootdev: if non-NULL, bootdev which will be used when the global
|
||||||
|
* bootmeths are done
|
||||||
|
* @pending_method_flags: method flags which will be used with @pending_bootdev
|
||||||
*/
|
*/
|
||||||
struct bootflow_iter {
|
struct bootflow_iter {
|
||||||
int flags;
|
int flags;
|
||||||
@@ -290,8 +302,12 @@ struct bootflow_iter {
|
|||||||
int first_glob_method;
|
int first_glob_method;
|
||||||
enum bootdev_prio_t cur_prio;
|
enum bootdev_prio_t cur_prio;
|
||||||
struct udevice **method_order;
|
struct udevice **method_order;
|
||||||
|
bool have_global;
|
||||||
bool doing_global;
|
bool doing_global;
|
||||||
int method_flags;
|
int method_flags;
|
||||||
|
uint methods_done;
|
||||||
|
struct udevice *pending_bootdev;
|
||||||
|
int pending_method_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -739,4 +755,13 @@ int bootflow_menu_poll(struct expo *exp, int *seqp);
|
|||||||
*/
|
*/
|
||||||
const char *bootflow_guess_label(const struct bootflow *bflow);
|
const char *bootflow_guess_label(const struct bootflow *bflow);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bootflow_show() - Show the status of a bootflow
|
||||||
|
*
|
||||||
|
* @seq: Bootflow index
|
||||||
|
* @bflow: Bootflow to show
|
||||||
|
* @errors: True to show the error received, if any
|
||||||
|
*/
|
||||||
|
void bootflow_show(int index, struct bootflow *bflow, bool errors);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -30,10 +30,14 @@ enum bootmeth_flags {
|
|||||||
*
|
*
|
||||||
* @desc: A long description of the bootmeth
|
* @desc: A long description of the bootmeth
|
||||||
* @flags: Flags for this bootmeth (enum bootmeth_flags)
|
* @flags: Flags for this bootmeth (enum bootmeth_flags)
|
||||||
|
* @glob_prio: Priority for this bootmeth. If unset (0) the bootmeth is started
|
||||||
|
* before all other bootmeths. Otherwise it is started before the iteration
|
||||||
|
* reaches the given priority.
|
||||||
*/
|
*/
|
||||||
struct bootmeth_uc_plat {
|
struct bootmeth_uc_plat {
|
||||||
const char *desc;
|
const char *desc;
|
||||||
int flags;
|
int flags;
|
||||||
|
enum bootdev_prio_t glob_prio;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** struct bootmeth_ops - Operations for boot methods */
|
/** struct bootmeth_ops - Operations for boot methods */
|
||||||
|
|||||||
@@ -313,6 +313,10 @@ static int bootflow_iter(struct unit_test_state *uts)
|
|||||||
ut_asserteq(0, iter.max_part);
|
ut_asserteq(0, iter.max_part);
|
||||||
ut_asserteq_str("extlinux", iter.method->name);
|
ut_asserteq_str("extlinux", iter.method->name);
|
||||||
ut_asserteq(0, bflow.err);
|
ut_asserteq(0, bflow.err);
|
||||||
|
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
|
* This shows MEDIA even though there is none, since in
|
||||||
@@ -321,6 +325,7 @@ static int bootflow_iter(struct unit_test_state *uts)
|
|||||||
* know.
|
* know.
|
||||||
*/
|
*/
|
||||||
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
|
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
|
||||||
|
bootflow_free(&bflow);
|
||||||
|
|
||||||
ut_asserteq(-EPROTONOSUPPORT, bootflow_scan_next(&iter, &bflow));
|
ut_asserteq(-EPROTONOSUPPORT, bootflow_scan_next(&iter, &bflow));
|
||||||
ut_asserteq(3, iter.num_methods);
|
ut_asserteq(3, iter.num_methods);
|
||||||
@@ -330,6 +335,7 @@ static int bootflow_iter(struct unit_test_state *uts)
|
|||||||
ut_asserteq_str("efi", iter.method->name);
|
ut_asserteq_str("efi", iter.method->name);
|
||||||
ut_asserteq(0, bflow.err);
|
ut_asserteq(0, bflow.err);
|
||||||
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
|
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
|
||||||
|
ut_asserteq(BIT(0) | BIT(1), iter.methods_done);
|
||||||
bootflow_free(&bflow);
|
bootflow_free(&bflow);
|
||||||
|
|
||||||
/* now the VBE boothmeth */
|
/* now the VBE boothmeth */
|
||||||
@@ -341,6 +347,7 @@ static int bootflow_iter(struct unit_test_state *uts)
|
|||||||
ut_asserteq_str("vbe", iter.method->name);
|
ut_asserteq_str("vbe", iter.method->name);
|
||||||
ut_asserteq(0, bflow.err);
|
ut_asserteq(0, bflow.err);
|
||||||
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
|
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
|
||||||
|
ut_asserteq(BIT(0) | BIT(1) | BIT(2), iter.methods_done);
|
||||||
bootflow_free(&bflow);
|
bootflow_free(&bflow);
|
||||||
|
|
||||||
/* The next device is mmc1.bootdev - at first we use the whole device */
|
/* The next device is mmc1.bootdev - at first we use the whole device */
|
||||||
@@ -352,6 +359,7 @@ static int bootflow_iter(struct unit_test_state *uts)
|
|||||||
ut_asserteq_str("extlinux", iter.method->name);
|
ut_asserteq_str("extlinux", iter.method->name);
|
||||||
ut_asserteq(0, bflow.err);
|
ut_asserteq(0, bflow.err);
|
||||||
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
|
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
|
||||||
|
ut_asserteq(BIT(0) | BIT(1) | BIT(2), iter.methods_done);
|
||||||
bootflow_free(&bflow);
|
bootflow_free(&bflow);
|
||||||
|
|
||||||
ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
|
ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
|
||||||
@@ -362,6 +370,7 @@ static int bootflow_iter(struct unit_test_state *uts)
|
|||||||
ut_asserteq_str("efi", iter.method->name);
|
ut_asserteq_str("efi", iter.method->name);
|
||||||
ut_asserteq(0, bflow.err);
|
ut_asserteq(0, bflow.err);
|
||||||
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
|
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
|
||||||
|
ut_asserteq(BIT(0) | BIT(1) | BIT(2), iter.methods_done);
|
||||||
bootflow_free(&bflow);
|
bootflow_free(&bflow);
|
||||||
|
|
||||||
/* now the VBE boothmeth */
|
/* now the VBE boothmeth */
|
||||||
@@ -373,6 +382,7 @@ static int bootflow_iter(struct unit_test_state *uts)
|
|||||||
ut_asserteq_str("vbe", iter.method->name);
|
ut_asserteq_str("vbe", iter.method->name);
|
||||||
ut_asserteq(0, bflow.err);
|
ut_asserteq(0, bflow.err);
|
||||||
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
|
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
|
||||||
|
ut_asserteq(BIT(0) | BIT(1) | BIT(2), iter.methods_done);
|
||||||
bootflow_free(&bflow);
|
bootflow_free(&bflow);
|
||||||
|
|
||||||
/* Then move to partition 1 where we find something */
|
/* Then move to partition 1 where we find something */
|
||||||
@@ -415,6 +425,7 @@ static int bootflow_iter(struct unit_test_state *uts)
|
|||||||
ut_asserteq_str("extlinux", iter.method->name);
|
ut_asserteq_str("extlinux", iter.method->name);
|
||||||
ut_asserteq(0, bflow.err);
|
ut_asserteq(0, bflow.err);
|
||||||
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
|
ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
|
||||||
|
ut_asserteq(BIT(0) | BIT(1) | BIT(2), iter.methods_done);
|
||||||
bootflow_free(&bflow);
|
bootflow_free(&bflow);
|
||||||
|
|
||||||
bootflow_iter_uninit(&iter);
|
bootflow_iter_uninit(&iter);
|
||||||
@@ -426,6 +437,51 @@ static int bootflow_iter(struct unit_test_state *uts)
|
|||||||
BOOTSTD_TEST(bootflow_iter, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
|
BOOTSTD_TEST(bootflow_iter, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
|
||||||
|
|
||||||
#if defined(CONFIG_SANDBOX) && defined(CONFIG_BOOTMETH_GLOBAL)
|
#if defined(CONFIG_SANDBOX) && defined(CONFIG_BOOTMETH_GLOBAL)
|
||||||
|
|
||||||
|
/* Check iterating through available bootflows to test global bootmeths */
|
||||||
|
static int bootflow_iter_glob(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct bootflow_iter iter;
|
||||||
|
struct bootflow bflow;
|
||||||
|
|
||||||
|
bootstd_clear_glob();
|
||||||
|
|
||||||
|
/* we should get the global bootmeth initially */
|
||||||
|
ut_asserteq(-EINVAL,
|
||||||
|
bootflow_scan_first(NULL, NULL, &iter, BOOTFLOWIF_ALL |
|
||||||
|
BOOTFLOWIF_SHOW, &bflow));
|
||||||
|
bootflow_show(0, &bflow, true);
|
||||||
|
ut_asserteq(4, iter.num_methods);
|
||||||
|
ut_assert(iter.doing_global);
|
||||||
|
ut_assert(iter.have_global);
|
||||||
|
ut_asserteq(3, iter.first_glob_method);
|
||||||
|
|
||||||
|
ut_asserteq(3, iter.cur_method);
|
||||||
|
ut_asserteq(0, iter.part);
|
||||||
|
ut_asserteq(0, iter.max_part);
|
||||||
|
ut_asserteq_str("firmware0", iter.method->name);
|
||||||
|
ut_asserteq(0, bflow.err);
|
||||||
|
bootflow_free(&bflow);
|
||||||
|
|
||||||
|
/* next we should get the first non-global bootmeth */
|
||||||
|
ut_asserteq(-EPROTONOSUPPORT, bootflow_scan_next(&iter, &bflow));
|
||||||
|
|
||||||
|
/* at this point the global bootmeths are stranded above num_methods */
|
||||||
|
ut_asserteq(4, iter.num_methods);
|
||||||
|
ut_asserteq(3, iter.first_glob_method);
|
||||||
|
ut_assert(!iter.doing_global);
|
||||||
|
ut_assert(iter.have_global);
|
||||||
|
|
||||||
|
ut_asserteq(0, iter.cur_method);
|
||||||
|
ut_asserteq(0, iter.part);
|
||||||
|
ut_asserteq(0, iter.max_part);
|
||||||
|
ut_asserteq_str("extlinux", iter.method->name);
|
||||||
|
ut_asserteq(0, bflow.err);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
BOOTSTD_TEST(bootflow_iter_glob, UTF_DM | UTF_SCAN_FDT);
|
||||||
|
|
||||||
/* Check using the system bootdev */
|
/* Check using the system bootdev */
|
||||||
static int bootflow_system(struct unit_test_state *uts)
|
static int bootflow_system(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
@@ -439,11 +495,11 @@ static int bootflow_system(struct unit_test_state *uts)
|
|||||||
ut_assertok(device_probe(dev));
|
ut_assertok(device_probe(dev));
|
||||||
sandbox_set_fake_efi_mgr_dev(dev, true);
|
sandbox_set_fake_efi_mgr_dev(dev, true);
|
||||||
|
|
||||||
/* We should get a single 'bootmgr' method right at the end */
|
/* We should get a single 'bootmgr' method at the end */
|
||||||
bootstd_clear_glob();
|
bootstd_clear_glob();
|
||||||
ut_assertok(run_command("bootflow scan -lH", 0));
|
ut_assertok(run_command("bootflow scan -lH", 0));
|
||||||
ut_assert_skip_to_line(
|
ut_assert_skip_to_line(
|
||||||
" 0 efi_mgr ready (none) 0 <NULL> ");
|
" 1 efi_mgr ready (none) 0 <NULL> ");
|
||||||
ut_assert_skip_to_line("No more bootdevs");
|
ut_assert_skip_to_line("No more bootdevs");
|
||||||
ut_assert_skip_to_line("(2 bootflows, 2 valid)");
|
ut_assert_skip_to_line("(2 bootflows, 2 valid)");
|
||||||
ut_assert_console_end();
|
ut_assert_console_end();
|
||||||
@@ -476,7 +532,12 @@ static int bootflow_iter_disable(struct unit_test_state *uts)
|
|||||||
/* Try to boot the bootmgr flow, which will fail */
|
/* Try to boot the bootmgr flow, which will fail */
|
||||||
console_record_reset_enable();
|
console_record_reset_enable();
|
||||||
ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
|
ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
|
||||||
ut_asserteq(4, iter.num_methods);
|
|
||||||
|
/* at this point the global bootmeths are stranded above num_methods */
|
||||||
|
ut_asserteq(5, iter.num_methods);
|
||||||
|
ut_assert(!iter.doing_global);
|
||||||
|
ut_assert(iter.have_global);
|
||||||
|
ut_asserteq(4, iter.first_glob_method);
|
||||||
ut_asserteq_str("sandbox", iter.method->name);
|
ut_asserteq_str("sandbox", iter.method->name);
|
||||||
ut_assertok(inject_response(uts));
|
ut_assertok(inject_response(uts));
|
||||||
ut_asserteq(-ENOTSUPP, bootflow_run_boot(&iter, &bflow));
|
ut_asserteq(-ENOTSUPP, bootflow_run_boot(&iter, &bflow));
|
||||||
@@ -485,10 +546,14 @@ static int bootflow_iter_disable(struct unit_test_state *uts)
|
|||||||
ut_assert_console_end();
|
ut_assert_console_end();
|
||||||
|
|
||||||
/* Check that the sandbox bootmeth has been removed */
|
/* Check that the sandbox bootmeth has been removed */
|
||||||
ut_asserteq(3, iter.num_methods);
|
ut_asserteq(4, iter.num_methods);
|
||||||
|
|
||||||
for (i = 0; i < iter.num_methods; i++)
|
for (i = 0; i < iter.num_methods; i++)
|
||||||
ut_assert(strcmp("sandbox", iter.method_order[i]->name));
|
ut_assert(strcmp("sandbox", iter.method_order[i]->name));
|
||||||
|
|
||||||
|
/* the first global bootmeth is now down one place in the list */
|
||||||
|
ut_asserteq(3, iter.first_glob_method);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
BOOTSTD_TEST(bootflow_iter_disable, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
|
BOOTSTD_TEST(bootflow_iter_disable, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
|
||||||
|
|||||||
Reference in New Issue
Block a user