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