Skip to content

Commit

Permalink
Merge patch series "bootstd: Support recording images"
Browse files Browse the repository at this point in the history
Simon Glass <sjg@chromium.org> says:

This series provides a way to keep track of the images used in bootstd,
including the type of each image.

At present this is sort-of handled by struct bootflow but in quite an
ad-hoc way. The structure has become quite large and is hard to query.
Future work will be able to reduce its size.

Ultimately the 'bootflow info' command may change to also show images as
a list, but that is left for later, as this series is already fairly
long. So for now, just introduce the concept and adjust bootstd to use
it, with a simple command to list the images.

This series includes various alist enhancements, to make use of this new
data structure a little easier.

[trini: Drop patch 18 and 19 for now due to size considerations]

Link: https://lore.kernel.org/r/20241115231926.211999-1-sjg@chromium.org
  • Loading branch information
trini committed Jan 16, 2025
2 parents e26a9ac + a3d0fad commit 178f6ec
Show file tree
Hide file tree
Showing 32 changed files with 685 additions and 178 deletions.
78 changes: 21 additions & 57 deletions boot/bootdev-uclass.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,55 +33,38 @@ enum {
BOOT_TARGETS_MAX_LEN = 100,
};

int bootdev_add_bootflow(struct bootflow *bflow)
int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp)
{
struct bootstd_priv *std;
struct bootflow *new;
struct bootflow *bflow;
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);
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;
}
return log_msg_ret("bff", ret);

int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp)
{
struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);

if (list_empty(&ucp->bootflow_head))
bflow = alist_getw(&std->bootflows, 0, struct bootflow);
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;
struct bootflow *bflow;
int ret;

*bflowp = NULL;
ret = bootstd_get_priv(&std);
if (ret)
return log_msg_ret("bff", ret);

if (list_is_last(&bflow->bm_node, &ucp->bootflow_head))
bflow = alist_nextw(&std->bootflows, *bflowp);
if (!bflow)
return -ENOENT;

*bflowp = list_entry(bflow->bm_node.next, struct bootflow, bm_node);
*bflowp = bflow;

return 0;
}
Expand Down Expand Up @@ -342,7 +325,7 @@ int bootdev_get_sibling_blk(struct udevice *dev, struct udevice **blkp)
return 0;
}

static int bootdev_get_from_blk(struct udevice *blk, struct udevice **bootdevp)
int bootdev_get_from_blk(struct udevice *blk, struct udevice **bootdevp)
{
struct udevice *parent = dev_get_parent(blk);
struct udevice *bootdev;
Expand Down Expand Up @@ -588,19 +571,6 @@ int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
return ops->get_bootflow(dev, iter, bflow);
}

void bootdev_clear_bootflows(struct udevice *dev)
{
struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);

while (!list_empty(&ucp->bootflow_head)) {
struct bootflow *bflow;

bflow = list_first_entry(&ucp->bootflow_head, struct bootflow,
bm_node);
bootflow_remove(bflow);
}
}

int bootdev_next_label(struct bootflow_iter *iter, struct udevice **devp,
int *method_flagsp)
{
Expand Down Expand Up @@ -955,18 +925,13 @@ 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)
{
bootdev_clear_bootflows(dev);
int ret;

ret = bootstd_clear_bootflows_for_bootdev(dev);
if (ret)
return log_msg_ret("bun", ret);

return 0;
}
Expand All @@ -976,6 +941,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,
};
77 changes: 63 additions & 14 deletions boot/bootflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ enum {
BF_NO_MORE_DEVICES = -ENODEV,
};

static const char *const bootflow_img[BFI_COUNT - BFI_FIRST] = {
"extlinux_cfg",
"logo",
"efi",
"cmdline",
};

