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