diff options
Diffstat (limited to 'boot/bootmeth-uclass.c')
-rw-r--r-- | boot/bootmeth-uclass.c | 105 |
1 files changed, 83 insertions, 22 deletions
diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c index c040d5f92b2..2d7652edeab 100644 --- a/boot/bootmeth-uclass.c +++ b/boot/bootmeth-uclass.c @@ -20,6 +20,16 @@ DECLARE_GLOBAL_DATA_PTR; +int bootmeth_get_state_desc(struct udevice *dev, char *buf, int maxsize) +{ + const struct bootmeth_ops *ops = bootmeth_get_ops(dev); + + if (!ops->get_state_desc) + return -ENOSYS; + + return ops->get_state_desc(dev, buf, maxsize); +} + int bootmeth_check(struct udevice *dev, struct bootflow_iter *iter) { const struct bootmeth_ops *ops = bootmeth_get_ops(dev); @@ -61,18 +71,21 @@ int bootmeth_read_file(struct udevice *dev, struct bootflow *bflow, return ops->read_file(dev, bflow, file_path, addr, sizep); } -/** - * bootmeth_setup_iter_order() - Set up the ordering of bootmeths to scan - * - * This sets up the ordering information in @iter, based on the selected - * ordering of the bootmethds in bootstd_priv->bootmeth_order. If there is no - * ordering there, then all bootmethods are added - * - * @iter: Iterator to update with the order - * Return: 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve - * on other error - */ -int bootmeth_setup_iter_order(struct bootflow_iter *iter) +int bootmeth_get_bootflow(struct udevice *dev, struct bootflow *bflow) +{ + const struct bootmeth_ops *ops = bootmeth_get_ops(dev); + + if (!ops->read_bootflow) + return -ENOSYS; + memset(bflow, '\0', sizeof(*bflow)); + bflow->dev = NULL; + bflow->method = dev; + bflow->state = BOOTFLOWST_BASE; + + return ops->read_bootflow(dev, bflow); +} + +int bootmeth_setup_iter_order(struct bootflow_iter *iter, bool include_global) { struct bootstd_priv *std; struct udevice **order; @@ -95,29 +108,77 @@ int bootmeth_setup_iter_order(struct bootflow_iter *iter) /* If we have an ordering, copy it */ if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && std->bootmeth_count) { + int i; + + /* + * We don't support skipping global bootmeths. Instead, the user + * should omit them from the ordering + */ + if (!include_global) + return log_msg_ret("glob", -EPERM); memcpy(order, std->bootmeth_order, count * sizeof(struct bootmeth *)); + + if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL)) { + for (i = 0; i < count; i++) { + struct udevice *dev = order[i]; + struct bootmeth_uc_plat *ucp; + bool is_global; + + ucp = dev_get_uclass_plat(dev); + is_global = ucp->flags & + BOOTMETHF_GLOBAL; + if (is_global) { + iter->first_glob_method = i; + break; + } + } + } } else { struct udevice *dev; - int i, upto; + int i, upto, pass; /* - * Get a list of bootmethods, in seq order (i.e. using aliases). - * There may be gaps so try to count up high enough to find them - * all. + * Do two passes, one to find the normal bootmeths and another + * to find the global ones, if required, The global ones go at + * the end. */ - for (i = 0, upto = 0; upto < count && i < 20 + count * 2; i++) { - ret = uclass_get_device_by_seq(UCLASS_BOOTMETH, i, - &dev); - if (!ret) - order[upto++] = dev; + for (pass = 0, upto = 0; pass < 1 + include_global; pass++) { + if (pass) + iter->first_glob_method = upto; + /* + * Get a list of bootmethods, in seq order (i.e. using + * aliases). There may be gaps so try to count up high + * enough to find them all. + */ + for (i = 0; upto < count && i < 20 + count * 2; i++) { + struct bootmeth_uc_plat *ucp; + bool is_global; + + ret = uclass_get_device_by_seq(UCLASS_BOOTMETH, + i, &dev); + if (ret) + continue; + ucp = dev_get_uclass_plat(dev); + is_global = + IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && + (ucp->flags & BOOTMETHF_GLOBAL); + if (pass ? is_global : !is_global) + order[upto++] = dev; + } } count = upto; } + if (!count) + return log_msg_ret("count2", -ENOENT); + if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && include_global && + iter->first_glob_method != -1 && iter->first_glob_method != count) { + iter->cur_method = iter->first_glob_method; + iter->doing_global = true; + } iter->method_order = order; iter->num_methods = count; - iter->cur_method = 0; return 0; } |