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