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