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