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