summaryrefslogtreecommitdiff
path: root/boot/bootflow.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2022-08-12 12:51:14 -0400
committerTom Rini <trini@konsulko.com>2022-08-12 12:51:14 -0400
commit6fc212779c990ff27a430e370bfb8fac01ddde7f (patch)
tree32ecaafa1d653e275683cfacac41dd2bb57efca1 /boot/bootflow.c
parentf5003e0791dbe796bf7b41515d67ae5527679ec9 (diff)
parent5fe76d460d857b00d582d7cd6cea9ac740ea912b (diff)
Merge branch '2022-08-11-verified-boot-for-embedded-initial-support'
To quote Simon: This adds the concept of a VBE method to U-Boot, along with an implementation of the 'VBE simple' method, basically a simple way of updating firmware in MMC from userspace and monitoring it from U-Boot. VBE simple is implemented in fwupd. U-Boot's role is to set up the device tree with the required firmware-update properties and provide the developer with information about the current VBE state. To that end this series includes a new 'vbe' command that allows VBE methods to be listed and examined. As part of this work, support for doing FDT fixups via the event interface is provided, along with the ability to write to the device tree via the ofnode interface. Another (significant) change is that bootmeths now have a 'global' flag, to allow the implementation of EFI bootmgr (and VBE) to be cleaned up. The 'system' bootdev is no-longer needed and these bootmeths are scanned first. Further work is needed to pull everything together, but this is a step along the way.
Diffstat (limited to 'boot/bootflow.c')
-rw-r--r--boot/bootflow.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/boot/bootflow.c b/boot/bootflow.c
index 24ba3c34660..5d94a27ff84 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -86,6 +86,7 @@ int bootflow_next_glob(struct bootflow **bflowp)
void bootflow_iter_init(struct bootflow_iter *iter, int flags)
{
memset(iter, '\0', sizeof(*iter));
+ iter->first_glob_method = -1;
iter->flags = flags;
}
@@ -115,11 +116,17 @@ int bootflow_iter_drop_bootmeth(struct bootflow_iter *iter,
static void bootflow_iter_set_dev(struct bootflow_iter *iter,
struct udevice *dev)
{
+ struct bootmeth_uc_plat *ucp = dev_get_uclass_plat(iter->method);
+
iter->dev = dev;
if ((iter->flags & (BOOTFLOWF_SHOW | BOOTFLOWF_SINGLE_DEV)) ==
BOOTFLOWF_SHOW) {
if (dev)
printf("Scanning bootdev '%s':\n", dev->name);
+ else if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) &&
+ ucp->flags & BOOTMETHF_GLOBAL)
+ printf("Scanning global bootmeth '%s':\n",
+ iter->method->name);
else
printf("No more bootdevs\n");
}
@@ -133,8 +140,12 @@ static void bootflow_iter_set_dev(struct bootflow_iter *iter,
static int iter_incr(struct bootflow_iter *iter)
{
struct udevice *dev;
+ bool inc_dev = true;
+ bool global;
int ret;
+ global = iter->doing_global;
+
if (iter->err == BF_NO_MORE_DEVICES)
return BF_NO_MORE_DEVICES;
@@ -144,6 +155,21 @@ static int iter_incr(struct bootflow_iter *iter)
iter->method = iter->method_order[iter->cur_method];
return 0;
}
+
+ /*
+ * If we have finished scanning the global bootmeths, start the
+ * normal bootdev scan
+ */
+ if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && global) {
+ iter->num_methods = iter->first_glob_method;
+ iter->doing_global = false;
+
+ /*
+ * Don't move to the next dev as we haven't tried this
+ * one yet!
+ */
+ inc_dev = false;
+ }
}
/* No more bootmeths; start at the first one, and... */
@@ -169,14 +195,18 @@ static int iter_incr(struct bootflow_iter *iter)
/* ...select next bootdev */
if (iter->flags & BOOTFLOWF_SINGLE_DEV) {
ret = -ENOENT;
- } else if (++iter->cur_dev == iter->num_devs) {
- ret = -ENOENT;
- bootflow_iter_set_dev(iter, NULL);
} else {
- dev = iter->dev_order[iter->cur_dev];
- ret = device_probe(dev);
- if (!log_msg_ret("probe", ret))
- bootflow_iter_set_dev(iter, dev);
+ if (inc_dev)
+ iter->cur_dev++;
+ if (iter->cur_dev == iter->num_devs) {
+ ret = -ENOENT;
+ bootflow_iter_set_dev(iter, NULL);
+ } else {
+ dev = iter->dev_order[iter->cur_dev];
+ ret = device_probe(dev);
+ if (!log_msg_ret("probe", ret))
+ bootflow_iter_set_dev(iter, dev);
+ }
}
/* if there are no more bootdevs, give up */
@@ -199,6 +229,15 @@ static int bootflow_check(struct bootflow_iter *iter, struct bootflow *bflow)
struct udevice *dev;
int ret;
+ if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && iter->doing_global) {
+ bootflow_iter_set_dev(iter, NULL);
+ ret = bootmeth_get_bootflow(iter->method, bflow);
+ if (ret)
+ return log_msg_ret("glob", ret);
+
+ return 0;
+ }
+
dev = iter->dev;
ret = bootdev_get_bootflow(dev, iter, bflow);
@@ -231,19 +270,22 @@ int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter,
{
int ret;
+ if (dev)
+ flags |= BOOTFLOWF_SKIP_GLOBAL;
bootflow_iter_init(iter, flags);
ret = bootdev_setup_iter_order(iter, &dev);
if (ret)
return log_msg_ret("obdev", -ENODEV);
- bootflow_iter_set_dev(iter, dev);
- ret = bootmeth_setup_iter_order(iter);
+ ret = bootmeth_setup_iter_order(iter, !(flags & BOOTFLOWF_SKIP_GLOBAL));
if (ret)
return log_msg_ret("obmeth", -ENODEV);
/* Find the first bootmeth (there must be at least one!) */
iter->method = iter->method_order[iter->cur_method];
+ if (!IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) || !iter->doing_global)
+ bootflow_iter_set_dev(iter, dev);
ret = bootflow_check(iter, bflow);
if (ret) {
@@ -307,7 +349,8 @@ void bootflow_free(struct bootflow *bflow)
void bootflow_remove(struct bootflow *bflow)
{
- list_del(&bflow->bm_node);
+ if (bflow->dev)
+ list_del(&bflow->bm_node);
list_del(&bflow->glob_node);
bootflow_free(bflow);