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