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