xref: /rk3399_rockchip-uboot/tools/rockchip/trust_merger.c (revision 6aa65bb1ee0951865e27da81dde1de76c6d4687e)
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