From 1e86296f7f1079b70c583a917d0c24cd02f77491 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:33 -0500 Subject: spl: blk_fs: Fix uninitialized return value when we can't get a blk_desc Initialize ret to avoid returning garbage if blk_get_devnum_by_uclass_id fails. Fixes: 8ce6a2e1757 ("spl: blk: Support loading images from fs") Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_blk_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common/spl') diff --git a/common/spl/spl_blk_fs.c b/common/spl/spl_blk_fs.c index 63825d6..144c8a6 100644 --- a/common/spl/spl_blk_fs.c +++ b/common/spl/spl_blk_fs.c @@ -50,7 +50,7 @@ int spl_blk_load_image(struct spl_image_info *spl_image, struct blk_desc *blk_desc; loff_t actlen, filesize; struct blk_dev dev; - int ret; + int ret = -ENODEV; blk_desc = blk_get_devnum_by_uclass_id(uclass_id, devnum); if (!blk_desc) { -- cgit v1.1 From 06b1bca69d355f3f03f3607d03ee308e012ebed2 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:35 -0500 Subject: spl: Make SHOW_ERRORS depend on LIBCOMMON The purpose of SHOW_ERRORS is to print extra information. Make it depend on LIBCOMMON to avoid having to check for two configs. Signed-off-by: Sean Anderson Reviewed-by: Tom Rini Reviewed-by: Simon Glass --- common/spl/Kconfig | 1 + common/spl/spl.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'common/spl') diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 00332cf..e929f1b 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -183,6 +183,7 @@ config SPL_SYS_REPORT_STACK_F_USAGE config SPL_SHOW_ERRORS bool "Show more information when something goes wrong" + depends on SPL_LIBCOMMON_SUPPORT help This enabled more verbose error messages and checking when something goes wrong in SPL. For example, it shows the error code when U-Boot diff --git a/common/spl/spl.c b/common/spl/spl.c index 732d90d..7ce38ce 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -718,8 +718,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2) ret = boot_from_devices(&spl_image, spl_boot_list, ARRAY_SIZE(spl_boot_list)); if (ret) { - if (CONFIG_IS_ENABLED(SHOW_ERRORS) && - CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT)) + if (CONFIG_IS_ENABLED(SHOW_ERRORS)) printf(SPL_TPL_PROMPT "failed to boot from all boot devices (err=%d)\n", ret); else -- cgit v1.1 From 517e70856f0fcbb9c84de0414430086bea0008ee Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:36 -0500 Subject: spl: semihosting: Don't close fd before spl_load_simple_fit On real hardware, semihosting calls tend to have a large constant overhead (on the order of tens of milliseconds). Reduce the number of calls by one by reusing the existing fd in smh_fit_read, and closing it at the end of spl_smh_load_image. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_semihosting.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_semihosting.c b/common/spl/spl_semihosting.c index f7dd289..8f11c29 100644 --- a/common/spl/spl_semihosting.c +++ b/common/spl/spl_semihosting.c @@ -24,18 +24,14 @@ static int smh_read_full(long fd, void *memp, size_t len) static ulong smh_fit_read(struct spl_load_info *load, ulong file_offset, ulong size, void *buf) { - long fd; + long fd = *(long *)load->priv; ulong ret; - fd = smh_open(load->filename, MODE_READ | MODE_BINARY); - if (fd < 0) { - log_debug("could not open %s: %ld\n", load->filename, fd); + if (smh_seek(fd, file_offset)) return 0; - } - ret = smh_read(fd, buf, size); - smh_close(fd); - return ret; + ret = smh_read(fd, buf, size); + return ret < 0 ? 0 : ret; } static int spl_smh_load_image(struct spl_image_info *spl_image, @@ -73,11 +69,11 @@ static int spl_smh_load_image(struct spl_image_info *spl_image, debug("Found FIT\n"); load.read = smh_fit_read; load.bl_len = 1; - load.filename = filename; - load.priv = NULL; - smh_close(fd); + load.filename = NULL; + load.priv = &fd; - return spl_load_simple_fit(spl_image, &load, 0, header); + ret = spl_load_simple_fit(spl_image, &load, 0, header); + goto out; } ret = spl_parse_image_header(spl_image, bootdev, header); -- cgit v1.1 From feaeb8fa6f949dd76d455a91793a859382678a72 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:37 -0500 Subject: spl: Remove NULL assignments in spl_load_info Remove NULL assignments to fields in spl_load_info when .load doesn't reference these fields. This can result in more efficient code. filename must stay even if it is unused, since load_simple_fit uses it. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_fat.c | 1 - common/spl/spl_mmc.c | 2 -- common/spl/spl_nand.c | 4 ---- common/spl/spl_spi.c | 2 -- common/spl/spl_ymodem.c | 1 - 5 files changed, 10 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index 014074f..6172e7b 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -99,7 +99,6 @@ int spl_load_image_fat(struct spl_image_info *spl_image, load.read = spl_fit_read; load.bl_len = 1; load.filename = (void *)filename; - load.priv = NULL; return spl_load_simple_fit(spl_image, &load, 0, header); } else { diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 82689da..6d9137c 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -106,7 +106,6 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, debug("Found FIT\n"); load.dev = mmc; - load.priv = NULL; load.filename = NULL; load.bl_len = mmc->read_bl_len; load.read = h_spl_load_read; @@ -116,7 +115,6 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, struct spl_load_info load; load.dev = mmc; - load.priv = NULL; load.filename = NULL; load.bl_len = mmc->read_bl_len; load.read = h_spl_load_read; diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index b8cd640..9a5a5ff 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -91,7 +91,6 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, struct spl_load_info load; debug("Found FIT\n"); - load.dev = NULL; load.priv = &offset; load.filename = NULL; load.bl_len = bl_len; @@ -101,7 +100,6 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, valid_container_hdr((void *)header)) { struct spl_load_info load; - load.dev = NULL; load.priv = &offset; load.filename = NULL; load.bl_len = bl_len; @@ -112,8 +110,6 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, struct spl_load_info load; debug("Found legacy image\n"); - load.dev = NULL; - load.priv = NULL; load.filename = NULL; load.bl_len = IS_ENABLED(CONFIG_SPL_LZMA) ? bl_len : 1; load.read = spl_nand_legacy_read; diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index 3ac4b1b..d83d70f 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -152,7 +152,6 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, debug("Found FIT\n"); load.dev = flash; - load.priv = NULL; load.filename = NULL; load.bl_len = 1; load.read = spl_spi_fit_read; @@ -164,7 +163,6 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, struct spl_load_info load; load.dev = flash; - load.priv = NULL; load.filename = NULL; load.bl_len = 1; load.read = spl_spi_fit_read; diff --git a/common/spl/spl_ymodem.c b/common/spl/spl_ymodem.c index 038b443..8616cb3 100644 --- a/common/spl/spl_ymodem.c +++ b/common/spl/spl_ymodem.c @@ -134,7 +134,6 @@ int spl_ymodem_load_image(struct spl_image_info *spl_image, struct ymodem_fit_info info; debug("Found FIT\n"); - load.dev = NULL; load.priv = (void *)&info; load.filename = NULL; load.bl_len = 1; -- cgit v1.1 From 0c6c83e6a2608421d992781bdbd33a12fa31c10d Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:38 -0500 Subject: spl: Remove dev from spl_load_info dev and priv serve the same purpose, and are never set at the same time. Remove dev and convert all users to priv. While we're at it, reorder bl_len to be last for better alignment. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_mmc.c | 6 +++--- common/spl/spl_spi.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 6d9137c..3d7551a 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -65,7 +65,7 @@ static int mmc_load_legacy(struct spl_image_info *spl_image, static ulong h_spl_load_read(struct spl_load_info *load, ulong sector, ulong count, void *buf) { - struct mmc *mmc = load->dev; + struct mmc *mmc = load->priv; return blk_dread(mmc_get_blk_desc(mmc), sector, count, buf); } @@ -105,7 +105,7 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, struct spl_load_info load; debug("Found FIT\n"); - load.dev = mmc; + load.priv = mmc; load.filename = NULL; load.bl_len = mmc->read_bl_len; load.read = h_spl_load_read; @@ -114,7 +114,7 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, valid_container_hdr((void *)header)) { struct spl_load_info load; - load.dev = mmc; + load.priv = mmc; load.filename = NULL; load.bl_len = mmc->read_bl_len; load.read = h_spl_load_read; diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index d83d70f..af7a28e 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -59,7 +59,7 @@ static int spi_load_image_os(struct spl_image_info *spl_image, static ulong spl_spi_fit_read(struct spl_load_info *load, ulong sector, ulong count, void *buf) { - struct spi_flash *flash = load->dev; + struct spi_flash *flash = load->priv; ulong ret; ret = spi_flash_read(flash, sector, count, buf); @@ -151,7 +151,7 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, struct spl_load_info load; debug("Found FIT\n"); - load.dev = flash; + load.priv = flash; load.filename = NULL; load.bl_len = 1; load.read = spl_spi_fit_read; @@ -162,7 +162,7 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, valid_container_hdr((void *)header)) { struct spl_load_info load; - load.dev = flash; + load.priv = flash; load.filename = NULL; load.bl_len = 1; load.read = spl_spi_fit_read; -- cgit v1.1 From 33c8d01a4d20ab1f7cb59bd9860e42196d6ddb4e Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:39 -0500 Subject: spl: Take advantage of bl_len's power-of-twoness bl_len must be a power of two, so we can use ALIGN instead of roundup and similar tricks to avoid divisions. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_fit.c | 2 +- common/spl/spl_imx_container.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 70d8d59..6084ead 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -194,7 +194,7 @@ static int get_aligned_image_overhead(struct spl_load_info *info, int offset) if (info->filename) return offset & (ARCH_DMA_MINALIGN - 1); - return offset % info->bl_len; + return offset & (info->bl_len - 1); } static int get_aligned_image_size(struct spl_load_info *info, int data_size, diff --git a/common/spl/spl_imx_container.c b/common/spl/spl_imx_container.c index 127802f..1cc5178 100644 --- a/common/spl/spl_imx_container.c +++ b/common/spl/spl_imx_container.c @@ -33,13 +33,13 @@ static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image, images = (struct boot_img_t *)((u8 *)container + sizeof(struct container_hdr)); - if (images[image_index].offset % info->bl_len) { + if (!IS_ALIGNED(images[image_index].offset, info->bl_len)) { printf("%s: image%d offset not aligned to %u\n", __func__, image_index, info->bl_len); return NULL; } - sectors = roundup(images[image_index].size, info->bl_len) / + sectors = ALIGN(images[image_index].size, info->bl_len) / info->bl_len; sector = images[image_index].offset / info->bl_len + container_sector; @@ -69,7 +69,7 @@ static int read_auth_container(struct spl_image_info *spl_image, u32 sectors; int i, size, ret = 0; - size = roundup(CONTAINER_HDR_ALIGNMENT, info->bl_len); + size = ALIGN(CONTAINER_HDR_ALIGNMENT, info->bl_len); sectors = size / info->bl_len; /* @@ -103,7 +103,7 @@ static int read_auth_container(struct spl_image_info *spl_image, debug("Container length %u\n", length); if (length > CONTAINER_HDR_ALIGNMENT) { - size = roundup(length, info->bl_len); + size = ALIGN(length, info->bl_len); sectors = size / info->bl_len; free(container); -- cgit v1.1 From 73c40fcb7367f5a431c987f7da0420c058a939fc Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:40 -0500 Subject: spl: Refactor spl_load_info->read to use units of bytes Simplify things a bit for callers of spl_load_info->read by refactoring it to use units of bytes instead of bl_len. This generally simplifies the logic, as MMC is the only loader which actually works in sectors. It will also allow further refactoring to remove the special-case handling of filename. spl_load_legacy_img already works in units of bytes (oops) so it doesn't need to be changed. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_fit.c | 51 +++++++++++++++++++++--------------------- common/spl/spl_imx_container.c | 45 ++++++++++++++++--------------------- common/spl/spl_mmc.c | 24 +++++++++++--------- common/spl/spl_nand.c | 8 +++---- 4 files changed, 61 insertions(+), 67 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 6084ead..ce7ef0e 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -180,7 +180,7 @@ static int get_aligned_image_offset(struct spl_load_info *info, int offset) if (info->filename) return offset & ~(ARCH_DMA_MINALIGN - 1); - return offset / info->bl_len; + return ALIGN_DOWN(offset, info->bl_len); } static int get_aligned_image_overhead(struct spl_load_info *info, int offset) @@ -205,7 +205,7 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size, if (info->filename) return data_size; - return (data_size + info->bl_len - 1) / info->bl_len; + return ALIGN(data_size, info->bl_len); } /** @@ -222,7 +222,7 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size, * * Return: 0 on success or a negative error number. */ -static int load_simple_fit(struct spl_load_info *info, ulong sector, +static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, const struct spl_fit_info *ctx, int node, struct spl_image_info *image_info) { @@ -234,7 +234,6 @@ static int load_simple_fit(struct spl_load_info *info, ulong sector, void *load_ptr; void *src; ulong overhead; - int nr_sectors; uint8_t image_comp = -1, type = -1; const void *data; const void *fit = ctx->fit; @@ -291,11 +290,12 @@ static int load_simple_fit(struct spl_load_info *info, ulong sector, length = len; overhead = get_aligned_image_overhead(info, offset); - nr_sectors = get_aligned_image_size(info, length, offset); + size = get_aligned_image_size(info, length, offset); if (info->read(info, - sector + get_aligned_image_offset(info, offset), - nr_sectors, src_ptr) != nr_sectors) + fit_offset + + get_aligned_image_offset(info, offset), size, + src_ptr) != size) return -EIO; debug("External data: dst=%p, offset=%x, size=%lx\n", @@ -380,7 +380,7 @@ __weak int board_spl_fit_append_fdt_skip(const char *name) } static int spl_fit_append_fdt(struct spl_image_info *spl_image, - struct spl_load_info *info, ulong sector, + struct spl_load_info *info, ulong offset, const struct spl_fit_info *ctx) { struct spl_image_info image_info; @@ -414,7 +414,7 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, spl_image->fdt_addr = map_sysmem(image_info.load_addr, size); memcpy(spl_image->fdt_addr, gd->fdt_blob, size); } else { - ret = load_simple_fit(info, sector, ctx, node, &image_info); + ret = load_simple_fit(info, offset, ctx, node, &image_info); if (ret < 0) return ret; @@ -465,7 +465,7 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, __func__); } image_info.load_addr = (ulong)tmpbuffer; - ret = load_simple_fit(info, sector, ctx, node, + ret = load_simple_fit(info, offset, ctx, node, &image_info); if (ret < 0) break; @@ -642,7 +642,7 @@ static int spl_fit_upload_fpga(struct spl_fit_info *ctx, int node, } static int spl_fit_load_fpga(struct spl_fit_info *ctx, - struct spl_load_info *info, ulong sector) + struct spl_load_info *info, ulong offset) { int node, ret; @@ -657,7 +657,7 @@ static int spl_fit_load_fpga(struct spl_fit_info *ctx, warn_deprecated("'fpga' property in config node. Use 'loadables'"); /* Load the image and set up the fpga_image structure */ - ret = load_simple_fit(info, sector, ctx, node, &fpga_image); + ret = load_simple_fit(info, offset, ctx, node, &fpga_image); if (ret) { printf("%s: Cannot load the FPGA: %i\n", __func__, ret); return ret; @@ -667,11 +667,10 @@ static int spl_fit_load_fpga(struct spl_fit_info *ctx, } static int spl_simple_fit_read(struct spl_fit_info *ctx, - struct spl_load_info *info, ulong sector, + struct spl_load_info *info, ulong offset, const void *fit_header) { unsigned long count, size; - int sectors; void *buf; /* @@ -690,13 +689,13 @@ static int spl_simple_fit_read(struct spl_fit_info *ctx, * For FIT with data embedded, data is loaded as part of FIT image. * For FIT with external data, data is not loaded in this step. */ - sectors = get_aligned_image_size(info, size, 0); - buf = board_spl_fit_buffer_addr(size, sectors, info->bl_len); + size = get_aligned_image_size(info, size, 0); + buf = board_spl_fit_buffer_addr(size, size, 1); - count = info->read(info, sector, sectors, buf); + count = info->read(info, offset, size, buf); ctx->fit = buf; - debug("fit read sector %lx, sectors=%d, dst=%p, count=%lu, size=0x%lx\n", - sector, sectors, buf, count, size); + debug("fit read offset %lx, size=%lu, dst=%p, count=%lu\n", + offset, size, buf, count); return (count == 0) ? -EIO : 0; } @@ -728,7 +727,7 @@ static int spl_simple_fit_parse(struct spl_fit_info *ctx) } int spl_load_simple_fit(struct spl_image_info *spl_image, - struct spl_load_info *info, ulong sector, void *fit) + struct spl_load_info *info, ulong offset, void *fit) { struct spl_image_info image_info; struct spl_fit_info ctx; @@ -737,7 +736,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, int index = 0; int firmware_node; - ret = spl_simple_fit_read(&ctx, info, sector, fit); + ret = spl_simple_fit_read(&ctx, info, offset, fit); if (ret < 0) return ret; @@ -752,7 +751,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, return ret; if (IS_ENABLED(CONFIG_SPL_FPGA)) - spl_fit_load_fpga(&ctx, info, sector); + spl_fit_load_fpga(&ctx, info, offset); /* * Find the U-Boot image using the following search order: @@ -782,7 +781,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, } /* Load the image and set up the spl_image structure */ - ret = load_simple_fit(info, sector, &ctx, node, spl_image); + ret = load_simple_fit(info, offset, &ctx, node, spl_image); if (ret) return ret; @@ -800,7 +799,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, * We allow this to fail, as the U-Boot image might embed its FDT. */ if (os_takes_devicetree(spl_image->os)) { - ret = spl_fit_append_fdt(spl_image, info, sector, &ctx); + ret = spl_fit_append_fdt(spl_image, info, offset, &ctx); if (ret < 0 && spl_image->os != IH_OS_U_BOOT) return ret; } @@ -823,7 +822,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, continue; image_info.load_addr = 0; - ret = load_simple_fit(info, sector, &ctx, node, &image_info); + ret = load_simple_fit(info, offset, &ctx, node, &image_info); if (ret < 0) { printf("%s: can't load image loadables index %d (ret = %d)\n", __func__, index, ret); @@ -837,7 +836,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, debug("Loadable is %s\n", genimg_get_os_name(os_type)); if (os_takes_devicetree(os_type)) { - spl_fit_append_fdt(&image_info, info, sector, &ctx); + spl_fit_append_fdt(&image_info, info, offset, &ctx); spl_image->fdt_addr = image_info.fdt_addr; } diff --git a/common/spl/spl_imx_container.c b/common/spl/spl_imx_container.c index 1cc5178..ad89a99 100644 --- a/common/spl/spl_imx_container.c +++ b/common/spl/spl_imx_container.c @@ -19,11 +19,10 @@ static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image, struct spl_load_info *info, struct container_hdr *container, int image_index, - u32 container_sector) + ulong container_offset) { struct boot_img_t *images; - ulong sector; - u32 sectors; + ulong offset, overhead, size; if (image_index > container->num_images) { debug("Invalid image number\n"); @@ -39,16 +38,14 @@ static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image, return NULL; } - sectors = ALIGN(images[image_index].size, info->bl_len) / - info->bl_len; - sector = images[image_index].offset / info->bl_len + - container_sector; + size = ALIGN(images[image_index].size, info->bl_len); + offset = images[image_index].offset + container_offset; - debug("%s: container: %p sector: %lu sectors: %u\n", __func__, - container, sector, sectors); - if (info->read(info, sector, sectors, - map_sysmem(images[image_index].dst, - images[image_index].size)) != sectors) { + debug("%s: container: %p offset: %lu size: %lu\n", __func__, + container, offset, size); + if (info->read(info, offset, size, + map_sysmem(images[image_index].dst - overhead, + images[image_index].size)) != size) { printf("%s wrong\n", __func__); return NULL; } @@ -62,15 +59,13 @@ static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image, } static int read_auth_container(struct spl_image_info *spl_image, - struct spl_load_info *info, ulong sector) + struct spl_load_info *info, ulong offset) { struct container_hdr *container = NULL; u16 length; - u32 sectors; int i, size, ret = 0; size = ALIGN(CONTAINER_HDR_ALIGNMENT, info->bl_len); - sectors = size / info->bl_len; /* * It will not override the ATF code, so safe to use it here, @@ -80,9 +75,9 @@ static int read_auth_container(struct spl_image_info *spl_image, if (!container) return -ENOMEM; - debug("%s: container: %p sector: %lu sectors: %u\n", __func__, - container, sector, sectors); - if (info->read(info, sector, sectors, container) != sectors) { + debug("%s: container: %p offset: %lu size: %u\n", __func__, + container, offset, size); + if (info->read(info, offset, size, container) != size) { ret = -EIO; goto end; } @@ -104,17 +99,15 @@ static int read_auth_container(struct spl_image_info *spl_image, if (length > CONTAINER_HDR_ALIGNMENT) { size = ALIGN(length, info->bl_len); - sectors = size / info->bl_len; free(container); container = malloc(size); if (!container) return -ENOMEM; - debug("%s: container: %p sector: %lu sectors: %u\n", - __func__, container, sector, sectors); - if (info->read(info, sector, sectors, container) != - sectors) { + debug("%s: container: %p offset: %lu size: %u\n", + __func__, container, offset, size); + if (info->read(info, offset, size, container) != size) { ret = -EIO; goto end; } @@ -129,7 +122,7 @@ static int read_auth_container(struct spl_image_info *spl_image, for (i = 0; i < container->num_images; i++) { struct boot_img_t *image = read_auth_image(spl_image, info, container, i, - sector); + offset); if (!image) { ret = -EINVAL; @@ -154,7 +147,7 @@ end: } int spl_load_imx_container(struct spl_image_info *spl_image, - struct spl_load_info *info, ulong sector) + struct spl_load_info *info, ulong offset) { - return read_auth_container(spl_image, info, sector); + return read_auth_container(spl_image, info, offset); } diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 3d7551a..9f41ea6 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -62,12 +62,14 @@ static int mmc_load_legacy(struct spl_image_info *spl_image, return 0; } -static ulong h_spl_load_read(struct spl_load_info *load, ulong sector, - ulong count, void *buf) +static ulong h_spl_load_read(struct spl_load_info *load, ulong off, + ulong size, void *buf) { - struct mmc *mmc = load->priv; + struct blk_desc *bd = load->priv; + lbaint_t sector = off >> bd->log2blksz; + lbaint_t count = size >> bd->log2blksz; - return blk_dread(mmc_get_blk_desc(mmc), sector, count, buf); + return blk_dread(bd, sector, count, buf) << bd->log2blksz; } static __maybe_unused unsigned long spl_mmc_raw_uboot_offset(int part) @@ -105,21 +107,23 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, struct spl_load_info load; debug("Found FIT\n"); - load.priv = mmc; + load.priv = bd; load.filename = NULL; - load.bl_len = mmc->read_bl_len; + load.bl_len = bd->blksz; load.read = h_spl_load_read; - ret = spl_load_simple_fit(spl_image, &load, sector, header); + ret = spl_load_simple_fit(spl_image, &load, + sector << bd->log2blksz, header); } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && valid_container_hdr((void *)header)) { struct spl_load_info load; - load.priv = mmc; + load.priv = bd; load.filename = NULL; - load.bl_len = mmc->read_bl_len; + load.bl_len = bd->blksz; load.read = h_spl_load_read; - ret = spl_load_imx_container(spl_image, &load, sector); + ret = spl_load_imx_container(spl_image, &load, + sector << bd->log2blksz); } else { ret = mmc_load_legacy(spl_image, bootdev, mmc, sector, header); } diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 9a5a5ff..1fcc89f 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -49,14 +49,12 @@ static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs, ulong sector; sector = *(int *)load->priv; - offs *= load->bl_len; - size *= load->bl_len; offs = sector + nand_spl_adjust_offset(sector, offs - sector); err = nand_spl_load_image(offs, size, dst); if (err) return 0; - return size / load->bl_len; + return size; } static ulong spl_nand_legacy_read(struct spl_load_info *load, ulong offs, @@ -95,7 +93,7 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, load.filename = NULL; load.bl_len = bl_len; load.read = spl_nand_fit_read; - return spl_load_simple_fit(spl_image, &load, offset / bl_len, header); + return spl_load_simple_fit(spl_image, &load, offset, header); } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && valid_container_hdr((void *)header)) { struct spl_load_info load; @@ -104,7 +102,7 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, load.filename = NULL; load.bl_len = bl_len; load.read = spl_nand_fit_read; - return spl_load_imx_container(spl_image, &load, offset / bl_len); + return spl_load_imx_container(spl_image, &load, offset); } else if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT) && image_get_magic(header) == IH_MAGIC) { struct spl_load_info load; -- cgit v1.1 From b63664be6a3d829639f8635365f22f4e1dd30aa1 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:41 -0500 Subject: spl: Set FAT bl_len to ARCH_DMA_MINALIGN Instead of relying on the presence of filename to determine whether we are dealing with a FAT filesystem (and should DMA-align the buffer), have FAT set bl_len to ARCH_DMA_MINALIGN instead. With this done, we can remove the special-case logic checking for the presence of filename. Because filesystems are not block-based, we may read less than the size passed to spl_load_info.read. This can happen if the file size is not DMA-aligned. This is fine as long as we read the amount we originally wanted to. Modify the conditions for callers of spl_load_info.read to check against the original, unaligned size to avoid failing spuriously. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_blk_fs.c | 3 ++- common/spl/spl_fat.c | 2 +- common/spl/spl_fit.c | 23 +---------------------- common/spl/spl_imx_container.c | 8 +++++--- 4 files changed, 9 insertions(+), 27 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_blk_fs.c b/common/spl/spl_blk_fs.c index 144c8a6..c105c55 100644 --- a/common/spl/spl_blk_fs.c +++ b/common/spl/spl_blk_fs.c @@ -9,6 +9,7 @@ #include #include #include +#include #include struct blk_dev { @@ -85,7 +86,7 @@ int spl_blk_load_image(struct spl_image_info *spl_image, debug("Found FIT\n"); load.read = spl_fit_read; - load.bl_len = 1; + load.bl_len = ARCH_DMA_MINALIGN; load.filename = (void *)filename; load.priv = &dev; diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index 6172e7b..5b72345 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -97,7 +97,7 @@ int spl_load_image_fat(struct spl_image_info *spl_image, debug("Found FIT\n"); load.read = spl_fit_read; - load.bl_len = 1; + load.bl_len = ARCH_DMA_MINALIGN; load.filename = (void *)filename; return spl_load_simple_fit(spl_image, &load, 0, header); diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index ce7ef0e..0df4e6d 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -172,28 +171,11 @@ static int spl_fit_get_image_node(const struct spl_fit_info *ctx, static int get_aligned_image_offset(struct spl_load_info *info, int offset) { - /* - * If it is a FS read, get the first address before offset which is - * aligned to ARCH_DMA_MINALIGN. If it is raw read return the - * block number to which offset belongs. - */ - if (info->filename) - return offset & ~(ARCH_DMA_MINALIGN - 1); - return ALIGN_DOWN(offset, info->bl_len); } static int get_aligned_image_overhead(struct spl_load_info *info, int offset) { - /* - * If it is a FS read, get the difference between the offset and - * the first address before offset which is aligned to - * ARCH_DMA_MINALIGN. If it is raw read return the offset within the - * block. - */ - if (info->filename) - return offset & (ARCH_DMA_MINALIGN - 1); - return offset & (info->bl_len - 1); } @@ -202,9 +184,6 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size, { data_size = data_size + get_aligned_image_overhead(info, offset); - if (info->filename) - return data_size; - return ALIGN(data_size, info->bl_len); } @@ -295,7 +274,7 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, if (info->read(info, fit_offset + get_aligned_image_offset(info, offset), size, - src_ptr) != size) + src_ptr) < length) return -EIO; debug("External data: dst=%p, offset=%x, size=%lx\n", diff --git a/common/spl/spl_imx_container.c b/common/spl/spl_imx_container.c index ad89a99..7cd674f 100644 --- a/common/spl/spl_imx_container.c +++ b/common/spl/spl_imx_container.c @@ -45,7 +45,8 @@ static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image, container, offset, size); if (info->read(info, offset, size, map_sysmem(images[image_index].dst - overhead, - images[image_index].size)) != size) { + images[image_index].size)) < + images[image_index].size) { printf("%s wrong\n", __func__); return NULL; } @@ -77,7 +78,8 @@ static int read_auth_container(struct spl_image_info *spl_image, debug("%s: container: %p offset: %lu size: %u\n", __func__, container, offset, size); - if (info->read(info, offset, size, container) != size) { + if (info->read(info, offset, size, container) < + CONTAINER_HDR_ALIGNMENT) { ret = -EIO; goto end; } @@ -107,7 +109,7 @@ static int read_auth_container(struct spl_image_info *spl_image, debug("%s: container: %p offset: %lu size: %u\n", __func__, container, offset, size); - if (info->read(info, offset, size, container) != size) { + if (info->read(info, offset, size, container) < length) { ret = -EIO; goto end; } -- cgit v1.1 From afdd2d98c29c443f348fd88198e59b78d50f4e2c Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:42 -0500 Subject: spl: Remove filename from spl_load_info For filesystems, filename serves the same purpose as priv. However, spl_load_fit_image also uses it to determine whether to use a DMA-aligned buffer. This is beneficial for FAT, which uses a bounce-buffer if the destination is not DMA-aligned. However, this is unnecessary now that filesystems set bl_len to ARCH_DMA_MINALIGN instead. With this done, we can remove filename entirely. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_blk_fs.c | 7 ++++--- common/spl/spl_fat.c | 4 ++-- common/spl/spl_mmc.c | 2 -- common/spl/spl_nand.c | 3 --- common/spl/spl_semihosting.c | 1 - common/spl/spl_spi.c | 2 -- common/spl/spl_ymodem.c | 1 - 7 files changed, 6 insertions(+), 14 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_blk_fs.c b/common/spl/spl_blk_fs.c index c105c55..4975ce4 100644 --- a/common/spl/spl_blk_fs.c +++ b/common/spl/spl_blk_fs.c @@ -14,6 +14,7 @@ struct blk_dev { const char *ifname; + const char *filename; char dev_part_str[8]; }; @@ -31,11 +32,11 @@ static ulong spl_fit_read(struct spl_load_info *load, ulong file_offset, return ret; } - ret = fs_read(load->filename, virt_to_phys(buf), file_offset, size, + ret = fs_read(dev->filename, virt_to_phys(buf), file_offset, size, &actlen); if (ret < 0) { printf("spl: error reading image %s. Err - %d\n", - load->filename, ret); + dev->filename, ret); return ret; } @@ -87,8 +88,8 @@ int spl_blk_load_image(struct spl_image_info *spl_image, debug("Found FIT\n"); load.read = spl_fit_read; load.bl_len = ARCH_DMA_MINALIGN; - load.filename = (void *)filename; load.priv = &dev; + dev.filename = filename; return spl_load_simple_fit(spl_image, &load, 0, header); } diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index 5b72345..8a2c4e3 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -51,7 +51,7 @@ static ulong spl_fit_read(struct spl_load_info *load, ulong file_offset, { loff_t actread; int ret; - char *filename = (char *)load->filename; + char *filename = load->priv; ret = fat_read_file(filename, buf, file_offset, size, &actread); if (ret) @@ -98,7 +98,7 @@ int spl_load_image_fat(struct spl_image_info *spl_image, debug("Found FIT\n"); load.read = spl_fit_read; load.bl_len = ARCH_DMA_MINALIGN; - load.filename = (void *)filename; + load.priv = (void *)filename; return spl_load_simple_fit(spl_image, &load, 0, header); } else { diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 9f41ea6..8c4ffe7 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -108,7 +108,6 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, debug("Found FIT\n"); load.priv = bd; - load.filename = NULL; load.bl_len = bd->blksz; load.read = h_spl_load_read; ret = spl_load_simple_fit(spl_image, &load, @@ -118,7 +117,6 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, struct spl_load_info load; load.priv = bd; - load.filename = NULL; load.bl_len = bd->blksz; load.read = h_spl_load_read; diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 1fcc89f..45d7c5f 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -90,7 +90,6 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, debug("Found FIT\n"); load.priv = &offset; - load.filename = NULL; load.bl_len = bl_len; load.read = spl_nand_fit_read; return spl_load_simple_fit(spl_image, &load, offset, header); @@ -99,7 +98,6 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, struct spl_load_info load; load.priv = &offset; - load.filename = NULL; load.bl_len = bl_len; load.read = spl_nand_fit_read; return spl_load_imx_container(spl_image, &load, offset); @@ -108,7 +106,6 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, struct spl_load_info load; debug("Found legacy image\n"); - load.filename = NULL; load.bl_len = IS_ENABLED(CONFIG_SPL_LZMA) ? bl_len : 1; load.read = spl_nand_legacy_read; diff --git a/common/spl/spl_semihosting.c b/common/spl/spl_semihosting.c index 8f11c29..24a3d9f 100644 --- a/common/spl/spl_semihosting.c +++ b/common/spl/spl_semihosting.c @@ -69,7 +69,6 @@ static int spl_smh_load_image(struct spl_image_info *spl_image, debug("Found FIT\n"); load.read = smh_fit_read; load.bl_len = 1; - load.filename = NULL; load.priv = &fd; ret = spl_load_simple_fit(spl_image, &load, 0, header); diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index af7a28e..373caea 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -152,7 +152,6 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, debug("Found FIT\n"); load.priv = flash; - load.filename = NULL; load.bl_len = 1; load.read = spl_spi_fit_read; err = spl_load_simple_fit(spl_image, &load, @@ -163,7 +162,6 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, struct spl_load_info load; load.priv = flash; - load.filename = NULL; load.bl_len = 1; load.read = spl_spi_fit_read; diff --git a/common/spl/spl_ymodem.c b/common/spl/spl_ymodem.c index 8616cb3..3f92b9b 100644 --- a/common/spl/spl_ymodem.c +++ b/common/spl/spl_ymodem.c @@ -135,7 +135,6 @@ int spl_ymodem_load_image(struct spl_image_info *spl_image, debug("Found FIT\n"); load.priv = (void *)&info; - load.filename = NULL; load.bl_len = 1; info.buf = buf; info.image_read = BUF_SIZE; -- cgit v1.1 From 5271e359a46cc6a60d0048576326e2fa1527f231 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:43 -0500 Subject: spl: Only support bl_len when we have to Aligning addresses and sizes causes overhead which is unnecessary when we are not loading from block devices. Remove bl_len when it is not needed. For example, on iot2050 we save 144 bytes with this patch (once the rest of this series is applied): add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-144 (-144) Function old new delta spl_load_simple_fit 920 904 -16 load_simple_fit 496 444 -52 spl_spi_load_image 384 308 -76 Total: Before=87431, After=87287, chg -0.16% We use panic() instead of BUILD_BUG_ON in spl_set_bl_len because we still need to be able to compile it for things like mmc_load_image_raw_sector, even if that function will not be used. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/Kconfig | 14 +++++++++++++- common/spl/spl_blk_fs.c | 2 +- common/spl/spl_fat.c | 2 +- common/spl/spl_fit.c | 6 +++--- common/spl/spl_imx_container.c | 10 +++++----- common/spl/spl_legacy.c | 4 ++-- common/spl/spl_mmc.c | 4 ++-- common/spl/spl_nand.c | 6 +++--- common/spl/spl_net.c | 2 +- common/spl/spl_nor.c | 8 ++++---- common/spl/spl_ram.c | 2 +- common/spl/spl_semihosting.c | 2 +- common/spl/spl_spi.c | 4 ++-- common/spl/spl_ymodem.c | 2 +- 14 files changed, 40 insertions(+), 28 deletions(-) (limited to 'common/spl') diff --git a/common/spl/Kconfig b/common/spl/Kconfig index e929f1b..0bc57d5 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -280,8 +280,15 @@ config SPL_BOARD_INIT spl_board_init() from board_init_r(). This function should be provided by the board. +config SPL_LOAD_BLOCK + bool + help + Support loading images from block devices. This adds a bl_len member + to struct spl_load_info. + config SPL_BOOTROM_SUPPORT bool "Support returning to the BOOTROM" + select SPL_LOAD_BLOCK if MACH_IMX help Some platforms (e.g. the Rockchip RK3368) provide support in their ROM for loading the next boot-stage after performing basic setup @@ -482,6 +489,7 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR ARCH_AT91 || ARCH_ZYNQ || ARCH_KEYSTONE || OMAP34XX || \ OMAP44XX || OMAP54XX || AM33XX || AM43XX || \ TARGET_SIFIVE_UNLEASHED || TARGET_SIFIVE_UNMATCHED + select SPL_LOAD_BLOCK if SPL_MMC help Use sector number for specifying U-Boot location on MMC/SD in raw mode. @@ -518,6 +526,7 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET config SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION bool "MMC Raw mode: by partition" + select SPL_LOAD_BLOCK if SPL_MMC help Use a partition for loading U-Boot when using MMC/SD in raw mode. @@ -678,6 +687,7 @@ config SPL_FS_SQUASHFS config SPL_FS_FAT bool "Support FAT filesystems" select FS_FAT + select SPL_LOAD_BLOCK help Enable support for FAT and VFAT filesystems with SPL. This permits U-Boot (or Linux in Falcon mode) to be loaded from a FAT @@ -877,6 +887,7 @@ config SPL_MUSB_NEW config SPL_NAND_SUPPORT bool "Support NAND flash" + select SPL_LOAD_BLOCK help Enable support for NAND (Negative AND) flash in SPL. NAND flash can be used to allow SPL to load U-Boot from supported devices. @@ -1102,6 +1113,7 @@ config SYS_OS_BASE config SPL_FALCON_BOOT_MMCSD bool "Enable Falcon boot from MMC or SD media" depends on SPL_OS_BOOT && SPL_MMC + select SPL_LOAD_BLOCK help Select this if the Falcon mode OS image mode is on MMC or SD media. @@ -1260,9 +1272,9 @@ config SPL_SATA_RAW_U_BOOT_SECTOR config SPL_NVME bool "NVM Express device support" depends on BLK - select HAVE_BLOCK_DEVICE select FS_LOADER select SPL_BLK_FS + select SPL_LOAD_BLOCK help This option enables support for NVM Express devices. It supports basic functions of NVMe (read/write). diff --git a/common/spl/spl_blk_fs.c b/common/spl/spl_blk_fs.c index 4975ce4..53b8e1b 100644 --- a/common/spl/spl_blk_fs.c +++ b/common/spl/spl_blk_fs.c @@ -87,7 +87,7 @@ int spl_blk_load_image(struct spl_image_info *spl_image, debug("Found FIT\n"); load.read = spl_fit_read; - load.bl_len = ARCH_DMA_MINALIGN; + spl_set_bl_len(&load, ARCH_DMA_MINALIGN); load.priv = &dev; dev.filename = filename; diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index 8a2c4e3..a0c34eb 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -97,7 +97,7 @@ int spl_load_image_fat(struct spl_image_info *spl_image, debug("Found FIT\n"); load.read = spl_fit_read; - load.bl_len = ARCH_DMA_MINALIGN; + spl_set_bl_len(&load, ARCH_DMA_MINALIGN); load.priv = (void *)filename; return spl_load_simple_fit(spl_image, &load, 0, header); diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 0df4e6d..872df0c 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -171,12 +171,12 @@ static int spl_fit_get_image_node(const struct spl_fit_info *ctx, static int get_aligned_image_offset(struct spl_load_info *info, int offset) { - return ALIGN_DOWN(offset, info->bl_len); + return ALIGN_DOWN(offset, spl_get_bl_len(info)); } static int get_aligned_image_overhead(struct spl_load_info *info, int offset) { - return offset & (info->bl_len - 1); + return offset & (spl_get_bl_len(info) - 1); } static int get_aligned_image_size(struct spl_load_info *info, int data_size, @@ -184,7 +184,7 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size, { data_size = data_size + get_aligned_image_overhead(info, offset); - return ALIGN(data_size, info->bl_len); + return ALIGN(data_size, spl_get_bl_len(info)); } /** diff --git a/common/spl/spl_imx_container.c b/common/spl/spl_imx_container.c index 7cd674f..b4ea924 100644 --- a/common/spl/spl_imx_container.c +++ b/common/spl/spl_imx_container.c @@ -32,13 +32,13 @@ static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image, images = (struct boot_img_t *)((u8 *)container + sizeof(struct container_hdr)); - if (!IS_ALIGNED(images[image_index].offset, info->bl_len)) { + if (!IS_ALIGNED(images[image_index].offset, spl_get_bl_len(info))) { printf("%s: image%d offset not aligned to %u\n", - __func__, image_index, info->bl_len); + __func__, image_index, spl_get_bl_len(info)); return NULL; } - size = ALIGN(images[image_index].size, info->bl_len); + size = ALIGN(images[image_index].size, spl_get_bl_len(info)); offset = images[image_index].offset + container_offset; debug("%s: container: %p offset: %lu size: %lu\n", __func__, @@ -66,7 +66,7 @@ static int read_auth_container(struct spl_image_info *spl_image, u16 length; int i, size, ret = 0; - size = ALIGN(CONTAINER_HDR_ALIGNMENT, info->bl_len); + size = ALIGN(CONTAINER_HDR_ALIGNMENT, spl_get_bl_len(info)); /* * It will not override the ATF code, so safe to use it here, @@ -100,7 +100,7 @@ static int read_auth_container(struct spl_image_info *spl_image, debug("Container length %u\n", length); if (length > CONTAINER_HDR_ALIGNMENT) { - size = ALIGN(length, info->bl_len); + size = ALIGN(length, spl_get_bl_len(info)); free(container); container = malloc(size); diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c index 9189576..75d9d82 100644 --- a/common/spl/spl_legacy.c +++ b/common/spl/spl_legacy.c @@ -139,9 +139,9 @@ int spl_load_legacy_img(struct spl_image_info *spl_image, lzma_len = LZMA_LEN; /* dataptr points to compressed payload */ - dataptr = ALIGN_DOWN(sizeof(*hdr), load->bl_len); + dataptr = ALIGN_DOWN(sizeof(*hdr), spl_get_bl_len(load)); overhead = sizeof(*hdr) - dataptr; - size = ALIGN(spl_image->size + overhead, load->bl_len); + size = ALIGN(spl_image->size + overhead, spl_get_bl_len(load)); dataptr += offset; debug("LZMA: Decompressing %08lx to %08lx\n", diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 8c4ffe7..91272c0 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -108,7 +108,7 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, debug("Found FIT\n"); load.priv = bd; - load.bl_len = bd->blksz; + spl_set_bl_len(&load, bd->blksz); load.read = h_spl_load_read; ret = spl_load_simple_fit(spl_image, &load, sector << bd->log2blksz, header); @@ -117,7 +117,7 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, struct spl_load_info load; load.priv = bd; - load.bl_len = bd->blksz; + spl_set_bl_len(&load, bd->blksz); load.read = h_spl_load_read; ret = spl_load_imx_container(spl_image, &load, diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 45d7c5f..281211b 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -90,7 +90,7 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, debug("Found FIT\n"); load.priv = &offset; - load.bl_len = bl_len; + spl_set_bl_len(&load, bl_len); load.read = spl_nand_fit_read; return spl_load_simple_fit(spl_image, &load, offset, header); } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && @@ -98,7 +98,7 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, struct spl_load_info load; load.priv = &offset; - load.bl_len = bl_len; + spl_set_bl_len(&load, bl_len); load.read = spl_nand_fit_read; return spl_load_imx_container(spl_image, &load, offset); } else if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT) && @@ -106,7 +106,7 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, struct spl_load_info load; debug("Found legacy image\n"); - load.bl_len = IS_ENABLED(CONFIG_SPL_LZMA) ? bl_len : 1; + spl_set_bl_len(&load, IS_ENABLED(CONFIG_SPL_LZMA) ? bl_len : 1); load.read = spl_nand_legacy_read; return spl_load_legacy_img(spl_image, bootdev, &load, offset, header); diff --git a/common/spl/spl_net.c b/common/spl/spl_net.c index f01d4df..47994e2 100644 --- a/common/spl/spl_net.c +++ b/common/spl/spl_net.c @@ -54,7 +54,7 @@ static int spl_net_load_image(struct spl_image_info *spl_image, struct spl_load_info load; debug("Found FIT\n"); - load.bl_len = 1; + spl_set_bl_len(&load, 1); load.read = spl_net_load_read; rv = spl_load_simple_fit(spl_image, &load, 0, header); } else { diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c index 236b071..aad230d 100644 --- a/common/spl/spl_nor.c +++ b/common/spl/spl_nor.c @@ -49,7 +49,7 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, int ret; debug("Found FIT\n"); - load.bl_len = 1; + spl_set_bl_len(&load, 1); load.read = spl_nor_load_read; ret = spl_load_simple_fit(spl_image, &load, @@ -97,7 +97,7 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, #ifdef CONFIG_SPL_LOAD_FIT if (image_get_magic(header) == FDT_MAGIC) { debug("Found FIT format U-Boot\n"); - load.bl_len = 1; + spl_set_bl_len(&load, 1); load.read = spl_nor_load_read; return spl_load_simple_fit(spl_image, &load, spl_nor_get_uboot_base(), @@ -106,7 +106,7 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, #endif if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && valid_container_hdr((void *)header)) { - load.bl_len = 1; + spl_set_bl_len(&load, 1); load.read = spl_nor_load_read; return spl_load_imx_container(spl_image, &load, spl_nor_get_uboot_base()); @@ -114,7 +114,7 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, /* Legacy image handling */ if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT)) { - load.bl_len = 1; + spl_set_bl_len(&load, 1); load.read = spl_nor_load_read; return spl_load_legacy_img(spl_image, bootdev, &load, spl_nor_get_uboot_base(), diff --git a/common/spl/spl_ram.c b/common/spl/spl_ram.c index 4158ed1..8aeda23 100644 --- a/common/spl/spl_ram.c +++ b/common/spl/spl_ram.c @@ -70,7 +70,7 @@ static int spl_ram_load_image(struct spl_image_info *spl_image, struct spl_load_info load; debug("Found FIT\n"); - load.bl_len = 1; + spl_set_bl_len(&load, 1); load.read = spl_ram_load_read; ret = spl_load_simple_fit(spl_image, &load, 0, header); } else { diff --git a/common/spl/spl_semihosting.c b/common/spl/spl_semihosting.c index 24a3d9f..9b0610b 100644 --- a/common/spl/spl_semihosting.c +++ b/common/spl/spl_semihosting.c @@ -68,7 +68,7 @@ static int spl_smh_load_image(struct spl_image_info *spl_image, debug("Found FIT\n"); load.read = smh_fit_read; - load.bl_len = 1; + spl_set_bl_len(&load, 1); load.priv = &fd; ret = spl_load_simple_fit(spl_image, &load, 0, header); diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index 373caea..3e08ac7 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -152,7 +152,7 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, debug("Found FIT\n"); load.priv = flash; - load.bl_len = 1; + spl_set_bl_len(&load, 1); load.read = spl_spi_fit_read; err = spl_load_simple_fit(spl_image, &load, payload_offs, @@ -162,7 +162,7 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, struct spl_load_info load; load.priv = flash; - load.bl_len = 1; + spl_set_bl_len(&load, 1); load.read = spl_spi_fit_read; err = spl_load_imx_container(spl_image, &load, diff --git a/common/spl/spl_ymodem.c b/common/spl/spl_ymodem.c index 3f92b9b..1faaa2c 100644 --- a/common/spl/spl_ymodem.c +++ b/common/spl/spl_ymodem.c @@ -135,7 +135,7 @@ int spl_ymodem_load_image(struct spl_image_info *spl_image, debug("Found FIT\n"); load.priv = (void *)&info; - load.bl_len = 1; + spl_set_bl_len(&load, 1); info.buf = buf; info.image_read = BUF_SIZE; load.read = ymodem_read_fit; -- cgit v1.1 From 0ddfa868ba45903babf19039c80dfeb1503f9001 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:44 -0500 Subject: spl: nand: Remove spl_nand_legacy_read Now that spl_nand_fit_read works in units of bytes, it can be combined with spl_nand_legacy_read. Rename the resulting function spl_nand_read, since it is no longer FIT-specific. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_nand.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 281211b..91fa767 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -42,29 +42,22 @@ static int spl_nand_load_image(struct spl_image_info *spl_image, } #else -static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs, - ulong size, void *dst) +__weak u32 nand_spl_adjust_offset(u32 sector, u32 offs) { - int err; - ulong sector; - - sector = *(int *)load->priv; - offs = sector + nand_spl_adjust_offset(sector, offs - sector); - err = nand_spl_load_image(offs, size, dst); - if (err) - return 0; - - return size; + return offs; } -static ulong spl_nand_legacy_read(struct spl_load_info *load, ulong offs, - ulong size, void *dst) +static ulong spl_nand_read(struct spl_load_info *load, ulong offs, ulong size, + void *dst) { int err; + ulong sector; debug("%s: offs %lx, size %lx, dst %p\n", __func__, offs, size, dst); + sector = *(int *)load->priv; + offs = sector + nand_spl_adjust_offset(sector, offs - sector); err = nand_spl_load_image(offs, size, dst); if (err) return 0; @@ -91,7 +84,7 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, debug("Found FIT\n"); load.priv = &offset; spl_set_bl_len(&load, bl_len); - load.read = spl_nand_fit_read; + load.read = spl_nand_read; return spl_load_simple_fit(spl_image, &load, offset, header); } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && valid_container_hdr((void *)header)) { @@ -99,16 +92,16 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, load.priv = &offset; spl_set_bl_len(&load, bl_len); - load.read = spl_nand_fit_read; + load.read = spl_nand_read; return spl_load_imx_container(spl_image, &load, offset); } else if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT) && image_get_magic(header) == IH_MAGIC) { struct spl_load_info load; debug("Found legacy image\n"); + load.priv = &offset; spl_set_bl_len(&load, IS_ENABLED(CONFIG_SPL_LZMA) ? bl_len : 1); - load.read = spl_nand_legacy_read; - + load.read = spl_nand_read; return spl_load_legacy_img(spl_image, bootdev, &load, offset, header); } else { err = spl_parse_image_header(spl_image, bootdev, header); -- cgit v1.1 From efe92cd2f9eff3699d4a6b5e1c3d261c4b88b342 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:45 -0500 Subject: spl: legacy: Split off LZMA decompression into its own function To allow for easier reuse of this functionality, split it off into its own function. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_legacy.c | 75 ++++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 35 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c index 75d9d82..a561939 100644 --- a/common/spl/spl_legacy.c +++ b/common/spl/spl_legacy.c @@ -82,6 +82,43 @@ int spl_parse_legacy_header(struct spl_image_info *spl_image, return 0; } +int spl_load_legacy_lzma(struct spl_image_info *spl_image, + struct spl_load_info *load, ulong offset) +{ + SizeT lzma_len = LZMA_LEN; + void *src; + ulong dataptr, overhead, size; + int ret; + + /* dataptr points to compressed payload */ + dataptr = ALIGN_DOWN(sizeof(struct legacy_img_hdr), + spl_get_bl_len(load)); + overhead = sizeof(struct legacy_img_hdr) - dataptr; + size = ALIGN(spl_image->size + overhead, spl_get_bl_len(load)); + dataptr += offset; + + debug("LZMA: Decompressing %08lx to %08lx\n", + dataptr, spl_image->load_addr); + src = malloc(size); + if (!src) { + printf("Unable to allocate %d bytes for LZMA\n", + spl_image->size); + return -ENOMEM; + } + + load->read(load, dataptr, size, src); + ret = lzmaBuffToBuffDecompress(map_sysmem(spl_image->load_addr, + spl_image->size), &lzma_len, + src + overhead, spl_image->size); + if (ret) { + printf("LZMA decompression error: %d\n", ret); + return ret; + } + + spl_image->size = lzma_len; + return 0; +} + /* * This function is added explicitly to avoid code size increase, when * no compression method is enabled. The compiler will optimize the @@ -101,8 +138,6 @@ int spl_load_legacy_img(struct spl_image_info *spl_image, struct spl_load_info *load, ulong offset, struct legacy_img_hdr *hdr) { - __maybe_unused SizeT lzma_len; - __maybe_unused void *src; ulong dataptr; int ret; @@ -133,39 +168,9 @@ int spl_load_legacy_img(struct spl_image_info *spl_image, map_sysmem(spl_image->load_addr, spl_image->size)); break; - case IH_COMP_LZMA: { - ulong overhead, size; - - lzma_len = LZMA_LEN; - - /* dataptr points to compressed payload */ - dataptr = ALIGN_DOWN(sizeof(*hdr), spl_get_bl_len(load)); - overhead = sizeof(*hdr) - dataptr; - size = ALIGN(spl_image->size + overhead, spl_get_bl_len(load)); - dataptr += offset; - - debug("LZMA: Decompressing %08lx to %08lx\n", - dataptr, spl_image->load_addr); - src = malloc(size); - if (!src) { - printf("Unable to allocate %d bytes for LZMA\n", - spl_image->size); - return -ENOMEM; - } - - load->read(load, dataptr, size, src); - ret = lzmaBuffToBuffDecompress(map_sysmem(spl_image->load_addr, - spl_image->size), - &lzma_len, src + overhead, - spl_image->size); - if (ret) { - printf("LZMA decompression error: %d\n", ret); - return ret; - } - - spl_image->size = lzma_len; - break; - } + case IH_COMP_LZMA: + return spl_load_legacy_lzma(spl_image, load, offset); + default: debug("Compression method %s is not supported\n", genimg_get_comp_short_name(image_get_comp(hdr))); -- cgit v1.1 From 775074165d97e03277eaf345d8c472e48659f5af Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:47 -0500 Subject: spl: Add generic spl_load function Implementers of SPL_LOAD_IMAGE_METHOD have to correctly determine what type of image is being loaded and then call the appropriate image load function correctly. This is tricky, because some image load functions expect the whole image to already be loaded (CONFIG_SPL_LOAD_FIT_FULL), some will load the image automatically using spl_load_info.read() (CONFIG_SPL_LOAD_FIT/CONFIG_SPL_LOAD_IMX_CONTAINER), and some just parse the header and expect the caller to do the actual loading afterwards (legacy/raw images). Load methods often only support a subset of the above methods, meaning that not all image types can be used with all load methods. Further, the code to invoke these functions is duplicated between different load functions. To address this problem, this commit introduces a "spl_load" function. It aims to handle image detection and correct invocation of each of the parse/load functions. Although this function generally results in a size reduction with several users, it tends to bloat boards with only a single user. This is generally because programmers open-coding the contents of this function can make optimizations based on the specific loader. For example, NOR flash is memory-mapped, so it never bothers calling load->read. The compiler can't really make these optimizations across translation units. LTO solves this, but it is only available on some arches. To address this, perform "pseudo-LTO" by inlining spl_load when there are one or fewer users. At the moment, there are no users, so define SPL_LOAD_USERS to be 0. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'common/spl') diff --git a/common/spl/spl.c b/common/spl/spl.c index 7ce38ce..3ce5bfe 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -352,6 +353,15 @@ int spl_parse_image_header(struct spl_image_info *spl_image, return 0; } +#if SPL_LOAD_USERS > 1 +int spl_load(struct spl_image_info *spl_image, + const struct spl_boot_device *bootdev, struct spl_load_info *info, + size_t size, size_t offset) +{ + return _spl_load(spl_image, bootdev, info, size, offset); +} +#endif + __weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) { typedef void __noreturn (*image_entry_noargs_t)(void); -- cgit v1.1 From b8ed72256748119d392c63c6fa8b1f8bb156fd38 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:48 -0500 Subject: spl: Convert ext to use spl_load This converts the ext load method to use spl_load. As a consequence, it also adds support for FIT and IMX images. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_ext.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_ext.c b/common/spl/spl_ext.c index af836ca..d280b69 100644 --- a/common/spl/spl_ext.c +++ b/common/spl/spl_ext.c @@ -2,25 +2,35 @@ #include #include -#include #include #include +#include #include #include #include #include +static ulong spl_fit_read(struct spl_load_info *load, ulong file_offset, + ulong size, void *buf) +{ + int ret; + loff_t actlen; + + ret = ext4fs_read(buf, file_offset, size, &actlen); + if (ret) + return ret; + return actlen; +} + int spl_load_image_ext(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, struct blk_desc *block_dev, int partition, const char *filename) { s32 err; - struct legacy_img_hdr *header; - loff_t filelen, actlen; + loff_t filelen; struct disk_partition part_info = {}; - - header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); + struct spl_load_info load; if (part_get_info(block_dev, partition, &part_info)) { printf("spl: no partition table found\n"); @@ -42,20 +52,10 @@ int spl_load_image_ext(struct spl_image_info *spl_image, puts("spl: ext4fs_open failed\n"); goto end; } - err = ext4fs_read((char *)header, 0, sizeof(struct legacy_img_hdr), &actlen); - if (err < 0) { - puts("spl: ext4fs_read failed\n"); - goto end; - } - - err = spl_parse_image_header(spl_image, bootdev, header); - if (err < 0) { - puts("spl: ext: failed to parse image header\n"); - goto end; - } - err = ext4fs_read(map_sysmem(spl_image->load_addr, filelen), 0, filelen, - &actlen); + spl_set_bl_len(&load, 1); + load.read = spl_fit_read; + err = spl_load(spl_image, bootdev, &load, filelen, 0); end: #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT -- cgit v1.1 From 682184e9b9a6f67b108209651ad2ce90aae9ec9d Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:49 -0500 Subject: spl: Convert fat to spl_load This converts the fat loader to use spl_load. Some platforms are very tight on space, so we take care to only include the code we really need. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_fat.c | 56 +++++++++++++++++----------------------------------- 1 file changed, 18 insertions(+), 38 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index a0c34eb..569f2b3 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -11,8 +11,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -66,58 +66,38 @@ int spl_load_image_fat(struct spl_image_info *spl_image, const char *filename) { int err; - struct legacy_img_hdr *header; + loff_t size; + struct spl_load_info load; err = spl_register_fat_device(block_dev, partition); if (err) goto end; - header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); - - err = file_fat_read(filename, header, sizeof(struct legacy_img_hdr)); - if (err <= 0) - goto end; - - if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) && - image_get_magic(header) == FDT_MAGIC) { - err = file_fat_read(filename, - map_sysmem(CONFIG_SYS_LOAD_ADDR, 0), 0); - if (err <= 0) - goto end; - err = spl_parse_image_header(spl_image, bootdev, - map_sysmem(CONFIG_SYS_LOAD_ADDR, - err)); - if (err == -EAGAIN) - return err; - if (err == 0) - err = 1; - } else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && - image_get_magic(header) == FDT_MAGIC) { - struct spl_load_info load; - - debug("Found FIT\n"); - load.read = spl_fit_read; - spl_set_bl_len(&load, ARCH_DMA_MINALIGN); - load.priv = (void *)filename; - - return spl_load_simple_fit(spl_image, &load, 0, header); - } else { - err = spl_parse_image_header(spl_image, bootdev, header); + /* + * Avoid pulling in this function for other image types since we are + * very short on space on some boards. + */ + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL)) { + err = fat_size(filename, &size); if (err) goto end; - - err = file_fat_read(filename, map_sysmem(spl_image->load_addr, - spl_image->size), 0); + } else { + size = 0; } + load.read = spl_fit_read; + spl_set_bl_len(&load, ARCH_DMA_MINALIGN); + load.priv = (void *)filename; + err = spl_load(spl_image, bootdev, &load, size, 0); + end: #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT - if (err <= 0) + if (err < 0) printf("%s: error reading image %s, err - %d\n", __func__, filename, err); #endif - return (err <= 0); + return err; } #if CONFIG_IS_ENABLED(OS_BOOT) -- cgit v1.1 From 5d3401a448353767c5e67246a79271c9ee6f3f73 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:50 -0500 Subject: spl: Convert mmc to spl_load This converts the mmc loader to spl_load. Legacy images are handled by spl_load (via spl_parse_image_header), so mmc_load_legacy can be omitted. To accurately determine whether mmc_load_image_raw_sector is used (which might not be the case if SYS_MMCSD_FS_BOOT is enabled), we introduce a helper config SYS_MMCSD_RAW_MODE. This ensures we can inline spl_load correctly when a board only boots from filesystems. We still need to check for SPL_MMC, since some boards enable configure raw mode even without MMC support. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/Kconfig | 8 +++++ common/spl/spl_mmc.c | 89 +++++----------------------------------------------- 2 files changed, 15 insertions(+), 82 deletions(-) (limited to 'common/spl') diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 0bc57d5..b935269 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -481,6 +481,11 @@ config SPL_DISPLAY_PRINT banner ("U-Boot SPL ..."). This function should be provided by the board. +config SPL_SYS_MMCSD_RAW_MODE + bool + help + Support booting from an MMC without a filesystem. + config SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR bool "MMC raw mode: by sector" default y if ARCH_SUNXI || ARCH_DAVINCI || ARCH_UNIPHIER || \ @@ -490,6 +495,7 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR OMAP44XX || OMAP54XX || AM33XX || AM43XX || \ TARGET_SIFIVE_UNLEASHED || TARGET_SIFIVE_UNMATCHED select SPL_LOAD_BLOCK if SPL_MMC + select SPL_SYS_MMCSD_RAW_MODE if SPL_MMC help Use sector number for specifying U-Boot location on MMC/SD in raw mode. @@ -527,6 +533,7 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET config SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION bool "MMC Raw mode: by partition" select SPL_LOAD_BLOCK if SPL_MMC + select SPL_SYS_MMCSD_RAW_MODE if SPL_MMC help Use a partition for loading U-Boot when using MMC/SD in raw mode. @@ -1114,6 +1121,7 @@ config SPL_FALCON_BOOT_MMCSD bool "Enable Falcon boot from MMC or SD media" depends on SPL_OS_BOOT && SPL_MMC select SPL_LOAD_BLOCK + select SPL_SYS_MMCSD_RAW_MODE help Select this if the Falcon mode OS image mode is on MMC or SD media. diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 91272c0..3d032bb 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -8,9 +8,9 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -19,49 +19,6 @@ #include #include -static int mmc_load_legacy(struct spl_image_info *spl_image, - struct spl_boot_device *bootdev, - struct mmc *mmc, - ulong sector, struct legacy_img_hdr *header) -{ - u32 image_offset_sectors; - u32 image_size_sectors; - unsigned long count; - u32 image_offset; - int ret; - - ret = spl_parse_image_header(spl_image, bootdev, header); - if (ret) - return ret; - - /* convert offset to sectors - round down */ - image_offset_sectors = spl_image->offset / mmc->read_bl_len; - /* calculate remaining offset */ - image_offset = spl_image->offset % mmc->read_bl_len; - - /* convert size to sectors - round up */ - image_size_sectors = (spl_image->size + mmc->read_bl_len - 1) / - mmc->read_bl_len; - - /* Read the header too to avoid extra memcpy */ - count = blk_dread(mmc_get_blk_desc(mmc), - sector + image_offset_sectors, - image_size_sectors, - map_sysmem(spl_image->load_addr, - image_size_sectors * mmc->read_bl_len)); - debug("read %x sectors to %lx\n", image_size_sectors, - spl_image->load_addr); - if (count != image_size_sectors) - return -EIO; - - if (image_offset) - memmove((void *)(ulong)spl_image->load_addr, - (void *)(ulong)spl_image->load_addr + image_offset, - spl_image->size); - - return 0; -} - static ulong h_spl_load_read(struct spl_load_info *load, ulong off, ulong size, void *buf) { @@ -87,46 +44,14 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, struct mmc *mmc, unsigned long sector) { - unsigned long count; - struct legacy_img_hdr *header; + int ret; struct blk_desc *bd = mmc_get_blk_desc(mmc); - int ret = 0; - - header = spl_get_load_buffer(-sizeof(*header), bd->blksz); - - /* read image header to find the image size & load address */ - count = blk_dread(bd, sector, 1, header); - debug("hdr read sector %lx, count=%lu\n", sector, count); - if (count == 0) { - ret = -EIO; - goto end; - } - - if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && - image_get_magic(header) == FDT_MAGIC) { - struct spl_load_info load; - - debug("Found FIT\n"); - load.priv = bd; - spl_set_bl_len(&load, bd->blksz); - load.read = h_spl_load_read; - ret = spl_load_simple_fit(spl_image, &load, - sector << bd->log2blksz, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && - valid_container_hdr((void *)header)) { - struct spl_load_info load; - - load.priv = bd; - spl_set_bl_len(&load, bd->blksz); - load.read = h_spl_load_read; - - ret = spl_load_imx_container(spl_image, &load, - sector << bd->log2blksz); - } else { - ret = mmc_load_legacy(spl_image, bootdev, mmc, sector, header); - } + struct spl_load_info load; -end: + load.priv = bd; + spl_set_bl_len(&load, bd->blksz); + load.read = h_spl_load_read; + ret = spl_load(spl_image, bootdev, &load, 0, sector << bd->log2blksz); if (ret) { #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT puts("mmc_load_image_raw_sector: mmc block read error\n"); -- cgit v1.1 From 11f834614e8577bffea04d39e7eb235ee1271b29 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:51 -0500 Subject: spl: Convert nand to spl_load This converts the nand load method to use spl_load. nand_page_size may not be valid until after nand_spl_load_image is called (see e.g. fsl_ifc_spl), so we set bl_len in spl_nand_read. Since spl_load reads the header for us, we can remove that argument from spl_nand_load_element. There are two possible regressions which could result from this commit. First, we ask for a negative address from spl_get_load_buffer. That is, instead of header = spl_get_load_buffer(0, sizeof(*header)); we do header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); this could cause a problem if spl_get_load_buffer does not return valid memory for negative offsets. Second, we now set bl_len for legacy images. This can cause memory up to a bl_len - 1 before the image load address to be written, which might not have been the case before. If this turns out to be a problem, we can add an option for a bounce buffer. We can't load FITs with external data with SPL_LOAD_FIT_FULL, so disable the test in that case. No boards enable SPL_NAND_SUPPORT and SPL_LOAD_FIT_FULL, so this is not a regression. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_nand.c | 70 ++++++++++++--------------------------------------- 1 file changed, 16 insertions(+), 54 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 91fa767..3b0a152 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,7 @@ static ulong spl_nand_read(struct spl_load_info *load, ulong offs, ulong size, sector = *(int *)load->priv; offs = sector + nand_spl_adjust_offset(sector, offs - sector); err = nand_spl_load_image(offs, size, dst); + spl_set_bl_len(load, nand_page_size()); if (err) return 0; @@ -66,60 +68,20 @@ static ulong spl_nand_read(struct spl_load_info *load, ulong offs, ulong size, } static int spl_nand_load_element(struct spl_image_info *spl_image, - struct spl_boot_device *bootdev, - int offset, struct legacy_img_hdr *header) + struct spl_boot_device *bootdev, int offset) { - int bl_len; - int err; + struct spl_load_info load; - err = nand_spl_load_image(offset, sizeof(*header), (void *)header); - if (err) - return err; - - bl_len = nand_page_size(); - if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && - image_get_magic(header) == FDT_MAGIC) { - struct spl_load_info load; - - debug("Found FIT\n"); - load.priv = &offset; - spl_set_bl_len(&load, bl_len); - load.read = spl_nand_read; - return spl_load_simple_fit(spl_image, &load, offset, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && - valid_container_hdr((void *)header)) { - struct spl_load_info load; - - load.priv = &offset; - spl_set_bl_len(&load, bl_len); - load.read = spl_nand_read; - return spl_load_imx_container(spl_image, &load, offset); - } else if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT) && - image_get_magic(header) == IH_MAGIC) { - struct spl_load_info load; - - debug("Found legacy image\n"); - load.priv = &offset; - spl_set_bl_len(&load, IS_ENABLED(CONFIG_SPL_LZMA) ? bl_len : 1); - load.read = spl_nand_read; - return spl_load_legacy_img(spl_image, bootdev, &load, offset, header); - } else { - err = spl_parse_image_header(spl_image, bootdev, header); - if (err) - return err; - return nand_spl_load_image(offset, spl_image->size, - map_sysmem(spl_image->load_addr, - spl_image->size)); - } + load.priv = &offset; + spl_set_bl_len(&load, 1); + load.read = spl_nand_read; + return spl_load(spl_image, bootdev, &load, 0, offset); } static int spl_nand_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { int err; - struct legacy_img_hdr *header; - int *src __attribute__((unused)); - int *dst __attribute__((unused)); #ifdef CONFIG_SPL_NAND_SOFTECC debug("spl: nand - using sw ecc\n"); @@ -128,10 +90,12 @@ static int spl_nand_load_image(struct spl_image_info *spl_image, #endif nand_init(); - header = spl_get_load_buffer(0, sizeof(*header)); - #if CONFIG_IS_ENABLED(OS_BOOT) if (!spl_start_uboot()) { + int *src, *dst; + struct legacy_img_hdr *header = + spl_get_load_buffer(0, sizeof(*header)); + /* * load parameter image * load to temp position since nand_spl_load_image reads @@ -174,20 +138,18 @@ static int spl_nand_load_image(struct spl_image_info *spl_image, } #endif #ifdef CONFIG_NAND_ENV_DST - spl_nand_load_element(spl_image, bootdev, CONFIG_ENV_OFFSET, header); + spl_nand_load_element(spl_image, bootdev, CONFIG_ENV_OFFSET); #ifdef CONFIG_ENV_OFFSET_REDUND - spl_nand_load_element(spl_image, bootdev, CONFIG_ENV_OFFSET_REDUND, header); + spl_nand_load_element(spl_image, bootdev, CONFIG_ENV_OFFSET_REDUND); #endif #endif /* Load u-boot */ - err = spl_nand_load_element(spl_image, bootdev, spl_nand_get_uboot_raw_page(), - header); + err = spl_nand_load_element(spl_image, bootdev, spl_nand_get_uboot_raw_page()); #ifdef CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND #if CONFIG_SYS_NAND_U_BOOT_OFFS != CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND if (err) err = spl_nand_load_element(spl_image, bootdev, - CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND, - header); + CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND); #endif #endif nand_deselect(); -- cgit v1.1 From 2e5476b5a7fe7255e58bd6b086c1c6c77350cadd Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:52 -0500 Subject: spl: Convert net to spl_load This converts the net load method to use spl_load. As a result, it also adds support for LOAD_FIT_FULL and IMX images. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_net.c | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_net.c b/common/spl/spl_net.c index 47994e2..898f9df 100644 --- a/common/spl/spl_net.c +++ b/common/spl/spl_net.c @@ -11,8 +11,8 @@ #include #include #include -#include #include +#include #include #include @@ -29,8 +29,7 @@ static ulong spl_net_load_read(struct spl_load_info *load, ulong sector, static int spl_net_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { - struct legacy_img_hdr *header = map_sysmem(image_load_addr, - sizeof(*header)); + struct spl_load_info load; int rv; env_init(); @@ -49,27 +48,9 @@ static int spl_net_load_image(struct spl_image_info *spl_image, return rv; } - if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && - image_get_magic(header) == FDT_MAGIC) { - struct spl_load_info load; - - debug("Found FIT\n"); - spl_set_bl_len(&load, 1); - load.read = spl_net_load_read; - rv = spl_load_simple_fit(spl_image, &load, 0, header); - } else { - debug("Legacy image\n"); - - rv = spl_parse_image_header(spl_image, bootdev, header); - if (rv) - return rv; - - memcpy(map_sysmem(spl_image->load_addr, spl_image->size), - map_sysmem(image_load_addr, spl_image->size), - spl_image->size); - } - - return rv; + spl_set_bl_len(&load, 1); + load.read = spl_net_load_read; + return spl_load(spl_image, bootdev, &load, 0, 0); } #endif -- cgit v1.1 From cbe86576cbe6344f9e9dafe10e28815a0fac801d Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:53 -0500 Subject: spl: Convert nor to spl_load This converts the nor load method to use spl_load. As a result it also adds support for LOAD_FIT_FULL. Since this is the last caller of spl_load_legacy_img, it has been removed. We can't load FITs with external data with SPL_LOAD_FIT_FULL, so disable the test in that case. No boards enable SPL_NOR_SUPPORT and SPL_LOAD_FIT_FULL, so this is not a regression. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_legacy.c | 61 ------------------------------------------------- common/spl/spl_nor.c | 40 ++++++-------------------------- 2 files changed, 7 insertions(+), 94 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c index a561939..08687ca 100644 --- a/common/spl/spl_legacy.c +++ b/common/spl/spl_legacy.c @@ -118,64 +118,3 @@ int spl_load_legacy_lzma(struct spl_image_info *spl_image, spl_image->size = lzma_len; return 0; } - -/* - * This function is added explicitly to avoid code size increase, when - * no compression method is enabled. The compiler will optimize the - * following switch/case statement in spl_load_legacy_img() away due to - * Dead Code Elimination. - */ -static inline int spl_image_get_comp(const struct legacy_img_hdr *hdr) -{ - if (IS_ENABLED(CONFIG_SPL_LZMA)) - return image_get_comp(hdr); - - return IH_COMP_NONE; -} - -int spl_load_legacy_img(struct spl_image_info *spl_image, - struct spl_boot_device *bootdev, - struct spl_load_info *load, ulong offset, - struct legacy_img_hdr *hdr) -{ - ulong dataptr; - int ret; - - /* - * If the payload is compressed, the decompressed data should be - * directly write to its load address. - */ - if (spl_image_get_comp(hdr) != IH_COMP_NONE) - spl_image->flags |= SPL_COPY_PAYLOAD_ONLY; - - ret = spl_parse_image_header(spl_image, bootdev, hdr); - if (ret) - return ret; - - /* Read image */ - switch (spl_image_get_comp(hdr)) { - case IH_COMP_NONE: - dataptr = offset; - - /* - * Image header will be skipped only if SPL_COPY_PAYLOAD_ONLY - * is set - */ - if (spl_image->flags & SPL_COPY_PAYLOAD_ONLY) - dataptr += sizeof(*hdr); - - load->read(load, dataptr, spl_image->size, - map_sysmem(spl_image->load_addr, spl_image->size)); - break; - - case IH_COMP_LZMA: - return spl_load_legacy_lzma(spl_image, load, offset); - - default: - debug("Compression method %s is not supported\n", - genimg_get_comp_short_name(image_get_comp(hdr))); - return -EINVAL; - } - - return 0; -} diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c index aad230d..7074511 100644 --- a/common/spl/spl_nor.c +++ b/common/spl/spl_nor.c @@ -7,8 +7,8 @@ #include #include #include -#include #include +#include static ulong spl_nor_load_read(struct spl_load_info *load, ulong sector, ulong count, void *buf) @@ -28,8 +28,7 @@ unsigned long __weak spl_nor_get_uboot_base(void) static int spl_nor_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { - struct legacy_img_hdr *header; - __maybe_unused struct spl_load_info load; + struct spl_load_info load; /* * Loading of the payload to SDRAM is done with skipping of @@ -43,7 +42,8 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, * Load Linux from its location in NOR flash to its defined * location in SDRAM */ - header = (void *)CONFIG_SYS_OS_BASE; + const struct legacy_img_hdr *header = + (const struct legacy_img_hdr *)CONFIG_SYS_OS_BASE; #ifdef CONFIG_SPL_LOAD_FIT if (image_get_magic(header) == FDT_MAGIC) { int ret; @@ -93,34 +93,8 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, * Load real U-Boot from its location in NOR flash to its * defined location in SDRAM */ - header = map_sysmem(spl_nor_get_uboot_base(), sizeof(*header)); -#ifdef CONFIG_SPL_LOAD_FIT - if (image_get_magic(header) == FDT_MAGIC) { - debug("Found FIT format U-Boot\n"); - spl_set_bl_len(&load, 1); - load.read = spl_nor_load_read; - return spl_load_simple_fit(spl_image, &load, - spl_nor_get_uboot_base(), - (void *)header); - } -#endif - if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && - valid_container_hdr((void *)header)) { - spl_set_bl_len(&load, 1); - load.read = spl_nor_load_read; - return spl_load_imx_container(spl_image, &load, - spl_nor_get_uboot_base()); - } - - /* Legacy image handling */ - if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT)) { - spl_set_bl_len(&load, 1); - load.read = spl_nor_load_read; - return spl_load_legacy_img(spl_image, bootdev, &load, - spl_nor_get_uboot_base(), - header); - } - - return -EINVAL; + spl_set_bl_len(&load, 1); + load.read = spl_nor_load_read; + return spl_load(spl_image, bootdev, &load, 0, spl_nor_get_uboot_base()); } SPL_LOAD_IMAGE_METHOD("NOR", 0, BOOT_DEVICE_NOR, spl_nor_load_image); -- cgit v1.1 From 6029a0e1affa19b83004083af3130e153af028fa Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:54 -0500 Subject: spl: Convert NVMe to spl_load This converts the blk load method (used exclusively by NVMe) to use spl_load. As a consequence, it also adds support for LOAD_FIT_FULL and IMX images. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_blk_fs.c | 66 +++++++++---------------------------------------- 1 file changed, 11 insertions(+), 55 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_blk_fs.c b/common/spl/spl_blk_fs.c index 53b8e1b..ac267ab 100644 --- a/common/spl/spl_blk_fs.c +++ b/common/spl/spl_blk_fs.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -48,11 +49,11 @@ int spl_blk_load_image(struct spl_image_info *spl_image, enum uclass_id uclass_id, int devnum, int partnum) { const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME; - struct legacy_img_hdr *header; struct blk_desc *blk_desc; - loff_t actlen, filesize; + loff_t filesize; struct blk_dev dev; - int ret = -ENODEV; + struct spl_load_info load; + int ret; blk_desc = blk_get_devnum_by_uclass_id(uclass_id, devnum); if (!blk_desc) { @@ -61,8 +62,8 @@ int spl_blk_load_image(struct spl_image_info *spl_image, } blk_show_device(uclass_id, devnum); - header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); + dev.filename = filename; dev.ifname = blk_get_uclass_name(uclass_id); snprintf(dev.dev_part_str, sizeof(dev.dev_part_str) - 1, "%x:%x", devnum, partnum); @@ -70,63 +71,18 @@ int spl_blk_load_image(struct spl_image_info *spl_image, if (ret) { printf("spl: unable to set blk_dev %s %s. Err - %d\n", dev.ifname, dev.dev_part_str, ret); - goto out; - } - - ret = fs_read(filename, virt_to_phys(header), 0, - sizeof(struct legacy_img_hdr), &actlen); - if (ret) { - printf("spl: unable to read file %s. Err - %d\n", filename, - ret); - goto out; - } - - if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && - image_get_magic(header) == FDT_MAGIC) { - struct spl_load_info load; - - debug("Found FIT\n"); - load.read = spl_fit_read; - spl_set_bl_len(&load, ARCH_DMA_MINALIGN); - load.priv = &dev; - dev.filename = filename; - - return spl_load_simple_fit(spl_image, &load, 0, header); - } - - ret = spl_parse_image_header(spl_image, bootdev, header); - if (ret) { - printf("spl: unable to parse image header. Err - %d\n", - ret); - goto out; - } - - ret = fs_set_blk_dev(dev.ifname, dev.dev_part_str, FS_TYPE_ANY); - if (ret) { - printf("spl: unable to set blk_dev %s %s. Err - %d\n", - dev.ifname, dev.dev_part_str, ret); - goto out; + return ret; } ret = fs_size(filename, &filesize); if (ret) { printf("spl: unable to get file size: %s. Err - %d\n", filename, ret); - goto out; - } - - ret = fs_set_blk_dev(dev.ifname, dev.dev_part_str, FS_TYPE_ANY); - if (ret) { - printf("spl: unable to set blk_dev %s %s. Err - %d\n", - dev.ifname, dev.dev_part_str, ret); - goto out; + return ret; } - ret = fs_read(filename, (ulong)spl_image->load_addr, 0, filesize, - &actlen); - if (ret) - printf("spl: unable to read file %s. Err - %d\n", - filename, ret); -out: - return ret; + load.read = spl_fit_read; + spl_set_bl_len(&load, ARCH_DMA_MINALIGN); + load.priv = &dev; + return spl_load(spl_image, bootdev, &load, filesize, 0); } -- cgit v1.1 From 9b9c6aaaf22e59bc903b640a26961cdba451140f Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:55 -0500 Subject: spl: Convert semihosting to spl_load This converts the semihosting load method to use spl_load. As a result, it also adds support for LOAD_FIT_FULL and IMX images. Signed-off-by: Sean Anderson --- common/spl/spl_semihosting.c | 52 +++++--------------------------------------- 1 file changed, 6 insertions(+), 46 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_semihosting.c b/common/spl/spl_semihosting.c index 9b0610b..941fa91 100644 --- a/common/spl/spl_semihosting.c +++ b/common/spl/spl_semihosting.c @@ -8,18 +8,7 @@ #include #include #include - -static int smh_read_full(long fd, void *memp, size_t len) -{ - long read; - - read = smh_read(fd, memp, len); - if (read < 0) - return read; - if (read != len) - return -EIO; - return 0; -} +#include static ulong smh_fit_read(struct spl_load_info *load, ulong file_offset, ulong size, void *buf) @@ -40,8 +29,7 @@ static int spl_smh_load_image(struct spl_image_info *spl_image, const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME; int ret; long fd, len; - struct legacy_img_hdr *header = - spl_get_load_buffer(-sizeof(*header), sizeof(*header)); + struct spl_load_info load; fd = smh_open(filename, MODE_READ | MODE_BINARY); if (fd < 0) { @@ -56,38 +44,10 @@ static int spl_smh_load_image(struct spl_image_info *spl_image, } len = ret; - ret = smh_read_full(fd, header, sizeof(struct legacy_img_hdr)); - if (ret) { - log_debug("could not read image header: %d\n", ret); - goto out; - } - - if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && - image_get_magic(header) == FDT_MAGIC) { - struct spl_load_info load; - - debug("Found FIT\n"); - load.read = smh_fit_read; - spl_set_bl_len(&load, 1); - load.priv = &fd; - - ret = spl_load_simple_fit(spl_image, &load, 0, header); - goto out; - } - - ret = spl_parse_image_header(spl_image, bootdev, header); - if (ret) { - log_debug("failed to parse image header: %d\n", ret); - goto out; - } - - ret = smh_seek(fd, 0); - if (ret) { - log_debug("could not seek to start of image: %d\n", ret); - goto out; - } - - ret = smh_read_full(fd, (void *)spl_image->load_addr, len); + load.read = smh_fit_read; + spl_set_bl_len(&load, 1); + load.priv = &fd; + ret = spl_load(spl_image, bootdev, &load, len, 0); if (ret) log_debug("could not read %s: %d\n", filename, ret); out: -- cgit v1.1 From a04d5f60a581ad5feac309ef014e47d41ccc8d48 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:56 -0500 Subject: spl: Convert spi to spl_load This converts the spi load method to use spl_load. The address used for LOAD_FIT_FULL may be different, but there are no in-tree users of that config. Since payload_offs is only used without OS_BOOT, we defer its initialization. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_spi.c | 80 +++++++++------------------------------------------- 1 file changed, 13 insertions(+), 67 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index 3e08ac7..f49e534 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -12,11 +12,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include @@ -95,9 +95,9 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, int err = 0; unsigned int payload_offs; struct spi_flash *flash; - struct legacy_img_hdr *header; unsigned int sf_bus = spl_spi_boot_bus(); unsigned int sf_cs = spl_spi_boot_cs(); + struct spl_load_info load; /* * Load U-Boot image from SPI flash into RAM @@ -112,77 +112,23 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, return -ENODEV; } - payload_offs = spl_spi_get_uboot_offs(flash); - - header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); +#if CONFIG_IS_ENABLED(OS_BOOT) + if (!spl_start_uboot() && !spi_load_image_os(spl_image, bootdev, flash, header)) + return 0; +#endif + payload_offs = spl_spi_get_uboot_offs(flash); if (CONFIG_IS_ENABLED(OF_REAL)) { payload_offs = ofnode_conf_read_int("u-boot,spl-payload-offset", payload_offs); } -#if CONFIG_IS_ENABLED(OS_BOOT) - if (spl_start_uboot() || spi_load_image_os(spl_image, bootdev, flash, header)) -#endif - { - /* Load u-boot, mkimage header is 64 bytes. */ - err = spi_flash_read(flash, payload_offs, sizeof(*header), - (void *)header); - if (err) { - debug("%s: Failed to read from SPI flash (err=%d)\n", - __func__, err); - return err; - } - - if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) && - image_get_magic(header) == FDT_MAGIC) { - u32 size = roundup(fdt_totalsize(header), 4); - - err = spi_flash_read(flash, payload_offs, - size, - map_sysmem(CONFIG_SYS_LOAD_ADDR, - size)); - if (err) - return err; - err = spl_parse_image_header(spl_image, bootdev, - phys_to_virt(CONFIG_SYS_LOAD_ADDR)); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && - image_get_magic(header) == FDT_MAGIC) { - struct spl_load_info load; - - debug("Found FIT\n"); - load.priv = flash; - spl_set_bl_len(&load, 1); - load.read = spl_spi_fit_read; - err = spl_load_simple_fit(spl_image, &load, - payload_offs, - header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && - valid_container_hdr((void *)header)) { - struct spl_load_info load; - - load.priv = flash; - spl_set_bl_len(&load, 1); - load.read = spl_spi_fit_read; - - err = spl_load_imx_container(spl_image, &load, - payload_offs); - } else { - err = spl_parse_image_header(spl_image, bootdev, header); - if (err) - return err; - err = spi_flash_read(flash, payload_offs + spl_image->offset, - spl_image->size, - map_sysmem(spl_image->load_addr, - spl_image->size)); - } - if (IS_ENABLED(CONFIG_SPI_FLASH_SOFT_RESET)) { - err = spi_nor_remove(flash); - if (err) - return err; - } - } - + load.priv = flash; + spl_set_bl_len(&load, 1); + load.read = spl_spi_fit_read; + err = spl_load(spl_image, bootdev, &load, 0, payload_offs); + if (IS_ENABLED(CONFIG_SPI_FLASH_SOFT_RESET)) + err = spi_nor_remove(flash); return err; } /* Use priorty 1 so that boards can override this */ -- cgit v1.1 From 14509a28aa20808875cc934eaf62f439345e6db6 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:57 -0500 Subject: spl: spi: Consolidate spi_load_image_os into spl_spi_load_image spi_load_image_os performs almost the same steps as the non-falcon-boot path of spl_spi_load_image. The load address is different, and it also loads a device tree, but that's it. Refactor the boot process so that they can both use the same load function. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/spl_spi.c | 54 ++++++++++++++-------------------------------------- 1 file changed, 14 insertions(+), 40 deletions(-) (limited to 'common/spl') diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index f49e534..89de73c 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -21,41 +21,6 @@ #include #include -#if CONFIG_IS_ENABLED(OS_BOOT) -/* - * Load the kernel, check for a valid header we can parse, and if found load - * the kernel and then device tree. - */ -static int spi_load_image_os(struct spl_image_info *spl_image, - struct spl_boot_device *bootdev, - struct spi_flash *flash, - struct legacy_img_hdr *header) -{ - int err; - - /* Read for a header, parse or error out. */ - spi_flash_read(flash, CFG_SYS_SPI_KERNEL_OFFS, sizeof(*header), - (void *)header); - - if (image_get_magic(header) != IH_MAGIC) - return -1; - - err = spl_parse_image_header(spl_image, bootdev, header); - if (err) - return err; - - spi_flash_read(flash, CFG_SYS_SPI_KERNEL_OFFS, - spl_image->size, (void *)spl_image->load_addr); - - /* Read device tree. */ - spi_flash_read(flash, CFG_SYS_SPI_ARGS_OFFS, - CFG_SYS_SPI_ARGS_SIZE, - (void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR); - - return 0; -} -#endif - static ulong spl_spi_fit_read(struct spl_load_info *load, ulong sector, ulong count, void *buf) { @@ -112,9 +77,21 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, return -ENODEV; } + load.priv = flash; + spl_set_bl_len(&load, 1); + load.read = spl_spi_fit_read; + #if CONFIG_IS_ENABLED(OS_BOOT) - if (!spl_start_uboot() && !spi_load_image_os(spl_image, bootdev, flash, header)) - return 0; + if (spl_start_uboot()) { + int err = spl_load(spl_image, bootdev, &load, 0, + CFG_SYS_SPI_KERNEL_OFFS); + + if (!err) + /* Read device tree. */ + return spi_flash_read(flash, CFG_SYS_SPI_ARGS_OFFS, + CFG_SYS_SPI_ARGS_SIZE, + (void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR); + } #endif payload_offs = spl_spi_get_uboot_offs(flash); @@ -123,9 +100,6 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, payload_offs); } - load.priv = flash; - spl_set_bl_len(&load, 1); - load.read = spl_spi_fit_read; err = spl_load(spl_image, bootdev, &load, 0, payload_offs); if (IS_ENABLED(CONFIG_SPI_FLASH_SOFT_RESET)) err = spi_nor_remove(flash); -- cgit v1.1 From 54a8d845be4f236a5eb7c93d927ff16cb3efb5fe Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 8 Nov 2023 11:48:58 -0500 Subject: spl: fat: Add option to disable DMA alignment If we don't DMA-align buffers we pass to FAT, it will align them itself. This behaviour likely should be deprecated in favor of CONFIG_BOUNCE_BUFFER, but that's a task for another series. For the meantime, don't bother aligning the buffer unless we had been doing so in the past. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- common/spl/Kconfig | 18 ++++++++++++++++-- common/spl/spl_blk_fs.c | 5 ++++- common/spl/spl_fat.c | 5 ++++- 3 files changed, 24 insertions(+), 4 deletions(-) (limited to 'common/spl') diff --git a/common/spl/Kconfig b/common/spl/Kconfig index b935269..fc284a5 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -694,13 +694,28 @@ config SPL_FS_SQUASHFS config SPL_FS_FAT bool "Support FAT filesystems" select FS_FAT - select SPL_LOAD_BLOCK help Enable support for FAT and VFAT filesystems with SPL. This permits U-Boot (or Linux in Falcon mode) to be loaded from a FAT filesystem from within SPL. Support for the underlying block device (e.g. MMC or USB) must be enabled separately. +config SPL_FS_FAT_DMA_ALIGN + bool "Use DMA-aligned buffers with FAT" + depends on SPL_FS_FAT + select SPL_LOAD_BLOCK + default y if SPL_LOAD_FIT + help + The FAT filesystem driver tries to ensure that the reads it issues to + the block subsystem use DMA-aligned buffers. If the supplied buffer is + not DMA-aligned, the FAT driver will use a bounce-buffer and read + block-by-block. This is separate from the bounce-buffer used by the + block subsystem (CONFIG_BOUNCE_BUFFER). + + Enable this config to align buffers passed to the FAT filesystem + driver. This will speed up reads, but will increase the size of U-Boot + by around 60 bytes. + config SPL_FS_LOAD_PAYLOAD_NAME string "File to load for U-Boot from the filesystem" depends on SPL_FS_EXT4 || SPL_FS_FAT || SPL_FS_SQUASHFS || SPL_SEMIHOSTING @@ -1282,7 +1297,6 @@ config SPL_NVME depends on BLK select FS_LOADER select SPL_BLK_FS - select SPL_LOAD_BLOCK help This option enables support for NVM Express devices. It supports basic functions of NVMe (read/write). diff --git a/common/spl/spl_blk_fs.c b/common/spl/spl_blk_fs.c index ac267ab..04eac6f 100644 --- a/common/spl/spl_blk_fs.c +++ b/common/spl/spl_blk_fs.c @@ -82,7 +82,10 @@ int spl_blk_load_image(struct spl_image_info *spl_image, } load.read = spl_fit_read; - spl_set_bl_len(&load, ARCH_DMA_MINALIGN); + if (IS_ENABLED(CONFIG_SPL_FS_FAT_DMA_ALIGN)) + spl_set_bl_len(&load, ARCH_DMA_MINALIGN); + else + spl_set_bl_len(&load, 1); load.priv = &dev; return spl_load(spl_image, bootdev, &load, filesize, 0); } diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index 569f2b3..a52f9e1 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -86,7 +86,10 @@ int spl_load_image_fat(struct spl_image_info *spl_image, } load.read = spl_fit_read; - spl_set_bl_len(&load, ARCH_DMA_MINALIGN); + if (IS_ENABLED(CONFIG_SPL_FS_FAT_DMA_ALIGN)) + spl_set_bl_len(&load, ARCH_DMA_MINALIGN); + else + spl_set_bl_len(&load, 1); load.priv = (void *)filename; err = spl_load(spl_image, bootdev, &load, size, 0); -- cgit v1.1