xref: /rk3399_rockchip-uboot/common/spl/spl_rkfw.c (revision 73b4df6a98d2d973cbf1e2b18947abbdbdb82bc1)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4  */
5 
6 #include <common.h>
7 #include <malloc.h>
8 #include <spl_rkfw.h>
9 
10 static const __aligned(16) struct s_fip_name_id fip_name_id[] = {
11 	{ BL30_IMAGE_NAME, UUID_SCP_FIRMWARE_BL30 },		/* optional */
12 	{ BL31_IMAGE_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31 },	/* mandatory */
13 	{ BL32_IMAGE_NAME, UUID_SECURE_PAYLOAD_BL32 },		/* optional */
14 };
15 
16 static int file2comp_id(const char *file_name, u32 *comp_id)
17 {
18 	int i;
19 
20 	for (i = 0; i < ARRAY_SIZE(fip_name_id); i++) {
21 		if (!strcmp(file_name, fip_name_id[i].name)) {
22 			*comp_id = fip_name_id[i].id;
23 			return 0;
24 		}
25 	}
26 
27 	return -ENOENT;
28 }
29 
30 static int open_image(const char *image_name, tboot_entry *entry,
31 		      struct tag_tboot_header_2k *hdr)
32 {
33 	u32 i, component_num, sign_offset;
34 	component_data *pcompdata;
35 	boot_component *pcomp;
36 	int n_found = 0;
37 	u32 comp_id;
38 	int ret;
39 
40 	ret = file2comp_id(image_name, &comp_id);
41 	if (ret) {
42 		printf("Can't find unknown image: %s\n", image_name);
43 		return ret;
44 	}
45 
46 	component_num = (hdr->size >> 16) & 0xffff;
47 	sign_offset = (hdr->size & 0xffff) << 2;
48 	pcompdata = (component_data *)((char *)hdr + sizeof(tboot_header));
49 	pcomp = (boot_component *)((char *)hdr + sign_offset + SIGNATURE_SIZE);
50 
51 	for (i = 0; i < component_num; i++) {
52 		if (comp_id == pcomp->component_id) {
53 			if (n_found < MAX_BL_CODE_NUM) {
54 				memcpy(&entry[n_found].component, pcomp,
55 				       sizeof(boot_component));
56 				memcpy(&entry[n_found].compdata, pcompdata,
57 				       sizeof(component_data));
58 				n_found++;
59 			} else {
60 				printf("Image num excess max: %d!\n",
61 				       MAX_BL_CODE_NUM);
62 				return -EINVAL;
63 			}
64 		} else {
65 			if (n_found > 0)
66 				break;
67 		}
68 
69 		pcomp++;
70 		pcompdata++;
71 	}
72 
73 	if (!n_found) {
74 		printf("No find %s\n", image_name);
75 		return -ENONET;
76 	}
77 
78 	return n_found;
79 }
80 
81 static int check_image(struct tag_tboot_header_2k *hdr)
82 {
83 	u32 hash_format[] = { 0, 160, 256, 256 };
84 
85 	/* HASH format identifier */
86 	return (hash_format[hdr->flags & 0x3] == 0) ? -EINVAL : 0;
87 }
88 
89 static int load_image(struct spl_load_info *info,
90 		      struct tag_tboot_header_2k *hdr,
91 		      u32 image_sector,
92 		      const char *image_name,
93 		      uintptr_t *entry_point)
94 {
95 	tboot_entry entry[MAX_BL_CODE_NUM];
96 	void *image_buf = NULL;
97 	ulong load_addr;
98 	u32 sect_off;
99 	u32 sect_cnt;
100 	int image_num;
101 	int i, ret;
102 
103 	/* Parse components from image header */
104 	image_num = open_image(image_name, entry, hdr);
105 	if (image_num < 0)
106 		return image_num;
107 
108 	/* Get all component */
109 	for (i = 0; i < image_num; i++) {
110 		load_addr = entry[i].compdata.load_addr;
111 		sect_cnt = entry[i].component.image_size;
112 		sect_off = entry[i].component.storage_addr;
113 
114 		printf("%s[%d]: addr=0x%lx, size=0x%lx\n",
115 		       image_name, i, load_addr, (ulong)sect_cnt * 512);
116 
117 		/*
118 		 * MMC/NAND controller DMA can't access sram region, so:
119 		 * data -> ddr buffer -> memcpy to sram region.
120 		 */
121 		if (load_addr < CONFIG_SYS_SDRAM_BASE ||
122 		    load_addr >= CONFIG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE) {
123 			image_buf = memalign(ARCH_DMA_MINALIGN, sect_cnt * 512);
124 			if (!image_buf) {
125 				printf("%s: malloc failed\n", __func__);
126 				return -ENOMEM;
127 			}
128 		} else {
129 			image_buf = (void *)load_addr;
130 		}
131 
132 		ret = info->read(info, image_sector + sect_off,
133 				 sect_cnt, image_buf);
134 		if (ret != sect_cnt) {
135 			printf("Read '%s' failed at sector: %ld, ret=%d\n",
136 			       image_name, (ulong)image_sector + sect_off, ret);
137 			return -EIO;
138 		}
139 
140 		/* Verify component */
141 		ret = check_image(hdr);
142 		if (ret) {
143 			printf("%s[%d]: verify image fail!\n", image_name, i);
144 			return ret;
145 		}
146 
147 		/* Handle sram region */
148 		if ((ulong)image_buf != load_addr) {
149 			memcpy((void *)load_addr, image_buf, sect_cnt << 9);
150 			free(image_buf);
151 		}
152 
153 		/* Fill entry_point by first component */
154 		if (i == 0)
155 			*entry_point = (uintptr_t)load_addr;
156 	}
157 
158 	return ret;
159 }
160 
161 static int rkfw_load_trust(struct spl_load_info *info, u32 image_sector,
162 			   uintptr_t *bl31_entry, uintptr_t *bl32_entry,
163 			   int *found_rkfw, u32 try_count)
164 {
165 	struct tag_tboot_header_2k hdr;
166 	u32 sect_addr = image_sector;
167 	int blkcnt = 4;	/* header sectors, 2KB */
168 	int i, ret = 0;
169 
170 	/* Find valid image header */
171 	for (i = 0; i < try_count; i++) {
172 		sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE);
173 		if (blkcnt != info->read(info, sect_addr, blkcnt, &hdr))
174 			continue;
175 
176 		if (hdr.tag == TBOOT_HEAD_TAG) {
177 			/* Mark it */
178 			*found_rkfw = 1;
179 
180 			/* bl31 is mandatory */
181 			ret = load_image(info, &hdr, sect_addr,
182 					 BL31_IMAGE_NAME, bl31_entry);
183 			if (ret)
184 				continue;
185 
186 			/* bl32 is optional */
187 			ret = load_image(info, &hdr, sect_addr,
188 					 BL32_IMAGE_NAME, bl32_entry);
189 			if (ret) {
190 				if (ret == -ENONET) {
191 					*bl32_entry = -1;	/* Not exist */
192 					ret = 0;
193 				} else {
194 					continue;
195 				}
196 			}
197 			break;
198 		}
199 	}
200 
201 	return ret;
202 }
203 
204 static int rkfw_load_uboot(struct spl_load_info *info, u32 image_sector,
205 			   uintptr_t *bl33_entry, u32 try_count)
206 {
207 	struct tag_second_loader_hdr hdr;
208 	int i, ret, blkcnt = 4;	/* header sectors, 2KB */
209 	char *load_addr;
210 	u32 sect_addr;
211 
212 	/* Detect valid image header */
213 	for (i = 0; i < try_count; i++) {
214 		sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE);
215 		ret = info->read(info, sect_addr, blkcnt, &hdr);
216 		if (ret != blkcnt)
217 			continue;
218 
219 		if (!memcmp(hdr.magic, LOADER_HARD_STR, 6)) {
220 			/* Load full binary image(right behind header) */
221 			sect_addr += blkcnt;
222 			load_addr = (char *)((size_t)hdr.loader_load_addr);
223 			blkcnt = DIV_ROUND_UP(hdr.loader_load_size, 512);
224 
225 			printf("u-boot.bin: addr=0x%lx, size=0x%lx\n",
226 			       (ulong)load_addr, (ulong)blkcnt * 512);
227 			ret = info->read(info, sect_addr, blkcnt, load_addr);
228 			if (ret != blkcnt)
229 				continue;
230 
231 			break;
232 		}
233 	}
234 
235 	if (i == try_count) {
236 		printf("Can not find usable uboot\n");
237 		return -ENONET;
238 	}
239 
240 	/* Fill entry point */
241 	*bl33_entry = (uintptr_t)hdr.loader_load_addr;
242 
243 	return 0;
244 }
245 
246 int spl_load_rkfw_image(struct spl_image_info *spl_image,
247 			struct spl_load_info *info,
248 			u32 trust_sector, u32 uboot_sector)
249 {
250 	int ret, try_count = RKFW_RETRY_SECTOR_TIMES;
251 	int found_rkfw = 0;
252 
253 	ret = rkfw_load_trust(info, trust_sector,
254 			      &spl_image->entry_point,
255 			      &spl_image->entry_point_bl32,
256 			      &found_rkfw, try_count);
257 	if (ret) {
258 		printf("Load trust image failed! ret=%d\n", ret);
259 		goto out;
260 	}
261 
262 	ret = rkfw_load_uboot(info, uboot_sector,
263 			      &spl_image->entry_point_bl33, try_count);
264 	if (ret) {
265 		printf("Load uboot image failed! ret=%d\n", ret);
266 		goto out;
267 	}
268 
269 #if CONFIG_IS_ENABLED(LOAD_FIT)
270 	spl_image->fdt_addr = 0;
271 #endif
272 	spl_image->os = IH_OS_ARM_TRUSTED_FIRMWARE;
273 
274 out:
275 	/* If not found rockchip firmware, try others outside */
276 	return found_rkfw ? ret : -EAGAIN;
277 }
278