Skip to content

Commit

Permalink
bootstd: Move the bootflow list into an alist
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
sjg20 authored and trini committed Jan 15, 2025
1 parent 6a3eb84 commit 49867e8
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 77 deletions.
47 changes: 14 additions & 33 deletions boot/bootdev-uclass.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,41 +32,17 @@ 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 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, dev, NULL);
bflow = alist_getw(&std->bootflows, 0, struct bootflow);
if (!bflow)
return -ENOENT;
*bflowp = bflow;
Expand All @@ -76,10 +52,15 @@ int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp)

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;
Expand Down
16 changes: 4 additions & 12 deletions boot/bootflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,32 +55,27 @@ int bootflow_first_glob(struct bootflow **bflowp)
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;
}

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;
}

Expand Down Expand Up @@ -476,10 +471,7 @@ void bootflow_free(struct bootflow *bflow)

void bootflow_remove(struct bootflow *bflow)
{
list_del(&bflow->glob_node);

bootflow_free(bflow);
free(bflow);
}

#if CONFIG_IS_ENABLED(BOOTSTD_FULL)
Expand Down
42 changes: 21 additions & 21 deletions boot/bootstd-uclass.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* Written by Simon Glass <[email protected]>
*/

#include <alist.h>
#include <bootflow.h>
#include <bootstd.h>
#include <dm.h>
Expand Down Expand Up @@ -42,13 +43,11 @@ static int bootstd_of_to_plat(struct udevice *dev)

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)
Expand All @@ -64,36 +63,37 @@ void bootstd_clear_glob(void)
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;
}
Expand Down Expand Up @@ -165,7 +165,7 @@ static int bootstd_probe(struct udevice *dev)
{
struct bootstd_priv *std = dev_get_priv(dev);

INIT_LIST_HEAD(&std->glob_head);
alist_init_struct(&std->bootflows, struct bootflow);

return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/bootdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ static int do_bootdev_info(struct cmd_tbl *cmdtp, int flag, int argc,

dev = priv->cur_bootdev;

/* Count the number of bootflows, including how many are valid*/
/* Count the number of bootflows, including how many are valid */
num_valid = 0;
for (ret = bootdev_first_bootflow(dev, &bflow), i = 0;
!ret;
Expand Down
2 changes: 1 addition & 1 deletion cmd/bootflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
if (!ret)
num_valid++;
ret = bootstd_add_bootflow(&bflow);
if (ret) {
if (ret < 0) {
printf("Out of memory\n");
return CMD_RET_FAILURE;
}
Expand Down
11 changes: 5 additions & 6 deletions include/bootflow.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,8 @@ enum bootflow_flags_t {
/**
* struct bootflow - information about a bootflow
*
* This is connected into a linked list:
* All bootflows are listed in bootstd's bootflow alist in struct bootstd_priv
*
* glob_sibling - links all bootflows in all bootdevs
*
* @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
* @blk: Block device which contains this bootflow, NULL if this is a network
Expand Down Expand Up @@ -90,7 +87,6 @@ enum bootflow_flags_t {
* @bootmeth_priv: Private data for the bootmeth
*/
struct bootflow {
struct list_head glob_node;
struct udevice *dev;
struct udevice *blk;
int part;
Expand Down Expand Up @@ -390,7 +386,10 @@ const char *bootflow_state_get_name(enum bootflow_state_t state);
/**
* bootflow_remove() - Remove a bootflow and free its memory
*
* This updates the linked lists containing the bootflow then frees it.
* This updates the 'global' linked list containing the bootflow, then frees it.
* It does not remove it from bootflows alist in struct bootstd_priv
*
* This does not free bflow itself, since this is assumed to be in an alist
*
* @bflow: Bootflow to remove
*/
Expand Down
8 changes: 5 additions & 3 deletions include/bootstd.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef __bootstd_h
#define __bootstd_h

#include <alist.h>
#include <dm/ofnode_decl.h>
#include <linux/list.h>
#include <linux/types.h>
Expand All @@ -30,7 +31,8 @@ struct udevice;
* terminated)
* @cur_bootdev: Currently selected bootdev (for commands)
* @cur_bootflow: Currently selected bootflow (for commands)
* @glob_head: Head for the global list of all bootflows across all bootdevs
* @bootflows: (struct bootflow) Global list of all bootflows across all
* bootdevs
* @bootmeth_count: Number of bootmeth devices in @bootmeth_order
* @bootmeth_order: List of bootmeth devices to use, in order, NULL-terminated
* @vbe_bootmeth: Currently selected VBE bootmeth, NULL if none
Expand All @@ -44,7 +46,7 @@ struct bootstd_priv {
const char **env_order;
struct udevice *cur_bootdev;
struct bootflow *cur_bootflow;
struct list_head glob_head;
struct alist bootflows;
int bootmeth_count;
struct udevice **bootmeth_order;
struct udevice *vbe_bootmeth;
Expand Down Expand Up @@ -135,7 +137,7 @@ int bootstd_prog_boot(void);
* since this function takes over ownership of these. This functions makes
* a copy of @bflow itself (without allocating its fields again), so the
* caller must dispose of the memory used by the @bflow pointer itself
* Return: 0 if OK, -ENOMEM if out of memory
* Return: element number in the list, if OK, -ENOMEM if out of memory
*/
int bootstd_add_bootflow(struct bootflow *bflow);

Expand Down

0 comments on commit 49867e8

Please sign in to comment.