xref: /rkdeveloptool/main.cpp (revision 2b17a44a657f2e4dc01ca13f2ddc31c823b14f11)
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[37;40m", 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)
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 = 1;
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)
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 
572 	MakeSector0((PBYTE)&sector0Info, usFlashDataSec, usFlashBootSec);
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 	memcpy(lpIDBlock + SECTOR_SIZE * 4, pDDR, dwLoaderDataSize);
588 	memcpy(lpIDBlock + SECTOR_SIZE * (4 + usFlashDataSec), pLoader, dwLoaderSize);
589 
590 	sector2Info.uiBootCodeCrc = CRC_32((PBYTE)(lpIDBlock + SECTOR_SIZE * 4), sector0Info.usBootCodeSize * SECTOR_SIZE);
591 	memcpy(lpIDBlock + SECTOR_SIZE * 2, &sector2Info, SECTOR_SIZE);
592 	for(i = 0; i < 4; i++) {
593 		if(i == 1) {
594 			continue;
595 		} else {
596 			P_RC4(lpIDBlock + SECTOR_SIZE * i, SECTOR_SIZE);
597 		}
598 	}
599 	return 0;
600 }
601 
602 
603 
604 bool check_device_type(STRUCT_RKDEVICE_DESC &dev, UINT uiSupportType)
605 {
606 	if ((dev.emUsbType & uiSupportType) == dev.emUsbType)
607 		return true;
608 	else
609 	{
610 		ERROR_COLOR_ATTR;
611 		printf("The device does not support this operation!");
612 		NORMAL_COLOR_ATTR;
613 		printf("\r\n");
614 		return false;
615 	}
616 }
617 bool write_gpt(STRUCT_RKDEVICE_DESC &dev, char *szParameter)
618 {
619 	u8 flash_info[SECTOR_SIZE], master_gpt[34 * SECTOR_SIZE], backup_gpt[33 * SECTOR_SIZE];
620 	u32 total_size_sector;
621 	CRKComm *pComm = NULL;
622 	PARAM_ITEM_VECTOR vecItems;
623 	int iRet;
624 	bool bRet, bSuccess = false;
625 	if (!check_device_type(dev, RKUSB_MASKROM))
626 		return false;
627 
628 	pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
629 	if (!bRet) {
630 		ERROR_COLOR_ATTR;
631 		printf("Creating Comm Object failed!");
632 		NORMAL_COLOR_ATTR;
633 		printf("\r\n");
634 		return bSuccess;
635 	}
636 	printf("Writing gpt...\r\n");
637 	//1.get flash info
638 	iRet = pComm->RKU_ReadFlashInfo(flash_info);
639 	if (iRet != ERR_SUCCESS) {
640 		ERROR_COLOR_ATTR;
641 		printf("Reading Flash Info failed!");
642 		NORMAL_COLOR_ATTR;
643 		printf("\r\n");
644 		return bSuccess;
645 	}
646 	total_size_sector = *(u32 *)flash_info;
647 	//2.get partition from parameter
648 	bRet = parse_parameter_file(szParameter, vecItems);
649 	if (!bRet) {
650 		ERROR_COLOR_ATTR;
651 		printf("Parsing parameter failed!");
652 		NORMAL_COLOR_ATTR;
653 		printf("\r\n");
654 		return bSuccess;
655 	}
656 	vecItems[vecItems.size()-1].uiItemSize = total_size_sector - 34;
657 	//3.generate gpt info
658 	create_gpt_buffer(master_gpt, vecItems, total_size_sector);
659 	memcpy(backup_gpt, master_gpt + 2* SECTOR_SIZE, 32 * SECTOR_SIZE);
660 	memcpy(backup_gpt + 32 * SECTOR_SIZE, master_gpt + SECTOR_SIZE, SECTOR_SIZE);
661 	//4. write gpt
662 	iRet = pComm->RKU_WriteLBA(0, 34, master_gpt);
663 	if (iRet != ERR_SUCCESS) {
664 		ERROR_COLOR_ATTR;
665 		printf("Writing master gpt failed!");
666 		NORMAL_COLOR_ATTR;
667 		printf("\r\n");
668 		return bSuccess;
669 	}
670 	iRet = pComm->RKU_WriteLBA(total_size_sector - 34, 33, backup_gpt);
671 	if (iRet != ERR_SUCCESS) {
672 		ERROR_COLOR_ATTR;
673 		printf("Writing backup gpt failed!");
674 		NORMAL_COLOR_ATTR;
675 		printf("\r\n");
676 		return bSuccess;
677 	}
678 	bSuccess = true;
679 	CURSOR_MOVEUP_LINE(1);
680 	CURSOR_DEL_LINE;
681 	printf("Writing gpt succeeded.\r\n");
682 	return bSuccess;
683 }
684 
685 #include "boot_merger.h"
686 #define ENTRY_ALIGN  (2048)
687 options gOpts;
688 
689 
690 char gSubfix[MAX_LINE_LEN] = OUT_SUBFIX;
691 char* gConfigPath;
692 uint8_t gBuf[MAX_MERGE_SIZE];
693 
694 static inline void fixPath(char* path) {
695 	int i, len = strlen(path);
696 	for(i=0; i<len; i++) {
697 		if (path[i] == '\\')
698 			path[i] = '/';
699 		else if (path[i] == '\r' || path[i] == '\n')
700 			path[i] = '\0';
701 	}
702 }
703 
704 static bool parseChip(FILE* file) {
705 	if (SCANF_EAT(file) != 0) {
706 		return false;
707 	}
708 	if (fscanf(file, OPT_NAME "=%s", gOpts.chip) != 1) {
709 		return false;
710 	}
711 	printf("chip: %s\n", gOpts.chip);
712 	return true;
713 }
714 
715 static bool parseVersion(FILE* file) {
716 	if (SCANF_EAT(file) != 0) {
717 		return false;
718 	}
719 	if (fscanf(file, OPT_MAJOR "=%d", &gOpts.major) != 1)
720 		return false;
721 	if (SCANF_EAT(file) != 0) {
722 		return false;
723 	}
724 	if (fscanf(file, OPT_MINOR "=%d", &gOpts.minor) != 1)
725 		return false;
726 	printf("major: %d, minor: %d\n", gOpts.major, gOpts.minor);
727 	return true;
728 }
729 
730 static bool parse471(FILE* file) {
731 	int i, index, pos;
732 	char buf[MAX_LINE_LEN];
733 
734 	if (SCANF_EAT(file) != 0) {
735 		return false;
736 	}
737 	if (fscanf(file, OPT_NUM "=%d", &gOpts.code471Num) != 1)
738 		return false;
739 	printf("num: %d\n", gOpts.code471Num);
740 	if (!gOpts.code471Num)
741 		return true;
742 	if (gOpts.code471Num < 0)
743 		return false;
744 	gOpts.code471Path = (line_t*) malloc(sizeof(line_t) * gOpts.code471Num);
745 	for (i=0; i<gOpts.code471Num; i++) {
746 		if (SCANF_EAT(file) != 0) {
747 			return false;
748 		}
749 		if (fscanf(file, OPT_PATH "%d=%[^\r^\n]", &index, buf)
750 				!= 2)
751 			return false;
752 		index--;
753 		fixPath(buf);
754 		strcpy((char*)gOpts.code471Path[index], buf);
755 		printf("path%i: %s\n", index, gOpts.code471Path[index]);
756 	}
757 	pos = ftell(file);
758 	if (SCANF_EAT(file) != 0) {
759 		return false;
760 	}
761 	if (fscanf(file, OPT_SLEEP "=%d", &gOpts.code471Sleep) != 1)
762 		fseek(file, pos, SEEK_SET);
763 	printf("sleep: %d\n", gOpts.code471Sleep);
764 	return true;
765 }
766 
767 static bool parse472(FILE* file) {
768 	int i, index, pos;
769 	char buf[MAX_LINE_LEN];
770 
771 	if (SCANF_EAT(file) != 0) {
772 		return false;
773 	}
774 	if (fscanf(file, OPT_NUM "=%d", &gOpts.code472Num) != 1)
775 		return false;
776 	printf("num: %d\n", gOpts.code472Num);
777 	if (!gOpts.code472Num)
778 		return true;
779 	if (gOpts.code472Num < 0)
780 		return false;
781 	gOpts.code472Path = (line_t*) malloc(sizeof(line_t) * gOpts.code472Num);
782 	for (i=0; i<gOpts.code472Num; i++) {
783 		if (SCANF_EAT(file) != 0) {
784 			return false;
785 		}
786 		if (fscanf(file, OPT_PATH "%d=%[^\r^\n]", &index, buf)
787 				!= 2)
788 			return false;
789 		fixPath(buf);
790 		index--;
791 		strcpy((char*)gOpts.code472Path[index], buf);
792 		printf("path%i: %s\n", index, gOpts.code472Path[index]);
793 	}
794 	pos = ftell(file);
795 	if (SCANF_EAT(file) != 0) {
796 		return false;
797 	}
798 	if (fscanf(file, OPT_SLEEP "=%d", &gOpts.code472Sleep) != 1)
799 		fseek(file, pos, SEEK_SET);
800 	printf("sleep: %d\n", gOpts.code472Sleep);
801 	return true;
802 }
803 
804 static bool parseLoader(FILE* file) {
805 	int i, j, index, pos;
806 	char buf[MAX_LINE_LEN];
807 	char buf2[MAX_LINE_LEN];
808 
809 	if (SCANF_EAT(file) != 0) {
810 		return false;
811 	}
812 	pos = ftell(file);
813 	if (fscanf(file, OPT_NUM "=%d", &gOpts.loaderNum) != 1) {
814 		fseek(file, pos, SEEK_SET);
815 		if(fscanf(file, OPT_LOADER_NUM "=%d", &gOpts.loaderNum) != 1) {
816 			return false;
817 		}
818 	}
819 	printf("num: %d\n", gOpts.loaderNum);
820 	if (!gOpts.loaderNum)
821 		return false;
822 	if (gOpts.loaderNum < 0)
823 		return false;
824 	gOpts.loader = (name_entry*) malloc(sizeof(name_entry) * gOpts.loaderNum);
825 	for (i=0; i<gOpts.loaderNum; i++) {
826 		if (SCANF_EAT(file) != 0) {
827 			return false;
828 		}
829 		if (fscanf(file, OPT_LOADER_NAME "%d=%s", &index, buf)
830 				!= 2)
831 			return false;
832 		index--;
833 		strcpy(gOpts.loader[index].name, buf);
834 		printf("name%d: %s\n", index, gOpts.loader[index].name);
835 	}
836 	for (i=0; i<gOpts.loaderNum; i++) {
837 		if (SCANF_EAT(file) != 0) {
838 			return false;
839 		}
840 		if (fscanf(file, "%[^=]=%[^\r^\n]", buf, buf2)
841 				!= 2)
842 			return false;
843 		for (j=0; j<gOpts.loaderNum; j++) {
844 			if (!strcmp(gOpts.loader[j].name, buf)) {
845 				fixPath(buf2);
846 				strcpy(gOpts.loader[j].path, buf2);
847 				printf("%s=%s\n", gOpts.loader[j].name, gOpts.loader[j].path);
848 				break;
849 			}
850 		}
851 		if (j >= gOpts.loaderNum) {
852 			return false;
853 		}
854 	}
855 	return true;
856 }
857 
858 static bool parseOut(FILE* file) {
859 	if (SCANF_EAT(file) != 0) {
860 		return false;
861 	}
862 	if (fscanf(file, OPT_OUT_PATH "=%[^\r^\n]", gOpts.outPath) != 1)
863 		return false;
864 	fixPath(gOpts.outPath);
865 	printf("out: %s\n", gOpts.outPath);
866 	return true;
867 }
868 
869 
870 void printOpts(FILE* out) {
871 	int i;
872 	fprintf(out, SEC_CHIP "\n" OPT_NAME "=%s\n", gOpts.chip);
873 	fprintf(out, SEC_VERSION "\n" OPT_MAJOR "=%d\n" OPT_MINOR
874 			"=%d\n", gOpts.major, gOpts.minor);
875 
876 	fprintf(out, SEC_471 "\n" OPT_NUM "=%d\n", gOpts.code471Num);
877 	for (i=0 ;i<gOpts.code471Num ;i++) {
878 		fprintf(out, OPT_PATH "%d=%s\n", i+1, gOpts.code471Path[i]);
879 	}
880 	if (gOpts.code471Sleep > 0)
881 		fprintf(out, OPT_SLEEP "=%d\n", gOpts.code471Sleep);
882 
883 	fprintf(out, SEC_472 "\n" OPT_NUM "=%d\n", gOpts.code472Num);
884 	for (i=0 ;i<gOpts.code472Num ;i++) {
885 		fprintf(out, OPT_PATH "%d=%s\n", i+1, gOpts.code472Path[i]);
886 	}
887 	if (gOpts.code472Sleep > 0)
888 		fprintf(out, OPT_SLEEP "=%d\n", gOpts.code472Sleep);
889 
890 	fprintf(out, SEC_LOADER "\n" OPT_NUM "=%d\n", gOpts.loaderNum);
891 	for (i=0 ;i<gOpts.loaderNum ;i++) {
892 		fprintf(out, OPT_LOADER_NAME "%d=%s\n", i+1, gOpts.loader[i].name);
893 	}
894 	for (i=0 ;i<gOpts.loaderNum ;i++) {
895 		fprintf(out, "%s=%s\n", gOpts.loader[i].name, gOpts.loader[i].path);
896 	}
897 
898 	fprintf(out, SEC_OUT "\n" OPT_OUT_PATH "=%s\n", gOpts.outPath);
899 }
900 
901 static bool parseOpts(void) {
902 	bool ret = false;
903 	bool chipOk = false;
904 	bool versionOk = false;
905 	bool code471Ok = true;
906 	bool code472Ok = true;
907 	bool loaderOk = false;
908 	bool outOk = false;
909 	char buf[MAX_LINE_LEN];
910 
911 	char* configPath = (gConfigPath == (char*)NULL)? (char*)DEF_CONFIG_FILE: gConfigPath;
912 	FILE* file;
913 	file = fopen(configPath, "r");
914 	if (!file) {
915 		fprintf(stderr, "config (%s) not found!\n", configPath);
916 		if (configPath == (char*)DEF_CONFIG_FILE) {
917 			file = fopen(DEF_CONFIG_FILE, "w");
918 			if (file) {
919 				fprintf(stderr, "creating defconfig\n");
920 				printOpts(file);
921 			}
922 		}
923 		goto end;
924 	}
925 
926 	printf("Starting to parse...\n");
927 
928 	if (SCANF_EAT(file) != 0) {
929 		goto end;
930 	}
931 	while(fscanf(file, "%s", buf) == 1) {
932 		if (!strcmp(buf, SEC_CHIP)) {
933 			chipOk = parseChip(file);
934 			if (!chipOk) {
935 				printf("parseChip failed!\n");
936 				goto end;
937 			}
938 		} else if (!strcmp(buf, SEC_VERSION)) {
939 			versionOk = parseVersion(file);
940 			if (!versionOk) {
941 				printf("parseVersion failed!\n");
942 				goto end;
943 			}
944 		} else if (!strcmp(buf, SEC_471)) {
945 			code471Ok = parse471(file);
946 			if (!code471Ok) {
947 				printf("parse471 failed!\n");
948 				goto end;
949 			}
950 		} else if (!strcmp(buf, SEC_472)) {
951 			code472Ok = parse472(file);
952 			if (!code472Ok) {
953 				printf("parse472 failed!\n");
954 				goto end;
955 			}
956 		} else if (!strcmp(buf, SEC_LOADER)) {
957 			loaderOk = parseLoader(file);
958 			if (!loaderOk) {
959 				printf("parseLoader failed!\n");
960 				goto end;
961 			}
962 		} else if (!strcmp(buf, SEC_OUT)) {
963 			outOk = parseOut(file);
964 			if (!outOk) {
965 				printf("parseOut failed!\n");
966 				goto end;
967 			}
968 		} else if (buf[0] == '#') {
969 			continue;
970 		} else {
971 			printf("unknown sec: %s!\n", buf);
972 			goto end;
973 		}
974 		if (SCANF_EAT(file) != 0) {
975 			goto end;
976 		}
977 	}
978 
979 	if (chipOk && versionOk && code471Ok && code472Ok
980 			&& loaderOk && outOk)
981 		ret = true;
982 end:
983 	if (file)
984 		fclose(file);
985 	return ret;
986 }
987 
988 bool initOpts(void) {
989 	//set default opts
990 	gOpts.major = DEF_MAJOR;
991 	gOpts.minor = DEF_MINOR;
992 	strcpy(gOpts.chip, DEF_CHIP);
993 	gOpts.code471Sleep = DEF_CODE471_SLEEP;
994 	gOpts.code472Sleep = DEF_CODE472_SLEEP;
995 	gOpts.code471Num = DEF_CODE471_NUM;
996 	gOpts.code471Path = (line_t*) malloc(sizeof(line_t) * gOpts.code471Num);
997 	strcpy((char*)gOpts.code471Path[0], DEF_CODE471_PATH);
998 	gOpts.code472Num = DEF_CODE472_NUM;
999 	gOpts.code472Path = (line_t*) malloc(sizeof(line_t) * gOpts.code472Num);
1000 	strcpy((char*)gOpts.code472Path[0], DEF_CODE472_PATH);
1001 	gOpts.loaderNum = DEF_LOADER_NUM;
1002 	gOpts.loader = (name_entry*) malloc(sizeof(name_entry) * gOpts.loaderNum);
1003 	strcpy(gOpts.loader[0].name, DEF_LOADER0);
1004 	strcpy(gOpts.loader[0].path, DEF_LOADER0_PATH);
1005 	strcpy(gOpts.loader[1].name, DEF_LOADER1);
1006 	strcpy(gOpts.loader[1].path, DEF_LOADER1_PATH);
1007 	strcpy(gOpts.outPath, DEF_OUT_PATH);
1008 
1009 	return parseOpts();
1010 }
1011 
1012 /************merge code****************/
1013 
1014 static inline uint32_t getBCD(unsigned short value) {
1015 	uint8_t tmp[2] = {0};
1016 	int i;
1017 	uint32_t ret;
1018 	//if (value > 0xFFFF) {
1019 	//	return 0;
1020 	//}
1021 	for(i=0; i < 2; i++) {
1022 		tmp[i] = (((value/10)%10)<<4) | (value%10);
1023 		value /= 100;
1024 	}
1025 	ret = ((uint16_t)(tmp[1] << 8)) | tmp[0];
1026 
1027 	printf("ret: %x\n",ret);
1028 	return ret&0xFF;
1029 }
1030 
1031 static inline void str2wide(const char* str, uint16_t* wide, int len)
1032 {
1033 	int i;
1034 	for (i = 0; i < len; i++) {
1035 		wide[i] = (uint16_t) str[i];
1036 	}
1037 	wide[len] = 0;
1038 }
1039 
1040 static inline void getName(char* path, uint16_t* dst) {
1041 	char* end;
1042 	char* start;
1043 	int len;
1044 	if (!path || !dst)
1045 		return;
1046 	start = strrchr(path, '/');
1047 	if (!start)
1048 		start = path;
1049 	else
1050 		start++;
1051 	end = strrchr(path, '.');
1052 	if (!end || (end < start))
1053 		end = path + strlen(path);
1054 	len = end - start;
1055 	if (len >= MAX_NAME_LEN)
1056 		len = MAX_NAME_LEN -1;
1057 	str2wide(start, dst, len);
1058 
1059 
1060 		char name[MAX_NAME_LEN];
1061 		memset(name, 0, sizeof(name));
1062 		memcpy(name, start, len);
1063 		printf("path: %s, name: %s\n", path, name);
1064 
1065 }
1066 
1067 static inline bool getFileSize(const char *path, uint32_t* size) {
1068 	struct stat st;
1069 	if(stat(path, &st) < 0)
1070 		return false;
1071 	*size = st.st_size;
1072 	printf("path: %s, size: %d\n", path, *size);
1073 	return true;
1074 }
1075 
1076 static inline rk_time getTime(void) {
1077 	rk_time rkTime;
1078 
1079 	struct tm *tm;
1080 	time_t tt = time(NULL);
1081 	tm = localtime(&tt);
1082 	rkTime.year = tm->tm_year + 1900;
1083 	rkTime.month = tm->tm_mon + 1;
1084 	rkTime.day = tm->tm_mday;
1085 	rkTime.hour = tm->tm_hour;
1086 	rkTime.minute = tm->tm_min;
1087 	rkTime.second = tm->tm_sec;
1088 	printf("%d-%d-%d %02d:%02d:%02d\n",
1089 			rkTime.year, rkTime.month, rkTime.day,
1090 			rkTime.hour, rkTime.minute, rkTime.second);
1091 	return rkTime;
1092 }
1093 
1094 static bool writeFile(FILE* outFile, const char* path, bool fix) {
1095 	bool ret = false;
1096 	uint32_t size = 0, fixSize = 0;
1097 	uint8_t* buf;
1098 
1099 	FILE* inFile = fopen(path, "rb");
1100 	if (!inFile)
1101 		goto end;
1102 
1103 	if (!getFileSize(path, &size))
1104 		goto end;
1105 	if (fix) {
1106 		fixSize = ((size - 1) / SMALL_PACKET + 1) * SMALL_PACKET;
1107 		uint32_t tmp = fixSize % ENTRY_ALIGN;
1108 		tmp = tmp ? (ENTRY_ALIGN - tmp): 0;
1109 		fixSize +=tmp;
1110 		memset(gBuf, 0, fixSize);
1111 	} else {
1112 		memset(gBuf, 0, size+ENTRY_ALIGN);
1113 	}
1114 	if (!fread(gBuf, size, 1, inFile))
1115 		goto end;
1116 
1117 	if (fix) {
1118 
1119 		buf = gBuf;
1120 		size = fixSize;
1121 		while(1) {
1122 			P_RC4(buf, fixSize < SMALL_PACKET ? fixSize : SMALL_PACKET);
1123 			buf += SMALL_PACKET;
1124 			if (fixSize <= SMALL_PACKET)
1125 				break;
1126 			fixSize -= SMALL_PACKET;
1127 		}
1128 	} else {
1129 		uint32_t tmp = size % ENTRY_ALIGN;
1130 		tmp = tmp ? (ENTRY_ALIGN - tmp): 0;
1131 		size +=tmp;
1132 		P_RC4(gBuf, size);
1133 	}
1134 
1135 	if (!fwrite(gBuf, size, 1, outFile))
1136 		goto end;
1137 	ret = true;
1138 end:
1139 	if (inFile)
1140 		fclose(inFile);
1141 	if (!ret)
1142 		printf("writing entry (%s) failed\n", path);
1143 	return ret;
1144 }
1145 
1146 static bool saveEntry(FILE* outFile, char* path, rk_entry_type type,
1147 		uint16_t delay, uint32_t* offset, char* fixName, bool fix) {
1148 	uint32_t size;
1149 	rk_boot_entry entry;
1150 
1151 	printf("writing: %s\n", path);
1152 	memset(&entry, 0, sizeof(rk_boot_entry));
1153 	getName(fixName ? fixName: path, entry.name);
1154 	entry.size = sizeof(rk_boot_entry);
1155 	entry.type = type;
1156 	entry.dataOffset = *offset;
1157 	if (!getFileSize(path, &size)) {
1158 		printf("Saving entry (%s) failed:\n\tCannot get file size.\n", path);
1159 		return false;
1160 	}
1161 	if (fix)
1162 		size = ((size - 1) / SMALL_PACKET + 1) * SMALL_PACKET;
1163 	uint32_t tmp = size % ENTRY_ALIGN;
1164 	size += tmp ? (ENTRY_ALIGN - tmp): 0;
1165 	printf("alignment size: %d\n", size);
1166 	entry.dataSize = size;
1167 	entry.dataDelay = delay;
1168 	*offset += size;
1169 	fwrite(&entry, sizeof(rk_boot_entry), 1, outFile);
1170 	return true;
1171 }
1172 
1173 static inline uint32_t convertChipType(const char* chip) {
1174 	char buffer[5];
1175 	memset(buffer, 0, sizeof(buffer));
1176 	snprintf(buffer, sizeof(buffer), "%s", chip);
1177 	return buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
1178 }
1179 
1180 static inline uint32_t getChipType(const char* chip) {
1181 	printf("chip: %s\n", chip);
1182 	int chipType = RKNONE_DEVICE;
1183 	if(!chip) {
1184 		goto end;
1185 	}
1186 	if (!strcmp(chip, CHIP_RK28)) {
1187 		chipType = RK28_DEVICE;
1188 	} else if (!strcmp(chip, CHIP_RK28)) {
1189 		chipType = RK28_DEVICE;
1190 	} else if (!strcmp(chip, CHIP_RK281X)) {
1191 		chipType = RK281X_DEVICE;
1192 	} else if (!strcmp(chip, CHIP_RKPANDA)) {
1193 		chipType = RKPANDA_DEVICE;
1194 	} else if (!strcmp(chip, CHIP_RK27)) {
1195 		chipType = RK27_DEVICE;
1196 	} else if (!strcmp(chip, CHIP_RKNANO)) {
1197 		chipType = RKNANO_DEVICE;
1198 	} else if (!strcmp(chip, CHIP_RKSMART)) {
1199 		chipType = RKSMART_DEVICE;
1200 	} else if (!strcmp(chip, CHIP_RKCROWN)) {
1201 		chipType = RKCROWN_DEVICE;
1202 	} else if (!strcmp(chip, CHIP_RKCAYMAN)) {
1203 		chipType = RKCAYMAN_DEVICE;
1204 	} else if (!strcmp(chip, CHIP_RK29)) {
1205 		chipType = RK29_DEVICE;
1206 	} else if (!strcmp(chip, CHIP_RK292X)) {
1207 		chipType = RK292X_DEVICE;
1208 	} else if (!strcmp(chip, CHIP_RK30)) {
1209 		chipType = RK30_DEVICE;
1210 	} else if (!strcmp(chip, CHIP_RK30B)) {
1211 		chipType = RK30B_DEVICE;
1212 	} else if (!strcmp(chip, CHIP_RK31)) {
1213 		chipType = RK31_DEVICE;
1214 	} else if (!strcmp(chip, CHIP_RK32)) {
1215 		chipType = RK32_DEVICE;
1216 	} else {
1217 		chipType = convertChipType(chip + 2);
1218 	}
1219 
1220 end:
1221 	printf("type: 0x%x\n", chipType);
1222 	if (chipType == RKNONE_DEVICE) {
1223 		printf("chip type not supported!\n");
1224 	}
1225 	return chipType;
1226 }
1227 
1228 static inline void getBoothdr(rk_boot_header* hdr) {
1229 	memset(hdr, 0, sizeof(rk_boot_header));
1230 	hdr->tag = TAG;
1231 	hdr->size = sizeof(rk_boot_header);
1232 	hdr->version = (getBCD(gOpts.major) << 8) | getBCD(gOpts.minor);
1233 	hdr->mergerVersion = MERGER_VERSION;
1234 	hdr->releaseTime = getTime();
1235 	hdr->chipType = getChipType(gOpts.chip);
1236 
1237 	hdr->code471Num = gOpts.code471Num;
1238 	hdr->code471Offset = sizeof(rk_boot_header);
1239 	hdr->code471Size = sizeof(rk_boot_entry);
1240 
1241 	hdr->code472Num = gOpts.code472Num;
1242 	hdr->code472Offset = hdr->code471Offset + gOpts.code471Num * hdr->code471Size;
1243 	hdr->code472Size = sizeof(rk_boot_entry);
1244 
1245 	hdr->loaderNum = gOpts.loaderNum;
1246 	hdr->loaderOffset = hdr->code472Offset + gOpts.code472Num * hdr->code472Size;
1247 	hdr->loaderSize = sizeof(rk_boot_entry);
1248 #ifndef USE_P_RC4
1249 	hdr->rc4Flag = 1;
1250 #endif
1251 }
1252 
1253 static inline uint32_t getCrc(const char* path) {
1254 	uint32_t size = 0;
1255 	uint32_t crc = 0;
1256 
1257 	FILE* file = fopen(path, "rb");
1258 	getFileSize(path, &size);
1259 	if (!file)
1260 		goto end;
1261 	if (!fread(gBuf, size, 1, file))
1262 		goto end;
1263 	crc = CRC_32(gBuf, size);
1264 	printf("crc: 0x%08x\n", crc);
1265 end:
1266 	if (file)
1267 		fclose(file);
1268 	return crc;
1269 }
1270 
1271 bool mergeBoot(void) {
1272 	uint32_t dataOffset;
1273 	bool ret = false;
1274 	int i;
1275 	FILE* outFile;
1276 	uint32_t crc;
1277 	rk_boot_header hdr;
1278 
1279 	if (!initOpts())
1280 		return false;
1281 	{
1282 		char* subfix = strstr(gOpts.outPath, OUT_SUBFIX);
1283 		char version[MAX_LINE_LEN];
1284 		snprintf(version, sizeof(version), "%s", gSubfix);
1285 		if (subfix && !strcmp(subfix, OUT_SUBFIX)) {
1286 			subfix[0] = '\0';
1287 		}
1288 		strcat(gOpts.outPath, version);
1289 		printf("fix opt: %s\n", gOpts.outPath);
1290 	}
1291 
1292 	printf("---------------\nUSING CONFIG:\n");
1293 	printOpts(stdout);
1294 	printf("---------------\n\n");
1295 
1296 
1297 	outFile = fopen(gOpts.outPath, "wb+");
1298 	if (!outFile) {
1299 		printf("Opening output file (%s) failed\n", gOpts.outPath);
1300 		goto end;
1301 	}
1302 
1303 	getBoothdr(&hdr);
1304 	printf("Writing header...\n");
1305 	fwrite(&hdr, 1, sizeof(rk_boot_header), outFile);
1306 
1307 	dataOffset = sizeof(rk_boot_header) +
1308 		(gOpts.code471Num + gOpts.code472Num + gOpts.loaderNum) *
1309 		sizeof(rk_boot_entry);
1310 
1311 	printf("Writing code 471 entry...\n");
1312 	for (i=0; i<gOpts.code471Num; i++) {
1313 		if (!saveEntry(outFile, (char*)gOpts.code471Path[i], ENTRY_471, gOpts.code471Sleep,
1314 					&dataOffset, NULL, false))
1315 			goto end;
1316 	}
1317 	printf("Writing code 472 entry...\n");
1318 	for (i=0; i<gOpts.code472Num; i++) {
1319 		if (!saveEntry(outFile, (char*)gOpts.code472Path[i], ENTRY_472, gOpts.code472Sleep,
1320 					&dataOffset, NULL, false))
1321 			goto end;
1322 	}
1323 	printf("Writing loader entry...\n");
1324 	for (i=0; i<gOpts.loaderNum; i++) {
1325 		if (!saveEntry(outFile, gOpts.loader[i].path, ENTRY_LOADER, 0,
1326 					&dataOffset, gOpts.loader[i].name, true))
1327 			goto end;
1328 	}
1329 
1330 	printf("Writing code 471...\n");
1331 	for (i=0; i<gOpts.code471Num; i++) {
1332 		if (!writeFile(outFile, (char*)gOpts.code471Path[i], false))
1333 			goto end;
1334 	}
1335 	printf("Writing code 472...\n");
1336 	for (i=0; i<gOpts.code472Num; i++) {
1337 		if (!writeFile(outFile, (char*)gOpts.code472Path[i], false))
1338 			goto end;
1339 	}
1340 	printf("Writing loader...\n");
1341 	for (i=0; i<gOpts.loaderNum; i++) {
1342 		if (!writeFile(outFile, gOpts.loader[i].path, true))
1343 			goto end;
1344 	}
1345 	fflush(outFile);
1346 
1347 	printf("Writing crc...\n");
1348 	crc = getCrc(gOpts.outPath);
1349 	if (!fwrite(&crc, sizeof(crc), 1, outFile))
1350 		goto end;
1351 	printf("Done.\n");
1352 	ret = true;
1353 end:
1354 	if (outFile)
1355 		fclose(outFile);
1356 	return ret;
1357 }
1358 
1359 /************merge code end************/
1360 /************unpack code***************/
1361 
1362 static inline void wide2str(const uint16_t* wide, char* str, int len)
1363 {
1364 	int i;
1365 	for (i = 0; i < len; i++) {
1366 		str[i] = (char) (wide[i] & 0xFF);
1367 	}
1368 	str[len] = 0;
1369 }
1370 
1371 static bool unpackEntry(rk_boot_entry* entry, const char* name,
1372 		FILE* inFile) {
1373 	bool ret = false;
1374 	int size, i;
1375 	FILE* outFile = fopen(name, "wb+");
1376 	if (!outFile)
1377 		goto end;
1378 	printf("unpacking entry (%s)\n", name);
1379 	fseek(inFile, entry->dataOffset, SEEK_SET);
1380 	size = entry->dataSize;
1381 	if (!fread(gBuf, size, 1, inFile))
1382 		goto end;
1383 	if (entry->type == ENTRY_LOADER) {
1384 		for(i=0; i<size/SMALL_PACKET; i++)
1385 			P_RC4(gBuf + i * SMALL_PACKET, SMALL_PACKET);
1386 		if (size % SMALL_PACKET)
1387 		{
1388 			P_RC4(gBuf + i * SMALL_PACKET, size - SMALL_PACKET * 512);
1389 		}
1390 	} else {
1391 		P_RC4(gBuf, size);
1392 	}
1393 	if (!fwrite(gBuf, size, 1, outFile))
1394 		goto end;
1395 	ret = true;
1396 end:
1397 	if (outFile)
1398 		fclose(outFile);
1399 	return ret;
1400 }
1401 
1402 bool unpackBoot(char* path) {
1403 	bool ret = false;
1404 	FILE* inFile = fopen(path, "rb");
1405 	int entryNum, i;
1406 	char name[MAX_NAME_LEN];
1407 	rk_boot_entry* entrys;
1408 	if (!inFile) {
1409 		fprintf(stderr, "loader (%s) not found\n", path);
1410 		goto end;
1411 	}
1412 
1413 	rk_boot_header hdr;
1414 	if (!fread(&hdr, sizeof(rk_boot_header), 1, inFile)) {
1415 		fprintf(stderr, "reading header failed\n");
1416 		goto end;
1417 	}
1418 	printf("471 num:%d, 472 num:%d, loader num:%d\n", hdr.code471Num, hdr.code472Num, hdr.loaderNum);
1419 	entryNum = hdr.code471Num + hdr.code472Num + hdr.loaderNum;
1420 	entrys = (rk_boot_entry*) malloc(sizeof(rk_boot_entry) * entryNum);
1421 	if (!fread(entrys, sizeof(rk_boot_entry) * entryNum, 1, inFile)) {
1422 		fprintf(stderr, "reading data failed\n");
1423 		goto end;
1424 	}
1425 
1426 	printf("entry num: %d\n", entryNum);
1427 	for (i=0; i<entryNum; i++) {
1428 		wide2str(entrys[i].name, name, MAX_NAME_LEN);
1429 
1430 		printf("entry: t=%d, name=%s, off=%d, size=%d\n",
1431 				entrys[i].type, name, entrys[i].dataOffset,
1432 				entrys[i].dataSize);
1433 		if (!unpackEntry(entrys + i, name, inFile)) {
1434 			fprintf(stderr, "unpacking entry (%s) failed\n", name);
1435 			goto end;
1436 		}
1437 	}
1438 	printf("done\n");
1439 	ret = true;
1440 end:
1441 	if (inFile)
1442 		fclose(inFile);
1443 	return ret;
1444 }
1445 
1446 bool download_boot(STRUCT_RKDEVICE_DESC &dev, char *szLoader)
1447 {
1448 	if (!check_device_type(dev, RKUSB_MASKROM))
1449 		return false;
1450 	CRKImage *pImage = NULL;
1451 	CRKBoot *pBoot = NULL;
1452 	bool bRet, bSuccess = false;
1453 	int iRet;
1454 
1455 	pImage = new CRKImage(szLoader, bRet);
1456 	if (!bRet){
1457 		ERROR_COLOR_ATTR;
1458 		printf("Opening loader failed, exiting download boot!");
1459 		NORMAL_COLOR_ATTR;
1460 		printf("\r\n");
1461 		return bSuccess;
1462 	} else {
1463 		pBoot = (CRKBoot *)pImage->m_bootObject;
1464 		CRKComm *pComm = NULL;
1465 		CRKDevice *pDevice = NULL;
1466 
1467 		dev.emDeviceType = pBoot->SupportDevice;
1468 		pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
1469 		if (!bRet) {
1470 			if (pImage)
1471 				delete pImage;
1472 			ERROR_COLOR_ATTR;
1473 			printf("Creating Comm Object failed!");
1474 			NORMAL_COLOR_ATTR;
1475 			printf("\r\n");
1476 			return bSuccess;
1477 		}
1478 
1479 		pDevice = new CRKDevice(dev);
1480 		if (!pDevice) {
1481 			if (pImage)
1482 				delete pImage;
1483 			if (pComm)
1484 				delete pComm;
1485 			ERROR_COLOR_ATTR;
1486 			printf("Creating device object failed!");
1487 			NORMAL_COLOR_ATTR;
1488 			printf("\r\n");
1489 			return bSuccess;
1490 		}
1491 
1492 		pDevice->SetObject(pImage, pComm, g_pLogObject);
1493 		printf("Downloading bootloader...\r\n");
1494 		iRet = pDevice->DownloadBoot();
1495 
1496 		CURSOR_MOVEUP_LINE(1);
1497 		CURSOR_DEL_LINE;
1498 		if (iRet == 0) {
1499 			bSuccess = true;
1500 			printf("Downloading bootloader succeeded.\r\n");
1501 		}
1502 		else
1503 			printf("Downloading bootloader failed!\r\n");
1504 
1505 		if (pImage)
1506 			delete pImage;
1507 		if(pDevice)
1508 			delete pDevice;
1509 	}
1510 	return bSuccess;
1511 }
1512 bool upgrade_loader(STRUCT_RKDEVICE_DESC &dev, char *szLoader)
1513 {
1514 	if (!check_device_type(dev, RKUSB_MASKROM))
1515 		return false;
1516 	CRKImage *pImage = NULL;
1517 	CRKBoot *pBoot = NULL;
1518 	CRKComm *pComm = NULL;
1519 	bool bRet, bSuccess = false;
1520 	int iRet;
1521 	char index;
1522 	USHORT usFlashDataSec, usFlashBootSec;
1523 	DWORD dwLoaderSize, dwLoaderDataSize, dwDelay, dwSectorNum;
1524 	char loaderCodeName[] = "FlashBoot";
1525 	char loaderDataName[] = "FlashData";
1526 	PBYTE loaderCodeBuffer = NULL;
1527 	PBYTE loaderDataBuffer = NULL;
1528 	PBYTE pIDBData = NULL;
1529 	pImage = new CRKImage(szLoader, bRet);
1530 	if (!bRet){
1531 		ERROR_COLOR_ATTR;
1532 		printf("Opening loader failed, exiting upgrade loader!");
1533 		NORMAL_COLOR_ATTR;
1534 		printf("\r\n");
1535 		goto Exit_UpgradeLoader;
1536 	} else {
1537 		pBoot = (CRKBoot *)pImage->m_bootObject;
1538 		dev.emDeviceType = pBoot->SupportDevice;
1539 		pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
1540 		if (!bRet) {
1541 			ERROR_COLOR_ATTR;
1542 			printf("Creating Comm Object failed!");
1543 			NORMAL_COLOR_ATTR;
1544 			printf("\r\n");
1545 			goto Exit_UpgradeLoader;
1546 		}
1547 
1548 		printf("Upgrading loader...\r\n");
1549 		index = pBoot->GetIndexByName(ENTRYLOADER, loaderCodeName);
1550 		if (index == -1) {
1551 			if (g_pLogObject) {
1552 				g_pLogObject->Record("ERROR: %s --> Get LoaderCode Entry failed", __func__);
1553 			}
1554 			goto Exit_UpgradeLoader;
1555 		}
1556 		bRet = pBoot->GetEntryProperty(ENTRYLOADER, index, dwLoaderSize, dwDelay);
1557 		if (!bRet) {
1558 			if (g_pLogObject) {
1559 				g_pLogObject->Record("ERROR: %s --> Get LoaderCode Entry Size failed", __func__);
1560 			}
1561 			goto Exit_UpgradeLoader;
1562 		}
1563 
1564 		loaderCodeBuffer = new BYTE[dwLoaderSize];
1565 		memset(loaderCodeBuffer, 0, dwLoaderSize);
1566 		if (!pBoot->GetEntryData(ENTRYLOADER, index, loaderCodeBuffer)) {
1567 			if (g_pLogObject) {
1568 				g_pLogObject->Record("ERROR: %s --> Get LoaderCode Data failed", __func__);
1569 			}
1570 			goto Exit_UpgradeLoader;
1571 		}
1572 
1573 		index = pBoot->GetIndexByName(ENTRYLOADER, loaderDataName);
1574 		if (index == -1) {
1575 			if (g_pLogObject) {
1576 				g_pLogObject->Record("ERROR: %s --> Get LoaderData Entry failed", __func__);
1577 			}
1578 			delete []loaderCodeBuffer;
1579 			return -4;
1580 		}
1581 
1582 		bRet = pBoot->GetEntryProperty(ENTRYLOADER, index, dwLoaderDataSize, dwDelay);
1583 		if (!bRet) {
1584 			if (g_pLogObject) {
1585 				g_pLogObject->Record("ERROR: %s --> Get LoaderData Entry Size failed", __func__);
1586 			}
1587 			goto Exit_UpgradeLoader;
1588 		}
1589 
1590 		loaderDataBuffer = new BYTE[dwLoaderDataSize];
1591 		memset(loaderDataBuffer, 0, dwLoaderDataSize);
1592 		if (!pBoot->GetEntryData(ENTRYLOADER,index,loaderDataBuffer)) {
1593 			if (g_pLogObject) {
1594 				g_pLogObject->Record("ERROR: %s --> Get LoaderData Data failed", __func__);
1595 			}
1596 			goto Exit_UpgradeLoader;
1597 		}
1598 
1599 		usFlashDataSec = (ALIGN(dwLoaderDataSize, 2048)) / SECTOR_SIZE;
1600 		usFlashBootSec = (ALIGN(dwLoaderSize, 2048)) / SECTOR_SIZE;
1601 		dwSectorNum = 4 + usFlashDataSec + usFlashBootSec;
1602 		pIDBData = new BYTE[dwSectorNum*SECTOR_SIZE];
1603 		if (!pIDBData) {
1604 			ERROR_COLOR_ATTR;
1605 			printf("Allocating memory failed!");
1606 			NORMAL_COLOR_ATTR;
1607 			printf("\r\n");
1608 			goto Exit_UpgradeLoader;
1609 		}
1610 		memset(pIDBData, 0, dwSectorNum * SECTOR_SIZE);
1611 		iRet = MakeIDBlockData(loaderDataBuffer, loaderCodeBuffer, pIDBData, usFlashDataSec, usFlashBootSec, dwLoaderDataSize, dwLoaderSize);
1612 		if (iRet != 0) {
1613 			ERROR_COLOR_ATTR;
1614 			printf("Making idblock failed!");
1615 			NORMAL_COLOR_ATTR;
1616 			printf("\r\n");
1617 			goto Exit_UpgradeLoader;
1618 		}
1619 		iRet = pComm->RKU_WriteLBA(64, dwSectorNum, pIDBData);
1620 		CURSOR_MOVEUP_LINE(1);
1621 		CURSOR_DEL_LINE;
1622 		if (iRet == ERR_SUCCESS) {
1623 			pComm->Reset_Usb_Device();
1624 			bSuccess = true;
1625 			printf("Upgrading loader succeeded.\r\n");
1626 		} else {
1627 			printf("Upgrading loader failed!\r\n");
1628 			goto Exit_UpgradeLoader;
1629 		}
1630 	}
1631 Exit_UpgradeLoader:
1632 	if (pImage)
1633 		delete pImage;
1634 	if (pComm)
1635 		delete pComm;
1636 	if (loaderCodeBuffer)
1637 		delete []loaderCodeBuffer;
1638 	if (loaderDataBuffer)
1639 		delete []loaderDataBuffer;
1640 	if (pIDBData)
1641 		delete []pIDBData;
1642 	return bSuccess;
1643 }
1644 
1645 bool erase_flash(STRUCT_RKDEVICE_DESC &dev)
1646 {
1647 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1648 		return false;
1649 	CRKImage *pImage = NULL;
1650 	bool bRet, bSuccess = false;
1651 	int iRet;
1652 	CRKScan *pScan = NULL;
1653 	pScan = new CRKScan();
1654 	pScan->SetVidPid();
1655 
1656 	CRKComm *pComm = NULL;
1657 	CRKDevice *pDevice = NULL;
1658 
1659 	pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
1660 	if (!bRet) {
1661 		if (pScan)
1662 			delete pScan;
1663 		ERROR_COLOR_ATTR;
1664 		printf("Creating Comm Object failed!");
1665 		NORMAL_COLOR_ATTR;
1666 		printf("\r\n");
1667 		return bSuccess;
1668 	}
1669 
1670 	pDevice = new CRKDevice(dev);
1671 	if (!pDevice) {
1672 		if (pComm)
1673 			delete pComm;
1674 		if (pScan)
1675 			delete pScan;
1676 		ERROR_COLOR_ATTR;
1677 		printf("Creating device object failed!");
1678 		NORMAL_COLOR_ATTR;
1679 		printf("\r\n");
1680 		return bSuccess;
1681 	}
1682 
1683 	pDevice->SetObject(pImage, pComm, g_pLogObject);
1684 	pDevice->CallBackPointer = ProgressInfoProc;
1685 
1686 	printf("Starting to erase flash...\r\n");
1687 	iRet = pDevice->EraseAllBlocks();
1688 	if (pDevice)
1689 		delete pDevice;
1690 
1691 	if (iRet == 0) {
1692 		if (pScan) {
1693 			pScan->SetVidPid();
1694 			pScan->Wait(dev, RKUSB_MASKROM, dev.usVid, dev.usPid);
1695 			delete pScan;
1696 		}
1697 		CURSOR_MOVEUP_LINE(1);
1698 		CURSOR_DEL_LINE;
1699 		bSuccess = true;
1700 		printf("Erasing flash complete.\r\n");
1701 	}
1702 
1703 	return bSuccess;
1704 }
1705 
1706 bool test_device(STRUCT_RKDEVICE_DESC &dev)
1707 {
1708 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1709 		return false;
1710 	CRKUsbComm *pComm = NULL;
1711 	bool bRet, bSuccess = false;
1712 	int iRet;
1713 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1714 	if (bRet) {
1715 		iRet = pComm->RKU_TestDeviceReady();
1716 		if (iRet != ERR_SUCCESS) {
1717 			if (g_pLogObject)
1718 				g_pLogObject->Record("Error: RKU_TestDeviceReady failed, err=%d", iRet);
1719 			printf("Test Device failed!\r\n");
1720 		} else {
1721 			bSuccess = true;
1722 			printf("Test Device OK.\r\n");
1723 		}
1724 	} else {
1725 		printf("Test Device quit, creating comm object failed!\r\n");
1726 	}
1727 	if (pComm) {
1728 		delete pComm;
1729 		pComm = NULL;
1730 	}
1731 	return bSuccess;
1732 }
1733 bool reset_device(STRUCT_RKDEVICE_DESC &dev, BYTE subCode = RST_NONE_SUBCODE)
1734 {
1735 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1736 		return false;
1737 	CRKUsbComm *pComm = NULL;
1738 	bool bRet, bSuccess = false;
1739 	int iRet;
1740 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1741 	if (bRet) {
1742 		iRet = pComm->RKU_ResetDevice(subCode);
1743 		if (iRet != ERR_SUCCESS) {
1744 			if (g_pLogObject)
1745 				g_pLogObject->Record("Error: RKU_ResetDevice failed, err=%d", iRet);
1746 			printf("Reset Device failed!\r\n");
1747 		} else {
1748 			bSuccess = true;
1749 			printf("Reset Device OK.\r\n");
1750 		}
1751 	} else {
1752 		printf("Reset Device quit, creating comm object failed!\r\n");
1753 	}
1754 	if (pComm) {
1755 		delete pComm;
1756 		pComm = NULL;
1757 	}
1758 	return bSuccess;
1759 }
1760 
1761 bool read_flash_id(STRUCT_RKDEVICE_DESC &dev)
1762 {
1763 	CRKUsbComm *pComm = NULL;
1764 	bool bRet, bSuccess = false;
1765 	int iRet;
1766 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1767 		return bSuccess;
1768 
1769 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1770 	if (bRet) {
1771 		BYTE flashID[5];
1772 		iRet = pComm->RKU_ReadFlashID(flashID);
1773 		if (iRet != ERR_SUCCESS) {
1774 			if (g_pLogObject)
1775 				g_pLogObject->Record("Error: RKU_ReadFlashID failed, err=%d", iRet);
1776 			printf("Reading flash ID failed!\r\n");
1777 		} else {
1778 			printf("Flash ID: %02X %02X %02X %02X %02X\r\n", flashID[0], flashID[1], flashID[2], flashID[3], flashID[4]);
1779 			bSuccess = true;
1780 		}
1781 	} else {
1782 		printf("Read Flash ID quit, creating comm object failed!\r\n");
1783 	}
1784 	if (pComm) {
1785 		delete pComm;
1786 		pComm = NULL;
1787 	}
1788 	return bSuccess;
1789 }
1790 bool read_flash_info(STRUCT_RKDEVICE_DESC &dev)
1791 {
1792 	CRKUsbComm *pComm = NULL;
1793 	bool bRet, bSuccess = false;
1794 	int iRet;
1795 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1796 		return bSuccess;
1797 
1798 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1799 	if (bRet) {
1800 		STRUCT_FLASHINFO_CMD info;
1801 		UINT uiRead;
1802 		iRet = pComm->RKU_ReadFlashInfo((BYTE *)&info, &uiRead);
1803 		if (iRet != ERR_SUCCESS) {
1804 			if (g_pLogObject)
1805 				g_pLogObject->Record("Error: RKU_ReadFlashInfo failed, err=%d", iRet);
1806 			printf("Read Flash Info failed!\r\n");
1807 		} else {
1808 			printf("Flash Info:\r\n");
1809 			if (info.bManufCode <= 7) {
1810 				printf("\tManufacturer: %s, value=%02X\r\n", szManufName[info.bManufCode], info.bManufCode);
1811 			}
1812 			else
1813 				printf("\tManufacturer: %s, value=%02X\r\n", "Unknown", info.bManufCode);
1814 
1815 			printf("\tFlash Size: %d MB\r\n", info.uiFlashSize / 2 / 1024);
1816 			printf("\tBlock Size: %d KB\r\n", info.usBlockSize / 2);
1817 			printf("\tPage Size: %d KB\r\n", info.bPageSize / 2);
1818 			printf("\tECC Bits: %d\r\n", info.bECCBits);
1819 			printf("\tAccess Time: %d\r\n", info.bAccessTime);
1820 			printf("\tFlash CS: ");
1821 			for(int i = 0; i < 8; i++) {
1822 				if( info.bFlashCS & (1 << i) )
1823 					printf("Flash<%d> ", i);
1824 			}
1825 			printf("\r\n");
1826 			bSuccess = true;
1827 		}
1828 	}else {
1829 		printf("Read Flash Info quit, creating comm object failed!\r\n");
1830 	}
1831 	if (pComm) {
1832 		delete pComm;
1833 		pComm = NULL;
1834 	}
1835 	return bSuccess;
1836 }
1837 bool read_chip_info(STRUCT_RKDEVICE_DESC &dev)
1838 {
1839 	CRKUsbComm *pComm = NULL;
1840 	bool bRet, bSuccess = false;
1841 	int iRet;
1842 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1843 		return bSuccess;
1844 
1845 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1846 	if (bRet) {
1847 		BYTE chipInfo[16];
1848 		iRet = pComm->RKU_ReadChipInfo(chipInfo);
1849 		if (iRet != ERR_SUCCESS) {
1850 			if (g_pLogObject)
1851 				g_pLogObject->Record("Error: RKU_ReadChipInfo failed, err=%d", iRet);
1852 			printf("Read Chip Info failed!\r\n");
1853 		} else {
1854 			string strChipInfo;
1855 			g_pLogObject->PrintBuffer(strChipInfo, chipInfo, 16, 16);
1856 			printf("Chip Info: %s\r\n", strChipInfo.c_str());
1857 			bSuccess = true;
1858 		}
1859 	} else {
1860 		printf("Read Chip Info quit, creating comm object failed!\r\n");
1861 	}
1862 	if (pComm) {
1863 		delete pComm;
1864 		pComm = NULL;
1865 	}
1866 	return bSuccess;
1867 }
1868 bool read_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, UINT uiLen, char *szFile)
1869 {
1870 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1871 		return false;
1872 	CRKUsbComm *pComm = NULL;
1873 	FILE *file = NULL;
1874 	bool bRet, bFirst = true, bSuccess = false;
1875 	int iRet;
1876 	UINT iTotalRead = 0,iRead = 0;
1877 	int nSectorSize = 512;
1878 	BYTE pBuf[nSectorSize * DEFAULT_RW_LBA];
1879 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1880 	if (bRet) {
1881 		if(szFile) {
1882 			file = fopen(szFile, "wb+");
1883 			if( !file ) {
1884 				printf("Read LBA failed, err=%d, can't open file: %s\r\n", errno, szFile);
1885 				goto Exit_ReadLBA;
1886 			}
1887 		}
1888 
1889 		while(uiLen > 0) {
1890 			memset(pBuf, 0, nSectorSize * DEFAULT_RW_LBA);
1891 			iRead = (uiLen >= DEFAULT_RW_LBA) ? DEFAULT_RW_LBA : uiLen;
1892 			iRet = pComm->RKU_ReadLBA( uiBegin + iTotalRead, iRead, pBuf);
1893 			if(ERR_SUCCESS == iRet) {
1894 				uiLen -= iRead;
1895 				iTotalRead += iRead;
1896 
1897 				if(szFile) {
1898 					fwrite(pBuf, 1, iRead * nSectorSize, file);
1899 					if (bFirst){
1900 						if (iTotalRead >= 1024)
1901 							printf("Read LBA to file (%d%%)\r\n", (iTotalRead / 1024) * 100 / ((uiLen + iTotalRead) / 1024));
1902 						else
1903 							printf("Read LBA to file (%d%%)\r\n", iTotalRead * 100 / (uiLen + iTotalRead));
1904 						bFirst = false;
1905 					} else {
1906 						CURSOR_MOVEUP_LINE(1);
1907 						CURSOR_DEL_LINE;
1908 						if (iTotalRead >= 1024)
1909 							printf("Read LBA to file (%d%%)\r\n", (iTotalRead / 1024) * 100 / ((uiLen + iTotalRead) / 1024));
1910 						else
1911 							printf("Read LBA to file (%d%%)\r\n", iTotalRead * 100 / (uiLen + iTotalRead));
1912 					}
1913 				}
1914 				else
1915 					PrintData(pBuf, nSectorSize * iRead);
1916 			} else {
1917 				if (g_pLogObject)
1918 					g_pLogObject->Record("Error: RKU_ReadLBA failed, err=%d", iRet);
1919 
1920 				printf("Read LBA failed!\r\n");
1921 				goto Exit_ReadLBA;
1922 			}
1923 		}
1924 		bSuccess = true;
1925 	} else {
1926 		printf("Read LBA quit, creating comm object failed!\r\n");
1927 	}
1928 Exit_ReadLBA:
1929 	if (pComm) {
1930 		delete pComm;
1931 		pComm = NULL;
1932 	}
1933 	if (file)
1934 		fclose(file);
1935 	return bSuccess;
1936 }
1937 bool write_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, char *szFile)
1938 {
1939 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1940 		return false;
1941 	CRKUsbComm *pComm = NULL;
1942 	FILE *file = NULL;
1943 	bool bRet, bFirst = true, bSuccess = false;
1944 	int iRet;
1945 	long long iTotalWrite = 0, iFileSize = 0;
1946 	UINT iWrite = 0, iRead = 0;
1947 	UINT uiLen;
1948 	int nSectorSize = 512;
1949 	BYTE pBuf[nSectorSize * DEFAULT_RW_LBA];
1950 
1951 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1952 	if (bRet) {
1953 		file = fopen(szFile, "rb");
1954 		if( !file ) {
1955 			printf("Write LBA failed, err=%d, can't open file: %s\r\n", errno, szFile);
1956 			goto Exit_WriteLBA;
1957 		}
1958 
1959 		iRet = fseeko(file, 0, SEEK_END);
1960 		iFileSize = ftello(file);
1961 		fseeko(file, 0, SEEK_SET);
1962 		while(iTotalWrite < iFileSize) {
1963 			memset(pBuf, 0, nSectorSize * DEFAULT_RW_LBA);
1964 			iWrite = iRead= fread(pBuf, 1, nSectorSize * DEFAULT_RW_LBA, file);
1965 			uiLen = ((iWrite % 512) == 0) ? (iWrite / 512) : (iWrite / 512 + 1);
1966 			iRet = pComm->RKU_WriteLBA( uiBegin, uiLen, pBuf);
1967 			if(ERR_SUCCESS == iRet) {
1968 				uiBegin += uiLen;
1969 				iTotalWrite += iWrite;
1970 				if (bFirst) {
1971 					if (iTotalWrite >= 1024)
1972 						printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
1973 					else
1974 						printf("Write LBA from file (%lld%%)\r\n", iTotalWrite * 100 / iFileSize);
1975 					bFirst = false;
1976 				} else {
1977 					CURSOR_MOVEUP_LINE(1);
1978 					CURSOR_DEL_LINE;
1979 					printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
1980 				}
1981 			} else {
1982 				if (g_pLogObject)
1983 					g_pLogObject->Record("Error: RKU_WriteLBA failed, err=%d", iRet);
1984 
1985 				printf("Write LBA failed!\r\n");
1986 				goto Exit_WriteLBA;
1987 			}
1988 		}
1989 		bSuccess = true;
1990 	} else {
1991 		printf("Write LBA quit, creating comm object failed!\r\n");
1992 	}
1993 Exit_WriteLBA:
1994 	if (pComm) {
1995 		delete pComm;
1996 		pComm = NULL;
1997 	}
1998 	if (file)
1999 		fclose(file);
2000 	return bSuccess;
2001 }
2002 
2003 void split_item(STRING_VECTOR &vecItems, char *pszItems)
2004 {
2005 	string strItem;
2006 	char szItem[100];
2007 	char *pos = NULL, *pStart;
2008 	pStart = pszItems;
2009 	pos = strchr(pStart, ',');
2010 	while(pos != NULL) {
2011 		memset(szItem, 0, 100);
2012 		strncpy(szItem, pStart, pos - pStart);
2013 		strItem = szItem;
2014 		vecItems.push_back(strItem);
2015 		pStart = pos + 1;
2016 		if (*pStart == 0)
2017 			break;
2018 		pos = strchr(pStart, ',');
2019 	}
2020 	if (strlen(pStart) > 0) {
2021 		memset(szItem, 0, 100);
2022 		strncpy(szItem, pStart, strlen(pStart));
2023 		strItem = szItem;
2024 		vecItems.push_back(strItem);
2025 	}
2026 }
2027 
2028 void tag_spl(char *tag, char *spl)
2029 {
2030 	FILE *file = NULL;
2031 	int len;
2032 
2033 	if(!tag || !spl)
2034 		return;
2035 	len = strlen(tag);
2036 	printf("tag len=%d\n",len);
2037 	file = fopen(spl, "rb");
2038 	if( !file ){
2039 		return;
2040 	}
2041 	int iFileSize;
2042 	fseek(file, 0, SEEK_END);
2043 	iFileSize = ftell(file);
2044 	fseek(file, 0, SEEK_SET);
2045 	char *Buf = NULL;
2046 	Buf = new char[iFileSize + len + 1];
2047 	if (!Buf){
2048 		fclose(file);
2049 		return;
2050 	}
2051 	memset(Buf, 0, iFileSize + 1);
2052 	memcpy(Buf, tag, len);
2053 	int iRead;
2054 	iRead = fread(Buf+len, 1, iFileSize, file);
2055 	if (iRead != iFileSize){
2056 		fclose(file);
2057 		delete []Buf;
2058 		return;
2059 	}
2060 	fclose(file);
2061 
2062 	len = strlen(spl);
2063 	char *taggedspl = new char[len + 5];
2064 	strcpy(taggedspl, spl);
2065 	strcpy(taggedspl + len, ".tag");
2066 	taggedspl[len+4] = 0;
2067 	printf("Writing tagged spl to %s\n", taggedspl);
2068 
2069 	file = fopen(taggedspl, "wb");
2070 	if( !file ){
2071 		delete []taggedspl;
2072 		delete []Buf;
2073 		return;
2074 	}
2075 	fwrite(Buf, 1, iFileSize+len, file);
2076 	fclose(file);
2077 	delete []taggedspl;
2078 	delete []Buf;
2079 	printf("done\n");
2080 	return;
2081 }
2082 
2083 bool handle_command(int argc, char* argv[], CRKScan *pScan)
2084 {
2085 	string strCmd;
2086 	strCmd = argv[1];
2087 	ssize_t cnt;
2088 	bool bRet,bSuccess = false;
2089 	char *s;
2090 	int i, ret;
2091 	STRUCT_RKDEVICE_DESC dev;
2092 
2093 	transform(strCmd.begin(), strCmd.end(), strCmd.begin(), (int(*)(int))toupper);
2094 	s = (char*)strCmd.c_str();
2095 	for(i = 0; i < (int)strlen(s); i++)
2096 	        s[i] = toupper(s[i]);
2097 
2098 	if((strcmp(strCmd.c_str(), "-H") == 0) || (strcmp(strCmd.c_str(), "--HELP")) == 0){
2099 		usage();
2100 		return true;
2101 	} else if((strcmp(strCmd.c_str(), "-V") == 0) || (strcmp(strCmd.c_str(), "--VERSION") == 0)) {
2102 		printf("rkdeveloptool ver %s\r\n", PACKAGE_VERSION);
2103 		return true;
2104 	} else if (strcmp(strCmd.c_str(), "PACK") == 0) {//pack boot loader
2105 		mergeBoot();
2106 
2107 		return true;
2108 	} else if (strcmp(strCmd.c_str(), "UNPACK") == 0) {//unpack boot loader
2109 		string strLoader = argv[2];
2110 
2111 		unpackBoot((char*)strLoader.c_str());
2112 		return true;
2113 	} else if (strcmp(strCmd.c_str(), "TAGSPL") == 0) {//tag u-boot spl
2114 		if (argc == 4) {
2115 			string tag = argv[2];
2116 			string spl = argv[3];
2117 			printf("tag %s to %s\n", tag.c_str(), spl.c_str());
2118 			tag_spl((char*)tag.c_str(), (char*)spl.c_str());
2119 			return true;
2120 		}
2121 		printf("tagspl: parameter error\n");
2122 		usage();
2123 	}
2124 	cnt = pScan->Search(RKUSB_MASKROM | RKUSB_LOADER);
2125 	if (cnt < 1) {
2126 		ERROR_COLOR_ATTR;
2127 		printf("Did not find any rockusb device, please plug device in!");
2128 		NORMAL_COLOR_ATTR;
2129 		printf("\r\n");
2130 		return bSuccess;
2131 	} else if (cnt > 1) {
2132 		ERROR_COLOR_ATTR;
2133 		printf("Found too many rockusb devices, please plug devices out!");
2134 		NORMAL_COLOR_ATTR;
2135 		printf("\r\n");
2136 		return bSuccess;
2137 	}
2138 
2139 	bRet = pScan->GetDevice(dev, 0);
2140 	if (!bRet) {
2141 		ERROR_COLOR_ATTR;
2142 		printf("Getting information about rockusb device failed!");
2143 		NORMAL_COLOR_ATTR;
2144 		printf("\r\n");
2145 		return bSuccess;
2146 	}
2147 
2148 	if(strcmp(strCmd.c_str(), "RD") == 0) {
2149 		if ((argc != 2) && (argc != 3))
2150 			printf("Parameter of [RD] command is invalid, please check help!\r\n");
2151 		else {
2152 			if (argc == 2)
2153 				bSuccess = reset_device(dev);
2154 			else {
2155 				UINT uiSubCode;
2156 				char *pszEnd;
2157 				uiSubCode = strtoul(argv[2], &pszEnd, 0);
2158 				if (*pszEnd)
2159 					printf("Subcode is invalid, please check!\r\n");
2160 				else {
2161 					if (uiSubCode <= 5)
2162 						bSuccess = reset_device(dev, uiSubCode);
2163 					else
2164 						printf("Subcode is invalid, please check!\r\n");
2165 				}
2166 			}
2167 		}
2168 	} else if(strcmp(strCmd.c_str(), "TD") == 0) {
2169 		bSuccess = test_device(dev);
2170 	} else if (strcmp(strCmd.c_str(), "RID") == 0) {//Read Flash ID
2171 		bSuccess = read_flash_id(dev);
2172 	} else if (strcmp(strCmd.c_str(), "RFI") == 0){//Read Flash Info
2173 		bSuccess = read_flash_info(dev);
2174 	} else if (strcmp(strCmd.c_str(), "RCI") == 0) {//Read Chip Info
2175 		bSuccess = read_chip_info(dev);
2176 	} else if(strcmp(strCmd.c_str(), "DB") == 0) {
2177 		if (argc > 2) {
2178 			string strLoader;
2179 			strLoader = argv[2];
2180 			bSuccess = download_boot(dev, (char *)strLoader.c_str());
2181 		} else if (argc == 2) {
2182 			ret = find_config_item("loader");
2183 			if (ret == -1)
2184 				printf("Did not find loader item in config!\r\n");
2185 			else
2186 				bSuccess = download_boot(dev, g_ConfigItemVec[ret].szItemValue);
2187 		} else
2188 			printf("Parameter of [DB] command is invalid, please check help!\r\n");
2189 	} else if(strcmp(strCmd.c_str(), "GPT") == 0) {
2190 		if (argc > 2) {
2191 			string strParameter;
2192 			strParameter = argv[2];
2193 			bSuccess = write_gpt(dev, (char *)strParameter.c_str());
2194 		} else
2195 			printf("Parameter of [GPT] command is invalid, please check help!\r\n");
2196 	} else if(strcmp(strCmd.c_str(), "UL") == 0) {
2197 		if (argc > 2) {
2198 			string strLoader;
2199 			strLoader = argv[2];
2200 			bSuccess = upgrade_loader(dev, (char *)strLoader.c_str());
2201 		} else
2202 			printf("Parameter of [UL] command is invalid, please check help!\r\n");
2203 	} else if(strcmp(strCmd.c_str(), "EF") == 0) {
2204 		if (argc == 2) {
2205 			bSuccess = erase_flash(dev);
2206 		} else
2207 			printf("Parameter of [EF] command is invalid, please check help!\r\n");
2208 	} else if(strcmp(strCmd.c_str(), "WL") == 0) {
2209 		if (argc == 4) {
2210 			UINT uiBegin;
2211 			char *pszEnd;
2212 			uiBegin = strtoul(argv[2], &pszEnd, 0);
2213 			if (*pszEnd)
2214 				printf("Begin is invalid, please check!\r\n");
2215 			else
2216 				bSuccess = write_lba(dev, uiBegin, argv[3]);
2217 		} else
2218 			printf("Parameter of [WL] command is invalid, please check help!\r\n");
2219 	} else if (strcmp(strCmd.c_str(), "RL") == 0) {//Read LBA
2220 		char *pszEnd;
2221 		UINT uiBegin, uiLen;
2222 		if (argc != 5)
2223 			printf("Parameter of [RL] command is invalid, please check help!\r\n");
2224 		else {
2225 			uiBegin = strtoul(argv[2], &pszEnd, 0);
2226 			if (*pszEnd)
2227 				printf("Begin is invalid, please check!\r\n");
2228 			else {
2229 				uiLen = strtoul(argv[3], &pszEnd, 0);
2230 				if (*pszEnd)
2231 					printf("Len is invalid, please check!\r\n");
2232 				else {
2233 					bSuccess = read_lba(dev, uiBegin, uiLen, argv[4]);
2234 				}
2235 			}
2236 		}
2237 	} else {
2238 		printf("command is invalid!\r\n");
2239 		usage();
2240 	}
2241 	return bSuccess;
2242 }
2243 
2244 
2245 int main(int argc, char* argv[])
2246 {
2247 	CRKScan *pScan = NULL;
2248 	int ret;
2249 	char szProgramProcPath[100];
2250 	char szProgramDir[256];
2251 	string strLogDir,strConfigFile;
2252 	struct stat statBuf;
2253 
2254 	g_ConfigItemVec.clear();
2255 	sprintf(szProgramProcPath, "/proc/%d/exe", getpid());
2256 	if (readlink(szProgramProcPath, szProgramDir, 256) == -1)
2257 		strcpy(szProgramDir, ".");
2258 	else {
2259 		char *pSlash;
2260 		pSlash = strrchr(szProgramDir, '/');
2261 		if (pSlash)
2262 			*pSlash = '\0';
2263 	}
2264 	strLogDir = szProgramDir;
2265 	strLogDir +=  "/log/";
2266 	strConfigFile = szProgramDir;
2267 	strConfigFile += "/config.ini";
2268 	if (opendir(strLogDir.c_str()) == NULL)
2269 		mkdir(strLogDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH);
2270 	g_pLogObject = new CRKLog(strLogDir.c_str(), "log",true);
2271 
2272 	if(stat(strConfigFile.c_str(), &statBuf) < 0) {
2273 		if (g_pLogObject) {
2274 			g_pLogObject->Record("Error: failed to stat config.ini, err=%d", errno);
2275 		}
2276 	} else if (S_ISREG(statBuf.st_mode)) {
2277 		parse_config_file(strConfigFile.c_str(), g_ConfigItemVec);
2278 	}
2279 
2280 	ret = libusb_init(NULL);
2281 	if (ret < 0) {
2282 		if (g_pLogObject) {
2283 			g_pLogObject->Record("Error: libusb_init failed, err=%d", ret);
2284 			delete g_pLogObject;
2285 		}
2286 		return -1;
2287 	}
2288 
2289 	pScan = new CRKScan();
2290 	if (!pScan) {
2291 		if (g_pLogObject) {
2292 			g_pLogObject->Record("Error: failed to create object for searching device");
2293 			delete g_pLogObject;
2294 		}
2295 		libusb_exit(NULL);
2296 		return -2;
2297 	}
2298 	pScan->SetVidPid();
2299 
2300 	if (argc == 1)
2301 		usage();
2302 	else if (!handle_command(argc, argv, pScan))
2303 			return -0xFF;
2304 	if (pScan)
2305 		delete pScan;
2306 	if (g_pLogObject)
2307 		delete g_pLogObject;
2308 	libusb_exit(NULL);
2309 	return 0;
2310 }
2311