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