/**
* bootflow_state - name for each state
*
Expand Down Expand Up @@ -55,32 +62,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 @@ -460,10 +462,13 @@ void bootflow_init(struct bootflow *bflow, struct udevice *bootdev,
bflow->dev = bootdev;
bflow->method = meth;
bflow->state = BOOTFLOWST_BASE;
alist_init_struct(&bflow->images, struct bootflow_img);
}

void bootflow_free(struct bootflow *bflow)
{
struct bootflow_img *img;

free(bflow->name);
free(bflow->subdir);
free(bflow->fname);
Expand All @@ -472,16 +477,15 @@ void bootflow_free(struct bootflow *bflow)
free(bflow->os_name);
free(bflow->fdt_fname);
free(bflow->bootmeth_priv);

alist_for_each(img, &bflow->images)
free(img->fname);
alist_empty(&bflow->images);
}

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

bootflow_free(bflow);
free(bflow);
}

#if CONFIG_IS_ENABLED(BOOTSTD_FULL)
Expand Down Expand Up @@ -960,3 +964,48 @@ int bootflow_cmdline_auto(struct bootflow *bflow, const char *arg)

return 0;
}

const char *bootflow_img_type_name(enum bootflow_img_t type)
{
const char *name;

if (type >= BFI_FIRST && type < BFI_COUNT)
name = bootflow_img[type - BFI_FIRST];
else
name = genimg_get_type_short_name(type);

return name;
}

struct bootflow_img *bootflow_img_add(struct bootflow *bflow, const char *fname,
enum bootflow_img_t type, ulong addr,
ulong size)
{
struct bootflow_img img, *ptr;

memset(&img, '\0', sizeof(struct bootflow_img));
img.fname = strdup(fname);
if (!img.fname)
return NULL;

img.type = type;
img.addr = addr;
img.size = size;
ptr = alist_add(&bflow->images, img);
if (!ptr)
return NULL;

return ptr;
}

int bootflow_get_seq(const struct bootflow *bflow)
{
struct bootstd_priv *std;
int ret;

ret = bootstd_get_priv(&std);
if (ret)
return ret;

return alist_calc_index(&std->bootflows, bflow);
}
29 changes: 24 additions & 5 deletions boot/bootmeth-uclass.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#define LOG_CATEGORY UCLASS_BOOTSTD

#include <alist.h>
#include <blk.h>
#include <bootflow.h>
#include <bootmeth.h>
Expand Down Expand Up @@ -83,14 +84,15 @@ int bootmeth_boot(struct udevice *dev, struct bootflow *bflow)
}

int bootmeth_read_file(struct udevice *dev, struct bootflow *bflow,
const char *file_path, ulong addr, ulong *sizep)
const char *file_path, ulong addr,
enum bootflow_img_t type, ulong *sizep)
{
const struct bootmeth_ops *ops = bootmeth_get_ops(dev);

if (!ops->read_file)
return -ENOSYS;

return ops->read_file(dev, bflow, file_path, addr, sizep);
return ops->read_file(dev, bflow, file_path, addr, type, sizep);
}

int bootmeth_get_bootflow(struct udevice *dev, struct bootflow *bflow)
Expand Down Expand Up @@ -326,8 +328,10 @@ int bootmeth_try_file(struct bootflow *bflow, struct blk_desc *desc,
return 0;
}

int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align)
int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align,
enum bootflow_img_t type)
{
struct blk_desc *desc = NULL;
void *buf;
uint size;
int ret;
Expand All @@ -344,11 +348,18 @@ int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align)
bflow->state = BOOTFLOWST_READY;
bflow->buf = buf;

if (bflow->blk)
desc = dev_get_uclass_plat(bflow->blk);

if (!bootflow_img_add(bflow, bflow->fname, type, map_to_sysmem(buf),
size))
return log_msg_ret("bai", -ENOMEM);

return 0;
}

int bootmeth_alloc_other(struct bootflow *bflow, const char *fname,
void **bufp, uint *sizep)
enum bootflow_img_t type, void **bufp, uint *sizep)
{
struct blk_desc *desc = NULL;
char path[200];
Expand Down Expand Up @@ -377,14 +388,19 @@ int bootmeth_alloc_other(struct bootflow *bflow, const char *fname,
if (ret)
return log_msg_ret("all", ret);

if (!bootflow_img_add(bflow, bflow->fname, type, map_to_sysmem(buf),
size))
return log_msg_ret("boi", -ENOMEM);

*bufp = buf;
*sizep = size;

return 0;
}

int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow,
const char *file_path, ulong addr, ulong *sizep)
const char *file_path, ulong addr,
enum bootflow_img_t type, ulong *sizep)
{
struct blk_desc *desc = NULL;
loff_t len_read;
Expand Down Expand Up @@ -413,6 +429,9 @@ int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow,
return ret;
*sizep = len_read;

if (!bootflow_img_add(bflow, bflow->fname, type, addr, size))
return log_msg_ret("bci", -ENOMEM);

return 0;
}

Expand Down
3 changes: 2 additions & 1 deletion boot/bootmeth_android.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,8 @@ static int android_read_bootflow(struct udevice *dev, struct bootflow *bflow)
}

static int android_read_file(struct udevice *dev, struct bootflow *bflow,
const char *file_path, ulong addr, ulong *sizep)
const char *file_path, ulong addr,
enum bootflow_img_t type, ulong *sizep)
{
/*
* Reading individual files is not supported since we only
Expand Down
Loading

0 comments on commit 178f6ec

Please sign in to comment.