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