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