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 return key_is_pressed(key_read(KEY_MENU)); 255 #endif 256 257 #elif defined(CONFIG_ADC) 258 const void *blob = gd->fdt_blob; 259 int node, ret, channel = 1; 260 u32 val, chns[2]; 261 262 node = fdt_node_offset_by_compatible(blob, 0, "adc-keys"); 263 if (node >= 0) { 264 if (!fdtdec_get_int_array(blob, node, "io-channels", chns, 2)) 265 channel = chns[1]; 266 } 267 268 ret = adc_channel_single_shot("saradc", channel, &val); 269 if (ret) { 270 printf("%s: Failed to read saradc, ret=%d\n", __func__, ret); 271 return 0; 272 } 273 274 return ((val >= KEY_DOWN_MIN_VAL) && (val <= KEY_DOWN_MAX_VAL)); 275 #endif 276 277 return 0; 278 } 279 280 void setup_download_mode(void) 281 { 282 int vbus = 1; /* Assumed 1 in case of no rockusb */ 283 284 boot_devtype_init(); 285 286 /* 287 * rockchip_dnl_key_pressed(): 288 * 289 * (1) volume-up key (default) 290 * (2) menu key (If no rockusb) 291 * 292 * It's possible that USB is disabled due to developer needs 293 * a critial size of u-boot.bin. 294 * 295 * Disabling USB makes vbus can't be detected any more, so that 296 * we add menu key. The events trigger are changed: 297 * 298 * - rockusb mode(actually fallback to bootrom mode): 299 * "volume-up pressed + vbus=1" replaced with "menu pressed" 300 * - recovery mode: 301 * "volume-up pressed + vbus=0" replaced with "volume-up pressed" 302 * 303 * At the most time, USB is enabled and this feature is not applied. 304 */ 305 if (rockchip_dnl_key_pressed() || is_hotkey(HK_ROCKUSB_DNL)) { 306 printf("download key pressed... "); 307 #ifdef CONFIG_CMD_ROCKUSB 308 vbus = rockchip_u2phy_vbus_detect(); 309 #endif 310 if (vbus > 0) { 311 printf("%sentering download mode...\n", 312 IS_ENABLED(CONFIG_CMD_ROCKUSB) ? 313 "" : "no rockusb, "); 314 315 /* try rockusb download and brom download */ 316 run_command("download", 0); 317 } else { 318 printf("entering recovery mode!\n"); 319 env_set("reboot_mode", "recovery-key"); 320 } 321 } else if (is_hotkey(HK_FASTBOOT)) { 322 env_set("reboot_mode", "fastboot"); 323 } 324 } 325 326 void board_run_recovery_wipe_data(void) 327 { 328 struct bootloader_message bmsg; 329 struct blk_desc *dev_desc; 330 disk_partition_t part_info; 331 #ifdef CONFIG_ANDROID_BOOT_IMAGE 332 u32 bcb_offset = android_bcb_msg_sector_offset(); 333 #else 334 u32 bcb_offset = BCB_MESSAGE_BLK_OFFSET; 335 #endif 336 int cnt, ret; 337 338 printf("Rebooting into recovery to do wipe_data\n"); 339 dev_desc = rockchip_get_bootdev(); 340 if (!dev_desc) { 341 printf("%s: dev_desc is NULL!\n", __func__); 342 return; 343 } 344 345 ret = part_get_info_by_name(dev_desc, PART_MISC, &part_info); 346 if (ret < 0) { 347 printf("%s: Could not found misc partition, just run recovery\n", 348 __func__); 349 goto out; 350 } 351 352 memset((char *)&bmsg, 0, sizeof(struct bootloader_message)); 353 strcpy(bmsg.command, "boot-recovery"); 354 strcpy(bmsg.recovery, "recovery\n--wipe_data"); 355 bmsg.status[0] = 0; 356 cnt = DIV_ROUND_UP(sizeof(struct bootloader_message), dev_desc->blksz); 357 ret = blk_dwrite(dev_desc, part_info.start + bcb_offset, cnt, &bmsg); 358 if (ret != cnt) 359 printf("Wipe data failed, ret=%d\n", ret); 360 out: 361 /* now reboot to recovery */ 362 env_set("reboot_mode", "recovery"); 363 run_command("run bootcmd", 0); 364 } 365 366 #if defined(CONFIG_USING_KERNEL_DTB) || defined(CONFIG_CMD_BOOTM) || \ 367 defined(CONFIG_CMD_BOOTZ) || defined(CONFIG_CMD_BOOTI) 368 #ifdef CONFIG_ROCKCHIP_DTB_VERIFY 369 #ifdef CONFIG_DM_CRYPTO 370 static int crypto_csum(u32 cap, char *input, u32 input_len, u8 *output) 371 { 372 sha_context csha_ctx; 373 struct udevice *dev; 374 375 dev = crypto_get_device(cap); 376 if (!dev) { 377 printf("Can't find expected crypto device\n"); 378 return -ENODEV; 379 } 380 381 csha_ctx.algo = cap; 382 csha_ctx.length = input_len; 383 crypto_sha_csum(dev, &csha_ctx, (char *)input, 384 input_len, output); 385 386 return 0; 387 } 388 389 static int fdt_check_hash(void *fdt_addr, u32 fdt_size, 390 char *hash_cmp, u32 hash_size) 391 { 392 uchar hash[32]; 393 394 if (!hash_size) 395 return 0; 396 397 if (hash_size == 20) 398 crypto_csum(CRYPTO_SHA1, fdt_addr, fdt_size, hash); 399 else if (hash_size == 32) 400 crypto_csum(CRYPTO_SHA256, fdt_addr, fdt_size, hash); 401 else 402 return -EINVAL; 403 404 printf("HASH(c): "); 405 if (memcmp(hash, hash_cmp, hash_size)) { 406 printf("error\n"); 407 return -EBADF; 408 } 409 410 printf("OK\n"); 411 412 return 0; 413 } 414 415 #else 416 static int fdt_check_hash(void *fdt_addr, u32 fdt_size, 417 char *hash_cmp, u32 hash_size) 418 { 419 uchar hash[32]; 420 421 if (!hash_size) 422 return 0; 423 424 if (hash_size == 20) 425 sha1_csum((const uchar *)fdt_addr, fdt_size, hash); 426 else if (hash_size == 32) 427 sha256_csum((const uchar *)fdt_addr, fdt_size, hash); 428 else 429 return -EINVAL; 430 431 printf("HASH(s): "); 432 if (memcmp(hash, hash_cmp, hash_size)) { 433 printf("error\n"); 434 return -EBADF; 435 } 436 437 printf("OK\n"); 438 439 return 0; 440 } 441 #endif 442 #endif /* CONFIG_ROCKCHIP_DTB_VERIFY */ 443 444 #if defined(CONFIG_ROCKCHIP_EARLY_DISTRO_DTB) 445 static int rockchip_read_distro_dtb(void *fdt_addr) 446 { 447 const char *cmd = "part list ${devtype} ${devnum} -bootable devplist"; 448 char *devnum, *devtype, *devplist; 449 char devnum_part[12]; 450 char fdt_hex_str[19]; 451 char *fs_argv[5]; 452 int size; 453 int ret; 454 455 if (!rockchip_get_bootdev() || !fdt_addr) 456 return -ENODEV; 457 458 if (run_command_list(cmd, -1, 0)) { 459 printf("Failed to find -bootable\n"); 460 return -EINVAL; 461 } 462 463 devplist = env_get("devplist"); 464 if (!devplist) 465 return -ENODEV; 466 467 devtype = env_get("devtype"); 468 devnum = env_get("devnum"); 469 sprintf(devnum_part, "%s:%s", devnum, devplist); 470 sprintf(fdt_hex_str, "0x%lx", (ulong)fdt_addr); 471 472 fs_argv[0] = "load"; 473 fs_argv[1] = devtype, 474 fs_argv[2] = devnum_part; 475 fs_argv[3] = fdt_hex_str; 476 fs_argv[4] = CONFIG_ROCKCHIP_EARLY_DISTRO_DTB_PATH; 477 478 if (do_load(NULL, 0, 5, fs_argv, FS_TYPE_ANY)) 479 return -EIO; 480 481 if (fdt_check_header(fdt_addr)) 482 return -EBADF; 483 484 printf("DTB(Distro): %s\n", CONFIG_ROCKCHIP_EARLY_DISTRO_DTB_PATH); 485 486 return 0; 487 } 488 #endif 489 490 int rockchip_read_dtb_file(void *fdt_addr) 491 { 492 int hash_size; 493 char *hash; 494 u32 size; 495 int ret = -1; 496 497 #ifdef CONFIG_ROCKCHIP_FIT_IMAGE 498 if (ret) { 499 hash_size = 0; 500 ret = rockchip_read_fit_dtb(fdt_addr, &hash, &hash_size); 501 } 502 #endif 503 #ifdef CONFIG_ROCKCHIP_UIMAGE 504 if (ret) { 505 hash_size = 0; 506 ret = rockchip_read_uimage_dtb(fdt_addr, &hash, &hash_size); 507 } 508 #endif 509 #ifdef CONFIG_ROCKCHIP_EARLY_DISTRO_DTB 510 if (ret) { 511 hash_size = 0; 512 ret = rockchip_read_distro_dtb(fdt_addr); 513 } 514 #endif 515 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE 516 if (ret) { 517 hash_size = 0; 518 ret = rockchip_read_resource_dtb(fdt_addr, &hash, &hash_size); 519 } 520 #endif 521 if (ret) { 522 printf("Failed to load DTB\n"); 523 return ret; 524 } 525 526 if (fdt_check_header(fdt_addr)) { 527 printf("Get a bad DTB file !\n"); 528 return -EBADF; 529 } 530 531 size = fdt_totalsize(fdt_addr); 532 533 #ifdef CONFIG_ROCKCHIP_DTB_VERIFY 534 if (hash_size && fdt_check_hash(fdt_addr, size, hash, hash_size)) { 535 printf("Get a bad hash of DTB !\n"); 536 return -EBADF; 537 } 538 #endif 539 if (!sysmem_alloc_base(MEM_FDT, (phys_addr_t)fdt_addr, 540 ALIGN(size, RK_BLK_SIZE) + 541 CONFIG_SYS_FDT_PAD)) 542 return -ENOMEM; 543 544 #if defined(CONFIG_ANDROID_BOOT_IMAGE) && defined(CONFIG_OF_LIBFDT_OVERLAY) 545 android_fdt_overlay_apply((void *)fdt_addr); 546 #endif 547 548 return 0; 549 } 550 #endif 551