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