xref: /rk3399_rockchip-uboot/common/spl/spl_rkfw.c (revision aa415ed977dfe09ebefc58d99f5e73521a5d3f07)
113c5d8ecSJoseph Chen // SPDX-License-Identifier: GPL-2.0
213c5d8ecSJoseph Chen /*
313c5d8ecSJoseph Chen  * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
413c5d8ecSJoseph Chen  */
513c5d8ecSJoseph Chen 
613c5d8ecSJoseph Chen #include <common.h>
7e3460df7SJason Zhu #include <android_image.h>
8e3460df7SJason Zhu #include <errno.h>
913c5d8ecSJoseph Chen #include <malloc.h>
10*aa415ed9SJoseph Chen #include <spl.h>
1113c5d8ecSJoseph Chen #include <spl_rkfw.h>
12e3460df7SJason Zhu #include <linux/kernel.h>
132241fc0fSJason Zhu #include <asm/arch/spl_resource_img.h>
1413c5d8ecSJoseph Chen 
151cb393f1SJason Zhu #ifdef CONFIG_SPL_ATF
1613c5d8ecSJoseph Chen static const __aligned(16) struct s_fip_name_id fip_name_id[] = {
1713c5d8ecSJoseph Chen 	{ BL30_IMAGE_NAME, UUID_SCP_FIRMWARE_BL30 },		/* optional */
1813c5d8ecSJoseph Chen 	{ BL31_IMAGE_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31 },	/* mandatory */
1913c5d8ecSJoseph Chen 	{ BL32_IMAGE_NAME, UUID_SECURE_PAYLOAD_BL32 },		/* optional */
2013c5d8ecSJoseph Chen };
2113c5d8ecSJoseph Chen 
2213c5d8ecSJoseph Chen static int file2comp_id(const char *file_name, u32 *comp_id)
2313c5d8ecSJoseph Chen {
2413c5d8ecSJoseph Chen 	int i;
2513c5d8ecSJoseph Chen 
2613c5d8ecSJoseph Chen 	for (i = 0; i < ARRAY_SIZE(fip_name_id); i++) {
2713c5d8ecSJoseph Chen 		if (!strcmp(file_name, fip_name_id[i].name)) {
2813c5d8ecSJoseph Chen 			*comp_id = fip_name_id[i].id;
2913c5d8ecSJoseph Chen 			return 0;
3013c5d8ecSJoseph Chen 		}
3113c5d8ecSJoseph Chen 	}
3213c5d8ecSJoseph Chen 
3313c5d8ecSJoseph Chen 	return -ENOENT;
3413c5d8ecSJoseph Chen }
3513c5d8ecSJoseph Chen 
3613c5d8ecSJoseph Chen static int open_image(const char *image_name, tboot_entry *entry,
3713c5d8ecSJoseph Chen 		      struct tag_tboot_header_2k *hdr)
3813c5d8ecSJoseph Chen {
3913c5d8ecSJoseph Chen 	u32 i, component_num, sign_offset;
4013c5d8ecSJoseph Chen 	component_data *pcompdata;
4113c5d8ecSJoseph Chen 	boot_component *pcomp;
4213c5d8ecSJoseph Chen 	int n_found = 0;
4313c5d8ecSJoseph Chen 	u32 comp_id;
4413c5d8ecSJoseph Chen 	int ret;
4513c5d8ecSJoseph Chen 
4613c5d8ecSJoseph Chen 	ret = file2comp_id(image_name, &comp_id);
4713c5d8ecSJoseph Chen 	if (ret) {
4813c5d8ecSJoseph Chen 		printf("Can't find unknown image: %s\n", image_name);
4913c5d8ecSJoseph Chen 		return ret;
5013c5d8ecSJoseph Chen 	}
5113c5d8ecSJoseph Chen 
5213c5d8ecSJoseph Chen 	component_num = (hdr->size >> 16) & 0xffff;
5313c5d8ecSJoseph Chen 	sign_offset = (hdr->size & 0xffff) << 2;
5413c5d8ecSJoseph Chen 	pcompdata = (component_data *)((char *)hdr + sizeof(tboot_header));
5513c5d8ecSJoseph Chen 	pcomp = (boot_component *)((char *)hdr + sign_offset + SIGNATURE_SIZE);
5613c5d8ecSJoseph Chen 
5713c5d8ecSJoseph Chen 	for (i = 0; i < component_num; i++) {
5813c5d8ecSJoseph Chen 		if (comp_id == pcomp->component_id) {
5913c5d8ecSJoseph Chen 			if (n_found < MAX_BL_CODE_NUM) {
6013c5d8ecSJoseph Chen 				memcpy(&entry[n_found].component, pcomp,
6113c5d8ecSJoseph Chen 				       sizeof(boot_component));
6213c5d8ecSJoseph Chen 				memcpy(&entry[n_found].compdata, pcompdata,
6313c5d8ecSJoseph Chen 				       sizeof(component_data));
6413c5d8ecSJoseph Chen 				n_found++;
6513c5d8ecSJoseph Chen 			} else {
6613c5d8ecSJoseph Chen 				printf("Image num excess max: %d!\n",
6713c5d8ecSJoseph Chen 				       MAX_BL_CODE_NUM);
6813c5d8ecSJoseph Chen 				return -EINVAL;
6913c5d8ecSJoseph Chen 			}
7013c5d8ecSJoseph Chen 		} else {
7113c5d8ecSJoseph Chen 			if (n_found > 0)
7213c5d8ecSJoseph Chen 				break;
7313c5d8ecSJoseph Chen 		}
7413c5d8ecSJoseph Chen 
7513c5d8ecSJoseph Chen 		pcomp++;
7613c5d8ecSJoseph Chen 		pcompdata++;
7713c5d8ecSJoseph Chen 	}
7813c5d8ecSJoseph Chen 
7913c5d8ecSJoseph Chen 	if (!n_found) {
8013c5d8ecSJoseph Chen 		printf("No find %s\n", image_name);
8113c5d8ecSJoseph Chen 		return -ENONET;
8213c5d8ecSJoseph Chen 	}
8313c5d8ecSJoseph Chen 
8413c5d8ecSJoseph Chen 	return n_found;
8513c5d8ecSJoseph Chen }
8613c5d8ecSJoseph Chen 
8713c5d8ecSJoseph Chen static int check_image(struct tag_tboot_header_2k *hdr)
8813c5d8ecSJoseph Chen {
8913c5d8ecSJoseph Chen 	u32 hash_format[] = { 0, 160, 256, 256 };
9013c5d8ecSJoseph Chen 
9113c5d8ecSJoseph Chen 	/* HASH format identifier */
9213c5d8ecSJoseph Chen 	return (hash_format[hdr->flags & 0x3] == 0) ? -EINVAL : 0;
9313c5d8ecSJoseph Chen }
9413c5d8ecSJoseph Chen 
9513c5d8ecSJoseph Chen static int load_image(struct spl_load_info *info,
9613c5d8ecSJoseph Chen 		      struct tag_tboot_header_2k *hdr,
9713c5d8ecSJoseph Chen 		      u32 image_sector,
9813c5d8ecSJoseph Chen 		      const char *image_name,
9913c5d8ecSJoseph Chen 		      uintptr_t *entry_point)
10013c5d8ecSJoseph Chen {
10113c5d8ecSJoseph Chen 	tboot_entry entry[MAX_BL_CODE_NUM];
10213c5d8ecSJoseph Chen 	void *image_buf = NULL;
10313c5d8ecSJoseph Chen 	ulong load_addr;
10413c5d8ecSJoseph Chen 	u32 sect_off;
10513c5d8ecSJoseph Chen 	u32 sect_cnt;
10613c5d8ecSJoseph Chen 	int image_num;
10713c5d8ecSJoseph Chen 	int i, ret;
10813c5d8ecSJoseph Chen 
10913c5d8ecSJoseph Chen 	/* Parse components from image header */
11013c5d8ecSJoseph Chen 	image_num = open_image(image_name, entry, hdr);
11113c5d8ecSJoseph Chen 	if (image_num < 0)
11213c5d8ecSJoseph Chen 		return image_num;
11313c5d8ecSJoseph Chen 
11413c5d8ecSJoseph Chen 	/* Get all component */
11513c5d8ecSJoseph Chen 	for (i = 0; i < image_num; i++) {
11613c5d8ecSJoseph Chen 		load_addr = entry[i].compdata.load_addr;
11713c5d8ecSJoseph Chen 		sect_cnt = entry[i].component.image_size;
11813c5d8ecSJoseph Chen 		sect_off = entry[i].component.storage_addr;
11913c5d8ecSJoseph Chen 
12013c5d8ecSJoseph Chen 		printf("%s[%d]: addr=0x%lx, size=0x%lx\n",
12113c5d8ecSJoseph Chen 		       image_name, i, load_addr, (ulong)sect_cnt * 512);
12213c5d8ecSJoseph Chen 
12313c5d8ecSJoseph Chen 		/*
12413c5d8ecSJoseph Chen 		 * MMC/NAND controller DMA can't access sram region, so:
12513c5d8ecSJoseph Chen 		 * data -> ddr buffer -> memcpy to sram region.
12613c5d8ecSJoseph Chen 		 */
127b35a1137SJoseph Chen 		if (load_addr < CONFIG_SYS_SDRAM_BASE ||
128b35a1137SJoseph Chen 		    load_addr >= CONFIG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE) {
12913c5d8ecSJoseph Chen 			image_buf = memalign(ARCH_DMA_MINALIGN, sect_cnt * 512);
13013c5d8ecSJoseph Chen 			if (!image_buf) {
13113c5d8ecSJoseph Chen 				printf("%s: malloc failed\n", __func__);
13213c5d8ecSJoseph Chen 				return -ENOMEM;
13313c5d8ecSJoseph Chen 			}
13413c5d8ecSJoseph Chen 		} else {
13513c5d8ecSJoseph Chen 			image_buf = (void *)load_addr;
13613c5d8ecSJoseph Chen 		}
13713c5d8ecSJoseph Chen 
13813c5d8ecSJoseph Chen 		ret = info->read(info, image_sector + sect_off,
13913c5d8ecSJoseph Chen 				 sect_cnt, image_buf);
14013c5d8ecSJoseph Chen 		if (ret != sect_cnt) {
14113c5d8ecSJoseph Chen 			printf("Read '%s' failed at sector: %ld, ret=%d\n",
14213c5d8ecSJoseph Chen 			       image_name, (ulong)image_sector + sect_off, ret);
14313c5d8ecSJoseph Chen 			return -EIO;
14413c5d8ecSJoseph Chen 		}
14513c5d8ecSJoseph Chen 
14613c5d8ecSJoseph Chen 		/* Verify component */
14713c5d8ecSJoseph Chen 		ret = check_image(hdr);
14813c5d8ecSJoseph Chen 		if (ret) {
14913c5d8ecSJoseph Chen 			printf("%s[%d]: verify image fail!\n", image_name, i);
15013c5d8ecSJoseph Chen 			return ret;
15113c5d8ecSJoseph Chen 		}
15213c5d8ecSJoseph Chen 
15313c5d8ecSJoseph Chen 		/* Handle sram region */
15413c5d8ecSJoseph Chen 		if ((ulong)image_buf != load_addr) {
15513c5d8ecSJoseph Chen 			memcpy((void *)load_addr, image_buf, sect_cnt << 9);
15613c5d8ecSJoseph Chen 			free(image_buf);
15713c5d8ecSJoseph Chen 		}
15813c5d8ecSJoseph Chen 
15913c5d8ecSJoseph Chen 		/* Fill entry_point by first component */
16013c5d8ecSJoseph Chen 		if (i == 0)
16113c5d8ecSJoseph Chen 			*entry_point = (uintptr_t)load_addr;
16213c5d8ecSJoseph Chen 	}
16313c5d8ecSJoseph Chen 
16413c5d8ecSJoseph Chen 	return ret;
16513c5d8ecSJoseph Chen }
16613c5d8ecSJoseph Chen 
16713c5d8ecSJoseph Chen static int rkfw_load_trust(struct spl_load_info *info, u32 image_sector,
1681cb393f1SJason Zhu 			   struct spl_image_info *spl_image,
16913c5d8ecSJoseph Chen 			   int *found_rkfw, u32 try_count)
17013c5d8ecSJoseph Chen {
17113c5d8ecSJoseph Chen 	struct tag_tboot_header_2k hdr;
17213c5d8ecSJoseph Chen 	u32 sect_addr = image_sector;
17313c5d8ecSJoseph Chen 	int blkcnt = 4;	/* header sectors, 2KB */
17413c5d8ecSJoseph Chen 	int i, ret = 0;
17513c5d8ecSJoseph Chen 
17613c5d8ecSJoseph Chen 	/* Find valid image header */
17713c5d8ecSJoseph Chen 	for (i = 0; i < try_count; i++) {
17813c5d8ecSJoseph Chen 		sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE);
17913c5d8ecSJoseph Chen 		if (blkcnt != info->read(info, sect_addr, blkcnt, &hdr))
18013c5d8ecSJoseph Chen 			continue;
18113c5d8ecSJoseph Chen 
18213c5d8ecSJoseph Chen 		if (hdr.tag == TBOOT_HEAD_TAG) {
18313c5d8ecSJoseph Chen 			/* Mark it */
18413c5d8ecSJoseph Chen 			*found_rkfw = 1;
18513c5d8ecSJoseph Chen 
18613c5d8ecSJoseph Chen 			/* bl31 is mandatory */
18713c5d8ecSJoseph Chen 			ret = load_image(info, &hdr, sect_addr,
1881cb393f1SJason Zhu 					 BL31_IMAGE_NAME, &spl_image->entry_point);
18913c5d8ecSJoseph Chen 			if (ret)
19013c5d8ecSJoseph Chen 				continue;
19113c5d8ecSJoseph Chen 
19213c5d8ecSJoseph Chen 			/* bl32 is optional */
19313c5d8ecSJoseph Chen 			ret = load_image(info, &hdr, sect_addr,
1941cb393f1SJason Zhu 					 BL32_IMAGE_NAME, &spl_image->entry_point_bl32);
19513c5d8ecSJoseph Chen 			if (ret) {
19613c5d8ecSJoseph Chen 				if (ret == -ENONET) {
1971cb393f1SJason Zhu 					spl_image->entry_point_bl32 = -1;	/* Not exist */
19813c5d8ecSJoseph Chen 					ret = 0;
19913c5d8ecSJoseph Chen 				} else {
20013c5d8ecSJoseph Chen 					continue;
20113c5d8ecSJoseph Chen 				}
20213c5d8ecSJoseph Chen 			}
20313c5d8ecSJoseph Chen 			break;
20413c5d8ecSJoseph Chen 		}
20513c5d8ecSJoseph Chen 	}
20613c5d8ecSJoseph Chen 
20713c5d8ecSJoseph Chen 	return ret;
20813c5d8ecSJoseph Chen }
2091cb393f1SJason Zhu #else
2101cb393f1SJason Zhu static int rkfw_load_trust(struct spl_load_info *info, u32 image_sector,
2111cb393f1SJason Zhu 			   struct spl_image_info *spl_image,
2121cb393f1SJason Zhu 			   int *found_rkfw, u32 try_count)
2131cb393f1SJason Zhu {
2141cb393f1SJason Zhu 	struct tag_second_loader_hdr hdr;
2151cb393f1SJason Zhu 	int i, ret, blkcnt = 4;	/* header sectors, 2KB */
2161cb393f1SJason Zhu 	char *load_addr;
2171cb393f1SJason Zhu 	u32 sect_addr;
2181cb393f1SJason Zhu 
2191cb393f1SJason Zhu 	/* Detect valid image header */
2201cb393f1SJason Zhu 	for (i = 0; i < try_count; i++) {
2211cb393f1SJason Zhu 		sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE);
2221cb393f1SJason Zhu 		ret = info->read(info, sect_addr, blkcnt, &hdr);
2231cb393f1SJason Zhu 		if (ret != blkcnt)
2241cb393f1SJason Zhu 			continue;
2251cb393f1SJason Zhu 
2261cb393f1SJason Zhu 		if (!memcmp(hdr.magic, TBOOT_HEAD_TAG, 6)) {
2271cb393f1SJason Zhu 			*found_rkfw = 1;
2281cb393f1SJason Zhu 			spl_image->entry_point = (uintptr_t)hdr.loader_load_addr;
2291cb393f1SJason Zhu 			/* Load full binary image(right behind header) */
2301cb393f1SJason Zhu 			sect_addr += blkcnt;
2311cb393f1SJason Zhu 			load_addr = (char *)((size_t)hdr.loader_load_addr);
2321cb393f1SJason Zhu 			blkcnt = DIV_ROUND_UP(hdr.loader_load_size, 512);
2331cb393f1SJason Zhu 
2341cb393f1SJason Zhu 			printf("tee.bin: addr=0x%lx, size=0x%lx\n",
2351cb393f1SJason Zhu 			       (ulong)load_addr, (ulong)blkcnt * 512);
2361cb393f1SJason Zhu 			ret = info->read(info, sect_addr, blkcnt, load_addr);
2371cb393f1SJason Zhu 			if (ret != blkcnt)
2381cb393f1SJason Zhu 				continue;
2391cb393f1SJason Zhu 
2401cb393f1SJason Zhu 			break;
2411cb393f1SJason Zhu 		}
2421cb393f1SJason Zhu 	}
2431cb393f1SJason Zhu 
2441cb393f1SJason Zhu 	if (i == try_count) {
2451cb393f1SJason Zhu 		printf("Can not find usable uboot\n");
2461cb393f1SJason Zhu 		return -ENONET;
2471cb393f1SJason Zhu 	}
2481cb393f1SJason Zhu 
2491cb393f1SJason Zhu 	return 0;
2501cb393f1SJason Zhu }
2511cb393f1SJason Zhu #endif
25213c5d8ecSJoseph Chen 
25313c5d8ecSJoseph Chen static int rkfw_load_uboot(struct spl_load_info *info, u32 image_sector,
2541cb393f1SJason Zhu 			   struct spl_image_info *spl_image, u32 try_count)
25513c5d8ecSJoseph Chen {
25613c5d8ecSJoseph Chen 	struct tag_second_loader_hdr hdr;
25713c5d8ecSJoseph Chen 	int i, ret, blkcnt = 4;	/* header sectors, 2KB */
25813c5d8ecSJoseph Chen 	char *load_addr;
25913c5d8ecSJoseph Chen 	u32 sect_addr;
26013c5d8ecSJoseph Chen 
26113c5d8ecSJoseph Chen 	/* Detect valid image header */
26213c5d8ecSJoseph Chen 	for (i = 0; i < try_count; i++) {
26313c5d8ecSJoseph Chen 		sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE);
26413c5d8ecSJoseph Chen 		ret = info->read(info, sect_addr, blkcnt, &hdr);
26513c5d8ecSJoseph Chen 		if (ret != blkcnt)
26613c5d8ecSJoseph Chen 			continue;
26713c5d8ecSJoseph Chen 
26813c5d8ecSJoseph Chen 		if (!memcmp(hdr.magic, LOADER_HARD_STR, 6)) {
26913c5d8ecSJoseph Chen 			/* Load full binary image(right behind header) */
27013c5d8ecSJoseph Chen 			sect_addr += blkcnt;
27113c5d8ecSJoseph Chen 			load_addr = (char *)((size_t)hdr.loader_load_addr);
27213c5d8ecSJoseph Chen 			blkcnt = DIV_ROUND_UP(hdr.loader_load_size, 512);
27313c5d8ecSJoseph Chen 
27413c5d8ecSJoseph Chen 			printf("u-boot.bin: addr=0x%lx, size=0x%lx\n",
27513c5d8ecSJoseph Chen 			       (ulong)load_addr, (ulong)blkcnt * 512);
27613c5d8ecSJoseph Chen 			ret = info->read(info, sect_addr, blkcnt, load_addr);
27713c5d8ecSJoseph Chen 			if (ret != blkcnt)
27813c5d8ecSJoseph Chen 				continue;
27913c5d8ecSJoseph Chen 
28013c5d8ecSJoseph Chen 			break;
28113c5d8ecSJoseph Chen 		}
28213c5d8ecSJoseph Chen 	}
28313c5d8ecSJoseph Chen 
28413c5d8ecSJoseph Chen 	if (i == try_count) {
28513c5d8ecSJoseph Chen 		printf("Can not find usable uboot\n");
28613c5d8ecSJoseph Chen 		return -ENONET;
28713c5d8ecSJoseph Chen 	}
28813c5d8ecSJoseph Chen 
28913c5d8ecSJoseph Chen 	/* Fill entry point */
2901cb393f1SJason Zhu #ifdef CONFIG_SPL_ATF
2911cb393f1SJason Zhu 	spl_image->entry_point_bl33 = (uintptr_t)hdr.loader_load_addr;
2921cb393f1SJason Zhu #endif
2931cb393f1SJason Zhu #ifdef CONFIG_SPL_OPTEE
2941cb393f1SJason Zhu 	spl_image->entry_point_os = (uintptr_t)hdr.loader_load_addr;
2951cb393f1SJason Zhu #endif
29613c5d8ecSJoseph Chen 	return 0;
29713c5d8ecSJoseph Chen }
29813c5d8ecSJoseph Chen 
299e3460df7SJason Zhu static int rkfw_load_kernel(struct spl_load_info *info, u32 image_sector,
3001cb393f1SJason Zhu 			    struct spl_image_info *spl_image, u32 try_count)
301e3460df7SJason Zhu {
302e3460df7SJason Zhu 	struct andr_img_hdr *hdr;
303e3460df7SJason Zhu 	int ret, cnt;
3042241fc0fSJason Zhu 	int dtb_sector, ramdisk_sector, resource_sector;
305e3460df7SJason Zhu 
306e3460df7SJason Zhu 	cnt = ALIGN(sizeof(struct andr_img_hdr), 512) >> 9;
307e3460df7SJason Zhu 	hdr = malloc(cnt * 512);
308e3460df7SJason Zhu 	if (!hdr)
309e3460df7SJason Zhu 		return -ENOMEM;
310e3460df7SJason Zhu 
311e3460df7SJason Zhu 	ret = info->read(info, image_sector, cnt, (void *)hdr);
312e3460df7SJason Zhu 	if (ret != cnt) {
313e3460df7SJason Zhu 		ret = -EIO;
314e3460df7SJason Zhu 		goto out;
315e3460df7SJason Zhu 	}
316e3460df7SJason Zhu 
317e3460df7SJason Zhu 	if (memcmp(hdr->magic, ANDR_BOOT_MAGIC, strlen(ANDR_BOOT_MAGIC)) != 0) {
318e3460df7SJason Zhu 		printf("SPL: boot image head magic error\n");
319e3460df7SJason Zhu 		ret = -EINVAL;
320e3460df7SJason Zhu 		goto out;
321e3460df7SJason Zhu 	}
322e3460df7SJason Zhu 
323e3460df7SJason Zhu 	ramdisk_sector = ALIGN(hdr->kernel_size, hdr->page_size);
3242241fc0fSJason Zhu 	resource_sector = ALIGN(hdr->kernel_size, hdr->page_size)
3252241fc0fSJason Zhu 			+ ALIGN(hdr->ramdisk_size, hdr->page_size);
326e3460df7SJason Zhu 	dtb_sector = ALIGN(hdr->kernel_size, hdr->page_size)
327e3460df7SJason Zhu 			+ ALIGN(hdr->ramdisk_size, hdr->page_size)
328e3460df7SJason Zhu 			+ ALIGN(hdr->second_size, hdr->page_size);
329e3460df7SJason Zhu 	image_sector = image_sector + cnt;
330e3460df7SJason Zhu 	cnt = ALIGN(hdr->kernel_size, hdr->page_size) >> 9;
331e3460df7SJason Zhu 
332e3460df7SJason Zhu 	/* Load kernel image */
333e3460df7SJason Zhu 	ret = info->read(info, image_sector, cnt, (void *)CONFIG_SPL_KERNEL_ADDR);
334e3460df7SJason Zhu 	if (ret != cnt) {
335e3460df7SJason Zhu 		ret = -EIO;
336e3460df7SJason Zhu 		goto out;
337e3460df7SJason Zhu 	}
338e3460df7SJason Zhu 
339e3460df7SJason Zhu 	/* Load ramdisk image */
340e3460df7SJason Zhu 	if (hdr->ramdisk_size) {
341e3460df7SJason Zhu 		ret = info->read(info, (ramdisk_sector >> 9) + image_sector,
342e3460df7SJason Zhu 				 ALIGN(hdr->ramdisk_size, hdr->page_size) >> 9,
343e3460df7SJason Zhu 				 (void *)CONFIG_SPL_RAMDISK_ADDR);
344e3460df7SJason Zhu 		if (ret != (ALIGN(hdr->ramdisk_size, hdr->page_size) >> 9)) {
345e3460df7SJason Zhu 			ret = -EIO;
346e3460df7SJason Zhu 			goto out;
347e3460df7SJason Zhu 		}
348e3460df7SJason Zhu 	}
349e3460df7SJason Zhu 
3502241fc0fSJason Zhu 	/* Load resource, and checkout the dtb */
3512241fc0fSJason Zhu 	if (hdr->second_size) {
3522241fc0fSJason Zhu 		struct resource_img_hdr *head =
3532241fc0fSJason Zhu 		   (struct resource_img_hdr *)(CONFIG_SPL_FDT_ADDR + 0x100000);
3542241fc0fSJason Zhu 
3552241fc0fSJason Zhu 		ret = info->read(info, (resource_sector >> 9) + image_sector,
3562241fc0fSJason Zhu 				 ALIGN(hdr->second_size, hdr->page_size) >> 9,
3572241fc0fSJason Zhu 				 (void *)head);
3582241fc0fSJason Zhu 		if (ret != (ALIGN(hdr->second_size, hdr->page_size) >> 9)) {
3592241fc0fSJason Zhu 			ret = -EIO;
3602241fc0fSJason Zhu 			goto out;
3612241fc0fSJason Zhu 		}
3621cb393f1SJason Zhu #ifdef CONFIG_SPL_KERNEL_BOOT
3632241fc0fSJason Zhu 		if (spl_resource_image_check_header(head)) {
3642241fc0fSJason Zhu 			printf("Can't find kernel dtb in spl.");
3652241fc0fSJason Zhu 		} else {
3662241fc0fSJason Zhu 			struct resource_entry *entry;
3672241fc0fSJason Zhu 			char *dtb_temp;
3682241fc0fSJason Zhu 
3692241fc0fSJason Zhu 			entry = spl_resource_image_get_dtb_entry(head);
3702241fc0fSJason Zhu 			if (!entry) {
3712241fc0fSJason Zhu 				ret = -EIO;
3722241fc0fSJason Zhu 				goto out;
3732241fc0fSJason Zhu 			}
3742241fc0fSJason Zhu 
3752241fc0fSJason Zhu 			dtb_temp = (char *)((char *)head + entry->f_offset * 512);
3762241fc0fSJason Zhu 			memcpy((char *)CONFIG_SPL_FDT_ADDR, dtb_temp,
3772241fc0fSJason Zhu 			       entry->f_size);
3782241fc0fSJason Zhu 		}
3791cb393f1SJason Zhu #endif
3802241fc0fSJason Zhu 	} else {
381e3460df7SJason Zhu 		/* Load dtb image */
382e3460df7SJason Zhu 		ret = info->read(info, (dtb_sector >> 9) + image_sector,
383e3460df7SJason Zhu 				 ALIGN(hdr->dtb_size, hdr->page_size) >> 9,
384e3460df7SJason Zhu 				 (void *)CONFIG_SPL_FDT_ADDR);
385e3460df7SJason Zhu 		if (ret != (ALIGN(hdr->dtb_size, hdr->page_size) >> 9)) {
386e3460df7SJason Zhu 			ret = -EIO;
387e3460df7SJason Zhu 			goto out;
388e3460df7SJason Zhu 		}
3892241fc0fSJason Zhu 	}
390e3460df7SJason Zhu 
3911cb393f1SJason Zhu 	spl_image->fdt_addr = (void *)CONFIG_SPL_FDT_ADDR;
3921cb393f1SJason Zhu #ifdef CONFIG_SPL_OPTEE
3931cb393f1SJason Zhu 	spl_image->entry_point_os = (uintptr_t)CONFIG_SPL_KERNEL_ADDR;
3941cb393f1SJason Zhu #endif
3951cb393f1SJason Zhu #ifdef CONFIG_SPL_ATF
3961cb393f1SJason Zhu 	spl_image->entry_point_bl33 = CONFIG_SPL_KERNEL_ADDR;
3971cb393f1SJason Zhu #endif
398e3460df7SJason Zhu 	ret = 0;
399e3460df7SJason Zhu out:
400e3460df7SJason Zhu 	free(hdr);
401e3460df7SJason Zhu 
402e3460df7SJason Zhu 	return ret;
403e3460df7SJason Zhu }
404e3460df7SJason Zhu 
40513c5d8ecSJoseph Chen int spl_load_rkfw_image(struct spl_image_info *spl_image,
40613c5d8ecSJoseph Chen 			struct spl_load_info *info,
407*aa415ed9SJoseph Chen 			u32 trust_sector, u32 uboot_sector,
408*aa415ed9SJoseph Chen 			u32 boot_sector)
40913c5d8ecSJoseph Chen {
41013c5d8ecSJoseph Chen 	int ret, try_count = RKFW_RETRY_SECTOR_TIMES;
41113c5d8ecSJoseph Chen 	int found_rkfw = 0;
41213c5d8ecSJoseph Chen 
4131cb393f1SJason Zhu 	ret = rkfw_load_trust(info, trust_sector, spl_image,
41413c5d8ecSJoseph Chen 			      &found_rkfw, try_count);
41513c5d8ecSJoseph Chen 	if (ret) {
41613c5d8ecSJoseph Chen 		printf("Load trust image failed! ret=%d\n", ret);
41713c5d8ecSJoseph Chen 		goto out;
41813c5d8ecSJoseph Chen 	}
419*aa415ed9SJoseph Chen #ifdef CONFIG_SPL_KERNEL_BOOT
420*aa415ed9SJoseph Chen 	if (spl_image->next_stage == SPL_NEXT_STAGE_UBOOT) {
421*aa415ed9SJoseph Chen #endif
422*aa415ed9SJoseph Chen 		ret = rkfw_load_uboot(info, uboot_sector, spl_image, try_count);
423e3460df7SJason Zhu 		if (ret)
42413c5d8ecSJoseph Chen 			printf("Load uboot image failed! ret=%d\n", ret);
425*aa415ed9SJoseph Chen #ifdef CONFIG_SPL_KERNEL_BOOT
426*aa415ed9SJoseph Chen 	} else if (spl_image->next_stage == SPL_NEXT_STAGE_KERNEL) {
427*aa415ed9SJoseph Chen #endif
428*aa415ed9SJoseph Chen 		ret = rkfw_load_kernel(info, boot_sector, spl_image, try_count);
429e3460df7SJason Zhu 		if (ret) {
430e3460df7SJason Zhu 			printf("Load kernel image failed! ret=%d\n", ret);
43113c5d8ecSJoseph Chen 			goto out;
43213c5d8ecSJoseph Chen 		}
433*aa415ed9SJoseph Chen #ifdef CONFIG_SPL_KERNEL_BOOT
434*aa415ed9SJoseph Chen 	}
435*aa415ed9SJoseph Chen #endif
43613c5d8ecSJoseph Chen 
43713c5d8ecSJoseph Chen #if CONFIG_IS_ENABLED(LOAD_FIT)
43813c5d8ecSJoseph Chen 	spl_image->fdt_addr = 0;
43913c5d8ecSJoseph Chen #endif
4401cb393f1SJason Zhu #ifdef CONFIG_SPL_ATF
44113c5d8ecSJoseph Chen 	spl_image->os = IH_OS_ARM_TRUSTED_FIRMWARE;
4421cb393f1SJason Zhu #else
4431cb393f1SJason Zhu 	spl_image->os = IH_OS_OP_TEE;
4441cb393f1SJason Zhu #endif
44513c5d8ecSJoseph Chen 
44613c5d8ecSJoseph Chen out:
44713c5d8ecSJoseph Chen 	/* If not found rockchip firmware, try others outside */
44813c5d8ecSJoseph Chen 	return found_rkfw ? ret : -EAGAIN;
44913c5d8ecSJoseph Chen }
450