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