
From: Simon Glass <sjg@chromium.org> In some cases we don't have a particular address to read into so would like one reserved. Adjust the read_file() method to support this. Signed-off-by: Simon Glass <sjg@chromium.org> --- boot/bootmeth-uclass.c | 24 ++++++++++++++++++------ boot/bootmeth_android.c | 2 +- boot/bootmeth_cros.c | 2 +- boot/bootmeth_efi.c | 6 +++--- boot/bootmeth_efi_mgr.c | 2 +- boot/bootmeth_extlinux.c | 2 +- boot/bootmeth_fel.c | 2 +- boot/bootmeth_pxe.c | 14 +++++++++----- boot/bootmeth_qfw.c | 2 +- boot/bootmeth_sandbox.c | 2 +- boot/vbe_abrec.c | 6 +++--- boot/vbe_abrec_os.c | 2 +- boot/vbe_simple.c | 9 +++++---- include/bootmeth.h | 22 ++++++++++++++++------ 14 files changed, 62 insertions(+), 35 deletions(-) diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c index 603ad98fc3a..6c0eff7579d 100644 --- a/boot/bootmeth-uclass.c +++ b/boot/bootmeth-uclass.c @@ -84,7 +84,7 @@ 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, + const char *file_path, ulong *addrp, ulong align, enum bootflow_img_t type, ulong *sizep) { const struct bootmeth_ops *ops = bootmeth_get_ops(dev); @@ -92,7 +92,7 @@ int bootmeth_read_file(struct udevice *dev, struct bootflow *bflow, if (!ops->read_file) return -ENOSYS; - return ops->read_file(dev, bflow, file_path, addr, type, sizep); + return ops->read_file(dev, bflow, file_path, addrp, align, type, sizep); } int bootmeth_get_bootflow(struct udevice *dev, struct bootflow *bflow) @@ -395,7 +395,7 @@ 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, + const char *file_path, ulong *addrp, ulong align, enum bootflow_img_t type, ulong *sizep) { struct blk_desc *desc = NULL; @@ -414,18 +414,30 @@ int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow, if (ret) return log_msg_ret("size", ret); if (size > *sizep) - return log_msg_ret("spc", -ENOSPC); + return log_msg_ret("spc", -E2BIG); ret = bootmeth_setup_fs(bflow, desc); if (ret) return log_msg_ret("fs", ret); - ret = fs_legacy_read(file_path, addr, 0, 0, &len_read); + if (!*addrp) { + phys_addr_t addr; + + if (!IS_ENABLED(CONFIG_LMB)) + return log_msg_ret("brf", -ENOTSUPP); + addr = lmb_alloc(size, align); + + if (!addr) + return -ENOSPC; + *addrp = addr; + } + + ret = fs_legacy_read(file_path, *addrp, 0, 0, &len_read); if (ret) return ret; *sizep = len_read; - if (!bootflow_img_add(bflow, bflow->fname, type, addr, size)) + if (!bootflow_img_add(bflow, bflow->fname, type, *addrp, size)) return log_msg_ret("bci", -ENOMEM); return 0; diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c index d8c92b44a99..69b50d327e8 100644 --- a/boot/bootmeth_android.c +++ b/boot/bootmeth_android.c @@ -323,7 +323,7 @@ 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, + const char *file_path, ulong *addrp, ulong align, enum bootflow_img_t type, ulong *sizep) { /* diff --git a/boot/bootmeth_cros.c b/boot/bootmeth_cros.c index ea4c9ed830f..f92e4437b27 100644 --- a/boot/bootmeth_cros.c +++ b/boot/bootmeth_cros.c @@ -414,7 +414,7 @@ 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, + const char *file_path, ulong *addrp, ulong align, enum bootflow_img_t type, ulong *sizep) { return -ENOSYS; diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index 2499fd3f219..78fb84334e5 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -63,7 +63,7 @@ static int efiload_read_file(struct bootflow *bflow, ulong addr, ulong max_size) size = max_size; ret = bootmeth_common_read_file(bflow->method, bflow, bflow->fname, - addr, BFI_EFI, &size); + &addr, SZ_2M, BFI_EFI, &size); if (ret) return log_msg_ret("rdf", ret); bflow->buf = map_sysmem(addr, bflow->size); @@ -139,8 +139,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, (enum bootflow_img_t)IH_TYPE_FLATDT, - &size); + &fdt_addr, SZ_4K, + (enum bootflow_img_t)IH_TYPE_FLATDT, &size); } } diff --git a/boot/bootmeth_efi_mgr.c b/boot/bootmeth_efi_mgr.c index 42b8863815e..5e83d1da103 100644 --- a/boot/bootmeth_efi_mgr.c +++ b/boot/bootmeth_efi_mgr.c @@ -74,7 +74,7 @@ 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, + const char *file_path, ulong *addrp, ulong align, 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 383f33e681c..cc086cdef0c 100644 --- a/boot/bootmeth_extlinux.c +++ b/boot/bootmeth_extlinux.c @@ -47,7 +47,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, + ret = bootmeth_read_file(info->dev, info->bflow, file_path, &addr, 0, type, sizep); if (ret) return log_msg_ret("read", ret); diff --git a/boot/bootmeth_fel.c b/boot/bootmeth_fel.c index b5a3f3730e3..f2593f6da74 100644 --- a/boot/bootmeth_fel.c +++ b/boot/bootmeth_fel.c @@ -34,7 +34,7 @@ static int fel_read_bootflow(struct udevice *dev, struct bootflow *bflow) } static int fel_read_file(struct udevice *dev, struct bootflow *bflow, - const char *file_path, ulong addr, + const char *file_path, ulong *addrp, ulong align, enum bootflow_img_t type, ulong *sizep) { return -ENOSYS; diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c index 30caadc8f3e..1025c5acb6c 100644 --- a/boot/bootmeth_pxe.c +++ b/boot/bootmeth_pxe.c @@ -34,7 +34,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, + ret = bootmeth_read_file(info->dev, info->bflow, file_path, &addr, 0, type, sizep); if (ret) return log_msg_ret("read", ret); @@ -113,15 +113,19 @@ 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, - enum bootflow_img_t type, ulong *sizep) + const char *file_path, ulong *addrp, + ulong align, enum bootflow_img_t type, + ulong *sizep) { ulong size; int ret; if (IS_ENABLED(CONFIG_NET_LWIP)) return -ENOTSUPP; - ret = netboot_run(TFTPGET, addr, file_path, 0, false); + if (!*addrp) + return log_msg_ret("tfta", -ENOTSUPP); + + ret = netboot_run(TFTPGET, *addrp, file_path, 0, false); if (ret) return log_msg_ret("tftp", ret); ret = pxe_get_file_size(&size); @@ -131,7 +135,7 @@ 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)) + if (!bootflow_img_add(bflow, file_path, type, *addrp, size)) return log_msg_ret("pxi", -ENOMEM); return 0; diff --git a/boot/bootmeth_qfw.c b/boot/bootmeth_qfw.c index 42ab7dc0a6f..3997dfa6b6f 100644 --- a/boot/bootmeth_qfw.c +++ b/boot/bootmeth_qfw.c @@ -115,7 +115,7 @@ static int qfw_read_files(struct udevice *dev, struct bootflow *bflow, } static int qfw_read_file(struct udevice *dev, struct bootflow *bflow, - const char *file_path, ulong addr, + const char *file_path, ulong *addrp, ulong align, enum bootflow_img_t type, ulong *sizep) { return -ENOSYS; diff --git a/boot/bootmeth_sandbox.c b/boot/bootmeth_sandbox.c index 92ba2e3f050..92638395bbf 100644 --- a/boot/bootmeth_sandbox.c +++ b/boot/bootmeth_sandbox.c @@ -27,7 +27,7 @@ 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, + const char *file_path, ulong *addrp, ulong align, enum bootflow_img_t type, ulong *sizep) { return -ENOSYS; diff --git a/boot/vbe_abrec.c b/boot/vbe_abrec.c index 4736e6147d2..ce3bcef08a7 100644 --- a/boot/vbe_abrec.c +++ b/boot/vbe_abrec.c @@ -119,14 +119,14 @@ static int vbe_abrec_read_bootflow(struct udevice *dev, struct bootflow *bflow) } static int vbe_abrec_read_file(struct udevice *dev, struct bootflow *bflow, - const char *file_path, ulong addr, + const char *file_path, ulong *addrp, ulong align, 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, - type, sizep); + ret = bootmeth_common_read_file(dev, bflow, file_path, addrp, + align, type, sizep); if (ret) return log_msg_ret("os", ret); } diff --git a/boot/vbe_abrec_os.c b/boot/vbe_abrec_os.c index 53eb3d79aca..ed4e4ab3dff 100644 --- a/boot/vbe_abrec_os.c +++ b/boot/vbe_abrec_os.c @@ -54,7 +54,7 @@ static int vbe_abrec_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, + ret = bootmeth_read_file(info->dev, info->bflow, file_path, &addr, 0, type, sizep); if (ret) return log_msg_ret("read", ret); diff --git a/boot/vbe_simple.c b/boot/vbe_simple.c index c6766c532f2..3711a70c906 100644 --- a/boot/vbe_simple.c +++ b/boot/vbe_simple.c @@ -98,14 +98,15 @@ 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, - enum bootflow_img_t type, ulong *sizep) + const char *file_path, ulong *addrp, + ulong align, 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, - type, sizep); + ret = bootmeth_common_read_file(dev, bflow, file_path, addrp, + align, type, sizep); if (ret) return log_msg_ret("os", ret); } diff --git a/include/bootmeth.h b/include/bootmeth.h index d25718d9a14..a34bfc91dd5 100644 --- a/include/bootmeth.h +++ b/include/bootmeth.h @@ -115,7 +115,10 @@ struct bootmeth_ops { * @dev: Bootmethod device to use * @bflow: Bootflow providing info on where to read from * @file_path: Path to file (may be absolute or relative) - * @addr: Address to load file + * @addrp: On entry, address to load file or 0 to reserve an + * address with lmb; on exit, address to which the file was + * loaded + * @align: Reservation alignment, if using lmb * @type: File type (IH_TYPE_...) * @sizep: On entry provides the maximum permitted size; on exit * returns the size of the file @@ -123,7 +126,7 @@ struct bootmeth_ops { * -ve value if something else goes wrong */ int (*read_file)(struct udevice *dev, struct bootflow *bflow, - const char *file_path, ulong addr, + const char *file_path, ulong *addrp, ulong align, enum bootflow_img_t type, ulong *sizep); #if CONFIG_IS_ENABLED(BOOTSTD_FULL) /** @@ -248,7 +251,10 @@ int bootmeth_set_bootflow(struct udevice *dev, struct bootflow *bflow, * @dev: Bootmethod device to use * @bflow: Bootflow providing info on where to read from * @file_path: Path to file (may be absolute or relative) - * @addr: Address to load file + * @addrp: On entry, address to load file or 0 to reserve an + * address with lmb; on exit, address to which the file was + * loaded + * @align: Reservation alignment, if using lmb * @type: File type (IH_TYPE_...) * @sizep: On entry provides the maximum permitted size; on exit * returns the size of the file @@ -256,7 +262,7 @@ int bootmeth_set_bootflow(struct udevice *dev, struct bootflow *bflow, * -ve value if something else goes wrong */ int bootmeth_read_file(struct udevice *dev, struct bootflow *bflow, - const char *file_path, ulong addr, + const char *file_path, ulong *addrp, ulong align, enum bootflow_img_t type, ulong *sizep); /** @@ -402,13 +408,17 @@ int bootmeth_alloc_other(struct bootflow *bflow, const char *fname, * @dev: bootmeth device to read from * @bflow: Bootflow information * @file_path: Path to file - * @addr: Address to load file to + * @addrp: On entry, address to load file or 0 to reserve an address with lmb; + * on exit, address to which the file was loaded + * @align: Reservation alignment, if using lmb * @type: File type (IH_TYPE_...) * @sizep: On entry, the maximum file size to accept, on exit the actual file * size read + * Return: 0 on success, -E2BIG if the file was too large, -ENOSPC if there is + * no memory available in LMB */ int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow, - const char *file_path, ulong addr, + const char *file_path, ulong *addrp, ulong align, enum bootflow_img_t type, ulong *sizep); /** -- 2.43.0