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