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