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