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