1 /*
2 * (C) Copyright 2020 Rockchip Electronics Co., Ltd
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include <common.h>
8 #include <boot_rkimg.h>
9 #include <malloc.h>
10 #include <misc.h>
11 #ifdef CONFIG_SPL_BUILD
12 #include <spl.h>
13 #endif
14 #include <lzma/LzmaTools.h>
15 #include <optee_include/OpteeClientInterface.h>
16 #include <optee_include/tee_api_defines.h>
17 #include <asm/arch/rk_atags.h>
18
19 DECLARE_GLOBAL_DATA_PTR;
20
21 #if CONFIG_IS_ENABLED(FIT)
22
23 /*
24 * Override __weak board_fit_image_post_process() for SPL & U-Boot proper.
25 */
26 #if CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS)
27
rk_board_fit_image_post_process(void * fit,int node,ulong * load_addr,ulong ** src_addr,size_t * src_len)28 __weak int rk_board_fit_image_post_process(void *fit, int node, ulong *load_addr,
29 ulong **src_addr, size_t *src_len)
30 {
31 return 0;
32 }
33
34 #define FIT_UNCOMP_HASH_NODENAME "digest"
35 #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) || CONFIG_IS_ENABLED(GZIP) || CONFIG_IS_ENABLED(LZMA)
fit_image_get_uncomp_digest(const void * fit,int parent_noffset)36 static int fit_image_get_uncomp_digest(const void *fit, int parent_noffset)
37 {
38 const char *name;
39 int noffset;
40
41 fdt_for_each_subnode(noffset, fit, parent_noffset) {
42 name = fit_get_name(fit, noffset, NULL);
43 if (!strncmp(name, FIT_UNCOMP_HASH_NODENAME,
44 strlen(FIT_UNCOMP_HASH_NODENAME))) {
45 return noffset;
46 }
47 }
48
49 return -EINVAL;
50 }
51
fit_image_check_uncomp_hash(const void * fit,int parent_noffset,const void * data,size_t size)52 static int fit_image_check_uncomp_hash(const void *fit, int parent_noffset,
53 const void *data, size_t size)
54 {
55 char *err_msgp;
56 int noffset;
57
58 noffset = fit_image_get_uncomp_digest(fit, parent_noffset);
59 if (noffset > 0)
60 return fit_image_check_hash(fit, noffset, data, size, &err_msgp);
61
62 return 0;
63 }
64
fit_decomp_image(void * fit,int node,ulong * load_addr,ulong ** src_addr,size_t * src_len,void * spec)65 static int fit_decomp_image(void *fit, int node, ulong *load_addr,
66 ulong **src_addr, size_t *src_len, void *spec)
67 {
68 u64 len = *src_len;
69 int ret = -ENOSYS;
70 u8 comp;
71 #if CONFIG_IS_ENABLED(MISC_DECOMPRESS)
72 u32 flags = 0;
73 #endif
74
75 if (fit_image_get_comp(fit, node, &comp))
76 return 0;
77
78 if (comp != IH_COMP_GZIP && comp != IH_COMP_LZMA)
79 return 0;
80
81 #ifndef CONFIG_SPL_BUILD
82 /*
83 * U-Boot:
84 * handled late in bootm_decomp_image()
85 */
86 if (fit_image_check_type(fit, node, IH_TYPE_KERNEL))
87 return 0;
88 #elif defined(CONFIG_SPL_MTD_SUPPORT) && defined(CONFIG_SPL_MISC_DECOMPRESS) && \
89 defined(CONFIG_SPL_KERNEL_BOOT)
90 /*
91 * SPL Thunder-boot policty on spi-nand:
92 * enable and use interrupt status as a sync signal for
93 * kernel to poll that whether ramdisk decompress is done.
94 */
95 struct spl_load_info *info = spec;
96 struct blk_desc *desc;
97
98 if (info && info->dev) {
99 desc = info->dev;
100 if ((desc->if_type == IF_TYPE_MTD) &&
101 (desc->devnum == BLK_MTD_SPI_NAND) &&
102 fit_image_check_type(fit, node, IH_TYPE_RAMDISK)) {
103 flags |= DCOMP_FLG_IRQ_ONESHOT;
104 }
105 }
106 #endif
107 if (comp == IH_COMP_LZMA) {
108 #if CONFIG_IS_ENABLED(LZMA)
109 SizeT lzma_len = ALIGN(len, FIT_MAX_SPL_IMAGE_SZ);
110 ret = lzmaBuffToBuffDecompress((uchar *)(*load_addr), &lzma_len,
111 (uchar *)(*src_addr), *src_len);
112 len = lzma_len;
113 #endif
114 } else if (comp == IH_COMP_GZIP) {
115 /*
116 * For smaller spl size, we don't use misc_decompress_process()
117 * inside the gunzip().
118 */
119 #if CONFIG_IS_ENABLED(MISC_DECOMPRESS)
120 const void *prop;
121 bool sync = true;
122
123 if (fit_image_get_uncomp_digest(fit, node) < 0)
124 sync = false;
125
126 ret = misc_decompress_process((ulong)(*load_addr),
127 (ulong)(*src_addr), (ulong)(*src_len),
128 DECOM_GZIP, sync, &len, flags);
129 /* mark for misc_decompress_cleanup() */
130 prop = fdt_getprop(fit, node, "decomp-async", NULL);
131 if (prop)
132 misc_decompress_async(comp);
133 else
134 misc_decompress_sync(comp);
135 #else
136 #if CONFIG_IS_ENABLED(GZIP)
137 ret = gunzip((void *)(*load_addr), ALIGN(len, FIT_MAX_SPL_IMAGE_SZ),
138 (void *)(*src_addr), (void *)(&len));
139 #endif
140 #endif
141 }
142
143 if (ret) {
144 printf("%s: decompress error, ret=%d\n",
145 fdt_get_name(fit, node, NULL), ret);
146 return ret;
147 }
148
149 /* check uncompressed data hash */
150 ret = fit_image_check_uncomp_hash(fit, node, (void *)(*load_addr), len);
151 if (!ret)
152 puts("+ ");
153 else
154 return ret;
155
156 *src_addr = (ulong *)*load_addr;
157 *src_len = len;
158
159 return 0;
160 }
161 #endif
162
board_fit_image_post_process(void * fit,int node,ulong * load_addr,ulong ** src_addr,size_t * src_len,void * spec)163 int board_fit_image_post_process(void *fit, int node, ulong *load_addr,
164 ulong **src_addr, size_t *src_len, void *spec)
165 {
166 #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) || CONFIG_IS_ENABLED(GZIP) || CONFIG_IS_ENABLED(LZMA)
167 int ret = 0;
168
169 ret = fit_decomp_image(fit, node, load_addr, src_addr, src_len, spec);
170 if (ret)
171 return ret;
172 #endif
173
174 #if CONFIG_IS_ENABLED(USING_KERNEL_DTB)
175 /* Avoid overriding processed(overlay, hw-dtb, ...) kernel dtb */
176 if (fit_image_check_type(fit, node, IH_TYPE_FLATDT)) {
177 if ((gd->flags & GD_FLG_KDTB_READY) && !gd->fdt_blob_kern) {
178 *src_addr = (void *)gd->fdt_blob;
179 *src_len = (size_t)fdt_totalsize(gd->fdt_blob);
180 } else {
181 printf(" Using fdt from load-in fdt\n");
182 }
183 }
184 #endif
185
186 #ifndef CONFIG_SPL_BUILD
187 if (fit_image_check_type(fit, node, IH_TYPE_FIRMWARE)) {
188 const char *uname;
189 char *old, *new;
190 size_t len;
191
192 uname = fdt_get_name(fit, node, NULL);
193 if (strcmp("bootargs", uname))
194 return 0;
195
196 old = env_get("bootargs");
197 if (!old)
198 return -EIO;
199
200 len = strlen(old) + (*src_len) + 2;
201 new = calloc(1, len);
202 if (new) {
203 strcpy(new, old);
204 strcat(new, " ");
205 strcat(new, (char *)(*src_addr));
206 env_set("bootargs", new);
207 free(new);
208 }
209
210 }
211 #endif
212
213 return rk_board_fit_image_post_process(fit, node, load_addr, src_addr, src_len);
214 }
215 #endif /* FIT_IMAGE_POST_PROCESS */
216 /*
217 * Override __weak fit_rollback_index_verify() for SPL & U-Boot proper.
218 */
219 #if CONFIG_IS_ENABLED(FIT_ROLLBACK_PROTECT)
fit_rollback_index_verify(const void * fit,uint32_t rollback_fd,uint32_t * fit_index,uint32_t * otp_index)220 int fit_rollback_index_verify(const void *fit, uint32_t rollback_fd,
221 uint32_t *fit_index, uint32_t *otp_index)
222 {
223 int conf_noffset, ret;
224
225 conf_noffset = fit_conf_get_node(fit, NULL); /* NULL for default conf */
226 if (conf_noffset < 0)
227 return conf_noffset;
228
229 ret = fit_image_get_rollback_index(fit, conf_noffset, fit_index);
230 if (ret) {
231 printf("Failed to get rollback-index from FIT, ret=%d\n", ret);
232 return ret;
233 }
234
235 ret = fit_read_otp_rollback_index(*fit_index, otp_index);
236 if (ret) {
237 printf("Failed to get rollback-index from otp, ret=%d\n", ret);
238 return ret;
239 }
240
241 /* Should update rollback index to otp ! */
242 if (*otp_index < *fit_index)
243 gd->rollback_index = *fit_index;
244
245 return 0;
246 }
247 #endif
248
249 /*
250 * Override __weak fit_board_verify_required_sigs() for SPL & U-Boot proper.
251 */
fit_board_verify_required_sigs(void)252 int fit_board_verify_required_sigs(void)
253 {
254 uint8_t vboot = 0;
255
256 #ifdef CONFIG_SPL_BUILD
257 #if defined(CONFIG_SPL_ROCKCHIP_SECURE_OTP)
258 struct udevice *dev;
259
260 dev = misc_otp_get_device(OTP_S);
261 if (!dev)
262 return 1;
263
264 if (misc_otp_read(dev, OTP_SECURE_BOOT_ENABLE_ADDR, &vboot, 1)) {
265 printf("Can't read verified-boot flag\n");
266 return 1;
267 }
268
269 vboot = (vboot == 0xff);
270 #endif
271 #else /* !CONFIG_SPL_BUILD */
272 #if defined(CONFIG_OPTEE_CLIENT)
273 int ret;
274
275 ret = trusty_read_vbootkey_enable_flag(&vboot);
276 if (ret) {
277 printf("Can't read verified-boot flag, ret=%d\n", ret);
278 return 1;
279 }
280 #elif defined(CONFIG_ROCKCHIP_PRELOADER_ATAGS)
281 struct tag *t;
282
283 t = atags_get_tag(ATAG_PUB_KEY);
284 if (t && t->u.pub_key.flag == PUBKEY_FUSE_PROGRAMMED)
285 vboot = 1;
286 #endif
287 #endif /* CONFIG_SPL_BUILD*/
288
289 printf("## Verified-boot: %d\n", vboot);
290
291 return vboot;
292 }
293
294 #endif /* CONFIG_IS_ENABLED(FIT) */
295