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