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);
-
- *bflowp = NULL;
+ struct bootstd_priv *std = bootstd_try_priv();
+ struct bootflow *bflow;
- 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;
}
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;
.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,
};
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;
/**
* 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
* @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;