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