1 /* 2 * Rockchip trust image generator 3 * 4 * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd 5 * Peter, Software Engineering, <superpeter.cai@gmail.com>. 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 #include <sys/stat.h> 10 #include <u-boot/sha256.h> 11 #include "trust_merger.h" 12 #include "sha2.h" 13 14 /* #define DEBUG */ 15 16 static bool gDebug = 17 #ifdef DEBUG 18 true; 19 #else 20 false; 21 #endif /* DEBUG */ 22 23 #define LOGE(fmt, args...) fprintf(stderr, "E: [%s] " fmt, __func__, ##args) 24 #define LOGD(fmt, args...) \ 25 do { \ 26 if (gDebug) \ 27 fprintf(stderr, "D: [%s] " fmt, __func__, ##args); \ 28 } while (0) 29 30 /* trust image has g_trust_max_num backups */ 31 static uint32_t g_trust_max_num = 2; 32 static uint32_t g_trust_max_size = 2 * 1024 * 1024; 33 34 /* config sha and rsa */ 35 #define SHA_SEL_256 3 /* little endian */ 36 #define SHA_SEL_256_RK 2 /* big endian: only rk3368 need it */ 37 #define SHA_SEL_160 1 38 #define SHA_SEL_NONE 0 39 40 #define RSA_SEL_2048_PSS 3 /* only RK3326, PX30, RK3308 */ 41 #define RSA_SEL_2048 2 /* most platforms except above PSS */ 42 #define RSA_SEL_1024 1 43 #define RSA_SEL_NONE 0 44 45 #define is_digit(c) ((c) >= '0' && (c) <= '9') 46 47 static char *gConfigPath; 48 static OPT_T gOpts; 49 #define BL3X_FILESIZE_MAX (512 * 1024) 50 static uint8_t gBuf[BL3X_FILESIZE_MAX]; 51 static bool gSubfix; 52 static char *gLegacyPath; 53 static char *gNewPath; 54 static uint8_t gRSAmode = RSA_SEL_2048; 55 static uint8_t gSHAmode = SHA_SEL_256; 56 static bool gIgnoreBL32; 57 58 const uint8_t gBl3xID[BL_MAX_SEC][4] = { { 'B', 'L', '3', '0' }, 59 { 'B', 'L', '3', '1' }, 60 { 'B', 'L', '3', '2' }, 61 { 'B', 'L', '3', '3' } 62 }; 63 64 static inline uint32_t getBCD(uint16_t value) 65 { 66 uint8_t tmp[2] = { 0 }; 67 int i; 68 uint32_t ret; 69 70 if (value > 0xFFFF) { 71 return 0; 72 } 73 74 for (i = 0; i < 2; i++) { 75 tmp[i] = (((value / 10) % 10) << 4) | (value % 10); 76 value /= 100; 77 } 78 ret = ((uint16_t)(tmp[1] << 8)) | tmp[0]; 79 80 LOGD("ret:%x\n", ret); 81 return ret & 0xFF; 82 } 83 84 static inline void fixPath(char *path) 85 { 86 int i, len = strlen(path); 87 char tmp[MAX_LINE_LEN]; 88 char *start, *end; 89 90 for (i = 0; i < len; i++) { 91 if (path[i] == '\\') 92 path[i] = '/'; 93 else if (path[i] == '\r' || path[i] == '\n') 94 path[i] = '\0'; 95 } 96 97 if (gLegacyPath && gNewPath) { 98 start = strstr(path, gLegacyPath); 99 if (start) { 100 end = start + strlen(gLegacyPath); 101 /* Backup, so tmp can be src for strcat() */ 102 strcpy(tmp, end); 103 /* Terminate, so path can be dest for strcat() */ 104 *start = '\0'; 105 strcat(path, gNewPath); 106 strcat(path, tmp); 107 } else { 108 strcpy(tmp, path); 109 strcpy(path, gNewPath); 110 strcat(path, tmp); 111 } 112 } 113 } 114 115 static bool parseVersion(FILE *file) 116 { 117 int d = 0; 118 119 if (SCANF_EAT(file) != 0) { 120 return false; 121 } 122 if (fscanf(file, OPT_MAJOR "=%d", &d) != 1) 123 return false; 124 gOpts.major = (uint16_t) d; 125 if (SCANF_EAT(file) != 0) { 126 return false; 127 } 128 if (fscanf(file, OPT_MINOR "=%d", &d) != 1) 129 return false; 130 gOpts.minor = (uint16_t) d; 131 LOGD("major:%d, minor:%d\n", gOpts.major, gOpts.minor); 132 return true; 133 } 134 135 static bool parseBL3x(FILE *file, int bl3x_id) 136 { 137 int pos; 138 int sec; 139 char buf[MAX_LINE_LEN]; 140 bl_entry_t *pbl3x = NULL; 141 142 if (bl3x_id >= BL_MAX_SEC) { 143 return false; 144 } 145 146 pbl3x = &gOpts.bl3x[bl3x_id]; 147 148 /* SEC */ 149 if (SCANF_EAT(file) != 0) { 150 return false; 151 } 152 if (fscanf(file, OPT_SEC "=%d", &sec) != 1) { 153 return false; 154 } 155 if ((gSubfix) && (bl3x_id == BL32_SEC)) { 156 if (sec == 0) { 157 sec = 1; 158 printf("BL3%d adjust sec from 0 to 1\n", bl3x_id); 159 } 160 } else if (gIgnoreBL32 && (bl3x_id == BL32_SEC)) { 161 if (sec == 1) { 162 sec = 0; 163 printf("BL3%d adjust sec from 1 to 0\n", bl3x_id); 164 } 165 } 166 pbl3x->sec = sec; 167 LOGD("bl3%d sec: %d\n", bl3x_id, pbl3x->sec); 168 169 /* PATH */ 170 if (SCANF_EAT(file) != 0) { 171 return false; 172 } 173 memset(buf, 0, MAX_LINE_LEN); 174 if (fscanf(file, OPT_PATH "=%s", buf) != 1) { 175 if (pbl3x->sec) 176 return false; 177 } else { 178 if (strlen(buf) != 0) { 179 fixPath(buf); 180 strcpy(pbl3x->path, buf); 181 LOGD("bl3%d path:%s\n", bl3x_id, pbl3x->path); 182 } 183 } 184 185 /* ADDR */ 186 if (SCANF_EAT(file) != 0) { 187 return false; 188 } 189 memset(buf, 0, MAX_LINE_LEN); 190 if (fscanf(file, OPT_ADDR "=%s", buf) != 1) { 191 if (pbl3x->sec) 192 return false; 193 } else { 194 if (strlen(buf) != 0) { 195 pbl3x->addr = strtoul(buf, NULL, 16); 196 LOGD("bl3%d addr:0x%x\n", bl3x_id, pbl3x->addr); 197 } 198 } 199 200 pos = ftell(file); 201 if (pos < 0) { 202 return false; 203 } 204 if (SCANF_EAT(file) != 0) { 205 return false; 206 } 207 208 return true; 209 } 210 211 static bool parseOut(FILE *file) 212 { 213 if (SCANF_EAT(file) != 0) { 214 return false; 215 } 216 if (fscanf(file, OPT_OUT_PATH "=%[^\r^\n]", gOpts.outPath) != 1) 217 return false; 218 printf("out:%s\n", gOpts.outPath); 219 220 return true; 221 } 222 223 void printOpts(FILE *out) 224 { 225 fprintf(out, SEC_BL30 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL30_SEC].sec); 226 if (gOpts.bl3x[BL30_SEC].sec) { 227 fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL30_SEC].path); 228 fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL30_SEC].addr); 229 } 230 231 fprintf(out, SEC_BL31 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL31_SEC].sec); 232 if (gOpts.bl3x[BL31_SEC].sec) { 233 fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL31_SEC].path); 234 fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL31_SEC].addr); 235 } 236 237 fprintf(out, SEC_BL32 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL32_SEC].sec); 238 if (gOpts.bl3x[BL32_SEC].sec) { 239 fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL32_SEC].path); 240 fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL32_SEC].addr); 241 } 242 243 fprintf(out, SEC_BL33 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL33_SEC].sec); 244 if (gOpts.bl3x[BL33_SEC].sec) { 245 fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL33_SEC].path); 246 fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL33_SEC].addr); 247 } 248 249 fprintf(out, SEC_OUT "\n" OPT_OUT_PATH "=%s\n", gOpts.outPath); 250 } 251 252 static bool parseOpts(void) 253 { 254 FILE *file = NULL; 255 char *configPath = (gConfigPath == NULL) ? DEF_CONFIG_FILE : gConfigPath; 256 bool bl30ok = false, bl31ok = false, bl32ok = false, bl33ok = false; 257 bool outOk = false; 258 bool versionOk = false; 259 char buf[MAX_LINE_LEN]; 260 bool ret = false; 261 262 file = fopen(configPath, "r"); 263 if (!file) { 264 fprintf(stderr, "config(%s) not found!\n", configPath); 265 if (configPath == (char *)DEF_CONFIG_FILE) { 266 file = fopen(DEF_CONFIG_FILE, "w"); 267 if (file) { 268 fprintf(stderr, "create defconfig\n"); 269 printOpts(file); 270 } 271 } 272 goto end; 273 } 274 275 LOGD("start parse\n"); 276 277 if (SCANF_EAT(file) != 0) { 278 goto end; 279 } 280 while (fscanf(file, "%s", buf) == 1) { 281 if (!strcmp(buf, SEC_VERSION)) { 282 versionOk = parseVersion(file); 283 if (!versionOk) { 284 LOGE("parseVersion failed!\n"); 285 goto end; 286 } 287 } else if (!strcmp(buf, SEC_BL30)) { 288 bl30ok = parseBL3x(file, BL30_SEC); 289 if (!bl30ok) { 290 LOGE("parseBL30 failed!\n"); 291 goto end; 292 } 293 } else if (!strcmp(buf, SEC_BL31)) { 294 bl31ok = parseBL3x(file, BL31_SEC); 295 if (!bl31ok) { 296 LOGE("parseBL31 failed!\n"); 297 goto end; 298 } 299 } else if (!strcmp(buf, SEC_BL32)) { 300 bl32ok = parseBL3x(file, BL32_SEC); 301 if (!bl32ok) { 302 LOGE("parseBL32 failed!\n"); 303 goto end; 304 } 305 } else if (!strcmp(buf, SEC_BL33)) { 306 bl33ok = parseBL3x(file, BL33_SEC); 307 if (!bl33ok) { 308 LOGE("parseBL33 failed!\n"); 309 goto end; 310 } 311 } else if (!strcmp(buf, SEC_OUT)) { 312 outOk = parseOut(file); 313 if (!outOk) { 314 LOGE("parseOut failed!\n"); 315 goto end; 316 } 317 } else if (buf[0] == '#') { 318 continue; 319 } else { 320 LOGE("unknown sec: %s!\n", buf); 321 goto end; 322 } 323 if (SCANF_EAT(file) != 0) { 324 goto end; 325 } 326 } 327 328 if (bl30ok && bl31ok && bl32ok && bl33ok && outOk) 329 ret = true; 330 end: 331 if (file) 332 fclose(file); 333 334 return ret; 335 } 336 337 bool initOpts(void) 338 { 339 340 memset(&gOpts, 0, sizeof(gOpts)); 341 342 gOpts.major = DEF_MAJOR; 343 gOpts.minor = DEF_MINOR; 344 345 memcpy(&gOpts.bl3x[BL30_SEC].id, gBl3xID[BL30_SEC], 4); 346 strcpy(gOpts.bl3x[BL30_SEC].path, DEF_BL30_PATH); 347 348 memcpy(&gOpts.bl3x[BL31_SEC].id, gBl3xID[BL31_SEC], 4); 349 strcpy(gOpts.bl3x[BL31_SEC].path, DEF_BL31_PATH); 350 351 memcpy(&gOpts.bl3x[BL32_SEC].id, gBl3xID[BL32_SEC], 4); 352 strcpy(gOpts.bl3x[BL32_SEC].path, DEF_BL32_PATH); 353 354 memcpy(&gOpts.bl3x[BL33_SEC].id, gBl3xID[BL33_SEC], 4); 355 strcpy(gOpts.bl3x[BL33_SEC].path, DEF_BL33_PATH); 356 357 strcpy(gOpts.outPath, DEF_OUT_PATH); 358 359 return parseOpts(); 360 } 361 362 static inline bool getFileSize(const char *path, uint32_t *size) 363 { 364 struct stat st; 365 366 if (stat(path, &st) < 0) 367 return false; 368 *size = st.st_size; 369 LOGD("path:%s, size:%d\n", path, *size); 370 return true; 371 } 372 373 void fill_file(FILE *file, char ch, uint32_t fill_size) 374 { 375 uint8_t fill_buffer[1024]; 376 uint32_t cur_write; 377 378 memset(fill_buffer, ch, 1024); 379 while (fill_size > 0) { 380 cur_write = (fill_size >= 1024) ? 1024 : fill_size; 381 fwrite(fill_buffer, 1, cur_write, file); 382 fill_size -= cur_write; 383 } 384 } 385 386 bool filter_elf(uint32_t index, uint8_t *pMeta, uint32_t *pMetaNum, 387 bool *bElf) 388 { 389 bool ret = false; 390 FILE *file = NULL; 391 uint8_t *file_buffer = NULL; 392 uint32_t file_size, read_size, i; 393 Elf32_Ehdr *pElfHeader32; 394 Elf32_Phdr *pElfProgram32; 395 Elf64_Ehdr *pElfHeader64; 396 Elf64_Phdr *pElfProgram64; 397 bl_entry_t *pEntry = (bl_entry_t *)(pMeta + sizeof(bl_entry_t) * (*pMetaNum)); 398 LOGD("index=%d,file=%s\n", index, gOpts.bl3x[index].path); 399 400 if (!getFileSize(gOpts.bl3x[index].path, &file_size)) 401 goto exit_fileter_elf; 402 file = fopen(gOpts.bl3x[index].path, "rb"); 403 if (!file) { 404 LOGE("open file(%s) failed\n", gOpts.bl3x[index].path); 405 goto exit_fileter_elf; 406 } 407 file_buffer = malloc(file_size); 408 if (!file_buffer) 409 goto exit_fileter_elf; 410 read_size = fread(file_buffer, 1, file_size, file); 411 if (read_size != file_size) 412 goto exit_fileter_elf; 413 414 if (*((uint32_t *)file_buffer) != ELF_MAGIC) { 415 ret = true; 416 *bElf = false; 417 goto exit_fileter_elf; 418 } 419 *bElf = true; 420 if (file_buffer[5] != 1) { /* only support little endian */ 421 goto exit_fileter_elf; 422 } 423 if (*((uint16_t *)(file_buffer + EI_NIDENT)) != 424 2) { /* only support executable case */ 425 goto exit_fileter_elf; 426 } 427 428 if (file_buffer[4] == 2) { 429 pElfHeader64 = (Elf64_Ehdr *)file_buffer; 430 for (i = 0; i < pElfHeader64->e_phnum; i++) { 431 pElfProgram64 = (Elf64_Phdr *)(file_buffer + pElfHeader64->e_phoff + 432 i * pElfHeader64->e_phentsize); 433 if (pElfProgram64->p_type == 1) { /* PT_LOAD */ 434 pEntry->id = gOpts.bl3x[index].id; 435 strcpy(pEntry->path, gOpts.bl3x[index].path); 436 pEntry->size = (uint32_t) pElfProgram64->p_filesz; 437 pEntry->offset = (uint32_t) pElfProgram64->p_offset; 438 pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN); 439 pEntry->addr = (uint32_t) pElfProgram64->p_vaddr; 440 if (pEntry->align_size > BL3X_FILESIZE_MAX) { 441 LOGE("elf_file %s too large,segment=%d.\n", pEntry->path, i); 442 goto exit_fileter_elf; 443 } 444 LOGD("bl3%d: filesize = %d, imagesize = %d, segment=%d\n", index, 445 pEntry->size, pEntry->align_size, i); 446 pEntry++; 447 (*pMetaNum)++; 448 } 449 } 450 451 } else { 452 pElfHeader32 = (Elf32_Ehdr *)file_buffer; 453 for (i = 0; i < pElfHeader32->e_phnum; i++) { 454 pElfProgram32 = (Elf32_Phdr *)(file_buffer + pElfHeader32->e_phoff + 455 i * pElfHeader32->e_phentsize); 456 if (pElfProgram32->p_type == 1) { /* PT_LOAD */ 457 pEntry->id = gOpts.bl3x[index].id; 458 strcpy(pEntry->path, gOpts.bl3x[index].path); 459 pEntry->size = pElfProgram32->p_filesz; 460 pEntry->offset = pElfProgram32->p_offset; 461 pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN); 462 pEntry->addr = pElfProgram32->p_vaddr; 463 if (pEntry->align_size > BL3X_FILESIZE_MAX) { 464 LOGE("elf_file %s too large,segment=%d.\n", pEntry->path, i); 465 goto exit_fileter_elf; 466 } 467 LOGD("bl3%d: filesize = %d, imagesize = %d, segment=%d\n", index, 468 pEntry->size, pEntry->align_size, i); 469 pEntry++; 470 (*pMetaNum)++; 471 } 472 } 473 } 474 ret = true; 475 exit_fileter_elf: 476 if (file) 477 fclose(file); 478 if (file_buffer) 479 free(file_buffer); 480 return ret; 481 } 482 483 #define SHA256_CHECK_SZ ((uint32_t)(256 * 1024)) 484 static bool bl3xHash256(uint8_t *pHash, uint8_t *pData, uint32_t nDataSize) 485 { 486 uint32_t nHashSize, nHasHashSize; 487 488 if (!pHash || !pData || !nDataSize) { 489 return false; 490 } 491 492 nHasHashSize = 0; 493 494 if (gSHAmode == SHA_SEL_256_RK) { 495 sha256_ctx ctx; 496 497 sha256_begin(&ctx); 498 while (nDataSize > 0) { 499 nHashSize = (nDataSize >= SHA256_CHECK_SZ) ? SHA256_CHECK_SZ : nDataSize; 500 sha256_hash(&ctx, pData + nHasHashSize, nHashSize); 501 nHasHashSize += nHashSize; 502 nDataSize -= nHashSize; 503 } 504 sha256_end(&ctx, pHash); 505 } else { 506 sha256_context ctx; 507 508 sha256_starts(&ctx); 509 while (nDataSize > 0) { 510 nHashSize = (nDataSize >= SHA256_CHECK_SZ) ? SHA256_CHECK_SZ : nDataSize; 511 sha256_update(&ctx, pData + nHasHashSize, nHashSize); 512 nHasHashSize += nHashSize; 513 nDataSize -= nHashSize; 514 } 515 sha256_finish(&ctx, pHash); 516 } 517 return true; 518 } 519 520 static bool mergetrust(void) 521 { 522 FILE *outFile = NULL; 523 uint32_t OutFileSize; 524 uint32_t SrcFileNum, SignOffset, nComponentNum; 525 TRUST_HEADER *pHead = NULL; 526 COMPONENT_DATA *pComponentData = NULL; 527 TRUST_COMPONENT *pComponent = NULL; 528 bool ret = false, bElf; 529 uint32_t i, n; 530 uint8_t *outBuf = NULL, *pbuf = NULL, *pMetaBuf = NULL; 531 bl_entry_t *pEntry = NULL; 532 if (!initOpts()) 533 return false; 534 535 if (gDebug) { 536 printf("---------------\nUSING CONFIG:\n"); 537 printOpts(stdout); 538 printf("---------------\n\n"); 539 } 540 pMetaBuf = malloc(sizeof(bl_entry_t) * 32); 541 if (!pMetaBuf) { 542 LOGE("Merge trust image: malloc buffer error.\n"); 543 goto end; 544 } 545 546 nComponentNum = SrcFileNum = 0; 547 for (i = BL30_SEC; i < BL_MAX_SEC; i++) { 548 if (gOpts.bl3x[i].sec) { 549 if (!filter_elf(i, pMetaBuf, &nComponentNum, &bElf)) { 550 LOGE("filter_elf %s file failed\n", gOpts.bl3x[i].path); 551 goto end; 552 } 553 if (!bElf) { 554 pEntry = (bl_entry_t *)(pMetaBuf + sizeof(bl_entry_t) * nComponentNum); 555 pEntry->id = gOpts.bl3x[i].id; 556 strcpy(pEntry->path, gOpts.bl3x[i].path); 557 getFileSize(pEntry->path, &pEntry->size); 558 pEntry->offset = 0; 559 pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN); 560 pEntry->addr = gOpts.bl3x[i].addr; 561 if (pEntry->align_size > BL3X_FILESIZE_MAX) { 562 LOGE("file %s too large.\n", gOpts.bl3x[i].path); 563 goto end; 564 } 565 LOGD("bl3%d: filesize = %d, imagesize = %d\n", i, pEntry->size, 566 pEntry->align_size); 567 pEntry++; 568 nComponentNum++; 569 } 570 571 } 572 } 573 LOGD("bl3x bin sec = %d\n", nComponentNum); 574 575 /* 2048bytes for head */ 576 memset(gBuf, 0, TRUST_HEADER_SIZE); 577 578 /* Trust Head */ 579 pHead = (TRUST_HEADER *)gBuf; 580 memcpy(&pHead->tag, TRUST_HEAD_TAG, 4); 581 pHead->version = (getBCD(gOpts.major) << 8) | getBCD(gOpts.minor); 582 pHead->flags = 0; 583 pHead->flags |= (gSHAmode << 0); 584 pHead->flags |= (gRSAmode << 4); 585 586 SignOffset = sizeof(TRUST_HEADER) + nComponentNum * sizeof(COMPONENT_DATA); 587 LOGD("trust bin sign offset = %d\n", SignOffset); 588 pHead->size = (nComponentNum << 16) | (SignOffset >> 2); 589 590 pComponent = (TRUST_COMPONENT *)(gBuf + SignOffset + SIGNATURE_SIZE); 591 pComponentData = (COMPONENT_DATA *)(gBuf + sizeof(TRUST_HEADER)); 592 593 OutFileSize = TRUST_HEADER_SIZE; 594 pEntry = (bl_entry_t *)pMetaBuf; 595 for (i = 0; i < nComponentNum; i++) { 596 /* bl3x load and run address */ 597 pComponentData->LoadAddr = pEntry->addr; 598 599 pComponent->ComponentID = pEntry->id; 600 pComponent->StorageAddr = (OutFileSize >> 9); 601 pComponent->ImageSize = (pEntry->align_size >> 9); 602 603 LOGD("bl3%c: LoadAddr = 0x%08x, StorageAddr = %d, ImageSize = %d\n", 604 (char)((pEntry->id & 0xFF000000) >> 24), pComponentData->LoadAddr, 605 pComponent->StorageAddr, pComponent->ImageSize); 606 607 OutFileSize += pEntry->align_size; 608 pComponentData++; 609 pComponent++; 610 pEntry++; 611 } 612 613 /* create out file */ 614 outFile = fopen(gOpts.outPath, "wb+"); 615 if (!outFile) { 616 LOGE("open out file(%s) failed\n", gOpts.outPath); 617 618 outFile = fopen(DEF_OUT_PATH, "wb"); 619 if (!outFile) { 620 LOGE("open default out file:%s failed!\n", DEF_OUT_PATH); 621 goto end; 622 } 623 } 624 625 /* 0 for g_trust_max_num backups */ 626 #if 0 627 /* save trust head to out file */ 628 if (!fwrite(gBuf, TRUST_HEADER_SIZE, 1, outFile)) 629 goto end; 630 631 /* save trust bl3x bin */ 632 for (i = BL30_SEC; i < BL_MAX_SEC; i++) { 633 if (gOpts.bl3x[i].sec) { 634 FILE *inFile = fopen(gOpts.bl3x[i].path, "rb"); 635 if (!inFile) 636 goto end; 637 638 memset(gBuf, 0, imagesize[i]); 639 if (!fread(gBuf, filesize[i], 1, inFile)) 640 goto end; 641 fclose(inFile); 642 643 if (!fwrite(gBuf, imagesize[i], 1, outFile)) 644 goto end; 645 } 646 } 647 #else 648 /* check bin size */ 649 if (OutFileSize > g_trust_max_size) { 650 LOGE("Merge trust image: trust bin size overfull.\n"); 651 goto end; 652 } 653 654 /* malloc buffer */ 655 pbuf = outBuf = calloc(g_trust_max_size, g_trust_max_num); 656 if (!outBuf) { 657 LOGE("Merge trust image: calloc buffer error.\n"); 658 goto end; 659 } 660 memset(outBuf, 0, (g_trust_max_size * g_trust_max_num)); 661 662 /* save trust head data */ 663 memcpy(pbuf, gBuf, TRUST_HEADER_SIZE); 664 pbuf += TRUST_HEADER_SIZE; 665 666 uint8_t *pHashData = NULL; 667 pComponentData = (COMPONENT_DATA *)(outBuf + sizeof(TRUST_HEADER)); 668 669 /* save trust bl3x bin */ 670 pEntry = (bl_entry_t *)pMetaBuf; 671 for (i = 0; i < nComponentNum; i++) { 672 FILE *inFile = fopen(pEntry->path, "rb"); 673 if (!inFile) 674 goto end; 675 676 memset(gBuf, 0, pEntry->align_size); 677 fseek(inFile, pEntry->offset, SEEK_SET); 678 if (!fread(gBuf, pEntry->size, 1, inFile)) 679 goto end; 680 fclose(inFile); 681 682 /* bl3x bin hash256 */ 683 pHashData = (uint8_t *)&pComponentData->HashData[0]; 684 bl3xHash256(pHashData, gBuf, pEntry->align_size); 685 memcpy(pbuf, gBuf, pEntry->align_size); 686 687 pComponentData++; 688 pbuf += pEntry->align_size; 689 pEntry++; 690 } 691 692 /* copy other (g_trust_max_num - 1) backup bin */ 693 for (n = 1; n < g_trust_max_num; n++) { 694 memcpy(outBuf + g_trust_max_size * n, outBuf, g_trust_max_size); 695 } 696 697 /* save date to file */ 698 if (!fwrite(outBuf, g_trust_max_size * g_trust_max_num, 1, outFile)) { 699 LOGE("Merge trust image: write file error.\n"); 700 goto end; 701 } 702 #endif 703 704 ret = true; 705 706 end: 707 /* 708 for (i = BL30_SEC; i < BL_MAX_SEC; i++) { 709 if (gOpts.bl3x[i].sec != false) { 710 if (gOpts.bl3x[i].is_elf) { 711 if (stat(gOpts.bl3x[i].path, &st) >= 0) 712 remove(gOpts.bl3x[i].path); 713 } 714 } 715 } 716 */ 717 if (pMetaBuf) 718 free(pMetaBuf); 719 if (outBuf) 720 free(outBuf); 721 if (outFile) 722 fclose(outFile); 723 return ret; 724 } 725 726 static int saveDatatoFile(char *FileName, void *pBuf, uint32_t size) 727 { 728 FILE *OutFile = NULL; 729 int ret = -1; 730 731 OutFile = fopen(FileName, "wb"); 732 if (!OutFile) { 733 printf("open OutPutFlie:%s failed!\n", FileName); 734 goto end; 735 } 736 if (1 != fwrite(pBuf, size, 1, OutFile)) { 737 printf("write output file failed!\n"); 738 goto end; 739 } 740 741 ret = 0; 742 end: 743 if (OutFile) 744 fclose(OutFile); 745 746 return ret; 747 } 748 749 static bool unpacktrust(char *path) 750 { 751 FILE *FileSrc = NULL; 752 uint32_t FileSize; 753 uint8_t *pBuf = NULL; 754 uint32_t SrcFileNum, SignOffset; 755 TRUST_HEADER *pHead = NULL; 756 COMPONENT_DATA *pComponentData = NULL; 757 TRUST_COMPONENT *pComponent = NULL; 758 char str[MAX_LINE_LEN]; 759 bool ret = false; 760 uint32_t i; 761 762 FileSrc = fopen(path, "rb"); 763 if (FileSrc == NULL) { 764 printf("open %s failed!\n", path); 765 goto end; 766 } 767 768 if (getFileSize(path, &FileSize) == false) { 769 printf("File Size failed!\n"); 770 goto end; 771 } 772 printf("File Size = %d\n", FileSize); 773 774 pBuf = (uint8_t *)malloc(FileSize); 775 if (1 != fread(pBuf, FileSize, 1, FileSrc)) { 776 printf("read input file failed!\n"); 777 goto end; 778 } 779 780 pHead = (TRUST_HEADER *)pBuf; 781 782 memcpy(str, &pHead->tag, 4); 783 str[4] = '\0'; 784 printf("Header Tag:%s\n", str); 785 printf("Header version:%d\n", pHead->version); 786 printf("Header flag:%d\n", pHead->flags); 787 788 SrcFileNum = (pHead->size >> 16) & 0xffff; 789 SignOffset = (pHead->size & 0xffff) << 2; 790 printf("SrcFileNum:%d\n", SrcFileNum); 791 printf("SignOffset:%d\n", SignOffset); 792 793 pComponent = (TRUST_COMPONENT *)(pBuf + SignOffset + SIGNATURE_SIZE); 794 pComponentData = (COMPONENT_DATA *)(pBuf + sizeof(TRUST_HEADER)); 795 796 for (i = 0; i < SrcFileNum; i++) { 797 printf("Component %d:\n", i); 798 799 memcpy(str, &pComponent->ComponentID, 4); 800 str[4] = '\0'; 801 printf("ComponentID:%s\n", str); 802 printf("StorageAddr:0x%x\n", pComponent->StorageAddr); 803 printf("ImageSize:0x%x\n", pComponent->ImageSize); 804 printf("LoadAddr:0x%x\n", pComponentData->LoadAddr); 805 806 saveDatatoFile(str, pBuf + (pComponent->StorageAddr << 9), 807 pComponent->ImageSize << 9); 808 809 pComponentData++; 810 pComponent++; 811 } 812 813 ret = true; 814 end: 815 if (FileSrc) 816 fclose(FileSrc); 817 if (pBuf) 818 free(pBuf); 819 820 return ret; 821 } 822 823 static void printHelp(void) 824 { 825 printf("Usage: trust_merger [options]... FILE\n"); 826 printf( 827 "Merge or unpack Rockchip's trust image (Default action is to merge.)\n"); 828 printf("Options:\n"); 829 printf("\t" OPT_MERGE "\t\t\tMerge trust with specified config.\n"); 830 printf("\t" OPT_UNPACK "\t\tUnpack specified trust to current dir.\n"); 831 printf("\t" OPT_VERBOSE "\t\tDisplay more runtime informations.\n"); 832 printf("\t" OPT_HELP "\t\t\tDisplay this information.\n"); 833 printf("\t" OPT_VERSION "\t\tDisplay version information.\n"); 834 printf("\t" OPT_SUBFIX "\t\tSpec subfix.\n"); 835 printf("\t" OPT_REPLACE "\t\tReplace some part of binary path.\n"); 836 printf("\t" OPT_RSA "\t\t\tRSA mode.\"--rsa [mode]\", [mode] can be: " 837 "0(none), 1(1024), 2(2048), 3(2048 pss).\n"); 838 printf("\t" OPT_SHA 839 "\t\t\tSHA mode.\"--sha [mode]\", [mode] can be: 0(none), 1(160), " 840 "2(256 RK big endian), 3(256 little endian).\n"); 841 printf("\t" OPT_SIZE "\t\t\tTrustImage size.\"--size [per image KB size] " 842 "[copy count]\", per image must be 64KB aligned\n"); 843 } 844 845 int main(int argc, char **argv) 846 { 847 bool merge = true; 848 char *optPath = NULL; 849 int i; 850 851 gConfigPath = NULL; 852 for (i = 1; i < argc; i++) { 853 if (!strcmp(OPT_VERBOSE, argv[i])) { 854 gDebug = true; 855 } else if (!strcmp(OPT_HELP, argv[i])) { 856 printHelp(); 857 return 0; 858 } else if (!strcmp(OPT_VERSION, argv[i])) { 859 printf("trust_merger (cwz@rock-chips.com)\t" VERSION "\n"); 860 return 0; 861 } else if (!strcmp(OPT_MERGE, argv[i])) { 862 merge = true; 863 } else if (!strcmp(OPT_UNPACK, argv[i])) { 864 merge = false; 865 } else if (!strcmp(OPT_SUBFIX, argv[i])) { 866 gSubfix = true; 867 printf("trust_merger: Spec subfix!\n"); 868 } else if (!strcmp(OPT_REPLACE, argv[i])) { 869 i++; 870 gLegacyPath = argv[i]; 871 i++; 872 gNewPath = argv[i]; 873 } else if (!strcmp(OPT_RSA, argv[i])) { 874 i++; 875 if (!is_digit(*(argv[i]))) { 876 printHelp(); 877 return -1; 878 } 879 gRSAmode = *(argv[i]) - '0'; 880 LOGD("rsa mode:%d\n", gRSAmode); 881 } else if (!strcmp(OPT_SHA, argv[i])) { 882 i++; 883 if (!is_digit(*(argv[i]))) { 884 printHelp(); 885 return -1; 886 } 887 gSHAmode = *(argv[i]) - '0'; 888 LOGD("sha mode:%d\n", gSHAmode); 889 } else if (!strcmp(OPT_SIZE, argv[i])) { 890 /* Per trust image size */ 891 g_trust_max_size = strtoul(argv[++i], NULL, 10); 892 /* 893 * Usually, it must be at 512kb align due to preloader 894 * detects every 512kb. But some product has critial 895 * flash size requirement, we have to make it small than 896 * 512KB. 897 */ 898 if (g_trust_max_size % 64) { 899 printHelp(); 900 return -1; 901 } 902 g_trust_max_size *= 1024; /* bytes */ 903 904 /* Total backup numbers */ 905 g_trust_max_num = strtoul(argv[++i], NULL, 10); 906 } else if (!strcmp(OPT_IGNORE_BL32, argv[i])) { 907 gIgnoreBL32 = true; 908 } else { 909 if (optPath) { 910 fprintf(stderr, "only need one path arg, but we have:\n%s\n%s.\n", 911 optPath, argv[i]); 912 printHelp(); 913 return -1; 914 } 915 optPath = argv[i]; 916 } 917 } 918 if (!merge && !optPath) { 919 fprintf(stderr, "need set out path to unpack!\n"); 920 printHelp(); 921 return -1; 922 } 923 924 if (merge) { 925 LOGD("do_merge\n"); 926 gConfigPath = optPath; 927 if (!mergetrust()) { 928 fprintf(stderr, "merge failed!\n"); 929 return -1; 930 } 931 printf("merge success(%s)\n", gOpts.outPath); 932 } else { 933 LOGD("do_unpack\n"); 934 if (!unpacktrust(optPath)) { 935 fprintf(stderr, "unpack failed!\n"); 936 return -1; 937 } 938 printf("unpack success\n"); 939 } 940 941 return 0; 942 } 943