xref: /rk3399_rockchip-uboot/tools/rockchip/boot_merger.c (revision 24f9e652a5e0459a0a66e0502e4b47654759b2e7)
123ba6841SJoseph Chen /*
223ba6841SJoseph Chen  * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
323ba6841SJoseph Chen  *
423ba6841SJoseph Chen  * SPDX-License-Identifier:	GPL-2.0+
523ba6841SJoseph Chen  */
623ba6841SJoseph Chen #include "boot_merger.h"
723ba6841SJoseph Chen #include <time.h>
823ba6841SJoseph Chen #include <sys/stat.h>
923ba6841SJoseph Chen #include <version.h>
1023ba6841SJoseph Chen 
1123ba6841SJoseph Chen /* #define USE_P_RC4 */
1223ba6841SJoseph Chen 
1323ba6841SJoseph Chen bool gDebug =
1423ba6841SJoseph Chen #ifdef DEBUG
1523ba6841SJoseph Chen         true;
1623ba6841SJoseph Chen #else
1723ba6841SJoseph Chen         false;
1823ba6841SJoseph Chen #endif /* DEBUG */
1923ba6841SJoseph Chen 
2023ba6841SJoseph Chen #define ENTRY_ALIGN (2048)
2123ba6841SJoseph Chen options gOpts;
2223ba6841SJoseph Chen char gLegacyPath[MAX_LINE_LEN] = { 0 };
2323ba6841SJoseph Chen char gNewPath[MAX_LINE_LEN] = { 0 };
24e311da24SJoseph Chen static char *gPrePath;
2523ba6841SJoseph Chen char gSubfix[MAX_LINE_LEN] = OUT_SUBFIX;
2623ba6841SJoseph Chen char gEat[MAX_LINE_LEN];
2723ba6841SJoseph Chen char *gConfigPath;
2823ba6841SJoseph Chen uint8_t *gBuf;
29*24f9e652SJoseph Chen bool enableRC4 = false;
3023ba6841SJoseph Chen 
3123ba6841SJoseph Chen static uint32_t g_merge_max_size = MAX_MERGE_SIZE;
3223ba6841SJoseph Chen 
3323ba6841SJoseph Chen uint32_t gTable_Crc32[256] = {
3423ba6841SJoseph Chen 	0x00000000, 0x04c10db7, 0x09821b6e, 0x0d4316d9, 0x130436dc, 0x17c53b6b,
3523ba6841SJoseph Chen 	0x1a862db2, 0x1e472005, 0x26086db8, 0x22c9600f, 0x2f8a76d6, 0x2b4b7b61,
3623ba6841SJoseph Chen 	0x350c5b64, 0x31cd56d3, 0x3c8e400a, 0x384f4dbd, 0x4c10db70, 0x48d1d6c7,
3723ba6841SJoseph Chen 	0x4592c01e, 0x4153cda9, 0x5f14edac, 0x5bd5e01b, 0x5696f6c2, 0x5257fb75,
3823ba6841SJoseph Chen 	0x6a18b6c8, 0x6ed9bb7f, 0x639aada6, 0x675ba011, 0x791c8014, 0x7ddd8da3,
3923ba6841SJoseph Chen 	0x709e9b7a, 0x745f96cd, 0x9821b6e0, 0x9ce0bb57, 0x91a3ad8e, 0x9562a039,
4023ba6841SJoseph Chen 	0x8b25803c, 0x8fe48d8b, 0x82a79b52, 0x866696e5, 0xbe29db58, 0xbae8d6ef,
4123ba6841SJoseph Chen 	0xb7abc036, 0xb36acd81, 0xad2ded84, 0xa9ece033, 0xa4aff6ea, 0xa06efb5d,
4223ba6841SJoseph Chen 	0xd4316d90, 0xd0f06027, 0xddb376fe, 0xd9727b49, 0xc7355b4c, 0xc3f456fb,
4323ba6841SJoseph Chen 	0xceb74022, 0xca764d95, 0xf2390028, 0xf6f80d9f, 0xfbbb1b46, 0xff7a16f1,
4423ba6841SJoseph Chen 	0xe13d36f4, 0xe5fc3b43, 0xe8bf2d9a, 0xec7e202d, 0x34826077, 0x30436dc0,
4523ba6841SJoseph Chen 	0x3d007b19, 0x39c176ae, 0x278656ab, 0x23475b1c, 0x2e044dc5, 0x2ac54072,
4623ba6841SJoseph Chen 	0x128a0dcf, 0x164b0078, 0x1b0816a1, 0x1fc91b16, 0x018e3b13, 0x054f36a4,
4723ba6841SJoseph Chen 	0x080c207d, 0x0ccd2dca, 0x7892bb07, 0x7c53b6b0, 0x7110a069, 0x75d1adde,
4823ba6841SJoseph Chen 	0x6b968ddb, 0x6f57806c, 0x621496b5, 0x66d59b02, 0x5e9ad6bf, 0x5a5bdb08,
4923ba6841SJoseph Chen 	0x5718cdd1, 0x53d9c066, 0x4d9ee063, 0x495fedd4, 0x441cfb0d, 0x40ddf6ba,
5023ba6841SJoseph Chen 	0xaca3d697, 0xa862db20, 0xa521cdf9, 0xa1e0c04e, 0xbfa7e04b, 0xbb66edfc,
5123ba6841SJoseph Chen 	0xb625fb25, 0xb2e4f692, 0x8aabbb2f, 0x8e6ab698, 0x8329a041, 0x87e8adf6,
5223ba6841SJoseph Chen 	0x99af8df3, 0x9d6e8044, 0x902d969d, 0x94ec9b2a, 0xe0b30de7, 0xe4720050,
5323ba6841SJoseph Chen 	0xe9311689, 0xedf01b3e, 0xf3b73b3b, 0xf776368c, 0xfa352055, 0xfef42de2,
5423ba6841SJoseph Chen 	0xc6bb605f, 0xc27a6de8, 0xcf397b31, 0xcbf87686, 0xd5bf5683, 0xd17e5b34,
5523ba6841SJoseph Chen 	0xdc3d4ded, 0xd8fc405a, 0x6904c0ee, 0x6dc5cd59, 0x6086db80, 0x6447d637,
5623ba6841SJoseph Chen 	0x7a00f632, 0x7ec1fb85, 0x7382ed5c, 0x7743e0eb, 0x4f0cad56, 0x4bcda0e1,
5723ba6841SJoseph Chen 	0x468eb638, 0x424fbb8f, 0x5c089b8a, 0x58c9963d, 0x558a80e4, 0x514b8d53,
5823ba6841SJoseph Chen 	0x25141b9e, 0x21d51629, 0x2c9600f0, 0x28570d47, 0x36102d42, 0x32d120f5,
5923ba6841SJoseph Chen 	0x3f92362c, 0x3b533b9b, 0x031c7626, 0x07dd7b91, 0x0a9e6d48, 0x0e5f60ff,
6023ba6841SJoseph Chen 	0x101840fa, 0x14d94d4d, 0x199a5b94, 0x1d5b5623, 0xf125760e, 0xf5e47bb9,
6123ba6841SJoseph Chen 	0xf8a76d60, 0xfc6660d7, 0xe22140d2, 0xe6e04d65, 0xeba35bbc, 0xef62560b,
6223ba6841SJoseph Chen 	0xd72d1bb6, 0xd3ec1601, 0xdeaf00d8, 0xda6e0d6f, 0xc4292d6a, 0xc0e820dd,
6323ba6841SJoseph Chen 	0xcdab3604, 0xc96a3bb3, 0xbd35ad7e, 0xb9f4a0c9, 0xb4b7b610, 0xb076bba7,
6423ba6841SJoseph Chen 	0xae319ba2, 0xaaf09615, 0xa7b380cc, 0xa3728d7b, 0x9b3dc0c6, 0x9ffccd71,
6523ba6841SJoseph Chen 	0x92bfdba8, 0x967ed61f, 0x8839f61a, 0x8cf8fbad, 0x81bbed74, 0x857ae0c3,
6623ba6841SJoseph Chen 	0x5d86a099, 0x5947ad2e, 0x5404bbf7, 0x50c5b640, 0x4e829645, 0x4a439bf2,
6723ba6841SJoseph Chen 	0x47008d2b, 0x43c1809c, 0x7b8ecd21, 0x7f4fc096, 0x720cd64f, 0x76cddbf8,
6823ba6841SJoseph Chen 	0x688afbfd, 0x6c4bf64a, 0x6108e093, 0x65c9ed24, 0x11967be9, 0x1557765e,
6923ba6841SJoseph Chen 	0x18146087, 0x1cd56d30, 0x02924d35, 0x06534082, 0x0b10565b, 0x0fd15bec,
7023ba6841SJoseph Chen 	0x379e1651, 0x335f1be6, 0x3e1c0d3f, 0x3add0088, 0x249a208d, 0x205b2d3a,
7123ba6841SJoseph Chen 	0x2d183be3, 0x29d93654, 0xc5a71679, 0xc1661bce, 0xcc250d17, 0xc8e400a0,
7223ba6841SJoseph Chen 	0xd6a320a5, 0xd2622d12, 0xdf213bcb, 0xdbe0367c, 0xe3af7bc1, 0xe76e7676,
7323ba6841SJoseph Chen 	0xea2d60af, 0xeeec6d18, 0xf0ab4d1d, 0xf46a40aa, 0xf9295673, 0xfde85bc4,
7423ba6841SJoseph Chen 	0x89b7cd09, 0x8d76c0be, 0x8035d667, 0x84f4dbd0, 0x9ab3fbd5, 0x9e72f662,
7523ba6841SJoseph Chen 	0x9331e0bb, 0x97f0ed0c, 0xafbfa0b1, 0xab7ead06, 0xa63dbbdf, 0xa2fcb668,
7623ba6841SJoseph Chen 	0xbcbb966d, 0xb87a9bda, 0xb5398d03, 0xb1f880b4,
7723ba6841SJoseph Chen };
7823ba6841SJoseph Chen 
CRC_32(uint8_t * pData,uint32_t ulSize)7923ba6841SJoseph Chen uint32_t CRC_32(uint8_t *pData, uint32_t ulSize)
8023ba6841SJoseph Chen {
8123ba6841SJoseph Chen 	uint32_t i;
8223ba6841SJoseph Chen 	uint32_t nAccum = 0;
8323ba6841SJoseph Chen 	for (i = 0; i < ulSize; i++) {
8423ba6841SJoseph Chen 		nAccum = (nAccum << 8) ^ gTable_Crc32[(nAccum >> 24) ^ (*pData++)];
8523ba6841SJoseph Chen 	}
8623ba6841SJoseph Chen 	return nAccum;
8723ba6841SJoseph Chen }
8823ba6841SJoseph Chen 
P_RC4(uint8_t * buf,uint32_t len)8923ba6841SJoseph Chen void P_RC4(uint8_t *buf, uint32_t len)
9023ba6841SJoseph Chen {
9123ba6841SJoseph Chen 	uint8_t S[256], K[256], temp;
9223ba6841SJoseph Chen 	uint32_t i, j, t, x;
9323ba6841SJoseph Chen 	uint8_t key[16] = { 124, 78, 3, 4, 85, 5, 9, 7, 45, 44, 123, 56, 23, 13, 23,
9423ba6841SJoseph Chen 	                    17
9523ba6841SJoseph Chen 	                  };
9623ba6841SJoseph Chen 
9723ba6841SJoseph Chen 	j = 0;
9823ba6841SJoseph Chen 	for (i = 0; i < 256; i++) {
9923ba6841SJoseph Chen 		S[i] = (uint8_t) i;
10023ba6841SJoseph Chen 		j &= 0x0f;
10123ba6841SJoseph Chen 		K[i] = key[j];
10223ba6841SJoseph Chen 		j++;
10323ba6841SJoseph Chen 	}
10423ba6841SJoseph Chen 
10523ba6841SJoseph Chen 	j = 0;
10623ba6841SJoseph Chen 	for (i = 0; i < 256; i++) {
10723ba6841SJoseph Chen 		j = (j + S[i] + K[i]) % 256;
10823ba6841SJoseph Chen 		temp = S[i];
10923ba6841SJoseph Chen 		S[i] = S[j];
11023ba6841SJoseph Chen 		S[j] = temp;
11123ba6841SJoseph Chen 	}
11223ba6841SJoseph Chen 
11323ba6841SJoseph Chen 	i = j = 0;
11423ba6841SJoseph Chen 	for (x = 0; x < len; x++) {
11523ba6841SJoseph Chen 		i = (i + 1) % 256;
11623ba6841SJoseph Chen 		j = (j + S[i]) % 256;
11723ba6841SJoseph Chen 		temp = S[i];
11823ba6841SJoseph Chen 		S[i] = S[j];
11923ba6841SJoseph Chen 		S[j] = temp;
12023ba6841SJoseph Chen 		t = (S[i] + (S[j] % 256)) % 256;
12123ba6841SJoseph Chen 		buf[x] = buf[x] ^ S[t];
12223ba6841SJoseph Chen 	}
12323ba6841SJoseph Chen }
12423ba6841SJoseph Chen 
fixPath(char * path)12523ba6841SJoseph Chen static inline void fixPath(char *path)
12623ba6841SJoseph Chen {
12723ba6841SJoseph Chen 	int i, len = strlen(path);
12823ba6841SJoseph Chen 	char tmp[MAX_LINE_LEN];
12923ba6841SJoseph Chen 	char *start, *end;
13023ba6841SJoseph Chen 
13123ba6841SJoseph Chen 	for (i = 0; i < len; i++) {
13223ba6841SJoseph Chen 		if (path[i] == '\\')
13323ba6841SJoseph Chen 			path[i] = '/';
13423ba6841SJoseph Chen 		else if (path[i] == '\r' || path[i] == '\n')
13523ba6841SJoseph Chen 			path[i] = '\0';
13623ba6841SJoseph Chen 	}
13723ba6841SJoseph Chen 
13823ba6841SJoseph Chen 	if (strlen(gLegacyPath) && strlen(gNewPath)) {
13923ba6841SJoseph Chen 		start = strstr(path, gLegacyPath);
14023ba6841SJoseph Chen 		if (start) {
14123ba6841SJoseph Chen 			end = start + strlen(gLegacyPath);
14223ba6841SJoseph Chen 			/* Backup, so tmp can be src for strcat() */
14323ba6841SJoseph Chen 			strcpy(tmp, end);
14423ba6841SJoseph Chen 			/* Terminate, so path can be dest for strcat() */
14523ba6841SJoseph Chen 			*start = '\0';
14645c2a034SJoseph Chen 			strcat(path, gNewPath);
14723ba6841SJoseph Chen 			strcat(path, tmp);
1489ad3008aSJoseph Chen 		} else {
1499ad3008aSJoseph Chen 			strcpy(tmp, path);
1509ad3008aSJoseph Chen 			strcpy(path, gNewPath);
1519ad3008aSJoseph Chen 			strcat(path, tmp);
15223ba6841SJoseph Chen 		}
1535f0203b7SJoseph Chen 	} else if ((ulong)path != (ulong)gOpts.outPath && /* ignore output */
1545f0203b7SJoseph Chen 		    gPrePath && strncmp(path, gPrePath, strlen(gPrePath))) {
155e311da24SJoseph Chen 		strcpy(tmp, path);
156e311da24SJoseph Chen 		strcpy(path, gPrePath);
157e311da24SJoseph Chen 		strcat(path, tmp);
15823ba6841SJoseph Chen 	}
15923ba6841SJoseph Chen }
16023ba6841SJoseph Chen 
parseChip(FILE * file)16123ba6841SJoseph Chen static bool parseChip(FILE *file)
16223ba6841SJoseph Chen {
16323ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
16423ba6841SJoseph Chen 		return false;
16523ba6841SJoseph Chen 	}
16623ba6841SJoseph Chen 	if (fscanf(file, OPT_NAME "=%s", gOpts.chip) != 1) {
16723ba6841SJoseph Chen 		return false;
16823ba6841SJoseph Chen 	}
16923ba6841SJoseph Chen 	LOGD("chip:%s\n", gOpts.chip);
17023ba6841SJoseph Chen 	return true;
17123ba6841SJoseph Chen }
17223ba6841SJoseph Chen 
parseVersion(FILE * file)17323ba6841SJoseph Chen static bool parseVersion(FILE *file)
17423ba6841SJoseph Chen {
17523ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
17623ba6841SJoseph Chen 		return false;
17723ba6841SJoseph Chen 	}
17823ba6841SJoseph Chen 	if (fscanf(file, OPT_MAJOR "=%d", &gOpts.major) != 1)
17923ba6841SJoseph Chen 		return false;
18023ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
18123ba6841SJoseph Chen 		return false;
18223ba6841SJoseph Chen 	}
18323ba6841SJoseph Chen 	if (fscanf(file, OPT_MINOR "=%d", &gOpts.minor) != 1)
18423ba6841SJoseph Chen 		return false;
18523ba6841SJoseph Chen 	LOGD("major:%d, minor:%d\n", gOpts.major, gOpts.minor);
18623ba6841SJoseph Chen 	return true;
18723ba6841SJoseph Chen }
18823ba6841SJoseph Chen 
parse471(FILE * file)18923ba6841SJoseph Chen static bool parse471(FILE *file)
19023ba6841SJoseph Chen {
19123ba6841SJoseph Chen 	int i, index, pos;
19223ba6841SJoseph Chen 	char buf[MAX_LINE_LEN];
19323ba6841SJoseph Chen 
19423ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
19523ba6841SJoseph Chen 		return false;
19623ba6841SJoseph Chen 	}
19723ba6841SJoseph Chen 	if (fscanf(file, OPT_NUM "=%d", &gOpts.code471Num) != 1)
19823ba6841SJoseph Chen 		return false;
19923ba6841SJoseph Chen 	LOGD("num:%d\n", gOpts.code471Num);
20023ba6841SJoseph Chen 	if (!gOpts.code471Num)
20123ba6841SJoseph Chen 		return true;
20223ba6841SJoseph Chen 	if (gOpts.code471Num < 0)
20323ba6841SJoseph Chen 		return false;
20423ba6841SJoseph Chen 	gOpts.code471Path = (line_t *)malloc(sizeof(line_t) * gOpts.code471Num);
20523ba6841SJoseph Chen 	for (i = 0; i < gOpts.code471Num; i++) {
20623ba6841SJoseph Chen 		if (SCANF_EAT(file) != 0) {
20723ba6841SJoseph Chen 			return false;
20823ba6841SJoseph Chen 		}
20923ba6841SJoseph Chen 		if (fscanf(file, OPT_PATH "%d=%[^\r^\n]", &index, buf) != 2)
21023ba6841SJoseph Chen 			return false;
21123ba6841SJoseph Chen 		index--;
21223ba6841SJoseph Chen 		fixPath(buf);
21323ba6841SJoseph Chen 		strcpy((char *)gOpts.code471Path[index], buf);
21423ba6841SJoseph Chen 		LOGD("path%i:%s\n", index, gOpts.code471Path[index]);
21523ba6841SJoseph Chen 	}
21623ba6841SJoseph Chen 	pos = ftell(file);
21723ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
21823ba6841SJoseph Chen 		return false;
21923ba6841SJoseph Chen 	}
22023ba6841SJoseph Chen 	if (fscanf(file, OPT_SLEEP "=%d", &gOpts.code471Sleep) != 1)
22123ba6841SJoseph Chen 		fseek(file, pos, SEEK_SET);
22223ba6841SJoseph Chen 	LOGD("sleep:%d\n", gOpts.code471Sleep);
22323ba6841SJoseph Chen 	return true;
22423ba6841SJoseph Chen }
22523ba6841SJoseph Chen 
parse472(FILE * file)22623ba6841SJoseph Chen static bool parse472(FILE *file)
22723ba6841SJoseph Chen {
22823ba6841SJoseph Chen 	int i, index, pos;
22923ba6841SJoseph Chen 	char buf[MAX_LINE_LEN];
23023ba6841SJoseph Chen 
23123ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
23223ba6841SJoseph Chen 		return false;
23323ba6841SJoseph Chen 	}
23423ba6841SJoseph Chen 	if (fscanf(file, OPT_NUM "=%d", &gOpts.code472Num) != 1)
23523ba6841SJoseph Chen 		return false;
23623ba6841SJoseph Chen 	LOGD("num:%d\n", gOpts.code472Num);
23723ba6841SJoseph Chen 	if (!gOpts.code472Num)
23823ba6841SJoseph Chen 		return true;
23923ba6841SJoseph Chen 	if (gOpts.code472Num < 0)
24023ba6841SJoseph Chen 		return false;
24123ba6841SJoseph Chen 	gOpts.code472Path = (line_t *)malloc(sizeof(line_t) * gOpts.code472Num);
24223ba6841SJoseph Chen 	for (i = 0; i < gOpts.code472Num; i++) {
24323ba6841SJoseph Chen 		if (SCANF_EAT(file) != 0) {
24423ba6841SJoseph Chen 			return false;
24523ba6841SJoseph Chen 		}
24623ba6841SJoseph Chen 		if (fscanf(file, OPT_PATH "%d=%[^\r^\n]", &index, buf) != 2)
24723ba6841SJoseph Chen 			return false;
24823ba6841SJoseph Chen 		fixPath(buf);
24923ba6841SJoseph Chen 		index--;
25023ba6841SJoseph Chen 		strcpy((char *)gOpts.code472Path[index], buf);
25123ba6841SJoseph Chen 		LOGD("path%i:%s\n", index, gOpts.code472Path[index]);
25223ba6841SJoseph Chen 	}
25323ba6841SJoseph Chen 	pos = ftell(file);
25423ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
25523ba6841SJoseph Chen 		return false;
25623ba6841SJoseph Chen 	}
25723ba6841SJoseph Chen 	if (fscanf(file, OPT_SLEEP "=%d", &gOpts.code472Sleep) != 1)
25823ba6841SJoseph Chen 		fseek(file, pos, SEEK_SET);
25923ba6841SJoseph Chen 	LOGD("sleep:%d\n", gOpts.code472Sleep);
26023ba6841SJoseph Chen 	return true;
26123ba6841SJoseph Chen }
26223ba6841SJoseph Chen 
parseLoader(FILE * file)26323ba6841SJoseph Chen static bool parseLoader(FILE *file)
26423ba6841SJoseph Chen {
26523ba6841SJoseph Chen 	int i, j, index, pos;
26623ba6841SJoseph Chen 	char buf[MAX_LINE_LEN];
26723ba6841SJoseph Chen 	char buf2[MAX_LINE_LEN];
26823ba6841SJoseph Chen 
26923ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
27023ba6841SJoseph Chen 		return false;
27123ba6841SJoseph Chen 	}
27223ba6841SJoseph Chen 	pos = ftell(file);
27323ba6841SJoseph Chen 	if (fscanf(file, OPT_NUM "=%d", &gOpts.loaderNum) != 1) {
27423ba6841SJoseph Chen 		fseek(file, pos, SEEK_SET);
27523ba6841SJoseph Chen 		if (fscanf(file, OPT_LOADER_NUM "=%d", &gOpts.loaderNum) != 1) {
27623ba6841SJoseph Chen 			return false;
27723ba6841SJoseph Chen 		}
27823ba6841SJoseph Chen 	}
27923ba6841SJoseph Chen 	LOGD("num:%d\n", gOpts.loaderNum);
28023ba6841SJoseph Chen 	if (!gOpts.loaderNum)
28123ba6841SJoseph Chen 		return false;
28223ba6841SJoseph Chen 	if (gOpts.loaderNum < 0)
28323ba6841SJoseph Chen 		return false;
28423ba6841SJoseph Chen 	gOpts.loader = (name_entry *)malloc(sizeof(name_entry) * gOpts.loaderNum);
28523ba6841SJoseph Chen 	for (i = 0; i < gOpts.loaderNum; i++) {
28623ba6841SJoseph Chen 		if (SCANF_EAT(file) != 0) {
28723ba6841SJoseph Chen 			return false;
28823ba6841SJoseph Chen 		}
28923ba6841SJoseph Chen 		if (fscanf(file, OPT_LOADER_NAME "%d=%s", &index, buf) != 2)
29023ba6841SJoseph Chen 			return false;
29123ba6841SJoseph Chen 		index--;
29223ba6841SJoseph Chen 		strcpy(gOpts.loader[index].name, buf);
29323ba6841SJoseph Chen 		LOGD("name%d:%s\n", index, gOpts.loader[index].name);
29423ba6841SJoseph Chen 	}
29523ba6841SJoseph Chen 	for (i = 0; i < gOpts.loaderNum; i++) {
29623ba6841SJoseph Chen 		if (SCANF_EAT(file) != 0) {
29723ba6841SJoseph Chen 			return false;
29823ba6841SJoseph Chen 		}
29923ba6841SJoseph Chen 		if (fscanf(file, "%[^=]=%[^\r^\n]", buf, buf2) != 2)
30023ba6841SJoseph Chen 			return false;
30123ba6841SJoseph Chen 		for (j = 0; j < gOpts.loaderNum; j++) {
30223ba6841SJoseph Chen 			if (!strcmp(gOpts.loader[j].name, buf)) {
30323ba6841SJoseph Chen 				fixPath(buf2);
30423ba6841SJoseph Chen 				strcpy(gOpts.loader[j].path, buf2);
30523ba6841SJoseph Chen 				LOGD("%s=%s\n", gOpts.loader[j].name, gOpts.loader[j].path);
30623ba6841SJoseph Chen 				break;
30723ba6841SJoseph Chen 			}
30823ba6841SJoseph Chen 		}
30923ba6841SJoseph Chen 		if (j >= gOpts.loaderNum) {
31023ba6841SJoseph Chen 			return false;
31123ba6841SJoseph Chen 		}
31223ba6841SJoseph Chen 	}
31323ba6841SJoseph Chen 	return true;
31423ba6841SJoseph Chen }
31523ba6841SJoseph Chen 
parseOut(FILE * file)31623ba6841SJoseph Chen static bool parseOut(FILE *file)
31723ba6841SJoseph Chen {
31823ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
31923ba6841SJoseph Chen 		return false;
32023ba6841SJoseph Chen 	}
32123ba6841SJoseph Chen 	if (fscanf(file, OPT_OUT_PATH "=%[^\r^\n]", gOpts.outPath) != 1)
32223ba6841SJoseph Chen 		return false;
3235f0203b7SJoseph Chen 	/* fixPath(gOpts.outPath); */
32423ba6841SJoseph Chen 	printf("out:%s\n", gOpts.outPath);
32523ba6841SJoseph Chen 	return true;
32623ba6841SJoseph Chen }
32723ba6841SJoseph Chen 
printOpts(FILE * out)32823ba6841SJoseph Chen void printOpts(FILE *out)
32923ba6841SJoseph Chen {
33023ba6841SJoseph Chen 	uint32_t i;
33123ba6841SJoseph Chen 	fprintf(out, SEC_CHIP "\n" OPT_NAME "=%s\n", gOpts.chip);
33223ba6841SJoseph Chen 	fprintf(out, SEC_VERSION "\n" OPT_MAJOR "=%d\n" OPT_MINOR "=%d\n",
33323ba6841SJoseph Chen 	        gOpts.major, gOpts.minor);
33423ba6841SJoseph Chen 
33523ba6841SJoseph Chen 	fprintf(out, SEC_471 "\n" OPT_NUM "=%d\n", gOpts.code471Num);
33623ba6841SJoseph Chen 	for (i = 0; i < gOpts.code471Num; i++) {
33723ba6841SJoseph Chen 		fprintf(out, OPT_PATH "%d=%s\n", i + 1, gOpts.code471Path[i]);
33823ba6841SJoseph Chen 	}
33923ba6841SJoseph Chen 	if (gOpts.code471Sleep > 0)
34023ba6841SJoseph Chen 		fprintf(out, OPT_SLEEP "=%d\n", gOpts.code471Sleep);
34123ba6841SJoseph Chen 
34223ba6841SJoseph Chen 	fprintf(out, SEC_472 "\n" OPT_NUM "=%d\n", gOpts.code472Num);
34323ba6841SJoseph Chen 	for (i = 0; i < gOpts.code472Num; i++) {
34423ba6841SJoseph Chen 		fprintf(out, OPT_PATH "%d=%s\n", i + 1, gOpts.code472Path[i]);
34523ba6841SJoseph Chen 	}
34623ba6841SJoseph Chen 	if (gOpts.code472Sleep > 0)
34723ba6841SJoseph Chen 		fprintf(out, OPT_SLEEP "=%d\n", gOpts.code472Sleep);
34823ba6841SJoseph Chen 
34923ba6841SJoseph Chen 	fprintf(out, SEC_LOADER "\n" OPT_NUM "=%d\n", gOpts.loaderNum);
35023ba6841SJoseph Chen 	for (i = 0; i < gOpts.loaderNum; i++) {
35123ba6841SJoseph Chen 		fprintf(out, OPT_LOADER_NAME "%d=%s\n", i + 1, gOpts.loader[i].name);
35223ba6841SJoseph Chen 	}
35323ba6841SJoseph Chen 	for (i = 0; i < gOpts.loaderNum; i++) {
35423ba6841SJoseph Chen 		fprintf(out, "%s=%s\n", gOpts.loader[i].name, gOpts.loader[i].path);
35523ba6841SJoseph Chen 	}
35623ba6841SJoseph Chen 
35723ba6841SJoseph Chen 	fprintf(out, SEC_OUT "\n" OPT_OUT_PATH "=%s\n", gOpts.outPath);
35823ba6841SJoseph Chen }
35923ba6841SJoseph Chen 
parseOpts_from_file(void)36023ba6841SJoseph Chen static bool parseOpts_from_file(void)
36123ba6841SJoseph Chen {
36223ba6841SJoseph Chen 	bool ret = false;
36323ba6841SJoseph Chen 	bool chipOk = false;
36423ba6841SJoseph Chen 	bool versionOk = false;
36523ba6841SJoseph Chen 	bool code471Ok = true;
36623ba6841SJoseph Chen 	bool code472Ok = true;
36723ba6841SJoseph Chen 	bool loaderOk = false;
36823ba6841SJoseph Chen 	bool outOk = false;
36923ba6841SJoseph Chen 	char buf[MAX_LINE_LEN];
37023ba6841SJoseph Chen 
37123ba6841SJoseph Chen 	char *configPath = (gConfigPath == NULL) ? DEF_CONFIG_FILE : gConfigPath;
37223ba6841SJoseph Chen 	FILE *file;
37323ba6841SJoseph Chen 	file = fopen(configPath, "r");
37423ba6841SJoseph Chen 	if (!file) {
37523ba6841SJoseph Chen 		fprintf(stderr, "config(%s) not found!\n", configPath);
37623ba6841SJoseph Chen 		if (configPath == (char *)DEF_CONFIG_FILE) {
37723ba6841SJoseph Chen 			file = fopen(DEF_CONFIG_FILE, "w");
37823ba6841SJoseph Chen 			if (file) {
37923ba6841SJoseph Chen 				fprintf(stderr, "create defconfig\n");
38023ba6841SJoseph Chen 				printOpts(file);
38123ba6841SJoseph Chen 			}
38223ba6841SJoseph Chen 		}
38323ba6841SJoseph Chen 		goto end;
38423ba6841SJoseph Chen 	}
38523ba6841SJoseph Chen 
38623ba6841SJoseph Chen 	LOGD("start parse\n");
38723ba6841SJoseph Chen 
38823ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
38923ba6841SJoseph Chen 		goto end;
39023ba6841SJoseph Chen 	}
39123ba6841SJoseph Chen 	while (fscanf(file, "%s", buf) == 1) {
39223ba6841SJoseph Chen 		if (!strcmp(buf, SEC_CHIP)) {
39323ba6841SJoseph Chen 			chipOk = parseChip(file);
39423ba6841SJoseph Chen 			if (!chipOk) {
39523ba6841SJoseph Chen 				LOGE("parseChip failed!\n");
39623ba6841SJoseph Chen 				goto end;
39723ba6841SJoseph Chen 			}
39823ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_VERSION)) {
39923ba6841SJoseph Chen 			versionOk = parseVersion(file);
40023ba6841SJoseph Chen 			if (!versionOk) {
40123ba6841SJoseph Chen 				LOGE("parseVersion failed!\n");
40223ba6841SJoseph Chen 				goto end;
40323ba6841SJoseph Chen 			}
40423ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_471)) {
40523ba6841SJoseph Chen 			code471Ok = parse471(file);
40623ba6841SJoseph Chen 			if (!code471Ok) {
40723ba6841SJoseph Chen 				LOGE("parse471 failed!\n");
40823ba6841SJoseph Chen 				goto end;
40923ba6841SJoseph Chen 			}
41023ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_472)) {
41123ba6841SJoseph Chen 			code472Ok = parse472(file);
41223ba6841SJoseph Chen 			if (!code472Ok) {
41323ba6841SJoseph Chen 				LOGE("parse472 failed!\n");
41423ba6841SJoseph Chen 				goto end;
41523ba6841SJoseph Chen 			}
41623ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_LOADER)) {
41723ba6841SJoseph Chen 			loaderOk = parseLoader(file);
41823ba6841SJoseph Chen 			if (!loaderOk) {
41923ba6841SJoseph Chen 				LOGE("parseLoader failed!\n");
42023ba6841SJoseph Chen 				goto end;
42123ba6841SJoseph Chen 			}
42223ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_OUT)) {
42323ba6841SJoseph Chen 			outOk = parseOut(file);
42423ba6841SJoseph Chen 			if (!outOk) {
42523ba6841SJoseph Chen 				LOGE("parseOut failed!\n");
42623ba6841SJoseph Chen 				goto end;
42723ba6841SJoseph Chen 			}
42823ba6841SJoseph Chen 		} else if (buf[0] == '#') {
42923ba6841SJoseph Chen 			continue;
43023ba6841SJoseph Chen 		} else {
43123ba6841SJoseph Chen 			LOGE("unknown sec: %s!\n", buf);
43223ba6841SJoseph Chen 			goto end;
43323ba6841SJoseph Chen 		}
43423ba6841SJoseph Chen 		if (SCANF_EAT(file) != 0) {
43523ba6841SJoseph Chen 			goto end;
43623ba6841SJoseph Chen 		}
43723ba6841SJoseph Chen 	}
43823ba6841SJoseph Chen 
43923ba6841SJoseph Chen 	if (chipOk && versionOk && code471Ok && code472Ok && loaderOk && outOk)
44023ba6841SJoseph Chen 		ret = true;
44123ba6841SJoseph Chen end:
44223ba6841SJoseph Chen 	if (file)
44323ba6841SJoseph Chen 		fclose(file);
44423ba6841SJoseph Chen 	return ret;
44523ba6841SJoseph Chen }
44623ba6841SJoseph Chen 
parseOpts_from_cmdline(int argc,char ** argv)44723ba6841SJoseph Chen static bool parseOpts_from_cmdline(int argc, char **argv)
44823ba6841SJoseph Chen {
44923ba6841SJoseph Chen 	int i;
45023ba6841SJoseph Chen 	int tag = 0;
45123ba6841SJoseph Chen 	int v0, v1, v2, v3;
45223ba6841SJoseph Chen 
45323ba6841SJoseph Chen 	for (i = 2; i < argc; i++) {
45423ba6841SJoseph Chen 		if (!strcmp(OPT_471, argv[i])) {
45523ba6841SJoseph Chen 			i++;
45623ba6841SJoseph Chen 			snprintf(gOpts.code471Path[0], sizeof(gOpts.code471Path[0]), "%s",
45723ba6841SJoseph Chen 			         argv[i]);
45823ba6841SJoseph Chen 			tag |= 1;
45923ba6841SJoseph Chen 		} else if (!strcmp(OPT_472, argv[i])) {
46023ba6841SJoseph Chen 			i++;
46123ba6841SJoseph Chen 			snprintf(gOpts.code472Path[0], sizeof(gOpts.code472Path[0]), "%s",
46223ba6841SJoseph Chen 			         argv[i]);
46323ba6841SJoseph Chen 			tag |= 2;
46423ba6841SJoseph Chen 		} else if (!strcmp(OPT_DATA, argv[i])) {
46523ba6841SJoseph Chen 			i++;
46623ba6841SJoseph Chen 			snprintf(gOpts.loader[0].path, sizeof(gOpts.loader[0].path), "%s",
46723ba6841SJoseph Chen 			         argv[i]);
46823ba6841SJoseph Chen 			tag |= 4;
46923ba6841SJoseph Chen 		} else if (!strcmp(OPT_BOOT, argv[i])) {
47023ba6841SJoseph Chen 			i++;
47123ba6841SJoseph Chen 			snprintf(gOpts.loader[1].path, sizeof(gOpts.loader[1].path), "%s",
47223ba6841SJoseph Chen 			         argv[i]);
47323ba6841SJoseph Chen 			tag |= 8;
47423ba6841SJoseph Chen 		} else if (!strcmp(OPT_OUT, argv[i])) {
47523ba6841SJoseph Chen 			i++;
47623ba6841SJoseph Chen 			snprintf(gOpts.outPath, sizeof(gOpts.outPath), "%s", argv[i]);
47723ba6841SJoseph Chen 			tag |= 0x10;
47823ba6841SJoseph Chen 		} else if (!strcmp(OPT_CHIP, argv[i])) {
47923ba6841SJoseph Chen 			i++;
48023ba6841SJoseph Chen 			snprintf(gOpts.chip, sizeof(gOpts.chip), "%s", argv[i]);
48123ba6841SJoseph Chen 			tag |= 0x20;
48223ba6841SJoseph Chen 		} else if (!strcmp(OPT_VERSION, argv[i])) {
48323ba6841SJoseph Chen 		}
48423ba6841SJoseph Chen 	}
48523ba6841SJoseph Chen 
48623ba6841SJoseph Chen 	sscanf(gOpts.loader[0].path, "%*[^v]v%d.%d.bin", &v0, &v1);
48723ba6841SJoseph Chen 	sscanf(gOpts.loader[1].path, "%*[^v]v%d.%d.bin", &v2, &v3);
48823ba6841SJoseph Chen 	gOpts.major = v2;
48923ba6841SJoseph Chen 	gOpts.minor = v3;
49023ba6841SJoseph Chen 	snprintf(gOpts.outPath, sizeof(gOpts.outPath),
49123ba6841SJoseph Chen 	         "%s_loader_v%d.%02d.%d%02d.bin", gOpts.chip, v0, v1, v2, v3);
49223ba6841SJoseph Chen 	return ((tag & 0x0f) == 0x0f) ? true : false;
49323ba6841SJoseph Chen }
49423ba6841SJoseph Chen 
initOpts(int argc,char ** argv)49523ba6841SJoseph Chen bool initOpts(int argc, char **argv)
49623ba6841SJoseph Chen {
49723ba6841SJoseph Chen 	bool ret;
49823ba6841SJoseph Chen 
49923ba6841SJoseph Chen 	/* set default opts */
50023ba6841SJoseph Chen 	gOpts.major = DEF_MAJOR;
50123ba6841SJoseph Chen 	gOpts.minor = DEF_MINOR;
50223ba6841SJoseph Chen 	strcpy(gOpts.chip, DEF_CHIP);
50323ba6841SJoseph Chen 	gOpts.code471Sleep = DEF_CODE471_SLEEP;
50423ba6841SJoseph Chen 	gOpts.code472Sleep = DEF_CODE472_SLEEP;
50523ba6841SJoseph Chen 	gOpts.code471Num = DEF_CODE471_NUM;
50623ba6841SJoseph Chen 	gOpts.code471Path = (line_t *)malloc(sizeof(line_t) * gOpts.code471Num);
50723ba6841SJoseph Chen 	strcpy((char *)gOpts.code471Path[0], DEF_CODE471_PATH);
50823ba6841SJoseph Chen 	gOpts.code472Num = DEF_CODE472_NUM;
50923ba6841SJoseph Chen 	gOpts.code472Path = (line_t *)malloc(sizeof(line_t) * gOpts.code472Num);
51023ba6841SJoseph Chen 	strcpy((char *)gOpts.code472Path[0], DEF_CODE472_PATH);
51123ba6841SJoseph Chen 	gOpts.loaderNum = DEF_LOADER_NUM;
51223ba6841SJoseph Chen 	gOpts.loader = (name_entry *)malloc(sizeof(name_entry) * gOpts.loaderNum);
51323ba6841SJoseph Chen 	strcpy(gOpts.loader[0].name, DEF_LOADER0);
51423ba6841SJoseph Chen 	strcpy(gOpts.loader[0].path, DEF_LOADER0_PATH);
51523ba6841SJoseph Chen 	strcpy(gOpts.loader[1].name, DEF_LOADER1);
51623ba6841SJoseph Chen 	strcpy(gOpts.loader[1].path, DEF_LOADER1_PATH);
51723ba6841SJoseph Chen 	strcpy(gOpts.outPath, DEF_OUT_PATH);
51823ba6841SJoseph Chen 
51923ba6841SJoseph Chen 	if (argc > 10)
52023ba6841SJoseph Chen 		ret = parseOpts_from_cmdline(argc, argv);
52123ba6841SJoseph Chen 	else
52223ba6841SJoseph Chen 		ret = parseOpts_from_file();
52323ba6841SJoseph Chen 
52423ba6841SJoseph Chen 	return ret;
52523ba6841SJoseph Chen }
52623ba6841SJoseph Chen 
52723ba6841SJoseph Chen /************merge code****************/
52823ba6841SJoseph Chen 
getBCD(unsigned short value)52923ba6841SJoseph Chen static inline uint32_t getBCD(unsigned short value)
53023ba6841SJoseph Chen {
53123ba6841SJoseph Chen 	uint8_t tmp[2] = { 0 };
53223ba6841SJoseph Chen 	int i;
53323ba6841SJoseph Chen 	uint32_t ret;
53423ba6841SJoseph Chen 	if (value > 0xFFFF) {
53523ba6841SJoseph Chen 		return 0;
53623ba6841SJoseph Chen 	}
53723ba6841SJoseph Chen 	for (i = 0; i < 2; i++) {
53823ba6841SJoseph Chen 		tmp[i] = (((value / 10) % 10) << 4) | (value % 10);
53923ba6841SJoseph Chen 		value /= 100;
54023ba6841SJoseph Chen 	}
54123ba6841SJoseph Chen 	ret = ((uint16_t)(tmp[1] << 8)) | tmp[0];
54223ba6841SJoseph Chen 
54323ba6841SJoseph Chen 	LOGD("ret:%x\n", ret);
54423ba6841SJoseph Chen 	return ret & 0xFF;
54523ba6841SJoseph Chen }
54623ba6841SJoseph Chen 
str2wide(const char * str,uint16_t * wide,int len)54723ba6841SJoseph Chen static inline void str2wide(const char *str, uint16_t *wide, int len)
54823ba6841SJoseph Chen {
54923ba6841SJoseph Chen 	int i;
55023ba6841SJoseph Chen 	for (i = 0; i < len; i++) {
55123ba6841SJoseph Chen 		wide[i] = (uint16_t) str[i];
55223ba6841SJoseph Chen 	}
55323ba6841SJoseph Chen 	wide[len] = 0;
55423ba6841SJoseph Chen }
55523ba6841SJoseph Chen 
getName(char * path,uint16_t * dst)55623ba6841SJoseph Chen static inline void getName(char *path, uint16_t *dst)
55723ba6841SJoseph Chen {
55823ba6841SJoseph Chen 	char *end;
55923ba6841SJoseph Chen 	char *start;
56023ba6841SJoseph Chen 	int len;
56123ba6841SJoseph Chen 	if (!path || !dst)
56223ba6841SJoseph Chen 		return;
56323ba6841SJoseph Chen 	start = strrchr(path, '/');
56423ba6841SJoseph Chen 	if (!start)
56523ba6841SJoseph Chen 		start = path;
56623ba6841SJoseph Chen 	else
56723ba6841SJoseph Chen 		start++;
56823ba6841SJoseph Chen 	end = strrchr(path, '.');
56923ba6841SJoseph Chen 	if (!end)
57023ba6841SJoseph Chen 		end = path + strlen(path);
57123ba6841SJoseph Chen 	len = end - start;
57223ba6841SJoseph Chen 	if (len >= MAX_NAME_LEN)
57323ba6841SJoseph Chen 		len = MAX_NAME_LEN - 1;
57423ba6841SJoseph Chen 	str2wide(start, dst, len);
57523ba6841SJoseph Chen 
57623ba6841SJoseph Chen 	if (gDebug) {
57723ba6841SJoseph Chen 		char name[MAX_NAME_LEN];
57823ba6841SJoseph Chen 		memset(name, 0, sizeof(name));
57923ba6841SJoseph Chen 		memcpy(name, start, len);
58023ba6841SJoseph Chen 		LOGD("path:%s, name:%s\n", path, name);
58123ba6841SJoseph Chen 	}
58223ba6841SJoseph Chen }
58323ba6841SJoseph Chen 
getFileSize(const char * path,uint32_t * size)58423ba6841SJoseph Chen static inline bool getFileSize(const char *path, uint32_t *size)
58523ba6841SJoseph Chen {
58623ba6841SJoseph Chen 	struct stat st;
58723ba6841SJoseph Chen 	if (stat(path, &st) < 0)
58823ba6841SJoseph Chen 		return false;
58923ba6841SJoseph Chen 	*size = st.st_size;
59023ba6841SJoseph Chen 	LOGD("path:%s, size:%d\n", path, *size);
59123ba6841SJoseph Chen 	return true;
59223ba6841SJoseph Chen }
59323ba6841SJoseph Chen 
getTime(void)59423ba6841SJoseph Chen static inline rk_time getTime(void)
59523ba6841SJoseph Chen {
59623ba6841SJoseph Chen 	rk_time rkTime;
59723ba6841SJoseph Chen 
59823ba6841SJoseph Chen 	struct tm *tm;
59923ba6841SJoseph Chen 	time_t tt = time(NULL);
60023ba6841SJoseph Chen 	tm = localtime(&tt);
60123ba6841SJoseph Chen 	rkTime.year = tm->tm_year + 1900;
60223ba6841SJoseph Chen 	rkTime.month = tm->tm_mon + 1;
60323ba6841SJoseph Chen 	rkTime.day = tm->tm_mday;
60423ba6841SJoseph Chen 	rkTime.hour = tm->tm_hour;
60523ba6841SJoseph Chen 	rkTime.minute = tm->tm_min;
60623ba6841SJoseph Chen 	rkTime.second = tm->tm_sec;
60723ba6841SJoseph Chen 	LOGD("%d-%d-%d %02d:%02d:%02d\n", rkTime.year, rkTime.month, rkTime.day,
60823ba6841SJoseph Chen 	     rkTime.hour, rkTime.minute, rkTime.second);
60923ba6841SJoseph Chen 	return rkTime;
61023ba6841SJoseph Chen }
61123ba6841SJoseph Chen 
writeFile(FILE * outFile,const char * path,bool fix)61223ba6841SJoseph Chen static bool writeFile(FILE *outFile, const char *path, bool fix)
61323ba6841SJoseph Chen {
61423ba6841SJoseph Chen 	bool ret = false;
61523ba6841SJoseph Chen 	uint32_t size = 0, fixSize = 0;
61623ba6841SJoseph Chen 	uint8_t *buf;
61723ba6841SJoseph Chen 
61823ba6841SJoseph Chen 	FILE *inFile = fopen(path, "rb");
61923ba6841SJoseph Chen 	if (!inFile)
62023ba6841SJoseph Chen 		goto end;
62123ba6841SJoseph Chen 
62223ba6841SJoseph Chen 	if (!getFileSize(path, &size))
62323ba6841SJoseph Chen 		goto end;
62423ba6841SJoseph Chen 	if (fix) {
62523ba6841SJoseph Chen 		fixSize = ((size - 1) / SMALL_PACKET + 1) * SMALL_PACKET;
62623ba6841SJoseph Chen 		uint32_t tmp = fixSize % ENTRY_ALIGN;
62723ba6841SJoseph Chen 		tmp = tmp ? (ENTRY_ALIGN - tmp) : 0;
62823ba6841SJoseph Chen 		fixSize += tmp;
62923ba6841SJoseph Chen 		memset(gBuf, 0, fixSize);
63023ba6841SJoseph Chen 	} else {
63123ba6841SJoseph Chen 		memset(gBuf, 0, size + ENTRY_ALIGN);
63223ba6841SJoseph Chen 	}
63323ba6841SJoseph Chen 	if (!fread(gBuf, size, 1, inFile))
63423ba6841SJoseph Chen 		goto end;
63523ba6841SJoseph Chen 
63623ba6841SJoseph Chen 	if (fix) {
63723ba6841SJoseph Chen 
63823ba6841SJoseph Chen 		buf = gBuf;
63923ba6841SJoseph Chen 		size = fixSize;
64023ba6841SJoseph Chen 		while (1) {
64123ba6841SJoseph Chen 			P_RC4(buf, fixSize < SMALL_PACKET ? fixSize : SMALL_PACKET);
64223ba6841SJoseph Chen 			buf += SMALL_PACKET;
64323ba6841SJoseph Chen 			if (fixSize <= SMALL_PACKET)
64423ba6841SJoseph Chen 				break;
64523ba6841SJoseph Chen 			fixSize -= SMALL_PACKET;
64623ba6841SJoseph Chen 		}
64723ba6841SJoseph Chen 	} else {
64823ba6841SJoseph Chen 		uint32_t tmp = size % ENTRY_ALIGN;
64923ba6841SJoseph Chen 		tmp = tmp ? (ENTRY_ALIGN - tmp) : 0;
65023ba6841SJoseph Chen 		size += tmp;
65123ba6841SJoseph Chen 		P_RC4(gBuf, size);
65223ba6841SJoseph Chen 	}
65323ba6841SJoseph Chen 
65423ba6841SJoseph Chen 	if (!fwrite(gBuf, size, 1, outFile))
65523ba6841SJoseph Chen 		goto end;
65623ba6841SJoseph Chen 	ret = true;
65723ba6841SJoseph Chen end:
65823ba6841SJoseph Chen 	if (inFile)
65923ba6841SJoseph Chen 		fclose(inFile);
66023ba6841SJoseph Chen 	if (!ret)
66123ba6841SJoseph Chen 		LOGE("write entry(%s) failed\n", path);
66223ba6841SJoseph Chen 	return ret;
66323ba6841SJoseph Chen }
66423ba6841SJoseph Chen 
saveEntry(FILE * outFile,char * path,rk_entry_type type,uint16_t delay,uint32_t * offset,char * fixName,bool fix)66523ba6841SJoseph Chen static bool saveEntry(FILE *outFile, char *path, rk_entry_type type,
66623ba6841SJoseph Chen                       uint16_t delay, uint32_t *offset, char *fixName,
66723ba6841SJoseph Chen                       bool fix)
66823ba6841SJoseph Chen {
66923ba6841SJoseph Chen 	LOGD("write:%s\n", path);
67023ba6841SJoseph Chen 	uint32_t size;
67123ba6841SJoseph Chen 	rk_boot_entry entry;
67223ba6841SJoseph Chen 	memset(&entry, 0, sizeof(rk_boot_entry));
67323ba6841SJoseph Chen 
67423ba6841SJoseph Chen 	LOGD("write:%s\n", path);
67523ba6841SJoseph Chen 
67623ba6841SJoseph Chen 	getName(fixName ? fixName : path, entry.name);
67723ba6841SJoseph Chen 	entry.size = sizeof(rk_boot_entry);
67823ba6841SJoseph Chen 	entry.type = type;
67923ba6841SJoseph Chen 	entry.dataOffset = *offset;
68023ba6841SJoseph Chen 	if (!getFileSize(path, &size)) {
68123ba6841SJoseph Chen 		LOGE("save entry(%s) failed:\n\tcannot get file size.\n", path);
68223ba6841SJoseph Chen 		return false;
68323ba6841SJoseph Chen 	}
68423ba6841SJoseph Chen 	if (fix)
68523ba6841SJoseph Chen 		size = ((size - 1) / SMALL_PACKET + 1) * SMALL_PACKET;
68623ba6841SJoseph Chen 	uint32_t tmp = size % ENTRY_ALIGN;
68723ba6841SJoseph Chen 	size += tmp ? (ENTRY_ALIGN - tmp) : 0;
68823ba6841SJoseph Chen 	LOGD("align size:%d\n", size);
68923ba6841SJoseph Chen 	entry.dataSize = size;
69023ba6841SJoseph Chen 	entry.dataDelay = delay;
69123ba6841SJoseph Chen 	*offset += size;
69223ba6841SJoseph Chen 	fwrite(&entry, sizeof(rk_boot_entry), 1, outFile);
69323ba6841SJoseph Chen 	return true;
69423ba6841SJoseph Chen }
69523ba6841SJoseph Chen 
convertChipType(const char * chip)69623ba6841SJoseph Chen static inline uint32_t convertChipType(const char *chip)
69723ba6841SJoseph Chen {
69823ba6841SJoseph Chen 	char buffer[5];
69923ba6841SJoseph Chen 	memset(buffer, 0, sizeof(buffer));
70023ba6841SJoseph Chen 	snprintf(buffer, sizeof(buffer), "%s", chip);
70123ba6841SJoseph Chen 	return buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
70223ba6841SJoseph Chen }
70323ba6841SJoseph Chen 
getChipType(const char * chip)70423ba6841SJoseph Chen static inline uint32_t getChipType(const char *chip)
70523ba6841SJoseph Chen {
70623ba6841SJoseph Chen 	LOGD("chip:%s\n", chip);
70723ba6841SJoseph Chen 	int chipType = RKNONE_DEVICE;
70823ba6841SJoseph Chen 	if (!chip) {
70923ba6841SJoseph Chen 		goto end;
71023ba6841SJoseph Chen 	}
71123ba6841SJoseph Chen 	if (!strcmp(chip, CHIP_RK28)) {
71223ba6841SJoseph Chen 		chipType = RK28_DEVICE;
71323ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK28)) {
71423ba6841SJoseph Chen 		chipType = RK28_DEVICE;
71523ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK281X)) {
71623ba6841SJoseph Chen 		chipType = RK281X_DEVICE;
71723ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RKPANDA)) {
71823ba6841SJoseph Chen 		chipType = RKPANDA_DEVICE;
71923ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK27)) {
72023ba6841SJoseph Chen 		chipType = RK27_DEVICE;
72123ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RKNANO)) {
72223ba6841SJoseph Chen 		chipType = RKNANO_DEVICE;
72323ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RKSMART)) {
72423ba6841SJoseph Chen 		chipType = RKSMART_DEVICE;
72523ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RKCROWN)) {
72623ba6841SJoseph Chen 		chipType = RKCROWN_DEVICE;
72723ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RKCAYMAN)) {
72823ba6841SJoseph Chen 		chipType = RKCAYMAN_DEVICE;
72923ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK29)) {
73023ba6841SJoseph Chen 		chipType = RK29_DEVICE;
73123ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK292X)) {
73223ba6841SJoseph Chen 		chipType = RK292X_DEVICE;
73323ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK30)) {
73423ba6841SJoseph Chen 		chipType = RK30_DEVICE;
73523ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK30B)) {
73623ba6841SJoseph Chen 		chipType = RK30B_DEVICE;
73723ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK31)) {
73823ba6841SJoseph Chen 		chipType = RK31_DEVICE;
73923ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK32)) {
74023ba6841SJoseph Chen 		chipType = RK32_DEVICE;
74123ba6841SJoseph Chen 	} else {
74223ba6841SJoseph Chen 		chipType = convertChipType(chip + 2);
74323ba6841SJoseph Chen 	}
74423ba6841SJoseph Chen 
74523ba6841SJoseph Chen end:
74623ba6841SJoseph Chen 	LOGD("type:0x%x\n", chipType);
74723ba6841SJoseph Chen 	if (chipType == RKNONE_DEVICE) {
74823ba6841SJoseph Chen 		LOGE("chip type not support!\n");
74923ba6841SJoseph Chen 	}
75023ba6841SJoseph Chen 	return chipType;
75123ba6841SJoseph Chen }
75223ba6841SJoseph Chen 
getBoothdr(rk_boot_header * hdr)75323ba6841SJoseph Chen static inline void getBoothdr(rk_boot_header *hdr)
75423ba6841SJoseph Chen {
75523ba6841SJoseph Chen 	memset(hdr, 0, sizeof(rk_boot_header));
75623ba6841SJoseph Chen 	hdr->tag = TAG;
75723ba6841SJoseph Chen 	hdr->size = sizeof(rk_boot_header);
75823ba6841SJoseph Chen 	hdr->version = (getBCD(gOpts.major) << 8) | getBCD(gOpts.minor);
75923ba6841SJoseph Chen 	hdr->mergerVersion = MERGER_VERSION;
76023ba6841SJoseph Chen 	hdr->releaseTime = getTime();
76123ba6841SJoseph Chen 	hdr->chipType = getChipType(gOpts.chip);
76223ba6841SJoseph Chen 
76323ba6841SJoseph Chen 	hdr->code471Num = gOpts.code471Num;
76423ba6841SJoseph Chen 	hdr->code471Offset = sizeof(rk_boot_header);
76523ba6841SJoseph Chen 	hdr->code471Size = sizeof(rk_boot_entry);
76623ba6841SJoseph Chen 
76723ba6841SJoseph Chen 	hdr->code472Num = gOpts.code472Num;
76823ba6841SJoseph Chen 	hdr->code472Offset = hdr->code471Offset + gOpts.code471Num * hdr->code471Size;
76923ba6841SJoseph Chen 	hdr->code472Size = sizeof(rk_boot_entry);
77023ba6841SJoseph Chen 
77123ba6841SJoseph Chen 	hdr->loaderNum = gOpts.loaderNum;
77223ba6841SJoseph Chen 	hdr->loaderOffset = hdr->code472Offset + gOpts.code472Num * hdr->code472Size;
77323ba6841SJoseph Chen 	hdr->loaderSize = sizeof(rk_boot_entry);
774*24f9e652SJoseph Chen 	if (!enableRC4)
77523ba6841SJoseph Chen 		hdr->rc4Flag = 1;
77623ba6841SJoseph Chen }
77723ba6841SJoseph Chen 
getCrc(const char * path)77823ba6841SJoseph Chen static inline uint32_t getCrc(const char *path)
77923ba6841SJoseph Chen {
78023ba6841SJoseph Chen 	uint32_t size = 0;
78123ba6841SJoseph Chen 	uint32_t crc = 0;
78223ba6841SJoseph Chen 	FILE *file = fopen(path, "rb");
78323ba6841SJoseph Chen 	getFileSize(path, &size);
78423ba6841SJoseph Chen 	if (!file)
78523ba6841SJoseph Chen 		goto end;
78623ba6841SJoseph Chen 	if (!fread(gBuf, size, 1, file))
78723ba6841SJoseph Chen 		goto end;
78823ba6841SJoseph Chen 	crc = CRC_32(gBuf, size);
78923ba6841SJoseph Chen 	LOGD("crc:0x%08x\n", crc);
79023ba6841SJoseph Chen end:
79123ba6841SJoseph Chen 	if (file)
79223ba6841SJoseph Chen 		fclose(file);
79323ba6841SJoseph Chen 	return crc;
79423ba6841SJoseph Chen }
79523ba6841SJoseph Chen 
mergeBoot(int argc,char ** argv)79623ba6841SJoseph Chen static bool mergeBoot(int argc, char **argv)
79723ba6841SJoseph Chen {
79823ba6841SJoseph Chen 	uint32_t dataOffset;
79923ba6841SJoseph Chen 	bool ret = false;
80023ba6841SJoseph Chen 	int i;
80123ba6841SJoseph Chen 	FILE *outFile;
80223ba6841SJoseph Chen 	uint32_t crc;
80323ba6841SJoseph Chen 	rk_boot_header hdr;
80423ba6841SJoseph Chen 
80523ba6841SJoseph Chen 	if (!initOpts(argc, argv))
80623ba6841SJoseph Chen 		return false;
80723ba6841SJoseph Chen 	{
80823ba6841SJoseph Chen 		char *subfix = strstr(gOpts.outPath, OUT_SUBFIX);
80923ba6841SJoseph Chen 		char version[MAX_LINE_LEN];
81023ba6841SJoseph Chen 		snprintf(version, sizeof(version), "%s", gSubfix);
81123ba6841SJoseph Chen 		if (subfix && !strcmp(subfix, OUT_SUBFIX)) {
81223ba6841SJoseph Chen 			subfix[0] = '\0';
81323ba6841SJoseph Chen 		}
81423ba6841SJoseph Chen 		strcat(gOpts.outPath, version);
81523ba6841SJoseph Chen 		printf("fix opt:%s\n", gOpts.outPath);
81623ba6841SJoseph Chen 	}
81723ba6841SJoseph Chen 
81823ba6841SJoseph Chen 	if (gDebug) {
81923ba6841SJoseph Chen 		printf("---------------\nUSING CONFIG:\n");
82023ba6841SJoseph Chen 		printOpts(stdout);
82123ba6841SJoseph Chen 		printf("---------------\n\n");
82223ba6841SJoseph Chen 	}
82323ba6841SJoseph Chen 
82423ba6841SJoseph Chen 	outFile = fopen(gOpts.outPath, "wb+");
82523ba6841SJoseph Chen 	if (!outFile) {
82623ba6841SJoseph Chen 		LOGE("open out file(%s) failed\n", gOpts.outPath);
82723ba6841SJoseph Chen 		goto end;
82823ba6841SJoseph Chen 	}
82923ba6841SJoseph Chen 
83023ba6841SJoseph Chen 	getBoothdr(&hdr);
83123ba6841SJoseph Chen 	LOGD("write hdr\n");
83223ba6841SJoseph Chen 	fwrite(&hdr, 1, sizeof(rk_boot_header), outFile);
83323ba6841SJoseph Chen 
83423ba6841SJoseph Chen 	dataOffset = sizeof(rk_boot_header) +
83523ba6841SJoseph Chen 	             (gOpts.code471Num + gOpts.code472Num + gOpts.loaderNum) *
83623ba6841SJoseph Chen 	             sizeof(rk_boot_entry);
83723ba6841SJoseph Chen 
83823ba6841SJoseph Chen 	LOGD("write code 471 entry\n");
83923ba6841SJoseph Chen 	for (i = 0; i < gOpts.code471Num; i++) {
84023ba6841SJoseph Chen 		if (!saveEntry(outFile, (char *)gOpts.code471Path[i], ENTRY_471,
84123ba6841SJoseph Chen 		               gOpts.code471Sleep, &dataOffset, NULL, false))
84223ba6841SJoseph Chen 			goto end;
84323ba6841SJoseph Chen 	}
84423ba6841SJoseph Chen 	LOGD("write code 472 entry\n");
84523ba6841SJoseph Chen 	for (i = 0; i < gOpts.code472Num; i++) {
84623ba6841SJoseph Chen 		if (!saveEntry(outFile, (char *)gOpts.code472Path[i], ENTRY_472,
84723ba6841SJoseph Chen 		               gOpts.code472Sleep, &dataOffset, NULL, false))
84823ba6841SJoseph Chen 			goto end;
84923ba6841SJoseph Chen 	}
85023ba6841SJoseph Chen 	LOGD("write loader entry\n");
85123ba6841SJoseph Chen 	for (i = 0; i < gOpts.loaderNum; i++) {
85223ba6841SJoseph Chen 		if (!saveEntry(outFile, gOpts.loader[i].path, ENTRY_LOADER, 0, &dataOffset,
85323ba6841SJoseph Chen 		               gOpts.loader[i].name, true))
85423ba6841SJoseph Chen 			goto end;
85523ba6841SJoseph Chen 	}
85623ba6841SJoseph Chen 
85723ba6841SJoseph Chen 	LOGD("write code 471\n");
85823ba6841SJoseph Chen 	for (i = 0; i < gOpts.code471Num; i++) {
85923ba6841SJoseph Chen 		if (!writeFile(outFile, (char *)gOpts.code471Path[i], false))
86023ba6841SJoseph Chen 			goto end;
86123ba6841SJoseph Chen 	}
86223ba6841SJoseph Chen 	LOGD("write code 472\n");
86323ba6841SJoseph Chen 	for (i = 0; i < gOpts.code472Num; i++) {
86423ba6841SJoseph Chen 		if (!writeFile(outFile, (char *)gOpts.code472Path[i], false))
86523ba6841SJoseph Chen 			goto end;
86623ba6841SJoseph Chen 	}
86723ba6841SJoseph Chen 	LOGD("write loader\n");
86823ba6841SJoseph Chen 	for (i = 0; i < gOpts.loaderNum; i++) {
86923ba6841SJoseph Chen 		if (!writeFile(outFile, gOpts.loader[i].path, true))
87023ba6841SJoseph Chen 			goto end;
87123ba6841SJoseph Chen 	}
87223ba6841SJoseph Chen 	fflush(outFile);
87323ba6841SJoseph Chen 
87423ba6841SJoseph Chen 	LOGD("write crc\n");
87523ba6841SJoseph Chen 	crc = getCrc(gOpts.outPath);
87623ba6841SJoseph Chen 	if (!fwrite(&crc, sizeof(crc), 1, outFile))
87723ba6841SJoseph Chen 		goto end;
87823ba6841SJoseph Chen 
87923ba6841SJoseph Chen 	ret = true;
88023ba6841SJoseph Chen end:
88123ba6841SJoseph Chen 	if (outFile)
88223ba6841SJoseph Chen 		fclose(outFile);
88323ba6841SJoseph Chen 	return ret;
88423ba6841SJoseph Chen }
88523ba6841SJoseph Chen 
88623ba6841SJoseph Chen /************merge code end************/
88723ba6841SJoseph Chen /************unpack code***************/
88823ba6841SJoseph Chen 
wide2str(const uint16_t * wide,char * str,int len)88923ba6841SJoseph Chen static inline void wide2str(const uint16_t *wide, char *str, int len)
89023ba6841SJoseph Chen {
89123ba6841SJoseph Chen 	int i;
89223ba6841SJoseph Chen 	for (i = 0; i < len; i++) {
89323ba6841SJoseph Chen 		str[i] = (char)(wide[i] & 0xFF);
89423ba6841SJoseph Chen 	}
89523ba6841SJoseph Chen 	str[len] = 0;
89623ba6841SJoseph Chen }
89723ba6841SJoseph Chen 
unpackEntry(rk_boot_entry * entry,const char * name,FILE * inFile)89823ba6841SJoseph Chen static bool unpackEntry(rk_boot_entry *entry, const char *name, FILE *inFile)
89923ba6841SJoseph Chen {
90023ba6841SJoseph Chen 	bool ret = false;
90123ba6841SJoseph Chen 	int size, i;
90223ba6841SJoseph Chen 	FILE *outFile = fopen(name, "wb+");
90323ba6841SJoseph Chen 	if (!outFile)
90423ba6841SJoseph Chen 		goto end;
90523ba6841SJoseph Chen 	printf("unpack entry(%s)\n", name);
90623ba6841SJoseph Chen 	fseek(inFile, entry->dataOffset, SEEK_SET);
90723ba6841SJoseph Chen 	size = entry->dataSize;
90823ba6841SJoseph Chen 	if (!fread(gBuf, size, 1, inFile))
90923ba6841SJoseph Chen 		goto end;
91023ba6841SJoseph Chen 	if (entry->type == ENTRY_LOADER) {
91123ba6841SJoseph Chen 		for (i = 0; i < size / SMALL_PACKET; i++)
91223ba6841SJoseph Chen 			P_RC4(gBuf + i * SMALL_PACKET, SMALL_PACKET);
91323ba6841SJoseph Chen 		if (size % SMALL_PACKET) {
91423ba6841SJoseph Chen 			P_RC4(gBuf + i * SMALL_PACKET, size - SMALL_PACKET * 512);
91523ba6841SJoseph Chen 		}
91623ba6841SJoseph Chen 	} else {
91723ba6841SJoseph Chen 		P_RC4(gBuf, size);
91823ba6841SJoseph Chen 	}
91923ba6841SJoseph Chen 	if (!fwrite(gBuf, size, 1, outFile))
92023ba6841SJoseph Chen 		goto end;
92123ba6841SJoseph Chen 	ret = true;
92223ba6841SJoseph Chen end:
92323ba6841SJoseph Chen 	if (outFile)
92423ba6841SJoseph Chen 		fclose(outFile);
92523ba6841SJoseph Chen 	return ret;
92623ba6841SJoseph Chen }
92723ba6841SJoseph Chen 
unpackBoot(char * path)92823ba6841SJoseph Chen static bool unpackBoot(char *path)
92923ba6841SJoseph Chen {
93023ba6841SJoseph Chen 	bool ret = false;
93123ba6841SJoseph Chen 	FILE *inFile = fopen(path, "rb");
93223ba6841SJoseph Chen 	int entryNum, i;
93323ba6841SJoseph Chen 	char name[MAX_NAME_LEN];
93423ba6841SJoseph Chen 	rk_boot_entry *entrys;
93523ba6841SJoseph Chen 	if (!inFile) {
93623ba6841SJoseph Chen 		fprintf(stderr, "loader(%s) not found\n", path);
93723ba6841SJoseph Chen 		goto end;
93823ba6841SJoseph Chen 	}
93923ba6841SJoseph Chen 
94023ba6841SJoseph Chen 	rk_boot_header hdr;
94123ba6841SJoseph Chen 	if (!fread(&hdr, sizeof(rk_boot_header), 1, inFile)) {
94223ba6841SJoseph Chen 		fprintf(stderr, "read header failed\n");
94323ba6841SJoseph Chen 		goto end;
94423ba6841SJoseph Chen 	}
94523ba6841SJoseph Chen 
94623ba6841SJoseph Chen 	entryNum = hdr.code471Num + hdr.code472Num + hdr.loaderNum;
94723ba6841SJoseph Chen 	entrys = (rk_boot_entry *)malloc(sizeof(rk_boot_entry) * entryNum);
94823ba6841SJoseph Chen 	if (!fread(entrys, sizeof(rk_boot_entry) * entryNum, 1, inFile)) {
94923ba6841SJoseph Chen 		fprintf(stderr, "read data failed\n");
95023ba6841SJoseph Chen 		goto end;
95123ba6841SJoseph Chen 	}
95223ba6841SJoseph Chen 
95323ba6841SJoseph Chen 	LOGD("entry num:%d\n", entryNum);
95423ba6841SJoseph Chen 	for (i = 0; i < entryNum; i++) {
95523ba6841SJoseph Chen 		wide2str(entrys[i].name, name, MAX_NAME_LEN);
95623ba6841SJoseph Chen 
95723ba6841SJoseph Chen 		LOGD("entry:t=%d, name=%s, off=%d, size=%d\n", entrys[i].type, name,
95823ba6841SJoseph Chen 		     entrys[i].dataOffset, entrys[i].dataSize);
95923ba6841SJoseph Chen 		if (!unpackEntry(entrys + i, name, inFile)) {
96023ba6841SJoseph Chen 			fprintf(stderr, "unpack entry(%s) failed\n", name);
96123ba6841SJoseph Chen 			goto end;
96223ba6841SJoseph Chen 		}
96323ba6841SJoseph Chen 	}
96423ba6841SJoseph Chen 
96523ba6841SJoseph Chen 	ret = true;
96623ba6841SJoseph Chen end:
96723ba6841SJoseph Chen 	if (inFile)
96823ba6841SJoseph Chen 		fclose(inFile);
96923ba6841SJoseph Chen 	return ret;
97023ba6841SJoseph Chen }
97123ba6841SJoseph Chen 
97223ba6841SJoseph Chen /************unpack code end***********/
97323ba6841SJoseph Chen 
printHelp(void)97423ba6841SJoseph Chen static void printHelp(void)
97523ba6841SJoseph Chen {
97623ba6841SJoseph Chen 	printf("Usage1: boot_merger [options]... FILE\n");
97723ba6841SJoseph Chen 	printf("Merge or unpack Rockchip's loader (Default action is to merge.)\n");
97823ba6841SJoseph Chen 	printf("Options:\n");
97923ba6841SJoseph Chen 	printf("\t" OPT_MERGE "\t\t\tMerge loader with specified config.\n");
98023ba6841SJoseph Chen 	printf("\t" OPT_UNPACK "\t\tUnpack specified loader to current dir.\n");
98123ba6841SJoseph Chen 	printf("\t" OPT_VERBOSE "\t\tDisplay more runtime informations.\n");
98223ba6841SJoseph Chen 	printf("\t" OPT_HELP "\t\t\tDisplay this information.\n");
98323ba6841SJoseph Chen 	printf("\t" OPT_VERSION "\t\tDisplay version information.\n");
98423ba6841SJoseph Chen 	printf("\t" OPT_SUBFIX "\t\tSpec subfix.\n");
98523ba6841SJoseph Chen 	printf("\t" OPT_REPLACE "\t\tReplace some part of binary path.\n");
986e311da24SJoseph Chen 	printf("\t" OPT_PREPATH "\t\tAdd prefix path of binary path.\n");
98723ba6841SJoseph Chen 	printf("\t" OPT_SIZE
98823ba6841SJoseph Chen 	       "\t\tImage size.\"--size [image KB size]\", must be 512KB aligned\n");
98923ba6841SJoseph Chen 	printf("Usage2: boot_merger [options] [parameter]\n");
99023ba6841SJoseph Chen 	printf("All below five option are must in this mode!\n");
99123ba6841SJoseph Chen 	printf("\t" OPT_CHIP "\t\tChip type, used for check with usbplug.\n");
99223ba6841SJoseph Chen 	printf("\t" OPT_471 "\t\t471 for download, ddr.bin.\n");
99323ba6841SJoseph Chen 	printf("\t" OPT_472 "\t\t472 for download, usbplug.bin.\n");
99423ba6841SJoseph Chen 	printf("\t" OPT_DATA "\t\tloader0 for flash, ddr.bin.\n");
99523ba6841SJoseph Chen 	printf("\t" OPT_BOOT "\t\tloader1 for flash, miniloader.bin.\n");
99623ba6841SJoseph Chen 	printf("\n./tools/boot_merger --pack --verbose -c RK322A -1 "
99723ba6841SJoseph Chen 	       "rkbin/rk322x_ddr_300MHz_v1.04.bin -2 "
99823ba6841SJoseph Chen 	       "rkbin/rk32/rk322x_usbplug_v2.32.bin -d "
99923ba6841SJoseph Chen 	       "rkbin/rk32/rk322x_ddr_300MHz_v1.04.bin -b "
100023ba6841SJoseph Chen 	       "rkbin/rk32/rk322x_miniloader_v2.32.bin\n");
100123ba6841SJoseph Chen }
100223ba6841SJoseph Chen 
main(int argc,char ** argv)100323ba6841SJoseph Chen int main(int argc, char **argv)
100423ba6841SJoseph Chen {
100523ba6841SJoseph Chen 
100623ba6841SJoseph Chen 	int i;
100723ba6841SJoseph Chen 	bool merge = true;
100823ba6841SJoseph Chen 	char *optPath = NULL;
100923ba6841SJoseph Chen 
101023ba6841SJoseph Chen 	for (i = 1; i < argc; i++) {
101123ba6841SJoseph Chen 		if (!strcmp(OPT_VERBOSE, argv[i])) {
101223ba6841SJoseph Chen 			gDebug = true;
101323ba6841SJoseph Chen 			printf("enable debug\n");
101423ba6841SJoseph Chen 		} else if (!strcmp(OPT_HELP, argv[i])) {
101523ba6841SJoseph Chen 			printHelp();
101623ba6841SJoseph Chen 			return 0;
101723ba6841SJoseph Chen 		} else if (!strcmp(OPT_VERSION, argv[i])) {
101823ba6841SJoseph Chen 			printf("boot_merger (cjf@rock-chips.com)\t" VERSION "\n");
101923ba6841SJoseph Chen 			return 0;
102023ba6841SJoseph Chen 		} else if (!strcmp(OPT_MERGE, argv[i])) {
102123ba6841SJoseph Chen 			merge = true;
102223ba6841SJoseph Chen 		} else if (!strcmp(OPT_UNPACK, argv[i])) {
102323ba6841SJoseph Chen 			merge = false;
1024*24f9e652SJoseph Chen 		} else if (!strcmp(OPT_RC4, argv[i])) {
1025*24f9e652SJoseph Chen 			printf("enable RC4 for IDB data(both ddr and preloader)\n");
1026*24f9e652SJoseph Chen 			enableRC4 = true;
102723ba6841SJoseph Chen 		} else if (!strcmp(OPT_SUBFIX, argv[i])) {
102823ba6841SJoseph Chen 			i++;
102923ba6841SJoseph Chen 			snprintf(gSubfix, sizeof(gSubfix), "%s", argv[i]);
103023ba6841SJoseph Chen 		} else if (!strcmp(OPT_REPLACE, argv[i])) {
103123ba6841SJoseph Chen 			i++;
103223ba6841SJoseph Chen 			snprintf(gLegacyPath, sizeof(gLegacyPath), "%s", argv[i]);
103323ba6841SJoseph Chen 			i++;
103423ba6841SJoseph Chen 			snprintf(gNewPath, sizeof(gNewPath), "%s", argv[i]);
1035e311da24SJoseph Chen 		} else if (!strcmp(OPT_PREPATH, argv[i])) {
1036e311da24SJoseph Chen 			i++;
1037e311da24SJoseph Chen 			gPrePath = argv[i];
103823ba6841SJoseph Chen 		} else if (!strcmp(OPT_SIZE, argv[i])) {
103923ba6841SJoseph Chen 			g_merge_max_size = strtoul(argv[++i], NULL, 10);
104023ba6841SJoseph Chen 			if (g_merge_max_size % 512) {
104123ba6841SJoseph Chen 				printHelp();
104223ba6841SJoseph Chen 				return -1;
104323ba6841SJoseph Chen 			}
104423ba6841SJoseph Chen 			g_merge_max_size *= 1024; /* bytes */
104523ba6841SJoseph Chen 		} else {
104623ba6841SJoseph Chen 			optPath = argv[i];
104723ba6841SJoseph Chen 			break;
104823ba6841SJoseph Chen 		}
104923ba6841SJoseph Chen 	}
105023ba6841SJoseph Chen 	if (!merge && !optPath) {
105123ba6841SJoseph Chen 		fprintf(stderr, "need set out path to unpack!\n");
105223ba6841SJoseph Chen 		printHelp();
105323ba6841SJoseph Chen 		return -1;
105423ba6841SJoseph Chen 	}
105523ba6841SJoseph Chen 
105623ba6841SJoseph Chen 	gBuf = calloc(g_merge_max_size, 1);
105723ba6841SJoseph Chen 	if (!gBuf) {
105823ba6841SJoseph Chen 		LOGE("Merge image: calloc buffer error.\n");
105923ba6841SJoseph Chen 		return -1;
106023ba6841SJoseph Chen 	}
106123ba6841SJoseph Chen 
106223ba6841SJoseph Chen 	if (merge) {
106323ba6841SJoseph Chen 		LOGD("do_merge\n");
106423ba6841SJoseph Chen 		gConfigPath = optPath;
106523ba6841SJoseph Chen 		if (!mergeBoot(argc, argv)) {
106623ba6841SJoseph Chen 			fprintf(stderr, "merge failed!\n");
106723ba6841SJoseph Chen 			return -1;
106823ba6841SJoseph Chen 		}
106923ba6841SJoseph Chen 		printf("merge success(%s)\n", gOpts.outPath);
107023ba6841SJoseph Chen 	} else {
107123ba6841SJoseph Chen 		LOGD("do_unpack\n");
107223ba6841SJoseph Chen 		if (!unpackBoot(optPath)) {
107323ba6841SJoseph Chen 			fprintf(stderr, "unpack failed!\n");
107423ba6841SJoseph Chen 			return -1;
107523ba6841SJoseph Chen 		}
107623ba6841SJoseph Chen 		printf("unpack success\n");
107723ba6841SJoseph Chen 	}
107823ba6841SJoseph Chen 	return 0;
107923ba6841SJoseph Chen }
1080