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