summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2025-01-15 17:34:26 -0600
committerTom Rini <[email protected]>2025-01-15 19:27:14 -0600
commit178f6ecb21fe12ada74a9a1a08093c812b15eea5 (patch)
tree60dee6152b33cbd13f311875ce2fc8e9350a8c3d /boot
parente26a9ac4c6900cac2fa043ac50a3a3c038f4505d (diff)
parenta3d0fadca6b14f57477a4143334993daf52f89dc (diff)
Merge patch series "bootstd: Support recording images"
Simon Glass <[email protected]> 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/[email protected]
Diffstat (limited to 'boot')
-rw-r--r--boot/bootdev-uclass.c78
-rw-r--r--boot/bootflow.c77
-rw-r--r--boot/bootmeth-uclass.c29
-rw-r--r--boot/bootmeth_android.c3
-rw-r--r--boot/bootmeth_cros.c17
-rw-r--r--boot/bootmeth_efi.c16
-rw-r--r--boot/bootmeth_efi_mgr.c3
-rw-r--r--boot/bootmeth_extlinux.c8
-rw-r--r--boot/bootmeth_pxe.c10
-rw-r--r--boot/bootmeth_qfw.c3
-rw-r--r--boot/bootmeth_sandbox.c3
-rw-r--r--boot/bootmeth_script.c7
-rw-r--r--boot/bootstd-uclass.c60
-rw-r--r--boot/pxe_utils.c36
-rw-r--r--boot/vbe_simple.c5
15 files changed, 232 insertions, 123 deletions
diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index 2e61c853142..c39147940b6 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -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;
}
@@ -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;
@@ -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)
{
@@ -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;
}
@@ -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,
};
diff --git a/boot/bootflow.c b/boot/bootflow.c
index d8807eb109d..58a1afa7a75 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -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
*
@@ -55,11 +62,10 @@ 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;
}
@@ -67,20 +73,16 @@ int bootflow_first_glob(struct bootflow **bflowp)
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;
}
@@ -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);
@@ -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)
@@ -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);
+}
diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c
index 5b5fea39b3b..014b7588e8d 100644
--- a/boot/bootmeth-uclass.c
+++ b/boot/bootmeth-uclass.c
@@ -6,6 +6,7 @@
#define LOG_CATEGORY UCLASS_BOOTSTD
+#include <alist.h>
#include <blk.h>
#include <bootflow.h>
#include <bootmeth.h>
@@ -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)
@@ -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;
@@ -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];
@@ -377,6 +388,10 @@ 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;
@@ -384,7 +399,8 @@ int bootmeth_alloc_other(struct bootflow *bflow, const char *fname,
}
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;
@@ -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;
}
diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c
index 3a5144aaa3b..d8c92b44a99 100644
--- a/boot/bootmeth_android.c
+++ b/boot/bootmeth_android.c
@@ -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
diff --git a/boot/bootmeth_cros.c b/boot/bootmeth_cros.c
index 676f550ca25..c7b862e512a 100644
--- a/boot/bootmeth_cros.c
+++ b/boot/bootmeth_cros.c
@@ -243,8 +243,17 @@ static int cros_read_buf(struct bootflow *bflow, void *buf, ulong size,
ret = copy_cmdline(map_sysmem(cmdline, 0), uuid, &bflow->cmdline);
if (ret)
return log_msg_ret("cmd", ret);
+
+ if (!bootflow_img_add(bflow, "setup",
+ (enum bootflow_img_t)IH_TYPE_X86_SETUP,
+ setup, 0x3000))
+ return log_msg_ret("cri", -ENOMEM);
+
bflow->x86_setup = map_sysmem(setup, 0);
+ if (!bootflow_img_add(bflow, "cmdline", BFI_CMDLINE, cmdline, 0x1000))
+ return log_msg_ret("crc", -ENOMEM);
+
return 0;
}
@@ -306,6 +315,11 @@ static int cros_read_info(struct bootflow *bflow, const char *uuid,
}
priv->info_buf = buf;
+ if (!bootflow_img_add(bflow, "kernel",
+ (enum bootflow_img_t)IH_TYPE_KERNEL, 0,
+ priv->body_size))
+ return log_msg_ret("crk", -ENOMEM);
+
return 0;
}
@@ -400,7 +414,8 @@ static int cros_read_bootflow(struct udevice *dev, struct bootflow *bflow)
}
static int cros_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)
{
return -ENOSYS;
}
diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
index f836aa655f5..a2998452666 100644
--- a/boot/bootmeth_efi.c
+++ b/boot/bootmeth_efi.c
@@ -89,18 +89,17 @@ static void set_efi_bootdev(struct blk_desc *desc, struct bootflow *bflow)
static int efiload_read_file(struct bootflow *bflow, ulong addr)
{
struct blk_desc *desc = NULL;
- loff_t bytes_read;
+ ulong size;
int ret;
if (bflow->blk)
desc = dev_get_uclass_plat(bflow->blk);
- ret = bootmeth_setup_fs(bflow, desc);
- if (ret)
- return log_msg_ret("set", ret);
- ret = fs_read(bflow->fname, addr, 0, bflow->size, &bytes_read);
+ size = SZ_1G;
+ ret = bootmeth_common_read_file(bflow->method, bflow, bflow->fname,
+ addr, BFI_EFI, &size);
if (ret)
- return log_msg_ret("read", ret);
+ return log_msg_ret("rdf", ret);
bflow->buf = map_sysmem(addr, bflow->size);
set_efi_bootdev(desc, bflow);
@@ -173,7 +172,8 @@ static int distro_efi_try_bootflow_files(struct udevice *dev,
/* Limit FDT files to 4MB */
size = SZ_4M;
ret = bootmeth_common_read_file(dev, bflow, fname,
- fdt_addr, &size);
+ fdt_addr, (enum bootflow_img_t)IH_TYPE_FLATDT,
+ &size);
}
}
@@ -252,6 +252,8 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow)
if (!bootfile_name)
return log_msg_ret("bootfile_name", ret);
bflow->fname = strdup(bootfile_name);
+ if (!bflow->fname)
+ return log_msg_ret("fi0", -ENOMEM);
/* do the hideous EFI hack */
efi_set_bootdev("Net", "", bflow->fname, map_sysmem(addr, 0),
diff --git a/boot/bootmeth_efi_mgr.c b/boot/bootmeth_efi_mgr.c
index 23ae1e610ac..42b8863815e 100644
--- a/boot/bootmeth_efi_mgr.c
+++ b/boot/bootmeth_efi_mgr.c
@@ -74,7 +74,8 @@ static int efi_mgr_read_bootflow(struct udevice *dev, struct bootflow *bflow)
}
static int efi_mgr_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)
{
/* Files are loaded by the 'bootefi bootmgr' command */
diff --git a/boot/bootmeth_extlinux.c b/boot/bootmeth_extlinux.c
index c6ae6dffcb7..17c6cebd2f4 100644
--- a/boot/bootmeth_extlinux.c
+++ b/boot/bootmeth_extlinux.c
@@ -69,7 +69,8 @@ static int extlinux_get_state_desc(struct udevice *dev, char *buf, int maxsize)
}
static int extlinux_getfile(struct pxe_context *ctx, const char *file_path,
- char *file_addr, ulong *sizep)
+ char *file_addr, enum bootflow_img_t type,
+ ulong *sizep)
{
struct extlinux_info *info = ctx->userdata;
ulong addr;
@@ -80,7 +81,7 @@ static int extlinux_getfile(struct pxe_context *ctx, const char *file_path,
/* Allow up to 1GB */
*sizep = 1 << 30;
ret = bootmeth_read_file(info->dev, info->bflow, file_path, addr,
- sizep);
+ type, sizep);
if (ret)
return log_msg_ret("read", ret);
@@ -160,7 +161,8 @@ static int extlinux_read_bootflow(struct udevice *dev, struct bootflow *bflow)
return log_msg_ret("try", ret);
size = bflow->size;
- ret = bootmeth_alloc_file(bflow, 0x10000, ARCH_DMA_MINALIGN);
+ ret = bootmeth_alloc_file(bflow, 0x10000, ARCH_DMA_MINALIGN,
+ BFI_EXTLINUX_CFG);
if (ret)
return log_msg_ret("read", ret);
diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c
index 05c6bece2c1..b91e61bcbc4 100644
--- a/boot/bootmeth_pxe.c
+++ b/boot/bootmeth_pxe.c
@@ -23,7 +23,8 @@
#include <pxe_utils.h>
static int extlinux_pxe_getfile(struct pxe_context *ctx, const char *file_path,
- char *file_addr, ulong *sizep)
+ char *file_addr, enum bootflow_img_t type,
+ ulong *sizep)
{
struct extlinux_info *info = ctx->userdata;
ulong addr;
@@ -34,7 +35,7 @@ static int extlinux_pxe_getfile(struct pxe_context *ctx, const char *file_path,
/* Allow up to 1GB */
*sizep = 1 << 30;
ret = bootmeth_read_file(info->dev, info->bflow, file_path, addr,
- sizep);
+ type, sizep);
if (ret)
return log_msg_ret("read", ret);
@@ -113,7 +114,7 @@ static int extlinux_pxe_read_bootflow(struct udevice *dev,
static int extlinux_pxe_read_file(struct udevice *dev, struct bootflow *bflow,
const char *file_path, ulong addr,
- ulong *sizep)
+ enum bootflow_img_t type, ulong *sizep)
{
char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
struct pxe_context *ctx = dev_get_priv(dev);
@@ -134,6 +135,9 @@ static int extlinux_pxe_read_file(struct udevice *dev, struct bootflow *bflow,
return log_msg_ret("spc", -ENOSPC);
*sizep = size;
+ if (!bootflow_img_add(bflow, file_path, type, addr, size))
+ return log_msg_ret("pxi", -ENOMEM);
+
return 0;
}
diff --git a/boot/bootmeth_qfw.c b/boot/bootmeth_qfw.c
index 2f8e00cf350..028c2481583 100644
--- a/boot/bootmeth_qfw.c
+++ b/boot/bootmeth_qfw.c
@@ -52,7 +52,8 @@ static int qfw_read_bootflow(struct udevice *dev, struct bootflow *bflow)
}
static int qfw_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)
{
return -ENOSYS;
}
diff --git a/boot/bootmeth_sandbox.c b/boot/bootmeth_sandbox.c
index 26c713bb5f3..92ba2e3f050 100644
--- a/boot/bootmeth_sandbox.c
+++ b/boot/bootmeth_sandbox.c
@@ -27,7 +27,8 @@ static int sandbox_read_bootflow(struct udevice *dev, struct bootflow *bflow)
}
static int sandbox_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)
{
return -ENOSYS;
}
diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c
index c5cbf18c2e6..020cb8a7aec 100644
--- a/boot/bootmeth_script.c
+++ b/boot/bootmeth_script.c
@@ -98,7 +98,8 @@ static int script_read_bootflow_file(struct udevice *bootstd,
if (!bflow->subdir)
return log_msg_ret("prefix", -ENOMEM);
- ret = bootmeth_alloc_file(bflow, 0x10000, ARCH_DMA_MINALIGN);
+ ret = bootmeth_alloc_file(bflow, 0x10000, ARCH_DMA_MINALIGN,
+ (enum bootflow_img_t)IH_TYPE_SCRIPT);
if (ret)
return log_msg_ret("read", ret);
@@ -106,8 +107,8 @@ static int script_read_bootflow_file(struct udevice *bootstd,
if (ret)
return log_msg_ret("inf", ret);
- ret = bootmeth_alloc_other(bflow, "boot.bmp", &bflow->logo,
- &bflow->logo_size);
+ ret = bootmeth_alloc_other(bflow, "boot.bmp", BFI_LOGO,
+ &bflow->logo, &bflow->logo_size);
/* ignore error */
return 0;
diff --git a/boot/bootstd-uclass.c b/boot/bootstd-uclass.c
index fdb8d69e320..8c0fd4e63c3 100644
--- a/boot/bootstd-uclass.c
+++ b/boot/bootstd-uclass.c
@@ -6,6 +6,7 @@
* Written by Simon Glass <[email protected]>
*/
+#include <alist.h>
#include <bootflow.h>
#include <bootstd.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)
{
- 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)
@@ -61,6 +60,44 @@ void bootstd_clear_glob(void)
bootstd_clear_glob_(std);
}
+int bootstd_add_bootflow(struct bootflow *bflow)
+{
+ struct bootstd_priv *std;
+ int ret;
+
+ ret = bootstd_get_priv(&std);
+ if (ret)
+ return ret;
+
+ ret = std->bootflows.count;
+ bflow = alist_add(&std->bootflows, *bflow);
+ if (!bflow)
+ return log_msg_ret("bf2", -ENOMEM);
+
+ return ret;
+}
+
+int bootstd_clear_bootflows_for_bootdev(struct udevice *dev)
+{
+ struct bootstd_priv *std = bootstd_try_priv();
+ struct bootflow *from, *to;
+
+ /* if bootstd does not exist we cannot have any bootflows */
+ if (!std)
+ return 0;
+
+ /* 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;
+}
+
static int bootstd_remove(struct udevice *dev)
{
struct bootstd_priv *priv = dev_get_priv(dev);
@@ -100,6 +137,17 @@ const char *const *const bootstd_get_prefixes(struct udevice *dev)
return std->prefixes ? std->prefixes : default_prefixes;
}
+struct bootstd_priv *bootstd_try_priv(void)
+{
+ struct udevice *dev;
+
+ dev = uclass_try_first_device(UCLASS_BOOTSTD);
+ if (!dev || !device_active(dev))
+ return NULL;
+
+ return dev_get_priv(dev);
+}
+
int bootstd_get_priv(struct bootstd_priv **stdp)
{
struct udevice *dev;
@@ -117,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;
}
diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index 3ae17553c6d..82f217aaf86 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -6,6 +6,7 @@
#define LOG_CATEGORY LOGC_BOOT
+#include <bootflow.h>
#include <command.h>
#include <dm.h>
#include <env.h>
@@ -97,7 +98,8 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len)
* Returns 1 for success, or < 0 on error
*/
static int get_relfile(struct pxe_context *ctx, const char *file_path,
- unsigned long file_addr, ulong *filesizep)
+ unsigned long file_addr, enum bootflow_img_t type,
+ ulong *filesizep)
{
size_t path_len;
char relfile[MAX_TFTP_PATH_LEN + 1];
@@ -124,7 +126,7 @@ static int get_relfile(struct pxe_context *ctx, const char *file_path,
sprintf(addr_buf, "%lx", file_addr);
- ret = ctx->getfile(ctx, relfile, addr_buf, &size);
+ ret = ctx->getfile(ctx, relfile, addr_buf, type, &size);
if (ret < 0)
return log_msg_ret("get", ret);
if (filesizep)
@@ -133,16 +135,6 @@ static int get_relfile(struct pxe_context *ctx, const char *file_path,
return 1;
}
-/**
- * get_pxe_file() - read a file
- *
- * The file is read and nul-terminated
- *
- * @ctx: PXE context
- * @file_path: File path to read (relative to the PXE file)
- * @file_addr: Address to load file to
- * Returns 1 for success, or < 0 on error
- */
int get_pxe_file(struct pxe_context *ctx, const char *file_path,
ulong file_addr)
{
@@ -150,7 +142,8 @@ int get_pxe_file(struct pxe_context *ctx, const char *file_path,
int err;
char *buf;
- err = get_relfile(ctx, file_path, file_addr, &size);
+ err = get_relfile(ctx, file_path, file_addr, BFI_EXTLINUX_CFG,
+ &size);
if (err < 0)
return err;
@@ -199,13 +192,15 @@ int get_pxelinux_path(struct pxe_context *ctx, const char *file,
* @file_path: File path to read (relative to the PXE file)
* @envaddr_name: Name of environment variable which contains the address to
* load to
+ * @type: File type
* @filesizep: Returns the file size in bytes
* Returns 1 on success, -ENOENT if @envaddr_name does not exist as an
* environment variable, -EINVAL if its format is not valid hex, or other
* value < 0 on other error
*/
static int get_relfile_envaddr(struct pxe_context *ctx, const char *file_path,
- const char *envaddr_name, ulong *filesizep)
+ const char *envaddr_name,
+ enum bootflow_img_t type, ulong *filesizep)
{
unsigned long file_addr;
char *envaddr;
@@ -217,7 +212,7 @@ static int get_relfile_envaddr(struct pxe_context *ctx, const char *file_path,
if (strict_strtoul(envaddr, 16, &file_addr) < 0)
return -EINVAL;
- return get_relfile(ctx, file_path, file_addr, filesizep);
+ return get_relfile(ctx, file_path, file_addr, type, filesizep);
}
/**
@@ -405,6 +400,7 @@ static void label_boot_fdtoverlay(struct pxe_context *ctx,
/* Load overlay file */
err = get_relfile_envaddr(ctx, overlayfile, "fdtoverlay_addr_r",
+ (enum bootflow_img_t)IH_TYPE_FLATDT,
NULL);
if (err < 0) {
printf("Failed loading overlay %s\n", overlayfile);
@@ -490,7 +486,8 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
}
if (get_relfile_envaddr(ctx, label->kernel, "kernel_addr_r",
- NULL) < 0) {
+ (enum bootflow_img_t)IH_TYPE_KERNEL, NULL)
+ < 0) {
printf("Skipping %s for failure retrieving kernel\n",
label->name);
return 1;
@@ -516,6 +513,7 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
} else if (label->initrd) {
ulong size;
if (get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r",
+ (enum bootflow_img_t)IH_TYPE_RAMDISK,
&size) < 0) {
printf("Skipping %s for failure retrieving initrd\n",
label->name);
@@ -661,7 +659,8 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
if (fdtfile) {
int err = get_relfile_envaddr(ctx, fdtfile,
- "fdt_addr_r", NULL);
+ "fdt_addr_r",
+ (enum bootflow_img_t)IH_TYPE_FLATDT, NULL);
free(fdtfilefree);
if (err < 0) {
@@ -1548,7 +1547,8 @@ void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg)
if (IS_ENABLED(CONFIG_CMD_BMP)) {
/* display BMP if available */
if (cfg->bmp) {
- if (get_relfile(ctx, cfg->bmp, image_load_addr, NULL)) {
+ if (get_relfile(ctx, cfg->bmp, image_load_addr,
+ BFI_LOGO, NULL)) {
#if defined(CONFIG_VIDEO)
struct udevice *dev;
diff --git a/boot/vbe_simple.c b/boot/vbe_simple.c
index 189e86d2a22..ed7b9598e38 100644
--- a/boot/vbe_simple.c
+++ b/boot/vbe_simple.c
@@ -160,13 +160,14 @@ static int vbe_simple_read_bootflow(struct udevice *dev, struct bootflow *bflow)
}
static int vbe_simple_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)
{
int ret;
if (vbe_phase() == VBE_PHASE_OS) {
ret = bootmeth_common_read_file(dev, bflow, file_path, addr,
- sizep);
+ type, sizep);
if (ret)
return log_msg_ret("os", ret);
}