xref: /rk3399_rockchip-uboot/tools/rockchip/trust_merger.c (revision 02c35d15a0427902d28d64300a2c288b11b72933)
123ba6841SJoseph Chen /*
223ba6841SJoseph Chen  * Rockchip trust image generator
323ba6841SJoseph Chen  *
423ba6841SJoseph Chen  * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
523ba6841SJoseph Chen  * Peter, Software Engineering, <superpeter.cai@gmail.com>.
623ba6841SJoseph Chen  *
723ba6841SJoseph Chen  * SPDX-License-Identifier:	GPL-2.0+
823ba6841SJoseph Chen  */
923ba6841SJoseph Chen #include <sys/stat.h>
1023ba6841SJoseph Chen #include <u-boot/sha256.h>
1123ba6841SJoseph Chen #include "trust_merger.h"
1223ba6841SJoseph Chen #include "sha2.h"
1323ba6841SJoseph Chen 
1423ba6841SJoseph Chen /* #define DEBUG */
1523ba6841SJoseph Chen 
1623ba6841SJoseph Chen static bool gDebug =
1723ba6841SJoseph Chen #ifdef DEBUG
1823ba6841SJoseph Chen         true;
1923ba6841SJoseph Chen #else
2023ba6841SJoseph Chen         false;
2123ba6841SJoseph Chen #endif /* DEBUG */
2223ba6841SJoseph Chen 
2323ba6841SJoseph Chen #define LOGE(fmt, args...) fprintf(stderr, "E: [%s] " fmt, __func__, ##args)
2423ba6841SJoseph Chen #define LOGD(fmt, args...)                                                     \
2523ba6841SJoseph Chen   do {                                                                         \
2623ba6841SJoseph Chen     if (gDebug)                                                                \
2723ba6841SJoseph Chen       fprintf(stderr, "D: [%s] " fmt, __func__, ##args);                       \
2823ba6841SJoseph Chen   } while (0)
2923ba6841SJoseph Chen 
3023ba6841SJoseph Chen /* trust image has g_trust_max_num backups */
3123ba6841SJoseph Chen static uint32_t g_trust_max_num = 2;
3223ba6841SJoseph Chen static uint32_t g_trust_max_size = 2 * 1024 * 1024;
3323ba6841SJoseph Chen 
3423ba6841SJoseph Chen /* config sha and rsa */
3523ba6841SJoseph Chen #define SHA_SEL_256 3    /* little endian */
3623ba6841SJoseph Chen #define SHA_SEL_256_RK 2 /* big endian: only rk3368 need it */
3723ba6841SJoseph Chen #define SHA_SEL_160 1
3823ba6841SJoseph Chen #define SHA_SEL_NONE 0
3923ba6841SJoseph Chen 
4023ba6841SJoseph Chen #define RSA_SEL_2048_PSS 3 /* only RK3326, PX30, RK3308 */
4123ba6841SJoseph Chen #define RSA_SEL_2048 2     /* most platforms except above PSS */
4223ba6841SJoseph Chen #define RSA_SEL_1024 1
4323ba6841SJoseph Chen #define RSA_SEL_NONE 0
4423ba6841SJoseph Chen 
4523ba6841SJoseph Chen #define is_digit(c) ((c) >= '0' && (c) <= '9')
4623ba6841SJoseph Chen 
4723ba6841SJoseph Chen static char *gConfigPath;
4823ba6841SJoseph Chen static OPT_T gOpts;
4923ba6841SJoseph Chen #define BL3X_FILESIZE_MAX (512 * 1024)
5023ba6841SJoseph Chen static uint8_t gBuf[BL3X_FILESIZE_MAX];
5123ba6841SJoseph Chen static bool gSubfix;
5223ba6841SJoseph Chen static char *gLegacyPath;
5323ba6841SJoseph Chen static char *gNewPath;
54e311da24SJoseph Chen static char *gPrePath;
5523ba6841SJoseph Chen static uint8_t gRSAmode = RSA_SEL_2048;
5623ba6841SJoseph Chen static uint8_t gSHAmode = SHA_SEL_256;
5775828958SJoseph Chen static bool gIgnoreBL32;
5823ba6841SJoseph Chen 
5923ba6841SJoseph Chen const uint8_t gBl3xID[BL_MAX_SEC][4] = { { 'B', 'L', '3', '0' },
6023ba6841SJoseph Chen 	{ 'B', 'L', '3', '1' },
6123ba6841SJoseph Chen 	{ 'B', 'L', '3', '2' },
6223ba6841SJoseph Chen 	{ 'B', 'L', '3', '3' }
6323ba6841SJoseph Chen };
6423ba6841SJoseph Chen 
getBCD(uint16_t value)6523ba6841SJoseph Chen static inline uint32_t getBCD(uint16_t value)
6623ba6841SJoseph Chen {
6723ba6841SJoseph Chen 	uint8_t tmp[2] = { 0 };
6823ba6841SJoseph Chen 	int i;
6923ba6841SJoseph Chen 	uint32_t ret;
7023ba6841SJoseph Chen 
7123ba6841SJoseph Chen 	if (value > 0xFFFF) {
7223ba6841SJoseph Chen 		return 0;
7323ba6841SJoseph Chen 	}
7423ba6841SJoseph Chen 
7523ba6841SJoseph Chen 	for (i = 0; i < 2; i++) {
7623ba6841SJoseph Chen 		tmp[i] = (((value / 10) % 10) << 4) | (value % 10);
7723ba6841SJoseph Chen 		value /= 100;
7823ba6841SJoseph Chen 	}
7923ba6841SJoseph Chen 	ret = ((uint16_t)(tmp[1] << 8)) | tmp[0];
8023ba6841SJoseph Chen 
8123ba6841SJoseph Chen 	LOGD("ret:%x\n", ret);
8223ba6841SJoseph Chen 	return ret & 0xFF;
8323ba6841SJoseph Chen }
8423ba6841SJoseph Chen 
fixPath(char * path)8523ba6841SJoseph Chen static inline void fixPath(char *path)
8623ba6841SJoseph Chen {
8723ba6841SJoseph Chen 	int i, len = strlen(path);
8823ba6841SJoseph Chen 	char tmp[MAX_LINE_LEN];
8923ba6841SJoseph Chen 	char *start, *end;
9023ba6841SJoseph Chen 
9123ba6841SJoseph Chen 	for (i = 0; i < len; i++) {
9223ba6841SJoseph Chen 		if (path[i] == '\\')
9323ba6841SJoseph Chen 			path[i] = '/';
9423ba6841SJoseph Chen 		else if (path[i] == '\r' || path[i] == '\n')
9523ba6841SJoseph Chen 			path[i] = '\0';
9623ba6841SJoseph Chen 	}
9723ba6841SJoseph Chen 
9823ba6841SJoseph Chen 	if (gLegacyPath && gNewPath) {
9923ba6841SJoseph Chen 		start = strstr(path, gLegacyPath);
10023ba6841SJoseph Chen 		if (start) {
10123ba6841SJoseph Chen 			end = start + strlen(gLegacyPath);
10223ba6841SJoseph Chen 			/* Backup, so tmp can be src for strcat() */
10323ba6841SJoseph Chen 			strcpy(tmp, end);
10423ba6841SJoseph Chen 			/* Terminate, so path can be dest for strcat() */
10523ba6841SJoseph Chen 			*start = '\0';
10645c2a034SJoseph Chen 			strcat(path, gNewPath);
10723ba6841SJoseph Chen 			strcat(path, tmp);
1089ad3008aSJoseph Chen 		} else {
1099ad3008aSJoseph Chen 			strcpy(tmp, path);
1109ad3008aSJoseph Chen 			strcpy(path, gNewPath);
1119ad3008aSJoseph Chen 			strcat(path, tmp);
11223ba6841SJoseph Chen 		}
1135f0203b7SJoseph Chen 	} else if ((ulong)path != (ulong)gOpts.outPath && /* ignore output */
1145f0203b7SJoseph Chen 		   gPrePath && strncmp(path, gPrePath, strlen(gPrePath))) {
115e311da24SJoseph Chen 		strcpy(tmp, path);
116e311da24SJoseph Chen 		strcpy(path, gPrePath);
117e311da24SJoseph Chen 		strcat(path, tmp);
11823ba6841SJoseph Chen 	}
11923ba6841SJoseph Chen }
12023ba6841SJoseph Chen 
parseVersion(FILE * file)12123ba6841SJoseph Chen static bool parseVersion(FILE *file)
12223ba6841SJoseph Chen {
12323ba6841SJoseph Chen 	int d = 0;
12423ba6841SJoseph Chen 
12523ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
12623ba6841SJoseph Chen 		return false;
12723ba6841SJoseph Chen 	}
12823ba6841SJoseph Chen 	if (fscanf(file, OPT_MAJOR "=%d", &d) != 1)
12923ba6841SJoseph Chen 		return false;
13023ba6841SJoseph Chen 	gOpts.major = (uint16_t) d;
13123ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
13223ba6841SJoseph Chen 		return false;
13323ba6841SJoseph Chen 	}
13423ba6841SJoseph Chen 	if (fscanf(file, OPT_MINOR "=%d", &d) != 1)
13523ba6841SJoseph Chen 		return false;
13623ba6841SJoseph Chen 	gOpts.minor = (uint16_t) d;
13723ba6841SJoseph Chen 	LOGD("major:%d, minor:%d\n", gOpts.major, gOpts.minor);
13823ba6841SJoseph Chen 	return true;
13923ba6841SJoseph Chen }
14023ba6841SJoseph Chen 
parseBL3x(FILE * file,int bl3x_id)14123ba6841SJoseph Chen static bool parseBL3x(FILE *file, int bl3x_id)
14223ba6841SJoseph Chen {
14323ba6841SJoseph Chen 	int pos;
14423ba6841SJoseph Chen 	int sec;
14523ba6841SJoseph Chen 	char buf[MAX_LINE_LEN];
14623ba6841SJoseph Chen 	bl_entry_t *pbl3x = NULL;
14723ba6841SJoseph Chen 
14823ba6841SJoseph Chen 	if (bl3x_id >= BL_MAX_SEC) {
14923ba6841SJoseph Chen 		return false;
15023ba6841SJoseph Chen 	}
15123ba6841SJoseph Chen 
15223ba6841SJoseph Chen 	pbl3x = &gOpts.bl3x[bl3x_id];
15323ba6841SJoseph Chen 
15423ba6841SJoseph Chen 	/* SEC */
15523ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
15623ba6841SJoseph Chen 		return false;
15723ba6841SJoseph Chen 	}
15823ba6841SJoseph Chen 	if (fscanf(file, OPT_SEC "=%d", &sec) != 1) {
15923ba6841SJoseph Chen 		return false;
16023ba6841SJoseph Chen 	}
16123ba6841SJoseph Chen 	if ((gSubfix) && (bl3x_id == BL32_SEC)) {
16223ba6841SJoseph Chen 		if (sec == 0) {
16323ba6841SJoseph Chen 			sec = 1;
16423ba6841SJoseph Chen 			printf("BL3%d adjust sec from 0 to 1\n", bl3x_id);
16523ba6841SJoseph Chen 		}
16675828958SJoseph Chen 	} else if (gIgnoreBL32 && (bl3x_id == BL32_SEC)) {
16775828958SJoseph Chen 		if (sec == 1) {
16875828958SJoseph Chen 			sec = 0;
16975828958SJoseph Chen 			printf("BL3%d adjust sec from 1 to 0\n", bl3x_id);
17075828958SJoseph Chen 		}
17123ba6841SJoseph Chen 	}
17223ba6841SJoseph Chen 	pbl3x->sec = sec;
17323ba6841SJoseph Chen 	LOGD("bl3%d sec: %d\n", bl3x_id, pbl3x->sec);
17423ba6841SJoseph Chen 
17523ba6841SJoseph Chen 	/* PATH */
17623ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
17723ba6841SJoseph Chen 		return false;
17823ba6841SJoseph Chen 	}
17923ba6841SJoseph Chen 	memset(buf, 0, MAX_LINE_LEN);
18023ba6841SJoseph Chen 	if (fscanf(file, OPT_PATH "=%s", buf) != 1) {
18123ba6841SJoseph Chen 		if (pbl3x->sec)
18223ba6841SJoseph Chen 			return false;
18323ba6841SJoseph Chen 	} else {
18423ba6841SJoseph Chen 		if (strlen(buf) != 0) {
18523ba6841SJoseph Chen 			fixPath(buf);
18623ba6841SJoseph Chen 			strcpy(pbl3x->path, buf);
18723ba6841SJoseph Chen 			LOGD("bl3%d path:%s\n", bl3x_id, pbl3x->path);
18823ba6841SJoseph Chen 		}
18923ba6841SJoseph Chen 	}
19023ba6841SJoseph Chen 
19123ba6841SJoseph Chen 	/* ADDR */
19223ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
19323ba6841SJoseph Chen 		return false;
19423ba6841SJoseph Chen 	}
19523ba6841SJoseph Chen 	memset(buf, 0, MAX_LINE_LEN);
19623ba6841SJoseph Chen 	if (fscanf(file, OPT_ADDR "=%s", buf) != 1) {
19723ba6841SJoseph Chen 		if (pbl3x->sec)
19823ba6841SJoseph Chen 			return false;
19923ba6841SJoseph Chen 	} else {
20023ba6841SJoseph Chen 		if (strlen(buf) != 0) {
20123ba6841SJoseph Chen 			pbl3x->addr = strtoul(buf, NULL, 16);
20223ba6841SJoseph Chen 			LOGD("bl3%d addr:0x%x\n", bl3x_id, pbl3x->addr);
20323ba6841SJoseph Chen 		}
20423ba6841SJoseph Chen 	}
20523ba6841SJoseph Chen 
20623ba6841SJoseph Chen 	pos = ftell(file);
20723ba6841SJoseph Chen 	if (pos < 0) {
20823ba6841SJoseph Chen 		return false;
20923ba6841SJoseph Chen 	}
21023ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
21123ba6841SJoseph Chen 		return false;
21223ba6841SJoseph Chen 	}
21323ba6841SJoseph Chen 
21423ba6841SJoseph Chen 	return true;
21523ba6841SJoseph Chen }
21623ba6841SJoseph Chen 
parseOut(FILE * file)21723ba6841SJoseph Chen static bool parseOut(FILE *file)
21823ba6841SJoseph Chen {
21923ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
22023ba6841SJoseph Chen 		return false;
22123ba6841SJoseph Chen 	}
22223ba6841SJoseph Chen 	if (fscanf(file, OPT_OUT_PATH "=%[^\r^\n]", gOpts.outPath) != 1)
22323ba6841SJoseph Chen 		return false;
2245f0203b7SJoseph Chen 	/* fixPath(gOpts.outPath); */
22523ba6841SJoseph Chen 	printf("out:%s\n", gOpts.outPath);
22623ba6841SJoseph Chen 
22723ba6841SJoseph Chen 	return true;
22823ba6841SJoseph Chen }
22923ba6841SJoseph Chen 
printOpts(FILE * out)23023ba6841SJoseph Chen void printOpts(FILE *out)
23123ba6841SJoseph Chen {
23223ba6841SJoseph Chen 	fprintf(out, SEC_BL30 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL30_SEC].sec);
23323ba6841SJoseph Chen 	if (gOpts.bl3x[BL30_SEC].sec) {
23423ba6841SJoseph Chen 		fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL30_SEC].path);
23523ba6841SJoseph Chen 		fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL30_SEC].addr);
23623ba6841SJoseph Chen 	}
23723ba6841SJoseph Chen 
23823ba6841SJoseph Chen 	fprintf(out, SEC_BL31 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL31_SEC].sec);
23923ba6841SJoseph Chen 	if (gOpts.bl3x[BL31_SEC].sec) {
24023ba6841SJoseph Chen 		fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL31_SEC].path);
24123ba6841SJoseph Chen 		fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL31_SEC].addr);
24223ba6841SJoseph Chen 	}
24323ba6841SJoseph Chen 
24423ba6841SJoseph Chen 	fprintf(out, SEC_BL32 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL32_SEC].sec);
24523ba6841SJoseph Chen 	if (gOpts.bl3x[BL32_SEC].sec) {
24623ba6841SJoseph Chen 		fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL32_SEC].path);
24723ba6841SJoseph Chen 		fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL32_SEC].addr);
24823ba6841SJoseph Chen 	}
24923ba6841SJoseph Chen 
25023ba6841SJoseph Chen 	fprintf(out, SEC_BL33 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL33_SEC].sec);
25123ba6841SJoseph Chen 	if (gOpts.bl3x[BL33_SEC].sec) {
25223ba6841SJoseph Chen 		fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL33_SEC].path);
25323ba6841SJoseph Chen 		fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL33_SEC].addr);
25423ba6841SJoseph Chen 	}
25523ba6841SJoseph Chen 
25623ba6841SJoseph Chen 	fprintf(out, SEC_OUT "\n" OPT_OUT_PATH "=%s\n", gOpts.outPath);
25723ba6841SJoseph Chen }
25823ba6841SJoseph Chen 
parseOpts(void)25923ba6841SJoseph Chen static bool parseOpts(void)
26023ba6841SJoseph Chen {
26123ba6841SJoseph Chen 	FILE *file = NULL;
26223ba6841SJoseph Chen 	char *configPath = (gConfigPath == NULL) ? DEF_CONFIG_FILE : gConfigPath;
26323ba6841SJoseph Chen 	bool bl30ok = false, bl31ok = false, bl32ok = false, bl33ok = false;
26423ba6841SJoseph Chen 	bool outOk = false;
26523ba6841SJoseph Chen 	bool versionOk = false;
26623ba6841SJoseph Chen 	char buf[MAX_LINE_LEN];
26723ba6841SJoseph Chen 	bool ret = false;
26823ba6841SJoseph Chen 
26923ba6841SJoseph Chen 	file = fopen(configPath, "r");
27023ba6841SJoseph Chen 	if (!file) {
27123ba6841SJoseph Chen 		fprintf(stderr, "config(%s) not found!\n", configPath);
27223ba6841SJoseph Chen 		if (configPath == (char *)DEF_CONFIG_FILE) {
27323ba6841SJoseph Chen 			file = fopen(DEF_CONFIG_FILE, "w");
27423ba6841SJoseph Chen 			if (file) {
27523ba6841SJoseph Chen 				fprintf(stderr, "create defconfig\n");
27623ba6841SJoseph Chen 				printOpts(file);
27723ba6841SJoseph Chen 			}
27823ba6841SJoseph Chen 		}
27923ba6841SJoseph Chen 		goto end;
28023ba6841SJoseph Chen 	}
28123ba6841SJoseph Chen 
28223ba6841SJoseph Chen 	LOGD("start parse\n");
28323ba6841SJoseph Chen 
28423ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
28523ba6841SJoseph Chen 		goto end;
28623ba6841SJoseph Chen 	}
28723ba6841SJoseph Chen 	while (fscanf(file, "%s", buf) == 1) {
28823ba6841SJoseph Chen 		if (!strcmp(buf, SEC_VERSION)) {
28923ba6841SJoseph Chen 			versionOk = parseVersion(file);
29023ba6841SJoseph Chen 			if (!versionOk) {
29123ba6841SJoseph Chen 				LOGE("parseVersion failed!\n");
29223ba6841SJoseph Chen 				goto end;
29323ba6841SJoseph Chen 			}
29423ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_BL30)) {
29523ba6841SJoseph Chen 			bl30ok = parseBL3x(file, BL30_SEC);
29623ba6841SJoseph Chen 			if (!bl30ok) {
29723ba6841SJoseph Chen 				LOGE("parseBL30 failed!\n");
29823ba6841SJoseph Chen 				goto end;
29923ba6841SJoseph Chen 			}
30023ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_BL31)) {
30123ba6841SJoseph Chen 			bl31ok = parseBL3x(file, BL31_SEC);
30223ba6841SJoseph Chen 			if (!bl31ok) {
30323ba6841SJoseph Chen 				LOGE("parseBL31 failed!\n");
30423ba6841SJoseph Chen 				goto end;
30523ba6841SJoseph Chen 			}
30623ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_BL32)) {
30723ba6841SJoseph Chen 			bl32ok = parseBL3x(file, BL32_SEC);
30823ba6841SJoseph Chen 			if (!bl32ok) {
30923ba6841SJoseph Chen 				LOGE("parseBL32 failed!\n");
31023ba6841SJoseph Chen 				goto end;
31123ba6841SJoseph Chen 			}
31223ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_BL33)) {
31323ba6841SJoseph Chen 			bl33ok = parseBL3x(file, BL33_SEC);
31423ba6841SJoseph Chen 			if (!bl33ok) {
31523ba6841SJoseph Chen 				LOGE("parseBL33 failed!\n");
31623ba6841SJoseph Chen 				goto end;
31723ba6841SJoseph Chen 			}
31823ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_OUT)) {
31923ba6841SJoseph Chen 			outOk = parseOut(file);
32023ba6841SJoseph Chen 			if (!outOk) {
32123ba6841SJoseph Chen 				LOGE("parseOut failed!\n");
32223ba6841SJoseph Chen 				goto end;
32323ba6841SJoseph Chen 			}
32423ba6841SJoseph Chen 		} else if (buf[0] == '#') {
32523ba6841SJoseph Chen 			continue;
32623ba6841SJoseph Chen 		} else {
3270600347bSJoseph Chen 			LOGD("unknown sec: %s!\n", buf);
3280600347bSJoseph Chen 			continue;
32923ba6841SJoseph Chen 		}
33023ba6841SJoseph Chen 		if (SCANF_EAT(file) != 0) {
33123ba6841SJoseph Chen 			goto end;
33223ba6841SJoseph Chen 		}
33323ba6841SJoseph Chen 	}
33423ba6841SJoseph Chen 
33523ba6841SJoseph Chen 	if (bl30ok && bl31ok && bl32ok && bl33ok && outOk)
33623ba6841SJoseph Chen 		ret = true;
33723ba6841SJoseph Chen end:
33823ba6841SJoseph Chen 	if (file)
33923ba6841SJoseph Chen 		fclose(file);
34023ba6841SJoseph Chen 
34123ba6841SJoseph Chen 	return ret;
34223ba6841SJoseph Chen }
34323ba6841SJoseph Chen 
initOpts(void)34423ba6841SJoseph Chen bool initOpts(void)
34523ba6841SJoseph Chen {
34623ba6841SJoseph Chen 
34723ba6841SJoseph Chen 	memset(&gOpts, 0, sizeof(gOpts));
34823ba6841SJoseph Chen 
34923ba6841SJoseph Chen 	gOpts.major = DEF_MAJOR;
35023ba6841SJoseph Chen 	gOpts.minor = DEF_MINOR;
35123ba6841SJoseph Chen 
35223ba6841SJoseph Chen 	memcpy(&gOpts.bl3x[BL30_SEC].id, gBl3xID[BL30_SEC], 4);
35323ba6841SJoseph Chen 	strcpy(gOpts.bl3x[BL30_SEC].path, DEF_BL30_PATH);
35423ba6841SJoseph Chen 
35523ba6841SJoseph Chen 	memcpy(&gOpts.bl3x[BL31_SEC].id, gBl3xID[BL31_SEC], 4);
35623ba6841SJoseph Chen 	strcpy(gOpts.bl3x[BL31_SEC].path, DEF_BL31_PATH);
35723ba6841SJoseph Chen 
35823ba6841SJoseph Chen 	memcpy(&gOpts.bl3x[BL32_SEC].id, gBl3xID[BL32_SEC], 4);
35923ba6841SJoseph Chen 	strcpy(gOpts.bl3x[BL32_SEC].path, DEF_BL32_PATH);
36023ba6841SJoseph Chen 
36123ba6841SJoseph Chen 	memcpy(&gOpts.bl3x[BL33_SEC].id, gBl3xID[BL33_SEC], 4);
36223ba6841SJoseph Chen 	strcpy(gOpts.bl3x[BL33_SEC].path, DEF_BL33_PATH);
36323ba6841SJoseph Chen 
36423ba6841SJoseph Chen 	strcpy(gOpts.outPath, DEF_OUT_PATH);
36523ba6841SJoseph Chen 
36623ba6841SJoseph Chen 	return parseOpts();
36723ba6841SJoseph Chen }
36823ba6841SJoseph Chen 
getFileSize(const char * path,uint32_t * size)36923ba6841SJoseph Chen static inline bool getFileSize(const char *path, uint32_t *size)
37023ba6841SJoseph Chen {
37123ba6841SJoseph Chen 	struct stat st;
37223ba6841SJoseph Chen 
37323ba6841SJoseph Chen 	if (stat(path, &st) < 0)
37423ba6841SJoseph Chen 		return false;
37523ba6841SJoseph Chen 	*size = st.st_size;
37623ba6841SJoseph Chen 	LOGD("path:%s, size:%d\n", path, *size);
37723ba6841SJoseph Chen 	return true;
37823ba6841SJoseph Chen }
37923ba6841SJoseph Chen 
fill_file(FILE * file,char ch,uint32_t fill_size)38023ba6841SJoseph Chen void fill_file(FILE *file, char ch, uint32_t fill_size)
38123ba6841SJoseph Chen {
38223ba6841SJoseph Chen 	uint8_t fill_buffer[1024];
38323ba6841SJoseph Chen 	uint32_t cur_write;
38423ba6841SJoseph Chen 
38523ba6841SJoseph Chen 	memset(fill_buffer, ch, 1024);
38623ba6841SJoseph Chen 	while (fill_size > 0) {
38723ba6841SJoseph Chen 		cur_write = (fill_size >= 1024) ? 1024 : fill_size;
38823ba6841SJoseph Chen 		fwrite(fill_buffer, 1, cur_write, file);
38923ba6841SJoseph Chen 		fill_size -= cur_write;
39023ba6841SJoseph Chen 	}
39123ba6841SJoseph Chen }
39223ba6841SJoseph Chen 
filter_elf(uint32_t index,uint8_t * pMeta,uint32_t * pMetaNum,bool * bElf)39323ba6841SJoseph Chen bool filter_elf(uint32_t index, uint8_t *pMeta, uint32_t *pMetaNum,
39423ba6841SJoseph Chen                 bool *bElf)
39523ba6841SJoseph Chen {
39623ba6841SJoseph Chen 	bool ret = false;
39723ba6841SJoseph Chen 	FILE *file = NULL;
39823ba6841SJoseph Chen 	uint8_t *file_buffer = NULL;
39923ba6841SJoseph Chen 	uint32_t file_size, read_size, i;
40023ba6841SJoseph Chen 	Elf32_Ehdr *pElfHeader32;
40123ba6841SJoseph Chen 	Elf32_Phdr *pElfProgram32;
40223ba6841SJoseph Chen 	Elf64_Ehdr *pElfHeader64;
40323ba6841SJoseph Chen 	Elf64_Phdr *pElfProgram64;
40423ba6841SJoseph Chen 	bl_entry_t *pEntry = (bl_entry_t *)(pMeta + sizeof(bl_entry_t) * (*pMetaNum));
40523ba6841SJoseph Chen 	LOGD("index=%d,file=%s\n", index, gOpts.bl3x[index].path);
40623ba6841SJoseph Chen 
40723ba6841SJoseph Chen 	if (!getFileSize(gOpts.bl3x[index].path, &file_size))
40823ba6841SJoseph Chen 		goto exit_fileter_elf;
40923ba6841SJoseph Chen 	file = fopen(gOpts.bl3x[index].path, "rb");
41023ba6841SJoseph Chen 	if (!file) {
41123ba6841SJoseph Chen 		LOGE("open file(%s) failed\n", gOpts.bl3x[index].path);
41223ba6841SJoseph Chen 		goto exit_fileter_elf;
41323ba6841SJoseph Chen 	}
41423ba6841SJoseph Chen 	file_buffer = malloc(file_size);
41523ba6841SJoseph Chen 	if (!file_buffer)
41623ba6841SJoseph Chen 		goto exit_fileter_elf;
41723ba6841SJoseph Chen 	read_size = fread(file_buffer, 1, file_size, file);
41823ba6841SJoseph Chen 	if (read_size != file_size)
41923ba6841SJoseph Chen 		goto exit_fileter_elf;
42023ba6841SJoseph Chen 
42123ba6841SJoseph Chen 	if (*((uint32_t *)file_buffer) != ELF_MAGIC) {
42223ba6841SJoseph Chen 		ret = true;
42323ba6841SJoseph Chen 		*bElf = false;
42423ba6841SJoseph Chen 		goto exit_fileter_elf;
42523ba6841SJoseph Chen 	}
42623ba6841SJoseph Chen 	*bElf = true;
42723ba6841SJoseph Chen 	if (file_buffer[5] != 1) { /* only support little endian */
42823ba6841SJoseph Chen 		goto exit_fileter_elf;
42923ba6841SJoseph Chen 	}
43023ba6841SJoseph Chen 	if (*((uint16_t *)(file_buffer + EI_NIDENT)) !=
43123ba6841SJoseph Chen 	    2) { /* only support executable case */
43223ba6841SJoseph Chen 		goto exit_fileter_elf;
43323ba6841SJoseph Chen 	}
43423ba6841SJoseph Chen 
43523ba6841SJoseph Chen 	if (file_buffer[4] == 2) {
43623ba6841SJoseph Chen 		pElfHeader64 = (Elf64_Ehdr *)file_buffer;
43723ba6841SJoseph Chen 		for (i = 0; i < pElfHeader64->e_phnum; i++) {
43823ba6841SJoseph Chen 			pElfProgram64 = (Elf64_Phdr *)(file_buffer + pElfHeader64->e_phoff +
43923ba6841SJoseph Chen 			                               i * pElfHeader64->e_phentsize);
44023ba6841SJoseph Chen 			if (pElfProgram64->p_type == 1) { /* PT_LOAD */
44123ba6841SJoseph Chen 				pEntry->id = gOpts.bl3x[index].id;
44223ba6841SJoseph Chen 				strcpy(pEntry->path, gOpts.bl3x[index].path);
44323ba6841SJoseph Chen 				pEntry->size = (uint32_t) pElfProgram64->p_filesz;
44423ba6841SJoseph Chen 				pEntry->offset = (uint32_t) pElfProgram64->p_offset;
44523ba6841SJoseph Chen 				pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN);
446*02c35d15SJoseph Chen 				pEntry->addr = (uint32_t) pElfProgram64->p_paddr;
44723ba6841SJoseph Chen 				if (pEntry->align_size > BL3X_FILESIZE_MAX) {
44823ba6841SJoseph Chen 					LOGE("elf_file %s too large,segment=%d.\n", pEntry->path, i);
44923ba6841SJoseph Chen 					goto exit_fileter_elf;
45023ba6841SJoseph Chen 				}
45123ba6841SJoseph Chen 				LOGD("bl3%d: filesize = %d, imagesize = %d, segment=%d\n", index,
45223ba6841SJoseph Chen 				     pEntry->size, pEntry->align_size, i);
45323ba6841SJoseph Chen 				pEntry++;
45423ba6841SJoseph Chen 				(*pMetaNum)++;
45523ba6841SJoseph Chen 			}
45623ba6841SJoseph Chen 		}
45723ba6841SJoseph Chen 
45823ba6841SJoseph Chen 	} else {
45923ba6841SJoseph Chen 		pElfHeader32 = (Elf32_Ehdr *)file_buffer;
46023ba6841SJoseph Chen 		for (i = 0; i < pElfHeader32->e_phnum; i++) {
46123ba6841SJoseph Chen 			pElfProgram32 = (Elf32_Phdr *)(file_buffer + pElfHeader32->e_phoff +
46223ba6841SJoseph Chen 			                               i * pElfHeader32->e_phentsize);
46323ba6841SJoseph Chen 			if (pElfProgram32->p_type == 1) { /* PT_LOAD */
46423ba6841SJoseph Chen 				pEntry->id = gOpts.bl3x[index].id;
46523ba6841SJoseph Chen 				strcpy(pEntry->path, gOpts.bl3x[index].path);
46623ba6841SJoseph Chen 				pEntry->size = pElfProgram32->p_filesz;
46723ba6841SJoseph Chen 				pEntry->offset = pElfProgram32->p_offset;
46823ba6841SJoseph Chen 				pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN);
469*02c35d15SJoseph Chen 				pEntry->addr = pElfProgram32->p_paddr;
47023ba6841SJoseph Chen 				if (pEntry->align_size > BL3X_FILESIZE_MAX) {
47123ba6841SJoseph Chen 					LOGE("elf_file %s too large,segment=%d.\n", pEntry->path, i);
47223ba6841SJoseph Chen 					goto exit_fileter_elf;
47323ba6841SJoseph Chen 				}
47423ba6841SJoseph Chen 				LOGD("bl3%d: filesize = %d, imagesize = %d, segment=%d\n", index,
47523ba6841SJoseph Chen 				     pEntry->size, pEntry->align_size, i);
47623ba6841SJoseph Chen 				pEntry++;
47723ba6841SJoseph Chen 				(*pMetaNum)++;
47823ba6841SJoseph Chen 			}
47923ba6841SJoseph Chen 		}
48023ba6841SJoseph Chen 	}
48123ba6841SJoseph Chen 	ret = true;
48223ba6841SJoseph Chen exit_fileter_elf:
48323ba6841SJoseph Chen 	if (file)
48423ba6841SJoseph Chen 		fclose(file);
48523ba6841SJoseph Chen 	if (file_buffer)
48623ba6841SJoseph Chen 		free(file_buffer);
48723ba6841SJoseph Chen 	return ret;
48823ba6841SJoseph Chen }
48923ba6841SJoseph Chen 
49023ba6841SJoseph Chen #define SHA256_CHECK_SZ ((uint32_t)(256 * 1024))
bl3xHash256(uint8_t * pHash,uint8_t * pData,uint32_t nDataSize)49123ba6841SJoseph Chen static bool bl3xHash256(uint8_t *pHash, uint8_t *pData, uint32_t nDataSize)
49223ba6841SJoseph Chen {
49323ba6841SJoseph Chen 	uint32_t nHashSize, nHasHashSize;
49423ba6841SJoseph Chen 
49523ba6841SJoseph Chen 	if (!pHash || !pData || !nDataSize) {
49623ba6841SJoseph Chen 		return false;
49723ba6841SJoseph Chen 	}
49823ba6841SJoseph Chen 
49923ba6841SJoseph Chen 	nHasHashSize = 0;
50023ba6841SJoseph Chen 
50123ba6841SJoseph Chen 	if (gSHAmode == SHA_SEL_256_RK) {
50223ba6841SJoseph Chen 		sha256_ctx ctx;
50323ba6841SJoseph Chen 
50423ba6841SJoseph Chen 		sha256_begin(&ctx);
50523ba6841SJoseph Chen 		while (nDataSize > 0) {
50623ba6841SJoseph Chen 			nHashSize = (nDataSize >= SHA256_CHECK_SZ) ? SHA256_CHECK_SZ : nDataSize;
50723ba6841SJoseph Chen 			sha256_hash(&ctx, pData + nHasHashSize, nHashSize);
50823ba6841SJoseph Chen 			nHasHashSize += nHashSize;
50923ba6841SJoseph Chen 			nDataSize -= nHashSize;
51023ba6841SJoseph Chen 		}
51123ba6841SJoseph Chen 		sha256_end(&ctx, pHash);
51223ba6841SJoseph Chen 	} else {
51323ba6841SJoseph Chen 		sha256_context ctx;
51423ba6841SJoseph Chen 
51523ba6841SJoseph Chen 		sha256_starts(&ctx);
51623ba6841SJoseph Chen 		while (nDataSize > 0) {
51723ba6841SJoseph Chen 			nHashSize = (nDataSize >= SHA256_CHECK_SZ) ? SHA256_CHECK_SZ : nDataSize;
51823ba6841SJoseph Chen 			sha256_update(&ctx, pData + nHasHashSize, nHashSize);
51923ba6841SJoseph Chen 			nHasHashSize += nHashSize;
52023ba6841SJoseph Chen 			nDataSize -= nHashSize;
52123ba6841SJoseph Chen 		}
52223ba6841SJoseph Chen 		sha256_finish(&ctx, pHash);
52323ba6841SJoseph Chen 	}
52423ba6841SJoseph Chen 	return true;
52523ba6841SJoseph Chen }
52623ba6841SJoseph Chen 
mergetrust(void)52723ba6841SJoseph Chen static bool mergetrust(void)
52823ba6841SJoseph Chen {
52923ba6841SJoseph Chen 	FILE *outFile = NULL;
53023ba6841SJoseph Chen 	uint32_t OutFileSize;
53123ba6841SJoseph Chen 	uint32_t SrcFileNum, SignOffset, nComponentNum;
53223ba6841SJoseph Chen 	TRUST_HEADER *pHead = NULL;
53323ba6841SJoseph Chen 	COMPONENT_DATA *pComponentData = NULL;
53423ba6841SJoseph Chen 	TRUST_COMPONENT *pComponent = NULL;
53523ba6841SJoseph Chen 	bool ret = false, bElf;
53623ba6841SJoseph Chen 	uint32_t i, n;
53723ba6841SJoseph Chen 	uint8_t *outBuf = NULL, *pbuf = NULL, *pMetaBuf = NULL;
53823ba6841SJoseph Chen 	bl_entry_t *pEntry = NULL;
53923ba6841SJoseph Chen 	if (!initOpts())
54023ba6841SJoseph Chen 		return false;
54123ba6841SJoseph Chen 
54223ba6841SJoseph Chen 	if (gDebug) {
54323ba6841SJoseph Chen 		printf("---------------\nUSING CONFIG:\n");
54423ba6841SJoseph Chen 		printOpts(stdout);
54523ba6841SJoseph Chen 		printf("---------------\n\n");
54623ba6841SJoseph Chen 	}
54723ba6841SJoseph Chen 	pMetaBuf = malloc(sizeof(bl_entry_t) * 32);
54823ba6841SJoseph Chen 	if (!pMetaBuf) {
54923ba6841SJoseph Chen 		LOGE("Merge trust image: malloc buffer error.\n");
55023ba6841SJoseph Chen 		goto end;
55123ba6841SJoseph Chen 	}
55223ba6841SJoseph Chen 
55323ba6841SJoseph Chen 	nComponentNum = SrcFileNum = 0;
55423ba6841SJoseph Chen 	for (i = BL30_SEC; i < BL_MAX_SEC; i++) {
55523ba6841SJoseph Chen 		if (gOpts.bl3x[i].sec) {
55623ba6841SJoseph Chen 			if (!filter_elf(i, pMetaBuf, &nComponentNum, &bElf)) {
55723ba6841SJoseph Chen 				LOGE("filter_elf %s file failed\n", gOpts.bl3x[i].path);
55823ba6841SJoseph Chen 				goto end;
55923ba6841SJoseph Chen 			}
56023ba6841SJoseph Chen 			if (!bElf) {
56123ba6841SJoseph Chen 				pEntry = (bl_entry_t *)(pMetaBuf + sizeof(bl_entry_t) * nComponentNum);
56223ba6841SJoseph Chen 				pEntry->id = gOpts.bl3x[i].id;
56323ba6841SJoseph Chen 				strcpy(pEntry->path, gOpts.bl3x[i].path);
56423ba6841SJoseph Chen 				getFileSize(pEntry->path, &pEntry->size);
56523ba6841SJoseph Chen 				pEntry->offset = 0;
56623ba6841SJoseph Chen 				pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN);
56723ba6841SJoseph Chen 				pEntry->addr = gOpts.bl3x[i].addr;
56823ba6841SJoseph Chen 				if (pEntry->align_size > BL3X_FILESIZE_MAX) {
56923ba6841SJoseph Chen 					LOGE("file %s too large.\n", gOpts.bl3x[i].path);
57023ba6841SJoseph Chen 					goto end;
57123ba6841SJoseph Chen 				}
57223ba6841SJoseph Chen 				LOGD("bl3%d: filesize = %d, imagesize = %d\n", i, pEntry->size,
57323ba6841SJoseph Chen 				     pEntry->align_size);
57423ba6841SJoseph Chen 				pEntry++;
57523ba6841SJoseph Chen 				nComponentNum++;
57623ba6841SJoseph Chen 			}
57723ba6841SJoseph Chen 
57823ba6841SJoseph Chen 		}
57923ba6841SJoseph Chen 	}
58023ba6841SJoseph Chen 	LOGD("bl3x bin sec = %d\n", nComponentNum);
58123ba6841SJoseph Chen 
58223ba6841SJoseph Chen 	/* 2048bytes for head */
58323ba6841SJoseph Chen 	memset(gBuf, 0, TRUST_HEADER_SIZE);
58423ba6841SJoseph Chen 
58523ba6841SJoseph Chen 	/* Trust Head */
58623ba6841SJoseph Chen 	pHead = (TRUST_HEADER *)gBuf;
58723ba6841SJoseph Chen 	memcpy(&pHead->tag, TRUST_HEAD_TAG, 4);
58823ba6841SJoseph Chen 	pHead->version = (getBCD(gOpts.major) << 8) | getBCD(gOpts.minor);
58923ba6841SJoseph Chen 	pHead->flags = 0;
59023ba6841SJoseph Chen 	pHead->flags |= (gSHAmode << 0);
59123ba6841SJoseph Chen 	pHead->flags |= (gRSAmode << 4);
59223ba6841SJoseph Chen 
59323ba6841SJoseph Chen 	SignOffset = sizeof(TRUST_HEADER) + nComponentNum * sizeof(COMPONENT_DATA);
59423ba6841SJoseph Chen 	LOGD("trust bin sign offset = %d\n", SignOffset);
59523ba6841SJoseph Chen 	pHead->size = (nComponentNum << 16) | (SignOffset >> 2);
59623ba6841SJoseph Chen 
59723ba6841SJoseph Chen 	pComponent = (TRUST_COMPONENT *)(gBuf + SignOffset + SIGNATURE_SIZE);
59823ba6841SJoseph Chen 	pComponentData = (COMPONENT_DATA *)(gBuf + sizeof(TRUST_HEADER));
59923ba6841SJoseph Chen 
60023ba6841SJoseph Chen 	OutFileSize = TRUST_HEADER_SIZE;
60123ba6841SJoseph Chen 	pEntry = (bl_entry_t *)pMetaBuf;
60223ba6841SJoseph Chen 	for (i = 0; i < nComponentNum; i++) {
60323ba6841SJoseph Chen 		/* bl3x load and run address */
60423ba6841SJoseph Chen 		pComponentData->LoadAddr = pEntry->addr;
60523ba6841SJoseph Chen 
60623ba6841SJoseph Chen 		pComponent->ComponentID = pEntry->id;
60723ba6841SJoseph Chen 		pComponent->StorageAddr = (OutFileSize >> 9);
60823ba6841SJoseph Chen 		pComponent->ImageSize = (pEntry->align_size >> 9);
6095033bc62Szain wang 		pComponentData->LoadSize = pComponent->ImageSize;
61023ba6841SJoseph Chen 
61123ba6841SJoseph Chen 		LOGD("bl3%c: LoadAddr = 0x%08x, StorageAddr = %d, ImageSize = %d\n",
61223ba6841SJoseph Chen 		     (char)((pEntry->id & 0xFF000000) >> 24), pComponentData->LoadAddr,
61323ba6841SJoseph Chen 		     pComponent->StorageAddr, pComponent->ImageSize);
61423ba6841SJoseph Chen 
61523ba6841SJoseph Chen 		OutFileSize += pEntry->align_size;
61623ba6841SJoseph Chen 		pComponentData++;
61723ba6841SJoseph Chen 		pComponent++;
61823ba6841SJoseph Chen 		pEntry++;
61923ba6841SJoseph Chen 	}
62023ba6841SJoseph Chen 
62123ba6841SJoseph Chen 	/* create out file */
62223ba6841SJoseph Chen 	outFile = fopen(gOpts.outPath, "wb+");
62323ba6841SJoseph Chen 	if (!outFile) {
62423ba6841SJoseph Chen 		LOGE("open out file(%s) failed\n", gOpts.outPath);
62523ba6841SJoseph Chen 
62623ba6841SJoseph Chen 		outFile = fopen(DEF_OUT_PATH, "wb");
62723ba6841SJoseph Chen 		if (!outFile) {
62823ba6841SJoseph Chen 			LOGE("open default out file:%s failed!\n", DEF_OUT_PATH);
62923ba6841SJoseph Chen 			goto end;
63023ba6841SJoseph Chen 		}
63123ba6841SJoseph Chen 	}
63223ba6841SJoseph Chen 
63323ba6841SJoseph Chen 	/* 0 for g_trust_max_num backups */
63423ba6841SJoseph Chen #if 0
63523ba6841SJoseph Chen 	/* save trust head to out file */
63623ba6841SJoseph Chen 	if (!fwrite(gBuf, TRUST_HEADER_SIZE, 1, outFile))
63723ba6841SJoseph Chen 		goto end;
63823ba6841SJoseph Chen 
63923ba6841SJoseph Chen 	/* save trust bl3x bin */
64023ba6841SJoseph Chen 	for (i = BL30_SEC; i < BL_MAX_SEC; i++) {
64123ba6841SJoseph Chen 		if (gOpts.bl3x[i].sec) {
64223ba6841SJoseph Chen 			FILE *inFile = fopen(gOpts.bl3x[i].path, "rb");
64323ba6841SJoseph Chen 			if (!inFile)
64423ba6841SJoseph Chen 				goto end;
64523ba6841SJoseph Chen 
64623ba6841SJoseph Chen 			memset(gBuf, 0, imagesize[i]);
64723ba6841SJoseph Chen 			if (!fread(gBuf, filesize[i], 1, inFile))
64823ba6841SJoseph Chen 				goto end;
64923ba6841SJoseph Chen 			fclose(inFile);
65023ba6841SJoseph Chen 
65123ba6841SJoseph Chen 			if (!fwrite(gBuf, imagesize[i], 1, outFile))
65223ba6841SJoseph Chen 				goto end;
65323ba6841SJoseph Chen 		}
65423ba6841SJoseph Chen 	}
65523ba6841SJoseph Chen #else
65623ba6841SJoseph Chen 	/* check bin size */
65723ba6841SJoseph Chen 	if (OutFileSize > g_trust_max_size) {
65823ba6841SJoseph Chen 		LOGE("Merge trust image: trust bin size overfull.\n");
65923ba6841SJoseph Chen 		goto end;
66023ba6841SJoseph Chen 	}
66123ba6841SJoseph Chen 
66223ba6841SJoseph Chen 	/* malloc buffer */
66323ba6841SJoseph Chen 	pbuf = outBuf = calloc(g_trust_max_size, g_trust_max_num);
66423ba6841SJoseph Chen 	if (!outBuf) {
66523ba6841SJoseph Chen 		LOGE("Merge trust image: calloc buffer error.\n");
66623ba6841SJoseph Chen 		goto end;
66723ba6841SJoseph Chen 	}
66823ba6841SJoseph Chen 	memset(outBuf, 0, (g_trust_max_size * g_trust_max_num));
66923ba6841SJoseph Chen 
67023ba6841SJoseph Chen 	/* save trust head data */
67123ba6841SJoseph Chen 	memcpy(pbuf, gBuf, TRUST_HEADER_SIZE);
67223ba6841SJoseph Chen 	pbuf += TRUST_HEADER_SIZE;
67323ba6841SJoseph Chen 
67423ba6841SJoseph Chen 	uint8_t *pHashData = NULL;
67523ba6841SJoseph Chen 	pComponentData = (COMPONENT_DATA *)(outBuf + sizeof(TRUST_HEADER));
67623ba6841SJoseph Chen 
67723ba6841SJoseph Chen 	/* save trust bl3x bin */
67823ba6841SJoseph Chen 	pEntry = (bl_entry_t *)pMetaBuf;
67923ba6841SJoseph Chen 	for (i = 0; i < nComponentNum; i++) {
68023ba6841SJoseph Chen 		FILE *inFile = fopen(pEntry->path, "rb");
68123ba6841SJoseph Chen 		if (!inFile)
68223ba6841SJoseph Chen 			goto end;
68323ba6841SJoseph Chen 
68423ba6841SJoseph Chen 		memset(gBuf, 0, pEntry->align_size);
68523ba6841SJoseph Chen 		fseek(inFile, pEntry->offset, SEEK_SET);
68623ba6841SJoseph Chen 		if (!fread(gBuf, pEntry->size, 1, inFile))
68723ba6841SJoseph Chen 			goto end;
68823ba6841SJoseph Chen 		fclose(inFile);
68923ba6841SJoseph Chen 
69023ba6841SJoseph Chen 		/* bl3x bin hash256 */
69123ba6841SJoseph Chen 		pHashData = (uint8_t *)&pComponentData->HashData[0];
69223ba6841SJoseph Chen 		bl3xHash256(pHashData, gBuf, pEntry->align_size);
69323ba6841SJoseph Chen 		memcpy(pbuf, gBuf, pEntry->align_size);
69423ba6841SJoseph Chen 
69523ba6841SJoseph Chen 		pComponentData++;
69623ba6841SJoseph Chen 		pbuf += pEntry->align_size;
69723ba6841SJoseph Chen 		pEntry++;
69823ba6841SJoseph Chen 	}
69923ba6841SJoseph Chen 
70023ba6841SJoseph Chen 	/* copy other (g_trust_max_num - 1) backup bin */
70123ba6841SJoseph Chen 	for (n = 1; n < g_trust_max_num; n++) {
70223ba6841SJoseph Chen 		memcpy(outBuf + g_trust_max_size * n, outBuf, g_trust_max_size);
70323ba6841SJoseph Chen 	}
70423ba6841SJoseph Chen 
70523ba6841SJoseph Chen 	/* save date to file */
70623ba6841SJoseph Chen 	if (!fwrite(outBuf, g_trust_max_size * g_trust_max_num, 1, outFile)) {
70723ba6841SJoseph Chen 		LOGE("Merge trust image: write file error.\n");
70823ba6841SJoseph Chen 		goto end;
70923ba6841SJoseph Chen 	}
71023ba6841SJoseph Chen #endif
71123ba6841SJoseph Chen 
71223ba6841SJoseph Chen 	ret = true;
71323ba6841SJoseph Chen 
71423ba6841SJoseph Chen end:
71523ba6841SJoseph Chen 	/*
71623ba6841SJoseph Chen 		for (i = BL30_SEC; i < BL_MAX_SEC; i++) {
71723ba6841SJoseph Chen 			if (gOpts.bl3x[i].sec != false) {
71823ba6841SJoseph Chen 				if (gOpts.bl3x[i].is_elf) {
71923ba6841SJoseph Chen 					if (stat(gOpts.bl3x[i].path, &st) >= 0)
72023ba6841SJoseph Chen 						remove(gOpts.bl3x[i].path);
72123ba6841SJoseph Chen 				}
72223ba6841SJoseph Chen 			}
72323ba6841SJoseph Chen 		}
72423ba6841SJoseph Chen 	*/
72523ba6841SJoseph Chen 	if (pMetaBuf)
72623ba6841SJoseph Chen 		free(pMetaBuf);
72723ba6841SJoseph Chen 	if (outBuf)
72823ba6841SJoseph Chen 		free(outBuf);
72923ba6841SJoseph Chen 	if (outFile)
73023ba6841SJoseph Chen 		fclose(outFile);
73123ba6841SJoseph Chen 	return ret;
73223ba6841SJoseph Chen }
73323ba6841SJoseph Chen 
saveDatatoFile(char * FileName,void * pBuf,uint32_t size)73423ba6841SJoseph Chen static int saveDatatoFile(char *FileName, void *pBuf, uint32_t size)
73523ba6841SJoseph Chen {
73623ba6841SJoseph Chen 	FILE *OutFile = NULL;
73723ba6841SJoseph Chen 	int ret = -1;
73823ba6841SJoseph Chen 
73923ba6841SJoseph Chen 	OutFile = fopen(FileName, "wb");
74023ba6841SJoseph Chen 	if (!OutFile) {
74123ba6841SJoseph Chen 		printf("open OutPutFlie:%s failed!\n", FileName);
74223ba6841SJoseph Chen 		goto end;
74323ba6841SJoseph Chen 	}
74423ba6841SJoseph Chen 	if (1 != fwrite(pBuf, size, 1, OutFile)) {
74523ba6841SJoseph Chen 		printf("write output file failed!\n");
74623ba6841SJoseph Chen 		goto end;
74723ba6841SJoseph Chen 	}
74823ba6841SJoseph Chen 
74923ba6841SJoseph Chen 	ret = 0;
75023ba6841SJoseph Chen end:
75123ba6841SJoseph Chen 	if (OutFile)
75223ba6841SJoseph Chen 		fclose(OutFile);
75323ba6841SJoseph Chen 
75423ba6841SJoseph Chen 	return ret;
75523ba6841SJoseph Chen }
75623ba6841SJoseph Chen 
unpacktrust(char * path)75723ba6841SJoseph Chen static bool unpacktrust(char *path)
75823ba6841SJoseph Chen {
75923ba6841SJoseph Chen 	FILE *FileSrc = NULL;
76023ba6841SJoseph Chen 	uint32_t FileSize;
76123ba6841SJoseph Chen 	uint8_t *pBuf = NULL;
76223ba6841SJoseph Chen 	uint32_t SrcFileNum, SignOffset;
76323ba6841SJoseph Chen 	TRUST_HEADER *pHead = NULL;
76423ba6841SJoseph Chen 	COMPONENT_DATA *pComponentData = NULL;
76523ba6841SJoseph Chen 	TRUST_COMPONENT *pComponent = NULL;
76623ba6841SJoseph Chen 	char str[MAX_LINE_LEN];
76723ba6841SJoseph Chen 	bool ret = false;
76823ba6841SJoseph Chen 	uint32_t i;
76923ba6841SJoseph Chen 
77023ba6841SJoseph Chen 	FileSrc = fopen(path, "rb");
77123ba6841SJoseph Chen 	if (FileSrc == NULL) {
77223ba6841SJoseph Chen 		printf("open %s failed!\n", path);
77323ba6841SJoseph Chen 		goto end;
77423ba6841SJoseph Chen 	}
77523ba6841SJoseph Chen 
77623ba6841SJoseph Chen 	if (getFileSize(path, &FileSize) == false) {
77723ba6841SJoseph Chen 		printf("File Size failed!\n");
77823ba6841SJoseph Chen 		goto end;
77923ba6841SJoseph Chen 	}
78023ba6841SJoseph Chen 	printf("File Size = %d\n", FileSize);
78123ba6841SJoseph Chen 
78223ba6841SJoseph Chen 	pBuf = (uint8_t *)malloc(FileSize);
78323ba6841SJoseph Chen 	if (1 != fread(pBuf, FileSize, 1, FileSrc)) {
78423ba6841SJoseph Chen 		printf("read input file failed!\n");
78523ba6841SJoseph Chen 		goto end;
78623ba6841SJoseph Chen 	}
78723ba6841SJoseph Chen 
78823ba6841SJoseph Chen 	pHead = (TRUST_HEADER *)pBuf;
78923ba6841SJoseph Chen 
79023ba6841SJoseph Chen 	memcpy(str, &pHead->tag, 4);
79123ba6841SJoseph Chen 	str[4] = '\0';
79223ba6841SJoseph Chen 	printf("Header Tag:%s\n", str);
79323ba6841SJoseph Chen 	printf("Header version:%d\n", pHead->version);
79423ba6841SJoseph Chen 	printf("Header flag:%d\n", pHead->flags);
79523ba6841SJoseph Chen 
79623ba6841SJoseph Chen 	SrcFileNum = (pHead->size >> 16) & 0xffff;
79723ba6841SJoseph Chen 	SignOffset = (pHead->size & 0xffff) << 2;
79823ba6841SJoseph Chen 	printf("SrcFileNum:%d\n", SrcFileNum);
79923ba6841SJoseph Chen 	printf("SignOffset:%d\n", SignOffset);
80023ba6841SJoseph Chen 
80123ba6841SJoseph Chen 	pComponent = (TRUST_COMPONENT *)(pBuf + SignOffset + SIGNATURE_SIZE);
80223ba6841SJoseph Chen 	pComponentData = (COMPONENT_DATA *)(pBuf + sizeof(TRUST_HEADER));
80323ba6841SJoseph Chen 
80423ba6841SJoseph Chen 	for (i = 0; i < SrcFileNum; i++) {
80523ba6841SJoseph Chen 		printf("Component %d:\n", i);
80623ba6841SJoseph Chen 
80723ba6841SJoseph Chen 		memcpy(str, &pComponent->ComponentID, 4);
80823ba6841SJoseph Chen 		str[4] = '\0';
80923ba6841SJoseph Chen 		printf("ComponentID:%s\n", str);
81023ba6841SJoseph Chen 		printf("StorageAddr:0x%x\n", pComponent->StorageAddr);
81123ba6841SJoseph Chen 		printf("ImageSize:0x%x\n", pComponent->ImageSize);
81223ba6841SJoseph Chen 		printf("LoadAddr:0x%x\n", pComponentData->LoadAddr);
81323ba6841SJoseph Chen 
81423ba6841SJoseph Chen 		saveDatatoFile(str, pBuf + (pComponent->StorageAddr << 9),
81523ba6841SJoseph Chen 		               pComponent->ImageSize << 9);
81623ba6841SJoseph Chen 
81723ba6841SJoseph Chen 		pComponentData++;
81823ba6841SJoseph Chen 		pComponent++;
81923ba6841SJoseph Chen 	}
82023ba6841SJoseph Chen 
82123ba6841SJoseph Chen 	ret = true;
82223ba6841SJoseph Chen end:
82323ba6841SJoseph Chen 	if (FileSrc)
82423ba6841SJoseph Chen 		fclose(FileSrc);
82523ba6841SJoseph Chen 	if (pBuf)
82623ba6841SJoseph Chen 		free(pBuf);
82723ba6841SJoseph Chen 
82823ba6841SJoseph Chen 	return ret;
82923ba6841SJoseph Chen }
83023ba6841SJoseph Chen 
printHelp(void)83123ba6841SJoseph Chen static void printHelp(void)
83223ba6841SJoseph Chen {
83323ba6841SJoseph Chen 	printf("Usage: trust_merger [options]... FILE\n");
83423ba6841SJoseph Chen 	printf(
83523ba6841SJoseph Chen 	        "Merge or unpack Rockchip's trust image (Default action is to merge.)\n");
83623ba6841SJoseph Chen 	printf("Options:\n");
83723ba6841SJoseph Chen 	printf("\t" OPT_MERGE "\t\t\tMerge trust with specified config.\n");
83823ba6841SJoseph Chen 	printf("\t" OPT_UNPACK "\t\tUnpack specified trust to current dir.\n");
83923ba6841SJoseph Chen 	printf("\t" OPT_VERBOSE "\t\tDisplay more runtime informations.\n");
84023ba6841SJoseph Chen 	printf("\t" OPT_HELP "\t\t\tDisplay this information.\n");
84123ba6841SJoseph Chen 	printf("\t" OPT_VERSION "\t\tDisplay version information.\n");
84223ba6841SJoseph Chen 	printf("\t" OPT_SUBFIX "\t\tSpec subfix.\n");
84323ba6841SJoseph Chen 	printf("\t" OPT_REPLACE "\t\tReplace some part of binary path.\n");
844e311da24SJoseph Chen 	printf("\t" OPT_PREPATH "\t\tAdd prefix path of binary path.\n");
84523ba6841SJoseph Chen 	printf("\t" OPT_RSA "\t\t\tRSA mode.\"--rsa [mode]\", [mode] can be: "
84623ba6841SJoseph Chen 	       "0(none), 1(1024), 2(2048), 3(2048 pss).\n");
84723ba6841SJoseph Chen 	printf("\t" OPT_SHA
84823ba6841SJoseph Chen 	       "\t\t\tSHA mode.\"--sha [mode]\", [mode] can be: 0(none), 1(160), "
84923ba6841SJoseph Chen 	       "2(256 RK big endian), 3(256 little endian).\n");
85023ba6841SJoseph Chen 	printf("\t" OPT_SIZE "\t\t\tTrustImage size.\"--size [per image KB size] "
85123ba6841SJoseph Chen 	       "[copy count]\", per image must be 64KB aligned\n");
85223ba6841SJoseph Chen }
85323ba6841SJoseph Chen 
main(int argc,char ** argv)85423ba6841SJoseph Chen int main(int argc, char **argv)
85523ba6841SJoseph Chen {
85623ba6841SJoseph Chen 	bool merge = true;
85723ba6841SJoseph Chen 	char *optPath = NULL;
85823ba6841SJoseph Chen 	int i;
85923ba6841SJoseph Chen 
86023ba6841SJoseph Chen 	gConfigPath = NULL;
86123ba6841SJoseph Chen 	for (i = 1; i < argc; i++) {
86223ba6841SJoseph Chen 		if (!strcmp(OPT_VERBOSE, argv[i])) {
86323ba6841SJoseph Chen 			gDebug = true;
86423ba6841SJoseph Chen 		} else if (!strcmp(OPT_HELP, argv[i])) {
86523ba6841SJoseph Chen 			printHelp();
86623ba6841SJoseph Chen 			return 0;
86723ba6841SJoseph Chen 		} else if (!strcmp(OPT_VERSION, argv[i])) {
86823ba6841SJoseph Chen 			printf("trust_merger (cwz@rock-chips.com)\t" VERSION "\n");
86923ba6841SJoseph Chen 			return 0;
87023ba6841SJoseph Chen 		} else if (!strcmp(OPT_MERGE, argv[i])) {
87123ba6841SJoseph Chen 			merge = true;
87223ba6841SJoseph Chen 		} else if (!strcmp(OPT_UNPACK, argv[i])) {
87323ba6841SJoseph Chen 			merge = false;
87423ba6841SJoseph Chen 		} else if (!strcmp(OPT_SUBFIX, argv[i])) {
87523ba6841SJoseph Chen 			gSubfix = true;
87623ba6841SJoseph Chen 			printf("trust_merger: Spec subfix!\n");
87723ba6841SJoseph Chen 		} else if (!strcmp(OPT_REPLACE, argv[i])) {
87823ba6841SJoseph Chen 			i++;
87923ba6841SJoseph Chen 			gLegacyPath = argv[i];
88023ba6841SJoseph Chen 			i++;
88123ba6841SJoseph Chen 			gNewPath = argv[i];
882e311da24SJoseph Chen 		} else if (!strcmp(OPT_PREPATH, argv[i])) {
883e311da24SJoseph Chen 			i++;
884e311da24SJoseph Chen 			gPrePath = argv[i];
88523ba6841SJoseph Chen 		} else if (!strcmp(OPT_RSA, argv[i])) {
88623ba6841SJoseph Chen 			i++;
88723ba6841SJoseph Chen 			if (!is_digit(*(argv[i]))) {
88823ba6841SJoseph Chen 				printHelp();
88923ba6841SJoseph Chen 				return -1;
89023ba6841SJoseph Chen 			}
89123ba6841SJoseph Chen 			gRSAmode = *(argv[i]) - '0';
89223ba6841SJoseph Chen 			LOGD("rsa mode:%d\n", gRSAmode);
89323ba6841SJoseph Chen 		} else if (!strcmp(OPT_SHA, argv[i])) {
89423ba6841SJoseph Chen 			i++;
89523ba6841SJoseph Chen 			if (!is_digit(*(argv[i]))) {
89623ba6841SJoseph Chen 				printHelp();
89723ba6841SJoseph Chen 				return -1;
89823ba6841SJoseph Chen 			}
89923ba6841SJoseph Chen 			gSHAmode = *(argv[i]) - '0';
90023ba6841SJoseph Chen 			LOGD("sha mode:%d\n", gSHAmode);
90123ba6841SJoseph Chen 		} else if (!strcmp(OPT_SIZE, argv[i])) {
90223ba6841SJoseph Chen 			/* Per trust image size */
90323ba6841SJoseph Chen 			g_trust_max_size = strtoul(argv[++i], NULL, 10);
90423ba6841SJoseph Chen 			/*
90523ba6841SJoseph Chen 			 * Usually, it must be at 512kb align due to preloader
90623ba6841SJoseph Chen 			 * detects every 512kb. But some product has critial
90723ba6841SJoseph Chen 			 * flash size requirement, we have to make it small than
90823ba6841SJoseph Chen 			 * 512KB.
90923ba6841SJoseph Chen 			 */
91023ba6841SJoseph Chen 			if (g_trust_max_size % 64) {
91123ba6841SJoseph Chen 				printHelp();
91223ba6841SJoseph Chen 				return -1;
91323ba6841SJoseph Chen 			}
91423ba6841SJoseph Chen 			g_trust_max_size *= 1024; /* bytes */
91523ba6841SJoseph Chen 
91623ba6841SJoseph Chen 			/* Total backup numbers */
91723ba6841SJoseph Chen 			g_trust_max_num = strtoul(argv[++i], NULL, 10);
91875828958SJoseph Chen 		} else if (!strcmp(OPT_IGNORE_BL32, argv[i])) {
91975828958SJoseph Chen 			gIgnoreBL32 = true;
92023ba6841SJoseph Chen 		} else {
92123ba6841SJoseph Chen 			if (optPath) {
92223ba6841SJoseph Chen 				fprintf(stderr, "only need one path arg, but we have:\n%s\n%s.\n",
92323ba6841SJoseph Chen 				        optPath, argv[i]);
92423ba6841SJoseph Chen 				printHelp();
92523ba6841SJoseph Chen 				return -1;
92623ba6841SJoseph Chen 			}
92723ba6841SJoseph Chen 			optPath = argv[i];
92823ba6841SJoseph Chen 		}
92923ba6841SJoseph Chen 	}
93023ba6841SJoseph Chen 	if (!merge && !optPath) {
93123ba6841SJoseph Chen 		fprintf(stderr, "need set out path to unpack!\n");
93223ba6841SJoseph Chen 		printHelp();
93323ba6841SJoseph Chen 		return -1;
93423ba6841SJoseph Chen 	}
93523ba6841SJoseph Chen 
93623ba6841SJoseph Chen 	if (merge) {
93723ba6841SJoseph Chen 		LOGD("do_merge\n");
93823ba6841SJoseph Chen 		gConfigPath = optPath;
93923ba6841SJoseph Chen 		if (!mergetrust()) {
94023ba6841SJoseph Chen 			fprintf(stderr, "merge failed!\n");
94123ba6841SJoseph Chen 			return -1;
94223ba6841SJoseph Chen 		}
94323ba6841SJoseph Chen 		printf("merge success(%s)\n", gOpts.outPath);
94423ba6841SJoseph Chen 	} else {
94523ba6841SJoseph Chen 		LOGD("do_unpack\n");
94623ba6841SJoseph Chen 		if (!unpacktrust(optPath)) {
94723ba6841SJoseph Chen 			fprintf(stderr, "unpack failed!\n");
94823ba6841SJoseph Chen 			return -1;
94923ba6841SJoseph Chen 		}
95023ba6841SJoseph Chen 		printf("unpack success\n");
95123ba6841SJoseph Chen 	}
95223ba6841SJoseph Chen 
95323ba6841SJoseph Chen 	return 0;
95423ba6841SJoseph Chen }
955