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