xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/fit_misc.c (revision 86b1f5c1b4dc87d1ea4a02a3df6f3a94b97e4e6b)
1aa8e825bSJoseph Chen /*
2aa8e825bSJoseph Chen  * (C) Copyright 2020 Rockchip Electronics Co., Ltd
3aa8e825bSJoseph Chen  *
4aa8e825bSJoseph Chen  * SPDX-License-Identifier:     GPL-2.0+
5aa8e825bSJoseph Chen  */
6aa8e825bSJoseph Chen 
7aa8e825bSJoseph Chen #include <common.h>
8aa8e825bSJoseph Chen #include <boot_rkimg.h>
9aa8e825bSJoseph Chen #include <misc.h>
10aa8e825bSJoseph Chen #ifdef CONFIG_SPL_BUILD
11aa8e825bSJoseph Chen #include <spl.h>
12aa8e825bSJoseph Chen #endif
13ade0ccd7SJoseph Chen #include <lzma/LzmaTools.h>
14aa8e825bSJoseph Chen #include <optee_include/OpteeClientInterface.h>
15aa8e825bSJoseph Chen #include <optee_include/tee_api_defines.h>
16aa8e825bSJoseph Chen 
17aa8e825bSJoseph Chen DECLARE_GLOBAL_DATA_PTR;
18aa8e825bSJoseph Chen 
19aa8e825bSJoseph Chen #if CONFIG_IS_ENABLED(FIT)
20aa8e825bSJoseph Chen 
21aa8e825bSJoseph Chen /*
22aa8e825bSJoseph Chen  * Override __weak board_fit_image_post_process() for SPL & U-Boot proper.
23aa8e825bSJoseph Chen  */
24aa8e825bSJoseph Chen #if CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS)
25aa8e825bSJoseph Chen 
26aa8e825bSJoseph Chen #define FIT_UNCOMP_HASH_NODENAME	"digest"
275beee4e8SYifeng Zhao #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) || CONFIG_IS_ENABLED(GZIP)
28aa8e825bSJoseph Chen static int fit_image_check_uncomp_hash(const void *fit, int parent_noffset,
29aa8e825bSJoseph Chen 				       const void *data, size_t size)
30aa8e825bSJoseph Chen {
31aa8e825bSJoseph Chen 	const char *name;
32aa8e825bSJoseph Chen 	char *err_msgp;
33aa8e825bSJoseph Chen 	int noffset;
34aa8e825bSJoseph Chen 
35aa8e825bSJoseph Chen 	fdt_for_each_subnode(noffset, fit, parent_noffset) {
36aa8e825bSJoseph Chen 		name = fit_get_name(fit, noffset, NULL);
37aa8e825bSJoseph Chen 		if (!strncmp(name, FIT_UNCOMP_HASH_NODENAME,
38aa8e825bSJoseph Chen 			     strlen(FIT_UNCOMP_HASH_NODENAME))) {
39aa8e825bSJoseph Chen 			return fit_image_check_hash(fit, noffset, data,
40aa8e825bSJoseph Chen 						    size, &err_msgp);
41aa8e825bSJoseph Chen 		}
42aa8e825bSJoseph Chen 	}
43aa8e825bSJoseph Chen 
44aa8e825bSJoseph Chen 	return 0;
45aa8e825bSJoseph Chen }
46aa8e825bSJoseph Chen 
47ade0ccd7SJoseph Chen static int fit_decomp_image(void *fit, int node, ulong *load_addr,
489bb8411cSJoseph Chen 			    ulong **src_addr, size_t *src_len, void *spec)
49aa8e825bSJoseph Chen {
50aa8e825bSJoseph Chen 	u64 len = *src_len;
51ade0ccd7SJoseph Chen 	int ret = -ENOSYS;
52aa8e825bSJoseph Chen 	u8 comp;
53*86b1f5c1SJason Zhu #if CONFIG_IS_ENABLED(MISC_DECOMPRESS)
54*86b1f5c1SJason Zhu 	u32 flags = 0;
55*86b1f5c1SJason Zhu #endif
56aa8e825bSJoseph Chen 
57aa8e825bSJoseph Chen 	if (fit_image_get_comp(fit, node, &comp))
58aa8e825bSJoseph Chen 		return 0;
59aa8e825bSJoseph Chen 
60ade0ccd7SJoseph Chen 	if (comp != IH_COMP_GZIP && comp != IH_COMP_LZMA)
61aa8e825bSJoseph Chen 		return 0;
62aa8e825bSJoseph Chen 
63aa8e825bSJoseph Chen #ifndef CONFIG_SPL_BUILD
649bb8411cSJoseph Chen 	/*
659bb8411cSJoseph Chen 	 * U-Boot:
669bb8411cSJoseph Chen 	 *	handled late in bootm_decomp_image()
679bb8411cSJoseph Chen 	 */
68aa8e825bSJoseph Chen 	if (fit_image_check_type(fit, node, IH_TYPE_KERNEL))
69aa8e825bSJoseph Chen 		return 0;
709bb8411cSJoseph Chen #elif defined(CONFIG_SPL_MTD_SUPPORT) && defined(CONFIG_SPL_MISC_DECOMPRESS) && \
719bb8411cSJoseph Chen       defined(CONFIG_SPL_KERNEL_BOOT)
729bb8411cSJoseph Chen 	/*
739bb8411cSJoseph Chen 	 * SPL Thunder-boot policty on spi-nand:
749bb8411cSJoseph Chen 	 *	enable and use interrupt status as a sync signal for
759bb8411cSJoseph Chen 	 *	kernel to poll that whether ramdisk decompress is done.
769bb8411cSJoseph Chen 	 */
779bb8411cSJoseph Chen 	struct spl_load_info *info = spec;
789bb8411cSJoseph Chen 	struct blk_desc *desc;
799bb8411cSJoseph Chen 
809bb8411cSJoseph Chen 	if (info && info->dev) {
819bb8411cSJoseph Chen 		desc = info->dev;
829bb8411cSJoseph Chen 		if ((desc->if_type == IF_TYPE_MTD) &&
839bb8411cSJoseph Chen 		    (desc->devnum == BLK_MTD_SPI_NAND) &&
849bb8411cSJoseph Chen 		    fit_image_check_type(fit, node, IH_TYPE_RAMDISK)) {
859bb8411cSJoseph Chen 			flags |= DCOMP_FLG_IRQ_ONESHOT;
869bb8411cSJoseph Chen 		}
879bb8411cSJoseph Chen 	}
88aa8e825bSJoseph Chen #endif
89ade0ccd7SJoseph Chen 	if (comp == IH_COMP_LZMA) {
90ade0ccd7SJoseph Chen #if CONFIG_IS_ENABLED(LZMA)
91ade0ccd7SJoseph Chen 		SizeT lzma_len = ALIGN(len, FIT_MAX_SPL_IMAGE_SZ);
92ade0ccd7SJoseph Chen 		SizeT src_lenp;
93ade0ccd7SJoseph Chen 		const fdt32_t *val;
94ade0ccd7SJoseph Chen 
95ade0ccd7SJoseph Chen 		val = fdt_getprop(fit, node, "raw-size", NULL);
96ade0ccd7SJoseph Chen 		if (!val)
97ade0ccd7SJoseph Chen 			return -ENOENT;
98ade0ccd7SJoseph Chen 		src_lenp = fdt32_to_cpu(*val);
99ade0ccd7SJoseph Chen 		ret = lzmaBuffToBuffDecompress((uchar *)(*load_addr), &lzma_len,
100ade0ccd7SJoseph Chen 					       (uchar *)(*src_addr), src_lenp);
101ade0ccd7SJoseph Chen 		len = lzma_len;
102ade0ccd7SJoseph Chen #endif
103ade0ccd7SJoseph Chen 	} else if (comp == IH_COMP_GZIP) {
104aa8e825bSJoseph Chen 		/*
105aa8e825bSJoseph Chen 		 * For smaller spl size, we don't use misc_decompress_process()
106aa8e825bSJoseph Chen 		 * inside the gunzip().
107aa8e825bSJoseph Chen 		 */
108aa8e825bSJoseph Chen #if CONFIG_IS_ENABLED(MISC_DECOMPRESS)
109ade0ccd7SJoseph Chen 		const void *prop;
110ade0ccd7SJoseph Chen 
111aa8e825bSJoseph Chen 		ret = misc_decompress_process((ulong)(*load_addr),
112aa8e825bSJoseph Chen 					      (ulong)(*src_addr), (ulong)(*src_len),
113dd5acf09SJason Zhu 					      DECOM_GZIP, true, &len, flags);
114ade0ccd7SJoseph Chen 		/* mark for misc_decompress_cleanup() */
115ade0ccd7SJoseph Chen 		prop = fdt_getprop(fit, node, "decomp-async", NULL);
116ade0ccd7SJoseph Chen 		if (prop)
117ade0ccd7SJoseph Chen 			misc_decompress_async(comp);
118ade0ccd7SJoseph Chen 		else
119ade0ccd7SJoseph Chen 			misc_decompress_sync(comp);
120aa8e825bSJoseph Chen #else
1212708ed29SJoseph Chen 		ret = gunzip((void *)(*load_addr), ALIGN(len, FIT_MAX_SPL_IMAGE_SZ),
122aa8e825bSJoseph Chen 			     (void *)(*src_addr), (void *)(&len));
123aa8e825bSJoseph Chen #endif
124ade0ccd7SJoseph Chen 	}
125ade0ccd7SJoseph Chen 
126aa8e825bSJoseph Chen 	if (ret) {
127aa8e825bSJoseph Chen 		printf("%s: decompress error, ret=%d\n",
128aa8e825bSJoseph Chen 		       fdt_get_name(fit, node, NULL), ret);
129aa8e825bSJoseph Chen 		return ret;
130aa8e825bSJoseph Chen 	}
131aa8e825bSJoseph Chen 
132aa8e825bSJoseph Chen 	/* check uncompressed data hash */
133aa8e825bSJoseph Chen 	ret = fit_image_check_uncomp_hash(fit, node, (void *)(*load_addr), len);
134aa8e825bSJoseph Chen 	if (!ret)
135aa8e825bSJoseph Chen 		puts("+ ");
136aa8e825bSJoseph Chen 	else
137aa8e825bSJoseph Chen 		return ret;
138aa8e825bSJoseph Chen 
139aa8e825bSJoseph Chen 	*src_addr = (ulong *)*load_addr;
140aa8e825bSJoseph Chen 	*src_len = len;
141aa8e825bSJoseph Chen 
142aa8e825bSJoseph Chen 	return 0;
143aa8e825bSJoseph Chen }
144aa8e825bSJoseph Chen #endif
145aa8e825bSJoseph Chen 
146aa8e825bSJoseph Chen void board_fit_image_post_process(void *fit, int node, ulong *load_addr,
1479bb8411cSJoseph Chen 				  ulong **src_addr, size_t *src_len, void *spec)
148aa8e825bSJoseph Chen {
149aa8e825bSJoseph Chen #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) || CONFIG_IS_ENABLED(GZIP)
150ade0ccd7SJoseph Chen 	fit_decomp_image(fit, node, load_addr, src_addr, src_len, spec);
151aa8e825bSJoseph Chen #endif
152aa8e825bSJoseph Chen 
153aa8e825bSJoseph Chen #if CONFIG_IS_ENABLED(USING_KERNEL_DTB)
154aa8e825bSJoseph Chen 	/* Avoid overriding processed(overlay, hw-dtb, ...) kernel dtb */
155d94316bfSJoseph Chen 	if (fit_image_check_type(fit, node, IH_TYPE_FLATDT)) {
156d94316bfSJoseph Chen 		if ((gd->flags & GD_FLG_KDTB_READY) && !gd->fdt_blob_kern) {
157aa8e825bSJoseph Chen 			*src_addr = (void *)gd->fdt_blob;
158aa8e825bSJoseph Chen 			*src_len = (size_t)fdt_totalsize(gd->fdt_blob);
159d94316bfSJoseph Chen 		} else {
160d94316bfSJoseph Chen 			printf("   Using fdt from load-in fdt\n");
161d94316bfSJoseph Chen 		}
162aa8e825bSJoseph Chen 	}
163aa8e825bSJoseph Chen #endif
164aa8e825bSJoseph Chen }
165aa8e825bSJoseph Chen #endif /* FIT_IMAGE_POST_PROCESS */
166aa8e825bSJoseph Chen /*
167aa8e825bSJoseph Chen  * Override __weak fit_rollback_index_verify() for SPL & U-Boot proper.
168aa8e825bSJoseph Chen  */
169aa8e825bSJoseph Chen #if CONFIG_IS_ENABLED(FIT_ROLLBACK_PROTECT)
170aa8e825bSJoseph Chen int fit_rollback_index_verify(const void *fit, uint32_t rollback_fd,
171aa8e825bSJoseph Chen 			      uint32_t *fit_index, uint32_t *otp_index)
172aa8e825bSJoseph Chen {
173aa8e825bSJoseph Chen 	int conf_noffset, ret;
174aa8e825bSJoseph Chen 
175aa8e825bSJoseph Chen 	conf_noffset = fit_conf_get_node(fit, NULL); /* NULL for default conf */
176aa8e825bSJoseph Chen 	if (conf_noffset < 0)
177aa8e825bSJoseph Chen 		return conf_noffset;
178aa8e825bSJoseph Chen 
179aa8e825bSJoseph Chen 	ret = fit_image_get_rollback_index(fit, conf_noffset, fit_index);
180aa8e825bSJoseph Chen 	if (ret) {
181aa8e825bSJoseph Chen 		printf("Failed to get rollback-index from FIT, ret=%d\n", ret);
182aa8e825bSJoseph Chen 		return ret;
183aa8e825bSJoseph Chen 	}
184aa8e825bSJoseph Chen 
185aa8e825bSJoseph Chen 	ret = fit_read_otp_rollback_index(*fit_index, otp_index);
186aa8e825bSJoseph Chen 	if (ret) {
187aa8e825bSJoseph Chen 		printf("Failed to get rollback-index from otp, ret=%d\n", ret);
188aa8e825bSJoseph Chen 		return ret;
189aa8e825bSJoseph Chen 	}
190aa8e825bSJoseph Chen 
191aa8e825bSJoseph Chen 	/* Should update rollback index to otp ! */
192aa8e825bSJoseph Chen 	if (*otp_index < *fit_index)
193aa8e825bSJoseph Chen 		gd->rollback_index = *fit_index;
194aa8e825bSJoseph Chen 
195aa8e825bSJoseph Chen 	return 0;
196aa8e825bSJoseph Chen }
197aa8e825bSJoseph Chen #endif
198aa8e825bSJoseph Chen 
199aa8e825bSJoseph Chen /*
200aa8e825bSJoseph Chen  * Override __weak fit_board_verify_required_sigs() for SPL & U-Boot proper.
201aa8e825bSJoseph Chen  */
202aa8e825bSJoseph Chen int fit_board_verify_required_sigs(void)
203aa8e825bSJoseph Chen {
204aa8e825bSJoseph Chen 	uint8_t vboot = 0;
205aa8e825bSJoseph Chen 
206aa8e825bSJoseph Chen #ifdef CONFIG_SPL_BUILD
207299f09a0SJason Zhu #if defined(CONFIG_SPL_ROCKCHIP_SECURE_OTP)
208aa8e825bSJoseph Chen 	struct udevice *dev;
209aa8e825bSJoseph Chen 
210aa8e825bSJoseph Chen 	dev = misc_otp_get_device(OTP_S);
211aa8e825bSJoseph Chen 	if (!dev)
212aa8e825bSJoseph Chen 		return 1;
213aa8e825bSJoseph Chen 
214a31e24f3SJason Zhu 	if (misc_otp_read(dev, OTP_SECURE_BOOT_ENABLE_ADDR, &vboot, 1)) {
215aa8e825bSJoseph Chen 		printf("Can't read verified-boot flag\n");
216aa8e825bSJoseph Chen 		return 1;
217aa8e825bSJoseph Chen 	}
218aa8e825bSJoseph Chen 
219aa8e825bSJoseph Chen 	vboot = (vboot == 0xff);
220aa8e825bSJoseph Chen #endif
221aa8e825bSJoseph Chen #else /* !CONFIG_SPL_BUILD */
222aa8e825bSJoseph Chen #ifdef CONFIG_OPTEE_CLIENT
223aa8e825bSJoseph Chen 	int ret;
224aa8e825bSJoseph Chen 
225aa8e825bSJoseph Chen 	ret = trusty_read_vbootkey_enable_flag(&vboot);
226aa8e825bSJoseph Chen 	if (ret) {
227aa8e825bSJoseph Chen 		printf("Can't read verified-boot flag, ret=%d\n", ret);
228aa8e825bSJoseph Chen 		return 1;
229aa8e825bSJoseph Chen 	}
230aa8e825bSJoseph Chen #endif
231aa8e825bSJoseph Chen #endif /* CONFIG_SPL_BUILD*/
232aa8e825bSJoseph Chen 
233aa8e825bSJoseph Chen 	printf("## Verified-boot: %d\n", vboot);
234aa8e825bSJoseph Chen 
235aa8e825bSJoseph Chen 	return vboot;
236aa8e825bSJoseph Chen }
237aa8e825bSJoseph Chen 
238aa8e825bSJoseph Chen #endif /* CONFIG_IS_ENABLED(FIT) */
239