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