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