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