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