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