"Das U-Boot" Source Tree
at master 153 lines 5.2 kB view raw
1/* SPDX-License-Identifier: GPL-2.0+ */ 2/* 3 * Copyright (C) Sean Anderson <seanga2@gmail.com> 4 */ 5#ifndef _SPL_LOAD_H_ 6#define _SPL_LOAD_H_ 7 8#include <image.h> 9#include <imx_container.h> 10#include <mapmem.h> 11#include <spl.h> 12 13static inline int _spl_load(struct spl_image_info *spl_image, 14 const struct spl_boot_device *bootdev, 15 struct spl_load_info *info, size_t size, 16 size_t offset) 17{ 18 struct legacy_img_hdr *header = 19 spl_get_load_buffer(-sizeof(*header), sizeof(*header)); 20 ulong base_offset, image_offset, overhead; 21 int read, ret; 22 23 log_debug("\nloading hdr from %lx to %p\n", (ulong)offset, header); 24 read = info->read(info, offset, ALIGN(sizeof(*header), 25 spl_get_bl_len(info)), header); 26 if (read < (int)sizeof(*header)) 27 return -EIO; 28 29 if (image_get_magic(header) == FDT_MAGIC) { 30 log_debug("Found FIT\n"); 31 if (CONFIG_IS_ENABLED(LOAD_FIT_FULL)) { 32 void *buf; 33 34 /* 35 * In order to support verifying images in the FIT, we 36 * need to load the whole FIT into memory. Try and 37 * guess how much we need to load by using the total 38 * size. This will fail for FITs with external data, 39 * but there's not much we can do about that. 40 */ 41 if (!size) 42 size = round_up(fdt_totalsize(header), 4); 43 buf = map_sysmem(CONFIG_SYS_LOAD_ADDR, size); 44 read = info->read(info, offset, 45 ALIGN(size, spl_get_bl_len(info)), 46 buf); 47 if (read < size) 48 return -EIO; 49 50 return spl_parse_image_header(spl_image, bootdev, buf); 51 } 52 53 if (CONFIG_IS_ENABLED(LOAD_FIT)) { 54 log_debug("Simple loading\n"); 55 return spl_load_simple_fit(spl_image, info, offset, 56 header); 57 } 58 log_debug("No FIT support\n"); 59 } 60 61 if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && 62 valid_container_hdr((void *)header)) 63 return spl_load_imx_container(spl_image, info, offset); 64 65 if (IS_ENABLED(CONFIG_SPL_LZMA) && 66 image_get_magic(header) == IH_MAGIC && 67 image_get_comp(header) == IH_COMP_LZMA) { 68 spl_image->flags |= SPL_COPY_PAYLOAD_ONLY; 69 ret = spl_parse_image_header(spl_image, bootdev, header); 70 if (ret) 71 return ret; 72 73 return spl_load_legacy_lzma(spl_image, info, offset); 74 } 75 76 ret = spl_parse_image_header(spl_image, bootdev, header); 77 if (ret) 78 return ret; 79 80 base_offset = spl_image->offset; 81 /* Only NOR sets this flag. */ 82 if (IS_ENABLED(CONFIG_SPL_NOR_SUPPORT) && 83 spl_image->flags & SPL_COPY_PAYLOAD_ONLY) 84 base_offset += sizeof(*header); 85 image_offset = ALIGN_DOWN(base_offset, spl_get_bl_len(info)); 86 overhead = base_offset - image_offset; 87 size = ALIGN(spl_image->size + overhead, spl_get_bl_len(info)); 88 89 read = info->read(info, offset + image_offset, size, 90 map_sysmem(spl_image->load_addr - overhead, size)); 91 92 if (read < 0) 93 return read; 94 95 return read < spl_image->size ? -EIO : 0; 96} 97 98/* 99 * Although spl_load results in size reduction for callers, this is generally 100 * not enough to counteract the bloat if there is only one caller. The core 101 * problem is that the compiler can't optimize across translation units. The 102 * general solution to this is CONFIG_LTO, but that is not available on all 103 * architectures. Perform a pseudo-LTO just for this function by declaring it 104 * inline if there is one caller, and extern otherwise. 105 */ 106#define SPL_LOAD_USERS \ 107 IS_ENABLED(CONFIG_SPL_BLK_FS) + \ 108 IS_ENABLED(CONFIG_SPL_FS_EXT4) + \ 109 IS_ENABLED(CONFIG_SPL_FS_FAT) + \ 110 IS_ENABLED(CONFIG_SPL_SYS_MMCSD_RAW_MODE) + \ 111 (IS_ENABLED(CONFIG_SPL_NAND_SUPPORT) && !IS_ENABLED(CONFIG_SPL_UBI)) + \ 112 IS_ENABLED(CONFIG_SPL_NET) + \ 113 IS_ENABLED(CONFIG_SPL_NOR_SUPPORT) + \ 114 IS_ENABLED(CONFIG_SPL_SEMIHOSTING) + \ 115 IS_ENABLED(CONFIG_SPL_SPI_LOAD) + \ 116 0 117 118#if SPL_LOAD_USERS > 1 119/** 120 * spl_load() - Parse a header and load the image 121 * @spl_image: Image data which will be filled in by this function 122 * @bootdev: The device to load from 123 * @info: Describes how to load additional information from @bootdev. At the 124 * minimum, read() and bl_len must be populated. 125 * @size: The size of the image, in bytes, if it is known in advance. Some boot 126 * devices (such as filesystems) know how big an image is before parsing 127 * the header. If 0, then the size will be determined from the header. 128 * @offset: The offset from the start of @bootdev, in bytes. This should have 129 * the offset @header was loaded from. It will be added to any offsets 130 * passed to @info->read(). 131 * 132 * This function determines the image type (FIT, legacy, i.MX, raw, etc), calls 133 * the appropriate parsing function, determines the load address, and the loads 134 * the image from storage. It is designed to replace ad-hoc image loading which 135 * may not support all image types (especially when config options are 136 * involved). 137 * 138 * Return: 0 on success, or a negative error on failure 139 */ 140int spl_load(struct spl_image_info *spl_image, 141 const struct spl_boot_device *bootdev, struct spl_load_info *info, 142 size_t size, size_t offset); 143#else 144static inline int spl_load(struct spl_image_info *spl_image, 145 const struct spl_boot_device *bootdev, 146 struct spl_load_info *info, size_t size, 147 size_t offset) 148{ 149 return _spl_load(spl_image, bootdev, info, size, offset); 150} 151#endif 152 153#endif /* _SPL_LOAD_H_ */