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