xref: /OK3568_Linux_fs/u-boot/common/spl/spl_rkfw.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <common.h>
7*4882a593Smuzhiyun #include <android_image.h>
8*4882a593Smuzhiyun #include <errno.h>
9*4882a593Smuzhiyun #include <malloc.h>
10*4882a593Smuzhiyun #include <misc.h>
11*4882a593Smuzhiyun #include <spl.h>
12*4882a593Smuzhiyun #include <spl_rkfw.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <asm/arch/spl_resource_img.h>
15*4882a593Smuzhiyun #include <boot_rkimg.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #ifdef CONFIG_SPL_ATF
18*4882a593Smuzhiyun static const __aligned(16) struct s_fip_name_id fip_name_id[] = {
19*4882a593Smuzhiyun 	{ BL30_IMAGE_NAME, UUID_SCP_FIRMWARE_BL30 },		/* optional */
20*4882a593Smuzhiyun 	{ BL31_IMAGE_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31 },	/* mandatory */
21*4882a593Smuzhiyun 	{ BL32_IMAGE_NAME, UUID_SECURE_PAYLOAD_BL32 },		/* optional */
22*4882a593Smuzhiyun };
23*4882a593Smuzhiyun 
file2comp_id(const char * file_name,u32 * comp_id)24*4882a593Smuzhiyun static int file2comp_id(const char *file_name, u32 *comp_id)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun 	int i;
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(fip_name_id); i++) {
29*4882a593Smuzhiyun 		if (!strcmp(file_name, fip_name_id[i].name)) {
30*4882a593Smuzhiyun 			*comp_id = fip_name_id[i].id;
31*4882a593Smuzhiyun 			return 0;
32*4882a593Smuzhiyun 		}
33*4882a593Smuzhiyun 	}
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 	return -ENOENT;
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun 
open_image(const char * image_name,tboot_entry * entry,struct tag_tboot_header_2k * hdr)38*4882a593Smuzhiyun static int open_image(const char *image_name, tboot_entry *entry,
39*4882a593Smuzhiyun 		      struct tag_tboot_header_2k *hdr)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun 	u32 i, component_num, sign_offset;
42*4882a593Smuzhiyun 	component_data *pcompdata;
43*4882a593Smuzhiyun 	boot_component *pcomp;
44*4882a593Smuzhiyun 	int n_found = 0;
45*4882a593Smuzhiyun 	u32 comp_id;
46*4882a593Smuzhiyun 	int ret;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	ret = file2comp_id(image_name, &comp_id);
49*4882a593Smuzhiyun 	if (ret) {
50*4882a593Smuzhiyun 		printf("Can't find unknown image: %s\n", image_name);
51*4882a593Smuzhiyun 		return ret;
52*4882a593Smuzhiyun 	}
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	component_num = (hdr->size >> 16) & 0xffff;
55*4882a593Smuzhiyun 	sign_offset = (hdr->size & 0xffff) << 2;
56*4882a593Smuzhiyun 	pcompdata = (component_data *)((char *)hdr + sizeof(tboot_header));
57*4882a593Smuzhiyun 	pcomp = (boot_component *)((char *)hdr + sign_offset + SIGNATURE_SIZE);
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	for (i = 0; i < component_num; i++) {
60*4882a593Smuzhiyun 		if (comp_id == pcomp->component_id) {
61*4882a593Smuzhiyun 			if (n_found < MAX_BL_CODE_NUM) {
62*4882a593Smuzhiyun 				memcpy(&entry[n_found].component, pcomp,
63*4882a593Smuzhiyun 				       sizeof(boot_component));
64*4882a593Smuzhiyun 				memcpy(&entry[n_found].compdata, pcompdata,
65*4882a593Smuzhiyun 				       sizeof(component_data));
66*4882a593Smuzhiyun 				n_found++;
67*4882a593Smuzhiyun 			} else {
68*4882a593Smuzhiyun 				printf("Image num excess max: %d!\n",
69*4882a593Smuzhiyun 				       MAX_BL_CODE_NUM);
70*4882a593Smuzhiyun 				return -EINVAL;
71*4882a593Smuzhiyun 			}
72*4882a593Smuzhiyun 		} else {
73*4882a593Smuzhiyun 			if (n_found > 0)
74*4882a593Smuzhiyun 				break;
75*4882a593Smuzhiyun 		}
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 		pcomp++;
78*4882a593Smuzhiyun 		pcompdata++;
79*4882a593Smuzhiyun 	}
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	if (!n_found) {
82*4882a593Smuzhiyun 		printf("No find %s\n", image_name);
83*4882a593Smuzhiyun 		return -ENONET;
84*4882a593Smuzhiyun 	}
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	return n_found;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun 
check_image(struct tag_tboot_header_2k * hdr)89*4882a593Smuzhiyun static int check_image(struct tag_tboot_header_2k *hdr)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun 	u32 hash_format[] = { 0, 160, 256, 256 };
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	/* HASH format identifier */
94*4882a593Smuzhiyun 	return (hash_format[hdr->flags & 0x3] == 0) ? -EINVAL : 0;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
load_image(struct spl_load_info * info,struct tag_tboot_header_2k * hdr,u32 image_sector,const char * image_name,uintptr_t * entry_point)97*4882a593Smuzhiyun static int load_image(struct spl_load_info *info,
98*4882a593Smuzhiyun 		      struct tag_tboot_header_2k *hdr,
99*4882a593Smuzhiyun 		      u32 image_sector,
100*4882a593Smuzhiyun 		      const char *image_name,
101*4882a593Smuzhiyun 		      uintptr_t *entry_point)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	tboot_entry entry[MAX_BL_CODE_NUM];
104*4882a593Smuzhiyun 	void *image_buf = NULL;
105*4882a593Smuzhiyun 	ulong load_addr;
106*4882a593Smuzhiyun 	u32 sect_off;
107*4882a593Smuzhiyun 	u32 sect_cnt;
108*4882a593Smuzhiyun 	int image_num;
109*4882a593Smuzhiyun 	int i, ret;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	/* Parse components from image header */
112*4882a593Smuzhiyun 	image_num = open_image(image_name, entry, hdr);
113*4882a593Smuzhiyun 	if (image_num < 0)
114*4882a593Smuzhiyun 		return image_num;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	/* Get all component */
117*4882a593Smuzhiyun 	for (i = 0; i < image_num; i++) {
118*4882a593Smuzhiyun 		load_addr = entry[i].compdata.load_addr;
119*4882a593Smuzhiyun 		sect_cnt = entry[i].component.image_size;
120*4882a593Smuzhiyun 		sect_off = entry[i].component.storage_addr;
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 		printf("%s[%d]: addr=0x%lx, size=0x%lx\n",
123*4882a593Smuzhiyun 		       image_name, i, load_addr, (ulong)sect_cnt * 512);
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 		/*
126*4882a593Smuzhiyun 		 * MMC/NAND controller DMA can't access sram region, so:
127*4882a593Smuzhiyun 		 * data -> ddr buffer -> memcpy to sram region.
128*4882a593Smuzhiyun 		 */
129*4882a593Smuzhiyun 		if (load_addr < CONFIG_SYS_SDRAM_BASE ||
130*4882a593Smuzhiyun 		    load_addr >= CONFIG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE) {
131*4882a593Smuzhiyun 			image_buf = memalign(ARCH_DMA_MINALIGN, sect_cnt * 512);
132*4882a593Smuzhiyun 			if (!image_buf) {
133*4882a593Smuzhiyun 				printf("%s: malloc failed\n", __func__);
134*4882a593Smuzhiyun 				return -ENOMEM;
135*4882a593Smuzhiyun 			}
136*4882a593Smuzhiyun 		} else {
137*4882a593Smuzhiyun 			image_buf = (void *)load_addr;
138*4882a593Smuzhiyun 		}
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 		ret = info->read(info, image_sector + sect_off,
141*4882a593Smuzhiyun 				 sect_cnt, image_buf);
142*4882a593Smuzhiyun 		if (ret != sect_cnt) {
143*4882a593Smuzhiyun 			printf("Read '%s' failed at sector: %ld, ret=%d\n",
144*4882a593Smuzhiyun 			       image_name, (ulong)image_sector + sect_off, ret);
145*4882a593Smuzhiyun 			return -EIO;
146*4882a593Smuzhiyun 		}
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 		/* Verify component */
149*4882a593Smuzhiyun 		ret = check_image(hdr);
150*4882a593Smuzhiyun 		if (ret) {
151*4882a593Smuzhiyun 			printf("%s[%d]: verify image fail!\n", image_name, i);
152*4882a593Smuzhiyun 			return ret;
153*4882a593Smuzhiyun 		}
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 		/* Handle sram region */
156*4882a593Smuzhiyun 		if ((ulong)image_buf != load_addr) {
157*4882a593Smuzhiyun 			memcpy((void *)load_addr, image_buf, sect_cnt << 9);
158*4882a593Smuzhiyun 			free(image_buf);
159*4882a593Smuzhiyun 		}
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 		/* Fill entry_point by first component */
162*4882a593Smuzhiyun 		if (i == 0)
163*4882a593Smuzhiyun 			*entry_point = (uintptr_t)load_addr;
164*4882a593Smuzhiyun 	}
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	return ret;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun 
rkfw_load_trust(struct spl_load_info * info,u32 image_sector,struct spl_image_info * spl_image,int * found_rkfw,u32 try_count)169*4882a593Smuzhiyun static int rkfw_load_trust(struct spl_load_info *info, u32 image_sector,
170*4882a593Smuzhiyun 			   struct spl_image_info *spl_image,
171*4882a593Smuzhiyun 			   int *found_rkfw, u32 try_count)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun 	struct tag_tboot_header_2k hdr;
174*4882a593Smuzhiyun 	u32 sect_addr = image_sector;
175*4882a593Smuzhiyun 	int blkcnt = 4;	/* header sectors, 2KB */
176*4882a593Smuzhiyun 	int i, ret = 0;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	/* Find valid image header */
179*4882a593Smuzhiyun 	for (i = 0; i < try_count; i++) {
180*4882a593Smuzhiyun 		sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE);
181*4882a593Smuzhiyun 		if (blkcnt != info->read(info, sect_addr, blkcnt, &hdr))
182*4882a593Smuzhiyun 			continue;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 		if (hdr.tag == TBOOT_HEAD_TAG) {
185*4882a593Smuzhiyun 			/* Mark it */
186*4882a593Smuzhiyun 			*found_rkfw = 1;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 			/* bl31 is mandatory */
189*4882a593Smuzhiyun 			ret = load_image(info, &hdr, sect_addr,
190*4882a593Smuzhiyun 					 BL31_IMAGE_NAME, &spl_image->entry_point);
191*4882a593Smuzhiyun 			if (ret)
192*4882a593Smuzhiyun 				continue;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 			/* bl32 is optional */
195*4882a593Smuzhiyun 			ret = load_image(info, &hdr, sect_addr,
196*4882a593Smuzhiyun 					 BL32_IMAGE_NAME, &spl_image->entry_point_bl32);
197*4882a593Smuzhiyun 			if (ret) {
198*4882a593Smuzhiyun 				if (ret == -ENONET) {
199*4882a593Smuzhiyun 					spl_image->entry_point_bl32 = -1;	/* Not exist */
200*4882a593Smuzhiyun 					ret = 0;
201*4882a593Smuzhiyun 				} else {
202*4882a593Smuzhiyun 					continue;
203*4882a593Smuzhiyun 				}
204*4882a593Smuzhiyun 			}
205*4882a593Smuzhiyun 			break;
206*4882a593Smuzhiyun 		}
207*4882a593Smuzhiyun 	}
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	return ret;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun #else /* op-tee */
rkfw_load_trust(struct spl_load_info * info,u32 image_sector,struct spl_image_info * spl_image,int * found_rkfw,u32 try_count)212*4882a593Smuzhiyun static int rkfw_load_trust(struct spl_load_info *info, u32 image_sector,
213*4882a593Smuzhiyun 			   struct spl_image_info *spl_image,
214*4882a593Smuzhiyun 			   int *found_rkfw, u32 try_count)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun 	struct tag_second_loader_hdr hdr;
217*4882a593Smuzhiyun 	int i, ret, blkcnt = 4;	/* header sectors, 2KB */
218*4882a593Smuzhiyun 	char *load_addr;
219*4882a593Smuzhiyun 	u32 sect_addr;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	/* Detect valid image header */
222*4882a593Smuzhiyun 	for (i = 0; i < try_count; i++) {
223*4882a593Smuzhiyun 		sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE);
224*4882a593Smuzhiyun 		ret = info->read(info, sect_addr, blkcnt, &hdr);
225*4882a593Smuzhiyun 		if (ret != blkcnt)
226*4882a593Smuzhiyun 			continue;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 		if (!memcmp(hdr.magic, TBOOT_HEAD_TAG, 6)) {
229*4882a593Smuzhiyun 			*found_rkfw = 1;
230*4882a593Smuzhiyun 			spl_image->entry_point = (uintptr_t)hdr.loader_load_addr;
231*4882a593Smuzhiyun 			/* Load full binary image(right behind header) */
232*4882a593Smuzhiyun 			sect_addr += blkcnt;
233*4882a593Smuzhiyun 			load_addr = (char *)((size_t)hdr.loader_load_addr);
234*4882a593Smuzhiyun 			blkcnt = DIV_ROUND_UP(hdr.loader_load_size, 512);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 			printf("tee.bin: addr=0x%lx, size=0x%lx\n",
237*4882a593Smuzhiyun 			       (ulong)load_addr, (ulong)blkcnt * 512);
238*4882a593Smuzhiyun 			ret = info->read(info, sect_addr, blkcnt, load_addr);
239*4882a593Smuzhiyun 			if (ret != blkcnt)
240*4882a593Smuzhiyun 				continue;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 			break;
243*4882a593Smuzhiyun 		}
244*4882a593Smuzhiyun 	}
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	if (i == try_count) {
247*4882a593Smuzhiyun 		printf("Can not find usable trust\n");
248*4882a593Smuzhiyun 		return -ENONET;
249*4882a593Smuzhiyun 	}
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	return 0;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun #endif
254*4882a593Smuzhiyun 
rkfw_load_uboot(struct spl_load_info * info,u32 image_sector,struct spl_image_info * spl_image,u32 try_count)255*4882a593Smuzhiyun static int rkfw_load_uboot(struct spl_load_info *info, u32 image_sector,
256*4882a593Smuzhiyun 			   struct spl_image_info *spl_image, u32 try_count)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun 	struct tag_second_loader_hdr hdr;
259*4882a593Smuzhiyun 	int i, ret, blkcnt = 4;	/* header sectors, 2KB */
260*4882a593Smuzhiyun 	char *load_addr;
261*4882a593Smuzhiyun 	u32 sect_addr;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	/* Detect valid image header */
264*4882a593Smuzhiyun 	for (i = 0; i < try_count; i++) {
265*4882a593Smuzhiyun 		sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE);
266*4882a593Smuzhiyun 		ret = info->read(info, sect_addr, blkcnt, &hdr);
267*4882a593Smuzhiyun 		if (ret != blkcnt)
268*4882a593Smuzhiyun 			continue;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 		if (!memcmp(hdr.magic, LOADER_HARD_STR, 6)) {
271*4882a593Smuzhiyun 			/* Load full binary image(right behind header) */
272*4882a593Smuzhiyun 			sect_addr += blkcnt;
273*4882a593Smuzhiyun 			load_addr = (char *)((size_t)hdr.loader_load_addr);
274*4882a593Smuzhiyun 			blkcnt = DIV_ROUND_UP(hdr.loader_load_size, 512);
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 			printf("u-boot.bin: addr=0x%lx, size=0x%lx\n",
277*4882a593Smuzhiyun 			       (ulong)load_addr, (ulong)blkcnt * 512);
278*4882a593Smuzhiyun 			ret = info->read(info, sect_addr, blkcnt, load_addr);
279*4882a593Smuzhiyun 			if (ret != blkcnt)
280*4882a593Smuzhiyun 				continue;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 			break;
283*4882a593Smuzhiyun 		}
284*4882a593Smuzhiyun 	}
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	if (i == try_count) {
287*4882a593Smuzhiyun 		printf("Can not find usable uboot\n");
288*4882a593Smuzhiyun 		return -ENONET;
289*4882a593Smuzhiyun 	}
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	/* Fill entry point */
292*4882a593Smuzhiyun #ifdef CONFIG_SPL_ATF
293*4882a593Smuzhiyun 	spl_image->entry_point_bl33 = (uintptr_t)hdr.loader_load_addr;
294*4882a593Smuzhiyun #endif
295*4882a593Smuzhiyun #ifdef CONFIG_SPL_OPTEE
296*4882a593Smuzhiyun 	spl_image->entry_point_os = (uintptr_t)hdr.loader_load_addr;
297*4882a593Smuzhiyun #endif
298*4882a593Smuzhiyun 	return 0;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun 
rkfw_load_kernel(struct spl_load_info * info,u32 image_sector,struct spl_image_info * spl_image,u32 try_count)301*4882a593Smuzhiyun static int rkfw_load_kernel(struct spl_load_info *info, u32 image_sector,
302*4882a593Smuzhiyun 			    struct spl_image_info *spl_image, u32 try_count)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun 	struct andr_img_hdr *hdr;
305*4882a593Smuzhiyun 	int ret, cnt;
306*4882a593Smuzhiyun 	int dtb_sector, ramdisk_sector, resource_sector;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	cnt = ALIGN(sizeof(struct andr_img_hdr), 512) >> 9;
309*4882a593Smuzhiyun 	hdr = malloc(cnt * 512);
310*4882a593Smuzhiyun 	if (!hdr)
311*4882a593Smuzhiyun 		return -ENOMEM;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	ret = info->read(info, image_sector, cnt, (void *)hdr);
314*4882a593Smuzhiyun 	if (ret != cnt) {
315*4882a593Smuzhiyun 		ret = -EIO;
316*4882a593Smuzhiyun 		goto out;
317*4882a593Smuzhiyun 	}
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	if (memcmp(hdr->magic, ANDR_BOOT_MAGIC, strlen(ANDR_BOOT_MAGIC)) != 0) {
320*4882a593Smuzhiyun 		printf("SPL: boot image head magic error\n");
321*4882a593Smuzhiyun 		ret = -EINVAL;
322*4882a593Smuzhiyun 		goto out;
323*4882a593Smuzhiyun 	}
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	ramdisk_sector = ALIGN(hdr->kernel_size, hdr->page_size);
326*4882a593Smuzhiyun 	resource_sector = ALIGN(hdr->kernel_size, hdr->page_size)
327*4882a593Smuzhiyun 			+ ALIGN(hdr->ramdisk_size, hdr->page_size);
328*4882a593Smuzhiyun 	dtb_sector = ALIGN(hdr->kernel_size, hdr->page_size)
329*4882a593Smuzhiyun 			+ ALIGN(hdr->ramdisk_size, hdr->page_size)
330*4882a593Smuzhiyun 			+ ALIGN(hdr->second_size, hdr->page_size);
331*4882a593Smuzhiyun 	image_sector = image_sector + cnt;
332*4882a593Smuzhiyun 	cnt = ALIGN(hdr->kernel_size, hdr->page_size) >> 9;
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	/* Load kernel image */
335*4882a593Smuzhiyun #ifdef CONFIG_SPL_ROCKCHIP_HW_DECOMPRESS
336*4882a593Smuzhiyun 	ret = info->read(info, image_sector, cnt,
337*4882a593Smuzhiyun 			 (void *)CONFIG_SPL_KERNEL_COMPRESS_ADDR);
338*4882a593Smuzhiyun #else
339*4882a593Smuzhiyun 	ret = info->read(info, image_sector, cnt, (void *)CONFIG_SPL_KERNEL_ADDR);
340*4882a593Smuzhiyun #endif
341*4882a593Smuzhiyun 	if (ret != cnt) {
342*4882a593Smuzhiyun 		ret = -EIO;
343*4882a593Smuzhiyun 		goto out;
344*4882a593Smuzhiyun 	}
345*4882a593Smuzhiyun #ifdef CONFIG_SPL_ROCKCHIP_HW_DECOMPRESS
346*4882a593Smuzhiyun 	struct udevice *dev;
347*4882a593Smuzhiyun 	u32 cap = DECOM_GZIP;
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	dev = misc_decompress_get_device(cap);
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	if (!dev)
352*4882a593Smuzhiyun 		goto out;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	ret = misc_decompress_start(dev, CONFIG_SPL_KERNEL_COMPRESS_ADDR,
355*4882a593Smuzhiyun 				    CONFIG_SPL_KERNEL_ADDR,
356*4882a593Smuzhiyun 				    CONFIG_SPL_KERNEL_DECOM_LIMIT_SIZE);
357*4882a593Smuzhiyun 	if (ret)
358*4882a593Smuzhiyun 		goto out;
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun #endif
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	/* Load ramdisk image */
363*4882a593Smuzhiyun 	if (hdr->ramdisk_size) {
364*4882a593Smuzhiyun #ifdef CONFIG_SPL_ROCKCHIP_HW_DECOMPRESS
365*4882a593Smuzhiyun 		ret = info->read(info, (ramdisk_sector >> 9) + image_sector,
366*4882a593Smuzhiyun 				 ALIGN(hdr->ramdisk_size, hdr->page_size) >> 9,
367*4882a593Smuzhiyun 				 (void *)CONFIG_SPL_RAMDISK_COMPRESS_ADDR);
368*4882a593Smuzhiyun #else
369*4882a593Smuzhiyun 		ret = info->read(info, (ramdisk_sector >> 9) + image_sector,
370*4882a593Smuzhiyun 				 ALIGN(hdr->ramdisk_size, hdr->page_size) >> 9,
371*4882a593Smuzhiyun 				 (void *)CONFIG_SPL_RAMDISK_ADDR);
372*4882a593Smuzhiyun #endif
373*4882a593Smuzhiyun 		if (ret != (ALIGN(hdr->ramdisk_size, hdr->page_size) >> 9)) {
374*4882a593Smuzhiyun 			ret = -EIO;
375*4882a593Smuzhiyun 			goto out;
376*4882a593Smuzhiyun 		}
377*4882a593Smuzhiyun #ifdef CONFIG_SPL_ROCKCHIP_HW_DECOMPRESS
378*4882a593Smuzhiyun 		int timeout = 10000;
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 		while (!misc_decompress_is_complete(dev)) {
381*4882a593Smuzhiyun 			if (timeout < 0) {
382*4882a593Smuzhiyun 				ret = -EIO;
383*4882a593Smuzhiyun 				goto out;
384*4882a593Smuzhiyun 			}
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 			timeout--;
387*4882a593Smuzhiyun 			udelay(10);
388*4882a593Smuzhiyun 		}
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 		ret = misc_decompress_stop(dev);
391*4882a593Smuzhiyun 		if (ret)
392*4882a593Smuzhiyun 			goto out;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 		ret = misc_decompress_start(dev,
395*4882a593Smuzhiyun 					    CONFIG_SPL_RAMDISK_COMPRESS_ADDR,
396*4882a593Smuzhiyun 					    CONFIG_SPL_RAMDISK_ADDR,
397*4882a593Smuzhiyun 					    CONFIG_SPL_RAMDISK_DECOM_LIMIT_SIZE);
398*4882a593Smuzhiyun 		if (ret)
399*4882a593Smuzhiyun 			goto out;
400*4882a593Smuzhiyun #endif
401*4882a593Smuzhiyun 	}
402*4882a593Smuzhiyun #ifdef CONFIG_SPL_ROCKCHIP_HW_DECOMPRESS
403*4882a593Smuzhiyun 	else {
404*4882a593Smuzhiyun 		int timeout = 10000;
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 		while (!misc_decompress_is_complete(dev)) {
407*4882a593Smuzhiyun 			if (timeout < 0) {
408*4882a593Smuzhiyun 				ret = -EIO;
409*4882a593Smuzhiyun 				goto out;
410*4882a593Smuzhiyun 			}
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 			timeout--;
413*4882a593Smuzhiyun 			udelay(10);
414*4882a593Smuzhiyun 		}
415*4882a593Smuzhiyun 	}
416*4882a593Smuzhiyun #endif
417*4882a593Smuzhiyun 	/* Load resource, and checkout the dtb */
418*4882a593Smuzhiyun 	if (hdr->second_size) {
419*4882a593Smuzhiyun 		struct resource_img_hdr *head =
420*4882a593Smuzhiyun 		   (struct resource_img_hdr *)(CONFIG_SPL_FDT_ADDR + 0x100000);
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 		ret = info->read(info, (resource_sector >> 9) + image_sector,
423*4882a593Smuzhiyun 				 ALIGN(hdr->second_size, hdr->page_size) >> 9,
424*4882a593Smuzhiyun 				 (void *)head);
425*4882a593Smuzhiyun 		if (ret != (ALIGN(hdr->second_size, hdr->page_size) >> 9)) {
426*4882a593Smuzhiyun 			ret = -EIO;
427*4882a593Smuzhiyun 			goto out;
428*4882a593Smuzhiyun 		}
429*4882a593Smuzhiyun #ifdef CONFIG_SPL_KERNEL_BOOT
430*4882a593Smuzhiyun 		if (spl_resource_image_check_header(head)) {
431*4882a593Smuzhiyun 			printf("Can't find kernel dtb in spl.");
432*4882a593Smuzhiyun 		} else {
433*4882a593Smuzhiyun 			struct resource_entry *entry;
434*4882a593Smuzhiyun 			char *dtb_temp;
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 			entry = spl_resource_image_get_dtb_entry(head);
437*4882a593Smuzhiyun 			if (!entry) {
438*4882a593Smuzhiyun 				ret = -EIO;
439*4882a593Smuzhiyun 				goto out;
440*4882a593Smuzhiyun 			}
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 			dtb_temp = (char *)((char *)head + entry->f_offset * 512);
443*4882a593Smuzhiyun 			memcpy((char *)CONFIG_SPL_FDT_ADDR, dtb_temp,
444*4882a593Smuzhiyun 			       entry->f_size);
445*4882a593Smuzhiyun 		}
446*4882a593Smuzhiyun #endif
447*4882a593Smuzhiyun 	} else {
448*4882a593Smuzhiyun 		/* Load dtb image */
449*4882a593Smuzhiyun 		ret = info->read(info, (dtb_sector >> 9) + image_sector,
450*4882a593Smuzhiyun 				 ALIGN(hdr->dtb_size, hdr->page_size) >> 9,
451*4882a593Smuzhiyun 				 (void *)CONFIG_SPL_FDT_ADDR);
452*4882a593Smuzhiyun 		if (ret != (ALIGN(hdr->dtb_size, hdr->page_size) >> 9)) {
453*4882a593Smuzhiyun 			ret = -EIO;
454*4882a593Smuzhiyun 			goto out;
455*4882a593Smuzhiyun 		}
456*4882a593Smuzhiyun 	}
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 	spl_image->fdt_addr = (void *)CONFIG_SPL_FDT_ADDR;
459*4882a593Smuzhiyun #ifdef CONFIG_SPL_OPTEE
460*4882a593Smuzhiyun 	spl_image->entry_point_os = (uintptr_t)CONFIG_SPL_KERNEL_ADDR;
461*4882a593Smuzhiyun #endif
462*4882a593Smuzhiyun #ifdef CONFIG_SPL_ATF
463*4882a593Smuzhiyun 	spl_image->entry_point_bl33 = CONFIG_SPL_KERNEL_ADDR;
464*4882a593Smuzhiyun #endif
465*4882a593Smuzhiyun 	ret = 0;
466*4882a593Smuzhiyun out:
467*4882a593Smuzhiyun 	free(hdr);
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	return ret;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun 
spl_load_rkfw_image(struct spl_image_info * spl_image,struct spl_load_info * info)472*4882a593Smuzhiyun int spl_load_rkfw_image(struct spl_image_info *spl_image,
473*4882a593Smuzhiyun 			struct spl_load_info *info)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun 	u32 uboot_sector = CONFIG_RKFW_U_BOOT_SECTOR;
476*4882a593Smuzhiyun 	u32 trust_sector = CONFIG_RKFW_TRUST_SECTOR;
477*4882a593Smuzhiyun 	u32 boot_sector  = CONFIG_RKFW_BOOT_SECTOR;
478*4882a593Smuzhiyun 	int ret, try_count = RKFW_RETRY_SECTOR_TIMES;
479*4882a593Smuzhiyun 	int found_rkfw = 0;
480*4882a593Smuzhiyun 	char *part_name;
481*4882a593Smuzhiyun #ifdef CONFIG_SPL_LIBDISK_SUPPORT
482*4882a593Smuzhiyun 	struct blk_desc *dev_desc = info->dev;
483*4882a593Smuzhiyun 	disk_partition_t part_info;
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	if (dev_desc) {
486*4882a593Smuzhiyun 		if (part_get_info_by_name(dev_desc, PART_UBOOT, &part_info) > 0)
487*4882a593Smuzhiyun 			uboot_sector = part_info.start;
488*4882a593Smuzhiyun 		if (part_get_info_by_name(dev_desc, PART_TRUST, &part_info) > 0)
489*4882a593Smuzhiyun 			trust_sector = part_info.start;
490*4882a593Smuzhiyun 		if (part_get_info_by_name(dev_desc, PART_BOOT, &part_info) > 0)
491*4882a593Smuzhiyun 			boot_sector = part_info.start;
492*4882a593Smuzhiyun 	}
493*4882a593Smuzhiyun #endif
494*4882a593Smuzhiyun 	/* u-boot or boot */
495*4882a593Smuzhiyun 	if (spl_image->next_stage != SPL_NEXT_STAGE_UBOOT)
496*4882a593Smuzhiyun 		uboot_sector = 0;
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	ret = rkfw_load_trust(info, trust_sector, spl_image,
499*4882a593Smuzhiyun 			      &found_rkfw, try_count);
500*4882a593Smuzhiyun 	if (ret) {
501*4882a593Smuzhiyun 		part_name = PART_TRUST;
502*4882a593Smuzhiyun 		goto out;
503*4882a593Smuzhiyun 	}
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	if (uboot_sector) {
506*4882a593Smuzhiyun 		ret = rkfw_load_uboot(info, uboot_sector, spl_image, try_count);
507*4882a593Smuzhiyun 		if (ret) {
508*4882a593Smuzhiyun 			part_name = PART_UBOOT;
509*4882a593Smuzhiyun 			goto out;
510*4882a593Smuzhiyun 		}
511*4882a593Smuzhiyun 	} else {
512*4882a593Smuzhiyun 		ret = rkfw_load_kernel(info, boot_sector, spl_image, try_count);
513*4882a593Smuzhiyun 		if (ret) {
514*4882a593Smuzhiyun 			part_name = PART_BOOT;
515*4882a593Smuzhiyun 			goto out;
516*4882a593Smuzhiyun 		}
517*4882a593Smuzhiyun 	}
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(LOAD_FIT)
520*4882a593Smuzhiyun 	spl_image->fdt_addr = 0;
521*4882a593Smuzhiyun #endif
522*4882a593Smuzhiyun #ifdef CONFIG_SPL_ATF
523*4882a593Smuzhiyun 	spl_image->os = IH_OS_ARM_TRUSTED_FIRMWARE;
524*4882a593Smuzhiyun #else
525*4882a593Smuzhiyun 	spl_image->os = IH_OS_OP_TEE;
526*4882a593Smuzhiyun #endif
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun out:
529*4882a593Smuzhiyun 	if (ret)
530*4882a593Smuzhiyun 		printf("Load %s part failed! ret=%d\n", part_name, ret);
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	/* If not found rockchip firmware, try others outside */
533*4882a593Smuzhiyun 	return found_rkfw ? ret : -EAGAIN;
534*4882a593Smuzhiyun }
535