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