diff options
36 files changed, 531 insertions, 730 deletions
diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c index 93d48e5..9f0968c 100644 --- a/arch/arm/mach-imx/spl_imx_romapi.c +++ b/arch/arm/mach-imx/spl_imx_romapi.c @@ -53,16 +53,10 @@ static int is_boot_from_stream_device(u32 boot) } static ulong spl_romapi_read_seekable(struct spl_load_info *load, - ulong sector, ulong count, + ulong offset, ulong byte, void *buf) { - u32 pagesize = *(u32 *)load->priv; - ulong byte = count * pagesize; - u32 offset; - - offset = sector * pagesize; - - return spl_romapi_raw_seekable_read(offset, byte, buf) / pagesize; + return spl_romapi_raw_seekable_read(offset, byte, buf); } static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image, @@ -107,20 +101,18 @@ static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image, struct spl_load_info load; memset(&load, 0, sizeof(load)); - load.bl_len = pagesize; + spl_set_bl_len(&load, pagesize); load.read = spl_romapi_read_seekable; - load.priv = &pagesize; - return spl_load_simple_fit(spl_image, &load, offset / pagesize, 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; memset(&load, 0, sizeof(load)); - load.bl_len = pagesize; + spl_set_bl_len(&load, pagesize); load.read = spl_romapi_read_seekable; - load.priv = &pagesize; - ret = spl_load_imx_container(spl_image, &load, offset / pagesize); + ret = spl_load_imx_container(spl_image, &load, offset); } else { /* TODO */ puts("Can't support legacy image\n"); @@ -342,7 +334,7 @@ static int spl_romapi_load_image_stream(struct spl_image_info *spl_image, ss.pagesize = pagesize; memset(&load, 0, sizeof(load)); - load.bl_len = 1; + spl_set_bl_len(&load, 1); load.read = spl_romapi_read_stream; load.priv = &ss; @@ -366,7 +358,7 @@ static int spl_romapi_load_image_stream(struct spl_image_info *spl_image, printf("ROM download failure %d\n", imagesize); memset(&load, 0, sizeof(load)); - load.bl_len = 1; + spl_set_bl_len(&load, 1); load.read = spl_ram_load_read; if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c index c2410dd..267cb0b 100644 --- a/arch/arm/mach-sunxi/spl_spi_sunxi.c +++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c @@ -354,10 +354,7 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, struct spl_load_info load; debug("Found FIT image\n"); - load.dev = NULL; - load.priv = NULL; - load.filename = NULL; - load.bl_len = 1; + spl_set_bl_len(&load, 1); load.read = spi_load_read; ret = spl_load_simple_fit(spl_image, &load, load_offset, header); diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 00332cf..fc284a5 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 @@ -279,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 @@ -473,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 || \ @@ -481,6 +494,8 @@ 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 + select SPL_SYS_MMCSD_RAW_MODE if SPL_MMC help Use sector number for specifying U-Boot location on MMC/SD in raw mode. @@ -517,6 +532,8 @@ 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. @@ -683,6 +700,22 @@ config SPL_FS_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 @@ -876,6 +909,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. @@ -1101,6 +1135,8 @@ 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 + select SPL_SYS_MMCSD_RAW_MODE help Select this if the Falcon mode OS image mode is on MMC or SD media. @@ -1259,7 +1295,6 @@ 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 help diff --git a/common/spl/spl.c b/common/spl/spl.c index 732d90d..3ce5bfe 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -19,6 +19,7 @@ #include <mapmem.h> #include <serial.h> #include <spl.h> +#include <spl_load.h> #include <system-constants.h> #include <asm/global_data.h> #include <asm-generic/gpio.h> @@ -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); @@ -718,8 +728,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 diff --git a/common/spl/spl_blk_fs.c b/common/spl/spl_blk_fs.c index 63825d6..04eac6f 100644 --- a/common/spl/spl_blk_fs.c +++ b/common/spl/spl_blk_fs.c @@ -7,12 +7,15 @@ #include <common.h> #include <spl.h> +#include <spl_load.h> #include <image.h> #include <fs.h> +#include <asm/cache.h> #include <asm/io.h> struct blk_dev { const char *ifname; + const char *filename; char dev_part_str[8]; }; @@ -30,11 +33,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; } @@ -46,10 +49,10 @@ 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; + struct spl_load_info load; int ret; blk_desc = blk_get_devnum_by_uclass_id(uclass_id, devnum); @@ -59,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); @@ -68,63 +71,21 @@ 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; - load.bl_len = 1; - load.filename = (void *)filename; - load.priv = &dev; - - 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; + 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_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 <common.h> #include <env.h> -#include <mapmem.h> #include <part.h> #include <spl.h> +#include <spl_load.h> #include <asm/u-boot.h> #include <ext4fs.h> #include <errno.h> #include <image.h> +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 diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index 014074f..a52f9e1 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -11,8 +11,8 @@ #include <common.h> #include <env.h> #include <log.h> -#include <mapmem.h> #include <spl.h> +#include <spl_load.h> #include <asm/u-boot.h> #include <fat.h> #include <errno.h> @@ -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) @@ -66,59 +66,41 @@ 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; - load.bl_len = 1; - load.filename = (void *)filename; - load.priv = NULL; - - 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; + 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); + 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) diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 70d8d59..872df0c 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -14,7 +14,6 @@ #include <mapmem.h> #include <spl.h> #include <sysinfo.h> -#include <asm/cache.h> #include <asm/global_data.h> #include <asm/io.h> #include <linux/libfdt.h> @@ -172,29 +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) { - /* - * 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 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) { - /* - * 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; + return offset & (spl_get_bl_len(info) - 1); } static int get_aligned_image_size(struct spl_load_info *info, int data_size, @@ -202,10 +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); - if (info->filename) - return data_size; - - return (data_size + info->bl_len - 1) / info->bl_len; + return ALIGN(data_size, spl_get_bl_len(info)); } /** @@ -222,7 +201,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 +213,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 +269,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) < length) return -EIO; debug("External data: dst=%p, offset=%x, size=%lx\n", @@ -380,7 +359,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 +393,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 +444,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 +621,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 +636,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 +646,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 +668,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 +706,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 +715,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 +730,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 +760,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 +778,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 +801,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 +815,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 127802f..b4ea924 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"); @@ -33,22 +32,21 @@ 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, 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; } - sectors = roundup(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, spl_get_bl_len(info)); + 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)) < + images[image_index].size) { printf("%s wrong\n", __func__); return NULL; } @@ -62,15 +60,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 = roundup(CONTAINER_HDR_ALIGNMENT, info->bl_len); - sectors = size / 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, @@ -80,9 +76,10 @@ 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) < + CONTAINER_HDR_ALIGNMENT) { ret = -EIO; goto end; } @@ -103,18 +100,16 @@ 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); - sectors = size / info->bl_len; + size = ALIGN(length, spl_get_bl_len(info)); 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) < length) { ret = -EIO; goto end; } @@ -129,7 +124,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 +149,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_legacy.c b/common/spl/spl_legacy.c index 9189576..08687ca 100644 --- a/common/spl/spl_legacy.c +++ b/common/spl/spl_legacy.c @@ -82,95 +82,39 @@ int spl_parse_legacy_header(struct spl_image_info *spl_image, 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) +int spl_load_legacy_lzma(struct spl_image_info *spl_image, + struct spl_load_info *load, ulong offset) { - 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) -{ - __maybe_unused SizeT lzma_len; - __maybe_unused void *src; - ulong dataptr; + SizeT lzma_len = LZMA_LEN; + void *src; + ulong dataptr, overhead, size; 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; + /* 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; + } - ret = spl_parse_image_header(spl_image, bootdev, hdr); - if (ret) + 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; - - /* 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: { - ulong overhead, size; - - lzma_len = LZMA_LEN; - - /* dataptr points to compressed payload */ - dataptr = ALIGN_DOWN(sizeof(*hdr), load->bl_len); - overhead = sizeof(*hdr) - dataptr; - size = ALIGN(spl_image->size + overhead, load->bl_len); - 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; - } - default: - debug("Compression method %s is not supported\n", - genimg_get_comp_short_name(image_get_comp(hdr))); - return -EINVAL; } + spl_image->size = lzma_len; return 0; } diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 82689da..3d032bb 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -8,9 +8,9 @@ #include <common.h> #include <dm.h> #include <log.h> -#include <mapmem.h> #include <part.h> #include <spl.h> +#include <spl_load.h> #include <linux/compiler.h> #include <errno.h> #include <asm/u-boot.h> @@ -19,55 +19,14 @@ #include <image.h> #include <imx_container.h> -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) +static ulong h_spl_load_read(struct spl_load_info *load, ulong off, + ulong size, void *buf) { - 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; + struct blk_desc *bd = load->priv; + lbaint_t sector = off >> bd->log2blksz; + lbaint_t count = size >> bd->log2blksz; - /* 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 sector, - ulong count, void *buf) -{ - struct mmc *mmc = load->dev; - - 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) @@ -85,48 +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.dev = mmc; - load.priv = NULL; - load.filename = NULL; - load.bl_len = mmc->read_bl_len; - load.read = h_spl_load_read; - ret = spl_load_simple_fit(spl_image, &load, sector, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && - valid_container_hdr((void *)header)) { - 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; - - ret = spl_load_imx_container(spl_image, &load, sector); - } 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"); diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index b8cd640..3b0a152 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -10,6 +10,7 @@ #include <imx_container.h> #include <log.h> #include <spl.h> +#include <spl_load.h> #include <asm/io.h> #include <mapmem.h> #include <nand.h> @@ -42,32 +43,24 @@ 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 *= 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 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); + spl_set_bl_len(load, nand_page_size()); if (err) return 0; @@ -75,67 +68,20 @@ static ulong spl_nand_legacy_read(struct spl_load_info *load, ulong offs, } 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.dev = NULL; - 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 / bl_len, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && - valid_container_hdr((void *)header)) { - struct spl_load_info load; - - load.dev = NULL; - 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 / bl_len); - } 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.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; - - 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"); @@ -144,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 @@ -190,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(); diff --git a/common/spl/spl_net.c b/common/spl/spl_net.c index f01d4df..898f9df 100644 --- a/common/spl/spl_net.c +++ b/common/spl/spl_net.c @@ -11,8 +11,8 @@ #include <errno.h> #include <image.h> #include <log.h> -#include <mapmem.h> #include <spl.h> +#include <spl_load.h> #include <net.h> #include <linux/libfdt.h> @@ -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"); - load.bl_len = 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 diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c index 236b071..7074511 100644 --- a/common/spl/spl_nor.c +++ b/common/spl/spl_nor.c @@ -7,8 +7,8 @@ #include <image.h> #include <imx_container.h> #include <log.h> -#include <mapmem.h> #include <spl.h> +#include <spl_load.h> 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,13 +42,14 @@ 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; 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, @@ -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"); - load.bl_len = 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)) { - load.bl_len = 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)) { - load.bl_len = 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); 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 f7dd289..941fa91 100644 --- a/common/spl/spl_semihosting.c +++ b/common/spl/spl_semihosting.c @@ -8,34 +8,19 @@ #include <log.h> #include <semihosting.h> #include <spl.h> - -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 <spl_load.h> 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, @@ -44,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) { @@ -60,39 +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; - load.bl_len = 1; - load.filename = filename; - load.priv = NULL; - smh_close(fd); - - return spl_load_simple_fit(spl_image, &load, 0, header); - } - - 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: diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index 3ac4b1b..89de73c 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -12,54 +12,19 @@ #include <image.h> #include <imx_container.h> #include <log.h> -#include <mapmem.h> #include <spi.h> #include <spi_flash.h> #include <errno.h> #include <spl.h> +#include <spl_load.h> #include <asm/global_data.h> #include <asm/io.h> #include <dm/ofnode.h> -#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) { - struct spi_flash *flash = load->dev; + struct spi_flash *flash = load->priv; ulong ret; ret = spi_flash_read(flash, sector, count, buf); @@ -95,9 +60,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,81 +77,32 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, return -ENODEV; } - payload_offs = spl_spi_get_uboot_offs(flash); + load.priv = flash; + spl_set_bl_len(&load, 1); + load.read = spl_spi_fit_read; - header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); +#if CONFIG_IS_ENABLED(OS_BOOT) + 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); 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.dev = flash; - load.priv = NULL; - load.filename = NULL; - load.bl_len = 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.dev = flash; - load.priv = NULL; - load.filename = NULL; - load.bl_len = 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; - } - } - + 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 */ diff --git a/common/spl/spl_ymodem.c b/common/spl/spl_ymodem.c index 038b443..1faaa2c 100644 --- a/common/spl/spl_ymodem.c +++ b/common/spl/spl_ymodem.c @@ -134,10 +134,8 @@ 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; + spl_set_bl_len(&load, 1); info.buf = buf; info.image_read = BUF_SIZE; load.read = ymodem_read_fit; diff --git a/configs/am335x_evm_spiboot_defconfig b/configs/am335x_evm_spiboot_defconfig index b5b11fb..fff5265 100644 --- a/configs/am335x_evm_spiboot_defconfig +++ b/configs/am335x_evm_spiboot_defconfig @@ -13,6 +13,7 @@ CONFIG_CLOCK_SYNTHESIZER=y # CONFIG_OF_LIBFDT_OVERLAY is not set # CONFIG_SPL_MMC is not set CONFIG_SPL=y +# CONFIG_SPL_FS_FAT is not set CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI=y CONFIG_TIMESTAMP=y @@ -27,7 +28,6 @@ CONFIG_SPL_SYS_MALLOC=y CONFIG_SPL_SYS_MALLOC_SIZE=0x800000 CONFIG_SPL_FIT_IMAGE_TINY=y # CONFIG_SPL_FS_EXT4 is not set -CONFIG_SPL_FS_LOAD_PAYLOAD_NAME="u-boot.img" CONFIG_SPL_MTD=y # CONFIG_SPL_NAND_SUPPORT is not set CONFIG_SPL_DM_SPI_FLASH=y diff --git a/configs/am65x_evm_r5_usbdfu_defconfig b/configs/am65x_evm_r5_usbdfu_defconfig index f610b2d..6b0bb12 100644 --- a/configs/am65x_evm_r5_usbdfu_defconfig +++ b/configs/am65x_evm_r5_usbdfu_defconfig @@ -21,7 +21,6 @@ CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_SPL_SIZE_LIMIT=0x7ec00 CONFIG_SPL_SIZE_LIMIT_PROVIDE_STACK=0x2000 -CONFIG_SPL_FS_FAT=y CONFIG_SPL_LIBDISK_SUPPORT=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_LOAD_FIT=y diff --git a/configs/xilinx_zynqmp_mini_qspi_defconfig b/configs/xilinx_zynqmp_mini_qspi_defconfig index a1adfb9..b044743 100644 --- a/configs/xilinx_zynqmp_mini_qspi_defconfig +++ b/configs/xilinx_zynqmp_mini_qspi_defconfig @@ -11,6 +11,8 @@ CONFIG_ENV_SIZE=0x80 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-mini-qspi" CONFIG_SPL_STACK=0xfffffffc CONFIG_SPL=y +# CONFIG_SPL_FS_FAT is not set +# CONFIG_SPL_LIBDISK_SUPPORT is not set CONFIG_SYS_MEM_RSVD_FOR_MMU=y CONFIG_ZYNQMP_NO_DDR=y # CONFIG_PSCI_RESET is not set @@ -89,7 +91,6 @@ CONFIG_SPI_FLASH_WINBOND=y CONFIG_ARM_DCC=y CONFIG_SPI=y CONFIG_ZYNQMP_GQSPI=y -# CONFIG_FAT_WRITE is not set CONFIG_PANIC_HANG=y # CONFIG_GZIP is not set # CONFIG_LMB is not set diff --git a/configs/zynq_cse_nand_defconfig b/configs/zynq_cse_nand_defconfig index 19f653f..2eb45e1 100644 --- a/configs/zynq_cse_nand_defconfig +++ b/configs/zynq_cse_nand_defconfig @@ -13,6 +13,8 @@ CONFIG_DEFAULT_DEVICE_TREE="zynq-cse-nand" CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_SPL_STACK=0xfffffe00 CONFIG_SPL=y +# CONFIG_SPL_FS_FAT is not set +# CONFIG_SPL_LIBDISK_SUPPORT is not set CONFIG_SYS_LOAD_ADDR=0x0 CONFIG_REMAKE_ELF=y CONFIG_SYS_CUSTOM_LDSCRIPT=y diff --git a/configs/zynq_cse_nor_defconfig b/configs/zynq_cse_nor_defconfig index 64df1f0..c5a28f2 100644 --- a/configs/zynq_cse_nor_defconfig +++ b/configs/zynq_cse_nor_defconfig @@ -13,6 +13,8 @@ CONFIG_DEFAULT_DEVICE_TREE="zynq-cse-nor" CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_SPL_STACK=0xfffffe00 CONFIG_SPL=y +# CONFIG_SPL_FS_FAT is not set +# CONFIG_SPL_LIBDISK_SUPPORT is not set CONFIG_SYS_LOAD_ADDR=0x0 CONFIG_REMAKE_ELF=y CONFIG_SYS_CUSTOM_LDSCRIPT=y diff --git a/configs/zynq_cse_qspi_defconfig b/configs/zynq_cse_qspi_defconfig index 9368fb4..9a2770a 100644 --- a/configs/zynq_cse_qspi_defconfig +++ b/configs/zynq_cse_qspi_defconfig @@ -16,6 +16,8 @@ CONFIG_SPL_STACK=0xfffffe00 CONFIG_SPL=y CONFIG_DEBUG_UART_BASE=0x0 CONFIG_DEBUG_UART_CLOCK=0 +# CONFIG_SPL_FS_FAT is not set +# CONFIG_SPL_LIBDISK_SUPPORT is not set # CONFIG_ZYNQ_DDRC_INIT is not set # CONFIG_CMD_ZYNQ is not set CONFIG_SYS_LOAD_ADDR=0x0 diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c index ee9384f..ca2760c 100644 --- a/drivers/usb/gadget/f_sdp.c +++ b/drivers/usb/gadget/f_sdp.c @@ -744,7 +744,7 @@ static ulong sdp_load_read(struct spl_load_info *load, ulong sector, { debug("%s: sector %lx, count %lx, buf %lx\n", __func__, sector, count, (ulong)buf); - memcpy(buf, (void *)(load->dev + sector), count); + memcpy(buf, (void *)(load->priv + sector), count); return count; } @@ -844,8 +844,8 @@ static int sdp_handle_in_ep(struct spl_image_info *spl_image, struct spl_load_info load; debug("Found FIT\n"); - load.dev = header; - load.bl_len = 1; + load.priv = header; + spl_set_bl_len(&load, 1); load.read = sdp_load_read; spl_load_simple_fit(spl_image, &load, 0, header); @@ -857,8 +857,8 @@ static int sdp_handle_in_ep(struct spl_image_info *spl_image, valid_container_hdr((void *)header)) { struct spl_load_info load; - load.dev = header; - load.bl_len = 1; + load.priv = header; + spl_set_bl_len(&load, 1); load.read = sdp_load_read; spl_load_imx_container(spl_image, &load, 0); return SDP_EXIT; diff --git a/include/spl.h b/include/spl.h index 8ff20ad..0952188 100644 --- a/include/spl.h +++ b/include/spl.h @@ -285,30 +285,53 @@ static inline void *spl_image_fdt_addr(struct spl_image_info *info) /** * Information required to load data from a device * - * @dev: Pointer to the device, e.g. struct mmc * * @priv: Private data for the device * @bl_len: Block length for reading in bytes - * @filename: Name of the fit image file. * @read: Function to call to read from the device */ struct spl_load_info { - void *dev; void *priv; - int bl_len; - const char *filename; /** * read() - Read from device * * @load: Information about the load state - * @sector: Sector number to read from (each @load->bl_len bytes) - * @count: Number of sectors to read + * @offset: Offset to read from in bytes. This must be a multiple of + * @load->bl_len. + * @count: Number of bytes to read. This must be a multiple of + * @load->bl_len. * @buf: Buffer to read into - * @return number of sectors read, 0 on error + * @return number of bytes read, 0 on error */ ulong (*read)(struct spl_load_info *load, ulong sector, ulong count, void *buf); +#if IS_ENABLED(CONFIG_SPL_LOAD_BLOCK) + int bl_len; +}; + +static inline int spl_get_bl_len(struct spl_load_info *info) +{ + return info->bl_len; +} + +static inline void spl_set_bl_len(struct spl_load_info *info, int bl_len) +{ + info->bl_len = bl_len; +} +#else }; +static inline int spl_get_bl_len(struct spl_load_info *info) +{ + return 1; +} + +static inline void spl_set_bl_len(struct spl_load_info *info, int bl_len) +{ + if (bl_len != 1) + panic("CONFIG_SPL_LOAD_BLOCK not enabled"); +} +#endif + /* * We need to know the position of U-Boot in memory so we can jump to it. We * allow any U-Boot binary to be used (u-boot.bin, u-boot-nodtb.bin, @@ -370,7 +393,8 @@ void *spl_load_simple_fit_fix_load(const void *fit); * spl_load_simple_fit() - Loads a fit image from a device. * @spl_image: Image description to set up * @info: Structure containing the information required to load data. - * @sector: Sector number where FIT image is located in the device + * @offset: Offset where FIT image is located in the device. Must be aligned + * to the device's bl_len. * @fdt: Pointer to the copied FIT header. * * Reads the FIT image @sector in the device. Loads u-boot image to @@ -378,12 +402,25 @@ void *spl_load_simple_fit_fix_load(const void *fit); * Returns 0 on success. */ int spl_load_simple_fit(struct spl_image_info *spl_image, - struct spl_load_info *info, ulong sector, void *fdt); + struct spl_load_info *info, ulong offset, void *fdt); #define SPL_COPY_PAYLOAD_ONLY 1 #define SPL_FIT_FOUND 2 /** + * spl_load_legacy_lzma() - Load an LZMA-compressed legacy image + * @spl_image: Image description (already set up) + * @load: Structure containing the information required to load data. + * @offset: Pointer to image + * + * Load/decompress an LZMA-compressed legacy image from the device. + * + * Return: 0 on success, or a negative error on failure + */ +int spl_load_legacy_lzma(struct spl_image_info *spl_image, + struct spl_load_info *load, ulong offset); + +/** * spl_load_legacy_img() - Loads a legacy image from a device. * @spl_image: Image description to set up * @load: Structure containing the information required to load data. @@ -404,13 +441,14 @@ int spl_load_legacy_img(struct spl_image_info *spl_image, * spl_load_imx_container() - Loads a imx container image from a device. * @spl_image: Image description to set up * @info: Structure containing the information required to load data. - * @sector: Sector number where container image is located in the device + * @sector: Offset where container image is located in the device. Must be + * aligned to the device block size. * * Reads the container image @sector in the device. Loads u-boot image to * specified load address. */ 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); /* SPL common functions */ void preloader_console_init(void); diff --git a/include/spl_load.h b/include/spl_load.h new file mode 100644 index 0000000..1c2b296 --- /dev/null +++ b/include/spl_load.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) Sean Anderson <seanga2@gmail.com> + */ +#ifndef _SPL_LOAD_H_ +#define _SPL_LOAD_H_ + +#include <image.h> +#include <imx_container.h> +#include <mapmem.h> +#include <spl.h> + +static inline 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) +{ + struct legacy_img_hdr *header = + spl_get_load_buffer(-sizeof(*header), sizeof(*header)); + ulong base_offset, image_offset, overhead; + int read, ret; + + read = info->read(info, offset, ALIGN(sizeof(*header), + spl_get_bl_len(info)), header); + if (read < sizeof(*header)) + return -EIO; + + if (image_get_magic(header) == FDT_MAGIC) { + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL)) { + void *buf; + + /* + * In order to support verifying images in the FIT, we + * need to load the whole FIT into memory. Try and + * guess how much we need to load by using the total + * size. This will fail for FITs with external data, + * but there's not much we can do about that. + */ + if (!size) + size = round_up(fdt_totalsize(header), 4); + buf = map_sysmem(CONFIG_SYS_LOAD_ADDR, size); + read = info->read(info, offset, + ALIGN(size, spl_get_bl_len(info)), + buf); + if (read < size) + return -EIO; + + return spl_parse_image_header(spl_image, bootdev, buf); + } + + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) + return spl_load_simple_fit(spl_image, info, offset, + header); + } + + if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) + return spl_load_imx_container(spl_image, info, offset); + + if (IS_ENABLED(CONFIG_SPL_LZMA) && + image_get_magic(header) == IH_MAGIC && + image_get_comp(header) == IH_COMP_LZMA) { + spl_image->flags |= SPL_COPY_PAYLOAD_ONLY; + ret = spl_parse_image_header(spl_image, bootdev, header); + if (ret) + return ret; + + return spl_load_legacy_lzma(spl_image, info, offset); + } + + ret = spl_parse_image_header(spl_image, bootdev, header); + if (ret) + return ret; + + base_offset = spl_image->offset; + /* Only NOR sets this flag. */ + if (IS_ENABLED(CONFIG_SPL_NOR_SUPPORT) && + spl_image->flags & SPL_COPY_PAYLOAD_ONLY) + base_offset += sizeof(*header); + image_offset = ALIGN_DOWN(base_offset, spl_get_bl_len(info)); + overhead = base_offset - image_offset; + size = ALIGN(spl_image->size + overhead, spl_get_bl_len(info)); + + read = info->read(info, offset + image_offset, size, + map_sysmem(spl_image->load_addr - overhead, size)); + return read < spl_image->size ? -EIO : 0; +} + +/* + * Although spl_load results in size reduction for callers, this is generally + * not enough to counteract the bloat if there is only one caller. The core + * problem is that the compiler can't optimize across translation units. The + * general solution to this is CONFIG_LTO, but that is not available on all + * architectures. Perform a pseudo-LTO just for this function by declaring it + * inline if there is one caller, and extern otherwise. + */ +#define SPL_LOAD_USERS \ + IS_ENABLED(CONFIG_SPL_BLK_FS) + \ + IS_ENABLED(CONFIG_SPL_FS_EXT4) + \ + IS_ENABLED(CONFIG_SPL_FS_FAT) + \ + IS_ENABLED(CONFIG_SPL_SYS_MMCSD_RAW_MODE) + \ + (IS_ENABLED(CONFIG_SPL_NAND_SUPPORT) && !IS_ENABLED(CONFIG_SPL_UBI)) + \ + IS_ENABLED(CONFIG_SPL_NET) + \ + IS_ENABLED(CONFIG_SPL_NOR_SUPPORT) + \ + IS_ENABLED(CONFIG_SPL_SEMIHOSTING) + \ + IS_ENABLED(CONFIG_SPL_SPI_LOAD) + \ + 0 + +#if SPL_LOAD_USERS > 1 +/** + * spl_load() - Parse a header and load the image + * @spl_image: Image data which will be filled in by this function + * @bootdev: The device to load from + * @info: Describes how to load additional information from @bootdev. At the + * minimum, read() and bl_len must be populated. + * @size: The size of the image, in bytes, if it is known in advance. Some boot + * devices (such as filesystems) know how big an image is before parsing + * the header. If 0, then the size will be determined from the header. + * @offset: The offset from the start of @bootdev, in bytes. This should have + * the offset @header was loaded from. It will be added to any offsets + * passed to @info->read(). + * + * This function determines the image type (FIT, legacy, i.MX, raw, etc), calls + * the appropriate parsing function, determines the load address, and the loads + * the image from storage. It is designed to replace ad-hoc image loading which + * may not support all image types (especially when config options are + * involved). + * + * Return: 0 on success, or a negative error on failure + */ +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); +#else +static inline 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 + +#endif /* _SPL_LOAD_H_ */ diff --git a/include/test/spl.h b/include/test/spl.h index c1f6465..a2a5f33 100644 --- a/include/test/spl.h +++ b/include/test/spl.h @@ -81,6 +81,10 @@ size_t create_image(void *dst, enum spl_test_image type, int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1, struct spl_image_info *info2); +/* Some compressed data and it size */ +extern const char lzma_compressed[]; +extern const size_t lzma_compressed_size; + /** * typedef write_image_t - Callback for writing an image * @uts: Current unit test state diff --git a/test/image/Kconfig b/test/image/Kconfig index 6f0bb81..45b6e8c 100644 --- a/test/image/Kconfig +++ b/test/image/Kconfig @@ -52,6 +52,7 @@ config SPL_UT_LOAD_SPI config SPL_UT_LOAD_OS bool "Test loading from the host OS" depends on SANDBOX && SPL_LOAD_FIT + select SPL_LOAD_BLOCK default y help Smoke test to ensure that loading U-boot works in sandbox. diff --git a/test/image/spl_load.c b/test/image/spl_load.c index ab4c14d..e1036ef 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -342,12 +342,11 @@ static int spl_test_image(struct unit_test_state *uts, const char *test_name, if (check_image_info(uts, &info_write, &info_read)) return CMD_RET_FAILURE; } else { - struct spl_load_info load = { - .bl_len = 1, - .priv = img, - .read = spl_test_read, - }; + struct spl_load_info load; + spl_set_bl_len(&load, 1); + load.priv = img; + load.read = spl_test_read; if (type == IMX8) ut_assertok(spl_load_imx_container(&info_read, &load, 0)); @@ -375,7 +374,7 @@ SPL_IMG_TEST(spl_test_image, FIT_EXTERNAL, 0); * LZMA is too complex to generate on the fly, so let's use some data I put in * the oven^H^H^H^H compressed earlier */ -static const char lzma_compressed[] = { +const char lzma_compressed[] = { 0x5d, 0x00, 0x00, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x02, 0x05, 0x55, 0x4e, 0x82, 0xbc, 0xc2, 0x42, 0xf6, 0x88, 0x6c, 0x99, 0xd6, 0x82, 0x48, 0xa6, 0x06, 0x67, 0xf8, 0x46, 0x7c, 0xe9, @@ -611,6 +610,8 @@ static const char lzma_compressed[] = { 0x1e, 0xff, 0xff, 0x80, 0x8e, 0x00, 0x00 }; +const size_t lzma_compressed_size = sizeof(lzma_compressed); + int do_spl_test_load(struct unit_test_state *uts, const char *test_name, enum spl_test_image type, struct spl_image_loader *loader, int (*write_image)(struct unit_test_state *, void *, size_t)) diff --git a/test/image/spl_load_fs.c b/test/image/spl_load_fs.c index 297ab08..5f1de54 100644 --- a/test/image/spl_load_fs.c +++ b/test/image/spl_load_fs.c @@ -320,10 +320,11 @@ static int spl_test_mmc_fs(struct unit_test_state *uts, const char *test_name, const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME; struct blk_desc *dev_desc; size_t fs_size, fs_data, img_size, img_data, - data_size = SPL_TEST_DATA_SIZE; + plain_size = SPL_TEST_DATA_SIZE; struct spl_image_info info_write = { .name = test_name, - .size = data_size, + .size = type == LEGACY_LZMA ? lzma_compressed_size : + plain_size, }, info_read = { }; struct disk_partition part = { .start = 1, @@ -335,7 +336,7 @@ static int spl_test_mmc_fs(struct unit_test_state *uts, const char *test_name, .boot_device = loader->boot_device, }; void *fs; - char *data; + char *data, *plain; img_size = create_image(NULL, type, &info_write, &img_data); ut_assert(img_size); @@ -345,7 +346,15 @@ static int spl_test_mmc_fs(struct unit_test_state *uts, const char *test_name, ut_assertnonnull(fs); data = fs + fs_data + img_data; - generate_data(data, data_size, test_name); + if (type == LEGACY_LZMA) { + plain = malloc(plain_size); + ut_assertnonnull(plain); + generate_data(plain, plain_size, "lzma"); + memcpy(data, lzma_compressed, lzma_compressed_size); + } else { + plain = data; + generate_data(plain, plain_size, test_name); + } ut_asserteq(img_size, create_image(fs + fs_data, type, &info_write, NULL)); ut_asserteq(fs_size, create_fs(fs, img_size, filename, NULL)); @@ -366,8 +375,12 @@ static int spl_test_mmc_fs(struct unit_test_state *uts, const char *test_name, ut_assertok(loader->load_image(&info_read, &bootdev)); if (check_image_info(uts, &info_write, &info_read)) return CMD_RET_FAILURE; - ut_asserteq_mem(data, phys_to_virt(info_write.load_addr), data_size); + if (type == LEGACY_LZMA) + ut_asserteq(plain_size, info_read.size); + ut_asserteq_mem(plain, phys_to_virt(info_write.load_addr), plain_size); + if (type == LEGACY_LZMA) + free(plain); free(fs); return 0; } @@ -382,6 +395,8 @@ static int spl_test_blk(struct unit_test_state *uts, const char *test_name, return spl_test_mmc_fs(uts, test_name, type, create_ext2, true); } SPL_IMG_TEST(spl_test_blk, LEGACY, DM_FLAGS); +SPL_IMG_TEST(spl_test_blk, LEGACY_LZMA, DM_FLAGS); +SPL_IMG_TEST(spl_test_blk, IMX8, DM_FLAGS); SPL_IMG_TEST(spl_test_blk, FIT_EXTERNAL, DM_FLAGS); SPL_IMG_TEST(spl_test_blk, FIT_INTERNAL, DM_FLAGS); @@ -409,12 +424,10 @@ static int spl_test_mmc(struct unit_test_state *uts, const char *test_name, spl_mmc_clear_cache(); spl_fat_force_reregister(); - if (type == LEGACY && - spl_test_mmc_fs(uts, test_name, type, create_ext2, false)) + if (spl_test_mmc_fs(uts, test_name, type, create_ext2, false)) return CMD_RET_FAILURE; - if (type != IMX8 && - spl_test_mmc_fs(uts, test_name, type, create_fat, false)) + if (spl_test_mmc_fs(uts, test_name, type, create_fat, false)) return CMD_RET_FAILURE; return do_spl_test_load(uts, test_name, type, @@ -423,6 +436,7 @@ static int spl_test_mmc(struct unit_test_state *uts, const char *test_name, spl_test_mmc_write_image); } SPL_IMG_TEST(spl_test_mmc, LEGACY, DM_FLAGS); +SPL_IMG_TEST(spl_test_mmc, LEGACY_LZMA, DM_FLAGS); SPL_IMG_TEST(spl_test_mmc, IMX8, DM_FLAGS); SPL_IMG_TEST(spl_test_mmc, FIT_EXTERNAL, DM_FLAGS); SPL_IMG_TEST(spl_test_mmc, FIT_INTERNAL, DM_FLAGS); diff --git a/test/image/spl_load_nand.c b/test/image/spl_load_nand.c index 30179de..ec24220 100644 --- a/test/image/spl_load_nand.c +++ b/test/image/spl_load_nand.c @@ -51,4 +51,6 @@ SPL_IMG_TEST(spl_test_nand, LEGACY, DM_FLAGS); SPL_IMG_TEST(spl_test_nand, LEGACY_LZMA, DM_FLAGS); SPL_IMG_TEST(spl_test_nand, IMX8, DM_FLAGS); SPL_IMG_TEST(spl_test_nand, FIT_INTERNAL, DM_FLAGS); +#if !IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) SPL_IMG_TEST(spl_test_nand, FIT_EXTERNAL, DM_FLAGS); +#endif diff --git a/test/image/spl_load_net.c b/test/image/spl_load_net.c index f570cef..9d067a7 100644 --- a/test/image/spl_load_net.c +++ b/test/image/spl_load_net.c @@ -248,5 +248,7 @@ static int spl_test_net(struct unit_test_state *uts, const char *test_name, return ret; } SPL_IMG_TEST(spl_test_net, LEGACY, DM_FLAGS); +SPL_IMG_TEST(spl_test_net, LEGACY_LZMA, DM_FLAGS); +SPL_IMG_TEST(spl_test_net, IMX8, DM_FLAGS); SPL_IMG_TEST(spl_test_net, FIT_INTERNAL, DM_FLAGS); SPL_IMG_TEST(spl_test_net, FIT_EXTERNAL, DM_FLAGS); diff --git a/test/image/spl_load_nor.c b/test/image/spl_load_nor.c index a62bb60..de56863 100644 --- a/test/image/spl_load_nor.c +++ b/test/image/spl_load_nor.c @@ -36,4 +36,6 @@ SPL_IMG_TEST(spl_test_nor, LEGACY, 0); SPL_IMG_TEST(spl_test_nor, LEGACY_LZMA, 0); SPL_IMG_TEST(spl_test_nor, IMX8, 0); SPL_IMG_TEST(spl_test_nor, FIT_INTERNAL, 0); +#if !IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) SPL_IMG_TEST(spl_test_nor, FIT_EXTERNAL, 0); +#endif diff --git a/test/image/spl_load_os.c b/test/image/spl_load_os.c index 49edf15..26228a8 100644 --- a/test/image/spl_load_os.c +++ b/test/image/spl_load_os.c @@ -16,14 +16,13 @@ struct text_ctx { int fd; }; -static ulong read_fit_image(struct spl_load_info *load, ulong sector, - ulong count, void *buf) +static ulong read_fit_image(struct spl_load_info *load, ulong offset, + ulong size, void *buf) { struct text_ctx *text_ctx = load->priv; - off_t offset, ret; + off_t ret; ssize_t res; - offset = sector * load->bl_len; ret = os_lseek(text_ctx->fd, offset, OS_SEEK_SET); if (ret != offset) { printf("Failed to seek to %zx, got %zx (errno=%d)\n", offset, @@ -31,14 +30,14 @@ static ulong read_fit_image(struct spl_load_info *load, ulong sector, return 0; } - res = os_read(text_ctx->fd, buf, count * load->bl_len); + res = os_read(text_ctx->fd, buf, size); if (res == -1) { printf("Failed to read %lx bytes, got %ld (errno=%d)\n", - count * load->bl_len, res, errno); + size, res, errno); return 0; } - return count; + return size; } static int spl_test_load(struct unit_test_state *uts) @@ -52,13 +51,12 @@ static int spl_test_load(struct unit_test_state *uts) int fd; memset(&load, '\0', sizeof(load)); - load.bl_len = 512; + spl_set_bl_len(&load, 512); load.read = read_fit_image; ret = sandbox_find_next_phase(fname, sizeof(fname), true); if (ret) ut_assertf(0, "%s not found, error %d\n", fname, ret); - load.filename = fname; header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); diff --git a/test/image/spl_load_spi.c b/test/image/spl_load_spi.c index 8f9b6e0..54a9546 100644 --- a/test/image/spl_load_spi.c +++ b/test/image/spl_load_spi.c @@ -34,6 +34,7 @@ static int spl_test_spi(struct unit_test_state *uts, const char *test_name, spl_test_spi_write_image); } SPL_IMG_TEST(spl_test_spi, LEGACY, DM_FLAGS); +SPL_IMG_TEST(spl_test_spi, LEGACY_LZMA, DM_FLAGS); SPL_IMG_TEST(spl_test_spi, IMX8, DM_FLAGS); SPL_IMG_TEST(spl_test_spi, FIT_INTERNAL, DM_FLAGS); #if !IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) |