diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c index 26b003427ec..81adfb4cfb7 100644 --- a/boot/bootdev-uclass.c +++ b/boot/bootdev-uclass.c @@ -32,30 +32,57 @@ enum { BOOT_TARGETS_MAX_LEN = 100, }; +struct bootflow *bootdev_next_bootflow_(struct bootstd_priv *std, + struct udevice *dev, + struct bootflow *prev) +{ + struct bootflow *bflow = prev; + + if (bflow) { + if (list_is_last(&bflow->glob_node, &std->glob_head)) + return NULL; + bflow = list_entry(bflow->glob_node.next, struct bootflow, + glob_node); + } else { + if (list_empty(&std->glob_head)) + return NULL; + + bflow = list_first_entry(&std->glob_head, struct bootflow, + glob_node); + } + + while (bflow->dev != dev) { + if (list_is_last(&bflow->glob_node, &std->glob_head)) + return NULL; + bflow = list_entry(bflow->glob_node.next, struct bootflow, + glob_node); + } + + return bflow; +} + int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp) { - struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + struct bootstd_priv *std = bootstd_try_priv(); + struct bootflow *bflow; - if (list_empty(&ucp->bootflow_head)) + bflow = bootdev_next_bootflow_(std, dev, NULL); + if (!bflow) return -ENOENT; - - *bflowp = list_first_entry(&ucp->bootflow_head, struct bootflow, - bm_node); + *bflowp = bflow; return 0; } int bootdev_next_bootflow(struct bootflow **bflowp) { - struct bootflow *bflow = *bflowp; - struct bootdev_uc_plat *ucp = dev_get_uclass_plat(bflow->dev); + struct bootstd_priv *std = bootstd_try_priv(); + struct bootflow *bflow; - *bflowp = NULL; - - if (list_is_last(&bflow->bm_node, &ucp->bootflow_head)) + bflow = bootdev_next_bootflow_(std, (*bflowp)->dev, *bflowp); + if (!bflow) return -ENOENT; - - *bflowp = list_entry(bflow->bm_node.next, struct bootflow, bm_node); + *bflowp = bflow; return 0; } @@ -911,15 +938,6 @@ void bootdev_list_hunters(struct bootstd_priv *std) printf("(total hunters: %d)\n", n_ent); } -static int bootdev_post_bind(struct udevice *dev) -{ - struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); - - INIT_LIST_HEAD(&ucp->bootflow_head); - - return 0; -} - static int bootdev_pre_unbind(struct udevice *dev) { int ret; @@ -936,6 +954,5 @@ UCLASS_DRIVER(bootdev) = { .name = "bootdev", .flags = DM_UC_FLAG_SEQ_ALIAS, .per_device_plat_auto = sizeof(struct bootdev_uc_plat), - .post_bind = bootdev_post_bind, .pre_unbind = bootdev_pre_unbind, }; diff --git a/boot/bootflow.c b/boot/bootflow.c index d8807eb109d..804809dc100 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -476,8 +476,6 @@ void bootflow_free(struct bootflow *bflow) void bootflow_remove(struct bootflow *bflow) { - if (bflow->dev) - list_del(&bflow->bm_node); list_del(&bflow->glob_node); bootflow_free(bflow); diff --git a/boot/bootstd-uclass.c b/boot/bootstd-uclass.c index b2f80808c85..91e90bdf43c 100644 --- a/boot/bootstd-uclass.c +++ b/boot/bootstd-uclass.c @@ -77,25 +77,22 @@ int bootstd_add_bootflow(struct bootflow *bflow) memcpy(new, bflow, sizeof(*bflow)); list_add_tail(&new->glob_node, &std->glob_head); - if (bflow->dev) { - struct bootdev_uc_plat *ucp = dev_get_uclass_plat(bflow->dev); - - list_add_tail(&new->bm_node, &ucp->bootflow_head); - } return 0; } int bootstd_clear_bootflows_for_bootdev(struct udevice *dev) { - struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + struct bootstd_priv *std = bootstd_try_priv(); - while (!list_empty(&ucp->bootflow_head)) { + if (std) { struct bootflow *bflow; + struct list_head *pos; - bflow = list_first_entry(&ucp->bootflow_head, struct bootflow, - bm_node); - bootflow_remove(bflow); + list_for_each(pos, &std->glob_head) { + bflow = list_entry(pos, struct bootflow, glob_node); + bootflow_remove(bflow); + } } return 0; diff --git a/include/bootdev.h b/include/bootdev.h index f9cae2fd1fd..991b6229c1c 100644 --- a/include/bootdev.h +++ b/include/bootdev.h @@ -109,11 +109,9 @@ struct bootdev_hunter { * This is attached to each device in the bootdev uclass and accessible via * dev_get_uclass_plat(dev) * - * @bootflows: List of available bootflows for this bootdev * @piro: Priority of this bootdev */ struct bootdev_uc_plat { - struct list_head bootflow_head; enum bootdev_prio_t prio; }; diff --git a/include/bootflow.h b/include/bootflow.h index 4d2fc7b69b5..64d1d6c3786 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -56,12 +56,10 @@ enum bootflow_flags_t { /** * struct bootflow - information about a bootflow * - * This is connected into two separate linked lists: + * This is connected into a linked list: * - * bm_sibling - links all bootflows in the same bootdev * glob_sibling - links all bootflows in all bootdevs * - * @bm_node: Points to siblings in the same bootdev * @glob_node: Points to siblings in the global list (all bootdev) * @dev: Bootdev device which produced this bootflow, NULL for flows created by * BOOTMETHF_GLOBAL bootmeths @@ -92,7 +90,6 @@ enum bootflow_flags_t { * @bootmeth_priv: Private data for the bootmeth */ struct bootflow { - struct list_head bm_node; struct list_head glob_node; struct udevice *dev; struct udevice *blk; diff --git a/include/bootstd.h b/include/bootstd.h index 4535d91e2ad..8aff536e3cb 100644 --- a/include/bootstd.h +++ b/include/bootstd.h @@ -123,7 +123,7 @@ void bootstd_clear_glob(void); int bootstd_prog_boot(void); /** - * bootstd_add_bootflow() - Add a bootflow to the bootdev's and global list + * bootstd_add_bootflow() - Add a bootflow to the global list * * All fields in @bflow must be set up. Note that @bflow->dev is used to add the * bootflow to that device.