xref: /rk3399_rockchip-uboot/tools/rockchip/boot_merger.c (revision 23ba6841ccdaeb51290dc49d4e32f175bd3baa34)
1*23ba6841SJoseph Chen /*
2*23ba6841SJoseph Chen  * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
3*23ba6841SJoseph Chen  *
4*23ba6841SJoseph Chen  * SPDX-License-Identifier:	GPL-2.0+
5*23ba6841SJoseph Chen  */
6*23ba6841SJoseph Chen #include "boot_merger.h"
7*23ba6841SJoseph Chen #include <time.h>
8*23ba6841SJoseph Chen #include <sys/stat.h>
9*23ba6841SJoseph Chen #include <version.h>
10*23ba6841SJoseph Chen 
11*23ba6841SJoseph Chen /* #define USE_P_RC4 */
12*23ba6841SJoseph Chen 
13*23ba6841SJoseph Chen bool gDebug =
14*23ba6841SJoseph Chen #ifdef DEBUG
15*23ba6841SJoseph Chen         true;
16*23ba6841SJoseph Chen #else
17*23ba6841SJoseph Chen         false;
18*23ba6841SJoseph Chen #endif /* DEBUG */
19*23ba6841SJoseph Chen 
20*23ba6841SJoseph Chen #define ENTRY_ALIGN (2048)
21*23ba6841SJoseph Chen options gOpts;
22*23ba6841SJoseph Chen char gLegacyPath[MAX_LINE_LEN] = { 0 };
23*23ba6841SJoseph Chen char gNewPath[MAX_LINE_LEN] = { 0 };
24*23ba6841SJoseph Chen char gSubfix[MAX_LINE_LEN] = OUT_SUBFIX;
25*23ba6841SJoseph Chen char gEat[MAX_LINE_LEN];
26*23ba6841SJoseph Chen char *gConfigPath;
27*23ba6841SJoseph Chen uint8_t *gBuf;
28*23ba6841SJoseph Chen 
29*23ba6841SJoseph Chen static uint32_t g_merge_max_size = MAX_MERGE_SIZE;
30*23ba6841SJoseph Chen 
31*23ba6841SJoseph Chen uint32_t gTable_Crc32[256] = {
32*23ba6841SJoseph Chen 	0x00000000, 0x04c10db7, 0x09821b6e, 0x0d4316d9, 0x130436dc, 0x17c53b6b,
33*23ba6841SJoseph Chen 	0x1a862db2, 0x1e472005, 0x26086db8, 0x22c9600f, 0x2f8a76d6, 0x2b4b7b61,
34*23ba6841SJoseph Chen 	0x350c5b64, 0x31cd56d3, 0x3c8e400a, 0x384f4dbd, 0x4c10db70, 0x48d1d6c7,
35*23ba6841SJoseph Chen 	0x4592c01e, 0x4153cda9, 0x5f14edac, 0x5bd5e01b, 0x5696f6c2, 0x5257fb75,
36*23ba6841SJoseph Chen 	0x6a18b6c8, 0x6ed9bb7f, 0x639aada6, 0x675ba011, 0x791c8014, 0x7ddd8da3,
37*23ba6841SJoseph Chen 	0x709e9b7a, 0x745f96cd, 0x9821b6e0, 0x9ce0bb57, 0x91a3ad8e, 0x9562a039,
38*23ba6841SJoseph Chen 	0x8b25803c, 0x8fe48d8b, 0x82a79b52, 0x866696e5, 0xbe29db58, 0xbae8d6ef,
39*23ba6841SJoseph Chen 	0xb7abc036, 0xb36acd81, 0xad2ded84, 0xa9ece033, 0xa4aff6ea, 0xa06efb5d,
40*23ba6841SJoseph Chen 	0xd4316d90, 0xd0f06027, 0xddb376fe, 0xd9727b49, 0xc7355b4c, 0xc3f456fb,
41*23ba6841SJoseph Chen 	0xceb74022, 0xca764d95, 0xf2390028, 0xf6f80d9f, 0xfbbb1b46, 0xff7a16f1,
42*23ba6841SJoseph Chen 	0xe13d36f4, 0xe5fc3b43, 0xe8bf2d9a, 0xec7e202d, 0x34826077, 0x30436dc0,
43*23ba6841SJoseph Chen 	0x3d007b19, 0x39c176ae, 0x278656ab, 0x23475b1c, 0x2e044dc5, 0x2ac54072,
44*23ba6841SJoseph Chen 	0x128a0dcf, 0x164b0078, 0x1b0816a1, 0x1fc91b16, 0x018e3b13, 0x054f36a4,
45*23ba6841SJoseph Chen 	0x080c207d, 0x0ccd2dca, 0x7892bb07, 0x7c53b6b0, 0x7110a069, 0x75d1adde,
46*23ba6841SJoseph Chen 	0x6b968ddb, 0x6f57806c, 0x621496b5, 0x66d59b02, 0x5e9ad6bf, 0x5a5bdb08,
47*23ba6841SJoseph Chen 	0x5718cdd1, 0x53d9c066, 0x4d9ee063, 0x495fedd4, 0x441cfb0d, 0x40ddf6ba,
48*23ba6841SJoseph Chen 	0xaca3d697, 0xa862db20, 0xa521cdf9, 0xa1e0c04e, 0xbfa7e04b, 0xbb66edfc,
49*23ba6841SJoseph Chen 	0xb625fb25, 0xb2e4f692, 0x8aabbb2f, 0x8e6ab698, 0x8329a041, 0x87e8adf6,
50*23ba6841SJoseph Chen 	0x99af8df3, 0x9d6e8044, 0x902d969d, 0x94ec9b2a, 0xe0b30de7, 0xe4720050,
51*23ba6841SJoseph Chen 	0xe9311689, 0xedf01b3e, 0xf3b73b3b, 0xf776368c, 0xfa352055, 0xfef42de2,
52*23ba6841SJoseph Chen 	0xc6bb605f, 0xc27a6de8, 0xcf397b31, 0xcbf87686, 0xd5bf5683, 0xd17e5b34,
53*23ba6841SJoseph Chen 	0xdc3d4ded, 0xd8fc405a, 0x6904c0ee, 0x6dc5cd59, 0x6086db80, 0x6447d637,
54*23ba6841SJoseph Chen 	0x7a00f632, 0x7ec1fb85, 0x7382ed5c, 0x7743e0eb, 0x4f0cad56, 0x4bcda0e1,
55*23ba6841SJoseph Chen 	0x468eb638, 0x424fbb8f, 0x5c089b8a, 0x58c9963d, 0x558a80e4, 0x514b8d53,
56*23ba6841SJoseph Chen 	0x25141b9e, 0x21d51629, 0x2c9600f0, 0x28570d47, 0x36102d42, 0x32d120f5,
57*23ba6841SJoseph Chen 	0x3f92362c, 0x3b533b9b, 0x031c7626, 0x07dd7b91, 0x0a9e6d48, 0x0e5f60ff,
58*23ba6841SJoseph Chen 	0x101840fa, 0x14d94d4d, 0x199a5b94, 0x1d5b5623, 0xf125760e, 0xf5e47bb9,
59*23ba6841SJoseph Chen 	0xf8a76d60, 0xfc6660d7, 0xe22140d2, 0xe6e04d65, 0xeba35bbc, 0xef62560b,
60*23ba6841SJoseph Chen 	0xd72d1bb6, 0xd3ec1601, 0xdeaf00d8, 0xda6e0d6f, 0xc4292d6a, 0xc0e820dd,
61*23ba6841SJoseph Chen 	0xcdab3604, 0xc96a3bb3, 0xbd35ad7e, 0xb9f4a0c9, 0xb4b7b610, 0xb076bba7,
62*23ba6841SJoseph Chen 	0xae319ba2, 0xaaf09615, 0xa7b380cc, 0xa3728d7b, 0x9b3dc0c6, 0x9ffccd71,
63*23ba6841SJoseph Chen 	0x92bfdba8, 0x967ed61f, 0x8839f61a, 0x8cf8fbad, 0x81bbed74, 0x857ae0c3,
64*23ba6841SJoseph Chen 	0x5d86a099, 0x5947ad2e, 0x5404bbf7, 0x50c5b640, 0x4e829645, 0x4a439bf2,
65*23ba6841SJoseph Chen 	0x47008d2b, 0x43c1809c, 0x7b8ecd21, 0x7f4fc096, 0x720cd64f, 0x76cddbf8,
66*23ba6841SJoseph Chen 	0x688afbfd, 0x6c4bf64a, 0x6108e093, 0x65c9ed24, 0x11967be9, 0x1557765e,
67*23ba6841SJoseph Chen 	0x18146087, 0x1cd56d30, 0x02924d35, 0x06534082, 0x0b10565b, 0x0fd15bec,
68*23ba6841SJoseph Chen 	0x379e1651, 0x335f1be6, 0x3e1c0d3f, 0x3add0088, 0x249a208d, 0x205b2d3a,
69*23ba6841SJoseph Chen 	0x2d183be3, 0x29d93654, 0xc5a71679, 0xc1661bce, 0xcc250d17, 0xc8e400a0,
70*23ba6841SJoseph Chen 	0xd6a320a5, 0xd2622d12, 0xdf213bcb, 0xdbe0367c, 0xe3af7bc1, 0xe76e7676,
71*23ba6841SJoseph Chen 	0xea2d60af, 0xeeec6d18, 0xf0ab4d1d, 0xf46a40aa, 0xf9295673, 0xfde85bc4,
72*23ba6841SJoseph Chen 	0x89b7cd09, 0x8d76c0be, 0x8035d667, 0x84f4dbd0, 0x9ab3fbd5, 0x9e72f662,
73*23ba6841SJoseph Chen 	0x9331e0bb, 0x97f0ed0c, 0xafbfa0b1, 0xab7ead06, 0xa63dbbdf, 0xa2fcb668,
74*23ba6841SJoseph Chen 	0xbcbb966d, 0xb87a9bda, 0xb5398d03, 0xb1f880b4,
75*23ba6841SJoseph Chen };
76*23ba6841SJoseph Chen 
77*23ba6841SJoseph Chen uint32_t CRC_32(uint8_t *pData, uint32_t ulSize)
78*23ba6841SJoseph Chen {
79*23ba6841SJoseph Chen 	uint32_t i;
80*23ba6841SJoseph Chen 	uint32_t nAccum = 0;
81*23ba6841SJoseph Chen 	for (i = 0; i < ulSize; i++) {
82*23ba6841SJoseph Chen 		nAccum = (nAccum << 8) ^ gTable_Crc32[(nAccum >> 24) ^ (*pData++)];
83*23ba6841SJoseph Chen 	}
84*23ba6841SJoseph Chen 	return nAccum;
85*23ba6841SJoseph Chen }
86*23ba6841SJoseph Chen 
87*23ba6841SJoseph Chen void P_RC4(uint8_t *buf, uint32_t len)
88*23ba6841SJoseph Chen {
89*23ba6841SJoseph Chen 	uint8_t S[256], K[256], temp;
90*23ba6841SJoseph Chen 	uint32_t i, j, t, x;
91*23ba6841SJoseph Chen 	uint8_t key[16] = { 124, 78, 3, 4, 85, 5, 9, 7, 45, 44, 123, 56, 23, 13, 23,
92*23ba6841SJoseph Chen 	                    17
93*23ba6841SJoseph Chen 	                  };
94*23ba6841SJoseph Chen 
95*23ba6841SJoseph Chen 	j = 0;
96*23ba6841SJoseph Chen 	for (i = 0; i < 256; i++) {
97*23ba6841SJoseph Chen 		S[i] = (uint8_t) i;
98*23ba6841SJoseph Chen 		j &= 0x0f;
99*23ba6841SJoseph Chen 		K[i] = key[j];
100*23ba6841SJoseph Chen 		j++;
101*23ba6841SJoseph Chen 	}
102*23ba6841SJoseph Chen 
103*23ba6841SJoseph Chen 	j = 0;
104*23ba6841SJoseph Chen 	for (i = 0; i < 256; i++) {
105*23ba6841SJoseph Chen 		j = (j + S[i] + K[i]) % 256;
106*23ba6841SJoseph Chen 		temp = S[i];
107*23ba6841SJoseph Chen 		S[i] = S[j];
108*23ba6841SJoseph Chen 		S[j] = temp;
109*23ba6841SJoseph Chen 	}
110*23ba6841SJoseph Chen 
111*23ba6841SJoseph Chen 	i = j = 0;
112*23ba6841SJoseph Chen 	for (x = 0; x < len; x++) {
113*23ba6841SJoseph Chen 		i = (i + 1) % 256;
114*23ba6841SJoseph Chen 		j = (j + S[i]) % 256;
115*23ba6841SJoseph Chen 		temp = S[i];
116*23ba6841SJoseph Chen 		S[i] = S[j];
117*23ba6841SJoseph Chen 		S[j] = temp;
118*23ba6841SJoseph Chen 		t = (S[i] + (S[j] % 256)) % 256;
119*23ba6841SJoseph Chen 		buf[x] = buf[x] ^ S[t];
120*23ba6841SJoseph Chen 	}
121*23ba6841SJoseph Chen }
122*23ba6841SJoseph Chen 
123*23ba6841SJoseph Chen static inline void fixPath(char *path)
124*23ba6841SJoseph Chen {
125*23ba6841SJoseph Chen 	int i, len = strlen(path);
126*23ba6841SJoseph Chen 	char tmp[MAX_LINE_LEN];
127*23ba6841SJoseph Chen 	char *start, *end;
128*23ba6841SJoseph Chen 
129*23ba6841SJoseph Chen 	for (i = 0; i < len; i++) {
130*23ba6841SJoseph Chen 		if (path[i] == '\\')
131*23ba6841SJoseph Chen 			path[i] = '/';
132*23ba6841SJoseph Chen 		else if (path[i] == '\r' || path[i] == '\n')
133*23ba6841SJoseph Chen 			path[i] = '\0';
134*23ba6841SJoseph Chen 	}
135*23ba6841SJoseph Chen 
136*23ba6841SJoseph Chen 	if (strlen(gLegacyPath) && strlen(gNewPath)) {
137*23ba6841SJoseph Chen 		start = strstr(path, gLegacyPath);
138*23ba6841SJoseph Chen 		if (start) {
139*23ba6841SJoseph Chen 			end = start + strlen(gLegacyPath);
140*23ba6841SJoseph Chen 			/* Backup, so tmp can be src for strcat() */
141*23ba6841SJoseph Chen 			strcpy(tmp, end);
142*23ba6841SJoseph Chen 			/* Terminate, so path can be dest for strcat() */
143*23ba6841SJoseph Chen 			*start = '\0';
144*23ba6841SJoseph Chen 			strcat(path, tmp);
145*23ba6841SJoseph Chen 		}
146*23ba6841SJoseph Chen 	}
147*23ba6841SJoseph Chen }
148*23ba6841SJoseph Chen 
149*23ba6841SJoseph Chen static bool parseChip(FILE *file)
150*23ba6841SJoseph Chen {
151*23ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
152*23ba6841SJoseph Chen 		return false;
153*23ba6841SJoseph Chen 	}
154*23ba6841SJoseph Chen 	if (fscanf(file, OPT_NAME "=%s", gOpts.chip) != 1) {
155*23ba6841SJoseph Chen 		return false;
156*23ba6841SJoseph Chen 	}
157*23ba6841SJoseph Chen 	LOGD("chip:%s\n", gOpts.chip);
158*23ba6841SJoseph Chen 	return true;
159*23ba6841SJoseph Chen }
160*23ba6841SJoseph Chen 
161*23ba6841SJoseph Chen static bool parseVersion(FILE *file)
162*23ba6841SJoseph Chen {
163*23ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
164*23ba6841SJoseph Chen 		return false;
165*23ba6841SJoseph Chen 	}
166*23ba6841SJoseph Chen 	if (fscanf(file, OPT_MAJOR "=%d", &gOpts.major) != 1)
167*23ba6841SJoseph Chen 		return false;
168*23ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
169*23ba6841SJoseph Chen 		return false;
170*23ba6841SJoseph Chen 	}
171*23ba6841SJoseph Chen 	if (fscanf(file, OPT_MINOR "=%d", &gOpts.minor) != 1)
172*23ba6841SJoseph Chen 		return false;
173*23ba6841SJoseph Chen 	LOGD("major:%d, minor:%d\n", gOpts.major, gOpts.minor);
174*23ba6841SJoseph Chen 	return true;
175*23ba6841SJoseph Chen }
176*23ba6841SJoseph Chen 
177*23ba6841SJoseph Chen static bool parse471(FILE *file)
178*23ba6841SJoseph Chen {
179*23ba6841SJoseph Chen 	int i, index, pos;
180*23ba6841SJoseph Chen 	char buf[MAX_LINE_LEN];
181*23ba6841SJoseph Chen 
182*23ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
183*23ba6841SJoseph Chen 		return false;
184*23ba6841SJoseph Chen 	}
185*23ba6841SJoseph Chen 	if (fscanf(file, OPT_NUM "=%d", &gOpts.code471Num) != 1)
186*23ba6841SJoseph Chen 		return false;
187*23ba6841SJoseph Chen 	LOGD("num:%d\n", gOpts.code471Num);
188*23ba6841SJoseph Chen 	if (!gOpts.code471Num)
189*23ba6841SJoseph Chen 		return true;
190*23ba6841SJoseph Chen 	if (gOpts.code471Num < 0)
191*23ba6841SJoseph Chen 		return false;
192*23ba6841SJoseph Chen 	gOpts.code471Path = (line_t *)malloc(sizeof(line_t) * gOpts.code471Num);
193*23ba6841SJoseph Chen 	for (i = 0; i < gOpts.code471Num; i++) {
194*23ba6841SJoseph Chen 		if (SCANF_EAT(file) != 0) {
195*23ba6841SJoseph Chen 			return false;
196*23ba6841SJoseph Chen 		}
197*23ba6841SJoseph Chen 		if (fscanf(file, OPT_PATH "%d=%[^\r^\n]", &index, buf) != 2)
198*23ba6841SJoseph Chen 			return false;
199*23ba6841SJoseph Chen 		index--;
200*23ba6841SJoseph Chen 		fixPath(buf);
201*23ba6841SJoseph Chen 		strcpy((char *)gOpts.code471Path[index], buf);
202*23ba6841SJoseph Chen 		LOGD("path%i:%s\n", index, gOpts.code471Path[index]);
203*23ba6841SJoseph Chen 	}
204*23ba6841SJoseph Chen 	pos = ftell(file);
205*23ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
206*23ba6841SJoseph Chen 		return false;
207*23ba6841SJoseph Chen 	}
208*23ba6841SJoseph Chen 	if (fscanf(file, OPT_SLEEP "=%d", &gOpts.code471Sleep) != 1)
209*23ba6841SJoseph Chen 		fseek(file, pos, SEEK_SET);
210*23ba6841SJoseph Chen 	LOGD("sleep:%d\n", gOpts.code471Sleep);
211*23ba6841SJoseph Chen 	return true;
212*23ba6841SJoseph Chen }
213*23ba6841SJoseph Chen 
214*23ba6841SJoseph Chen static bool parse472(FILE *file)
215*23ba6841SJoseph Chen {
216*23ba6841SJoseph Chen 	int i, index, pos;
217*23ba6841SJoseph Chen 	char buf[MAX_LINE_LEN];
218*23ba6841SJoseph Chen 
219*23ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
220*23ba6841SJoseph Chen 		return false;
221*23ba6841SJoseph Chen 	}
222*23ba6841SJoseph Chen 	if (fscanf(file, OPT_NUM "=%d", &gOpts.code472Num) != 1)
223*23ba6841SJoseph Chen 		return false;
224*23ba6841SJoseph Chen 	LOGD("num:%d\n", gOpts.code472Num);
225*23ba6841SJoseph Chen 	if (!gOpts.code472Num)
226*23ba6841SJoseph Chen 		return true;
227*23ba6841SJoseph Chen 	if (gOpts.code472Num < 0)
228*23ba6841SJoseph Chen 		return false;
229*23ba6841SJoseph Chen 	gOpts.code472Path = (line_t *)malloc(sizeof(line_t) * gOpts.code472Num);
230*23ba6841SJoseph Chen 	for (i = 0; i < gOpts.code472Num; i++) {
231*23ba6841SJoseph Chen 		if (SCANF_EAT(file) != 0) {
232*23ba6841SJoseph Chen 			return false;
233*23ba6841SJoseph Chen 		}
234*23ba6841SJoseph Chen 		if (fscanf(file, OPT_PATH "%d=%[^\r^\n]", &index, buf) != 2)
235*23ba6841SJoseph Chen 			return false;
236*23ba6841SJoseph Chen 		fixPath(buf);
237*23ba6841SJoseph Chen 		index--;
238*23ba6841SJoseph Chen 		strcpy((char *)gOpts.code472Path[index], buf);
239*23ba6841SJoseph Chen 		LOGD("path%i:%s\n", index, gOpts.code472Path[index]);
240*23ba6841SJoseph Chen 	}
241*23ba6841SJoseph Chen 	pos = ftell(file);
242*23ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
243*23ba6841SJoseph Chen 		return false;
244*23ba6841SJoseph Chen 	}
245*23ba6841SJoseph Chen 	if (fscanf(file, OPT_SLEEP "=%d", &gOpts.code472Sleep) != 1)
246*23ba6841SJoseph Chen 		fseek(file, pos, SEEK_SET);
247*23ba6841SJoseph Chen 	LOGD("sleep:%d\n", gOpts.code472Sleep);
248*23ba6841SJoseph Chen 	return true;
249*23ba6841SJoseph Chen }
250*23ba6841SJoseph Chen 
251*23ba6841SJoseph Chen static bool parseLoader(FILE *file)
252*23ba6841SJoseph Chen {
253*23ba6841SJoseph Chen 	int i, j, index, pos;
254*23ba6841SJoseph Chen 	char buf[MAX_LINE_LEN];
255*23ba6841SJoseph Chen 	char buf2[MAX_LINE_LEN];
256*23ba6841SJoseph Chen 
257*23ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
258*23ba6841SJoseph Chen 		return false;
259*23ba6841SJoseph Chen 	}
260*23ba6841SJoseph Chen 	pos = ftell(file);
261*23ba6841SJoseph Chen 	if (fscanf(file, OPT_NUM "=%d", &gOpts.loaderNum) != 1) {
262*23ba6841SJoseph Chen 		fseek(file, pos, SEEK_SET);
263*23ba6841SJoseph Chen 		if (fscanf(file, OPT_LOADER_NUM "=%d", &gOpts.loaderNum) != 1) {
264*23ba6841SJoseph Chen 			return false;
265*23ba6841SJoseph Chen 		}
266*23ba6841SJoseph Chen 	}
267*23ba6841SJoseph Chen 	LOGD("num:%d\n", gOpts.loaderNum);
268*23ba6841SJoseph Chen 	if (!gOpts.loaderNum)
269*23ba6841SJoseph Chen 		return false;
270*23ba6841SJoseph Chen 	if (gOpts.loaderNum < 0)
271*23ba6841SJoseph Chen 		return false;
272*23ba6841SJoseph Chen 	gOpts.loader = (name_entry *)malloc(sizeof(name_entry) * gOpts.loaderNum);
273*23ba6841SJoseph Chen 	for (i = 0; i < gOpts.loaderNum; i++) {
274*23ba6841SJoseph Chen 		if (SCANF_EAT(file) != 0) {
275*23ba6841SJoseph Chen 			return false;
276*23ba6841SJoseph Chen 		}
277*23ba6841SJoseph Chen 		if (fscanf(file, OPT_LOADER_NAME "%d=%s", &index, buf) != 2)
278*23ba6841SJoseph Chen 			return false;
279*23ba6841SJoseph Chen 		index--;
280*23ba6841SJoseph Chen 		strcpy(gOpts.loader[index].name, buf);
281*23ba6841SJoseph Chen 		LOGD("name%d:%s\n", index, gOpts.loader[index].name);
282*23ba6841SJoseph Chen 	}
283*23ba6841SJoseph Chen 	for (i = 0; i < gOpts.loaderNum; i++) {
284*23ba6841SJoseph Chen 		if (SCANF_EAT(file) != 0) {
285*23ba6841SJoseph Chen 			return false;
286*23ba6841SJoseph Chen 		}
287*23ba6841SJoseph Chen 		if (fscanf(file, "%[^=]=%[^\r^\n]", buf, buf2) != 2)
288*23ba6841SJoseph Chen 			return false;
289*23ba6841SJoseph Chen 		for (j = 0; j < gOpts.loaderNum; j++) {
290*23ba6841SJoseph Chen 			if (!strcmp(gOpts.loader[j].name, buf)) {
291*23ba6841SJoseph Chen 				fixPath(buf2);
292*23ba6841SJoseph Chen 				strcpy(gOpts.loader[j].path, buf2);
293*23ba6841SJoseph Chen 				LOGD("%s=%s\n", gOpts.loader[j].name, gOpts.loader[j].path);
294*23ba6841SJoseph Chen 				break;
295*23ba6841SJoseph Chen 			}
296*23ba6841SJoseph Chen 		}
297*23ba6841SJoseph Chen 		if (j >= gOpts.loaderNum) {
298*23ba6841SJoseph Chen 			return false;
299*23ba6841SJoseph Chen 		}
300*23ba6841SJoseph Chen 	}
301*23ba6841SJoseph Chen 	return true;
302*23ba6841SJoseph Chen }
303*23ba6841SJoseph Chen 
304*23ba6841SJoseph Chen static bool parseOut(FILE *file)
305*23ba6841SJoseph Chen {
306*23ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
307*23ba6841SJoseph Chen 		return false;
308*23ba6841SJoseph Chen 	}
309*23ba6841SJoseph Chen 	if (fscanf(file, OPT_OUT_PATH "=%[^\r^\n]", gOpts.outPath) != 1)
310*23ba6841SJoseph Chen 		return false;
311*23ba6841SJoseph Chen 	fixPath(gOpts.outPath);
312*23ba6841SJoseph Chen 	printf("out:%s\n", gOpts.outPath);
313*23ba6841SJoseph Chen 	return true;
314*23ba6841SJoseph Chen }
315*23ba6841SJoseph Chen 
316*23ba6841SJoseph Chen void printOpts(FILE *out)
317*23ba6841SJoseph Chen {
318*23ba6841SJoseph Chen 	uint32_t i;
319*23ba6841SJoseph Chen 	fprintf(out, SEC_CHIP "\n" OPT_NAME "=%s\n", gOpts.chip);
320*23ba6841SJoseph Chen 	fprintf(out, SEC_VERSION "\n" OPT_MAJOR "=%d\n" OPT_MINOR "=%d\n",
321*23ba6841SJoseph Chen 	        gOpts.major, gOpts.minor);
322*23ba6841SJoseph Chen 
323*23ba6841SJoseph Chen 	fprintf(out, SEC_471 "\n" OPT_NUM "=%d\n", gOpts.code471Num);
324*23ba6841SJoseph Chen 	for (i = 0; i < gOpts.code471Num; i++) {
325*23ba6841SJoseph Chen 		fprintf(out, OPT_PATH "%d=%s\n", i + 1, gOpts.code471Path[i]);
326*23ba6841SJoseph Chen 	}
327*23ba6841SJoseph Chen 	if (gOpts.code471Sleep > 0)
328*23ba6841SJoseph Chen 		fprintf(out, OPT_SLEEP "=%d\n", gOpts.code471Sleep);
329*23ba6841SJoseph Chen 
330*23ba6841SJoseph Chen 	fprintf(out, SEC_472 "\n" OPT_NUM "=%d\n", gOpts.code472Num);
331*23ba6841SJoseph Chen 	for (i = 0; i < gOpts.code472Num; i++) {
332*23ba6841SJoseph Chen 		fprintf(out, OPT_PATH "%d=%s\n", i + 1, gOpts.code472Path[i]);
333*23ba6841SJoseph Chen 	}
334*23ba6841SJoseph Chen 	if (gOpts.code472Sleep > 0)
335*23ba6841SJoseph Chen 		fprintf(out, OPT_SLEEP "=%d\n", gOpts.code472Sleep);
336*23ba6841SJoseph Chen 
337*23ba6841SJoseph Chen 	fprintf(out, SEC_LOADER "\n" OPT_NUM "=%d\n", gOpts.loaderNum);
338*23ba6841SJoseph Chen 	for (i = 0; i < gOpts.loaderNum; i++) {
339*23ba6841SJoseph Chen 		fprintf(out, OPT_LOADER_NAME "%d=%s\n", i + 1, gOpts.loader[i].name);
340*23ba6841SJoseph Chen 	}
341*23ba6841SJoseph Chen 	for (i = 0; i < gOpts.loaderNum; i++) {
342*23ba6841SJoseph Chen 		fprintf(out, "%s=%s\n", gOpts.loader[i].name, gOpts.loader[i].path);
343*23ba6841SJoseph Chen 	}
344*23ba6841SJoseph Chen 
345*23ba6841SJoseph Chen 	fprintf(out, SEC_OUT "\n" OPT_OUT_PATH "=%s\n", gOpts.outPath);
346*23ba6841SJoseph Chen }
347*23ba6841SJoseph Chen 
348*23ba6841SJoseph Chen static bool parseOpts_from_file(void)
349*23ba6841SJoseph Chen {
350*23ba6841SJoseph Chen 	bool ret = false;
351*23ba6841SJoseph Chen 	bool chipOk = false;
352*23ba6841SJoseph Chen 	bool versionOk = false;
353*23ba6841SJoseph Chen 	bool code471Ok = true;
354*23ba6841SJoseph Chen 	bool code472Ok = true;
355*23ba6841SJoseph Chen 	bool loaderOk = false;
356*23ba6841SJoseph Chen 	bool outOk = false;
357*23ba6841SJoseph Chen 	char buf[MAX_LINE_LEN];
358*23ba6841SJoseph Chen 
359*23ba6841SJoseph Chen 	char *configPath = (gConfigPath == NULL) ? DEF_CONFIG_FILE : gConfigPath;
360*23ba6841SJoseph Chen 	FILE *file;
361*23ba6841SJoseph Chen 	file = fopen(configPath, "r");
362*23ba6841SJoseph Chen 	if (!file) {
363*23ba6841SJoseph Chen 		fprintf(stderr, "config(%s) not found!\n", configPath);
364*23ba6841SJoseph Chen 		if (configPath == (char *)DEF_CONFIG_FILE) {
365*23ba6841SJoseph Chen 			file = fopen(DEF_CONFIG_FILE, "w");
366*23ba6841SJoseph Chen 			if (file) {
367*23ba6841SJoseph Chen 				fprintf(stderr, "create defconfig\n");
368*23ba6841SJoseph Chen 				printOpts(file);
369*23ba6841SJoseph Chen 			}
370*23ba6841SJoseph Chen 		}
371*23ba6841SJoseph Chen 		goto end;
372*23ba6841SJoseph Chen 	}
373*23ba6841SJoseph Chen 
374*23ba6841SJoseph Chen 	LOGD("start parse\n");
375*23ba6841SJoseph Chen 
376*23ba6841SJoseph Chen 	if (SCANF_EAT(file) != 0) {
377*23ba6841SJoseph Chen 		goto end;
378*23ba6841SJoseph Chen 	}
379*23ba6841SJoseph Chen 	while (fscanf(file, "%s", buf) == 1) {
380*23ba6841SJoseph Chen 		if (!strcmp(buf, SEC_CHIP)) {
381*23ba6841SJoseph Chen 			chipOk = parseChip(file);
382*23ba6841SJoseph Chen 			if (!chipOk) {
383*23ba6841SJoseph Chen 				LOGE("parseChip failed!\n");
384*23ba6841SJoseph Chen 				goto end;
385*23ba6841SJoseph Chen 			}
386*23ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_VERSION)) {
387*23ba6841SJoseph Chen 			versionOk = parseVersion(file);
388*23ba6841SJoseph Chen 			if (!versionOk) {
389*23ba6841SJoseph Chen 				LOGE("parseVersion failed!\n");
390*23ba6841SJoseph Chen 				goto end;
391*23ba6841SJoseph Chen 			}
392*23ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_471)) {
393*23ba6841SJoseph Chen 			code471Ok = parse471(file);
394*23ba6841SJoseph Chen 			if (!code471Ok) {
395*23ba6841SJoseph Chen 				LOGE("parse471 failed!\n");
396*23ba6841SJoseph Chen 				goto end;
397*23ba6841SJoseph Chen 			}
398*23ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_472)) {
399*23ba6841SJoseph Chen 			code472Ok = parse472(file);
400*23ba6841SJoseph Chen 			if (!code472Ok) {
401*23ba6841SJoseph Chen 				LOGE("parse472 failed!\n");
402*23ba6841SJoseph Chen 				goto end;
403*23ba6841SJoseph Chen 			}
404*23ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_LOADER)) {
405*23ba6841SJoseph Chen 			loaderOk = parseLoader(file);
406*23ba6841SJoseph Chen 			if (!loaderOk) {
407*23ba6841SJoseph Chen 				LOGE("parseLoader failed!\n");
408*23ba6841SJoseph Chen 				goto end;
409*23ba6841SJoseph Chen 			}
410*23ba6841SJoseph Chen 		} else if (!strcmp(buf, SEC_OUT)) {
411*23ba6841SJoseph Chen 			outOk = parseOut(file);
412*23ba6841SJoseph Chen 			if (!outOk) {
413*23ba6841SJoseph Chen 				LOGE("parseOut failed!\n");
414*23ba6841SJoseph Chen 				goto end;
415*23ba6841SJoseph Chen 			}
416*23ba6841SJoseph Chen 		} else if (buf[0] == '#') {
417*23ba6841SJoseph Chen 			continue;
418*23ba6841SJoseph Chen 		} else {
419*23ba6841SJoseph Chen 			LOGE("unknown sec: %s!\n", buf);
420*23ba6841SJoseph Chen 			goto end;
421*23ba6841SJoseph Chen 		}
422*23ba6841SJoseph Chen 		if (SCANF_EAT(file) != 0) {
423*23ba6841SJoseph Chen 			goto end;
424*23ba6841SJoseph Chen 		}
425*23ba6841SJoseph Chen 	}
426*23ba6841SJoseph Chen 
427*23ba6841SJoseph Chen 	if (chipOk && versionOk && code471Ok && code472Ok && loaderOk && outOk)
428*23ba6841SJoseph Chen 		ret = true;
429*23ba6841SJoseph Chen end:
430*23ba6841SJoseph Chen 	if (file)
431*23ba6841SJoseph Chen 		fclose(file);
432*23ba6841SJoseph Chen 	return ret;
433*23ba6841SJoseph Chen }
434*23ba6841SJoseph Chen 
435*23ba6841SJoseph Chen static bool parseOpts_from_cmdline(int argc, char **argv)
436*23ba6841SJoseph Chen {
437*23ba6841SJoseph Chen 	int i;
438*23ba6841SJoseph Chen 	int tag = 0;
439*23ba6841SJoseph Chen 	int v0, v1, v2, v3;
440*23ba6841SJoseph Chen 
441*23ba6841SJoseph Chen 	for (i = 2; i < argc; i++) {
442*23ba6841SJoseph Chen 		if (!strcmp(OPT_471, argv[i])) {
443*23ba6841SJoseph Chen 			i++;
444*23ba6841SJoseph Chen 			snprintf(gOpts.code471Path[0], sizeof(gOpts.code471Path[0]), "%s",
445*23ba6841SJoseph Chen 			         argv[i]);
446*23ba6841SJoseph Chen 			tag |= 1;
447*23ba6841SJoseph Chen 		} else if (!strcmp(OPT_472, argv[i])) {
448*23ba6841SJoseph Chen 			i++;
449*23ba6841SJoseph Chen 			snprintf(gOpts.code472Path[0], sizeof(gOpts.code472Path[0]), "%s",
450*23ba6841SJoseph Chen 			         argv[i]);
451*23ba6841SJoseph Chen 			tag |= 2;
452*23ba6841SJoseph Chen 		} else if (!strcmp(OPT_DATA, argv[i])) {
453*23ba6841SJoseph Chen 			i++;
454*23ba6841SJoseph Chen 			snprintf(gOpts.loader[0].path, sizeof(gOpts.loader[0].path), "%s",
455*23ba6841SJoseph Chen 			         argv[i]);
456*23ba6841SJoseph Chen 			tag |= 4;
457*23ba6841SJoseph Chen 		} else if (!strcmp(OPT_BOOT, argv[i])) {
458*23ba6841SJoseph Chen 			i++;
459*23ba6841SJoseph Chen 			snprintf(gOpts.loader[1].path, sizeof(gOpts.loader[1].path), "%s",
460*23ba6841SJoseph Chen 			         argv[i]);
461*23ba6841SJoseph Chen 			tag |= 8;
462*23ba6841SJoseph Chen 		} else if (!strcmp(OPT_OUT, argv[i])) {
463*23ba6841SJoseph Chen 			i++;
464*23ba6841SJoseph Chen 			snprintf(gOpts.outPath, sizeof(gOpts.outPath), "%s", argv[i]);
465*23ba6841SJoseph Chen 			tag |= 0x10;
466*23ba6841SJoseph Chen 		} else if (!strcmp(OPT_CHIP, argv[i])) {
467*23ba6841SJoseph Chen 			i++;
468*23ba6841SJoseph Chen 			snprintf(gOpts.chip, sizeof(gOpts.chip), "%s", argv[i]);
469*23ba6841SJoseph Chen 			tag |= 0x20;
470*23ba6841SJoseph Chen 		} else if (!strcmp(OPT_VERSION, argv[i])) {
471*23ba6841SJoseph Chen 		}
472*23ba6841SJoseph Chen 	}
473*23ba6841SJoseph Chen 
474*23ba6841SJoseph Chen 	sscanf(gOpts.loader[0].path, "%*[^v]v%d.%d.bin", &v0, &v1);
475*23ba6841SJoseph Chen 	sscanf(gOpts.loader[1].path, "%*[^v]v%d.%d.bin", &v2, &v3);
476*23ba6841SJoseph Chen 	gOpts.major = v2;
477*23ba6841SJoseph Chen 	gOpts.minor = v3;
478*23ba6841SJoseph Chen 	snprintf(gOpts.outPath, sizeof(gOpts.outPath),
479*23ba6841SJoseph Chen 	         "%s_loader_v%d.%02d.%d%02d.bin", gOpts.chip, v0, v1, v2, v3);
480*23ba6841SJoseph Chen 	return ((tag & 0x0f) == 0x0f) ? true : false;
481*23ba6841SJoseph Chen }
482*23ba6841SJoseph Chen 
483*23ba6841SJoseph Chen bool initOpts(int argc, char **argv)
484*23ba6841SJoseph Chen {
485*23ba6841SJoseph Chen 	bool ret;
486*23ba6841SJoseph Chen 
487*23ba6841SJoseph Chen 	/* set default opts */
488*23ba6841SJoseph Chen 	gOpts.major = DEF_MAJOR;
489*23ba6841SJoseph Chen 	gOpts.minor = DEF_MINOR;
490*23ba6841SJoseph Chen 	strcpy(gOpts.chip, DEF_CHIP);
491*23ba6841SJoseph Chen 	gOpts.code471Sleep = DEF_CODE471_SLEEP;
492*23ba6841SJoseph Chen 	gOpts.code472Sleep = DEF_CODE472_SLEEP;
493*23ba6841SJoseph Chen 	gOpts.code471Num = DEF_CODE471_NUM;
494*23ba6841SJoseph Chen 	gOpts.code471Path = (line_t *)malloc(sizeof(line_t) * gOpts.code471Num);
495*23ba6841SJoseph Chen 	strcpy((char *)gOpts.code471Path[0], DEF_CODE471_PATH);
496*23ba6841SJoseph Chen 	gOpts.code472Num = DEF_CODE472_NUM;
497*23ba6841SJoseph Chen 	gOpts.code472Path = (line_t *)malloc(sizeof(line_t) * gOpts.code472Num);
498*23ba6841SJoseph Chen 	strcpy((char *)gOpts.code472Path[0], DEF_CODE472_PATH);
499*23ba6841SJoseph Chen 	gOpts.loaderNum = DEF_LOADER_NUM;
500*23ba6841SJoseph Chen 	gOpts.loader = (name_entry *)malloc(sizeof(name_entry) * gOpts.loaderNum);
501*23ba6841SJoseph Chen 	strcpy(gOpts.loader[0].name, DEF_LOADER0);
502*23ba6841SJoseph Chen 	strcpy(gOpts.loader[0].path, DEF_LOADER0_PATH);
503*23ba6841SJoseph Chen 	strcpy(gOpts.loader[1].name, DEF_LOADER1);
504*23ba6841SJoseph Chen 	strcpy(gOpts.loader[1].path, DEF_LOADER1_PATH);
505*23ba6841SJoseph Chen 	strcpy(gOpts.outPath, DEF_OUT_PATH);
506*23ba6841SJoseph Chen 
507*23ba6841SJoseph Chen 	if (argc > 10)
508*23ba6841SJoseph Chen 		ret = parseOpts_from_cmdline(argc, argv);
509*23ba6841SJoseph Chen 	else
510*23ba6841SJoseph Chen 		ret = parseOpts_from_file();
511*23ba6841SJoseph Chen 
512*23ba6841SJoseph Chen 	return ret;
513*23ba6841SJoseph Chen }
514*23ba6841SJoseph Chen 
515*23ba6841SJoseph Chen /************merge code****************/
516*23ba6841SJoseph Chen 
517*23ba6841SJoseph Chen static inline uint32_t getBCD(unsigned short value)
518*23ba6841SJoseph Chen {
519*23ba6841SJoseph Chen 	uint8_t tmp[2] = { 0 };
520*23ba6841SJoseph Chen 	int i;
521*23ba6841SJoseph Chen 	uint32_t ret;
522*23ba6841SJoseph Chen 	if (value > 0xFFFF) {
523*23ba6841SJoseph Chen 		return 0;
524*23ba6841SJoseph Chen 	}
525*23ba6841SJoseph Chen 	for (i = 0; i < 2; i++) {
526*23ba6841SJoseph Chen 		tmp[i] = (((value / 10) % 10) << 4) | (value % 10);
527*23ba6841SJoseph Chen 		value /= 100;
528*23ba6841SJoseph Chen 	}
529*23ba6841SJoseph Chen 	ret = ((uint16_t)(tmp[1] << 8)) | tmp[0];
530*23ba6841SJoseph Chen 
531*23ba6841SJoseph Chen 	LOGD("ret:%x\n", ret);
532*23ba6841SJoseph Chen 	return ret & 0xFF;
533*23ba6841SJoseph Chen }
534*23ba6841SJoseph Chen 
535*23ba6841SJoseph Chen static inline void str2wide(const char *str, uint16_t *wide, int len)
536*23ba6841SJoseph Chen {
537*23ba6841SJoseph Chen 	int i;
538*23ba6841SJoseph Chen 	for (i = 0; i < len; i++) {
539*23ba6841SJoseph Chen 		wide[i] = (uint16_t) str[i];
540*23ba6841SJoseph Chen 	}
541*23ba6841SJoseph Chen 	wide[len] = 0;
542*23ba6841SJoseph Chen }
543*23ba6841SJoseph Chen 
544*23ba6841SJoseph Chen static inline void getName(char *path, uint16_t *dst)
545*23ba6841SJoseph Chen {
546*23ba6841SJoseph Chen 	char *end;
547*23ba6841SJoseph Chen 	char *start;
548*23ba6841SJoseph Chen 	int len;
549*23ba6841SJoseph Chen 	if (!path || !dst)
550*23ba6841SJoseph Chen 		return;
551*23ba6841SJoseph Chen 	start = strrchr(path, '/');
552*23ba6841SJoseph Chen 	if (!start)
553*23ba6841SJoseph Chen 		start = path;
554*23ba6841SJoseph Chen 	else
555*23ba6841SJoseph Chen 		start++;
556*23ba6841SJoseph Chen 	end = strrchr(path, '.');
557*23ba6841SJoseph Chen 	if (!end)
558*23ba6841SJoseph Chen 		end = path + strlen(path);
559*23ba6841SJoseph Chen 	len = end - start;
560*23ba6841SJoseph Chen 	if (len >= MAX_NAME_LEN)
561*23ba6841SJoseph Chen 		len = MAX_NAME_LEN - 1;
562*23ba6841SJoseph Chen 	str2wide(start, dst, len);
563*23ba6841SJoseph Chen 
564*23ba6841SJoseph Chen 	if (gDebug) {
565*23ba6841SJoseph Chen 		char name[MAX_NAME_LEN];
566*23ba6841SJoseph Chen 		memset(name, 0, sizeof(name));
567*23ba6841SJoseph Chen 		memcpy(name, start, len);
568*23ba6841SJoseph Chen 		LOGD("path:%s, name:%s\n", path, name);
569*23ba6841SJoseph Chen 	}
570*23ba6841SJoseph Chen }
571*23ba6841SJoseph Chen 
572*23ba6841SJoseph Chen static inline bool getFileSize(const char *path, uint32_t *size)
573*23ba6841SJoseph Chen {
574*23ba6841SJoseph Chen 	struct stat st;
575*23ba6841SJoseph Chen 	if (stat(path, &st) < 0)
576*23ba6841SJoseph Chen 		return false;
577*23ba6841SJoseph Chen 	*size = st.st_size;
578*23ba6841SJoseph Chen 	LOGD("path:%s, size:%d\n", path, *size);
579*23ba6841SJoseph Chen 	return true;
580*23ba6841SJoseph Chen }
581*23ba6841SJoseph Chen 
582*23ba6841SJoseph Chen static inline rk_time getTime(void)
583*23ba6841SJoseph Chen {
584*23ba6841SJoseph Chen 	rk_time rkTime;
585*23ba6841SJoseph Chen 
586*23ba6841SJoseph Chen 	struct tm *tm;
587*23ba6841SJoseph Chen 	time_t tt = time(NULL);
588*23ba6841SJoseph Chen 	tm = localtime(&tt);
589*23ba6841SJoseph Chen 	rkTime.year = tm->tm_year + 1900;
590*23ba6841SJoseph Chen 	rkTime.month = tm->tm_mon + 1;
591*23ba6841SJoseph Chen 	rkTime.day = tm->tm_mday;
592*23ba6841SJoseph Chen 	rkTime.hour = tm->tm_hour;
593*23ba6841SJoseph Chen 	rkTime.minute = tm->tm_min;
594*23ba6841SJoseph Chen 	rkTime.second = tm->tm_sec;
595*23ba6841SJoseph Chen 	LOGD("%d-%d-%d %02d:%02d:%02d\n", rkTime.year, rkTime.month, rkTime.day,
596*23ba6841SJoseph Chen 	     rkTime.hour, rkTime.minute, rkTime.second);
597*23ba6841SJoseph Chen 	return rkTime;
598*23ba6841SJoseph Chen }
599*23ba6841SJoseph Chen 
600*23ba6841SJoseph Chen static bool writeFile(FILE *outFile, const char *path, bool fix)
601*23ba6841SJoseph Chen {
602*23ba6841SJoseph Chen 	bool ret = false;
603*23ba6841SJoseph Chen 	uint32_t size = 0, fixSize = 0;
604*23ba6841SJoseph Chen 	uint8_t *buf;
605*23ba6841SJoseph Chen 
606*23ba6841SJoseph Chen 	FILE *inFile = fopen(path, "rb");
607*23ba6841SJoseph Chen 	if (!inFile)
608*23ba6841SJoseph Chen 		goto end;
609*23ba6841SJoseph Chen 
610*23ba6841SJoseph Chen 	if (!getFileSize(path, &size))
611*23ba6841SJoseph Chen 		goto end;
612*23ba6841SJoseph Chen 	if (fix) {
613*23ba6841SJoseph Chen 		fixSize = ((size - 1) / SMALL_PACKET + 1) * SMALL_PACKET;
614*23ba6841SJoseph Chen 		uint32_t tmp = fixSize % ENTRY_ALIGN;
615*23ba6841SJoseph Chen 		tmp = tmp ? (ENTRY_ALIGN - tmp) : 0;
616*23ba6841SJoseph Chen 		fixSize += tmp;
617*23ba6841SJoseph Chen 		memset(gBuf, 0, fixSize);
618*23ba6841SJoseph Chen 	} else {
619*23ba6841SJoseph Chen 		memset(gBuf, 0, size + ENTRY_ALIGN);
620*23ba6841SJoseph Chen 	}
621*23ba6841SJoseph Chen 	if (!fread(gBuf, size, 1, inFile))
622*23ba6841SJoseph Chen 		goto end;
623*23ba6841SJoseph Chen 
624*23ba6841SJoseph Chen 	if (fix) {
625*23ba6841SJoseph Chen 
626*23ba6841SJoseph Chen 		buf = gBuf;
627*23ba6841SJoseph Chen 		size = fixSize;
628*23ba6841SJoseph Chen 		while (1) {
629*23ba6841SJoseph Chen 			P_RC4(buf, fixSize < SMALL_PACKET ? fixSize : SMALL_PACKET);
630*23ba6841SJoseph Chen 			buf += SMALL_PACKET;
631*23ba6841SJoseph Chen 			if (fixSize <= SMALL_PACKET)
632*23ba6841SJoseph Chen 				break;
633*23ba6841SJoseph Chen 			fixSize -= SMALL_PACKET;
634*23ba6841SJoseph Chen 		}
635*23ba6841SJoseph Chen 	} else {
636*23ba6841SJoseph Chen 		uint32_t tmp = size % ENTRY_ALIGN;
637*23ba6841SJoseph Chen 		tmp = tmp ? (ENTRY_ALIGN - tmp) : 0;
638*23ba6841SJoseph Chen 		size += tmp;
639*23ba6841SJoseph Chen 		P_RC4(gBuf, size);
640*23ba6841SJoseph Chen 	}
641*23ba6841SJoseph Chen 
642*23ba6841SJoseph Chen 	if (!fwrite(gBuf, size, 1, outFile))
643*23ba6841SJoseph Chen 		goto end;
644*23ba6841SJoseph Chen 	ret = true;
645*23ba6841SJoseph Chen end:
646*23ba6841SJoseph Chen 	if (inFile)
647*23ba6841SJoseph Chen 		fclose(inFile);
648*23ba6841SJoseph Chen 	if (!ret)
649*23ba6841SJoseph Chen 		LOGE("write entry(%s) failed\n", path);
650*23ba6841SJoseph Chen 	return ret;
651*23ba6841SJoseph Chen }
652*23ba6841SJoseph Chen 
653*23ba6841SJoseph Chen static bool saveEntry(FILE *outFile, char *path, rk_entry_type type,
654*23ba6841SJoseph Chen                       uint16_t delay, uint32_t *offset, char *fixName,
655*23ba6841SJoseph Chen                       bool fix)
656*23ba6841SJoseph Chen {
657*23ba6841SJoseph Chen 	LOGD("write:%s\n", path);
658*23ba6841SJoseph Chen 	uint32_t size;
659*23ba6841SJoseph Chen 	rk_boot_entry entry;
660*23ba6841SJoseph Chen 	memset(&entry, 0, sizeof(rk_boot_entry));
661*23ba6841SJoseph Chen 
662*23ba6841SJoseph Chen 	LOGD("write:%s\n", path);
663*23ba6841SJoseph Chen 
664*23ba6841SJoseph Chen 	getName(fixName ? fixName : path, entry.name);
665*23ba6841SJoseph Chen 	entry.size = sizeof(rk_boot_entry);
666*23ba6841SJoseph Chen 	entry.type = type;
667*23ba6841SJoseph Chen 	entry.dataOffset = *offset;
668*23ba6841SJoseph Chen 	if (!getFileSize(path, &size)) {
669*23ba6841SJoseph Chen 		LOGE("save entry(%s) failed:\n\tcannot get file size.\n", path);
670*23ba6841SJoseph Chen 		return false;
671*23ba6841SJoseph Chen 	}
672*23ba6841SJoseph Chen 	if (fix)
673*23ba6841SJoseph Chen 		size = ((size - 1) / SMALL_PACKET + 1) * SMALL_PACKET;
674*23ba6841SJoseph Chen 	uint32_t tmp = size % ENTRY_ALIGN;
675*23ba6841SJoseph Chen 	size += tmp ? (ENTRY_ALIGN - tmp) : 0;
676*23ba6841SJoseph Chen 	LOGD("align size:%d\n", size);
677*23ba6841SJoseph Chen 	entry.dataSize = size;
678*23ba6841SJoseph Chen 	entry.dataDelay = delay;
679*23ba6841SJoseph Chen 	*offset += size;
680*23ba6841SJoseph Chen 	fwrite(&entry, sizeof(rk_boot_entry), 1, outFile);
681*23ba6841SJoseph Chen 	return true;
682*23ba6841SJoseph Chen }
683*23ba6841SJoseph Chen 
684*23ba6841SJoseph Chen static inline uint32_t convertChipType(const char *chip)
685*23ba6841SJoseph Chen {
686*23ba6841SJoseph Chen 	char buffer[5];
687*23ba6841SJoseph Chen 	memset(buffer, 0, sizeof(buffer));
688*23ba6841SJoseph Chen 	snprintf(buffer, sizeof(buffer), "%s", chip);
689*23ba6841SJoseph Chen 	return buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
690*23ba6841SJoseph Chen }
691*23ba6841SJoseph Chen 
692*23ba6841SJoseph Chen static inline uint32_t getChipType(const char *chip)
693*23ba6841SJoseph Chen {
694*23ba6841SJoseph Chen 	LOGD("chip:%s\n", chip);
695*23ba6841SJoseph Chen 	int chipType = RKNONE_DEVICE;
696*23ba6841SJoseph Chen 	if (!chip) {
697*23ba6841SJoseph Chen 		goto end;
698*23ba6841SJoseph Chen 	}
699*23ba6841SJoseph Chen 	if (!strcmp(chip, CHIP_RK28)) {
700*23ba6841SJoseph Chen 		chipType = RK28_DEVICE;
701*23ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK28)) {
702*23ba6841SJoseph Chen 		chipType = RK28_DEVICE;
703*23ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK281X)) {
704*23ba6841SJoseph Chen 		chipType = RK281X_DEVICE;
705*23ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RKPANDA)) {
706*23ba6841SJoseph Chen 		chipType = RKPANDA_DEVICE;
707*23ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK27)) {
708*23ba6841SJoseph Chen 		chipType = RK27_DEVICE;
709*23ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RKNANO)) {
710*23ba6841SJoseph Chen 		chipType = RKNANO_DEVICE;
711*23ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RKSMART)) {
712*23ba6841SJoseph Chen 		chipType = RKSMART_DEVICE;
713*23ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RKCROWN)) {
714*23ba6841SJoseph Chen 		chipType = RKCROWN_DEVICE;
715*23ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RKCAYMAN)) {
716*23ba6841SJoseph Chen 		chipType = RKCAYMAN_DEVICE;
717*23ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK29)) {
718*23ba6841SJoseph Chen 		chipType = RK29_DEVICE;
719*23ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK292X)) {
720*23ba6841SJoseph Chen 		chipType = RK292X_DEVICE;
721*23ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK30)) {
722*23ba6841SJoseph Chen 		chipType = RK30_DEVICE;
723*23ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK30B)) {
724*23ba6841SJoseph Chen 		chipType = RK30B_DEVICE;
725*23ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK31)) {
726*23ba6841SJoseph Chen 		chipType = RK31_DEVICE;
727*23ba6841SJoseph Chen 	} else if (!strcmp(chip, CHIP_RK32)) {
728*23ba6841SJoseph Chen 		chipType = RK32_DEVICE;
729*23ba6841SJoseph Chen 	} else {
730*23ba6841SJoseph Chen 		chipType = convertChipType(chip + 2);
731*23ba6841SJoseph Chen 	}
732*23ba6841SJoseph Chen 
733*23ba6841SJoseph Chen end:
734*23ba6841SJoseph Chen 	LOGD("type:0x%x\n", chipType);
735*23ba6841SJoseph Chen 	if (chipType == RKNONE_DEVICE) {
736*23ba6841SJoseph Chen 		LOGE("chip type not support!\n");
737*23ba6841SJoseph Chen 	}
738*23ba6841SJoseph Chen 	return chipType;
739*23ba6841SJoseph Chen }
740*23ba6841SJoseph Chen 
741*23ba6841SJoseph Chen static inline void getBoothdr(rk_boot_header *hdr)
742*23ba6841SJoseph Chen {
743*23ba6841SJoseph Chen 	memset(hdr, 0, sizeof(rk_boot_header));
744*23ba6841SJoseph Chen 	hdr->tag = TAG;
745*23ba6841SJoseph Chen 	hdr->size = sizeof(rk_boot_header);
746*23ba6841SJoseph Chen 	hdr->version = (getBCD(gOpts.major) << 8) | getBCD(gOpts.minor);
747*23ba6841SJoseph Chen 	hdr->mergerVersion = MERGER_VERSION;
748*23ba6841SJoseph Chen 	hdr->releaseTime = getTime();
749*23ba6841SJoseph Chen 	hdr->chipType = getChipType(gOpts.chip);
750*23ba6841SJoseph Chen 
751*23ba6841SJoseph Chen 	hdr->code471Num = gOpts.code471Num;
752*23ba6841SJoseph Chen 	hdr->code471Offset = sizeof(rk_boot_header);
753*23ba6841SJoseph Chen 	hdr->code471Size = sizeof(rk_boot_entry);
754*23ba6841SJoseph Chen 
755*23ba6841SJoseph Chen 	hdr->code472Num = gOpts.code472Num;
756*23ba6841SJoseph Chen 	hdr->code472Offset = hdr->code471Offset + gOpts.code471Num * hdr->code471Size;
757*23ba6841SJoseph Chen 	hdr->code472Size = sizeof(rk_boot_entry);
758*23ba6841SJoseph Chen 
759*23ba6841SJoseph Chen 	hdr->loaderNum = gOpts.loaderNum;
760*23ba6841SJoseph Chen 	hdr->loaderOffset = hdr->code472Offset + gOpts.code472Num * hdr->code472Size;
761*23ba6841SJoseph Chen 	hdr->loaderSize = sizeof(rk_boot_entry);
762*23ba6841SJoseph Chen #ifndef USE_P_RC4
763*23ba6841SJoseph Chen 	hdr->rc4Flag = 1;
764*23ba6841SJoseph Chen #endif
765*23ba6841SJoseph Chen }
766*23ba6841SJoseph Chen 
767*23ba6841SJoseph Chen static inline uint32_t getCrc(const char *path)
768*23ba6841SJoseph Chen {
769*23ba6841SJoseph Chen 	uint32_t size = 0;
770*23ba6841SJoseph Chen 	uint32_t crc = 0;
771*23ba6841SJoseph Chen 	FILE *file = fopen(path, "rb");
772*23ba6841SJoseph Chen 	getFileSize(path, &size);
773*23ba6841SJoseph Chen 	if (!file)
774*23ba6841SJoseph Chen 		goto end;
775*23ba6841SJoseph Chen 	if (!fread(gBuf, size, 1, file))
776*23ba6841SJoseph Chen 		goto end;
777*23ba6841SJoseph Chen 	crc = CRC_32(gBuf, size);
778*23ba6841SJoseph Chen 	LOGD("crc:0x%08x\n", crc);
779*23ba6841SJoseph Chen end:
780*23ba6841SJoseph Chen 	if (file)
781*23ba6841SJoseph Chen 		fclose(file);
782*23ba6841SJoseph Chen 	return crc;
783*23ba6841SJoseph Chen }
784*23ba6841SJoseph Chen 
785*23ba6841SJoseph Chen static bool mergeBoot(int argc, char **argv)
786*23ba6841SJoseph Chen {
787*23ba6841SJoseph Chen 	uint32_t dataOffset;
788*23ba6841SJoseph Chen 	bool ret = false;
789*23ba6841SJoseph Chen 	int i;
790*23ba6841SJoseph Chen 	FILE *outFile;
791*23ba6841SJoseph Chen 	uint32_t crc;
792*23ba6841SJoseph Chen 	rk_boot_header hdr;
793*23ba6841SJoseph Chen 
794*23ba6841SJoseph Chen 	if (!initOpts(argc, argv))
795*23ba6841SJoseph Chen 		return false;
796*23ba6841SJoseph Chen 	{
797*23ba6841SJoseph Chen 		char *subfix = strstr(gOpts.outPath, OUT_SUBFIX);
798*23ba6841SJoseph Chen 		char version[MAX_LINE_LEN];
799*23ba6841SJoseph Chen 		snprintf(version, sizeof(version), "%s", gSubfix);
800*23ba6841SJoseph Chen 		if (subfix && !strcmp(subfix, OUT_SUBFIX)) {
801*23ba6841SJoseph Chen 			subfix[0] = '\0';
802*23ba6841SJoseph Chen 		}
803*23ba6841SJoseph Chen 		strcat(gOpts.outPath, version);
804*23ba6841SJoseph Chen 		printf("fix opt:%s\n", gOpts.outPath);
805*23ba6841SJoseph Chen 	}
806*23ba6841SJoseph Chen 
807*23ba6841SJoseph Chen 	if (gDebug) {
808*23ba6841SJoseph Chen 		printf("---------------\nUSING CONFIG:\n");
809*23ba6841SJoseph Chen 		printOpts(stdout);
810*23ba6841SJoseph Chen 		printf("---------------\n\n");
811*23ba6841SJoseph Chen 	}
812*23ba6841SJoseph Chen 
813*23ba6841SJoseph Chen 	outFile = fopen(gOpts.outPath, "wb+");
814*23ba6841SJoseph Chen 	if (!outFile) {
815*23ba6841SJoseph Chen 		LOGE("open out file(%s) failed\n", gOpts.outPath);
816*23ba6841SJoseph Chen 		goto end;
817*23ba6841SJoseph Chen 	}
818*23ba6841SJoseph Chen 
819*23ba6841SJoseph Chen 	getBoothdr(&hdr);
820*23ba6841SJoseph Chen 	LOGD("write hdr\n");
821*23ba6841SJoseph Chen 	fwrite(&hdr, 1, sizeof(rk_boot_header), outFile);
822*23ba6841SJoseph Chen 
823*23ba6841SJoseph Chen 	dataOffset = sizeof(rk_boot_header) +
824*23ba6841SJoseph Chen 	             (gOpts.code471Num + gOpts.code472Num + gOpts.loaderNum) *
825*23ba6841SJoseph Chen 	             sizeof(rk_boot_entry);
826*23ba6841SJoseph Chen 
827*23ba6841SJoseph Chen 	LOGD("write code 471 entry\n");
828*23ba6841SJoseph Chen 	for (i = 0; i < gOpts.code471Num; i++) {
829*23ba6841SJoseph Chen 		if (!saveEntry(outFile, (char *)gOpts.code471Path[i], ENTRY_471,
830*23ba6841SJoseph Chen 		               gOpts.code471Sleep, &dataOffset, NULL, false))
831*23ba6841SJoseph Chen 			goto end;
832*23ba6841SJoseph Chen 	}
833*23ba6841SJoseph Chen 	LOGD("write code 472 entry\n");
834*23ba6841SJoseph Chen 	for (i = 0; i < gOpts.code472Num; i++) {
835*23ba6841SJoseph Chen 		if (!saveEntry(outFile, (char *)gOpts.code472Path[i], ENTRY_472,
836*23ba6841SJoseph Chen 		               gOpts.code472Sleep, &dataOffset, NULL, false))
837*23ba6841SJoseph Chen 			goto end;
838*23ba6841SJoseph Chen 	}
839*23ba6841SJoseph Chen 	LOGD("write loader entry\n");
840*23ba6841SJoseph Chen 	for (i = 0; i < gOpts.loaderNum; i++) {
841*23ba6841SJoseph Chen 		if (!saveEntry(outFile, gOpts.loader[i].path, ENTRY_LOADER, 0, &dataOffset,
842*23ba6841SJoseph Chen 		               gOpts.loader[i].name, true))
843*23ba6841SJoseph Chen 			goto end;
844*23ba6841SJoseph Chen 	}
845*23ba6841SJoseph Chen 
846*23ba6841SJoseph Chen 	LOGD("write code 471\n");
847*23ba6841SJoseph Chen 	for (i = 0; i < gOpts.code471Num; i++) {
848*23ba6841SJoseph Chen 		if (!writeFile(outFile, (char *)gOpts.code471Path[i], false))
849*23ba6841SJoseph Chen 			goto end;
850*23ba6841SJoseph Chen 	}
851*23ba6841SJoseph Chen 	LOGD("write code 472\n");
852*23ba6841SJoseph Chen 	for (i = 0; i < gOpts.code472Num; i++) {
853*23ba6841SJoseph Chen 		if (!writeFile(outFile, (char *)gOpts.code472Path[i], false))
854*23ba6841SJoseph Chen 			goto end;
855*23ba6841SJoseph Chen 	}
856*23ba6841SJoseph Chen 	LOGD("write loader\n");
857*23ba6841SJoseph Chen 	for (i = 0; i < gOpts.loaderNum; i++) {
858*23ba6841SJoseph Chen 		if (!writeFile(outFile, gOpts.loader[i].path, true))
859*23ba6841SJoseph Chen 			goto end;
860*23ba6841SJoseph Chen 	}
861*23ba6841SJoseph Chen 	fflush(outFile);
862*23ba6841SJoseph Chen 
863*23ba6841SJoseph Chen 	LOGD("write crc\n");
864*23ba6841SJoseph Chen 	crc = getCrc(gOpts.outPath);
865*23ba6841SJoseph Chen 	if (!fwrite(&crc, sizeof(crc), 1, outFile))
866*23ba6841SJoseph Chen 		goto end;
867*23ba6841SJoseph Chen 
868*23ba6841SJoseph Chen 	ret = true;
869*23ba6841SJoseph Chen end:
870*23ba6841SJoseph Chen 	if (outFile)
871*23ba6841SJoseph Chen 		fclose(outFile);
872*23ba6841SJoseph Chen 	return ret;
873*23ba6841SJoseph Chen }
874*23ba6841SJoseph Chen 
875*23ba6841SJoseph Chen /************merge code end************/
876*23ba6841SJoseph Chen /************unpack code***************/
877*23ba6841SJoseph Chen 
878*23ba6841SJoseph Chen static inline void wide2str(const uint16_t *wide, char *str, int len)
879*23ba6841SJoseph Chen {
880*23ba6841SJoseph Chen 	int i;
881*23ba6841SJoseph Chen 	for (i = 0; i < len; i++) {
882*23ba6841SJoseph Chen 		str[i] = (char)(wide[i] & 0xFF);
883*23ba6841SJoseph Chen 	}
884*23ba6841SJoseph Chen 	str[len] = 0;
885*23ba6841SJoseph Chen }
886*23ba6841SJoseph Chen 
887*23ba6841SJoseph Chen static bool unpackEntry(rk_boot_entry *entry, const char *name, FILE *inFile)
888*23ba6841SJoseph Chen {
889*23ba6841SJoseph Chen 	bool ret = false;
890*23ba6841SJoseph Chen 	int size, i;
891*23ba6841SJoseph Chen 	FILE *outFile = fopen(name, "wb+");
892*23ba6841SJoseph Chen 	if (!outFile)
893*23ba6841SJoseph Chen 		goto end;
894*23ba6841SJoseph Chen 	printf("unpack entry(%s)\n", name);
895*23ba6841SJoseph Chen 	fseek(inFile, entry->dataOffset, SEEK_SET);
896*23ba6841SJoseph Chen 	size = entry->dataSize;
897*23ba6841SJoseph Chen 	if (!fread(gBuf, size, 1, inFile))
898*23ba6841SJoseph Chen 		goto end;
899*23ba6841SJoseph Chen 	if (entry->type == ENTRY_LOADER) {
900*23ba6841SJoseph Chen 		for (i = 0; i < size / SMALL_PACKET; i++)
901*23ba6841SJoseph Chen 			P_RC4(gBuf + i * SMALL_PACKET, SMALL_PACKET);
902*23ba6841SJoseph Chen 		if (size % SMALL_PACKET) {
903*23ba6841SJoseph Chen 			P_RC4(gBuf + i * SMALL_PACKET, size - SMALL_PACKET * 512);
904*23ba6841SJoseph Chen 		}
905*23ba6841SJoseph Chen 	} else {
906*23ba6841SJoseph Chen 		P_RC4(gBuf, size);
907*23ba6841SJoseph Chen 	}
908*23ba6841SJoseph Chen 	if (!fwrite(gBuf, size, 1, outFile))
909*23ba6841SJoseph Chen 		goto end;
910*23ba6841SJoseph Chen 	ret = true;
911*23ba6841SJoseph Chen end:
912*23ba6841SJoseph Chen 	if (outFile)
913*23ba6841SJoseph Chen 		fclose(outFile);
914*23ba6841SJoseph Chen 	return ret;
915*23ba6841SJoseph Chen }
916*23ba6841SJoseph Chen 
917*23ba6841SJoseph Chen static bool unpackBoot(char *path)
918*23ba6841SJoseph Chen {
919*23ba6841SJoseph Chen 	bool ret = false;
920*23ba6841SJoseph Chen 	FILE *inFile = fopen(path, "rb");
921*23ba6841SJoseph Chen 	int entryNum, i;
922*23ba6841SJoseph Chen 	char name[MAX_NAME_LEN];
923*23ba6841SJoseph Chen 	rk_boot_entry *entrys;
924*23ba6841SJoseph Chen 	if (!inFile) {
925*23ba6841SJoseph Chen 		fprintf(stderr, "loader(%s) not found\n", path);
926*23ba6841SJoseph Chen 		goto end;
927*23ba6841SJoseph Chen 	}
928*23ba6841SJoseph Chen 
929*23ba6841SJoseph Chen 	rk_boot_header hdr;
930*23ba6841SJoseph Chen 	if (!fread(&hdr, sizeof(rk_boot_header), 1, inFile)) {
931*23ba6841SJoseph Chen 		fprintf(stderr, "read header failed\n");
932*23ba6841SJoseph Chen 		goto end;
933*23ba6841SJoseph Chen 	}
934*23ba6841SJoseph Chen 
935*23ba6841SJoseph Chen 	entryNum = hdr.code471Num + hdr.code472Num + hdr.loaderNum;
936*23ba6841SJoseph Chen 	entrys = (rk_boot_entry *)malloc(sizeof(rk_boot_entry) * entryNum);
937*23ba6841SJoseph Chen 	if (!fread(entrys, sizeof(rk_boot_entry) * entryNum, 1, inFile)) {
938*23ba6841SJoseph Chen 		fprintf(stderr, "read data failed\n");
939*23ba6841SJoseph Chen 		goto end;
940*23ba6841SJoseph Chen 	}
941*23ba6841SJoseph Chen 
942*23ba6841SJoseph Chen 	LOGD("entry num:%d\n", entryNum);
943*23ba6841SJoseph Chen 	for (i = 0; i < entryNum; i++) {
944*23ba6841SJoseph Chen 		wide2str(entrys[i].name, name, MAX_NAME_LEN);
945*23ba6841SJoseph Chen 
946*23ba6841SJoseph Chen 		LOGD("entry:t=%d, name=%s, off=%d, size=%d\n", entrys[i].type, name,
947*23ba6841SJoseph Chen 		     entrys[i].dataOffset, entrys[i].dataSize);
948*23ba6841SJoseph Chen 		if (!unpackEntry(entrys + i, name, inFile)) {
949*23ba6841SJoseph Chen 			fprintf(stderr, "unpack entry(%s) failed\n", name);
950*23ba6841SJoseph Chen 			goto end;
951*23ba6841SJoseph Chen 		}
952*23ba6841SJoseph Chen 	}
953*23ba6841SJoseph Chen 
954*23ba6841SJoseph Chen 	ret = true;
955*23ba6841SJoseph Chen end:
956*23ba6841SJoseph Chen 	if (inFile)
957*23ba6841SJoseph Chen 		fclose(inFile);
958*23ba6841SJoseph Chen 	return ret;
959*23ba6841SJoseph Chen }
960*23ba6841SJoseph Chen 
961*23ba6841SJoseph Chen /************unpack code end***********/
962*23ba6841SJoseph Chen 
963*23ba6841SJoseph Chen static void printHelp(void)
964*23ba6841SJoseph Chen {
965*23ba6841SJoseph Chen 	printf("Usage1: boot_merger [options]... FILE\n");
966*23ba6841SJoseph Chen 	printf("Merge or unpack Rockchip's loader (Default action is to merge.)\n");
967*23ba6841SJoseph Chen 	printf("Options:\n");
968*23ba6841SJoseph Chen 	printf("\t" OPT_MERGE "\t\t\tMerge loader with specified config.\n");
969*23ba6841SJoseph Chen 	printf("\t" OPT_UNPACK "\t\tUnpack specified loader to current dir.\n");
970*23ba6841SJoseph Chen 	printf("\t" OPT_VERBOSE "\t\tDisplay more runtime informations.\n");
971*23ba6841SJoseph Chen 	printf("\t" OPT_HELP "\t\t\tDisplay this information.\n");
972*23ba6841SJoseph Chen 	printf("\t" OPT_VERSION "\t\tDisplay version information.\n");
973*23ba6841SJoseph Chen 	printf("\t" OPT_SUBFIX "\t\tSpec subfix.\n");
974*23ba6841SJoseph Chen 	printf("\t" OPT_REPLACE "\t\tReplace some part of binary path.\n");
975*23ba6841SJoseph Chen 	printf("\t" OPT_SIZE
976*23ba6841SJoseph Chen 	       "\t\tImage size.\"--size [image KB size]\", must be 512KB aligned\n");
977*23ba6841SJoseph Chen 	printf("Usage2: boot_merger [options] [parameter]\n");
978*23ba6841SJoseph Chen 	printf("All below five option are must in this mode!\n");
979*23ba6841SJoseph Chen 	printf("\t" OPT_CHIP "\t\tChip type, used for check with usbplug.\n");
980*23ba6841SJoseph Chen 	printf("\t" OPT_471 "\t\t471 for download, ddr.bin.\n");
981*23ba6841SJoseph Chen 	printf("\t" OPT_472 "\t\t472 for download, usbplug.bin.\n");
982*23ba6841SJoseph Chen 	printf("\t" OPT_DATA "\t\tloader0 for flash, ddr.bin.\n");
983*23ba6841SJoseph Chen 	printf("\t" OPT_BOOT "\t\tloader1 for flash, miniloader.bin.\n");
984*23ba6841SJoseph Chen 	printf("\n./tools/boot_merger --pack --verbose -c RK322A -1 "
985*23ba6841SJoseph Chen 	       "rkbin/rk322x_ddr_300MHz_v1.04.bin -2 "
986*23ba6841SJoseph Chen 	       "rkbin/rk32/rk322x_usbplug_v2.32.bin -d "
987*23ba6841SJoseph Chen 	       "rkbin/rk32/rk322x_ddr_300MHz_v1.04.bin -b "
988*23ba6841SJoseph Chen 	       "rkbin/rk32/rk322x_miniloader_v2.32.bin\n");
989*23ba6841SJoseph Chen }
990*23ba6841SJoseph Chen 
991*23ba6841SJoseph Chen int main(int argc, char **argv)
992*23ba6841SJoseph Chen {
993*23ba6841SJoseph Chen 
994*23ba6841SJoseph Chen 	int i;
995*23ba6841SJoseph Chen 	bool merge = true;
996*23ba6841SJoseph Chen 	char *optPath = NULL;
997*23ba6841SJoseph Chen 
998*23ba6841SJoseph Chen 	for (i = 1; i < argc; i++) {
999*23ba6841SJoseph Chen 		if (!strcmp(OPT_VERBOSE, argv[i])) {
1000*23ba6841SJoseph Chen 			gDebug = true;
1001*23ba6841SJoseph Chen 			printf("enable debug\n");
1002*23ba6841SJoseph Chen 		} else if (!strcmp(OPT_HELP, argv[i])) {
1003*23ba6841SJoseph Chen 			printHelp();
1004*23ba6841SJoseph Chen 			return 0;
1005*23ba6841SJoseph Chen 		} else if (!strcmp(OPT_VERSION, argv[i])) {
1006*23ba6841SJoseph Chen 			printf("boot_merger (cjf@rock-chips.com)\t" VERSION "\n");
1007*23ba6841SJoseph Chen 			return 0;
1008*23ba6841SJoseph Chen 		} else if (!strcmp(OPT_MERGE, argv[i])) {
1009*23ba6841SJoseph Chen 			merge = true;
1010*23ba6841SJoseph Chen 		} else if (!strcmp(OPT_UNPACK, argv[i])) {
1011*23ba6841SJoseph Chen 			merge = false;
1012*23ba6841SJoseph Chen 		} else if (!strcmp(OPT_SUBFIX, argv[i])) {
1013*23ba6841SJoseph Chen 			i++;
1014*23ba6841SJoseph Chen 			snprintf(gSubfix, sizeof(gSubfix), "%s", argv[i]);
1015*23ba6841SJoseph Chen 		} else if (!strcmp(OPT_REPLACE, argv[i])) {
1016*23ba6841SJoseph Chen 			i++;
1017*23ba6841SJoseph Chen 			snprintf(gLegacyPath, sizeof(gLegacyPath), "%s", argv[i]);
1018*23ba6841SJoseph Chen 			i++;
1019*23ba6841SJoseph Chen 			snprintf(gNewPath, sizeof(gNewPath), "%s", argv[i]);
1020*23ba6841SJoseph Chen 		} else if (!strcmp(OPT_SIZE, argv[i])) {
1021*23ba6841SJoseph Chen 			g_merge_max_size = strtoul(argv[++i], NULL, 10);
1022*23ba6841SJoseph Chen 			if (g_merge_max_size % 512) {
1023*23ba6841SJoseph Chen 				printHelp();
1024*23ba6841SJoseph Chen 				return -1;
1025*23ba6841SJoseph Chen 			}
1026*23ba6841SJoseph Chen 			g_merge_max_size *= 1024; /* bytes */
1027*23ba6841SJoseph Chen 		} else {
1028*23ba6841SJoseph Chen 			optPath = argv[i];
1029*23ba6841SJoseph Chen 			break;
1030*23ba6841SJoseph Chen 		}
1031*23ba6841SJoseph Chen 	}
1032*23ba6841SJoseph Chen 	if (!merge && !optPath) {
1033*23ba6841SJoseph Chen 		fprintf(stderr, "need set out path to unpack!\n");
1034*23ba6841SJoseph Chen 		printHelp();
1035*23ba6841SJoseph Chen 		return -1;
1036*23ba6841SJoseph Chen 	}
1037*23ba6841SJoseph Chen 
1038*23ba6841SJoseph Chen 	gBuf = calloc(g_merge_max_size, 1);
1039*23ba6841SJoseph Chen 	if (!gBuf) {
1040*23ba6841SJoseph Chen 		LOGE("Merge image: calloc buffer error.\n");
1041*23ba6841SJoseph Chen 		return -1;
1042*23ba6841SJoseph Chen 	}
1043*23ba6841SJoseph Chen 
1044*23ba6841SJoseph Chen 	if (merge) {
1045*23ba6841SJoseph Chen 		LOGD("do_merge\n");
1046*23ba6841SJoseph Chen 		gConfigPath = optPath;
1047*23ba6841SJoseph Chen 		if (!mergeBoot(argc, argv)) {
1048*23ba6841SJoseph Chen 			fprintf(stderr, "merge failed!\n");
1049*23ba6841SJoseph Chen 			return -1;
1050*23ba6841SJoseph Chen 		}
1051*23ba6841SJoseph Chen 		printf("merge success(%s)\n", gOpts.outPath);
1052*23ba6841SJoseph Chen 	} else {
1053*23ba6841SJoseph Chen 		LOGD("do_unpack\n");
1054*23ba6841SJoseph Chen 		if (!unpackBoot(optPath)) {
1055*23ba6841SJoseph Chen 			fprintf(stderr, "unpack failed!\n");
1056*23ba6841SJoseph Chen 			return -1;
1057*23ba6841SJoseph Chen 		}
1058*23ba6841SJoseph Chen 		printf("unpack success\n");
1059*23ba6841SJoseph Chen 	}
1060*23ba6841SJoseph Chen 	return 0;
1061*23ba6841SJoseph Chen }
1062