mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-10-31 03:58:17 +00:00 
			
		
		
		
	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 <seanga2@gmail.com> Reviewed-by: Simon Glass <sjg@chromium.org>
		
			
				
	
	
		
			145 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* 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_ */
 |