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