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