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