xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/boot_rkimg.c (revision 514e00a960f8a815e0c86931b498063c6fc4ef76)
1 /*
2  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <adc.h>
9 #include <android_bootloader.h>
10 #include <android_image.h>
11 #include <bidram.h>
12 #include <bootm.h>
13 #include <boot_rkimg.h>
14 #include <cli.h>
15 #include <crypto.h>
16 #include <dm.h>
17 #include <fs.h>
18 #include <image.h>
19 #include <key.h>
20 #include <mmc.h>
21 #include <malloc.h>
22 #include <nvme.h>
23 #include <scsi.h>
24 #include <stdlib.h>
25 #include <sysmem.h>
26 #include <asm/io.h>
27 #include <asm/arch/boot_mode.h>
28 #include <asm/arch/fit.h>
29 #include <asm/arch/hotkey.h>
30 #include <asm/arch/param.h>
31 #include <asm/arch/resource_img.h>
32 #include <asm/arch/uimage.h>
33 #include <dm/ofnode.h>
34 #include <linux/list.h>
35 #include <u-boot/sha1.h>
36 #include <u-boot/sha256.h>
37 #include <linux/usb/phy-rockchip-usb2.h>
38 
39 DECLARE_GLOBAL_DATA_PTR;
40 
41 __weak int rk_board_early_fdt_fixup(void *blob)
42 {
43 	return 0;
44 }
45 
46 __weak int rk_board_scan_bootdev(void)
47 {
48 	const char *devtype_num_set = "run rkimg_bootdev";
49 
50 	return run_command_list(devtype_num_set, -1, 0);
51 }
52 
53 static int bootdev_init(const char *devtype, const char *devnum)
54 {
55 #ifdef CONFIG_MMC
56 	if (!strcmp("mmc", devtype))
57 		mmc_initialize(gd->bd);
58 #endif
59 #ifdef CONFIG_NVME
60 	if (!strcmp("nvme", devtype)) {
61 		pci_init();
62 		if (nvme_scan_namespace())
63 			return -ENODEV;
64 	}
65 #endif
66 #if defined(CONFIG_SCSI) && defined(CONFIG_CMD_SCSI) && defined(CONFIG_AHCI)
67 	if (!strcmp("scsi", devtype)) {
68 		if (scsi_scan(true))
69 			return -ENODEV;
70 	}
71 #endif
72 	/* Ok, let's test whether we can get the expected boot device or not */
73 	if (!blk_get_devnum_by_typename(devtype, atoi(devnum)))
74 		return -ENODEV;
75 
76 	env_set("devtype", devtype);
77 	env_set("devnum", devnum);
78 
79 	return 0;
80 }
81 
82 /*
83  * Priority: configuration > atags > scan list.
84  */
85 static void boot_devtype_init(void)
86 {
87 	char *devtype = NULL, *devnum = NULL;
88 	char *src = "scan";
89 	static int done;	/* static */
90 	int ret;
91 
92 	if (done)
93 		return;
94 
95 	/* configuration */
96 	if (!param_parse_assign_bootdev(&devtype, &devnum)) {
97 		if (!bootdev_init(devtype, devnum)) {
98 			src = "assign";
99 			goto finish;
100 		}
101 	}
102 
103 	/* atags */
104 #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
105 	if (!param_parse_atags_bootdev(&devtype, &devnum)) {
106 		if (!bootdev_init(devtype, devnum)) {
107 			src = "atags";
108 			goto finish;
109 		}
110 	}
111 #endif
112 
113 	/* scan list */
114 #ifdef CONFIG_MMC
115 	mmc_initialize(gd->bd);
116 #endif
117 	ret = rk_board_scan_bootdev();
118 	if (ret) {
119 		/* Set default if all failed */
120 		devtype = "mmc";
121 		devnum = "0";
122 		env_set("devtype", devtype);
123 		env_set("devnum", devnum);
124 	}
125 finish:
126 	done = 1;
127 	printf("Bootdev(%s): %s %s\n", src,
128 	       env_get("devtype"), env_get("devnum"));
129 }
130 
131 static int get_bootdev_type(void)
132 {
133 	char *boot_media = NULL, *devtype = NULL;
134 	char boot_options[128] = {0};
135 	static int appended;
136 	ulong devnum = 0;
137 	int type = 0;
138 
139 	devtype = env_get("devtype");
140 	devnum = env_get_ulong("devnum", 10, 0);
141 
142 	/* For current use(Only EMMC support!) */
143 	if (!devtype) {
144 		devtype = "mmc";
145 		printf("Use emmc as default boot media\n");
146 	}
147 
148 	if (!strcmp(devtype, "mmc")) {
149 		type = IF_TYPE_MMC;
150 		if (devnum == 1)
151 			boot_media = "sd";
152 		else
153 			boot_media = "emmc";
154 	} else if (!strcmp(devtype, "rknand")) {
155 		type = IF_TYPE_RKNAND;
156 		boot_media = "nand";
157 	} else if (!strcmp(devtype, "spinand")) {
158 		type = IF_TYPE_SPINAND;
159 		boot_media = "nand"; /* kernel treat sfc nand as nand device */
160 	} else if (!strcmp(devtype, "spinor")) {
161 		type = IF_TYPE_SPINOR;
162 		boot_media = "nor";
163 	} else if (!strcmp(devtype, "ramdisk")) {
164 		type = IF_TYPE_RAMDISK;
165 		boot_media = "ramdisk";
166 	} else if (!strcmp(devtype, "mtd")) {
167 		type = IF_TYPE_MTD;
168 		boot_media = "mtd";
169 	} else if (!strcmp(devtype, "scsi")) {
170 		type = IF_TYPE_SCSI;
171 		boot_media = "scsi";
172 	} else if (!strcmp(devtype, "nvme")) {
173 		type = IF_TYPE_NVME;
174 		boot_media = "nvme";
175 	} else {
176 		/* Add new to support */
177 	}
178 
179 	if (!appended && boot_media) {
180 		appended = 1;
181 
182 	/*
183 	 * The legacy rockchip Android (SDK < 8.1) requires "androidboot.mode="
184 	 * to be "charger" or boot media which is a rockchip private solution.
185 	 *
186 	 * The official Android rule (SDK >= 8.1) is:
187 	 * "androidboot.mode=normal" or "androidboot.mode=charger".
188 	 *
189 	 * Now that this U-Boot is usually working with higher version
190 	 * Android (SDK >= 8.1), we follow the official rules.
191 	 *
192 	 * Common: androidboot.mode=charger has higher priority, don't override;
193 	 */
194 #ifdef CONFIG_RKIMG_ANDROID_BOOTMODE_LEGACY
195 		/* rknand doesn't need "androidboot.mode="; */
196 		if (env_exist("bootargs", "androidboot.mode=charger") ||
197 		    (type == IF_TYPE_RKNAND) ||
198 		    (type == IF_TYPE_SPINAND) ||
199 		    (type == IF_TYPE_SPINOR))
200 			snprintf(boot_options, sizeof(boot_options),
201 				 "storagemedia=%s", boot_media);
202 		else
203 			snprintf(boot_options, sizeof(boot_options),
204 				 "storagemedia=%s androidboot.mode=%s",
205 				 boot_media, boot_media);
206 #else
207 		/*
208 		 * 1. "storagemedia": This is a legacy variable to indicate board
209 		 *    storage media for kernel and android.
210 		 *
211 		 * 2. "androidboot.storagemedia": The same purpose as "storagemedia",
212 		 *    but the android framework will auto create property by
213 		 *    variable with format "androidboot.xxx", eg:
214 		 *
215 		 *    "androidboot.storagemedia" => "ro.boot.storagemedia".
216 		 *
217 		 *    So, U-Boot pass this new variable is only for the convenience
218 		 *    to Android.
219 		 */
220 		if (env_exist("bootargs", "androidboot.mode=charger"))
221 			snprintf(boot_options, sizeof(boot_options),
222 				 "storagemedia=%s androidboot.storagemedia=%s",
223 				 boot_media, boot_media);
224 		else
225 			snprintf(boot_options, sizeof(boot_options),
226 				 "storagemedia=%s androidboot.storagemedia=%s "
227 				 "androidboot.mode=normal ",
228 				 boot_media, boot_media);
229 #endif
230 		env_update("bootargs", boot_options);
231 	}
232 
233 	return type;
234 }
235 
236 static struct blk_desc *dev_desc;
237 
238 struct blk_desc *rockchip_get_bootdev(void)
239 {
240 	int dev_type;
241 	int devnum;
242 
243 	if (dev_desc)
244 		return dev_desc;
245 
246 	boot_devtype_init();
247 	dev_type = get_bootdev_type();
248 	devnum = env_get_ulong("devnum", 10, 0);
249 
250 	dev_desc = blk_get_devnum_by_type(dev_type, devnum);
251 	if (!dev_desc) {
252 		printf("%s: Can't find dev_desc!\n", __func__);
253 		return NULL;
254 	}
255 
256 #ifdef CONFIG_MMC
257 	if (dev_type == IF_TYPE_MMC) {
258 		struct mmc *mmc;
259 		const char *timing[] = {
260 			"Legacy", "High Speed", "High Speed", "SDR12",
261 			"SDR25", "SDR50", "SDR104", "DDR50",
262 			"DDR52", "HS200", "HS400", "HS400 Enhanced Strobe"};
263 
264 		mmc = find_mmc_device(devnum);
265 		printf("MMC%d: %s, %dMhz\n", devnum,
266 		       timing[mmc->timing], mmc->clock / 1000000);
267 	}
268 #endif
269 
270 	printf("PartType: %s\n", part_get_type(dev_desc));
271 
272 	return dev_desc;
273 }
274 
275 void rockchip_set_bootdev(struct blk_desc *desc)
276 {
277 	dev_desc = desc;
278 }
279 
280 /*
281  * detect download key status by adc, most rockchip
282  * based boards use adc sample the download key status,
283  * but there are also some use gpio. So it's better to
284  * make this a weak function that can be override by
285  * some special boards.
286  */
287 #define KEY_DOWN_MIN_VAL	0
288 #define KEY_DOWN_MAX_VAL	30
289 
290 __weak int rockchip_dnl_key_pressed(void)
291 {
292 #if defined(CONFIG_DM_KEY)
293 	return key_is_pressed(key_read(KEY_VOLUMEUP));
294 
295 #elif defined(CONFIG_ADC)
296 	const void *blob = gd->fdt_blob;
297 	int node, ret, channel = 1;
298 	u32 val, chns[2];
299 
300 	node = fdt_node_offset_by_compatible(blob, 0, "adc-keys");
301 	if (node >= 0) {
302 		if (!fdtdec_get_int_array(blob, node, "io-channels", chns, 2))
303 			channel = chns[1];
304 	}
305 
306 	ret = adc_channel_single_shot("saradc", channel, &val);
307 	if (ret) {
308 		printf("%s: Failed to read saradc, ret=%d\n", __func__, ret);
309 		return 0;
310 	}
311 
312 	return ((val >= KEY_DOWN_MIN_VAL) && (val <= KEY_DOWN_MAX_VAL));
313 #endif
314 
315 	return 0;
316 }
317 
318 void setup_download_mode(void)
319 {
320 	int vbus = 1; /* Assumed 1 in case of no rockusb */
321 
322 	boot_devtype_init();
323 
324 	if (rockchip_dnl_key_pressed() || is_hotkey(HK_ROCKUSB_DNL)) {
325 		printf("download %skey pressed... ",
326 		       is_hotkey(HK_ROCKUSB_DNL) ? "hot" : "");
327 #ifdef CONFIG_CMD_ROCKUSB
328 		vbus = rockchip_u2phy_vbus_detect();
329 #endif
330 		if (vbus > 0) {
331 			printf("%sentering download mode...\n",
332 			       IS_ENABLED(CONFIG_CMD_ROCKUSB) ?
333 			       "" : "no rockusb, ");
334 
335 			/* try rockusb download and brom download */
336 			run_command("download", 0);
337 		} else {
338 			printf("entering recovery mode!\n");
339 			env_set("reboot_mode", "recovery-key");
340 		}
341 	} else if (is_hotkey(HK_FASTBOOT)) {
342 		env_set("reboot_mode", "fastboot");
343 	}
344 }
345 
346 void board_run_recovery_wipe_data(void)
347 {
348 	struct bootloader_message bmsg;
349 	struct blk_desc *dev_desc;
350 	disk_partition_t part_info;
351 #ifdef CONFIG_ANDROID_BOOT_IMAGE
352 	u32 bcb_offset = android_bcb_msg_sector_offset();
353 #else
354 	u32 bcb_offset = BCB_MESSAGE_BLK_OFFSET;
355 #endif
356 	int cnt, ret;
357 
358 	printf("Rebooting into recovery to do wipe_data\n");
359 	dev_desc = rockchip_get_bootdev();
360 	if (!dev_desc) {
361 		printf("%s: dev_desc is NULL!\n", __func__);
362 		return;
363 	}
364 
365 	ret = part_get_info_by_name(dev_desc, PART_MISC, &part_info);
366 	if (ret < 0) {
367 		printf("%s: Could not found misc partition, just run recovery\n",
368 		       __func__);
369 		goto out;
370 	}
371 
372 	memset((char *)&bmsg, 0, sizeof(struct bootloader_message));
373 	strcpy(bmsg.command, "boot-recovery");
374 	strcpy(bmsg.recovery, "recovery\n--wipe_data");
375 	bmsg.status[0] = 0;
376 	cnt = DIV_ROUND_UP(sizeof(struct bootloader_message), dev_desc->blksz);
377 	ret = blk_dwrite(dev_desc, part_info.start + bcb_offset, cnt, &bmsg);
378 	if (ret != cnt)
379 		printf("Wipe data failed, ret=%d\n", ret);
380 out:
381 	/* now reboot to recovery */
382 	env_set("reboot_mode", "recovery");
383 	run_command("run bootcmd", 0);
384 }
385 
386 #if defined(CONFIG_USING_KERNEL_DTB) || defined(CONFIG_CMD_BOOTM) || \
387     defined(CONFIG_CMD_BOOTZ) || defined(CONFIG_CMD_BOOTI)
388 #ifdef CONFIG_ROCKCHIP_DTB_VERIFY
389 #ifdef CONFIG_DM_CRYPTO
390 static int crypto_csum(u32 cap, char *input, u32 input_len, u8 *output)
391 {
392 	sha_context csha_ctx;
393 	struct udevice *dev;
394 
395 	dev = crypto_get_device(cap);
396 	if (!dev) {
397 		printf("Can't find expected crypto device\n");
398 		return -ENODEV;
399 	}
400 
401 	csha_ctx.algo = cap;
402 	csha_ctx.length = input_len;
403 	crypto_sha_csum(dev, &csha_ctx, (char *)input,
404 			input_len, output);
405 
406 	return 0;
407 }
408 
409 static int fdt_check_hash(void *fdt_addr, u32 fdt_size,
410 			  char *hash_cmp, u32 hash_size)
411 {
412 	uchar hash[32];
413 
414 	if (!hash_size)
415 		return 0;
416 
417 	if (hash_size == 20)
418 		crypto_csum(CRYPTO_SHA1, fdt_addr, fdt_size, hash);
419 	else if (hash_size == 32)
420 		crypto_csum(CRYPTO_SHA256, fdt_addr, fdt_size, hash);
421 	else
422 		return -EINVAL;
423 
424 	printf("HASH(c): ");
425 	if (memcmp(hash, hash_cmp, hash_size)) {
426 		printf("error\n");
427 		return -EBADF;
428 	}
429 
430 	printf("OK\n");
431 
432 	return 0;
433 }
434 
435 #else
436 static int fdt_check_hash(void *fdt_addr, u32 fdt_size,
437 			  char *hash_cmp, u32 hash_size)
438 {
439 	uchar hash[32];
440 
441 	if (!hash_size)
442 		return 0;
443 
444 	if (hash_size == 20)
445 		sha1_csum((const uchar *)fdt_addr, fdt_size, hash);
446 	else if (hash_size == 32)
447 		sha256_csum((const uchar *)fdt_addr, fdt_size, hash);
448 	else
449 		return -EINVAL;
450 
451 	printf("HASH(s): ");
452 	if (memcmp(hash, hash_cmp, hash_size)) {
453 		printf("error\n");
454 		return -EBADF;
455 	}
456 
457 	printf("OK\n");
458 
459 	return 0;
460 }
461 #endif
462 #endif	/* CONFIG_ROCKCHIP_DTB_VERIFY */
463 
464 #if defined(CONFIG_ROCKCHIP_EARLY_DISTRO_DTB)
465 static int rockchip_read_distro_dtb(void *fdt_addr)
466 {
467 	const char *cmd = "part list ${devtype} ${devnum} -bootable devplist";
468 	char *devnum, *devtype, *devplist;
469 	char devnum_part[12];
470 	char fdt_hex_str[19];
471 	char *fs_argv[5];
472 
473 	if (!rockchip_get_bootdev() || !fdt_addr)
474 		return -ENODEV;
475 
476 	if (run_command_list(cmd, -1, 0)) {
477 		printf("Failed to find -bootable\n");
478 		return -EINVAL;
479 	}
480 
481 	devplist = env_get("devplist");
482 	if (!devplist)
483 		devplist = "1";
484 
485 	devtype = env_get("devtype");
486 	devnum = env_get("devnum");
487 	sprintf(devnum_part, "%s:%s", devnum, devplist);
488 	sprintf(fdt_hex_str, "0x%lx", (ulong)fdt_addr);
489 
490 	fs_argv[0] = "load";
491 	fs_argv[1] = devtype,
492 	fs_argv[2] = devnum_part;
493 	fs_argv[3] = fdt_hex_str;
494 	fs_argv[4] = CONFIG_ROCKCHIP_EARLY_DISTRO_DTB_PATH;
495 
496 	if (do_load(NULL, 0, 5, fs_argv, FS_TYPE_ANY))
497 		return -EIO;
498 
499 	if (fdt_check_header(fdt_addr))
500 		return -EBADF;
501 
502 	printf("DTB(Distro): %s\n", CONFIG_ROCKCHIP_EARLY_DISTRO_DTB_PATH);
503 
504 	return 0;
505 }
506 #endif
507 
508 enum {
509 	LOCATE_DISTRO,
510 	LOCATE_RESOURCE,
511 	LOCATE_FIT,
512 	LOCATE_END,
513 };
514 
515 static int rkimg_traverse_read_dtb(void *fdt, int where)
516 {
517 	if (where == LOCATE_DISTRO) {
518 #ifdef CONFIG_ROCKCHIP_EARLY_DISTRO_DTB
519 		return rockchip_read_distro_dtb(fdt);
520 #endif
521 	} else if (where == LOCATE_RESOURCE) {
522 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
523 		int hash_size = 0;
524 		char *hash;
525 		u32 ret;
526 
527 		ret = rockchip_read_resource_dtb(fdt, &hash, &hash_size);
528 		if (ret) {
529 			printf("Failed to load DTB, ret=%d\n", ret);
530 			return ret;
531 		}
532 
533 		if (fdt_check_header(fdt)) {
534 			printf("Invalid DTB magic !\n");
535 			return -EBADF;
536 		}
537 #ifdef CONFIG_ROCKCHIP_DTB_VERIFY
538 		if (hash_size && fdt_check_hash(fdt,
539 			fdt_totalsize(fdt), hash, hash_size)) {
540 			printf("Invalid DTB hash !\n");
541 			return -EBADF;
542 		}
543 #endif
544 		return 0;
545 #endif
546 	} else if (where == LOCATE_FIT) {
547 #if defined(CONFIG_ROCKCHIP_FIT_IMAGE) && !defined(CONFIG_ROCKCHIP_RESOURCE_IMAGE)
548 		return fit_image_read_dtb(fdt);
549 #endif
550 	}
551 
552 	return -EINVAL;
553 }
554 
555 int rockchip_read_dtb_file(void *fdt)
556 {
557 	int locate, ret;
558 	int size;
559 
560 	/* init resource list */
561 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
562 	resource_traverse_init_list();
563 #endif
564 
565 	/* traverse location */
566 	for (locate = 0; locate < LOCATE_END; locate++) {
567 		ret = rkimg_traverse_read_dtb(fdt, locate);
568 		if (!ret)
569 			break;
570 	}
571 	if (ret) {
572 		printf("No find valid DTB, ret=%d\n", ret);
573 		return ret;
574 	}
575 
576 	/* reserved memory */
577 	size = fdt_totalsize(fdt);
578 	if (!sysmem_alloc_base(MEM_FDT, (phys_addr_t)fdt,
579 		ALIGN(size, RK_BLK_SIZE) + CONFIG_SYS_FDT_PAD))
580 		return -ENOMEM;
581 
582 	/* fixup/overlay */
583 	rk_board_early_fdt_fixup(fdt);
584 #if defined(CONFIG_ANDROID_BOOT_IMAGE) && defined(CONFIG_OF_LIBFDT_OVERLAY)
585 	android_fdt_overlay_apply((void *)fdt);
586 #endif
587 
588 	return 0;
589 }
590 #endif
591 
592 int rockchip_ram_read_dtb_file(void *img, void *fdt)
593 {
594 	int format;
595 	int ret;
596 
597 	format = (genimg_get_format(img));
598 #ifdef CONFIG_ANDROID_BOOT_IMAGE
599 	if (format == IMAGE_FORMAT_ANDROID) {
600 		struct andr_img_hdr *hdr = img;
601 		struct blk_desc *dev_desc;
602 		ulong offset;
603 
604 		dev_desc = rockchip_get_bootdev();
605 		if (!dev_desc)
606 			return -ENODEV;
607 
608 		offset = hdr->page_size + ALIGN(hdr->kernel_size, hdr->page_size) +
609 			ALIGN(hdr->ramdisk_size, hdr->page_size);
610 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
611 		ret = resource_create_ram_list(dev_desc, (void *)hdr + offset);
612 		if (ret)
613 			return ret;
614 
615 		return rockchip_read_dtb_file((void *)fdt);
616 #else
617 		if (fdt_check_header((void *)offset))
618 			return -EINVAL;
619 
620 		memcpy(fdt, (char *)offset, fdt_totalsize(offset));
621 		if (!sysmem_alloc_base(MEM_FDT, (phys_addr_t)fdt,
622 			ALIGN(fdt_totalsize(fdt), RK_BLK_SIZE) + CONFIG_SYS_FDT_PAD))
623 			return -ENOMEM;
624 
625 		return 0;
626 #endif
627 	}
628 #endif
629 #if IMAGE_ENABLE_FIT
630 	if (format == IMAGE_FORMAT_FIT) {
631 		const void *data;
632 		size_t size;
633 		int noffset;
634 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
635 		const char *path = "/images/resource";
636 #else
637 		const char *path = "/images/fdt";
638 #endif
639 
640 		noffset = fdt_path_offset(img, path);
641 		if (noffset < 0)
642 			return noffset;
643 
644 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
645 		ret = fit_image_get_data(img, noffset, &data, &size);
646 		if (ret < 0)
647 			return ret;
648 
649 		dev_desc = rockchip_get_bootdev();
650 		if (!dev_desc)
651 			return -ENODEV;
652 
653 		ret = resource_create_ram_list(dev_desc, (void *)data);
654 		if (ret) {
655 			printf("resource_create_ram_list fail, ret=%d\n", ret);
656 			return ret;
657 		}
658 
659 		return rockchip_read_dtb_file((void *)fdt);
660 #else
661 
662 		ret = fit_image_get_data(img, noffset, &data, &size);
663 		if (ret)
664 			return ret;
665 
666 		if (fdt_check_header(data))
667 			return -EINVAL;
668 
669 		memcpy(fdt, data, size);
670 		if (!sysmem_alloc_base(MEM_FDT, (phys_addr_t)fdt,
671 			ALIGN(fdt_totalsize(fdt), RK_BLK_SIZE) + CONFIG_SYS_FDT_PAD))
672 			return -ENOMEM;
673 
674 		printf("Load DTB from 'images/fdt'\n");
675 
676 		return 0;
677 #endif
678 	}
679 #endif
680 
681 	return -EINVAL;
682 }
683