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