diff options
Diffstat (limited to 'boot/bootflow.c')
-rw-r--r-- | boot/bootflow.c | 63 |
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); |