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