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