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) || defined(CONFIG_UFS))
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 ret = adc_channel_single_shot("adc", channel, &val);
318 if (ret) {
319 printf("%s: Failed to read saradc, ret=%d\n", __func__, ret);
320 return 0;
321 }
322
323 return ((val >= KEY_DOWN_MIN_VAL) && (val <= KEY_DOWN_MAX_VAL));
324 #endif
325
326 return 0;
327 }
328
setup_download_mode(void)329 void setup_download_mode(void)
330 {
331 int vbus = 1; /* Assumed 1 in case of no rockusb */
332
333 boot_devtype_init();
334
335 if (rockchip_dnl_key_pressed() || is_hotkey(HK_ROCKUSB_DNL)) {
336 printf("download %skey pressed... ",
337 is_hotkey(HK_ROCKUSB_DNL) ? "hot" : "");
338 #ifdef CONFIG_CMD_ROCKUSB
339 vbus = rockchip_u2phy_vbus_detect();
340 #endif
341 if (vbus > 0) {
342 printf("%sentering download mode...\n",
343 IS_ENABLED(CONFIG_CMD_ROCKUSB) ?
344 "" : "no rockusb, ");
345
346 /* try rockusb download and brom download */
347 run_command("download", 0);
348 } else {
349 printf("entering recovery mode!\n");
350 env_set("reboot_mode", "recovery-key");
351 }
352 } else if (is_hotkey(HK_FASTBOOT)) {
353 env_set("reboot_mode", "fastboot");
354 }
355 }
356
board_run_recovery_wipe_data(void)357 void board_run_recovery_wipe_data(void)
358 {
359 struct bootloader_message bmsg;
360 struct blk_desc *dev_desc;
361 disk_partition_t part_info;
362 #ifdef CONFIG_ANDROID_BOOT_IMAGE
363 u32 bcb_offset = android_bcb_msg_sector_offset();
364 #else
365 u32 bcb_offset = BCB_MESSAGE_BLK_OFFSET;
366 #endif
367 int cnt, ret;
368
369 printf("Rebooting into recovery to do wipe_data\n");
370 dev_desc = rockchip_get_bootdev();
371 if (!dev_desc) {
372 printf("%s: dev_desc is NULL!\n", __func__);
373 return;
374 }
375
376 ret = part_get_info_by_name(dev_desc, PART_MISC, &part_info);
377 if (ret < 0) {
378 printf("%s: Could not found misc partition, just run recovery\n",
379 __func__);
380 goto out;
381 }
382
383 memset((char *)&bmsg, 0, sizeof(struct bootloader_message));
384 strcpy(bmsg.command, "boot-recovery");
385 strcpy(bmsg.recovery, "recovery\n--wipe_data");
386 bmsg.status[0] = 0;
387 cnt = DIV_ROUND_UP(sizeof(struct bootloader_message), dev_desc->blksz);
388 ret = blk_dwrite(dev_desc, part_info.start + bcb_offset, cnt, &bmsg);
389 if (ret != cnt)
390 printf("Wipe data failed, ret=%d\n", ret);
391 out:
392 /* now reboot to recovery */
393 env_set("reboot_mode", "recovery");
394 run_command("run bootcmd", 0);
395 }
396
397 #if defined(CONFIG_USING_KERNEL_DTB) || defined(CONFIG_CMD_BOOTM) || \
398 defined(CONFIG_CMD_BOOTZ) || defined(CONFIG_CMD_BOOTI)
399 #ifdef CONFIG_ROCKCHIP_DTB_VERIFY
fdt_check_hash(void * fdt_addr,u32 fdt_size,char * hash_cmp,u32 hash_size)400 static int fdt_check_hash(void *fdt_addr, u32 fdt_size,
401 char *hash_cmp, u32 hash_size)
402 {
403 uchar hash[32];
404 #ifdef CONFIG_ARMV8_CRYPTO
405 char *engine = "ce";
406 #elif defined(CONFIG_DM_CRYPTO)
407 char *engine = "c";
408 #else
409 char *engine = "s";
410 #endif
411
412 if (!hash_size)
413 return 0;
414
415 if (hash_size == 20)
416 sha1_csum((const uchar *)fdt_addr, fdt_size, hash);
417 else if (hash_size == 32)
418 sha256_csum((const uchar *)fdt_addr, fdt_size, hash);
419 else
420 return -EINVAL;
421
422 printf("HASH(%s): ", engine);
423 if (memcmp(hash, hash_cmp, hash_size)) {
424 printf("error\n");
425 return -EBADF;
426 }
427
428 printf("OK\n");
429
430 return 0;
431 }
432 #endif /* CONFIG_ROCKCHIP_DTB_VERIFY */
433
434 #if defined(CONFIG_ROCKCHIP_EARLY_DISTRO_DTB)
rockchip_read_distro_dtb(void * fdt_addr)435 static int rockchip_read_distro_dtb(void *fdt_addr)
436 {
437 const char *cmd = "part list ${devtype} ${devnum} -bootable devplist";
438 char *devnum, *devtype, *devplist;
439 char devnum_part[12];
440 char fdt_hex_str[19];
441 char *fs_argv[5];
442
443 if (!rockchip_get_bootdev() || !fdt_addr)
444 return -ENODEV;
445
446 if (run_command_list(cmd, -1, 0)) {
447 printf("Failed to find -bootable\n");
448 return -EINVAL;
449 }
450
451 devplist = env_get("devplist");
452 if (!devplist)
453 devplist = "1";
454
455 devtype = env_get("devtype");
456 devnum = env_get("devnum");
457 sprintf(devnum_part, "%s:%s", devnum, devplist);
458 sprintf(fdt_hex_str, "0x%lx", (ulong)fdt_addr);
459
460 fs_argv[0] = "load";
461 fs_argv[1] = devtype,
462 fs_argv[2] = devnum_part;
463 fs_argv[3] = fdt_hex_str;
464 fs_argv[4] = CONFIG_ROCKCHIP_EARLY_DISTRO_DTB_PATH;
465
466 if (do_load(NULL, 0, 5, fs_argv, FS_TYPE_ANY))
467 return -EIO;
468
469 if (fdt_check_header(fdt_addr))
470 return -EBADF;
471
472 printf("DTB(Distro): %s\n", CONFIG_ROCKCHIP_EARLY_DISTRO_DTB_PATH);
473
474 return 0;
475 }
476 #endif
477
478 enum {
479 LOCATE_DISTRO,
480 LOCATE_RESOURCE,
481 LOCATE_FIT,
482 LOCATE_END,
483 };
484
dtb_scan(void * fdt,int where)485 static int dtb_scan(void *fdt, int where)
486 {
487 if (where == LOCATE_DISTRO) {
488 #ifdef CONFIG_ROCKCHIP_EARLY_DISTRO_DTB
489 return rockchip_read_distro_dtb(fdt);
490 #endif
491 } else if (where == LOCATE_RESOURCE) {
492 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
493 int hash_size = 0;
494 char *hash;
495 u32 ret;
496
497 ret = rockchip_read_resource_dtb(fdt, &hash, &hash_size);
498 if (ret) {
499 printf("Failed to load DTB, ret=%d\n", ret);
500 return ret;
501 }
502
503 if (fdt_check_header(fdt)) {
504 printf("Invalid DTB magic !\n");
505 return -EBADF;
506 }
507 #ifdef CONFIG_ROCKCHIP_DTB_VERIFY
508 if (hash_size && fdt_check_hash(fdt,
509 fdt_totalsize(fdt), hash, hash_size)) {
510 printf("Invalid DTB hash !\n");
511 return -EBADF;
512 }
513 #endif
514 return 0;
515 #endif
516 } else if (where == LOCATE_FIT) {
517 #if defined(CONFIG_ROCKCHIP_FIT_IMAGE) && !defined(CONFIG_ROCKCHIP_RESOURCE_IMAGE)
518 return fit_image_read_dtb(fdt);
519 #endif
520 }
521
522 return -EINVAL;
523 }
524
rockchip_read_dtb_file(void * fdt)525 int rockchip_read_dtb_file(void *fdt)
526 {
527 int locate, ret;
528 int size;
529
530 for (locate = 0; locate < LOCATE_END; locate++) {
531 ret = dtb_scan(fdt, locate);
532 if (!ret)
533 break;
534 }
535 if (ret) {
536 printf("No valid DTB, ret=%d\n", ret);
537 return ret;
538 }
539
540 /* reserved memory */
541 size = fdt_totalsize(fdt);
542 if (!sysmem_alloc_base(MEM_FDT, (phys_addr_t)fdt,
543 ALIGN(size, RK_BLK_SIZE) + CONFIG_SYS_FDT_PAD))
544 return -ENOMEM;
545
546 /* fixup/overlay */
547 rk_board_early_fdt_fixup(fdt);
548 #if defined(CONFIG_ANDROID_BOOT_IMAGE) && defined(CONFIG_OF_LIBFDT_OVERLAY)
549 android_fdt_overlay_apply((void *)fdt);
550 #endif
551
552 return 0;
553 }
554 #endif
555
rockchip_ram_read_dtb_file(void * img,void * fdt)556 int rockchip_ram_read_dtb_file(void *img, void *fdt)
557 {
558 int format;
559 int ret;
560
561 format = (genimg_get_format(img));
562 #ifdef CONFIG_ANDROID_BOOT_IMAGE
563 if (format == IMAGE_FORMAT_ANDROID) {
564 struct andr_img_hdr *hdr = img;
565 struct blk_desc *dev_desc;
566 ulong offset;
567
568 dev_desc = rockchip_get_bootdev();
569 if (!dev_desc)
570 return -ENODEV;
571
572 offset = hdr->page_size + ALIGN(hdr->kernel_size, hdr->page_size) +
573 ALIGN(hdr->ramdisk_size, hdr->page_size);
574 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
575 ret = resource_setup_ram_list(dev_desc, (void *)hdr + offset);
576 if (ret)
577 return ret;
578
579 return rockchip_read_dtb_file((void *)fdt);
580 #else
581 if (fdt_check_header((void *)offset))
582 return -EINVAL;
583
584 memcpy(fdt, (char *)offset, fdt_totalsize(offset));
585 if (!sysmem_alloc_base(MEM_FDT, (phys_addr_t)fdt,
586 ALIGN(fdt_totalsize(fdt), RK_BLK_SIZE) + CONFIG_SYS_FDT_PAD))
587 return -ENOMEM;
588
589 return 0;
590 #endif
591 }
592 #endif
593 #if IMAGE_ENABLE_FIT
594 if (format == IMAGE_FORMAT_FIT) {
595 const void *data;
596 size_t size;
597 int noffset;
598 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
599 const char *path = "/images/resource";
600 #else
601 const char *path = "/images/fdt";
602 #endif
603
604 noffset = fdt_path_offset(img, path);
605 if (noffset < 0)
606 return noffset;
607
608 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
609 ret = fit_image_get_data(img, noffset, &data, &size);
610 if (ret < 0)
611 return ret;
612
613 dev_desc = rockchip_get_bootdev();
614 if (!dev_desc)
615 return -ENODEV;
616
617 ret = resource_setup_ram_list(dev_desc, (void *)data);
618 if (ret) {
619 printf("resource_setup_ram_list fail, ret=%d\n", ret);
620 return ret;
621 }
622
623 return rockchip_read_dtb_file((void *)fdt);
624 #else
625
626 ret = fit_image_get_data(img, noffset, &data, &size);
627 if (ret)
628 return ret;
629
630 if (fdt_check_header(data))
631 return -EINVAL;
632
633 memcpy(fdt, data, size);
634 if (!sysmem_alloc_base(MEM_FDT, (phys_addr_t)fdt,
635 ALIGN(fdt_totalsize(fdt), RK_BLK_SIZE) + CONFIG_SYS_FDT_PAD))
636 return -ENOMEM;
637
638 printf("Load DTB from 'images/fdt'\n");
639
640 return 0;
641 #endif
642 }
643 #endif
644
645 return -EINVAL;
646 }
647