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