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