xref: /rkdeveloptool/main.cpp (revision 055958c9e7f983929e65c6b87c5ad522fdf678ed)
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 || (end < start))
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 	uint32_t size;
1148 	rk_boot_entry entry;
1149 
1150 	printf("write:%s\n", path);
1151 	memset(&entry, 0, sizeof(rk_boot_entry));
1152 	getName(fixName ? fixName: path, entry.name);
1153 	entry.size = sizeof(rk_boot_entry);
1154 	entry.type = type;
1155 	entry.dataOffset = *offset;
1156 	if (!getFileSize(path, &size)) {
1157 		printf("save entry(%s) failed:\n\tcannot get file size.\n", path);
1158 		return false;
1159 	}
1160 	if (fix)
1161 		size = ((size - 1) / SMALL_PACKET + 1) * SMALL_PACKET;
1162 	uint32_t tmp = size % ENTRY_ALIGN;
1163 	size += tmp ? (ENTRY_ALIGN - tmp): 0;
1164 	printf("align size:%d\n", size);
1165 	entry.dataSize = size;
1166 	entry.dataDelay = delay;
1167 	*offset += size;
1168 	fwrite(&entry, sizeof(rk_boot_entry), 1, outFile);
1169 	return true;
1170 }
1171 
1172 static inline uint32_t convertChipType(const char* chip) {
1173 	char buffer[5];
1174 	memset(buffer, 0, sizeof(buffer));
1175 	snprintf(buffer, sizeof(buffer), "%s", chip);
1176 	return buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
1177 }
1178 
1179 static inline uint32_t getChipType(const char* chip) {
1180 	printf("chip:%s\n", chip);
1181 	int chipType = RKNONE_DEVICE;
1182 	if(!chip) {
1183 		goto end;
1184 	}
1185 	if (!strcmp(chip, CHIP_RK28)) {
1186 		chipType = RK28_DEVICE;
1187 	} else if (!strcmp(chip, CHIP_RK28)) {
1188 		chipType = RK28_DEVICE;
1189 	} else if (!strcmp(chip, CHIP_RK281X)) {
1190 		chipType = RK281X_DEVICE;
1191 	} else if (!strcmp(chip, CHIP_RKPANDA)) {
1192 		chipType = RKPANDA_DEVICE;
1193 	} else if (!strcmp(chip, CHIP_RK27)) {
1194 		chipType = RK27_DEVICE;
1195 	} else if (!strcmp(chip, CHIP_RKNANO)) {
1196 		chipType = RKNANO_DEVICE;
1197 	} else if (!strcmp(chip, CHIP_RKSMART)) {
1198 		chipType = RKSMART_DEVICE;
1199 	} else if (!strcmp(chip, CHIP_RKCROWN)) {
1200 		chipType = RKCROWN_DEVICE;
1201 	} else if (!strcmp(chip, CHIP_RKCAYMAN)) {
1202 		chipType = RKCAYMAN_DEVICE;
1203 	} else if (!strcmp(chip, CHIP_RK29)) {
1204 		chipType = RK29_DEVICE;
1205 	} else if (!strcmp(chip, CHIP_RK292X)) {
1206 		chipType = RK292X_DEVICE;
1207 	} else if (!strcmp(chip, CHIP_RK30)) {
1208 		chipType = RK30_DEVICE;
1209 	} else if (!strcmp(chip, CHIP_RK30B)) {
1210 		chipType = RK30B_DEVICE;
1211 	} else if (!strcmp(chip, CHIP_RK31)) {
1212 		chipType = RK31_DEVICE;
1213 	} else if (!strcmp(chip, CHIP_RK32)) {
1214 		chipType = RK32_DEVICE;
1215 	} else {
1216 		chipType = convertChipType(chip + 2);
1217 	}
1218 
1219 end:
1220 	printf("type:0x%x\n", chipType);
1221 	if (chipType == RKNONE_DEVICE) {
1222 		printf("chip type not support!\n");
1223 	}
1224 	return chipType;
1225 }
1226 
1227 static inline void getBoothdr(rk_boot_header* hdr) {
1228 	memset(hdr, 0, sizeof(rk_boot_header));
1229 	hdr->tag = TAG;
1230 	hdr->size = sizeof(rk_boot_header);
1231 	hdr->version = (getBCD(gOpts.major) << 8) | getBCD(gOpts.minor);
1232 	hdr->mergerVersion = MERGER_VERSION;
1233 	hdr->releaseTime = getTime();
1234 	hdr->chipType = getChipType(gOpts.chip);
1235 
1236 	hdr->code471Num = gOpts.code471Num;
1237 	hdr->code471Offset = sizeof(rk_boot_header);
1238 	hdr->code471Size = sizeof(rk_boot_entry);
1239 
1240 	hdr->code472Num = gOpts.code472Num;
1241 	hdr->code472Offset = hdr->code471Offset + gOpts.code471Num * hdr->code471Size;
1242 	hdr->code472Size = sizeof(rk_boot_entry);
1243 
1244 	hdr->loaderNum = gOpts.loaderNum;
1245 	hdr->loaderOffset = hdr->code472Offset + gOpts.code472Num * hdr->code472Size;
1246 	hdr->loaderSize = sizeof(rk_boot_entry);
1247 #ifndef USE_P_RC4
1248 	hdr->rc4Flag = 1;
1249 #endif
1250 }
1251 
1252 static inline uint32_t getCrc(const char* path) {
1253 	uint32_t size = 0;
1254 	uint32_t crc = 0;
1255 
1256 	FILE* file = fopen(path, "rb");
1257 	getFileSize(path, &size);
1258 	if (!file)
1259 		goto end;
1260 	if (!fread(gBuf, size, 1, file))
1261 		goto end;
1262 	crc = CRC_32(gBuf, size);
1263 	printf("crc:0x%08x\n", crc);
1264 end:
1265 	if (file)
1266 		fclose(file);
1267 	return crc;
1268 }
1269 
1270 bool mergeBoot(void) {
1271 	uint32_t dataOffset;
1272 	bool ret = false;
1273 	int i;
1274 	FILE* outFile;
1275 	uint32_t crc;
1276 	rk_boot_header hdr;
1277 
1278 	if (!initOpts())
1279 		return false;
1280 	{
1281 		char* subfix = strstr(gOpts.outPath, OUT_SUBFIX);
1282 		char version[MAX_LINE_LEN];
1283 		snprintf(version, sizeof(version), "%s", gSubfix);
1284 		if (subfix && !strcmp(subfix, OUT_SUBFIX)) {
1285 			subfix[0] = '\0';
1286 		}
1287 		strcat(gOpts.outPath, version);
1288 		printf("fix opt:%s\n", gOpts.outPath);
1289 	}
1290 
1291 	printf("---------------\nUSING CONFIG:\n");
1292 	printOpts(stdout);
1293 	printf("---------------\n\n");
1294 
1295 
1296 	outFile = fopen(gOpts.outPath, "wb+");
1297 	if (!outFile) {
1298 		printf("open out file(%s) failed\n", gOpts.outPath);
1299 		goto end;
1300 	}
1301 
1302 	getBoothdr(&hdr);
1303 	printf("write hdr\n");
1304 	fwrite(&hdr, 1, sizeof(rk_boot_header), outFile);
1305 
1306 	dataOffset = sizeof(rk_boot_header) +
1307 		(gOpts.code471Num + gOpts.code472Num + gOpts.loaderNum) *
1308 		sizeof(rk_boot_entry);
1309 
1310 	printf("write code 471 entry\n");
1311 	for (i=0; i<gOpts.code471Num; i++) {
1312 		if (!saveEntry(outFile, (char*)gOpts.code471Path[i], ENTRY_471, gOpts.code471Sleep,
1313 					&dataOffset, NULL, false))
1314 			goto end;
1315 	}
1316 	printf("write code 472 entry\n");
1317 	for (i=0; i<gOpts.code472Num; i++) {
1318 		if (!saveEntry(outFile, (char*)gOpts.code472Path[i], ENTRY_472, gOpts.code472Sleep,
1319 					&dataOffset, NULL, false))
1320 			goto end;
1321 	}
1322 	printf("write loader entry\n");
1323 	for (i=0; i<gOpts.loaderNum; i++) {
1324 		if (!saveEntry(outFile, gOpts.loader[i].path, ENTRY_LOADER, 0,
1325 					&dataOffset, gOpts.loader[i].name, true))
1326 			goto end;
1327 	}
1328 
1329 	printf("write code 471\n");
1330 	for (i=0; i<gOpts.code471Num; i++) {
1331 		if (!writeFile(outFile, (char*)gOpts.code471Path[i], false))
1332 			goto end;
1333 	}
1334 	printf("write code 472\n");
1335 	for (i=0; i<gOpts.code472Num; i++) {
1336 		if (!writeFile(outFile, (char*)gOpts.code472Path[i], false))
1337 			goto end;
1338 	}
1339 	printf("write loader\n");
1340 	for (i=0; i<gOpts.loaderNum; i++) {
1341 		if (!writeFile(outFile, gOpts.loader[i].path, true))
1342 			goto end;
1343 	}
1344 	fflush(outFile);
1345 
1346 	printf("write crc\n");
1347 	crc = getCrc(gOpts.outPath);
1348 	if (!fwrite(&crc, sizeof(crc), 1, outFile))
1349 		goto end;
1350 	printf("done\n");
1351 	ret = true;
1352 end:
1353 	if (outFile)
1354 		fclose(outFile);
1355 	return ret;
1356 }
1357 
1358 /************merge code end************/
1359 /************unpack code***************/
1360 
1361 static inline void wide2str(const uint16_t* wide, char* str, int len)
1362 {
1363 	int i;
1364 	for (i = 0; i < len; i++) {
1365 		str[i] = (char) (wide[i] & 0xFF);
1366 	}
1367 	str[len] = 0;
1368 }
1369 
1370 static bool unpackEntry(rk_boot_entry* entry, const char* name,
1371 		FILE* inFile) {
1372 	bool ret = false;
1373 	int size, i;
1374 	FILE* outFile = fopen(name, "wb+");
1375 	if (!outFile)
1376 		goto end;
1377 	printf("unpack entry(%s)\n", name);
1378 	fseek(inFile, entry->dataOffset, SEEK_SET);
1379 	size = entry->dataSize;
1380 	if (!fread(gBuf, size, 1, inFile))
1381 		goto end;
1382 	if (entry->type == ENTRY_LOADER) {
1383 		for(i=0; i<size/SMALL_PACKET; i++)
1384 			P_RC4(gBuf + i * SMALL_PACKET, SMALL_PACKET);
1385 		if (size % SMALL_PACKET)
1386 		{
1387 			P_RC4(gBuf + i * SMALL_PACKET, size - SMALL_PACKET * 512);
1388 		}
1389 	} else {
1390 		P_RC4(gBuf, size);
1391 	}
1392 	if (!fwrite(gBuf, size, 1, outFile))
1393 		goto end;
1394 	ret = true;
1395 end:
1396 	if (outFile)
1397 		fclose(outFile);
1398 	return ret;
1399 }
1400 
1401 bool unpackBoot(char* path) {
1402 	bool ret = false;
1403 	FILE* inFile = fopen(path, "rb");
1404 	int entryNum, i;
1405 	char name[MAX_NAME_LEN];
1406 	rk_boot_entry* entrys;
1407 	if (!inFile) {
1408 		fprintf(stderr, "loader(%s) not found\n", path);
1409 		goto end;
1410 	}
1411 
1412 	rk_boot_header hdr;
1413 	if (!fread(&hdr, sizeof(rk_boot_header), 1, inFile)) {
1414 		fprintf(stderr, "read header failed\n");
1415 		goto end;
1416 	}
1417 	printf("471 num:%d, 472 num:%d, loader num:%d\n", hdr.code471Num, hdr.code472Num, hdr.loaderNum);
1418 	entryNum = hdr.code471Num + hdr.code472Num + hdr.loaderNum;
1419 	entrys = (rk_boot_entry*) malloc(sizeof(rk_boot_entry) * entryNum);
1420 	if (!fread(entrys, sizeof(rk_boot_entry) * entryNum, 1, inFile)) {
1421 		fprintf(stderr, "read data failed\n");
1422 		goto end;
1423 	}
1424 
1425 	printf("entry num:%d\n", entryNum);
1426 	for (i=0; i<entryNum; i++) {
1427 		wide2str(entrys[i].name, name, MAX_NAME_LEN);
1428 
1429 		printf("entry:t=%d, name=%s, off=%d, size=%d\n",
1430 				entrys[i].type, name, entrys[i].dataOffset,
1431 				entrys[i].dataSize);
1432 		if (!unpackEntry(entrys + i, name, inFile)) {
1433 			fprintf(stderr, "unpack entry(%s) failed\n", name);
1434 			goto end;
1435 		}
1436 	}
1437 	printf("done\n");
1438 	ret = true;
1439 end:
1440 	if (inFile)
1441 		fclose(inFile);
1442 	return ret;
1443 }
1444 
1445 bool download_boot(STRUCT_RKDEVICE_DESC &dev, char *szLoader)
1446 {
1447 	if (!check_device_type(dev, RKUSB_MASKROM))
1448 		return false;
1449 	CRKImage *pImage = NULL;
1450 	CRKBoot *pBoot = NULL;
1451 	bool bRet, bSuccess = false;
1452 	int iRet;
1453 
1454 	pImage = new CRKImage(szLoader, bRet);
1455 	if (!bRet){
1456 		ERROR_COLOR_ATTR;
1457 		printf("Open loader failed,exit download boot!");
1458 		NORMAL_COLOR_ATTR;
1459 		printf("\r\n");
1460 		return bSuccess;
1461 	} else {
1462 		pBoot = (CRKBoot *)pImage->m_bootObject;
1463 		CRKComm *pComm = NULL;
1464 		CRKDevice *pDevice = NULL;
1465 
1466 		dev.emDeviceType = pBoot->SupportDevice;
1467 		pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
1468 		if (!bRet) {
1469 			if (pImage)
1470 				delete pImage;
1471 			ERROR_COLOR_ATTR;
1472 			printf("Creating Comm Object failed!");
1473 			NORMAL_COLOR_ATTR;
1474 			printf("\r\n");
1475 			return bSuccess;
1476 		}
1477 
1478 		pDevice = new CRKDevice(dev);
1479 		if (!pDevice) {
1480 			if (pImage)
1481 				delete pImage;
1482 			if (pComm)
1483 				delete pComm;
1484 			ERROR_COLOR_ATTR;
1485 			printf("Creating device object failed!");
1486 			NORMAL_COLOR_ATTR;
1487 			printf("\r\n");
1488 			return bSuccess;
1489 		}
1490 
1491 		pDevice->SetObject(pImage, pComm, g_pLogObject);
1492 		printf("Download boot...\r\n");
1493 		iRet = pDevice->DownloadBoot();
1494 
1495 		CURSOR_MOVEUP_LINE(1);
1496 		CURSOR_DEL_LINE;
1497 		if (iRet == 0) {
1498 			bSuccess = true;
1499 			printf("Download boot ok.\r\n");
1500 		}
1501 		else
1502 			printf("Download boot failed!\r\n");
1503 
1504 		if (pImage)
1505 			delete pImage;
1506 		if(pDevice)
1507 			delete pDevice;
1508 	}
1509 	return bSuccess;
1510 }
1511 bool upgrade_loader(STRUCT_RKDEVICE_DESC &dev, char *szLoader)
1512 {
1513 	if (!check_device_type(dev, RKUSB_MASKROM))
1514 		return false;
1515 	CRKImage *pImage = NULL;
1516 	CRKBoot *pBoot = NULL;
1517 	CRKComm *pComm = NULL;
1518 	bool bRet, bSuccess = false;
1519 	int iRet;
1520 	char index;
1521 	USHORT usFlashDataSec, usFlashBootSec;
1522 	DWORD dwLoaderSize, dwLoaderDataSize, dwDelay, dwSectorNum;
1523 	char loaderCodeName[] = "FlashBoot";
1524 	char loaderDataName[] = "FlashData";
1525 	PBYTE loaderCodeBuffer = NULL;
1526 	PBYTE loaderDataBuffer = NULL;
1527 	PBYTE pIDBData = NULL;
1528 	pImage = new CRKImage(szLoader, bRet);
1529 	if (!bRet){
1530 		ERROR_COLOR_ATTR;
1531 		printf("Open loader failed,exit upgrade loader!");
1532 		NORMAL_COLOR_ATTR;
1533 		printf("\r\n");
1534 		goto Exit_UpgradeLoader;
1535 	} else {
1536 		pBoot = (CRKBoot *)pImage->m_bootObject;
1537 		dev.emDeviceType = pBoot->SupportDevice;
1538 		pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
1539 		if (!bRet) {
1540 			ERROR_COLOR_ATTR;
1541 			printf("Creating Comm Object failed!");
1542 			NORMAL_COLOR_ATTR;
1543 			printf("\r\n");
1544 			goto Exit_UpgradeLoader;
1545 		}
1546 
1547 		printf("Upgrade loader...\r\n");
1548 		index = pBoot->GetIndexByName(ENTRYLOADER, loaderCodeName);
1549 		if (index == -1) {
1550 			if (g_pLogObject) {
1551 				g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderCode Entry failed");
1552 			}
1553 			goto Exit_UpgradeLoader;
1554 		}
1555 		bRet = pBoot->GetEntryProperty(ENTRYLOADER, index, dwLoaderSize, dwDelay);
1556 		if (!bRet) {
1557 			if (g_pLogObject) {
1558 				g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderCode Entry Size failed");
1559 			}
1560 			goto Exit_UpgradeLoader;
1561 		}
1562 
1563 		loaderCodeBuffer = new BYTE[dwLoaderSize];
1564 		memset(loaderCodeBuffer, 0, dwLoaderSize);
1565 		if (!pBoot->GetEntryData(ENTRYLOADER, index, loaderCodeBuffer)) {
1566 			if (g_pLogObject) {
1567 				g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderCode Data failed");
1568 			}
1569 			goto Exit_UpgradeLoader;
1570 		}
1571 
1572 		index = pBoot->GetIndexByName(ENTRYLOADER, loaderDataName);
1573 		if (index == -1) {
1574 			if (g_pLogObject) {
1575 				g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderData Entry failed");
1576 			}
1577 			delete []loaderCodeBuffer;
1578 			return -4;
1579 		}
1580 
1581 		bRet = pBoot->GetEntryProperty(ENTRYLOADER, index, dwLoaderDataSize, dwDelay);
1582 		if (!bRet) {
1583 			if (g_pLogObject) {
1584 				g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderData Entry Size failed");
1585 			}
1586 			goto Exit_UpgradeLoader;
1587 		}
1588 
1589 		loaderDataBuffer = new BYTE[dwLoaderDataSize];
1590 		memset(loaderDataBuffer, 0, dwLoaderDataSize);
1591 		if (!pBoot->GetEntryData(ENTRYLOADER,index,loaderDataBuffer)) {
1592 			if (g_pLogObject) {
1593 				g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderData Data failed");
1594 			}
1595 			goto Exit_UpgradeLoader;
1596 		}
1597 
1598 		usFlashDataSec = (ALIGN(dwLoaderDataSize, 2048)) / SECTOR_SIZE;
1599 		usFlashBootSec = (ALIGN(dwLoaderSize, 2048)) / SECTOR_SIZE;
1600 		dwSectorNum = 4 + usFlashDataSec + usFlashBootSec;
1601 		pIDBData = new BYTE[dwSectorNum*SECTOR_SIZE];
1602 		if (!pIDBData) {
1603 			ERROR_COLOR_ATTR;
1604 			printf("New memory failed!");
1605 			NORMAL_COLOR_ATTR;
1606 			printf("\r\n");
1607 			goto Exit_UpgradeLoader;
1608 		}
1609 		memset(pIDBData, 0, dwSectorNum * SECTOR_SIZE);
1610 		iRet = MakeIDBlockData(loaderDataBuffer, loaderCodeBuffer, pIDBData, usFlashDataSec, usFlashBootSec, dwLoaderDataSize, dwLoaderSize);
1611 		if (iRet != 0) {
1612 			ERROR_COLOR_ATTR;
1613 			printf("Make idblock failed!");
1614 			NORMAL_COLOR_ATTR;
1615 			printf("\r\n");
1616 			goto Exit_UpgradeLoader;
1617 		}
1618 		iRet = pComm->RKU_WriteLBA(64, dwSectorNum, pIDBData);
1619 		CURSOR_MOVEUP_LINE(1);
1620 		CURSOR_DEL_LINE;
1621 		if (iRet == ERR_SUCCESS) {
1622 			pComm->Reset_Usb_Device();
1623 			bSuccess = true;
1624 			printf("Upgrade loader ok.\r\n");
1625 		} else {
1626 			printf("Upgrade loader failed!\r\n");
1627 			goto Exit_UpgradeLoader;
1628 		}
1629 	}
1630 Exit_UpgradeLoader:
1631 	if (pImage)
1632 		delete pImage;
1633 	if (pComm)
1634 		delete pComm;
1635 	if (loaderCodeBuffer)
1636 		delete []loaderCodeBuffer;
1637 	if (loaderDataBuffer)
1638 		delete []loaderDataBuffer;
1639 	if (pIDBData)
1640 		delete []pIDBData;
1641 	return bSuccess;
1642 }
1643 
1644 bool erase_flash(STRUCT_RKDEVICE_DESC &dev)
1645 {
1646 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1647 		return false;
1648 	CRKImage *pImage = NULL;
1649 	bool bRet, bSuccess = false;
1650 	int iRet;
1651 	CRKScan *pScan = NULL;
1652 	pScan = new CRKScan();
1653 	pScan->SetVidPid();
1654 
1655 	CRKComm *pComm = NULL;
1656 	CRKDevice *pDevice = NULL;
1657 
1658 	pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
1659 	if (!bRet) {
1660 		if (pScan)
1661 			delete pScan;
1662 		ERROR_COLOR_ATTR;
1663 		printf("Creating Comm Object failed!");
1664 		NORMAL_COLOR_ATTR;
1665 		printf("\r\n");
1666 		return bSuccess;
1667 	}
1668 
1669 	pDevice = new CRKDevice(dev);
1670 	if (!pDevice) {
1671 		if (pComm)
1672 			delete pComm;
1673 		if (pScan)
1674 			delete pScan;
1675 		ERROR_COLOR_ATTR;
1676 		printf("Creating device object failed!");
1677 		NORMAL_COLOR_ATTR;
1678 		printf("\r\n");
1679 		return bSuccess;
1680 	}
1681 
1682 	pDevice->SetObject(pImage, pComm, g_pLogObject);
1683 	pDevice->CallBackPointer = ProgressInfoProc;
1684 
1685 	printf("Start to erase flash...\r\n");
1686 	iRet = pDevice->EraseAllBlocks();
1687 	if (pDevice)
1688 		delete pDevice;
1689 
1690 	if (iRet == 0) {
1691 		if (pScan) {
1692 			pScan->SetVidPid();
1693 			pScan->Wait(dev, RKUSB_MASKROM, dev.usVid, dev.usPid);
1694 			delete pScan;
1695 		}
1696 		CURSOR_MOVEUP_LINE(1);
1697 		CURSOR_DEL_LINE;
1698 		bSuccess = true;
1699 		printf("Erase flash ok.\r\n");
1700 	}
1701 
1702 	return bSuccess;
1703 }
1704 
1705 bool test_device(STRUCT_RKDEVICE_DESC &dev)
1706 {
1707 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1708 		return false;
1709 	CRKUsbComm *pComm = NULL;
1710 	bool bRet, bSuccess = false;
1711 	int iRet;
1712 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1713 	if (bRet) {
1714 		iRet = pComm->RKU_TestDeviceReady();
1715 		if (iRet != ERR_SUCCESS) {
1716 			if (g_pLogObject)
1717 				g_pLogObject->Record("Error:RKU_TestDeviceReady failed,err=%d", iRet);
1718 			printf("Test Device Fail!\r\n");
1719 		} else {
1720 			bSuccess = true;
1721 			printf("Test Device OK.\r\n");
1722 		}
1723 	} else {
1724 		printf("Test Device quit,Creating comm object failed!\r\n");
1725 	}
1726 	if (pComm) {
1727 		delete pComm;
1728 		pComm = NULL;
1729 	}
1730 	return bSuccess;
1731 }
1732 bool reset_device(STRUCT_RKDEVICE_DESC &dev, BYTE subCode = RST_NONE_SUBCODE)
1733 {
1734 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1735 		return false;
1736 	CRKUsbComm *pComm = NULL;
1737 	bool bRet, bSuccess = false;
1738 	int iRet;
1739 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1740 	if (bRet) {
1741 		iRet = pComm->RKU_ResetDevice(subCode);
1742 		if (iRet != ERR_SUCCESS) {
1743 			if (g_pLogObject)
1744 				g_pLogObject->Record("Error:RKU_ResetDevice failed,err=%d", iRet);
1745 			printf("Reset Device Fail!\r\n");
1746 		} else {
1747 			bSuccess = true;
1748 			printf("Reset Device OK.\r\n");
1749 		}
1750 	} else {
1751 		printf("Reset Device quit,Creating comm object failed!\r\n");
1752 	}
1753 	if (pComm) {
1754 		delete pComm;
1755 		pComm = NULL;
1756 	}
1757 	return bSuccess;
1758 }
1759 
1760 bool read_flash_id(STRUCT_RKDEVICE_DESC &dev)
1761 {
1762 	CRKUsbComm *pComm = NULL;
1763 	bool bRet, bSuccess = false;
1764 	int iRet;
1765 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1766 		return bSuccess;
1767 
1768 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1769 	if (bRet) {
1770 		BYTE flashID[5];
1771 		iRet = pComm->RKU_ReadFlashID(flashID);
1772 		if (iRet != ERR_SUCCESS) {
1773 			if (g_pLogObject)
1774 				g_pLogObject->Record("Error:RKU_ReadFlashID failed,err=%d", iRet);
1775 			printf("Read flash ID Fail!\r\n");
1776 		} else {
1777 			printf("Flash ID:%02X %02X %02X %02X %02X \r\n", flashID[0], flashID[1], flashID[2], flashID[3], flashID[4]);
1778 			bSuccess = true;
1779 		}
1780 	} else {
1781 		printf("Read flash ID quit,Creating comm object failed!\r\n");
1782 	}
1783 	if (pComm) {
1784 		delete pComm;
1785 		pComm = NULL;
1786 	}
1787 	return bSuccess;
1788 }
1789 bool read_flash_info(STRUCT_RKDEVICE_DESC &dev)
1790 {
1791 	CRKUsbComm *pComm = NULL;
1792 	bool bRet, bSuccess = false;
1793 	int iRet;
1794 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1795 		return bSuccess;
1796 
1797 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1798 	if (bRet) {
1799 		STRUCT_FLASHINFO_CMD info;
1800 		UINT uiRead;
1801 		iRet = pComm->RKU_ReadFlashInfo((BYTE *)&info, &uiRead);
1802 		if (iRet != ERR_SUCCESS) {
1803 			if (g_pLogObject)
1804 				g_pLogObject->Record("Error:RKU_ReadFlashInfo failed,err=%d", iRet);
1805 			printf("Read flash Info Fail!\r\n");
1806 		} else {
1807 			printf("Flash Info:\r\n");
1808 			if (info.bManufCode <= 7) {
1809 				printf("\tManufacturer: %s,value=%02X\r\n", szManufName[info.bManufCode], info.bManufCode);
1810 			}
1811 			else
1812 				printf("\tManufacturer: %s,value=%02X\r\n", "Unknown", info.bManufCode);
1813 
1814 			printf("\tFlash Size: %dMB\r\n", info.uiFlashSize / 2 / 1024);
1815 			printf("\tBlock Size: %dKB\r\n", info.usBlockSize / 2);
1816 			printf("\tPage Size: %dKB\r\n", info.bPageSize / 2);
1817 			printf("\tECC Bits: %d\r\n", info.bECCBits);
1818 			printf("\tAccess Time: %d\r\n", info.bAccessTime);
1819 			printf("\tFlash CS: ");
1820 			for(int i = 0; i < 8; i++) {
1821 				if( info.bFlashCS & (1 << i) )
1822 					printf("Flash<%d> ", i);
1823 			}
1824 			printf("\r\n");
1825 			bSuccess = true;
1826 		}
1827 	}else {
1828 		printf("Read flash Info quit,Creating comm object failed!\r\n");
1829 	}
1830 	if (pComm) {
1831 		delete pComm;
1832 		pComm = NULL;
1833 	}
1834 	return bSuccess;
1835 }
1836 bool read_chip_info(STRUCT_RKDEVICE_DESC &dev)
1837 {
1838 	CRKUsbComm *pComm = NULL;
1839 	bool bRet, bSuccess = false;
1840 	int iRet;
1841 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1842 		return bSuccess;
1843 
1844 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1845 	if (bRet) {
1846 		BYTE chipInfo[16];
1847 		iRet = pComm->RKU_ReadChipInfo(chipInfo);
1848 		if (iRet != ERR_SUCCESS) {
1849 			if (g_pLogObject)
1850 				g_pLogObject->Record("Error:RKU_ReadChipInfo failed,err=%d", iRet);
1851 			printf("Read Chip Info Fail!\r\n");
1852 		} else {
1853 			string strChipInfo;
1854 			g_pLogObject->PrintBuffer(strChipInfo, chipInfo, 16, 16);
1855 			printf("Chip Info:%s\r\n", strChipInfo.c_str());
1856 			bSuccess = true;
1857 		}
1858 	} else {
1859 		printf("Read Chip Info quit,Creating comm object failed!\r\n");
1860 	}
1861 	if (pComm) {
1862 		delete pComm;
1863 		pComm = NULL;
1864 	}
1865 	return bSuccess;
1866 }
1867 bool read_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, UINT uiLen, char *szFile)
1868 {
1869 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1870 		return false;
1871 	CRKUsbComm *pComm = NULL;
1872 	FILE *file = NULL;
1873 	bool bRet, bFirst = true, bSuccess = false;
1874 	int iRet;
1875 	UINT iTotalRead = 0,iRead = 0;
1876 	int nSectorSize = 512;
1877 	BYTE pBuf[nSectorSize * DEFAULT_RW_LBA];
1878 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1879 	if (bRet) {
1880 		if(szFile) {
1881 			file = fopen(szFile, "wb+");
1882 			if( !file ) {
1883 				printf("Read LBA failed,err=%d,can't open file: %s\r\n", errno, szFile);
1884 				goto Exit_ReadLBA;
1885 			}
1886 		}
1887 
1888 		while(uiLen > 0) {
1889 			memset(pBuf, 0, nSectorSize * DEFAULT_RW_LBA);
1890 			iRead = (uiLen >= DEFAULT_RW_LBA) ? DEFAULT_RW_LBA : uiLen;
1891 			iRet = pComm->RKU_ReadLBA( uiBegin + iTotalRead, iRead, pBuf);
1892 			if(ERR_SUCCESS == iRet) {
1893 				uiLen -= iRead;
1894 				iTotalRead += iRead;
1895 
1896 				if(szFile) {
1897 					fwrite(pBuf, 1, iRead * nSectorSize, file);
1898 					if (bFirst){
1899 						if (iTotalRead >= 1024)
1900 							printf("Read LBA from file (%d%%)\r\n", (iTotalRead / 1024) * 100 / ((uiLen + iTotalRead) / 1024));
1901 						else
1902 							printf("Read LBA from file %d%%)\r\n", iTotalRead * 100 / (uiLen + iTotalRead));
1903 						bFirst = false;
1904 					} else {
1905 						CURSOR_MOVEUP_LINE(1);
1906 						CURSOR_DEL_LINE;
1907 						if (iTotalRead >= 1024)
1908 							printf("Read LBA from file (%d%%)\r\n", (iTotalRead / 1024) * 100 / ((uiLen + iTotalRead) / 1024));
1909 						else
1910 							printf("Read LBA from file %d%%)\r\n", iTotalRead * 100 / (uiLen + iTotalRead));
1911 					}
1912 				}
1913 				else
1914 					PrintData(pBuf, nSectorSize * iRead);
1915 			} else {
1916 				if (g_pLogObject)
1917 					g_pLogObject->Record("Error:RKU_ReadLBA failed,err=%d", iRet);
1918 
1919 				printf("Read LBA failed!\r\n");
1920 				goto Exit_ReadLBA;
1921 			}
1922 		}
1923 		bSuccess = true;
1924 	} else {
1925 		printf("Read LBA quit,Creating comm object failed!\r\n");
1926 	}
1927 Exit_ReadLBA:
1928 	if (pComm) {
1929 		delete pComm;
1930 		pComm = NULL;
1931 	}
1932 	if (file)
1933 		fclose(file);
1934 	return bSuccess;
1935 }
1936 bool write_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, char *szFile)
1937 {
1938 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1939 		return false;
1940 	CRKUsbComm *pComm = NULL;
1941 	FILE *file = NULL;
1942 	bool bRet, bFirst = true, bSuccess = false;
1943 	int iRet;
1944 	long long iTotalWrite = 0, iFileSize = 0;
1945 	UINT iWrite = 0, iRead = 0;
1946 	UINT uiLen;
1947 	int nSectorSize = 512;
1948 	BYTE pBuf[nSectorSize * DEFAULT_RW_LBA];
1949 
1950 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1951 	if (bRet) {
1952 		file = fopen(szFile, "rb");
1953 		if( !file ) {
1954 			printf("Write LBA failed,err=%d,can't open file: %s\r\n", errno, szFile);
1955 			goto Exit_WriteLBA;
1956 		}
1957 
1958 		iRet = fseeko(file, 0, SEEK_END);
1959 		iFileSize = ftello(file);
1960 		fseeko(file, 0, SEEK_SET);
1961 		while(iTotalWrite < iFileSize) {
1962 			memset(pBuf, 0, nSectorSize * DEFAULT_RW_LBA);
1963 			iWrite = iRead= fread(pBuf, 1, nSectorSize * DEFAULT_RW_LBA, file);
1964 			uiLen = ((iWrite % 512) == 0) ? (iWrite / 512) : (iWrite / 512 + 1);
1965 			iRet = pComm->RKU_WriteLBA( uiBegin, uiLen, pBuf);
1966 			if(ERR_SUCCESS == iRet) {
1967 				uiBegin += uiLen;
1968 				iTotalWrite += iWrite;
1969 				if (bFirst) {
1970 					if (iTotalWrite >= 1024)
1971 						printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
1972 					else
1973 						printf("Write LBA from file %lld%%)\r\n", iTotalWrite * 100 / iFileSize);
1974 					bFirst = false;
1975 				} else {
1976 					CURSOR_MOVEUP_LINE(1);
1977 					CURSOR_DEL_LINE;
1978 					printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
1979 				}
1980 			} else {
1981 				if (g_pLogObject)
1982 					g_pLogObject->Record("Error:RKU_WriteLBA failed,err=%d", iRet);
1983 
1984 				printf("Write LBA failed!\r\n");
1985 				goto Exit_WriteLBA;
1986 			}
1987 		}
1988 		bSuccess = true;
1989 	} else {
1990 		printf("Write LBA quit,Creating comm object failed!\r\n");
1991 	}
1992 Exit_WriteLBA:
1993 	if (pComm) {
1994 		delete pComm;
1995 		pComm = NULL;
1996 	}
1997 	if (file)
1998 		fclose(file);
1999 	return bSuccess;
2000 }
2001 
2002 void split_item(STRING_VECTOR &vecItems, char *pszItems)
2003 {
2004 	string strItem;
2005 	char szItem[100];
2006 	char *pos = NULL, *pStart;
2007 	pStart = pszItems;
2008 	pos = strchr(pStart, ',');
2009 	while(pos != NULL) {
2010 		memset(szItem, 0, 100);
2011 		strncpy(szItem, pStart, pos - pStart);
2012 		strItem = szItem;
2013 		vecItems.push_back(strItem);
2014 		pStart = pos + 1;
2015 		if (*pStart == 0)
2016 			break;
2017 		pos = strchr(pStart, ',');
2018 	}
2019 	if (strlen(pStart) > 0) {
2020 		memset(szItem, 0, 100);
2021 		strncpy(szItem, pStart, strlen(pStart));
2022 		strItem = szItem;
2023 		vecItems.push_back(strItem);
2024 	}
2025 }
2026 
2027 bool handle_command(int argc, char* argv[], CRKScan *pScan)
2028 {
2029 	string strCmd;
2030 	strCmd = argv[1];
2031 	ssize_t cnt;
2032 	bool bRet,bSuccess = false;
2033 	char *s;
2034 	int i, ret;
2035 	STRUCT_RKDEVICE_DESC dev;
2036 
2037 	transform(strCmd.begin(), strCmd.end(), strCmd.begin(), (int(*)(int))toupper);
2038 	s = (char*)strCmd.c_str();
2039 	for(i = 0; i < (int)strlen(s); i++)
2040 	        s[i] = toupper(s[i]);
2041 
2042 	if((strcmp(strCmd.c_str(), "-H") == 0) || (strcmp(strCmd.c_str(), "--HELP")) == 0){
2043 		usage();
2044 		return true;
2045 	} else if((strcmp(strCmd.c_str(), "-V") == 0) || (strcmp(strCmd.c_str(), "--VERSION") == 0)) {
2046 		printf("rkdeveloptool ver %s\r\n", PACKAGE_VERSION);
2047 		return true;
2048 	} else if (strcmp(strCmd.c_str(), "PACK") == 0) {//pack boot loader
2049 		mergeBoot();
2050 
2051 		return true;
2052 	} else if (strcmp(strCmd.c_str(), "UNPACK") == 0) {//unpack boot loader
2053 		string strLoader = argv[2];
2054 
2055 		unpackBoot((char*)strLoader.c_str());
2056 		return true;
2057 	}
2058 	cnt = pScan->Search(RKUSB_MASKROM | RKUSB_LOADER);
2059 	if (cnt < 1) {
2060 		ERROR_COLOR_ATTR;
2061 		printf("No found any rockusb device,please plug device in!");
2062 		NORMAL_COLOR_ATTR;
2063 		printf("\r\n");
2064 		return bSuccess;
2065 	} else if (cnt > 1) {
2066 		ERROR_COLOR_ATTR;
2067 		printf("Found many rockusb devices,please plug device out!");
2068 		NORMAL_COLOR_ATTR;
2069 		printf("\r\n");
2070 		return bSuccess;
2071 	}
2072 
2073 	bRet = pScan->GetDevice(dev, 0);
2074 	if (!bRet) {
2075 		ERROR_COLOR_ATTR;
2076 		printf("Getting information of rockusb device failed!");
2077 		NORMAL_COLOR_ATTR;
2078 		printf("\r\n");
2079 		return bSuccess;
2080 	}
2081 
2082 	if(strcmp(strCmd.c_str(), "RD") == 0) {
2083 		if ((argc != 2) && (argc != 3))
2084 			printf("Parameter of [RD] command is invalid,please check help!\r\n");
2085 		else {
2086 			if (argc == 2)
2087 				bSuccess = reset_device(dev);
2088 			else {
2089 				UINT uiSubCode;
2090 				char *pszEnd;
2091 				uiSubCode = strtoul(argv[2], &pszEnd, 0);
2092 				if (*pszEnd)
2093 					printf("Subcode is invalid,please check!\r\n");
2094 				else {
2095 					if (uiSubCode <= 5)
2096 						bSuccess = reset_device(dev, uiSubCode);
2097 					else
2098 						printf("Subcode is invalid,please check!\r\n");
2099 				}
2100 			}
2101 		}
2102 	} else if(strcmp(strCmd.c_str(), "TD") == 0) {
2103 		bSuccess = test_device(dev);
2104 	} else if (strcmp(strCmd.c_str(), "RID") == 0) {//Read Flash ID
2105 		bSuccess = read_flash_id(dev);
2106 	} else if (strcmp(strCmd.c_str(), "RFI") == 0){//Read Flash Info
2107 		bSuccess = read_flash_info(dev);
2108 	} else if (strcmp(strCmd.c_str(), "RCI") == 0) {//Read Chip Info
2109 		bSuccess = read_chip_info(dev);
2110 	} else if(strcmp(strCmd.c_str(), "DB") == 0) {
2111 		if (argc > 2) {
2112 			string strLoader;
2113 			strLoader = argv[2];
2114 			bSuccess = download_boot(dev, (char *)strLoader.c_str());
2115 		} else if (argc == 2) {
2116 			ret = find_config_item("loader");
2117 			if (ret == -1)
2118 				printf("No found loader item from config!\r\n");
2119 			else
2120 				bSuccess = download_boot(dev, g_ConfigItemVec[ret].szItemValue);
2121 		} else
2122 			printf("Parameter of [DB] command is invalid,please check help!\r\n");
2123 	} else if(strcmp(strCmd.c_str(), "GPT") == 0) {
2124 		if (argc > 2) {
2125 			string strParameter;
2126 			strParameter = argv[2];
2127 			bSuccess = write_gpt(dev, (char *)strParameter.c_str());
2128 		} else
2129 			printf("Parameter of [GPT] command is invalid,please check help!\r\n");
2130 	} else if(strcmp(strCmd.c_str(), "UL") == 0) {
2131 		if (argc > 2) {
2132 			string strLoader;
2133 			strLoader = argv[2];
2134 			bSuccess = upgrade_loader(dev, (char *)strLoader.c_str());
2135 		} else
2136 			printf("Parameter of [UL] command is invalid,please check help!\r\n");
2137 	} else if(strcmp(strCmd.c_str(), "EF") == 0) {
2138 		if (argc == 2) {
2139 			bSuccess = erase_flash(dev);
2140 		} else
2141 			printf("Parameter of [EF] command is invalid,please check help!\r\n");
2142 	} else if(strcmp(strCmd.c_str(), "WL") == 0) {
2143 		if (argc == 4) {
2144 			UINT uiBegin;
2145 			char *pszEnd;
2146 			uiBegin = strtoul(argv[2], &pszEnd, 0);
2147 			if (*pszEnd)
2148 				printf("Begin is invalid,please check!\r\n");
2149 			else
2150 				bSuccess = write_lba(dev, uiBegin, argv[3]);
2151 		} else
2152 			printf("Parameter of [WL] command is invalid,please check help!\r\n");
2153 	} else if (strcmp(strCmd.c_str(), "RL") == 0) {//Read LBA
2154 		char *pszEnd;
2155 		UINT uiBegin, uiLen;
2156 		if (argc != 5)
2157 			printf("Parameter of [RL] command is invalid,please check help!\r\n");
2158 		else {
2159 			uiBegin = strtoul(argv[2], &pszEnd, 0);
2160 			if (*pszEnd)
2161 				printf("Begin is invalid,please check!\r\n");
2162 			else {
2163 				uiLen = strtoul(argv[3], &pszEnd, 0);
2164 				if (*pszEnd)
2165 					printf("Len is invalid,please check!\r\n");
2166 				else {
2167 					bSuccess = read_lba(dev, uiBegin, uiLen, argv[4]);
2168 				}
2169 			}
2170 		}
2171 	} else {
2172 		printf("command is invalid,please press rkDevelopTool -h to check usage!\r\n");
2173 	}
2174 	return bSuccess;
2175 }
2176 
2177 
2178 int main(int argc, char* argv[])
2179 {
2180 	CRKScan *pScan = NULL;
2181 	int ret;
2182 	char szProgramProcPath[100];
2183 	char szProgramDir[256];
2184 	string strLogDir,strConfigFile;
2185 	struct stat statBuf;
2186 
2187 	g_ConfigItemVec.clear();
2188 	sprintf(szProgramProcPath, "/proc/%d/exe", getpid());
2189 	if (readlink(szProgramProcPath, szProgramDir, 256) == -1)
2190 		strcpy(szProgramDir, ".");
2191 	else {
2192 		char *pSlash;
2193 		pSlash = strrchr(szProgramDir, '/');
2194 		if (pSlash)
2195 			*pSlash = '\0';
2196 	}
2197 	strLogDir = szProgramDir;
2198 	strLogDir +=  "/log/";
2199 	strConfigFile = szProgramDir;
2200 	strConfigFile += "/config.ini";
2201 	if (opendir(strLogDir.c_str()) == NULL)
2202 		mkdir(strLogDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH);
2203 	g_pLogObject = new CRKLog(strLogDir.c_str(), "log");
2204 
2205 	if(stat(strConfigFile.c_str(), &statBuf) < 0) {
2206 		if (g_pLogObject) {
2207 			g_pLogObject->Record("Error:failed to stat config.ini,err=%d", errno);
2208 		}
2209 	} else if (S_ISREG(statBuf.st_mode)) {
2210 		parse_config_file(strConfigFile.c_str(), g_ConfigItemVec);
2211 	}
2212 
2213 	ret = libusb_init(NULL);
2214 	if (ret < 0) {
2215 		if (g_pLogObject) {
2216 			g_pLogObject->Record("Error:libusb_init failed,err=%d", ret);
2217 			delete g_pLogObject;
2218 		}
2219 		return -1;
2220 	}
2221 
2222 	pScan = new CRKScan();
2223 	if (!pScan) {
2224 		if (g_pLogObject) {
2225 			g_pLogObject->Record("Error:failed to Create object for searching device");
2226 			delete g_pLogObject;
2227 		}
2228 		libusb_exit(NULL);
2229 		return -2;
2230 	}
2231 	pScan->SetVidPid();
2232 
2233 	if (argc == 1)
2234 		usage();
2235 	else if (!handle_command(argc, argv, pScan))
2236 			return -0xFF;
2237 	if (pScan)
2238 		delete pScan;
2239 	if (g_pLogObject)
2240 		delete g_pLogObject;
2241 	libusb_exit(NULL);
2242 	return 0;
2243 }
2244