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