mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-08-08 00:06:59 +02:00
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>
This commit is contained in:
parent
6a3eb84b18
commit
49867e8045
@ -32,41 +32,17 @@ enum {
|
|||||||
BOOT_TARGETS_MAX_LEN = 100,
|
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)
|
int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp)
|
||||||
{
|
{
|
||||||
struct bootstd_priv *std = bootstd_try_priv();
|
struct bootstd_priv *std;
|
||||||
struct bootflow *bflow;
|
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)
|
if (!bflow)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
*bflowp = bflow;
|
*bflowp = bflow;
|
||||||
@ -76,10 +52,15 @@ int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp)
|
|||||||
|
|
||||||
int bootdev_next_bootflow(struct bootflow **bflowp)
|
int bootdev_next_bootflow(struct bootflow **bflowp)
|
||||||
{
|
{
|
||||||
struct bootstd_priv *std = bootstd_try_priv();
|
struct bootstd_priv *std;
|
||||||
struct bootflow *bflow;
|
struct bootflow *bflow;
|
||||||
|
int ret;
|
||||||
|
|
||||||
bflow = bootdev_next_bootflow_(std, (*bflowp)->dev, *bflowp);
|
ret = bootstd_get_priv(&std);
|
||||||
|
if (ret)
|
||||||
|
return log_msg_ret("bff", ret);
|
||||||
|
|
||||||
|
bflow = alist_nextw(&std->bootflows, *bflowp);
|
||||||
if (!bflow)
|
if (!bflow)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
*bflowp = bflow;
|
*bflowp = bflow;
|
||||||
|
@ -55,11 +55,10 @@ int bootflow_first_glob(struct bootflow **bflowp)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (list_empty(&std->glob_head))
|
if (!std->bootflows.count)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
*bflowp = list_first_entry(&std->glob_head, struct bootflow,
|
*bflowp = alist_getw(&std->bootflows, 0, struct bootflow);
|
||||||
glob_node);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -67,20 +66,16 @@ int bootflow_first_glob(struct bootflow **bflowp)
|
|||||||
int bootflow_next_glob(struct bootflow **bflowp)
|
int bootflow_next_glob(struct bootflow **bflowp)
|
||||||
{
|
{
|
||||||
struct bootstd_priv *std;
|
struct bootstd_priv *std;
|
||||||
struct bootflow *bflow = *bflowp;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = bootstd_get_priv(&std);
|
ret = bootstd_get_priv(&std);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
*bflowp = NULL;
|
*bflowp = alist_nextw(&std->bootflows, *bflowp);
|
||||||
|
if (!*bflowp)
|
||||||
if (list_is_last(&bflow->glob_node, &std->glob_head))
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
*bflowp = list_entry(bflow->glob_node.next, struct bootflow, glob_node);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,10 +471,7 @@ void bootflow_free(struct bootflow *bflow)
|
|||||||
|
|
||||||
void bootflow_remove(struct bootflow *bflow)
|
void bootflow_remove(struct bootflow *bflow)
|
||||||
{
|
{
|
||||||
list_del(&bflow->glob_node);
|
|
||||||
|
|
||||||
bootflow_free(bflow);
|
bootflow_free(bflow);
|
||||||
free(bflow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(BOOTSTD_FULL)
|
#if CONFIG_IS_ENABLED(BOOTSTD_FULL)
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
* Written by Simon Glass <sjg@chromium.org>
|
* Written by Simon Glass <sjg@chromium.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <alist.h>
|
||||||
#include <bootflow.h>
|
#include <bootflow.h>
|
||||||
#include <bootstd.h>
|
#include <bootstd.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
@ -42,13 +43,11 @@ static int bootstd_of_to_plat(struct udevice *dev)
|
|||||||
|
|
||||||
static void bootstd_clear_glob_(struct bootstd_priv *priv)
|
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,
|
alist_for_each(bflow, &priv->bootflows)
|
||||||
glob_node);
|
|
||||||
bootflow_remove(bflow);
|
bootflow_remove(bflow);
|
||||||
}
|
alist_empty(&priv->bootflows);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bootstd_clear_glob(void)
|
void bootstd_clear_glob(void)
|
||||||
@ -64,36 +63,37 @@ void bootstd_clear_glob(void)
|
|||||||
int bootstd_add_bootflow(struct bootflow *bflow)
|
int bootstd_add_bootflow(struct bootflow *bflow)
|
||||||
{
|
{
|
||||||
struct bootstd_priv *std;
|
struct bootstd_priv *std;
|
||||||
struct bootflow *new;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = bootstd_get_priv(&std);
|
ret = bootstd_get_priv(&std);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
new = malloc(sizeof(*bflow));
|
ret = std->bootflows.count;
|
||||||
if (!new)
|
bflow = alist_add(&std->bootflows, *bflow);
|
||||||
return log_msg_ret("bflow", -ENOMEM);
|
if (!bflow)
|
||||||
memcpy(new, bflow, sizeof(*bflow));
|
return log_msg_ret("bf2", -ENOMEM);
|
||||||
|
|
||||||
list_add_tail(&new->glob_node, &std->glob_head);
|
return ret;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int bootstd_clear_bootflows_for_bootdev(struct udevice *dev)
|
int bootstd_clear_bootflows_for_bootdev(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct bootstd_priv *std = bootstd_try_priv();
|
struct bootstd_priv *std = bootstd_try_priv();
|
||||||
|
struct bootflow *from, *to;
|
||||||
|
|
||||||
if (std) {
|
/* if bootstd does not exist we cannot have any bootflows */
|
||||||
struct bootflow *bflow;
|
if (!std)
|
||||||
struct list_head *pos;
|
return 0;
|
||||||
|
|
||||||
list_for_each(pos, &std->glob_head) {
|
/* Drop any bootflows that mention this dev */
|
||||||
bflow = list_entry(pos, struct bootflow, glob_node);
|
alist_for_each_filter(from, to, &std->bootflows) {
|
||||||
bootflow_remove(bflow);
|
if (from->dev == dev)
|
||||||
}
|
bootflow_remove(from);
|
||||||
|
else
|
||||||
|
*to++ = *from;
|
||||||
}
|
}
|
||||||
|
alist_update_end(&std->bootflows, to);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -165,7 +165,7 @@ static int bootstd_probe(struct udevice *dev)
|
|||||||
{
|
{
|
||||||
struct bootstd_priv *std = dev_get_priv(dev);
|
struct bootstd_priv *std = dev_get_priv(dev);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&std->glob_head);
|
alist_init_struct(&std->bootflows, struct bootflow);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||||||
if (!ret)
|
if (!ret)
|
||||||
num_valid++;
|
num_valid++;
|
||||||
ret = bootstd_add_bootflow(&bflow);
|
ret = bootstd_add_bootflow(&bflow);
|
||||||
if (ret) {
|
if (ret < 0) {
|
||||||
printf("Out of memory\n");
|
printf("Out of memory\n");
|
||||||
return CMD_RET_FAILURE;
|
return CMD_RET_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -56,11 +56,8 @@ enum bootflow_flags_t {
|
|||||||
/**
|
/**
|
||||||
* struct bootflow - information about a bootflow
|
* 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
|
* @dev: Bootdev device which produced this bootflow, NULL for flows created by
|
||||||
* BOOTMETHF_GLOBAL bootmeths
|
* BOOTMETHF_GLOBAL bootmeths
|
||||||
* @blk: Block device which contains this bootflow, NULL if this is a network
|
* @blk: Block device which contains this bootflow, NULL if this is a network
|
||||||
@ -90,7 +87,6 @@ enum bootflow_flags_t {
|
|||||||
* @bootmeth_priv: Private data for the bootmeth
|
* @bootmeth_priv: Private data for the bootmeth
|
||||||
*/
|
*/
|
||||||
struct bootflow {
|
struct bootflow {
|
||||||
struct list_head glob_node;
|
|
||||||
struct udevice *dev;
|
struct udevice *dev;
|
||||||
struct udevice *blk;
|
struct udevice *blk;
|
||||||
int part;
|
int part;
|
||||||
@ -390,7 +386,10 @@ const char *bootflow_state_get_name(enum bootflow_state_t state);
|
|||||||
/**
|
/**
|
||||||
* bootflow_remove() - Remove a bootflow and free its memory
|
* 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
|
* @bflow: Bootflow to remove
|
||||||
*/
|
*/
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#ifndef __bootstd_h
|
#ifndef __bootstd_h
|
||||||
#define __bootstd_h
|
#define __bootstd_h
|
||||||
|
|
||||||
|
#include <alist.h>
|
||||||
#include <dm/ofnode_decl.h>
|
#include <dm/ofnode_decl.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
@ -30,7 +31,8 @@ struct udevice;
|
|||||||
* terminated)
|
* terminated)
|
||||||
* @cur_bootdev: Currently selected bootdev (for commands)
|
* @cur_bootdev: Currently selected bootdev (for commands)
|
||||||
* @cur_bootflow: Currently selected bootflow (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_count: Number of bootmeth devices in @bootmeth_order
|
||||||
* @bootmeth_order: List of bootmeth devices to use, in order, NULL-terminated
|
* @bootmeth_order: List of bootmeth devices to use, in order, NULL-terminated
|
||||||
* @vbe_bootmeth: Currently selected VBE bootmeth, NULL if none
|
* @vbe_bootmeth: Currently selected VBE bootmeth, NULL if none
|
||||||
@ -44,7 +46,7 @@ struct bootstd_priv {
|
|||||||
const char **env_order;
|
const char **env_order;
|
||||||
struct udevice *cur_bootdev;
|
struct udevice *cur_bootdev;
|
||||||
struct bootflow *cur_bootflow;
|
struct bootflow *cur_bootflow;
|
||||||
struct list_head glob_head;
|
struct alist bootflows;
|
||||||
int bootmeth_count;
|
int bootmeth_count;
|
||||||
struct udevice **bootmeth_order;
|
struct udevice **bootmeth_order;
|
||||||
struct udevice *vbe_bootmeth;
|
struct udevice *vbe_bootmeth;
|
||||||
@ -135,7 +137,7 @@ int bootstd_prog_boot(void);
|
|||||||
* since this function takes over ownership of these. This functions makes
|
* since this function takes over ownership of these. This functions makes
|
||||||
* a copy of @bflow itself (without allocating its fields again), so the
|
* a copy of @bflow itself (without allocating its fields again), so the
|
||||||
* caller must dispose of the memory used by the @bflow pointer itself
|
* 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);
|
int bootstd_add_bootflow(struct bootflow *bflow);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user