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