xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/fit_misc.c (revision 8ec1924f7c3bb759088f648fd366f086e8d1f802)
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)
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 
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 
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 		ret = gunzip((void *)(*load_addr), ALIGN(len, FIT_MAX_SPL_IMAGE_SZ),
131 			     (void *)(*src_addr), (void *)(&len));
132 #endif
133 	}
134 
135 	if (ret) {
136 		printf("%s: decompress error, ret=%d\n",
137 		       fdt_get_name(fit, node, NULL), ret);
138 		return ret;
139 	}
140 
141 	/* check uncompressed data hash */
142 	ret = fit_image_check_uncomp_hash(fit, node, (void *)(*load_addr), len);
143 	if (!ret)
144 		puts("+ ");
145 	else
146 		return ret;
147 
148 	*src_addr = (ulong *)*load_addr;
149 	*src_len = len;
150 
151 	return 0;
152 }
153 #endif
154 
155 void board_fit_image_post_process(void *fit, int node, ulong *load_addr,
156 				  ulong **src_addr, size_t *src_len, void *spec)
157 {
158 #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) || CONFIG_IS_ENABLED(GZIP)
159 	fit_decomp_image(fit, node, load_addr, src_addr, src_len, spec);
160 #endif
161 
162 #if CONFIG_IS_ENABLED(USING_KERNEL_DTB)
163 	/* Avoid overriding processed(overlay, hw-dtb, ...) kernel dtb */
164 	if (fit_image_check_type(fit, node, IH_TYPE_FLATDT)) {
165 		if ((gd->flags & GD_FLG_KDTB_READY) && !gd->fdt_blob_kern) {
166 			*src_addr = (void *)gd->fdt_blob;
167 			*src_len = (size_t)fdt_totalsize(gd->fdt_blob);
168 		} else {
169 			printf("   Using fdt from load-in fdt\n");
170 		}
171 	}
172 #endif
173 
174 #ifndef CONFIG_SPL_BUILD
175 	if (fit_image_check_type(fit, node, IH_TYPE_FIRMWARE)) {
176 		const char *uname;
177 		char *old, *new;
178 		size_t len;
179 
180 		uname = fdt_get_name(fit, node, NULL);
181 		if (strcmp("bootargs", uname))
182 			return;
183 
184 		old = env_get("bootargs");
185 		if (!old)
186 			return;
187 
188 		len = strlen(old) + (*src_len) + 2;
189 		new = calloc(1, len);
190 		if (new) {
191 			strcpy(new, old);
192 			strcat(new, " ");
193 			strcat(new, (char *)(*src_addr));
194 			env_set("bootargs", new);
195 			free(new);
196 		}
197 
198 	}
199 #endif
200 }
201 #endif /* FIT_IMAGE_POST_PROCESS */
202 /*
203  * Override __weak fit_rollback_index_verify() for SPL & U-Boot proper.
204  */
205 #if CONFIG_IS_ENABLED(FIT_ROLLBACK_PROTECT)
206 int fit_rollback_index_verify(const void *fit, uint32_t rollback_fd,
207 			      uint32_t *fit_index, uint32_t *otp_index)
208 {
209 	int conf_noffset, ret;
210 
211 	conf_noffset = fit_conf_get_node(fit, NULL); /* NULL for default conf */
212 	if (conf_noffset < 0)
213 		return conf_noffset;
214 
215 	ret = fit_image_get_rollback_index(fit, conf_noffset, fit_index);
216 	if (ret) {
217 		printf("Failed to get rollback-index from FIT, ret=%d\n", ret);
218 		return ret;
219 	}
220 
221 	ret = fit_read_otp_rollback_index(*fit_index, otp_index);
222 	if (ret) {
223 		printf("Failed to get rollback-index from otp, ret=%d\n", ret);
224 		return ret;
225 	}
226 
227 	/* Should update rollback index to otp ! */
228 	if (*otp_index < *fit_index)
229 		gd->rollback_index = *fit_index;
230 
231 	return 0;
232 }
233 #endif
234 
235 /*
236  * Override __weak fit_board_verify_required_sigs() for SPL & U-Boot proper.
237  */
238 int fit_board_verify_required_sigs(void)
239 {
240 	uint8_t vboot = 0;
241 
242 #ifdef CONFIG_SPL_BUILD
243 #if defined(CONFIG_SPL_ROCKCHIP_SECURE_OTP)
244 	struct udevice *dev;
245 
246 	dev = misc_otp_get_device(OTP_S);
247 	if (!dev)
248 		return 1;
249 
250 	if (misc_otp_read(dev, OTP_SECURE_BOOT_ENABLE_ADDR, &vboot, 1)) {
251 		printf("Can't read verified-boot flag\n");
252 		return 1;
253 	}
254 
255 	vboot = (vboot == 0xff);
256 #endif
257 #else /* !CONFIG_SPL_BUILD */
258 #if defined(CONFIG_OPTEE_CLIENT)
259 	int ret;
260 
261 	ret = trusty_read_vbootkey_enable_flag(&vboot);
262 	if (ret) {
263 		printf("Can't read verified-boot flag, ret=%d\n", ret);
264 		return 1;
265 	}
266 #elif defined(CONFIG_ROCKCHIP_PRELOADER_ATAGS)
267 	struct tag *t;
268 
269 	t = atags_get_tag(ATAG_PUB_KEY);
270 	if (t && t->u.pub_key.flag == PUBKEY_FUSE_PROGRAMMED)
271 		vboot = 1;
272 #endif
273 #endif /* CONFIG_SPL_BUILD*/
274 
275 	printf("## Verified-boot: %d\n", vboot);
276 
277 	return vboot;
278 }
279 
280 #endif /* CONFIG_IS_ENABLED(FIT) */
281