bootstd: Move the bootflow list into an alist
Use an alist for this data structure as it is somewhat simpler to
manage. This means that bootstd holds a simple list of bootflow structs
and can drop it at will, without chasing down lists.
Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index 81adfb4..a4e1d79 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -32,41 +32,17 @@
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 bootstd_priv *std = bootstd_try_priv();
+ struct bootstd_priv *std;
struct bootflow *bflow;
+ int ret;
- bflow = bootdev_next_bootflow_(std, dev, NULL);
+ ret = bootstd_get_priv(&std);
+ if (ret)
+ return log_msg_ret("bff", ret);
+
+ bflow = alist_getw(&std->bootflows, 0, struct bootflow);
if (!bflow)
return -ENOENT;
*bflowp = bflow;
@@ -76,10 +52,15 @@
int bootdev_next_bootflow(struct bootflow **bflowp)
{
- struct bootstd_priv *std = bootstd_try_priv();
+ struct bootstd_priv *std;
struct bootflow *bflow;
+ int ret;
+
+ ret = bootstd_get_priv(&std);
+ if (ret)
+ return log_msg_ret("bff", ret);
- bflow = bootdev_next_bootflow_(std, (*bflowp)->dev, *bflowp);
+ bflow = alist_nextw(&std->bootflows, *bflowp);
if (!bflow)
return -ENOENT;
*bflowp = bflow;
diff --git a/boot/bootflow.c b/boot/bootflow.c
index 804809d..7ce04fd 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -55,11 +55,10 @@
if (ret)
return ret;
- if (list_empty(&std->glob_head))
+ if (!std->bootflows.count)
return -ENOENT;
- *bflowp = list_first_entry(&std->glob_head, struct bootflow,
- glob_node);
+ *bflowp = alist_getw(&std->bootflows, 0, struct bootflow);
return 0;
}
@@ -67,20 +66,16 @@
int bootflow_next_glob(struct bootflow **bflowp)
{
struct bootstd_priv *std;
- struct bootflow *bflow = *bflowp;
int ret;
ret = bootstd_get_priv(&std);
if (ret)
return ret;
- *bflowp = NULL;
-
- if (list_is_last(&bflow->glob_node, &std->glob_head))
+ *bflowp = alist_nextw(&std->bootflows, *bflowp);
+ if (!*bflowp)
return -ENOENT;
- *bflowp = list_entry(bflow->glob_node.next, struct bootflow, glob_node);
-
return 0;
}
@@ -476,10 +471,7 @@
void bootflow_remove(struct bootflow *bflow)
{
- list_del(&bflow->glob_node);
-
bootflow_free(bflow);
- free(bflow);
}
#if CONFIG_IS_ENABLED(BOOTSTD_FULL)
diff --git a/boot/bootstd-uclass.c b/boot/bootstd-uclass.c
index 91e90bd..8c0fd4e 100644
--- a/boot/bootstd-uclass.c
+++ b/boot/bootstd-uclass.c
@@ -6,6 +6,7 @@
* Written by Simon Glass <sjg@chromium.org>
*/
+#include <alist.h>
#include <bootflow.h>
#include <bootstd.h>
#include <dm.h>
@@ -42,13 +43,11 @@
static void bootstd_clear_glob_(struct bootstd_priv *priv)
{
- while (!list_empty(&priv->glob_head)) {
- struct bootflow *bflow;
+ struct bootflow *bflow;
- bflow = list_first_entry(&priv->glob_head, struct bootflow,
- glob_node);
+ alist_for_each(bflow, &priv->bootflows)
bootflow_remove(bflow);
- }
+ alist_empty(&priv->bootflows);
}
void bootstd_clear_glob(void)
@@ -64,36 +63,37 @@
int bootstd_add_bootflow(struct bootflow *bflow)
{
struct bootstd_priv *std;
- struct bootflow *new;
int ret;
ret = bootstd_get_priv(&std);
if (ret)
return ret;
- new = malloc(sizeof(*bflow));
- if (!new)
- return log_msg_ret("bflow", -ENOMEM);
- memcpy(new, bflow, sizeof(*bflow));
-
- list_add_tail(&new->glob_node, &std->glob_head);
+ ret = std->bootflows.count;
+ bflow = alist_add(&std->bootflows, *bflow);
+ if (!bflow)
+ return log_msg_ret("bf2", -ENOMEM);
- return 0;
+ return ret;
}
int bootstd_clear_bootflows_for_bootdev(struct udevice *dev)
{
struct bootstd_priv *std = bootstd_try_priv();
+ struct bootflow *from, *to;
- if (std) {
- struct bootflow *bflow;
- struct list_head *pos;
+ /* if bootstd does not exist we cannot have any bootflows */
+ if (!std)
+ return 0;
- list_for_each(pos, &std->glob_head) {
- bflow = list_entry(pos, struct bootflow, glob_node);
- bootflow_remove(bflow);
- }
+ /* Drop any bootflows that mention this dev */
+ alist_for_each_filter(from, to, &std->bootflows) {
+ if (from->dev == dev)
+ bootflow_remove(from);
+ else
+ *to++ = *from;
}
+ alist_update_end(&std->bootflows, to);
return 0;
}
@@ -165,7 +165,7 @@
{
struct bootstd_priv *std = dev_get_priv(dev);
- INIT_LIST_HEAD(&std->glob_head);
+ alist_init_struct(&std->bootflows, struct bootflow);
return 0;
}