xref: /rkdeveloptool/main.cpp (revision 641cfa16d6d52b78ded6d85f20c2a9bbfcf46c59)
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 			pComm->Reset_Usb_Device();
1499 			CRKScan *pScan = NULL;
1500 			pScan = new CRKScan();
1501 			if (pScan) {
1502 				pScan->SetVidPid();
1503 				pScan->Wait(dev, RKUSB_MASKROM, dev.usVid, dev.usPid);
1504 				delete pScan;
1505 			}
1506 			bSuccess = true;
1507 			printf("Download boot ok.\r\n");
1508 		}
1509 		else
1510 			printf("Download boot failed!\r\n");
1511 
1512 		if (pImage)
1513 			delete pImage;
1514 		if(pDevice)
1515 			delete pDevice;
1516 	}
1517 	return bSuccess;
1518 }
1519 bool upgrade_loader(STRUCT_RKDEVICE_DESC &dev, char *szLoader)
1520 {
1521 	if (!check_device_type(dev, RKUSB_MASKROM))
1522 		return false;
1523 	CRKImage *pImage = NULL;
1524 	CRKBoot *pBoot = NULL;
1525 	CRKComm *pComm = NULL;
1526 	bool bRet, bSuccess = false;
1527 	int iRet;
1528 	char index;
1529 	USHORT usFlashDataSec, usFlashBootSec;
1530 	DWORD dwLoaderSize, dwLoaderDataSize, dwDelay, dwSectorNum;
1531 	char loaderCodeName[] = "FlashBoot";
1532 	char loaderDataName[] = "FlashData";
1533 	PBYTE loaderCodeBuffer = NULL;
1534 	PBYTE loaderDataBuffer = NULL;
1535 	PBYTE pIDBData = NULL;
1536 	pImage = new CRKImage(szLoader, bRet);
1537 	if (!bRet){
1538 		ERROR_COLOR_ATTR;
1539 		printf("Open loader failed,exit upgrade loader!");
1540 		NORMAL_COLOR_ATTR;
1541 		printf("\r\n");
1542 		goto Exit_UpgradeLoader;
1543 	} else {
1544 		pBoot = (CRKBoot *)pImage->m_bootObject;
1545 		dev.emDeviceType = pBoot->SupportDevice;
1546 		pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
1547 		if (!bRet) {
1548 			ERROR_COLOR_ATTR;
1549 			printf("Creating Comm Object failed!");
1550 			NORMAL_COLOR_ATTR;
1551 			printf("\r\n");
1552 			goto Exit_UpgradeLoader;
1553 		}
1554 
1555 		printf("Upgrade loader...\r\n");
1556 		index = pBoot->GetIndexByName(ENTRYLOADER, loaderCodeName);
1557 		if (index == -1) {
1558 			if (g_pLogObject) {
1559 				g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderCode Entry failed");
1560 			}
1561 			goto Exit_UpgradeLoader;
1562 		}
1563 		bRet = pBoot->GetEntryProperty(ENTRYLOADER, index, dwLoaderSize, dwDelay);
1564 		if (!bRet) {
1565 			if (g_pLogObject) {
1566 				g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderCode Entry Size failed");
1567 			}
1568 			goto Exit_UpgradeLoader;
1569 		}
1570 
1571 		loaderCodeBuffer = new BYTE[dwLoaderSize];
1572 		memset(loaderCodeBuffer, 0, dwLoaderSize);
1573 		if (!pBoot->GetEntryData(ENTRYLOADER, index, loaderCodeBuffer)) {
1574 			if (g_pLogObject) {
1575 				g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderCode Data failed");
1576 			}
1577 			goto Exit_UpgradeLoader;
1578 		}
1579 
1580 		index = pBoot->GetIndexByName(ENTRYLOADER, loaderDataName);
1581 		if (index == -1) {
1582 			if (g_pLogObject) {
1583 				g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderData Entry failed");
1584 			}
1585 			delete []loaderCodeBuffer;
1586 			return -4;
1587 		}
1588 
1589 		bRet = pBoot->GetEntryProperty(ENTRYLOADER, index, dwLoaderDataSize, dwDelay);
1590 		if (!bRet) {
1591 			if (g_pLogObject) {
1592 				g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderData Entry Size failed");
1593 			}
1594 			goto Exit_UpgradeLoader;
1595 		}
1596 
1597 		loaderDataBuffer = new BYTE[dwLoaderDataSize];
1598 		memset(loaderDataBuffer, 0, dwLoaderDataSize);
1599 		if (!pBoot->GetEntryData(ENTRYLOADER,index,loaderDataBuffer)) {
1600 			if (g_pLogObject) {
1601 				g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderData Data failed");
1602 			}
1603 			goto Exit_UpgradeLoader;
1604 		}
1605 
1606 		usFlashDataSec = (ALIGN(dwLoaderDataSize, 2048)) / SECTOR_SIZE;
1607 		usFlashBootSec = (ALIGN(dwLoaderSize, 2048)) / SECTOR_SIZE;
1608 		dwSectorNum = 4 + usFlashDataSec + usFlashBootSec;
1609 		pIDBData = new BYTE[dwSectorNum*SECTOR_SIZE];
1610 		if (!pIDBData) {
1611 			ERROR_COLOR_ATTR;
1612 			printf("New memory failed!");
1613 			NORMAL_COLOR_ATTR;
1614 			printf("\r\n");
1615 			goto Exit_UpgradeLoader;
1616 		}
1617 		memset(pIDBData, 0, dwSectorNum * SECTOR_SIZE);
1618 		iRet = MakeIDBlockData(loaderDataBuffer, loaderCodeBuffer, pIDBData, usFlashDataSec, usFlashBootSec, dwLoaderDataSize, dwLoaderSize);
1619 		if (iRet != 0) {
1620 			ERROR_COLOR_ATTR;
1621 			printf("Make idblock failed!");
1622 			NORMAL_COLOR_ATTR;
1623 			printf("\r\n");
1624 			goto Exit_UpgradeLoader;
1625 		}
1626 		iRet = pComm->RKU_WriteLBA(64, dwSectorNum, pIDBData);
1627 		CURSOR_MOVEUP_LINE(1);
1628 		CURSOR_DEL_LINE;
1629 		if (iRet == ERR_SUCCESS) {
1630 			pComm->Reset_Usb_Device();
1631 			bSuccess = true;
1632 			printf("Upgrade loader ok.\r\n");
1633 		} else {
1634 			printf("Upgrade loader failed!\r\n");
1635 			goto Exit_UpgradeLoader;
1636 		}
1637 	}
1638 Exit_UpgradeLoader:
1639 	if (pImage)
1640 		delete pImage;
1641 	if (pComm)
1642 		delete pComm;
1643 	if (loaderCodeBuffer)
1644 		delete []loaderCodeBuffer;
1645 	if (loaderDataBuffer)
1646 		delete []loaderDataBuffer;
1647 	if (pIDBData)
1648 		delete []pIDBData;
1649 	return bSuccess;
1650 }
1651 
1652 bool erase_flash(STRUCT_RKDEVICE_DESC &dev)
1653 {
1654 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1655 		return false;
1656 	CRKImage *pImage = NULL;
1657 	bool bRet, bSuccess = false;
1658 	int iRet;
1659 	CRKScan *pScan = NULL;
1660 	pScan = new CRKScan();
1661 	pScan->SetVidPid();
1662 
1663 	CRKComm *pComm = NULL;
1664 	CRKDevice *pDevice = NULL;
1665 
1666 	pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
1667 	if (!bRet) {
1668 		if (pScan)
1669 			delete pScan;
1670 		ERROR_COLOR_ATTR;
1671 		printf("Creating Comm Object failed!");
1672 		NORMAL_COLOR_ATTR;
1673 		printf("\r\n");
1674 		return bSuccess;
1675 	}
1676 
1677 	pDevice = new CRKDevice(dev);
1678 	if (!pDevice) {
1679 		if (pComm)
1680 			delete pComm;
1681 		if (pScan)
1682 			delete pScan;
1683 		ERROR_COLOR_ATTR;
1684 		printf("Creating device object failed!");
1685 		NORMAL_COLOR_ATTR;
1686 		printf("\r\n");
1687 		return bSuccess;
1688 	}
1689 
1690 	pDevice->SetObject(pImage, pComm, g_pLogObject);
1691 	pDevice->CallBackPointer = ProgressInfoProc;
1692 
1693 	printf("Start to erase flash...\r\n");
1694 	iRet = pDevice->EraseAllBlocks();
1695 	if (pDevice)
1696 		delete pDevice;
1697 
1698 	if (iRet == 0) {
1699 		if (pScan) {
1700 			pScan->SetVidPid();
1701 			pScan->Wait(dev, RKUSB_MASKROM, dev.usVid, dev.usPid);
1702 			delete pScan;
1703 		}
1704 		CURSOR_MOVEUP_LINE(1);
1705 		CURSOR_DEL_LINE;
1706 		bSuccess = true;
1707 		printf("Erase flash ok.\r\n");
1708 	}
1709 
1710 	return bSuccess;
1711 }
1712 
1713 bool test_device(STRUCT_RKDEVICE_DESC &dev)
1714 {
1715 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1716 		return false;
1717 	CRKUsbComm *pComm = NULL;
1718 	bool bRet, bSuccess = false;
1719 	int iRet;
1720 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1721 	if (bRet) {
1722 		iRet = pComm->RKU_TestDeviceReady();
1723 		if (iRet != ERR_SUCCESS) {
1724 			if (g_pLogObject)
1725 				g_pLogObject->Record("Error:RKU_TestDeviceReady failed,err=%d", iRet);
1726 			printf("Test Device Fail!\r\n");
1727 		} else {
1728 			bSuccess = true;
1729 			printf("Test Device OK.\r\n");
1730 		}
1731 	} else {
1732 		printf("Test Device quit,Creating comm object failed!\r\n");
1733 	}
1734 	if (pComm) {
1735 		delete pComm;
1736 		pComm = NULL;
1737 	}
1738 	return bSuccess;
1739 }
1740 bool reset_device(STRUCT_RKDEVICE_DESC &dev, BYTE subCode = RST_NONE_SUBCODE)
1741 {
1742 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1743 		return false;
1744 	CRKUsbComm *pComm = NULL;
1745 	bool bRet, bSuccess = false;
1746 	int iRet;
1747 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1748 	if (bRet) {
1749 		iRet = pComm->RKU_ResetDevice(subCode);
1750 		if (iRet != ERR_SUCCESS) {
1751 			if (g_pLogObject)
1752 				g_pLogObject->Record("Error:RKU_ResetDevice failed,err=%d", iRet);
1753 			printf("Reset Device Fail!\r\n");
1754 		} else {
1755 			bSuccess = true;
1756 			printf("Reset Device OK.\r\n");
1757 		}
1758 	} else {
1759 		printf("Reset Device quit,Creating comm object failed!\r\n");
1760 	}
1761 	if (pComm) {
1762 		delete pComm;
1763 		pComm = NULL;
1764 	}
1765 	return bSuccess;
1766 }
1767 
1768 bool read_flash_id(STRUCT_RKDEVICE_DESC &dev)
1769 {
1770 	CRKUsbComm *pComm = NULL;
1771 	bool bRet, bSuccess = false;
1772 	int iRet;
1773 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1774 		return bSuccess;
1775 
1776 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1777 	if (bRet) {
1778 		BYTE flashID[5];
1779 		iRet = pComm->RKU_ReadFlashID(flashID);
1780 		if (iRet != ERR_SUCCESS) {
1781 			if (g_pLogObject)
1782 				g_pLogObject->Record("Error:RKU_ReadFlashID failed,err=%d", iRet);
1783 			printf("Read flash ID Fail!\r\n");
1784 		} else {
1785 			printf("Flash ID:%02X %02X %02X %02X %02X \r\n", flashID[0], flashID[1], flashID[2], flashID[3], flashID[4]);
1786 			bSuccess = true;
1787 		}
1788 	} else {
1789 		printf("Read flash ID quit,Creating comm object failed!\r\n");
1790 	}
1791 	if (pComm) {
1792 		delete pComm;
1793 		pComm = NULL;
1794 	}
1795 	return bSuccess;
1796 }
1797 bool read_flash_info(STRUCT_RKDEVICE_DESC &dev)
1798 {
1799 	CRKUsbComm *pComm = NULL;
1800 	bool bRet, bSuccess = false;
1801 	int iRet;
1802 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1803 		return bSuccess;
1804 
1805 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1806 	if (bRet) {
1807 		STRUCT_FLASHINFO_CMD info;
1808 		UINT uiRead;
1809 		iRet = pComm->RKU_ReadFlashInfo((BYTE *)&info, &uiRead);
1810 		if (iRet != ERR_SUCCESS) {
1811 			if (g_pLogObject)
1812 				g_pLogObject->Record("Error:RKU_ReadFlashInfo failed,err=%d", iRet);
1813 			printf("Read flash Info Fail!\r\n");
1814 		} else {
1815 			printf("Flash Info:\r\n");
1816 			if (info.bManufCode <= 7) {
1817 				printf("\tManufacturer: %s,value=%02X\r\n", szManufName[info.bManufCode], info.bManufCode);
1818 			}
1819 			else
1820 				printf("\tManufacturer: %s,value=%02X\r\n", "Unknown", info.bManufCode);
1821 
1822 			printf("\tFlash Size: %dMB\r\n", info.uiFlashSize / 2 / 1024);
1823 			printf("\tBlock Size: %dKB\r\n", info.usBlockSize / 2);
1824 			printf("\tPage Size: %dKB\r\n", info.bPageSize / 2);
1825 			printf("\tECC Bits: %d\r\n", info.bECCBits);
1826 			printf("\tAccess Time: %d\r\n", info.bAccessTime);
1827 			printf("\tFlash CS: ");
1828 			for(int i = 0; i < 8; i++) {
1829 				if( info.bFlashCS & (1 << i) )
1830 					printf("Flash<%d> ", i);
1831 			}
1832 			printf("\r\n");
1833 			bSuccess = true;
1834 		}
1835 	}else {
1836 		printf("Read flash Info quit,Creating comm object failed!\r\n");
1837 	}
1838 	if (pComm) {
1839 		delete pComm;
1840 		pComm = NULL;
1841 	}
1842 	return bSuccess;
1843 }
1844 bool read_chip_info(STRUCT_RKDEVICE_DESC &dev)
1845 {
1846 	CRKUsbComm *pComm = NULL;
1847 	bool bRet, bSuccess = false;
1848 	int iRet;
1849 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1850 		return bSuccess;
1851 
1852 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1853 	if (bRet) {
1854 		BYTE chipInfo[16];
1855 		iRet = pComm->RKU_ReadChipInfo(chipInfo);
1856 		if (iRet != ERR_SUCCESS) {
1857 			if (g_pLogObject)
1858 				g_pLogObject->Record("Error:RKU_ReadChipInfo failed,err=%d", iRet);
1859 			printf("Read Chip Info Fail!\r\n");
1860 		} else {
1861 			string strChipInfo;
1862 			g_pLogObject->PrintBuffer(strChipInfo, chipInfo, 16, 16);
1863 			printf("Chip Info:%s\r\n", strChipInfo.c_str());
1864 			bSuccess = true;
1865 		}
1866 	} else {
1867 		printf("Read Chip Info quit,Creating comm object failed!\r\n");
1868 	}
1869 	if (pComm) {
1870 		delete pComm;
1871 		pComm = NULL;
1872 	}
1873 	return bSuccess;
1874 }
1875 bool read_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, UINT uiLen, char *szFile)
1876 {
1877 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1878 		return false;
1879 	CRKUsbComm *pComm = NULL;
1880 	FILE *file = NULL;
1881 	bool bRet, bFirst = true, bSuccess = false;
1882 	int iRet;
1883 	UINT iTotalRead = 0,iRead = 0;
1884 	int nSectorSize = 512;
1885 	BYTE pBuf[nSectorSize * DEFAULT_RW_LBA];
1886 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1887 	if (bRet) {
1888 		if(szFile) {
1889 			file = fopen(szFile, "wb+");
1890 			if( !file ) {
1891 				printf("Read LBA failed,err=%d,can't open file: %s\r\n", errno, szFile);
1892 				goto Exit_ReadLBA;
1893 			}
1894 		}
1895 
1896 		while(uiLen > 0) {
1897 			memset(pBuf, 0, nSectorSize * DEFAULT_RW_LBA);
1898 			iRead = (uiLen >= DEFAULT_RW_LBA) ? DEFAULT_RW_LBA : uiLen;
1899 			iRet = pComm->RKU_ReadLBA( uiBegin + iTotalRead, iRead, pBuf);
1900 			if(ERR_SUCCESS == iRet) {
1901 				uiLen -= iRead;
1902 				iTotalRead += iRead;
1903 
1904 				if(szFile) {
1905 					fwrite(pBuf, 1, iRead * nSectorSize, file);
1906 					if (bFirst){
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 						bFirst = false;
1912 					} else {
1913 						CURSOR_MOVEUP_LINE(1);
1914 						CURSOR_DEL_LINE;
1915 						if (iTotalRead >= 1024)
1916 							printf("Read LBA from file (%d%%)\r\n", (iTotalRead / 1024) * 100 / ((uiLen + iTotalRead) / 1024));
1917 						else
1918 							printf("Read LBA from file %d%%)\r\n", iTotalRead * 100 / (uiLen + iTotalRead));
1919 					}
1920 				}
1921 				else
1922 					PrintData(pBuf, nSectorSize * iRead);
1923 			} else {
1924 				if (g_pLogObject)
1925 					g_pLogObject->Record("Error:RKU_ReadLBA failed,err=%d", iRet);
1926 
1927 				printf("Read LBA failed!\r\n");
1928 				goto Exit_ReadLBA;
1929 			}
1930 		}
1931 		bSuccess = true;
1932 	} else {
1933 		printf("Read LBA quit,Creating comm object failed!\r\n");
1934 	}
1935 Exit_ReadLBA:
1936 	if (pComm) {
1937 		delete pComm;
1938 		pComm = NULL;
1939 	}
1940 	if (file)
1941 		fclose(file);
1942 	return bSuccess;
1943 }
1944 bool write_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, char *szFile)
1945 {
1946 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
1947 		return false;
1948 	CRKUsbComm *pComm = NULL;
1949 	FILE *file = NULL;
1950 	bool bRet, bFirst = true, bSuccess = false;
1951 	int iRet;
1952 	long long iTotalWrite = 0, iFileSize = 0;
1953 	UINT iWrite = 0, iRead = 0;
1954 	UINT uiLen;
1955 	int nSectorSize = 512;
1956 	BYTE pBuf[nSectorSize * DEFAULT_RW_LBA];
1957 
1958 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
1959 	if (bRet) {
1960 		file = fopen(szFile, "rb");
1961 		if( !file ) {
1962 			printf("Write LBA failed,err=%d,can't open file: %s\r\n", errno, szFile);
1963 			goto Exit_WriteLBA;
1964 		}
1965 
1966 		iRet = fseeko(file, 0, SEEK_END);
1967 		iFileSize = ftello(file);
1968 		fseeko(file, 0, SEEK_SET);
1969 		while(iTotalWrite < iFileSize) {
1970 			memset(pBuf, 0, nSectorSize * DEFAULT_RW_LBA);
1971 			iWrite = iRead= fread(pBuf, 1, nSectorSize * DEFAULT_RW_LBA, file);
1972 			uiLen = ((iWrite % 512) == 0) ? (iWrite / 512) : (iWrite / 512 + 1);
1973 			iRet = pComm->RKU_WriteLBA( uiBegin, uiLen, pBuf);
1974 			if(ERR_SUCCESS == iRet) {
1975 				uiBegin += uiLen;
1976 				iTotalWrite += iWrite;
1977 				if (bFirst) {
1978 					if (iTotalWrite >= 1024)
1979 						printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
1980 					else
1981 						printf("Write LBA from file %lld%%)\r\n", iTotalWrite * 100 / iFileSize);
1982 					bFirst = false;
1983 				} else {
1984 					CURSOR_MOVEUP_LINE(1);
1985 					CURSOR_DEL_LINE;
1986 					printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
1987 				}
1988 			} else {
1989 				if (g_pLogObject)
1990 					g_pLogObject->Record("Error:RKU_WriteLBA failed,err=%d", iRet);
1991 
1992 				printf("Write LBA failed!\r\n");
1993 				goto Exit_WriteLBA;
1994 			}
1995 		}
1996 		bSuccess = true;
1997 	} else {
1998 		printf("Write LBA quit,Creating comm object failed!\r\n");
1999 	}
2000 Exit_WriteLBA:
2001 	if (pComm) {
2002 		delete pComm;
2003 		pComm = NULL;
2004 	}
2005 	if (file)
2006 		fclose(file);
2007 	return bSuccess;
2008 }
2009 
2010 void split_item(STRING_VECTOR &vecItems, char *pszItems)
2011 {
2012 	string strItem;
2013 	char szItem[100];
2014 	char *pos = NULL, *pStart;
2015 	pStart = pszItems;
2016 	pos = strchr(pStart, ',');
2017 	while(pos != NULL) {
2018 		memset(szItem, 0, 100);
2019 		strncpy(szItem, pStart, pos - pStart);
2020 		strItem = szItem;
2021 		vecItems.push_back(strItem);
2022 		pStart = pos + 1;
2023 		if (*pStart == 0)
2024 			break;
2025 		pos = strchr(pStart, ',');
2026 	}
2027 	if (strlen(pStart) > 0) {
2028 		memset(szItem, 0, 100);
2029 		strncpy(szItem, pStart, strlen(pStart));
2030 		strItem = szItem;
2031 		vecItems.push_back(strItem);
2032 	}
2033 }
2034 
2035 bool handle_command(int argc, char* argv[], CRKScan *pScan)
2036 {
2037 	string strCmd;
2038 	strCmd = argv[1];
2039 	ssize_t cnt;
2040 	bool bRet,bSuccess = false;
2041 	char *s;
2042 	int i, ret;
2043 	STRUCT_RKDEVICE_DESC dev;
2044 
2045 	transform(strCmd.begin(), strCmd.end(), strCmd.begin(), (int(*)(int))toupper);
2046 	s = (char*)strCmd.c_str();
2047 	for(i = 0; i < (int)strlen(s); i++)
2048 	        s[i] = toupper(s[i]);
2049 
2050 	if((strcmp(strCmd.c_str(), "-H") == 0) || (strcmp(strCmd.c_str(), "--HELP")) == 0){
2051 		usage();
2052 		return true;
2053 	} else if((strcmp(strCmd.c_str(), "-V") == 0) || (strcmp(strCmd.c_str(), "--VERSION") == 0)) {
2054 		printf("rkdeveloptool ver %s\r\n", PACKAGE_VERSION);
2055 		return true;
2056 	} else if (strcmp(strCmd.c_str(), "PACK") == 0) {//pack boot loader
2057 		mergeBoot();
2058 
2059 		return true;
2060 	} else if (strcmp(strCmd.c_str(), "UNPACK") == 0) {//unpack boot loader
2061 		string strLoader = argv[2];
2062 
2063 		unpackBoot((char*)strLoader.c_str());
2064 		return true;
2065 	}
2066 	cnt = pScan->Search(RKUSB_MASKROM | RKUSB_LOADER);
2067 	if (cnt < 1) {
2068 		ERROR_COLOR_ATTR;
2069 		printf("No found any rockusb device,please plug device in!");
2070 		NORMAL_COLOR_ATTR;
2071 		printf("\r\n");
2072 		return bSuccess;
2073 	} else if (cnt > 1) {
2074 		ERROR_COLOR_ATTR;
2075 		printf("Found many rockusb devices,please plug device out!");
2076 		NORMAL_COLOR_ATTR;
2077 		printf("\r\n");
2078 		return bSuccess;
2079 	}
2080 
2081 	bRet = pScan->GetDevice(dev, 0);
2082 	if (!bRet) {
2083 		ERROR_COLOR_ATTR;
2084 		printf("Getting information of rockusb device failed!");
2085 		NORMAL_COLOR_ATTR;
2086 		printf("\r\n");
2087 		return bSuccess;
2088 	}
2089 
2090 	if(strcmp(strCmd.c_str(), "RD") == 0) {
2091 		if ((argc != 2) && (argc != 3))
2092 			printf("Parameter of [RD] command is invalid,please check help!\r\n");
2093 		else {
2094 			if (argc == 2)
2095 				bSuccess = reset_device(dev);
2096 			else {
2097 				UINT uiSubCode;
2098 				char *pszEnd;
2099 				uiSubCode = strtoul(argv[2], &pszEnd, 0);
2100 				if (*pszEnd)
2101 					printf("Subcode is invalid,please check!\r\n");
2102 				else {
2103 					if (uiSubCode <= 5)
2104 						bSuccess = reset_device(dev, uiSubCode);
2105 					else
2106 						printf("Subcode is invalid,please check!\r\n");
2107 				}
2108 			}
2109 		}
2110 	} else if(strcmp(strCmd.c_str(), "TD") == 0) {
2111 		bSuccess = test_device(dev);
2112 	} else if (strcmp(strCmd.c_str(), "RID") == 0) {//Read Flash ID
2113 		bSuccess = read_flash_id(dev);
2114 	} else if (strcmp(strCmd.c_str(), "RFI") == 0){//Read Flash Info
2115 		bSuccess = read_flash_info(dev);
2116 	} else if (strcmp(strCmd.c_str(), "RCI") == 0) {//Read Chip Info
2117 		bSuccess = read_chip_info(dev);
2118 	} else if(strcmp(strCmd.c_str(), "DB") == 0) {
2119 		if (argc > 2) {
2120 			string strLoader;
2121 			strLoader = argv[2];
2122 			bSuccess = download_boot(dev, (char *)strLoader.c_str());
2123 		} else if (argc == 2) {
2124 			ret = find_config_item("loader");
2125 			if (ret == -1)
2126 				printf("No found loader item from config!\r\n");
2127 			else
2128 				bSuccess = download_boot(dev, g_ConfigItemVec[ret].szItemValue);
2129 		} else
2130 			printf("Parameter of [DB] command is invalid,please check help!\r\n");
2131 	} else if(strcmp(strCmd.c_str(), "GPT") == 0) {
2132 		if (argc > 2) {
2133 			string strParameter;
2134 			strParameter = argv[2];
2135 			bSuccess = write_gpt(dev, (char *)strParameter.c_str());
2136 		} else
2137 			printf("Parameter of [GPT] command is invalid,please check help!\r\n");
2138 	} else if(strcmp(strCmd.c_str(), "UL") == 0) {
2139 		if (argc > 2) {
2140 			string strLoader;
2141 			strLoader = argv[2];
2142 			bSuccess = upgrade_loader(dev, (char *)strLoader.c_str());
2143 		} else
2144 			printf("Parameter of [UL] command is invalid,please check help!\r\n");
2145 	} else if(strcmp(strCmd.c_str(), "EF") == 0) {
2146 		if (argc == 2) {
2147 			bSuccess = erase_flash(dev);
2148 		} else
2149 			printf("Parameter of [EF] command is invalid,please check help!\r\n");
2150 	} else if(strcmp(strCmd.c_str(), "WL") == 0) {
2151 		if (argc == 4) {
2152 			UINT uiBegin;
2153 			char *pszEnd;
2154 			uiBegin = strtoul(argv[2], &pszEnd, 0);
2155 			if (*pszEnd)
2156 				printf("Begin is invalid,please check!\r\n");
2157 			else
2158 				bSuccess = write_lba(dev, uiBegin, argv[3]);
2159 		} else
2160 			printf("Parameter of [WL] command is invalid,please check help!\r\n");
2161 	} else if (strcmp(strCmd.c_str(), "RL") == 0) {//Read LBA
2162 		char *pszEnd;
2163 		UINT uiBegin, uiLen;
2164 		if (argc != 5)
2165 			printf("Parameter of [RL] command is invalid,please check help!\r\n");
2166 		else {
2167 			uiBegin = strtoul(argv[2], &pszEnd, 0);
2168 			if (*pszEnd)
2169 				printf("Begin is invalid,please check!\r\n");
2170 			else {
2171 				uiLen = strtoul(argv[3], &pszEnd, 0);
2172 				if (*pszEnd)
2173 					printf("Len is invalid,please check!\r\n");
2174 				else {
2175 					bSuccess = read_lba(dev, uiBegin, uiLen, argv[4]);
2176 				}
2177 			}
2178 		}
2179 	} else {
2180 		printf("command is invalid,please press rkDevelopTool -h to check usage!\r\n");
2181 	}
2182 	return bSuccess;
2183 }
2184 
2185 
2186 int main(int argc, char* argv[])
2187 {
2188 	CRKScan *pScan = NULL;
2189 	int ret;
2190 	char szProgramProcPath[100];
2191 	char szProgramDir[256];
2192 	string strLogDir,strConfigFile;
2193 	struct stat statBuf;
2194 
2195 	g_ConfigItemVec.clear();
2196 	sprintf(szProgramProcPath, "/proc/%d/exe", getpid());
2197 	if (readlink(szProgramProcPath, szProgramDir, 256) == -1)
2198 		strcpy(szProgramDir, ".");
2199 	else {
2200 		char *pSlash;
2201 		pSlash = strrchr(szProgramDir, '/');
2202 		if (pSlash)
2203 			*pSlash = '\0';
2204 	}
2205 	strLogDir = szProgramDir;
2206 	strLogDir +=  "/log/";
2207 	strConfigFile = szProgramDir;
2208 	strConfigFile += "/config.ini";
2209 	if (opendir(strLogDir.c_str()) == NULL)
2210 		mkdir(strLogDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH);
2211 	g_pLogObject = new CRKLog(strLogDir.c_str(), "log");
2212 
2213 	if(stat(strConfigFile.c_str(), &statBuf) < 0) {
2214 		if (g_pLogObject) {
2215 			g_pLogObject->Record("Error:failed to stat config.ini,err=%d", errno);
2216 		}
2217 	} else if (S_ISREG(statBuf.st_mode)) {
2218 		parse_config_file(strConfigFile.c_str(), g_ConfigItemVec);
2219 	}
2220 
2221 	ret = libusb_init(NULL);
2222 	if (ret < 0) {
2223 		if (g_pLogObject) {
2224 			g_pLogObject->Record("Error:libusb_init failed,err=%d", ret);
2225 			delete g_pLogObject;
2226 		}
2227 		return -1;
2228 	}
2229 
2230 	pScan = new CRKScan();
2231 	if (!pScan) {
2232 		if (g_pLogObject) {
2233 			g_pLogObject->Record("Error:failed to Create object for searching device");
2234 			delete g_pLogObject;
2235 		}
2236 		libusb_exit(NULL);
2237 		return -2;
2238 	}
2239 	pScan->SetVidPid();
2240 
2241 	if (argc == 1)
2242 		usage();
2243 	else if (!handle_command(argc, argv, pScan))
2244 			return -0xFF;
2245 	if (pScan)
2246 		delete pScan;
2247 	if (g_pLogObject)
2248 		delete g_pLogObject;
2249 	libusb_exit(NULL);
2250 	return 0;
2251 }
2252