1 /* 2 * (C) Copyright 2015 Google, Inc 3 * Written by Simon Glass <sjg@chromium.org> 4 * 5 * (C) 2017 Theobroma Systems Design und Consulting GmbH 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 * 9 * Helper functions for Rockchip images 10 */ 11 12 #include "imagetool.h" 13 #include <image.h> 14 #include <rc4.h> 15 #include "mkimage.h" 16 #include "rkcommon.h" 17 18 enum { 19 RK_SIGNATURE = 0x0ff0aa55, 20 }; 21 22 /** 23 * struct header0_info - header block for boot ROM 24 * 25 * This is stored at SD card block 64 (where each block is 512 bytes, or at 26 * the start of SPI flash. It is encoded with RC4. 27 * 28 * @signature: Signature (must be RKSD_SIGNATURE) 29 * @disable_rc4: 0 to use rc4 for boot image, 1 to use plain binary 30 * @init_offset: Offset in blocks of the SPL code from this header 31 * block. E.g. 4 means 2KB after the start of this header. 32 * Other fields are not used by U-Boot 33 */ 34 struct header0_info { 35 uint32_t signature; 36 uint8_t reserved[4]; 37 uint32_t disable_rc4; 38 uint16_t init_offset; 39 uint8_t reserved1[492]; 40 uint16_t init_size; 41 uint16_t init_boot_size; 42 uint8_t reserved2[2]; 43 }; 44 45 /** 46 * struct header1 info 47 */ 48 struct header1_info { 49 uint32_t magic; 50 }; 51 52 /** 53 * struct spl_info - spl info for each chip 54 * 55 * @imagename: Image name(passed by "mkimage -n") 56 * @spl_hdr: Boot ROM requires a 4-bytes spl header 57 * @spl_size: Spl size(include extra 4-bytes spl header) 58 * @spl_rc4: RC4 encode the SPL binary (same key as header) 59 */ 60 61 struct spl_info { 62 const char *imagename; 63 const char *spl_hdr; 64 const uint32_t spl_size; 65 const bool spl_rc4; 66 }; 67 68 static struct spl_info spl_infos[] = { 69 { "rk3036", "RK30", 0x1000, false }, 70 { "rk3066", "RK30", 0x8000, true, }, 71 { "rk3128", "RK31", 0x1800, false }, 72 { "rk3188", "RK31", 0x8000 - 0x800, true }, 73 { "rk322x", "RK32", 0x8000 - 0x1000, false }, 74 { "rk3288", "RK32", 0x8000, false }, 75 { "rk3308", "RK33", 0x40000 - 0x1000, false}, 76 { "rk3328", "RK32", 0x8000 - 0x800, false }, 77 { "rk3368", "RK33", 0x8000 - 0x1000, false }, 78 { "rk3399", "RK33", 0x30000 - 0x2000, false }, 79 { "px30", "RK33", 0x2800, false }, 80 { "rv1108", "RK11", 0x1800, false }, 81 { "rv1126", "110B", 0x10000 - 0x1000, false}, 82 { "rk1808", "RK18", 0x200000 - 0x2000, false}, 83 }; 84 85 /** 86 * struct spl_params - spl params parsed in check_params() 87 * 88 * @init_file: Init data file path 89 * @init_size: Aligned size of init data in bytes 90 * @boot_file: Boot data file path 91 * @boot_size: Aligned size of boot data in bytes 92 */ 93 94 struct spl_params { 95 char *init_file; 96 uint32_t init_size; 97 char *boot_file; 98 uint32_t boot_size; 99 }; 100 101 static struct spl_params spl_params = { 0 }; 102 103 static unsigned char rc4_key[16] = { 104 124, 78, 3, 4, 85, 5, 9, 7, 105 45, 44, 123, 56, 23, 13, 23, 17 106 }; 107 108 static struct spl_info *rkcommon_get_spl_info(char *imagename) 109 { 110 int i; 111 112 if (!imagename) 113 return NULL; 114 115 for (i = 0; i < ARRAY_SIZE(spl_infos); i++) 116 if (!strncmp(imagename, spl_infos[i].imagename, 6)) 117 return spl_infos + i; 118 119 return NULL; 120 } 121 122 static int rkcommon_get_aligned_size(struct image_tool_params *params, 123 const char *fname) 124 { 125 int size; 126 127 size = imagetool_get_filesize(params, fname); 128 if (size < 0) 129 return -1; 130 131 /* 132 * Pad to a 2KB alignment, as required for init/boot size by the ROM 133 * (see https://lists.denx.de/pipermail/u-boot/2017-May/293268.html) 134 */ 135 return ROUND(size, RK_SIZE_ALIGN); 136 } 137 138 int rkcommon_check_params(struct image_tool_params *params) 139 { 140 int i; 141 142 /* 143 * If this is a operation (list or extract), the don't require 144 * imagename to be set. 145 */ 146 if (params->lflag || params->iflag) 147 return EXIT_SUCCESS; 148 149 if (!rkcommon_get_spl_info(params->imagename)) 150 goto err_spl_info; 151 152 spl_params.init_file = params->datafile; 153 154 spl_params.boot_file = strchr(spl_params.init_file, ':'); 155 if (spl_params.boot_file) { 156 *spl_params.boot_file = '\0'; 157 spl_params.boot_file += 1; 158 } 159 160 spl_params.init_size = 161 rkcommon_get_aligned_size(params, spl_params.init_file); 162 if (spl_params.init_size < 0) 163 return EXIT_FAILURE; 164 165 /* Boot file is optional, and only for back-to-bootrom functionality. */ 166 if (spl_params.boot_file) { 167 spl_params.boot_size = 168 rkcommon_get_aligned_size(params, spl_params.boot_file); 169 if (spl_params.boot_size < 0) 170 return EXIT_FAILURE; 171 } 172 173 if (spl_params.init_size > rkcommon_get_spl_size(params)) { 174 fprintf(stderr, 175 "Error: SPL image is too large (size %#x than %#x)\n", 176 spl_params.init_size, rkcommon_get_spl_size(params)); 177 return EXIT_FAILURE; 178 } 179 180 return EXIT_SUCCESS; 181 182 err_spl_info: 183 fprintf(stderr, "ERROR: imagename (%s) is not supported!\n", 184 params->imagename ? params->imagename : "NULL"); 185 186 fprintf(stderr, "Available imagename:"); 187 for (i = 0; i < ARRAY_SIZE(spl_infos); i++) 188 fprintf(stderr, "\t%s", spl_infos[i].imagename); 189 fprintf(stderr, "\n"); 190 191 return EXIT_FAILURE; 192 } 193 194 const char *rkcommon_get_spl_hdr(struct image_tool_params *params) 195 { 196 struct spl_info *info = rkcommon_get_spl_info(params->imagename); 197 198 /* 199 * info would not be NULL, because of we checked params before. 200 */ 201 return info->spl_hdr; 202 } 203 204 205 int rkcommon_get_spl_size(struct image_tool_params *params) 206 { 207 struct spl_info *info = rkcommon_get_spl_info(params->imagename); 208 209 /* 210 * info would not be NULL, because of we checked params before. 211 */ 212 return info->spl_size; 213 } 214 215 bool rkcommon_need_rc4_spl(struct image_tool_params *params) 216 { 217 struct spl_info *info = rkcommon_get_spl_info(params->imagename); 218 219 /* 220 * info would not be NULL, because of we checked params before. 221 */ 222 return info->spl_rc4; 223 } 224 225 static void rkcommon_set_header0(void *buf, struct image_tool_params *params) 226 { 227 struct header0_info *hdr = buf; 228 229 memset(buf, '\0', RK_INIT_OFFSET * RK_BLK_SIZE); 230 hdr->signature = RK_SIGNATURE; 231 hdr->disable_rc4 = !rkcommon_need_rc4_spl(params); 232 hdr->init_offset = RK_INIT_OFFSET; 233 hdr->init_size = spl_params.init_size / RK_BLK_SIZE; 234 235 /* 236 * init_boot_size needs to be set, as it is read by the BootROM 237 * to determine the size of the next-stage bootloader (e.g. U-Boot 238 * proper), when used with the back-to-bootrom functionality. 239 * 240 * see https://lists.denx.de/pipermail/u-boot/2017-May/293267.html 241 * for a more detailed explanation by Andy Yan 242 */ 243 if (spl_params.boot_file) 244 hdr->init_boot_size = 245 hdr->init_size + spl_params.boot_size / RK_BLK_SIZE; 246 else 247 hdr->init_boot_size = 248 hdr->init_size + RK_MAX_BOOT_SIZE / RK_BLK_SIZE; 249 250 rc4_encode(buf, RK_BLK_SIZE, rc4_key); 251 } 252 253 void rkcommon_set_header(void *buf, struct stat *sbuf, int ifd, 254 struct image_tool_params *params) 255 { 256 struct header1_info *hdr = buf + RK_SPL_HDR_START; 257 258 rkcommon_set_header0(buf, params); 259 260 /* Set up the SPL name (i.e. copy spl_hdr over) */ 261 if (memcmp(&hdr->magic, "RSAK", 4)) 262 memcpy(&hdr->magic, rkcommon_get_spl_hdr(params), RK_SPL_HDR_SIZE); 263 264 if (rkcommon_need_rc4_spl(params)) 265 rkcommon_rc4_encode_spl(buf, RK_SPL_HDR_START, 266 spl_params.init_size); 267 268 if (spl_params.boot_file) { 269 if (rkcommon_need_rc4_spl(params)) 270 rkcommon_rc4_encode_spl(buf + RK_SPL_HDR_START, 271 spl_params.init_size, 272 spl_params.boot_size); 273 } 274 } 275 276 static inline unsigned rkcommon_offset_to_spi(unsigned offset) 277 { 278 /* 279 * While SD/MMC images use a flat addressing, SPI images are padded 280 * to use the first 2K of every 4K sector only. 281 */ 282 return ((offset & ~0x7ff) << 1) + (offset & 0x7ff); 283 } 284 285 static int rkcommon_parse_header(const void *buf, struct header0_info *header0, 286 struct spl_info **spl_info) 287 { 288 unsigned hdr1_offset; 289 struct header1_info *hdr1_sdmmc, *hdr1_spi; 290 int i; 291 292 if (spl_info) 293 *spl_info = NULL; 294 295 /* 296 * The first header (hdr0) is always RC4 encoded, so try to decrypt 297 * with the well-known key. 298 */ 299 memcpy((void *)header0, buf, sizeof(struct header0_info)); 300 rc4_encode((void *)header0, sizeof(struct header0_info), rc4_key); 301 302 if (header0->signature != RK_SIGNATURE) 303 return -EPROTO; 304 305 /* We don't support RC4 encoded image payloads here, yet... */ 306 if (header0->disable_rc4 == 0) 307 return -ENOSYS; 308 309 hdr1_offset = header0->init_offset * RK_BLK_SIZE; 310 hdr1_sdmmc = (struct header1_info *)(buf + hdr1_offset); 311 hdr1_spi = (struct header1_info *)(buf + 312 rkcommon_offset_to_spi(hdr1_offset)); 313 314 for (i = 0; i < ARRAY_SIZE(spl_infos); i++) { 315 if (!memcmp(&hdr1_sdmmc->magic, spl_infos[i].spl_hdr, 4)) { 316 if (spl_info) 317 *spl_info = &spl_infos[i]; 318 return IH_TYPE_RKSD; 319 } else if (!memcmp(&hdr1_spi->magic, spl_infos[i].spl_hdr, 4)) { 320 if (spl_info) 321 *spl_info = &spl_infos[i]; 322 return IH_TYPE_RKSPI; 323 } 324 } 325 326 return -1; 327 } 328 329 int rkcommon_verify_header(unsigned char *buf, int size, 330 struct image_tool_params *params) 331 { 332 struct header0_info header0; 333 struct spl_info *img_spl_info, *spl_info; 334 int ret; 335 336 ret = rkcommon_parse_header(buf, &header0, &img_spl_info); 337 338 /* If this is the (unimplemented) RC4 case, then rewrite the result */ 339 if (ret == -ENOSYS) 340 return 0; 341 342 if (ret < 0) 343 return ret; 344 345 /* 346 * If no 'imagename' is specified via the commandline (e.g. if this is 347 * 'dumpimage -l' w/o any further constraints), we accept any spl_info. 348 */ 349 if (params->imagename == NULL) 350 return 0; 351 352 /* Match the 'imagename' against the 'spl_hdr' found */ 353 spl_info = rkcommon_get_spl_info(params->imagename); 354 if (spl_info && img_spl_info) 355 return strcmp(spl_info->spl_hdr, img_spl_info->spl_hdr); 356 357 return -ENOENT; 358 } 359 360 void rkcommon_print_header(const void *buf) 361 { 362 struct header0_info header0; 363 struct spl_info *spl_info; 364 uint8_t image_type; 365 int ret, boot_size; 366 367 ret = rkcommon_parse_header(buf, &header0, &spl_info); 368 369 /* If this is the (unimplemented) RC4 case, then fail silently */ 370 if (ret == -ENOSYS) 371 return; 372 373 if (ret < 0) { 374 fprintf(stderr, "Error: image verification failed\n"); 375 return; 376 } 377 378 image_type = ret; 379 380 printf("Image Type: Rockchip %s (%s) boot image\n", 381 spl_info->spl_hdr, 382 (image_type == IH_TYPE_RKSD) ? "SD/MMC" : "SPI"); 383 printf("Init Data Size: %d bytes\n", header0.init_size * RK_BLK_SIZE); 384 385 boot_size = (header0.init_boot_size - header0.init_size) * RK_BLK_SIZE; 386 if (boot_size != RK_MAX_BOOT_SIZE) 387 printf("Boot Data Size: %d bytes\n", boot_size); 388 } 389 390 void rkcommon_rc4_encode_spl(void *buf, unsigned int offset, unsigned int size) 391 { 392 unsigned int remaining = size; 393 394 while (remaining > 0) { 395 int step = (remaining > RK_BLK_SIZE) ? RK_BLK_SIZE : remaining; 396 397 rc4_encode(buf + offset, step, rc4_key); 398 offset += RK_BLK_SIZE; 399 remaining -= step; 400 } 401 } 402 403 int rkcommon_vrec_header(struct image_tool_params *params, 404 struct image_type_params *tparams) 405 { 406 /* 407 * The SPL image looks as follows: 408 * 409 * 0x0 header0 (see rkcommon.c) 410 * 0x800 spl_name ('RK30', ..., 'RK33') 411 * (start of the payload for AArch64 payloads: we expect the 412 * first 4 bytes to be available for overwriting with our 413 * spl_name) 414 * 0x804 first instruction to be executed 415 * (start of the image/payload for 32bit payloads) 416 * 417 * For AArch64 (ARMv8) payloads, natural alignment (8-bytes) is 418 * required for its sections (so the image we receive needs to 419 * have the first 4 bytes reserved for the spl_name). Reserving 420 * these 4 bytes is done using the BOOT0_HOOK infrastructure. 421 * 422 * The header is always at 0x800 (as we now use a payload 423 * prepadded using the boot0 hook for all targets): the first 424 * 4 bytes of these images can safely be overwritten using the 425 * boot magic. 426 */ 427 tparams->header_size = RK_SPL_HDR_START; 428 429 /* Allocate, clear and install the header */ 430 tparams->hdr = malloc(tparams->header_size); 431 if (!tparams->hdr) { 432 fprintf(stderr, "%s: Can't alloc header: %s\n", 433 params->cmdname, strerror(errno)); 434 exit(EXIT_FAILURE); 435 } 436 memset(tparams->hdr, 0, tparams->header_size); 437 438 /* 439 * We need to store the original file-size (i.e. before padding), as 440 * imagetool does not set this during its adjustment of file_size. 441 */ 442 params->orig_file_size = tparams->header_size + 443 spl_params.init_size + spl_params.boot_size; 444 445 params->file_size = ROUND(params->orig_file_size, RK_SIZE_ALIGN); 446 447 /* Ignoring pad len, since we are using our own copy_image() */ 448 return 0; 449 } 450 451 static int pad_file(struct image_tool_params *params, int ifd, int pad) 452 { 453 uint8_t zeros[4096]; 454 455 memset(zeros, 0, sizeof(zeros)); 456 457 while (pad > 0) { 458 int todo = sizeof(zeros); 459 460 if (todo > pad) 461 todo = pad; 462 if (write(ifd, (char *)&zeros, todo) != todo) { 463 fprintf(stderr, "%s: Write error on %s: %s\n", 464 params->cmdname, params->imagefile, 465 strerror(errno)); 466 return -1; 467 } 468 pad -= todo; 469 } 470 471 return 0; 472 } 473 474 static int copy_file(struct image_tool_params *params, int ifd, 475 const char *file, int padded_size) 476 { 477 int dfd; 478 struct stat sbuf; 479 unsigned char *ptr; 480 int size; 481 482 if (params->vflag) 483 fprintf(stderr, "Adding Image %s\n", file); 484 485 dfd = open(file, O_RDONLY | O_BINARY); 486 if (dfd < 0) { 487 fprintf(stderr, "%s: Can't open %s: %s\n", 488 params->cmdname, file, strerror(errno)); 489 return -1; 490 } 491 492 if (fstat(dfd, &sbuf) < 0) { 493 fprintf(stderr, "%s: Can't stat %s: %s\n", 494 params->cmdname, file, strerror(errno)); 495 goto err_close; 496 } 497 498 if (params->vflag) 499 fprintf(stderr, "Size %u(pad to %u)\n", 500 (int)sbuf.st_size, padded_size); 501 502 ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0); 503 if (ptr == MAP_FAILED) { 504 fprintf(stderr, "%s: Can't read %s: %s\n", 505 params->cmdname, file, strerror(errno)); 506 goto err_munmap; 507 } 508 509 size = sbuf.st_size; 510 if (write(ifd, ptr, size) != size) { 511 fprintf(stderr, "%s: Write error on %s: %s\n", 512 params->cmdname, params->imagefile, strerror(errno)); 513 goto err_munmap; 514 } 515 516 munmap((void *)ptr, sbuf.st_size); 517 close(dfd); 518 return pad_file(params, ifd, padded_size - size); 519 520 err_munmap: 521 munmap((void *)ptr, sbuf.st_size); 522 err_close: 523 close(dfd); 524 return -1; 525 } 526 527 int rockchip_copy_image(int ifd, struct image_tool_params *params) 528 { 529 int ret; 530 531 ret = copy_file(params, ifd, spl_params.init_file, 532 spl_params.init_size); 533 if (ret) 534 return ret; 535 536 if (spl_params.boot_file) { 537 ret = copy_file(params, ifd, spl_params.boot_file, 538 spl_params.boot_size); 539 if (ret) 540 return ret; 541 } 542 543 return pad_file(params, ifd, 544 params->file_size - params->orig_file_size); 545 } 546