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
getBCD(uint16_t value)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
fixPath(char * path)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
parseVersion(FILE * file)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
parseBL3x(FILE * file,int bl3x_id)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
parseOut(FILE * file)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
printOpts(FILE * out)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
parseOpts(void)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
initOpts(void)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
getFileSize(const char * path,uint32_t * size)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
fill_file(FILE * file,char ch,uint32_t fill_size)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
filter_elf(uint32_t index,uint8_t * pMeta,uint32_t * pMetaNum,bool * bElf)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_paddr;
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_paddr;
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))
bl3xHash256(uint8_t * pHash,uint8_t * pData,uint32_t nDataSize)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
mergetrust(void)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
saveDatatoFile(char * FileName,void * pBuf,uint32_t size)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
unpacktrust(char * path)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
printHelp(void)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
main(int argc,char ** argv)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