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