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