xref: /rkdeveloptool/main.cpp (revision c29e5f0fb3abaf1286e0478b8fc93c6c4f41dd53)
1 /*
2  * (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd
3  * Seth Liu 2017.03.01
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include   <unistd.h>
9 #include   <dirent.h>
10 #include "config.h"
11 #include "DefineHeader.h"
12 #include "gpt.h"
13 #include "RKLog.h"
14 #include "RKScan.h"
15 #include "RKComm.h"
16 #include "RKDevice.h"
17 #include "RKImage.h"
18 extern const char *szManufName[];
19 CRKLog *g_pLogObject=NULL;
20 CONFIG_ITEM_VECTOR g_ConfigItemVec;
21 #define DEFAULT_RW_LBA 128
22 #define CURSOR_MOVEUP_LINE(n) printf("%c[%dA", 0x1B, n)
23 #define CURSOR_DEL_LINE printf("%c[2K", 0x1B)
24 #define CURSOR_MOVE_HOME printf("%c[H", 0x1B)
25 #define CURSOR_CLEAR_SCREEN printf("%c[2J", 0x1B)
26 #define ERROR_COLOR_ATTR  printf("%c[30;41m", 0x1B);
27 #define NORMAL_COLOR_ATTR  printf("%c[0m", 0x1B);
28 extern UINT CRC_32(unsigned char* pData, UINT ulSize);
29 extern unsigned short CRC_16(unsigned char* aData, UINT aSize);
30 extern void P_RC4(unsigned char* buf, unsigned short len);
31 extern unsigned int crc32_le(unsigned int crc, unsigned char *p, unsigned int len);
32 /*
33 u8 test_gpt_head[] = {
34 	0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54, 0x00, 0x00, 0x01, 0x00, 0x5C, 0x00, 0x00, 0x00,
35 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36 	0xFF, 0xFF, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 	0xDE, 0xFF, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x49, 0x94, 0xEC, 0x23, 0xE8, 0x58, 0x4B,
38 	0xAE, 0xB7, 0xA9, 0x46, 0x51, 0xD0, 0x08, 0xF8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39 	0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x51, 0xEA, 0xFE, 0x08};
40 */
41 
42 void usage()
43 {
44 	printf("\r\n---------------------Tool Usage ---------------------\r\n");
45 	printf("Help:\t\t\t-h or --version\r\n");
46 	printf("Version:\t\t-v or --version\r\n");
47 	printf("DownloadBoot:\t\tdb <Loader>\r\n");
48 	printf("UpgradeLoader:\t\tul <Loader>\r\n");
49 	printf("ReadLBA:\t\trl  <BeginSec> <SectorLen> <File>\r\n");
50 	printf("WriteLBA:\t\twl  <BeginSec> <File>\r\n");
51 	printf("WriteGPT:\t\tgpt <gpt partition table>\r\n");
52 	printf("EraseFlash:\t\tef \r\n");
53 	printf("TestDevice:\t\ttd\r\n");
54 	printf("ResetDevice:\t\trd [subcode]\r\n");
55 	printf("ReadFlashID:\t\trid\r\n");
56 	printf("ReadFlashInfo:\t\trfi\r\n");
57 	printf("ReadChipInfo:\t\trci\r\n");
58 	printf("PackBootLoader:\t\tpack\r\n");
59 	printf("UnpackBootLoader:\tunpack <boot loader>\r\n");
60 	printf("TagSPL:\t\t\ttagspl <tag> <U-Boot SPL>\r\n");
61 	printf("-------------------------------------------------------\r\n\r\n");
62 }
63 void ProgressInfoProc(DWORD deviceLayer, ENUM_PROGRESS_PROMPT promptID, long long totalValue, long long currentValue, ENUM_CALL_STEP emCall)
64 {
65 	string strInfoText="";
66 	char szText[256];
67 	switch (promptID) {
68 	case TESTDEVICE_PROGRESS:
69 		sprintf(szText, "Test Device total %lld, current %lld", totalValue, currentValue);
70 		strInfoText = szText;
71 		break;
72 	case LOWERFORMAT_PROGRESS:
73 		sprintf(szText, "Lowerformat Device total %lld, current %lld", totalValue, currentValue);
74 		strInfoText = szText;
75 		break;
76 	case DOWNLOADIMAGE_PROGRESS:
77 		sprintf(szText, "Download Image total %lldK, current %lldK", totalValue/1024, currentValue/1024);
78 		strInfoText = szText;
79 		break;
80 	case CHECKIMAGE_PROGRESS:
81 		sprintf(szText, "Check Image total %lldK, current %lldK", totalValue/1024, currentValue/1024);
82 		strInfoText = szText;
83 		break;
84 	case TAGBADBLOCK_PROGRESS:
85 		sprintf(szText, "Tag Bad Block total %lld, current %lld", totalValue, currentValue);
86 		strInfoText = szText;
87 		break;
88 	case TESTBLOCK_PROGRESS:
89 		sprintf(szText, "Test Block total %lld, current %lld", totalValue, currentValue);
90 		strInfoText = szText;
91 		break;
92 	case ERASEFLASH_PROGRESS:
93 		sprintf(szText, "Erase Flash total %lld, current %lld", totalValue, currentValue);
94 		strInfoText = szText;
95 		break;
96 	case ERASESYSTEM_PROGRESS:
97 		sprintf(szText, "Erase System partition total %lld, current %lld", totalValue, currentValue);
98 		strInfoText = szText;
99 		break;
100 	case ERASEUSERDATA_PROGRESS:
101 		sprintf(szText, "<LocationID=%x> Erase Userdata partition total %lld, current %lld", deviceLayer, totalValue, currentValue);
102 		strInfoText = szText;
103 		break;
104 	}
105 	if (strInfoText.size() > 0){
106 		CURSOR_MOVEUP_LINE(1);
107 		CURSOR_DEL_LINE;
108 		printf("%s\r\n", strInfoText.c_str());
109 	}
110 	if (emCall == CALL_LAST)
111 		deviceLayer = 0;
112 }
113 
114 char *strupr(char *szSrc)
115 {
116 	char *p = szSrc;
117 	while(*p){
118 		if ((*p >= 'a') && (*p <= 'z'))
119 			*p = *p - 'a' + 'A';
120 		p++;
121 	}
122 	return szSrc;
123 }
124 void PrintData(PBYTE pData, int nSize)
125 {
126 	char szPrint[17] = "\0";
127 	int i;
128 	for( i = 0; i < nSize; i++){
129 		if(i % 16 == 0){
130 			if(i / 16 > 0)
131 				printf("     %s\r\n", szPrint);
132 			printf("%08d ", i / 16);
133 		}
134 		printf("%02X ", pData[i]);
135 		szPrint[i%16] = isprint(pData[i]) ? pData[i] : '.';
136 	}
137 	if(i / 16 > 0)
138 		printf("     %s\r\n", szPrint);
139 }
140 
141 bool StringToWideString(char *pszSrc, wchar_t *&pszDest)
142 {
143 	if (!pszSrc)
144 		return false;
145 	int nSrcLen = strlen(pszSrc);
146 	int nDestLen = nSrcLen * 2;
147 
148 	pszDest = NULL;
149 	pszDest = new wchar_t[nDestLen];
150 	if (!pszDest)
151 		return false;
152 	nDestLen = nDestLen * sizeof(wchar_t);
153 	memset(pszDest, 0, nDestLen);
154 	int iRet;
155 	iconv_t cd;
156 	cd = iconv_open("UTF-32", "UTF-8");
157 	if((iconv_t)-1 == cd) {
158 		delete []pszDest;
159 		pszDest = NULL;
160 	      return false;
161 	 }
162 	char *pIn, *pOut;
163 	pIn = (char *)pszSrc;
164 	pOut = (char *)pszDest;
165 
166 	iRet = iconv(cd, (char **)&pIn, (size_t *)&nSrcLen, (char **)&pOut, (size_t *)&nDestLen);
167 
168 	if(iRet == -1) {
169 		delete []pszDest;
170 		pszDest = NULL;
171 		iconv_close(cd);
172 		return false;
173 	 }
174 
175 	 iconv_close(cd);
176 
177 	 return true;
178 }
179 bool WideStringToString(wchar_t *pszSrc, char *&pszDest)
180 {
181 	if (!pszSrc)
182 		return false;
183 	int nSrcLen = wcslen(pszSrc);
184 	int nDestLen = nSrcLen * 2;
185 	nSrcLen = nSrcLen * sizeof(wchar_t);
186 	pszDest = NULL;
187 	pszDest = new char[nDestLen];
188 	if (!pszDest)
189 		return false;
190 	memset(pszDest, 0, nDestLen);
191 	int iRet;
192 	iconv_t cd;
193 	cd = iconv_open("UTF-8", "UTF-32");
194 
195 	if((iconv_t)-1 == cd) {
196 		delete []pszDest;
197 		pszDest = NULL;
198 	      return false;
199 	 }
200 	char *pIn, *pOut;
201 	pIn = (char *)pszSrc;
202 	pOut = (char *)pszDest;
203 	iRet = iconv(cd, (char **)&pIn, (size_t *)&nSrcLen, (char **)&pOut, (size_t *)&nDestLen);
204 
205 	if(iRet == -1) {
206 		delete []pszDest;
207 		pszDest = NULL;
208 		iconv_close(cd);
209 		return false;
210 	 }
211 
212 	 iconv_close(cd);
213 
214 	 return true;
215 }
216 int find_config_item(CONFIG_ITEM_VECTOR &vecItems, const char *pszName)
217 {
218 	unsigned int i;
219 	for(i = 0; i < vecItems.size(); i++){
220 		if (strcasecmp(pszName, vecItems[i].szItemName) == 0){
221 			return i;
222 		}
223 	}
224 	return -1;
225 }
226 void string_to_uuid(string strUUid, char *uuid)
227 {
228 	unsigned int i;
229 	char value;
230 	memset(uuid, 0, 16);
231 	for (i =0; i < strUUid.size(); i++) {
232 		value = 0;
233 		if ((strUUid[i] >= '0')&&(strUUid[i] <= '9'))
234 			value = strUUid[i] - '0';
235 		if ((strUUid[i] >= 'a')&&(strUUid[i] <= 'f'))
236 			value = strUUid[i] - 'a' + 10;
237 		if ((strUUid[i] >= 'A')&&(strUUid[i] <= 'F'))
238 			value = strUUid[i] - 'A' + 10;
239 		if ((i % 2) == 0)
240 			uuid[i / 2] += (value << 4);
241 		else
242 			uuid[i / 2] += value;
243 	}
244 	unsigned int *p32;
245 	unsigned short *p16;
246 	p32 = (unsigned int*)uuid;
247 	*p32 = cpu_to_be32(*p32);
248 	p16 = (unsigned short *)(uuid + 4);
249 	*p16 = cpu_to_be16(*p16);
250 	p16 = (unsigned short *)(uuid + 6);
251 	*p16 = cpu_to_be16(*p16);
252 }
253 
254 bool parse_config(char *pConfig, CONFIG_ITEM_VECTOR &vecItem)
255 {
256 
257 	stringstream configStream(pConfig);
258 	string strLine, strItemName, strItemValue;
259 	string::size_type line_size,pos;
260 	STRUCT_CONFIG_ITEM item;
261 	vecItem.clear();
262 	while (!configStream.eof()){
263 		getline(configStream, strLine);
264 		line_size = strLine.size();
265 		if (line_size == 0)
266 			continue;
267 		if (strLine[line_size-1] == '\r'){
268 			strLine = strLine.substr(0, line_size-1);
269 		}
270 		strLine.erase(0, strLine.find_first_not_of(" "));
271 		strLine.erase(strLine.find_last_not_of(" ") + 1);
272 		if (strLine.size()==0 )
273 			continue;
274 		if (strLine[0] == '#')
275 			continue;
276 		pos = strLine.find("=");
277 		if (pos == string::npos){
278 			continue;
279 		}
280 		strItemName = strLine.substr(0, pos);
281 		strItemValue = strLine.substr(pos + 1);
282 		strItemName.erase(0, strItemName.find_first_not_of(" "));
283 		strItemName.erase(strItemName.find_last_not_of(" ") + 1);
284 		strItemValue.erase(0, strItemValue.find_first_not_of(" "));
285 		strItemValue.erase(strItemValue.find_last_not_of(" ") + 1);
286 		if ((strItemName.size() > 0) && (strItemValue.size() > 0)){
287 			strcpy(item.szItemName, strItemName.c_str());
288 			strcpy(item.szItemValue, strItemValue.c_str());
289 			vecItem.push_back(item);
290 		}
291 	}
292 	return true;
293 
294 }
295 bool parse_config_file(const char *pConfigFile, CONFIG_ITEM_VECTOR &vecItem)
296 {
297 	FILE *file = NULL;
298 	file = fopen(pConfigFile, "rb");
299 	if( !file ){
300 		if (g_pLogObject)
301 			g_pLogObject->Record("%s failed, err=%d, can't open file: %s\r\n", __func__, errno, pConfigFile);
302 		return false;
303 	}
304 	int iFileSize;
305 	fseek(file, 0, SEEK_END);
306 	iFileSize = ftell(file);
307 	fseek(file, 0, SEEK_SET);
308 	char *pConfigBuf = NULL;
309 	pConfigBuf = new char[iFileSize + 1];
310 	if (!pConfigBuf){
311 		fclose(file);
312 		return false;
313 	}
314 	memset(pConfigBuf, 0, iFileSize + 1);
315 	int iRead;
316 	iRead = fread(pConfigBuf, 1, iFileSize, file);
317 	if (iRead != iFileSize){
318 		if (g_pLogObject)
319 			g_pLogObject->Record("%s failed, err=%d, read=%d, total=%d\r\n", __func__, errno, iRead, iFileSize);
320 		fclose(file);
321 		delete []pConfigBuf;
322 		return false;
323 	}
324 	fclose(file);
325 	bool bRet;
326 	bRet = parse_config(pConfigBuf, vecItem);
327 	delete []pConfigBuf;
328 	return bRet;
329 }
330 bool ParsePartitionInfo(string &strPartInfo, string &strName, UINT &uiOffset, UINT &uiLen)
331 {
332 	string::size_type pos,prevPos;
333 	string strOffset,strLen;
334 	int iCount;
335 	prevPos = pos = 0;
336 	if (strPartInfo.size() <= 0) {
337 		return false;
338 	}
339 	pos = strPartInfo.find('@');
340 	if (pos == string::npos) {
341 		return false;
342 	}
343 	strLen = strPartInfo.substr(prevPos, pos - prevPos);
344 	strLen.erase(0, strLen.find_first_not_of(" "));
345 	strLen.erase(strLen.find_last_not_of(" ") + 1);
346 	if (strchr(strLen.c_str(), '-')) {
347 		uiLen = 0xFFFFFFFF;
348 	} else {
349 		iCount = sscanf(strLen.c_str(), "0x%x", &uiLen);
350 		if (iCount != 1) {
351 			return false;
352 		}
353 	}
354 
355 	prevPos = pos + 1;
356 	pos = strPartInfo.find('(',prevPos);
357 	if (pos == string::npos) {
358 		return false;
359 	}
360 	strOffset = strPartInfo.substr(prevPos, pos - prevPos);
361 	strOffset.erase(0, strOffset.find_first_not_of(" "));
362 	strOffset.erase(strOffset.find_last_not_of(" ") + 1);
363 	iCount = sscanf(strOffset.c_str(), "0x%x", &uiOffset);
364 	if (iCount != 1) {
365 		return false;
366 	}
367 	prevPos = pos + 1;
368 	pos = strPartInfo.find(')', prevPos);
369 	if (pos == string::npos) {
370 		return false;
371 	}
372 	strName = strPartInfo.substr(prevPos, pos - prevPos);
373 	strName.erase(0, strName.find_first_not_of(" "));
374 	strName.erase(strName.find_last_not_of(" ") + 1);
375 
376 	return true;
377 }
378 bool ParseUuidInfo(string &strUuidInfo, string &strName, string &strUUid)
379 {
380 	string::size_type pos(0);
381 
382 	if (strUuidInfo.size() <= 0) {
383 		return false;
384 	}
385 	pos = strUuidInfo.find('=');
386 	if (pos == string::npos) {
387 		return false;
388 	}
389 	strName = strUuidInfo.substr(0, pos);
390 	strName.erase(0, strName.find_first_not_of(" "));
391 	strName.erase(strName.find_last_not_of(" ") + 1);
392 
393 	strUUid = strUuidInfo.substr(pos+1);
394 	strUUid.erase(0, strUUid.find_first_not_of(" "));
395 	strUUid.erase(strUUid.find_last_not_of(" ") + 1);
396 
397 	while(true) {
398 		pos = 0;
399 		if( (pos = strUUid.find("-")) != string::npos)
400 			strUUid.replace(pos,1,"");
401 		else
402 			break;
403 	}
404 	if (strUUid.size() != 32)
405 		return false;
406 	return true;
407 }
408 
409 
410 bool parse_parameter(char *pParameter, PARAM_ITEM_VECTOR &vecItem, CONFIG_ITEM_VECTOR &vecUuidItem)
411 {
412 	stringstream paramStream(pParameter);
413 	bool bRet,bFind = false;
414 	string strLine, strPartition, strPartInfo, strPartName, strUUid;
415 	string::size_type line_size, pos, posColon, posComma;
416 	UINT uiPartOffset, uiPartSize;
417 	STRUCT_PARAM_ITEM item;
418 	STRUCT_CONFIG_ITEM uuid_item;
419 	vecItem.clear();
420 	vecUuidItem.clear();
421 	while (!paramStream.eof()) {
422 		getline(paramStream,strLine);
423 		line_size = strLine.size();
424 		if (line_size == 0)
425 			continue;
426 		if (strLine[line_size - 1] == '\r'){
427 			strLine = strLine.substr(0, line_size - 1);
428 		}
429 		strLine.erase(0, strLine.find_first_not_of(" "));
430 		strLine.erase(strLine.find_last_not_of(" ") + 1);
431 		if (strLine.size()==0 )
432 			continue;
433 		if (strLine[0] == '#')
434 			continue;
435 		pos = strLine.find("uuid:");
436 		if (pos != string::npos) {
437 			strPartInfo = strLine.substr(pos+5);
438 			bRet = ParseUuidInfo(strPartInfo, strPartName, strUUid);
439 			if (bRet) {
440 				strcpy(uuid_item.szItemName, strPartName.c_str());
441 				string_to_uuid(strUUid,uuid_item.szItemValue);
442 				vecUuidItem.push_back(uuid_item);
443 			}
444 			continue;
445 		}
446 
447 		pos = strLine.find("mtdparts");
448 		if (pos == string::npos) {
449 			continue;
450 		}
451 		bFind = true;
452 		posColon = strLine.find(':', pos);
453 		if (posColon == string::npos) {
454 			continue;
455 		}
456 		strPartition = strLine.substr(posColon + 1);
457 		pos = 0;
458 		posComma = strPartition.find(',', pos);
459 		while (posComma != string::npos) {
460 			strPartInfo = strPartition.substr(pos, posComma - pos);
461 			bRet = ParsePartitionInfo(strPartInfo, strPartName, uiPartOffset, uiPartSize);
462 			if (bRet) {
463 				strcpy(item.szItemName, strPartName.c_str());
464 				item.uiItemOffset = uiPartOffset;
465 				item.uiItemSize = uiPartSize;
466 				vecItem.push_back(item);
467 			}
468 			pos = posComma + 1;
469 			posComma = strPartition.find(',', pos);
470 		}
471 		strPartInfo = strPartition.substr(pos);
472 		if (strPartInfo.size() > 0) {
473 			bRet = ParsePartitionInfo(strPartInfo, strPartName, uiPartOffset, uiPartSize);
474 			if (bRet) {
475 				strcpy(item.szItemName, strPartName.c_str());
476 				item.uiItemOffset = uiPartOffset;
477 				item.uiItemSize = uiPartSize;
478 				vecItem.push_back(item);
479 			}
480 		}
481 		break;
482 	}
483 	return bFind;
484 
485 }
486 bool parse_parameter_file(char *pParamFile, PARAM_ITEM_VECTOR &vecItem, CONFIG_ITEM_VECTOR &vecUuidItem)
487 {
488 	FILE *file = NULL;
489 	file = fopen(pParamFile, "rb");
490 	if( !file ) {
491 		if (g_pLogObject)
492 			g_pLogObject->Record("%s failed, err=%d, can't open file: %s\r\n", __func__, errno, pParamFile);
493 		return false;
494 	}
495 	int iFileSize;
496 	fseek(file, 0, SEEK_END);
497 	iFileSize = ftell(file);
498 	fseek(file, 0, SEEK_SET);
499 	char *pParamBuf = NULL;
500 	pParamBuf = new char[iFileSize];
501 	if (!pParamBuf) {
502 		fclose(file);
503 		return false;
504 	}
505 	int iRead;
506 	iRead = fread(pParamBuf, 1, iFileSize, file);
507 	if (iRead != iFileSize) {
508 		if (g_pLogObject)
509 			g_pLogObject->Record("%s failed, err=%d, read=%d, total=%d\r\n", __func__, errno,iRead,iFileSize);
510 		fclose(file);
511 		delete []pParamBuf;
512 		return false;
513 	}
514 	fclose(file);
515 	bool bRet;
516 	bRet = parse_parameter(pParamBuf, vecItem, vecUuidItem);
517 	delete []pParamBuf;
518 	return bRet;
519 }
520 void gen_rand_uuid(unsigned char *uuid_bin)
521 {
522 	efi_guid_t id;
523 	unsigned int *ptr = (unsigned int *)&id;
524 	unsigned int i;
525 
526 	/* Set all fields randomly */
527 	for (i = 0; i < sizeof(id) / sizeof(*ptr); i++)
528 		*(ptr + i) = cpu_to_be32(rand());
529 
530 	id.uuid.time_hi_and_version = (id.uuid.time_hi_and_version & 0x0FFF) | 0x4000;
531 	id.uuid.clock_seq_hi_and_reserved = id.uuid.clock_seq_hi_and_reserved | 0x80;
532 
533 	memcpy(uuid_bin, id.raw, sizeof(id));
534 }
535 
536 void prepare_gpt_backup(u8 *master, u8 *backup)
537 {
538 	gpt_header *gptMasterHead = (gpt_header *)(master + SECTOR_SIZE);
539 	gpt_header *gptBackupHead = (gpt_header *)(backup + 32 * SECTOR_SIZE);
540 	u32 calc_crc32;
541 	u64 val;
542 
543 	/* recalculate the values for the Backup GPT Header */
544 	val = le64_to_cpu(gptMasterHead->my_lba);
545 	gptBackupHead->my_lba = gptMasterHead->alternate_lba;
546 	gptBackupHead->alternate_lba = cpu_to_le64(val);
547 	gptBackupHead->partition_entry_lba = cpu_to_le64(le64_to_cpu(gptMasterHead->last_usable_lba) + 1);
548 	gptBackupHead->header_crc32 = 0;
549 
550 	calc_crc32 = crc32_le(0, (unsigned char *)gptBackupHead, le32_to_cpu(gptBackupHead->header_size));
551 	gptBackupHead->header_crc32 = cpu_to_le32(calc_crc32);
552 }
553 void update_gpt_disksize(u8 *master, u8 *backup, u32 total_sector)
554 {
555 	gpt_header *gptMasterHead = (gpt_header *)(master + SECTOR_SIZE);
556 	gpt_entry  *gptLastPartEntry  = NULL;
557 	u32 i;
558 	u64 old_disksize;
559 	u8 zerobuf[GPT_ENTRY_SIZE];
560 
561 	memset(zerobuf,0,GPT_ENTRY_SIZE);
562 	old_disksize = le64_to_cpu(gptMasterHead->alternate_lba) + 1;
563 	for (i = 0; i < le32_to_cpu(gptMasterHead->num_partition_entries); i++) {
564 		gptLastPartEntry = (gpt_entry *)(master + 2 * SECTOR_SIZE + i * GPT_ENTRY_SIZE);
565 		if (memcmp(zerobuf, (u8 *)gptLastPartEntry, GPT_ENTRY_SIZE) == 0)
566 			break;
567 	}
568 	i--;
569 	gptLastPartEntry = (gpt_entry *)(master + 2 * SECTOR_SIZE + i * sizeof(gpt_entry));
570 
571 	gptMasterHead->alternate_lba = cpu_to_le64(total_sector - 1);
572 	gptMasterHead->last_usable_lba = cpu_to_le64(total_sector- 34);
573 
574 	if (gptLastPartEntry->ending_lba == (old_disksize - 34)) {//grow partition
575 		gptLastPartEntry->ending_lba = cpu_to_le64(total_sector- 34);
576 		gptMasterHead->partition_entry_array_crc32 = cpu_to_le32(crc32_le(0, master + 2 * SECTOR_SIZE, GPT_ENTRY_SIZE * GPT_ENTRY_NUMBERS));
577 	}
578 	gptMasterHead->header_crc32 = 0;
579 	gptMasterHead->header_crc32 = cpu_to_le32(crc32_le(0, master + SECTOR_SIZE, sizeof(gpt_header)));
580 	memcpy(backup,master + 2 * SECTOR_SIZE, GPT_ENTRY_SIZE * GPT_ENTRY_NUMBERS);
581 	memcpy(backup + GPT_ENTRY_SIZE * GPT_ENTRY_NUMBERS, master + SECTOR_SIZE, SECTOR_SIZE);
582 	prepare_gpt_backup(master, backup);
583 
584 }
585 bool load_gpt_buffer(char *pParamFile, u8 *master, u8 *backup)
586 {
587 	FILE *file = NULL;
588 	file = fopen(pParamFile, "rb");
589 	if( !file ) {
590 		if (g_pLogObject)
591 			g_pLogObject->Record("%s failed, err=%d, can't open file: %s\r\n", __func__, errno, pParamFile);
592 		return false;
593 	}
594 	int iFileSize;
595 	fseek(file, 0, SEEK_END);
596 	iFileSize = ftell(file);
597 	fseek(file, 0, SEEK_SET);
598 	if (iFileSize != 67 * SECTOR_SIZE) {
599 		if (g_pLogObject)
600 			g_pLogObject->Record("%s failed, wrong size file: %s\r\n", __func__, pParamFile);
601 		fclose(file);
602 		return false;
603 	}
604 
605 	int iRead;
606 	iRead = fread(master, 1, 34 * SECTOR_SIZE, file);
607 	if (iRead != 34 * SECTOR_SIZE) {
608 		if (g_pLogObject)
609 			g_pLogObject->Record("%s failed,read master gpt err=%d, read=%d, total=%d\r\n", __func__, errno,iRead, 34 * SECTOR_SIZE);
610 		fclose(file);
611 		return false;
612 	}
613 	iRead = fread(backup, 1, 33 * SECTOR_SIZE, file);
614 	if (iRead != 33 * SECTOR_SIZE) {
615 		if (g_pLogObject)
616 			g_pLogObject->Record("%s failed,read backup gpt err=%d, read=%d, total=%d\r\n", __func__, errno,iRead, 33 * SECTOR_SIZE);
617 		fclose(file);
618 		return false;
619 	}
620 	fclose(file);
621 	return true;
622 }
623 void create_gpt_buffer(u8 *gpt, PARAM_ITEM_VECTOR &vecParts, CONFIG_ITEM_VECTOR &vecUuid, u64 diskSectors)
624 {
625 	legacy_mbr *mbr = (legacy_mbr *)gpt;
626 	gpt_header *gptHead = (gpt_header *)(gpt + SECTOR_SIZE);
627 	gpt_entry *gptEntry = (gpt_entry *)(gpt + 2 * SECTOR_SIZE);
628 	u32 i,j;
629 	int pos;
630 	string strPartName;
631 	string::size_type colonPos;
632 	/*1.protective mbr*/
633 	memset(gpt, 0, SECTOR_SIZE);
634 	mbr->signature = MSDOS_MBR_SIGNATURE;
635 	mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT;
636 	mbr->partition_record[0].start_sect = 1;
637 	mbr->partition_record[0].nr_sects = (u32)-1;
638 	/*2.gpt header*/
639 	memset(gpt + SECTOR_SIZE, 0, SECTOR_SIZE);
640 	gptHead->signature = cpu_to_le64(GPT_HEADER_SIGNATURE);
641 	gptHead->revision = cpu_to_le32(GPT_HEADER_REVISION_V1);
642 	gptHead->header_size = cpu_to_le32(sizeof(gpt_header));
643 	gptHead->my_lba = cpu_to_le64(1);
644 	gptHead->alternate_lba = cpu_to_le64(diskSectors - 1);
645 	gptHead->first_usable_lba = cpu_to_le64(34);
646 	gptHead->last_usable_lba = cpu_to_le64(diskSectors - 34);
647 	gptHead->partition_entry_lba = cpu_to_le64(2);
648 	gptHead->num_partition_entries = cpu_to_le32(GPT_ENTRY_NUMBERS);
649 	gptHead->sizeof_partition_entry = cpu_to_le32(GPT_ENTRY_SIZE);
650 	gptHead->header_crc32 = 0;
651 	gptHead->partition_entry_array_crc32 = 0;
652 	gen_rand_uuid(gptHead->disk_guid.raw);
653 
654 	/*3.gpt partition entry*/
655 	memset(gpt + 2 * SECTOR_SIZE, 0, 32 * SECTOR_SIZE);
656 	for (i = 0; i < vecParts.size(); i++) {
657 		gen_rand_uuid(gptEntry->partition_type_guid.raw);
658 		gen_rand_uuid(gptEntry->unique_partition_guid.raw);
659 		gptEntry->starting_lba = cpu_to_le64(vecParts[i].uiItemOffset);
660 		gptEntry->ending_lba = cpu_to_le64(gptEntry->starting_lba + vecParts[i].uiItemSize - 1);
661 		gptEntry->attributes.raw = 0;
662 		strPartName = vecParts[i].szItemName;
663 		colonPos = strPartName.find_first_of(':');
664 		if (colonPos != string::npos) {
665 			if (strPartName.find("bootable") != string::npos)
666 				gptEntry->attributes.raw = PART_PROPERTY_BOOTABLE;
667 			if (strPartName.find("grow") != string::npos)
668 				gptEntry->ending_lba = cpu_to_le64(diskSectors - 34);
669 			strPartName = strPartName.substr(0, colonPos);
670 			vecParts[i].szItemName[strPartName.size()] = 0;
671 		}
672 		for (j = 0; j < strlen(vecParts[i].szItemName); j++)
673 			gptEntry->partition_name[j] = vecParts[i].szItemName[j];
674 		if ((pos = find_config_item(vecUuid, vecParts[i].szItemName)) != -1)
675 			memcpy(gptEntry->unique_partition_guid.raw, vecUuid[pos].szItemValue, 16);
676 		gptEntry++;
677 	}
678 
679 	gptHead->partition_entry_array_crc32 = cpu_to_le32(crc32_le(0, gpt + 2 * SECTOR_SIZE, GPT_ENTRY_SIZE * GPT_ENTRY_NUMBERS));
680 	gptHead->header_crc32 = cpu_to_le32(crc32_le(0, gpt + SECTOR_SIZE, sizeof(gpt_header)));
681 
682 }
683 bool MakeSector0(PBYTE pSector, USHORT usFlashDataSec, USHORT usFlashBootSec, bool rc4Flag)
684 {
685 	PRK28_IDB_SEC0 pSec0;
686 	memset(pSector, 0, SECTOR_SIZE);
687 	pSec0 = (PRK28_IDB_SEC0)pSector;
688 
689 	pSec0->dwTag = 0x0FF0AA55;
690 	pSec0->uiRc4Flag = rc4Flag;
691 	pSec0->usBootCode1Offset = 0x4;
692 	pSec0->usBootCode2Offset = 0x4;
693 	pSec0->usBootDataSize = usFlashDataSec;
694 	pSec0->usBootCodeSize = usFlashDataSec + usFlashBootSec;
695 	return true;
696 }
697 
698 
699 bool MakeSector1(PBYTE pSector)
700 {
701 	PRK28_IDB_SEC1 pSec1;
702 	memset(pSector, 0, SECTOR_SIZE);
703 	pSec1 = (PRK28_IDB_SEC1)pSector;
704 
705 	pSec1->usSysReservedBlock = 0xC;
706 	pSec1->usDisk0Size = 0xFFFF;
707 	pSec1->uiChipTag = 0x38324B52;
708 	return true;
709 }
710 
711 bool MakeSector2(PBYTE pSector)
712 {
713 	PRK28_IDB_SEC2 pSec2;
714 	memset(pSector, 0, SECTOR_SIZE);
715 	pSec2 = (PRK28_IDB_SEC2)pSector;
716 
717 	strcpy(pSec2->szVcTag, "VC");
718 	strcpy(pSec2->szCrcTag, "CRC");
719 	return true;
720 }
721 
722 bool MakeSector3(PBYTE pSector)
723 {
724 	memset(pSector,0,SECTOR_SIZE);
725 	return true;
726 }
727 
728 int MakeIDBlockData(PBYTE pDDR, PBYTE pLoader, PBYTE lpIDBlock, USHORT usFlashDataSec, USHORT usFlashBootSec, DWORD dwLoaderDataSize, DWORD dwLoaderSize, bool rc4Flag)
729 {
730 	RK28_IDB_SEC0 sector0Info;
731 	RK28_IDB_SEC1 sector1Info;
732 	RK28_IDB_SEC2 sector2Info;
733 	RK28_IDB_SEC3 sector3Info;
734 	UINT i;
735 	MakeSector0((PBYTE)&sector0Info, usFlashDataSec, usFlashBootSec, rc4Flag);
736 	MakeSector1((PBYTE)&sector1Info);
737 	if (!MakeSector2((PBYTE)&sector2Info)) {
738 		return -6;
739 	}
740 	if (!MakeSector3((PBYTE)&sector3Info)) {
741 		return -7;
742 	}
743 	sector2Info.usSec0Crc = CRC_16((PBYTE)&sector0Info, SECTOR_SIZE);
744 	sector2Info.usSec1Crc = CRC_16((PBYTE)&sector1Info, SECTOR_SIZE);
745 	sector2Info.usSec3Crc = CRC_16((PBYTE)&sector3Info, SECTOR_SIZE);
746 
747 	memcpy(lpIDBlock, &sector0Info, SECTOR_SIZE);
748 	memcpy(lpIDBlock + SECTOR_SIZE, &sector1Info, SECTOR_SIZE);
749 	memcpy(lpIDBlock + SECTOR_SIZE * 3, &sector3Info, SECTOR_SIZE);
750 
751 	if (rc4Flag) {
752 		for (i = 0; i < dwLoaderDataSize/SECTOR_SIZE; i++)
753 			P_RC4(pDDR + i * SECTOR_SIZE, SECTOR_SIZE);
754 		for (i = 0; i < dwLoaderSize/SECTOR_SIZE; i++)
755 			P_RC4(pLoader + i * SECTOR_SIZE, SECTOR_SIZE);
756 	}
757 
758 	memcpy(lpIDBlock + SECTOR_SIZE * 4, pDDR, dwLoaderDataSize);
759 	memcpy(lpIDBlock + SECTOR_SIZE * (4 + usFlashDataSec), pLoader, dwLoaderSize);
760 
761 	sector2Info.uiBootCodeCrc = CRC_32((PBYTE)(lpIDBlock + SECTOR_SIZE * 4), sector0Info.usBootCodeSize * SECTOR_SIZE);
762 	memcpy(lpIDBlock + SECTOR_SIZE * 2, &sector2Info, SECTOR_SIZE);
763 	for(i = 0; i < 4; i++) {
764 		if(i == 1) {
765 			continue;
766 		} else {
767 			P_RC4(lpIDBlock + SECTOR_SIZE * i, SECTOR_SIZE);
768 		}
769 	}
770 	return 0;
771 }
772 
773 
774 
775 bool check_device_type(STRUCT_RKDEVICE_DESC &dev, UINT uiSupportType)
776 {
777 	if ((dev.emUsbType & uiSupportType) == dev.emUsbType)
778 		return true;
779 	else
780 	{
781 		ERROR_COLOR_ATTR;
782 		printf("The device does not support this operation!");
783 		NORMAL_COLOR_ATTR;
784 		printf("\r\n");
785 		return false;
786 	}
787 }
788 bool write_gpt(STRUCT_RKDEVICE_DESC &dev, char *szParameter)
789 {
790 	u8 flash_info[SECTOR_SIZE], master_gpt[34 * SECTOR_SIZE], backup_gpt[33 * SECTOR_SIZE];
791 	u32 total_size_sector;
792 	CRKComm *pComm = NULL;
793 	PARAM_ITEM_VECTOR vecItems;
794 	CONFIG_ITEM_VECTOR vecUuid;
795 	int iRet;
796 	bool bRet, bSuccess = false;
797 	if (!check_device_type(dev, RKUSB_MASKROM))
798 		return false;
799 
800 	pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
801 	if (!bRet) {
802 		ERROR_COLOR_ATTR;
803 		printf("Creating Comm Object failed!");
804 		NORMAL_COLOR_ATTR;
805 		printf("\r\n");
806 		return bSuccess;
807 	}
808 	printf("Writing gpt...\r\n");
809 	//1.get flash info
810 	iRet = pComm->RKU_ReadFlashInfo(flash_info);
811 	if (iRet != ERR_SUCCESS) {
812 		ERROR_COLOR_ATTR;
813 		printf("Reading Flash Info failed!");
814 		NORMAL_COLOR_ATTR;
815 		printf("\r\n");
816 		return bSuccess;
817 	}
818 	total_size_sector = *(u32 *)flash_info;
819 	if (strstr(szParameter, ".img")) {
820 		if (!load_gpt_buffer(szParameter, master_gpt, backup_gpt)) {
821 			ERROR_COLOR_ATTR;
822 			printf("Loading partition image failed!");
823 			NORMAL_COLOR_ATTR;
824 			printf("\r\n");
825 			return bSuccess;
826 		}
827 		update_gpt_disksize(master_gpt, backup_gpt, total_size_sector);
828 	} else {
829 		//2.get partition from parameter
830 		bRet = parse_parameter_file(szParameter, vecItems, vecUuid);
831 		if (!bRet) {
832 			ERROR_COLOR_ATTR;
833 			printf("Parsing parameter failed!");
834 			NORMAL_COLOR_ATTR;
835 			printf("\r\n");
836 			return bSuccess;
837 		}
838 		vecItems[vecItems.size()-1].uiItemSize = total_size_sector - 33;
839 		//3.generate gpt info
840 		create_gpt_buffer(master_gpt, vecItems, vecUuid, total_size_sector);
841 		memcpy(backup_gpt, master_gpt + 2* SECTOR_SIZE, 32 * SECTOR_SIZE);
842 		memcpy(backup_gpt + 32 * SECTOR_SIZE, master_gpt + SECTOR_SIZE, SECTOR_SIZE);
843 		prepare_gpt_backup(master_gpt, backup_gpt);
844 	}
845 
846 	//4. write gpt
847 	iRet = pComm->RKU_WriteLBA(0, 34, master_gpt);
848 	if (iRet != ERR_SUCCESS) {
849 		ERROR_COLOR_ATTR;
850 		printf("Writing master gpt failed!");
851 		NORMAL_COLOR_ATTR;
852 		printf("\r\n");
853 		return bSuccess;
854 	}
855 	iRet = pComm->RKU_WriteLBA(total_size_sector - 33, 33, backup_gpt);
856 	if (iRet != ERR_SUCCESS) {
857 		ERROR_COLOR_ATTR;
858 		printf("Writing backup gpt failed!");
859 		NORMAL_COLOR_ATTR;
860 		printf("\r\n");
861 		return bSuccess;
862 	}
863 
864 	bSuccess = true;
865 	CURSOR_MOVEUP_LINE(1);
866 	CURSOR_DEL_LINE;
867 	printf("Writing gpt succeeded.\r\n");
868 	return bSuccess;
869 }
870 
871 #include "boot_merger.h"
872 #define ENTRY_ALIGN  (2048)
873 options gOpts;
874 
875 
876 char gSubfix[MAX_LINE_LEN] = OUT_SUBFIX;
877 char* gConfigPath;
878 uint8_t gBuf[MAX_MERGE_SIZE];
879 
880 static inline void fixPath(char* path) {
881 	int i, len = strlen(path);
882 	for(i=0; i<len; i++) {
883 		if (path[i] == '\\')
884 			path[i] = '/';
885 		else if (path[i] == '\r' || path[i] == '\n')
886 			path[i] = '\0';
887 	}
888 }
889 
890 static bool parseChip(FILE* file) {
891 	if (SCANF_EAT(file) != 0) {
892 		return false;
893 	}
894 	if (fscanf(file, OPT_NAME "=%s", gOpts.chip) != 1) {
895 		return false;
896 	}
897 	printf("chip: %s\n", gOpts.chip);
898 	return true;
899 }
900 
901 static bool parseVersion(FILE* file) {
902 	if (SCANF_EAT(file) != 0) {
903 		return false;
904 	}
905 	if (fscanf(file, OPT_MAJOR "=%d", &gOpts.major) != 1)
906 		return false;
907 	if (SCANF_EAT(file) != 0) {
908 		return false;
909 	}
910 	if (fscanf(file, OPT_MINOR "=%d", &gOpts.minor) != 1)
911 		return false;
912 	printf("major: %d, minor: %d\n", gOpts.major, gOpts.minor);
913 	return true;
914 }
915 
916 static bool parse471(FILE* file) {
917 	int i, index, pos;
918 	char buf[MAX_LINE_LEN];
919 
920 	if (SCANF_EAT(file) != 0) {
921 		return false;
922 	}
923 	if (fscanf(file, OPT_NUM "=%d", &gOpts.code471Num) != 1)
924 		return false;
925 	printf("num: %d\n", gOpts.code471Num);
926 	if (!gOpts.code471Num)
927 		return true;
928 	if (gOpts.code471Num < 0)
929 		return false;
930 	gOpts.code471Path = (line_t*) malloc(sizeof(line_t) * gOpts.code471Num);
931 	for (i=0; i<gOpts.code471Num; i++) {
932 		if (SCANF_EAT(file) != 0) {
933 			return false;
934 		}
935 		if (fscanf(file, OPT_PATH "%d=%[^\r^\n]", &index, buf)
936 				!= 2)
937 			return false;
938 		index--;
939 		fixPath(buf);
940 		strcpy((char*)gOpts.code471Path[index], buf);
941 		printf("path%i: %s\n", index, gOpts.code471Path[index]);
942 	}
943 	pos = ftell(file);
944 	if (SCANF_EAT(file) != 0) {
945 		return false;
946 	}
947 	if (fscanf(file, OPT_SLEEP "=%d", &gOpts.code471Sleep) != 1)
948 		fseek(file, pos, SEEK_SET);
949 	printf("sleep: %d\n", gOpts.code471Sleep);
950 	return true;
951 }
952 
953 static bool parse472(FILE* file) {
954 	int i, index, pos;
955 	char buf[MAX_LINE_LEN];
956 
957 	if (SCANF_EAT(file) != 0) {
958 		return false;
959 	}
960 	if (fscanf(file, OPT_NUM "=%d", &gOpts.code472Num) != 1)
961 		return false;
962 	printf("num: %d\n", gOpts.code472Num);
963 	if (!gOpts.code472Num)
964 		return true;
965 	if (gOpts.code472Num < 0)
966 		return false;
967 	gOpts.code472Path = (line_t*) malloc(sizeof(line_t) * gOpts.code472Num);
968 	for (i=0; i<gOpts.code472Num; i++) {
969 		if (SCANF_EAT(file) != 0) {
970 			return false;
971 		}
972 		if (fscanf(file, OPT_PATH "%d=%[^\r^\n]", &index, buf)
973 				!= 2)
974 			return false;
975 		fixPath(buf);
976 		index--;
977 		strcpy((char*)gOpts.code472Path[index], buf);
978 		printf("path%i: %s\n", index, gOpts.code472Path[index]);
979 	}
980 	pos = ftell(file);
981 	if (SCANF_EAT(file) != 0) {
982 		return false;
983 	}
984 	if (fscanf(file, OPT_SLEEP "=%d", &gOpts.code472Sleep) != 1)
985 		fseek(file, pos, SEEK_SET);
986 	printf("sleep: %d\n", gOpts.code472Sleep);
987 	return true;
988 }
989 
990 static bool parseLoader(FILE* file) {
991 	int i, j, index, pos;
992 	char buf[MAX_LINE_LEN];
993 	char buf2[MAX_LINE_LEN];
994 
995 	if (SCANF_EAT(file) != 0) {
996 		return false;
997 	}
998 	pos = ftell(file);
999 	if (fscanf(file, OPT_NUM "=%d", &gOpts.loaderNum) != 1) {
1000 		fseek(file, pos, SEEK_SET);
1001 		if(fscanf(file, OPT_LOADER_NUM "=%d", &gOpts.loaderNum) != 1) {
1002 			return false;
1003 		}
1004 	}
1005 	printf("num: %d\n", gOpts.loaderNum);
1006 	if (!gOpts.loaderNum)
1007 		return false;
1008 	if (gOpts.loaderNum < 0)
1009 		return false;
1010 	gOpts.loader = (name_entry*) malloc(sizeof(name_entry) * gOpts.loaderNum);
1011 	for (i=0; i<gOpts.loaderNum; i++) {
1012 		if (SCANF_EAT(file) != 0) {
1013 			return false;
1014 		}
1015 		if (fscanf(file, OPT_LOADER_NAME "%d=%s", &index, buf)
1016 				!= 2)
1017 			return false;
1018 		index--;
1019 		strcpy(gOpts.loader[index].name, buf);
1020 		printf("name%d: %s\n", index, gOpts.loader[index].name);
1021 	}
1022 	for (i=0; i<gOpts.loaderNum; i++) {
1023 		if (SCANF_EAT(file) != 0) {
1024 			return false;
1025 		}
1026 		if (fscanf(file, "%[^=]=%[^\r^\n]", buf, buf2)
1027 				!= 2)
1028 			return false;
1029 		for (j=0; j<gOpts.loaderNum; j++) {
1030 			if (!strcmp(gOpts.loader[j].name, buf)) {
1031 				fixPath(buf2);
1032 				strcpy(gOpts.loader[j].path, buf2);
1033 				printf("%s=%s\n", gOpts.loader[j].name, gOpts.loader[j].path);
1034 				break;
1035 			}
1036 		}
1037 		if (j >= gOpts.loaderNum) {
1038 			return false;
1039 		}
1040 	}
1041 	return true;
1042 }
1043 
1044 static bool parseOut(FILE* file) {
1045 	if (SCANF_EAT(file) != 0) {
1046 		return false;
1047 	}
1048 	if (fscanf(file, OPT_OUT_PATH "=%[^\r^\n]", gOpts.outPath) != 1)
1049 		return false;
1050 	fixPath(gOpts.outPath);
1051 	printf("out: %s\n", gOpts.outPath);
1052 	return true;
1053 }
1054 
1055 
1056 void printOpts(FILE* out) {
1057 	int i;
1058 	fprintf(out, SEC_CHIP "\n" OPT_NAME "=%s\n", gOpts.chip);
1059 	fprintf(out, SEC_VERSION "\n" OPT_MAJOR "=%d\n" OPT_MINOR
1060 			"=%d\n", gOpts.major, gOpts.minor);
1061 
1062 	fprintf(out, SEC_471 "\n" OPT_NUM "=%d\n", gOpts.code471Num);
1063 	for (i=0 ;i<gOpts.code471Num ;i++) {
1064 		fprintf(out, OPT_PATH "%d=%s\n", i+1, gOpts.code471Path[i]);
1065 	}
1066 	if (gOpts.code471Sleep > 0)
1067 		fprintf(out, OPT_SLEEP "=%d\n", gOpts.code471Sleep);
1068 
1069 	fprintf(out, SEC_472 "\n" OPT_NUM "=%d\n", gOpts.code472Num);
1070 	for (i=0 ;i<gOpts.code472Num ;i++) {
1071 		fprintf(out, OPT_PATH "%d=%s\n", i+1, gOpts.code472Path[i]);
1072 	}
1073 	if (gOpts.code472Sleep > 0)
1074 		fprintf(out, OPT_SLEEP "=%d\n", gOpts.code472Sleep);
1075 
1076 	fprintf(out, SEC_LOADER "\n" OPT_NUM "=%d\n", gOpts.loaderNum);
1077 	for (i=0 ;i<gOpts.loaderNum ;i++) {
1078 		fprintf(out, OPT_LOADER_NAME "%d=%s\n", i+1, gOpts.loader[i].name);
1079 	}
1080 	for (i=0 ;i<gOpts.loaderNum ;i++) {
1081 		fprintf(out, "%s=%s\n", gOpts.loader[i].name, gOpts.loader[i].path);
1082 	}
1083 
1084 	fprintf(out, SEC_OUT "\n" OPT_OUT_PATH "=%s\n", gOpts.outPath);
1085 }
1086 
1087 static bool parseOpts(void) {
1088 	bool ret = false;
1089 	bool chipOk = false;
1090 	bool versionOk = false;
1091 	bool code471Ok = true;
1092 	bool code472Ok = true;
1093 	bool loaderOk = false;
1094 	bool outOk = false;
1095 	char buf[MAX_LINE_LEN];
1096 
1097 	char* configPath = (gConfigPath == (char*)NULL)? (char*)DEF_CONFIG_FILE: gConfigPath;
1098 	FILE* file;
1099 	file = fopen(configPath, "r");
1100 	if (!file) {
1101 		fprintf(stderr, "config (%s) not found!\n", configPath);
1102 		if (configPath == (char*)DEF_CONFIG_FILE) {
1103 			file = fopen(DEF_CONFIG_FILE, "w");
1104 			if (file) {
1105 				fprintf(stderr, "creating defconfig\n");
1106 				printOpts(file);
1107 			}
1108 		}
1109 		goto end;
1110 	}
1111 
1112 	printf("Starting to parse...\n");
1113 
1114 	if (SCANF_EAT(file) != 0) {
1115 		goto end;
1116 	}
1117 	while(fscanf(file, "%s", buf) == 1) {
1118 		if (!strcmp(buf, SEC_CHIP)) {
1119 			chipOk = parseChip(file);
1120 			if (!chipOk) {
1121 				printf("parseChip failed!\n");
1122 				goto end;
1123 			}
1124 		} else if (!strcmp(buf, SEC_VERSION)) {
1125 			versionOk = parseVersion(file);
1126 			if (!versionOk) {
1127 				printf("parseVersion failed!\n");
1128 				goto end;
1129 			}
1130 		} else if (!strcmp(buf, SEC_471)) {
1131 			code471Ok = parse471(file);
1132 			if (!code471Ok) {
1133 				printf("parse471 failed!\n");
1134 				goto end;
1135 			}
1136 		} else if (!strcmp(buf, SEC_472)) {
1137 			code472Ok = parse472(file);
1138 			if (!code472Ok) {
1139 				printf("parse472 failed!\n");
1140 				goto end;
1141 			}
1142 		} else if (!strcmp(buf, SEC_LOADER)) {
1143 			loaderOk = parseLoader(file);
1144 			if (!loaderOk) {
1145 				printf("parseLoader failed!\n");
1146 				goto end;
1147 			}
1148 		} else if (!strcmp(buf, SEC_OUT)) {
1149 			outOk = parseOut(file);
1150 			if (!outOk) {
1151 				printf("parseOut failed!\n");
1152 				goto end;
1153 			}
1154 		} else if (buf[0] == '#') {
1155 			continue;
1156 		} else {
1157 			printf("unknown sec: %s!\n", buf);
1158 			goto end;
1159 		}
1160 		if (SCANF_EAT(file) != 0) {
1161 			goto end;
1162 		}
1163 	}
1164 
1165 	if (chipOk && versionOk && code471Ok && code472Ok
1166 			&& loaderOk && outOk)
1167 		ret = true;
1168 end:
1169 	if (file)
1170 		fclose(file);
1171 	return ret;
1172 }
1173 
1174 bool initOpts(void) {
1175 	//set default opts
1176 	gOpts.major = DEF_MAJOR;
1177 	gOpts.minor = DEF_MINOR;
1178 	strcpy(gOpts.chip, DEF_CHIP);
1179 	gOpts.code471Sleep = DEF_CODE471_SLEEP;
1180 	gOpts.code472Sleep = DEF_CODE472_SLEEP;
1181 	gOpts.code471Num = DEF_CODE471_NUM;
1182 	gOpts.code471Path = (line_t*) malloc(sizeof(line_t) * gOpts.code471Num);
1183 	strcpy((char*)gOpts.code471Path[0], DEF_CODE471_PATH);
1184 	gOpts.code472Num = DEF_CODE472_NUM;
1185 	gOpts.code472Path = (line_t*) malloc(sizeof(line_t) * gOpts.code472Num);
1186 	strcpy((char*)gOpts.code472Path[0], DEF_CODE472_PATH);
1187 	gOpts.loaderNum = DEF_LOADER_NUM;
1188 	gOpts.loader = (name_entry*) malloc(sizeof(name_entry) * gOpts.loaderNum);
1189 	strcpy(gOpts.loader[0].name, DEF_LOADER0);
1190 	strcpy(gOpts.loader[0].path, DEF_LOADER0_PATH);
1191 	strcpy(gOpts.loader[1].name, DEF_LOADER1);
1192 	strcpy(gOpts.loader[1].path, DEF_LOADER1_PATH);
1193 	strcpy(gOpts.outPath, DEF_OUT_PATH);
1194 
1195 	return parseOpts();
1196 }
1197 
1198 /************merge code****************/
1199 
1200 static inline uint32_t getBCD(unsigned short value) {
1201 	uint8_t tmp[2] = {0};
1202 	int i;
1203 	uint32_t ret;
1204 	//if (value > 0xFFFF) {
1205 	//	return 0;
1206 	//}
1207 	for(i=0; i < 2; i++) {
1208 		tmp[i] = (((value/10)%10)<<4) | (value%10);
1209 		value /= 100;
1210 	}
1211 	ret = ((uint16_t)(tmp[1] << 8)) | tmp[0];
1212 
1213 	printf("ret: %x\n",ret);
1214 	return ret&0xFF;
1215 }
1216 
1217 static inline void str2wide(const char* str, uint16_t* wide, int len)
1218 {
1219 	int i;
1220 	for (i = 0; i < len; i++) {
1221 		wide[i] = (uint16_t) str[i];
1222 	}
1223 	wide[len] = 0;
1224 }
1225 
1226 static inline void getName(char* path, uint16_t* dst) {
1227 	char* end;
1228 	char* start;
1229 	int len;
1230 	if (!path || !dst)
1231 		return;
1232 	start = strrchr(path, '/');
1233 	if (!start)
1234 		start = path;
1235 	else
1236 		start++;
1237 	end = strrchr(path, '.');
1238 	if (!end || (end < start))
1239 		end = path + strlen(path);
1240 	len = end - start;
1241 	if (len >= MAX_NAME_LEN)
1242 		len = MAX_NAME_LEN -1;
1243 	str2wide(start, dst, len);
1244 
1245 
1246 		char name[MAX_NAME_LEN];
1247 		memset(name, 0, sizeof(name));
1248 		memcpy(name, start, len);
1249 		printf("path: %s, name: %s\n", path, name);
1250 
1251 }
1252 
1253 static inline bool getFileSize(const char *path, uint32_t* size) {
1254 	struct stat st;
1255 	if(stat(path, &st) < 0)
1256 		return false;
1257 	*size = st.st_size;
1258 	printf("path: %s, size: %d\n", path, *size);
1259 	return true;
1260 }
1261 
1262 static inline rk_time getTime(void) {
1263 	rk_time rkTime;
1264 
1265 	struct tm *tm;
1266 	time_t tt = time(NULL);
1267 	tm = localtime(&tt);
1268 	rkTime.year = tm->tm_year + 1900;
1269 	rkTime.month = tm->tm_mon + 1;
1270 	rkTime.day = tm->tm_mday;
1271 	rkTime.hour = tm->tm_hour;
1272 	rkTime.minute = tm->tm_min;
1273 	rkTime.second = tm->tm_sec;
1274 	printf("%d-%d-%d %02d:%02d:%02d\n",
1275 			rkTime.year, rkTime.month, rkTime.day,
1276 			rkTime.hour, rkTime.minute, rkTime.second);
1277 	return rkTime;
1278 }
1279 
1280 static bool writeFile(FILE* outFile, const char* path, bool fix) {
1281 	bool ret = false;
1282 	uint32_t size = 0, fixSize = 0;
1283 	uint8_t* buf;
1284 
1285 	FILE* inFile = fopen(path, "rb");
1286 	if (!inFile)
1287 		goto end;
1288 
1289 	if (!getFileSize(path, &size))
1290 		goto end;
1291 	if (fix) {
1292 		fixSize = ((size - 1) / SMALL_PACKET + 1) * SMALL_PACKET;
1293 		uint32_t tmp = fixSize % ENTRY_ALIGN;
1294 		tmp = tmp ? (ENTRY_ALIGN - tmp): 0;
1295 		fixSize +=tmp;
1296 		memset(gBuf, 0, fixSize);
1297 	} else {
1298 		memset(gBuf, 0, size+ENTRY_ALIGN);
1299 	}
1300 	if (!fread(gBuf, size, 1, inFile))
1301 		goto end;
1302 
1303 	if (fix) {
1304 
1305 		buf = gBuf;
1306 		size = fixSize;
1307 		while(1) {
1308 			P_RC4(buf, fixSize < SMALL_PACKET ? fixSize : SMALL_PACKET);
1309 			buf += SMALL_PACKET;
1310 			if (fixSize <= SMALL_PACKET)
1311 				break;
1312 			fixSize -= SMALL_PACKET;
1313 		}
1314 	} else {
1315 		uint32_t tmp = size % ENTRY_ALIGN;
1316 		tmp = tmp ? (ENTRY_ALIGN - tmp): 0;
1317 		size +=tmp;
1318 		P_RC4(gBuf, size);
1319 	}
1320 
1321 	if (!fwrite(gBuf, size, 1, outFile))
1322 		goto end;
1323 	ret = true;
1324 end:
1325 	if (inFile)
1326 		fclose(inFile);
1327 	if (!ret)
1328 		printf("writing entry (%s) failed\n", path);
1329 	return ret;
1330 }
1331 
1332 static bool saveEntry(FILE* outFile, char* path, rk_entry_type type,
1333 		uint16_t delay, uint32_t* offset, char* fixName, bool fix) {
1334 	uint32_t size;
1335 	rk_boot_entry entry;
1336 
1337 	printf("writing: %s\n", path);
1338 	memset(&entry, 0, sizeof(rk_boot_entry));
1339 	getName(fixName ? fixName: path, entry.name);
1340 	entry.size = sizeof(rk_boot_entry);
1341 	entry.type = type;
1342 	entry.dataOffset = *offset;
1343 	if (!getFileSize(path, &size)) {
1344 		printf("Saving entry (%s) failed:\n\tCannot get file size.\n", path);
1345 		return false;
1346 	}
1347 	if (fix)
1348 		size = ((size - 1) / SMALL_PACKET + 1) * SMALL_PACKET;
1349 	uint32_t tmp = size % ENTRY_ALIGN;
1350 	size += tmp ? (ENTRY_ALIGN - tmp): 0;
1351 	printf("alignment size: %d\n", size);
1352 	entry.dataSize = size;
1353 	entry.dataDelay = delay;
1354 	*offset += size;
1355 	fwrite(&entry, sizeof(rk_boot_entry), 1, outFile);
1356 	return true;
1357 }
1358 
1359 static inline uint32_t convertChipType(const char* chip) {
1360 	char buffer[5];
1361 	memset(buffer, 0, sizeof(buffer));
1362 	snprintf(buffer, sizeof(buffer), "%s", chip);
1363 	return buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
1364 }
1365 
1366 static inline uint32_t getChipType(const char* chip) {
1367 	printf("chip: %s\n", chip);
1368 	int chipType = RKNONE_DEVICE;
1369 	if(!chip) {
1370 		goto end;
1371 	}
1372 	if (!strcmp(chip, CHIP_RK28)) {
1373 		chipType = RK28_DEVICE;
1374 	} else if (!strcmp(chip, CHIP_RK28)) {
1375 		chipType = RK28_DEVICE;
1376 	} else if (!strcmp(chip, CHIP_RK281X)) {
1377 		chipType = RK281X_DEVICE;
1378 	} else if (!strcmp(chip, CHIP_RKPANDA)) {
1379 		chipType = RKPANDA_DEVICE;
1380 	} else if (!strcmp(chip, CHIP_RK27)) {
1381 		chipType = RK27_DEVICE;
1382 	} else if (!strcmp(chip, CHIP_RKNANO)) {
1383 		chipType = RKNANO_DEVICE;
1384 	} else if (!strcmp(chip, CHIP_RKSMART)) {
1385 		chipType = RKSMART_DEVICE;
1386 	} else if (!strcmp(chip, CHIP_RKCROWN)) {
1387 		chipType = RKCROWN_DEVICE;
1388 	} else if (!strcmp(chip, CHIP_RKCAYMAN)) {
1389 		chipType = RKCAYMAN_DEVICE;
1390 	} else if (!strcmp(chip, CHIP_RK29)) {
1391 		chipType = RK29_DEVICE;
1392 	} else if (!strcmp(chip, CHIP_RK292X)) {
1393 		chipType = RK292X_DEVICE;
1394 	} else if (!strcmp(chip, CHIP_RK30)) {
1395 		chipType = RK30_DEVICE;
1396 	} else if (!strcmp(chip, CHIP_RK30B)) {
1397 		chipType = RK30B_DEVICE;
1398 	} else if (!strcmp(chip, CHIP_RK31)) {
1399 		chipType = RK31_DEVICE;
1400 	} else if (!strcmp(chip, CHIP_RK32)) {
1401 		chipType = RK32_DEVICE;
1402 	} else {
1403 		chipType = convertChipType(chip + 2);
1404 	}
1405 
1406 end:
1407 	printf("type: 0x%x\n", chipType);
1408 	if (chipType == RKNONE_DEVICE) {
1409 		printf("chip type not supported!\n");
1410 	}
1411 	return chipType;
1412 }
1413 
1414 static inline void getBoothdr(rk_boot_header* hdr) {
1415 	memset(hdr, 0, sizeof(rk_boot_header));
1416 	hdr->tag = TAG;
1417 	hdr->size = sizeof(rk_boot_header);
1418 	hdr->version = (getBCD(gOpts.major) << 8) | getBCD(gOpts.minor);
1419 	hdr->mergerVersion = MERGER_VERSION;
1420 	hdr->releaseTime = getTime();
1421 	hdr->chipType = getChipType(gOpts.chip);
1422 
1423 	hdr->code471Num = gOpts.code471Num;
1424 	hdr->code471Offset = sizeof(rk_boot_header);
1425 	hdr->code471Size = sizeof(rk_boot_entry);
1426 
1427 	hdr->code472Num = gOpts.code472Num;
1428 	hdr->code472Offset = hdr->code471Offset + gOpts.code471Num * hdr->code471Size;
1429 	hdr->code472Size = sizeof(rk_boot_entry);
1430 
1431 	hdr->loaderNum = gOpts.loaderNum;
1432 	hdr->loaderOffset = hdr->code472Offset + gOpts.code472Num * hdr->code472Size;
1433 	hdr->loaderSize = sizeof(rk_boot_entry);
1434 #ifndef USE_P_RC4
1435 	hdr->rc4Flag = 1;
1436 #endif
1437 }
1438 
1439 static inline uint32_t getCrc(const char* path) {
1440 	uint32_t size = 0;
1441 	uint32_t crc = 0;
1442 
1443 	FILE* file = fopen(path, "rb");
1444 	getFileSize(path, &size);
1445 	if (!file)
1446 		goto end;
1447 	if (!fread(gBuf, size, 1, file))
1448 		goto end;
1449 	crc = CRC_32(gBuf, size);
1450 	printf("crc: 0x%08x\n", crc);
1451 end:
1452 	if (file)
1453 		fclose(file);
1454 	return crc;
1455 }
1456 
1457 bool mergeBoot(void) {
1458 	uint32_t dataOffset;
1459 	bool ret = false;
1460 	int i;
1461 	FILE* outFile;
1462 	uint32_t crc;
1463 	rk_boot_header hdr;
1464 
1465 	if (!initOpts())
1466 		return false;
1467 	{
1468 		char* subfix = strstr(gOpts.outPath, OUT_SUBFIX);
1469 		char version[MAX_LINE_LEN];
1470 		snprintf(version, sizeof(version), "%s", gSubfix);
1471 		if (subfix && !strcmp(subfix, OUT_SUBFIX)) {
1472 			subfix[0] = '\0';
1473 		}
1474 		strcat(gOpts.outPath, version);
1475 		printf("fix opt: %s\n", gOpts.outPath);
1476 	}
1477 
1478 	printf("---------------\nUSING CONFIG:\n");
1479 	printOpts(stdout);
1480 	printf("---------------\n\n");
1481 
1482 
1483 	outFile = fopen(gOpts.outPath, "wb+");
1484 	if (!outFile) {
1485 		printf("Opening output file (%s) failed\n", gOpts.outPath);
1486 		goto end;
1487 	}
1488 
1489 	getBoothdr(&hdr);
1490 	printf("Writing header...\n");
1491 	fwrite(&hdr, 1, sizeof(rk_boot_header), outFile);
1492 
1493 	dataOffset = sizeof(rk_boot_header) +
1494 		(gOpts.code471Num + gOpts.code472Num + gOpts.loaderNum) *
1495 		sizeof(rk_boot_entry);
1496 
1497 	printf("Writing code 471 entry...\n");
1498 	for (i=0; i<gOpts.code471Num; i++) {
1499 		if (!saveEntry(outFile, (char*)gOpts.code471Path[i], ENTRY_471, gOpts.code471Sleep,
1500 					&dataOffset, NULL, false))
1501 			goto end;
1502 	}
1503 	printf("Writing code 472 entry...\n");
1504 	for (i=0; i<gOpts.code472Num; i++) {
1505 		if (!saveEntry(outFile, (char*)gOpts.code472Path[i], ENTRY_472, gOpts.code472Sleep,
1506 					&dataOffset, NULL, false))
1507 			goto end;
1508 	}
1509 	printf("Writing loader entry...\n");
1510 	for (i=0; i<gOpts.loaderNum; i++) {
1511 		if (!saveEntry(outFile, gOpts.loader[i].path, ENTRY_LOADER, 0,
1512 					&dataOffset, gOpts.loader[i].name, true))
1513 			goto end;
1514 	}
1515 
1516 	printf("Writing code 471...\n");
1517 	for (i=0; i<gOpts.code471Num; i++) {
1518 		if (!writeFile(outFile, (char*)gOpts.code471Path[i], false))
1519 			goto end;
1520 	}
1521 	printf("Writing code 472...\n");
1522 	for (i=0; i<gOpts.code472Num; i++) {
1523 		if (!writeFile(outFile, (char*)gOpts.code472Path[i], false))
1524 			goto end;
1525 	}
1526 	printf("Writing loader...\n");
1527 	for (i=0; i<gOpts.loaderNum; i++) {
1528 		if (!writeFile(outFile, gOpts.loader[i].path, true))
1529 			goto end;
1530 	}
1531 	fflush(outFile);
1532 
1533 	printf("Writing crc...\n");
1534 	crc = getCrc(gOpts.outPath);
1535 	if (!fwrite(&crc, sizeof(crc), 1, outFile))
1536 		goto end;
1537 	printf("Done.\n");
1538 	ret = true;
1539 end:
1540 	if (outFile)
1541 		fclose(outFile);
1542 	return ret;
1543 }
1544 
1545 /************merge code end************/
1546 /************unpack code***************/
1547 
1548 static inline void wide2str(const uint16_t* wide, char* str, int len)
1549 {
1550 	int i;
1551 	for (i = 0; i < len; i++) {
1552 		str[i] = (char) (wide[i] & 0xFF);
1553 	}
1554 	str[len] = 0;
1555 }
1556 
1557 static bool unpackEntry(rk_boot_entry* entry, const char* name,
1558 		FILE* inFile) {
1559 	bool ret = false;
1560 	int size, i;
1561 	FILE* outFile = fopen(name, "wb+");
1562 	if (!outFile)
1563 		goto end;
1564 	printf("unpacking entry (%s)\n", name);
1565 	fseek(inFile, entry->dataOffset, SEEK_SET);
1566 	size = entry->dataSize;
1567 	if (!fread(gBuf, size, 1, inFile))
1568 		goto end;
1569 	if (entry->type == ENTRY_LOADER) {
1570 		for(i=0; i<size/SMALL_PACKET; i++)
1571 			P_RC4(gBuf + i * SMALL_PACKET, SMALL_PACKET);
1572 		if (size % SMALL_PACKET)
1573 		{
1574 			P_RC4(gBuf + i * SMALL_PACKET, size - SMALL_PACKET * 512);
1575 		}
1576 	} else {
1577 		P_RC4(gBuf, size);
1578 	}
1579 	if (!fwrite(gBuf, size, 1, outFile))
1580 		goto end;
1581 	ret = true;
1582 end:
1583 	if (outFile)
1584 		fclose(outFile);
1585 	return ret;
1586 }
1587 
1588 bool unpackBoot(char* path) {
1589 	bool ret = false;
1590 	FILE* inFile = fopen(path, "rb");
1591 	int entryNum, i;
1592 	char name[MAX_NAME_LEN];
1593 	rk_boot_entry* entrys;
1594 	if (!inFile) {
1595 		fprintf(stderr, "loader (%s) not found\n", path);
1596 		goto end;
1597 	}
1598 
1599 	rk_boot_header hdr;
1600 	if (!fread(&hdr, sizeof(rk_boot_header), 1, inFile)) {
1601 		fprintf(stderr, "reading header failed\n");
1602 		goto end;
1603 	}
1604 	printf("471 num:%d, 472 num:%d, loader num:%d\n", hdr.code471Num, hdr.code472Num, hdr.loaderNum);
1605 	entryNum = hdr.code471Num + hdr.code472Num + hdr.loaderNum;
1606 	entrys = (rk_boot_entry*) malloc(sizeof(rk_boot_entry) * entryNum);
1607 	if (!fread(entrys, sizeof(rk_boot_entry) * entryNum, 1, inFile)) {
1608 		fprintf(stderr, "reading data failed\n");
1609 		goto end;
1610 	}
1611 
1612 	printf("entry num: %d\n", entryNum);
1613 	for (i=0; i<entryNum; i++) {
1614 		wide2str(entrys[i].name, name, MAX_NAME_LEN);
1615 
1616 		printf("entry: t=%d, name=%s, off=%d, size=%d\n",
1617 				entrys[i].type, name, entrys[i].dataOffset,
1618 				entrys[i].dataSize);
1619 		if (!unpackEntry(entrys + i, name, inFile)) {
1620 			fprintf(stderr, "unpacking entry (%s) failed\n", name);
1621 			goto end;
1622 		}
1623 	}
1624 	printf("done\n");
1625 	ret = true;
1626 end:
1627 	if (inFile)
1628 		fclose(inFile);
1629 	return ret;
1630 }
1631 
1632 bool download_boot(STRUCT_RKDEVICE_DESC &dev, char *szLoader)
1633 {
1634 	if (!check_device_type(dev, RKUSB_MASKROM))
1635 		return false;
1636 	CRKImage *pImage = NULL;
1637 	CRKBoot *pBoot = NULL;
1638 	bool bRet, bSuccess = false;
1639 	int iRet;
1640 
1641 	pImage = new CRKImage(szLoader, bRet);
1642 	if (!bRet){
1643 		ERROR_COLOR_ATTR;
1644 		printf("Opening loader failed, exiting download boot!");
1645 		NORMAL_COLOR_ATTR;
1646 		printf("\r\n");
1647 		return bSuccess;
1648 	} else {
1649 		pBoot = (CRKBoot *)pImage->m_bootObject;
1650 		CRKComm *pComm = NULL;
1651 		CRKDevice *pDevice = NULL;
1652 
1653 		dev.emDeviceType = pBoot->SupportDevice;
1654 		pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
1655 		if (!bRet) {
1656 			if (pImage)
1657 				delete pImage;
1658 			ERROR_COLOR_ATTR;
1659 			printf("Creating Comm Object failed!");
1660 			NORMAL_COLOR_ATTR;
1661 			printf("\r\n");
1662 			return bSuccess;
1663 		}
1664 
1665 		pDevice = new CRKDevice(dev);
1666 		if (!pDevice) {
1667 			if (pImage)
1668 				delete pImage;
1669 			if (pComm)
1670 				delete pComm;
1671 			ERROR_COLOR_ATTR;
1672 			printf("Creating device object failed!");
1673 			NORMAL_COLOR_ATTR;
1674 			printf("\r\n");
1675 			return bSuccess;
1676 		}
1677 
1678 		pDevice->SetObject(pImage, pComm, g_pLogObject);
1679 		printf("Downloading bootloader...\r\n");
1680 		iRet = pDevice->DownloadBoot();
1681 
1682 		CURSOR_MOVEUP_LINE(1);
1683 		CURSOR_DEL_LINE;
1684 		if (iRet == 0) {
1685 			bSuccess = true;
1686 			printf("Downloading bootloader succeeded.\r\n");
1687 		}
1688 		else
1689 			printf("Downloading bootloader failed!\r\n");
1690 
1691 		if (pImage)
1692 			delete pImage;
1693 		if(pDevice)
1694 			delete pDevice;
1695 	}
1696 	return bSuccess;
1697 }
1698 bool upgrade_loader(STRUCT_RKDEVICE_DESC &dev, char *szLoader)
1699 {
1700 	if (!check_device_type(dev, RKUSB_MASKROM))
1701 		return false;
1702 	CRKImage *pImage = NULL;
1703 	CRKBoot *pBoot = NULL;
1704 	CRKComm *pComm = NULL;
1705 	bool bRet, bSuccess = false;
1706 	int iRet;
1707 	char index;
1708 	USHORT usFlashDataSec, usFlashBootSec;
1709 	DWORD dwLoaderSize, dwLoaderDataSize, dwDelay, dwSectorNum;
1710 	char loaderCodeName[] = "FlashBoot";
1711 	char loaderDataName[] = "FlashData";
1712 	PBYTE loaderCodeBuffer = NULL;
1713 	PBYTE loaderDataBuffer = NULL;
1714 	PBYTE pIDBData = NULL;
1715 	pImage = new CRKImage(szLoader, bRet);
1716 	if (!bRet){
1717 		ERROR_COLOR_ATTR;
1718 		printf("Opening loader failed, exiting upgrade loader!");
1719 		NORMAL_COLOR_ATTR;
1720 		printf("\r\n");
1721 		goto Exit_UpgradeLoader;
1722 	} else {
1723 		pBoot = (CRKBoot *)pImage->m_bootObject;
1724 		dev.emDeviceType = pBoot->SupportDevice;
1725 		pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
1726 		if (!bRet) {
1727 			ERROR_COLOR_ATTR;
1728 			printf("Creating Comm Object failed!");
1729 			NORMAL_COLOR_ATTR;
1730 			printf("\r\n");
1731 			goto Exit_UpgradeLoader;
1732 		}
1733 
1734 		printf("Upgrading loader...\r\n");
1735 		index = pBoot->GetIndexByName(ENTRYLOADER, loaderCodeName);
1736 		if (index == -1) {
1737 			if (g_pLogObject) {
1738 				g_pLogObject->Record("ERROR: %s --> Get LoaderCode Entry failed", __func__);
1739 			}
1740 			goto Exit_UpgradeLoader;
1741 		}
1742 		bRet = pBoot->GetEntryProperty(ENTRYLOADER, index, dwLoaderSize, dwDelay);
1743 		if (!bRet) {
1744 			if (g_pLogObject) {
1745 				g_pLogObject->Record("ERROR: %s --> Get LoaderCode Entry Size failed", __func__);
1746 			}
1747 			goto Exit_UpgradeLoader;
1748 		}
1749 
1750 		loaderCodeBuffer = new BYTE[dwLoaderSize];
1751 		memset(loaderCodeBuffer, 0, dwLoaderSize);
1752 		if (!pBoot->GetEntryData(ENTRYLOADER, index, loaderCodeBuffer)) {
1753 			if (g_pLogObject) {
1754 				g_pLogObject->Record("ERROR: %s --> Get LoaderCode Data failed", __func__);
1755 			}
1756 			goto Exit_UpgradeLoader;
1757 		}
1758 
1759 		index = pBoot->GetIndexByName(ENTRYLOADER, loaderDataName);
1760 		if (index == -1) {
1761 			if (g_pLogObject) {
1762 				g_pLogObject->Record("ERROR: %s --> Get LoaderData Entry failed", __func__);
1763 			}
1764 			delete []loaderCodeBuffer;
1765 			return -4;
1766 		}
1767 
1768 		bRet = pBoot->GetEntryProperty(ENTRYLOADER, index, dwLoaderDataSize, dwDelay);
1769 		if (!bRet) {
1770 			if (g_pLogObject) {
1771 				g_pLogObject->Record("ERROR: %s --> Get LoaderData Entry Size failed", __func__);
1772 			}
1773 			goto Exit_UpgradeLoader;
1774 		}
1775 
1776 		loaderDataBuffer = new BYTE[dwLoaderDataSize];
1777 		memset(loaderDataBuffer, 0, dwLoaderDataSize);
1778 		if (!pBoot->GetEntryData(ENTRYLOADER,index,loaderDataBuffer)) {
1779 			if (g_pLogObject) {
1780 				g_pLogObject->Record("ERROR: %s --> Get LoaderData Data failed", __func__);
1781 			}
1782 			goto Exit_UpgradeLoader;
1783 		}
1784 
1785 		usFlashDataSec = (ALIGN(dwLoaderDataSize, 2048)) / SECTOR_SIZE;
1786 		usFlashBootSec = (ALIGN(dwLoaderSize, 2048)) / SECTOR_SIZE;
1787 		dwSectorNum = 4 + usFlashDataSec + usFlashBootSec;
1788 		pIDBData = new BYTE[dwSectorNum*SECTOR_SIZE];
1789 		if (!pIDBData) {
1790 			ERROR_COLOR_ATTR;
1791 			printf("Allocating memory failed!");
1792 			NORMAL_COLOR_ATTR;
1793 			printf("\r\n");
1794 			goto Exit_UpgradeLoader;
1795 		}
1796 		memset(pIDBData, 0, dwSectorNum * SECTOR_SIZE);
1797 		iRet = MakeIDBlockData(loaderDataBuffer, loaderCodeBuffer, pIDBData, usFlashDataSec, usFlashBootSec, dwLoaderDataSize, dwLoaderSize, pBoot->Rc4DisableFlag);
1798 		if (iRet != 0) {
1799 			ERROR_COLOR_ATTR;
1800 			printf("Making idblock failed!");
1801 			NORMAL_COLOR_ATTR;
1802 			printf("\r\n");
1803 			goto Exit_UpgradeLoader;
1804 		}
1805 		iRet = pComm->RKU_WriteLBA(64, dwSectorNum, pIDBData);
1806 		CURSOR_MOVEUP_LINE(1);
1807 		CURSOR_DEL_LINE;
1808 		if (iRet == ERR_SUCCESS) {
1809 			//pComm->Reset_Usb_Device();
1810 			bSuccess = true;
1811 			printf("Upgrading loader succeeded.\r\n");
1812 		} else {
1813 			printf("Upgrading loader failed!\r\n");
1814 			goto Exit_UpgradeLoader;
1815 		}
1816 	}
1817 Exit_UpgradeLoader:
1818 	if (pImage)
1819 		delete pImage;
1820 	if (pComm)
1821 		delete pComm;
1822 	if (loaderCodeBuffer)
1823 		delete []loaderCodeBuffer;
1824 	if (loaderDataBuffer)
1825 		delete []loaderDataBuffer;
1826 	if (pIDBData)
1827 		delete []pIDBData;
1828 	return bSuccess;
1829 }
1830 
1831 bool erase_flash(STRUCT_RKDEVICE_DESC &dev)
1832 {
1833 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1834 		return false;
1835 	CRKImage *pImage = NULL;
1836 	bool bRet, bSuccess = false;
1837 	int iRet;
1838 	CRKScan *pScan = NULL;
1839 	pScan = new CRKScan();
1840 	pScan->SetVidPid();
1841 
1842 	CRKComm *pComm = NULL;
1843 	CRKDevice *pDevice = NULL;
1844 
1845 	pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
1846 	if (!bRet) {
1847 		if (pScan)
1848 			delete pScan;
1849 		ERROR_COLOR_ATTR;
1850 		printf("Creating Comm Object failed!");
1851 		NORMAL_COLOR_ATTR;
1852 		printf("\r\n");
1853 		return bSuccess;
1854 	}
1855 
1856 	pDevice = new CRKDevice(dev);
1857 	if (!pDevice) {
1858 		if (pComm)
1859 			delete pComm;
1860 		if (pScan)
1861 			delete pScan;
1862 		ERROR_COLOR_ATTR;
1863 		printf("Creating device object failed!");
1864 		NORMAL_COLOR_ATTR;
1865 		printf("\r\n");
1866 		return bSuccess;
1867 	}
1868 
1869 	pDevice->SetObject(pImage, pComm, g_pLogObject);
1870 	pDevice->CallBackPointer = ProgressInfoProc;
1871 
1872 	printf("Starting to erase flash...\r\n");
1873 	iRet = pDevice->EraseAllBlocks();
1874 	if (pDevice)
1875 		delete pDevice;
1876 
1877 	if (iRet == 0) {
1878 		if (pScan) {
1879 			pScan->SetVidPid();
1880 			pScan->Wait(dev, RKUSB_MASKROM, dev.usVid, dev.usPid);
1881 			delete pScan;
1882 		}
1883 		CURSOR_MOVEUP_LINE(1);
1884 		CURSOR_DEL_LINE;
1885 		bSuccess = true;
1886 		printf("Erasing flash complete.\r\n");
1887 	}
1888 
1889 	return bSuccess;
1890 }
1891 
1892 bool test_device(STRUCT_RKDEVICE_DESC &dev)
1893 {
1894 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1895 		return false;
1896 	CRKUsbComm *pComm = NULL;
1897 	bool bRet, bSuccess = false;
1898 	int iRet;
1899 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1900 	if (bRet) {
1901 		iRet = pComm->RKU_TestDeviceReady();
1902 		if (iRet != ERR_SUCCESS) {
1903 			if (g_pLogObject)
1904 				g_pLogObject->Record("Error: RKU_TestDeviceReady failed, err=%d", iRet);
1905 			printf("Test Device failed!\r\n");
1906 		} else {
1907 			bSuccess = true;
1908 			printf("Test Device OK.\r\n");
1909 		}
1910 	} else {
1911 		printf("Test Device quit, creating comm object failed!\r\n");
1912 	}
1913 	if (pComm) {
1914 		delete pComm;
1915 		pComm = NULL;
1916 	}
1917 	return bSuccess;
1918 }
1919 bool reset_device(STRUCT_RKDEVICE_DESC &dev, BYTE subCode = RST_NONE_SUBCODE)
1920 {
1921 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1922 		return false;
1923 	CRKUsbComm *pComm = NULL;
1924 	bool bRet, bSuccess = false;
1925 	int iRet;
1926 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1927 	if (bRet) {
1928 		iRet = pComm->RKU_ResetDevice(subCode);
1929 		if (iRet != ERR_SUCCESS) {
1930 			if (g_pLogObject)
1931 				g_pLogObject->Record("Error: RKU_ResetDevice failed, err=%d", iRet);
1932 			printf("Reset Device failed!\r\n");
1933 		} else {
1934 			bSuccess = true;
1935 			printf("Reset Device OK.\r\n");
1936 		}
1937 	} else {
1938 		printf("Reset Device quit, creating comm object failed!\r\n");
1939 	}
1940 	if (pComm) {
1941 		delete pComm;
1942 		pComm = NULL;
1943 	}
1944 	return bSuccess;
1945 }
1946 
1947 bool read_flash_id(STRUCT_RKDEVICE_DESC &dev)
1948 {
1949 	CRKUsbComm *pComm = NULL;
1950 	bool bRet, bSuccess = false;
1951 	int iRet;
1952 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1953 		return bSuccess;
1954 
1955 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1956 	if (bRet) {
1957 		BYTE flashID[5];
1958 		iRet = pComm->RKU_ReadFlashID(flashID);
1959 		if (iRet != ERR_SUCCESS) {
1960 			if (g_pLogObject)
1961 				g_pLogObject->Record("Error: RKU_ReadFlashID failed, err=%d", iRet);
1962 			printf("Reading flash ID failed!\r\n");
1963 		} else {
1964 			printf("Flash ID: %02X %02X %02X %02X %02X\r\n", flashID[0], flashID[1], flashID[2], flashID[3], flashID[4]);
1965 			bSuccess = true;
1966 		}
1967 	} else {
1968 		printf("Read Flash ID quit, creating comm object failed!\r\n");
1969 	}
1970 	if (pComm) {
1971 		delete pComm;
1972 		pComm = NULL;
1973 	}
1974 	return bSuccess;
1975 }
1976 bool read_flash_info(STRUCT_RKDEVICE_DESC &dev)
1977 {
1978 	CRKUsbComm *pComm = NULL;
1979 	bool bRet, bSuccess = false;
1980 	int iRet;
1981 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1982 		return bSuccess;
1983 
1984 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1985 	if (bRet) {
1986 		STRUCT_FLASHINFO_CMD info;
1987 		UINT uiRead;
1988 		iRet = pComm->RKU_ReadFlashInfo((BYTE *)&info, &uiRead);
1989 		if (iRet != ERR_SUCCESS) {
1990 			if (g_pLogObject)
1991 				g_pLogObject->Record("Error: RKU_ReadFlashInfo failed, err=%d", iRet);
1992 			printf("Read Flash Info failed!\r\n");
1993 		} else {
1994 			printf("Flash Info:\r\n");
1995 			if (info.bManufCode <= 7) {
1996 				printf("\tManufacturer: %s, value=%02X\r\n", szManufName[info.bManufCode], info.bManufCode);
1997 			}
1998 			else
1999 				printf("\tManufacturer: %s, value=%02X\r\n", "Unknown", info.bManufCode);
2000 
2001 			printf("\tFlash Size: %d MB\r\n", info.uiFlashSize / 2 / 1024);
2002 			printf("\tBlock Size: %d KB\r\n", info.usBlockSize / 2);
2003 			printf("\tPage Size: %d KB\r\n", info.bPageSize / 2);
2004 			printf("\tECC Bits: %d\r\n", info.bECCBits);
2005 			printf("\tAccess Time: %d\r\n", info.bAccessTime);
2006 			printf("\tFlash CS: ");
2007 			for(int i = 0; i < 8; i++) {
2008 				if( info.bFlashCS & (1 << i) )
2009 					printf("Flash<%d> ", i);
2010 			}
2011 			printf("\r\n");
2012 			bSuccess = true;
2013 		}
2014 	}else {
2015 		printf("Read Flash Info quit, creating comm object failed!\r\n");
2016 	}
2017 	if (pComm) {
2018 		delete pComm;
2019 		pComm = NULL;
2020 	}
2021 	return bSuccess;
2022 }
2023 bool read_chip_info(STRUCT_RKDEVICE_DESC &dev)
2024 {
2025 	CRKUsbComm *pComm = NULL;
2026 	bool bRet, bSuccess = false;
2027 	int iRet;
2028 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
2029 		return bSuccess;
2030 
2031 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
2032 	if (bRet) {
2033 		BYTE chipInfo[16];
2034 		iRet = pComm->RKU_ReadChipInfo(chipInfo);
2035 		if (iRet != ERR_SUCCESS) {
2036 			if (g_pLogObject)
2037 				g_pLogObject->Record("Error: RKU_ReadChipInfo failed, err=%d", iRet);
2038 			printf("Read Chip Info failed!\r\n");
2039 		} else {
2040 			string strChipInfo;
2041 			g_pLogObject->PrintBuffer(strChipInfo, chipInfo, 16, 16);
2042 			printf("Chip Info: %s\r\n", strChipInfo.c_str());
2043 			bSuccess = true;
2044 		}
2045 	} else {
2046 		printf("Read Chip Info quit, creating comm object failed!\r\n");
2047 	}
2048 	if (pComm) {
2049 		delete pComm;
2050 		pComm = NULL;
2051 	}
2052 	return bSuccess;
2053 }
2054 bool read_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, UINT uiLen, char *szFile)
2055 {
2056 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
2057 		return false;
2058 	CRKUsbComm *pComm = NULL;
2059 	FILE *file = NULL;
2060 	bool bRet, bFirst = true, bSuccess = false;
2061 	int iRet;
2062 	UINT iTotalRead = 0,iRead = 0;
2063 	int nSectorSize = 512;
2064 	BYTE pBuf[nSectorSize * DEFAULT_RW_LBA];
2065 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
2066 	if (bRet) {
2067 		if(szFile) {
2068 			file = fopen(szFile, "wb+");
2069 			if( !file ) {
2070 				printf("Read LBA failed, err=%d, can't open file: %s\r\n", errno, szFile);
2071 				goto Exit_ReadLBA;
2072 			}
2073 		}
2074 
2075 		while(uiLen > 0) {
2076 			memset(pBuf, 0, nSectorSize * DEFAULT_RW_LBA);
2077 			iRead = (uiLen >= DEFAULT_RW_LBA) ? DEFAULT_RW_LBA : uiLen;
2078 			iRet = pComm->RKU_ReadLBA( uiBegin + iTotalRead, iRead, pBuf);
2079 			if(ERR_SUCCESS == iRet) {
2080 				uiLen -= iRead;
2081 				iTotalRead += iRead;
2082 
2083 				if(szFile) {
2084 					fwrite(pBuf, 1, iRead * nSectorSize, file);
2085 					if (bFirst){
2086 						if (iTotalRead >= 1024)
2087 							printf("Read LBA to file (%d%%)\r\n", (iTotalRead / 1024) * 100 / ((uiLen + iTotalRead) / 1024));
2088 						else
2089 							printf("Read LBA to file (%d%%)\r\n", iTotalRead * 100 / (uiLen + iTotalRead));
2090 						bFirst = false;
2091 					} else {
2092 						CURSOR_MOVEUP_LINE(1);
2093 						CURSOR_DEL_LINE;
2094 						if (iTotalRead >= 1024)
2095 							printf("Read LBA to file (%d%%)\r\n", (iTotalRead / 1024) * 100 / ((uiLen + iTotalRead) / 1024));
2096 						else
2097 							printf("Read LBA to file (%d%%)\r\n", iTotalRead * 100 / (uiLen + iTotalRead));
2098 					}
2099 				}
2100 				else
2101 					PrintData(pBuf, nSectorSize * iRead);
2102 			} else {
2103 				if (g_pLogObject)
2104 					g_pLogObject->Record("Error: RKU_ReadLBA failed, err=%d", iRet);
2105 
2106 				printf("Read LBA failed!\r\n");
2107 				goto Exit_ReadLBA;
2108 			}
2109 		}
2110 		bSuccess = true;
2111 	} else {
2112 		printf("Read LBA quit, creating comm object failed!\r\n");
2113 	}
2114 Exit_ReadLBA:
2115 	if (pComm) {
2116 		delete pComm;
2117 		pComm = NULL;
2118 	}
2119 	if (file)
2120 		fclose(file);
2121 	return bSuccess;
2122 }
2123 bool write_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, char *szFile)
2124 {
2125 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
2126 		return false;
2127 	CRKUsbComm *pComm = NULL;
2128 	FILE *file = NULL;
2129 	bool bRet, bFirst = true, bSuccess = false;
2130 	int iRet;
2131 	long long iTotalWrite = 0, iFileSize = 0;
2132 	UINT iWrite = 0, iRead = 0;
2133 	UINT uiLen;
2134 	int nSectorSize = 512;
2135 	BYTE pBuf[nSectorSize * DEFAULT_RW_LBA];
2136 
2137 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
2138 	if (bRet) {
2139 		file = fopen(szFile, "rb");
2140 		if( !file ) {
2141 			printf("Write LBA failed, err=%d, can't open file: %s\r\n", errno, szFile);
2142 			goto Exit_WriteLBA;
2143 		}
2144 
2145 		iRet = fseeko(file, 0, SEEK_END);
2146 		iFileSize = ftello(file);
2147 		fseeko(file, 0, SEEK_SET);
2148 		while(iTotalWrite < iFileSize) {
2149 			memset(pBuf, 0, nSectorSize * DEFAULT_RW_LBA);
2150 			iWrite = iRead= fread(pBuf, 1, nSectorSize * DEFAULT_RW_LBA, file);
2151 			uiLen = ((iWrite % 512) == 0) ? (iWrite / 512) : (iWrite / 512 + 1);
2152 			iRet = pComm->RKU_WriteLBA( uiBegin, uiLen, pBuf);
2153 			if(ERR_SUCCESS == iRet) {
2154 				uiBegin += uiLen;
2155 				iTotalWrite += iWrite;
2156 				if (bFirst) {
2157 					if (iTotalWrite >= 1024)
2158 						printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
2159 					else
2160 						printf("Write LBA from file (%lld%%)\r\n", iTotalWrite * 100 / iFileSize);
2161 					bFirst = false;
2162 				} else {
2163 					CURSOR_MOVEUP_LINE(1);
2164 					CURSOR_DEL_LINE;
2165 					printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
2166 				}
2167 			} else {
2168 				if (g_pLogObject)
2169 					g_pLogObject->Record("Error: RKU_WriteLBA failed, err=%d", iRet);
2170 
2171 				printf("Write LBA failed!\r\n");
2172 				goto Exit_WriteLBA;
2173 			}
2174 		}
2175 		bSuccess = true;
2176 	} else {
2177 		printf("Write LBA quit, creating comm object failed!\r\n");
2178 	}
2179 Exit_WriteLBA:
2180 	if (pComm) {
2181 		delete pComm;
2182 		pComm = NULL;
2183 	}
2184 	if (file)
2185 		fclose(file);
2186 	return bSuccess;
2187 }
2188 
2189 void split_item(STRING_VECTOR &vecItems, char *pszItems)
2190 {
2191 	string strItem;
2192 	char szItem[100];
2193 	char *pos = NULL, *pStart;
2194 	pStart = pszItems;
2195 	pos = strchr(pStart, ',');
2196 	while(pos != NULL) {
2197 		memset(szItem, 0, 100);
2198 		strncpy(szItem, pStart, pos - pStart);
2199 		strItem = szItem;
2200 		vecItems.push_back(strItem);
2201 		pStart = pos + 1;
2202 		if (*pStart == 0)
2203 			break;
2204 		pos = strchr(pStart, ',');
2205 	}
2206 	if (strlen(pStart) > 0) {
2207 		memset(szItem, 0, 100);
2208 		strncpy(szItem, pStart, strlen(pStart));
2209 		strItem = szItem;
2210 		vecItems.push_back(strItem);
2211 	}
2212 }
2213 
2214 void tag_spl(char *tag, char *spl)
2215 {
2216 	FILE *file = NULL;
2217 	int len;
2218 
2219 	if(!tag || !spl)
2220 		return;
2221 	len = strlen(tag);
2222 	printf("tag len=%d\n",len);
2223 	file = fopen(spl, "rb");
2224 	if( !file ){
2225 		return;
2226 	}
2227 	int iFileSize;
2228 	fseek(file, 0, SEEK_END);
2229 	iFileSize = ftell(file);
2230 	fseek(file, 0, SEEK_SET);
2231 	char *Buf = NULL;
2232 	Buf = new char[iFileSize + len + 1];
2233 	if (!Buf){
2234 		fclose(file);
2235 		return;
2236 	}
2237 	memset(Buf, 0, iFileSize + 1);
2238 	memcpy(Buf, tag, len);
2239 	int iRead;
2240 	iRead = fread(Buf+len, 1, iFileSize, file);
2241 	if (iRead != iFileSize){
2242 		fclose(file);
2243 		delete []Buf;
2244 		return;
2245 	}
2246 	fclose(file);
2247 
2248 	len = strlen(spl);
2249 	char *taggedspl = new char[len + 5];
2250 	strcpy(taggedspl, spl);
2251 	strcpy(taggedspl + len, ".tag");
2252 	taggedspl[len+4] = 0;
2253 	printf("Writing tagged spl to %s\n", taggedspl);
2254 
2255 	file = fopen(taggedspl, "wb");
2256 	if( !file ){
2257 		delete []taggedspl;
2258 		delete []Buf;
2259 		return;
2260 	}
2261 	fwrite(Buf, 1, iFileSize+len, file);
2262 	fclose(file);
2263 	delete []taggedspl;
2264 	delete []Buf;
2265 	printf("done\n");
2266 	return;
2267 }
2268 
2269 bool handle_command(int argc, char* argv[], CRKScan *pScan)
2270 {
2271 	string strCmd;
2272 	strCmd = argv[1];
2273 	ssize_t cnt;
2274 	bool bRet,bSuccess = false;
2275 	char *s;
2276 	int i, ret;
2277 	STRUCT_RKDEVICE_DESC dev;
2278 
2279 	transform(strCmd.begin(), strCmd.end(), strCmd.begin(), (int(*)(int))toupper);
2280 	s = (char*)strCmd.c_str();
2281 	for(i = 0; i < (int)strlen(s); i++)
2282 	        s[i] = toupper(s[i]);
2283 
2284 	if((strcmp(strCmd.c_str(), "-H") == 0) || (strcmp(strCmd.c_str(), "--HELP")) == 0){
2285 		usage();
2286 		return true;
2287 	} else if((strcmp(strCmd.c_str(), "-V") == 0) || (strcmp(strCmd.c_str(), "--VERSION") == 0)) {
2288 		printf("rkdeveloptool ver %s\r\n", PACKAGE_VERSION);
2289 		return true;
2290 	} else if (strcmp(strCmd.c_str(), "PACK") == 0) {//pack boot loader
2291 		mergeBoot();
2292 
2293 		return true;
2294 	} else if (strcmp(strCmd.c_str(), "UNPACK") == 0) {//unpack boot loader
2295 		string strLoader = argv[2];
2296 
2297 		unpackBoot((char*)strLoader.c_str());
2298 		return true;
2299 	} else if (strcmp(strCmd.c_str(), "TAGSPL") == 0) {//tag u-boot spl
2300 		if (argc == 4) {
2301 			string tag = argv[2];
2302 			string spl = argv[3];
2303 			printf("tag %s to %s\n", tag.c_str(), spl.c_str());
2304 			tag_spl((char*)tag.c_str(), (char*)spl.c_str());
2305 			return true;
2306 		}
2307 		printf("tagspl: parameter error\n");
2308 		usage();
2309 	}
2310 	cnt = pScan->Search(RKUSB_MASKROM | RKUSB_LOADER);
2311 	if (cnt < 1) {
2312 		ERROR_COLOR_ATTR;
2313 		printf("Did not find any rockusb device, please plug device in!");
2314 		NORMAL_COLOR_ATTR;
2315 		printf("\r\n");
2316 		return bSuccess;
2317 	} else if (cnt > 1) {
2318 		ERROR_COLOR_ATTR;
2319 		printf("Found too many rockusb devices, please plug devices out!");
2320 		NORMAL_COLOR_ATTR;
2321 		printf("\r\n");
2322 		return bSuccess;
2323 	}
2324 
2325 	bRet = pScan->GetDevice(dev, 0);
2326 	if (!bRet) {
2327 		ERROR_COLOR_ATTR;
2328 		printf("Getting information about rockusb device failed!");
2329 		NORMAL_COLOR_ATTR;
2330 		printf("\r\n");
2331 		return bSuccess;
2332 	}
2333 
2334 	if(strcmp(strCmd.c_str(), "RD") == 0) {
2335 		if ((argc != 2) && (argc != 3))
2336 			printf("Parameter of [RD] command is invalid, please check help!\r\n");
2337 		else {
2338 			if (argc == 2)
2339 				bSuccess = reset_device(dev);
2340 			else {
2341 				UINT uiSubCode;
2342 				char *pszEnd;
2343 				uiSubCode = strtoul(argv[2], &pszEnd, 0);
2344 				if (*pszEnd)
2345 					printf("Subcode is invalid, please check!\r\n");
2346 				else {
2347 					if (uiSubCode <= 5)
2348 						bSuccess = reset_device(dev, uiSubCode);
2349 					else
2350 						printf("Subcode is invalid, please check!\r\n");
2351 				}
2352 			}
2353 		}
2354 	} else if(strcmp(strCmd.c_str(), "TD") == 0) {
2355 		bSuccess = test_device(dev);
2356 	} else if (strcmp(strCmd.c_str(), "RID") == 0) {//Read Flash ID
2357 		bSuccess = read_flash_id(dev);
2358 	} else if (strcmp(strCmd.c_str(), "RFI") == 0){//Read Flash Info
2359 		bSuccess = read_flash_info(dev);
2360 	} else if (strcmp(strCmd.c_str(), "RCI") == 0) {//Read Chip Info
2361 		bSuccess = read_chip_info(dev);
2362 	} else if(strcmp(strCmd.c_str(), "DB") == 0) {
2363 		if (argc > 2) {
2364 			string strLoader;
2365 			strLoader = argv[2];
2366 			bSuccess = download_boot(dev, (char *)strLoader.c_str());
2367 		} else if (argc == 2) {
2368 			ret = find_config_item(g_ConfigItemVec, "loader");
2369 			if (ret == -1)
2370 				printf("Did not find loader item in config!\r\n");
2371 			else
2372 				bSuccess = download_boot(dev, g_ConfigItemVec[ret].szItemValue);
2373 		} else
2374 			printf("Parameter of [DB] command is invalid, please check help!\r\n");
2375 	} else if(strcmp(strCmd.c_str(), "GPT") == 0) {
2376 		if (argc > 2) {
2377 			string strParameter;
2378 			strParameter = argv[2];
2379 			bSuccess = write_gpt(dev, (char *)strParameter.c_str());
2380 		} else
2381 			printf("Parameter of [GPT] command is invalid, please check help!\r\n");
2382 	} else if(strcmp(strCmd.c_str(), "UL") == 0) {
2383 		if (argc > 2) {
2384 			string strLoader;
2385 			strLoader = argv[2];
2386 			bSuccess = upgrade_loader(dev, (char *)strLoader.c_str());
2387 		} else
2388 			printf("Parameter of [UL] command is invalid, please check help!\r\n");
2389 	} else if(strcmp(strCmd.c_str(), "EF") == 0) {
2390 		if (argc == 2) {
2391 			bSuccess = erase_flash(dev);
2392 		} else
2393 			printf("Parameter of [EF] command is invalid, please check help!\r\n");
2394 	} else if(strcmp(strCmd.c_str(), "WL") == 0) {
2395 		if (argc == 4) {
2396 			UINT uiBegin;
2397 			char *pszEnd;
2398 			uiBegin = strtoul(argv[2], &pszEnd, 0);
2399 			if (*pszEnd)
2400 				printf("Begin is invalid, please check!\r\n");
2401 			else
2402 				bSuccess = write_lba(dev, uiBegin, argv[3]);
2403 		} else
2404 			printf("Parameter of [WL] command is invalid, please check help!\r\n");
2405 	} else if (strcmp(strCmd.c_str(), "RL") == 0) {//Read LBA
2406 		char *pszEnd;
2407 		UINT uiBegin, uiLen;
2408 		if (argc != 5)
2409 			printf("Parameter of [RL] command is invalid, please check help!\r\n");
2410 		else {
2411 			uiBegin = strtoul(argv[2], &pszEnd, 0);
2412 			if (*pszEnd)
2413 				printf("Begin is invalid, please check!\r\n");
2414 			else {
2415 				uiLen = strtoul(argv[3], &pszEnd, 0);
2416 				if (*pszEnd)
2417 					printf("Len is invalid, please check!\r\n");
2418 				else {
2419 					bSuccess = read_lba(dev, uiBegin, uiLen, argv[4]);
2420 				}
2421 			}
2422 		}
2423 	} else {
2424 		printf("command is invalid!\r\n");
2425 		usage();
2426 	}
2427 	return bSuccess;
2428 }
2429 
2430 
2431 int main(int argc, char* argv[])
2432 {
2433 	CRKScan *pScan = NULL;
2434 	int ret;
2435 	char szProgramProcPath[100];
2436 	char szProgramDir[256];
2437 	string strLogDir,strConfigFile;
2438 	struct stat statBuf;
2439 
2440 	g_ConfigItemVec.clear();
2441 	sprintf(szProgramProcPath, "/proc/%d/exe", getpid());
2442 	if (readlink(szProgramProcPath, szProgramDir, 256) == -1)
2443 		strcpy(szProgramDir, ".");
2444 	else {
2445 		char *pSlash;
2446 		pSlash = strrchr(szProgramDir, '/');
2447 		if (pSlash)
2448 			*pSlash = '\0';
2449 	}
2450 	strLogDir = szProgramDir;
2451 	strLogDir +=  "/log/";
2452 	strConfigFile = szProgramDir;
2453 	strConfigFile += "/config.ini";
2454 	if (opendir(strLogDir.c_str()) == NULL)
2455 		mkdir(strLogDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH);
2456 	g_pLogObject = new CRKLog(strLogDir.c_str(), "log",true);
2457 
2458 	if(stat(strConfigFile.c_str(), &statBuf) < 0) {
2459 		if (g_pLogObject) {
2460 			g_pLogObject->Record("Error: failed to stat config.ini, err=%d", errno);
2461 		}
2462 	} else if (S_ISREG(statBuf.st_mode)) {
2463 		parse_config_file(strConfigFile.c_str(), g_ConfigItemVec);
2464 	}
2465 
2466 	ret = libusb_init(NULL);
2467 	if (ret < 0) {
2468 		if (g_pLogObject) {
2469 			g_pLogObject->Record("Error: libusb_init failed, err=%d", ret);
2470 			delete g_pLogObject;
2471 		}
2472 		return -1;
2473 	}
2474 
2475 	pScan = new CRKScan();
2476 	if (!pScan) {
2477 		if (g_pLogObject) {
2478 			g_pLogObject->Record("Error: failed to create object for searching device");
2479 			delete g_pLogObject;
2480 		}
2481 		libusb_exit(NULL);
2482 		return -2;
2483 	}
2484 	pScan->SetVidPid();
2485 
2486 	if (argc == 1)
2487 		usage();
2488 	else if (!handle_command(argc, argv, pScan))
2489 			return -0xFF;
2490 	if (pScan)
2491 		delete pScan;
2492 	if (g_pLogObject)
2493 		delete g_pLogObject;
2494 	libusb_exit(NULL);
2495 	return 0;
2496 }
2497