xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/fit_misc.c (revision e55dfbd47140353ad2ac122e706d44b699c8162a)
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 		SizeT src_lenp;
93 		const fdt32_t *val;
94 
95 		val = fdt_getprop(fit, node, "raw-size", NULL);
96 		if (!val)
97 			return -ENOENT;
98 		src_lenp = fdt32_to_cpu(*val);
99 		ret = lzmaBuffToBuffDecompress((uchar *)(*load_addr), &lzma_len,
100 					       (uchar *)(*src_addr), src_lenp);
101 		len = lzma_len;
102 #endif
103 	} else if (comp == IH_COMP_GZIP) {
104 		/*
105 		 * For smaller spl size, we don't use misc_decompress_process()
106 		 * inside the gunzip().
107 		 */
108 #if CONFIG_IS_ENABLED(MISC_DECOMPRESS)
109 		const void *prop;
110 
111 		ret = misc_decompress_process((ulong)(*load_addr),
112 					      (ulong)(*src_addr), (ulong)(*src_len),
113 					      DECOM_GZIP, true, &len, flags);
114 		/* mark for misc_decompress_cleanup() */
115 		prop = fdt_getprop(fit, node, "decomp-async", NULL);
116 		if (prop)
117 			misc_decompress_async(comp);
118 		else
119 			misc_decompress_sync(comp);
120 #else
121 		ret = gunzip((void *)(*load_addr), ALIGN(len, FIT_MAX_SPL_IMAGE_SZ),
122 			     (void *)(*src_addr), (void *)(&len));
123 #endif
124 	}
125 
126 	if (ret) {
127 		printf("%s: decompress error, ret=%d\n",
128 		       fdt_get_name(fit, node, NULL), ret);
129 		return ret;
130 	}
131 
132 	/* check uncompressed data hash */
133 	ret = fit_image_check_uncomp_hash(fit, node, (void *)(*load_addr), len);
134 	if (!ret)
135 		puts("+ ");
136 	else
137 		return ret;
138 
139 	*src_addr = (ulong *)*load_addr;
140 	*src_len = len;
141 
142 	return 0;
143 }
144 #endif
145 
146 void board_fit_image_post_process(void *fit, int node, ulong *load_addr,
147 				  ulong **src_addr, size_t *src_len, void *spec)
148 {
149 #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) || CONFIG_IS_ENABLED(GZIP)
150 	fit_decomp_image(fit, node, load_addr, src_addr, src_len, spec);
151 #endif
152 
153 #if CONFIG_IS_ENABLED(USING_KERNEL_DTB)
154 	/* Avoid overriding processed(overlay, hw-dtb, ...) kernel dtb */
155 	if (fit_image_check_type(fit, node, IH_TYPE_FLATDT)) {
156 		if ((gd->flags & GD_FLG_KDTB_READY) && !gd->fdt_blob_kern) {
157 			*src_addr = (void *)gd->fdt_blob;
158 			*src_len = (size_t)fdt_totalsize(gd->fdt_blob);
159 		} else {
160 			printf("   Using fdt from load-in fdt\n");
161 		}
162 	}
163 #endif
164 }
165 #endif /* FIT_IMAGE_POST_PROCESS */
166 /*
167  * Override __weak fit_rollback_index_verify() for SPL & U-Boot proper.
168  */
169 #if CONFIG_IS_ENABLED(FIT_ROLLBACK_PROTECT)
170 int fit_rollback_index_verify(const void *fit, uint32_t rollback_fd,
171 			      uint32_t *fit_index, uint32_t *otp_index)
172 {
173 	int conf_noffset, ret;
174 
175 	conf_noffset = fit_conf_get_node(fit, NULL); /* NULL for default conf */
176 	if (conf_noffset < 0)
177 		return conf_noffset;
178 
179 	ret = fit_image_get_rollback_index(fit, conf_noffset, fit_index);
180 	if (ret) {
181 		printf("Failed to get rollback-index from FIT, ret=%d\n", ret);
182 		return ret;
183 	}
184 
185 	ret = fit_read_otp_rollback_index(*fit_index, otp_index);
186 	if (ret) {
187 		printf("Failed to get rollback-index from otp, ret=%d\n", ret);
188 		return ret;
189 	}
190 
191 	/* Should update rollback index to otp ! */
192 	if (*otp_index < *fit_index)
193 		gd->rollback_index = *fit_index;
194 
195 	return 0;
196 }
197 #endif
198 
199 /*
200  * Override __weak fit_board_verify_required_sigs() for SPL & U-Boot proper.
201  */
202 int fit_board_verify_required_sigs(void)
203 {
204 	uint8_t vboot = 0;
205 
206 #ifdef CONFIG_SPL_BUILD
207 #if defined(CONFIG_SPL_ROCKCHIP_SECURE_OTP)
208 	struct udevice *dev;
209 
210 	dev = misc_otp_get_device(OTP_S);
211 	if (!dev)
212 		return 1;
213 
214 	if (misc_otp_read(dev, OTP_SECURE_BOOT_ENABLE_ADDR, &vboot, 1)) {
215 		printf("Can't read verified-boot flag\n");
216 		return 1;
217 	}
218 
219 	vboot = (vboot == 0xff);
220 #endif
221 #else /* !CONFIG_SPL_BUILD */
222 #ifdef CONFIG_OPTEE_CLIENT
223 	int ret;
224 
225 	ret = trusty_read_vbootkey_enable_flag(&vboot);
226 	if (ret) {
227 		printf("Can't read verified-boot flag, ret=%d\n", ret);
228 		return 1;
229 	}
230 #endif
231 #endif /* CONFIG_SPL_BUILD*/
232 
233 	printf("## Verified-boot: %d\n", vboot);
234 
235 	return vboot;
236 }
237 
238 #endif /* CONFIG_IS_ENABLED(FIT) */
239