xref: /rkdeveloptool/main.cpp (revision 08c0d218889dacdac3705605cdb4bb920daed9eb)
176af099aSliuyi /*
276af099aSliuyi  * (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd
376af099aSliuyi  * Seth Liu 2017.03.01
476af099aSliuyi  *
576af099aSliuyi  * SPDX-License-Identifier:	GPL-2.0+
676af099aSliuyi  */
776af099aSliuyi 
876af099aSliuyi #include   <unistd.h>
976af099aSliuyi #include   <dirent.h>
10c30d921cSKever Yang #include "config.h"
1176af099aSliuyi #include "DefineHeader.h"
12c30d921cSKever Yang #include "gpt.h"
1376af099aSliuyi #include "RKLog.h"
1476af099aSliuyi #include "RKScan.h"
1576af099aSliuyi #include "RKComm.h"
1676af099aSliuyi #include "RKDevice.h"
1776af099aSliuyi #include "RKImage.h"
1876af099aSliuyi extern const char *szManufName[];
1976af099aSliuyi CRKLog *g_pLogObject=NULL;
2076af099aSliuyi CONFIG_ITEM_VECTOR g_ConfigItemVec;
2176af099aSliuyi #define DEFAULT_RW_LBA 128
2276af099aSliuyi #define CURSOR_MOVEUP_LINE(n) printf("%c[%dA", 0x1B, n)
2376af099aSliuyi #define CURSOR_DEL_LINE printf("%c[2K", 0x1B)
2476af099aSliuyi #define CURSOR_MOVE_HOME printf("%c[H", 0x1B)
2576af099aSliuyi #define CURSOR_CLEAR_SCREEN printf("%c[2J", 0x1B)
2676af099aSliuyi #define ERROR_COLOR_ATTR  printf("%c[30;41m", 0x1B);
273601cc08SAndreas Färber #define NORMAL_COLOR_ATTR  printf("%c[0m", 0x1B);
28c30d921cSKever Yang extern UINT CRC_32(unsigned char* pData, UINT ulSize);
29c30d921cSKever Yang extern unsigned short CRC_16(unsigned char* aData, UINT aSize);
30c30d921cSKever Yang extern void P_RC4(unsigned char* buf, unsigned short len);
31c30d921cSKever Yang extern unsigned int crc32_le(unsigned int crc, unsigned char *p, unsigned int len);
32c30d921cSKever Yang /*
33c30d921cSKever Yang u8 test_gpt_head[] = {
34c30d921cSKever Yang 	0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54, 0x00, 0x00, 0x01, 0x00, 0x5C, 0x00, 0x00, 0x00,
35c30d921cSKever Yang 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36c30d921cSKever Yang 	0xFF, 0xFF, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37c30d921cSKever Yang 	0xDE, 0xFF, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x49, 0x94, 0xEC, 0x23, 0xE8, 0x58, 0x4B,
38c30d921cSKever Yang 	0xAE, 0xB7, 0xA9, 0x46, 0x51, 0xD0, 0x08, 0xF8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39c30d921cSKever Yang 	0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x51, 0xEA, 0xFE, 0x08};
40c30d921cSKever Yang */
41c30d921cSKever Yang 
4276af099aSliuyi void usage()
4376af099aSliuyi {
4476af099aSliuyi 	printf("\r\n---------------------Tool Usage ---------------------\r\n");
45154ee062SEddie Cai 	printf("Help:\t\t\t-h or --version\r\n");
46154ee062SEddie Cai 	printf("Version:\t\t-v or --version\r\n");
47154ee062SEddie Cai 	printf("DownloadBoot:\t\tdb <Loader>\r\n");
48154ee062SEddie Cai 	printf("UpgradeLoader:\t\tul <Loader>\r\n");
49154ee062SEddie Cai 	printf("ReadLBA:\t\trl  <BeginSec> <SectorLen> <File>\r\n");
50154ee062SEddie Cai 	printf("WriteLBA:\t\twl  <BeginSec> <File>\r\n");
516ae612beSliuyi 	printf("WriteLBA:\t\twlx  <PartitionName> <File>\r\n");
52154ee062SEddie Cai 	printf("WriteGPT:\t\tgpt <gpt partition table>\r\n");
533dc7e3ceSliuyi 	printf("PrintGPT:\t\tpgpt \r\n");
54154ee062SEddie Cai 	printf("EraseFlash:\t\tef \r\n");
55154ee062SEddie Cai 	printf("TestDevice:\t\ttd\r\n");
56154ee062SEddie Cai 	printf("ResetDevice:\t\trd [subcode]\r\n");
57154ee062SEddie Cai 	printf("ReadFlashID:\t\trid\r\n");
58154ee062SEddie Cai 	printf("ReadFlashInfo:\t\trfi\r\n");
59154ee062SEddie Cai 	printf("ReadChipInfo:\t\trci\r\n");
6078884ef4SEddie Cai 	printf("PackBootLoader:\t\tpack\r\n");
6178884ef4SEddie Cai 	printf("UnpackBootLoader:\tunpack <boot loader>\r\n");
62d71e8c20SEddie Cai 	printf("TagSPL:\t\t\ttagspl <tag> <U-Boot SPL>\r\n");
6376af099aSliuyi 	printf("-------------------------------------------------------\r\n\r\n");
6476af099aSliuyi }
6576af099aSliuyi void ProgressInfoProc(DWORD deviceLayer, ENUM_PROGRESS_PROMPT promptID, long long totalValue, long long currentValue, ENUM_CALL_STEP emCall)
6676af099aSliuyi {
6776af099aSliuyi 	string strInfoText="";
6876af099aSliuyi 	char szText[256];
6976af099aSliuyi 	switch (promptID) {
7076af099aSliuyi 	case TESTDEVICE_PROGRESS:
7132268622SAndreas Färber 		sprintf(szText, "Test Device total %lld, current %lld", totalValue, currentValue);
7276af099aSliuyi 		strInfoText = szText;
7376af099aSliuyi 		break;
7476af099aSliuyi 	case LOWERFORMAT_PROGRESS:
7532268622SAndreas Färber 		sprintf(szText, "Lowerformat Device total %lld, current %lld", totalValue, currentValue);
7676af099aSliuyi 		strInfoText = szText;
7776af099aSliuyi 		break;
7876af099aSliuyi 	case DOWNLOADIMAGE_PROGRESS:
7932268622SAndreas Färber 		sprintf(szText, "Download Image total %lldK, current %lldK", totalValue/1024, currentValue/1024);
8076af099aSliuyi 		strInfoText = szText;
8176af099aSliuyi 		break;
8276af099aSliuyi 	case CHECKIMAGE_PROGRESS:
8332268622SAndreas Färber 		sprintf(szText, "Check Image total %lldK, current %lldK", totalValue/1024, currentValue/1024);
8476af099aSliuyi 		strInfoText = szText;
8576af099aSliuyi 		break;
8676af099aSliuyi 	case TAGBADBLOCK_PROGRESS:
8732268622SAndreas Färber 		sprintf(szText, "Tag Bad Block total %lld, current %lld", totalValue, currentValue);
8876af099aSliuyi 		strInfoText = szText;
8976af099aSliuyi 		break;
9076af099aSliuyi 	case TESTBLOCK_PROGRESS:
9132268622SAndreas Färber 		sprintf(szText, "Test Block total %lld, current %lld", totalValue, currentValue);
9276af099aSliuyi 		strInfoText = szText;
9376af099aSliuyi 		break;
9476af099aSliuyi 	case ERASEFLASH_PROGRESS:
9532268622SAndreas Färber 		sprintf(szText, "Erase Flash total %lld, current %lld", totalValue, currentValue);
9676af099aSliuyi 		strInfoText = szText;
9776af099aSliuyi 		break;
9876af099aSliuyi 	case ERASESYSTEM_PROGRESS:
9932268622SAndreas Färber 		sprintf(szText, "Erase System partition total %lld, current %lld", totalValue, currentValue);
10076af099aSliuyi 		strInfoText = szText;
10176af099aSliuyi 		break;
10276af099aSliuyi 	case ERASEUSERDATA_PROGRESS:
10332268622SAndreas Färber 		sprintf(szText, "<LocationID=%x> Erase Userdata partition total %lld, current %lld", deviceLayer, totalValue, currentValue);
10476af099aSliuyi 		strInfoText = szText;
10576af099aSliuyi 		break;
10676af099aSliuyi 	}
10776af099aSliuyi 	if (strInfoText.size() > 0){
10876af099aSliuyi 		CURSOR_MOVEUP_LINE(1);
10976af099aSliuyi 		CURSOR_DEL_LINE;
11076af099aSliuyi 		printf("%s\r\n", strInfoText.c_str());
11176af099aSliuyi 	}
11276af099aSliuyi 	if (emCall == CALL_LAST)
11376af099aSliuyi 		deviceLayer = 0;
11476af099aSliuyi }
11576af099aSliuyi 
11676af099aSliuyi char *strupr(char *szSrc)
11776af099aSliuyi {
11876af099aSliuyi 	char *p = szSrc;
11976af099aSliuyi 	while(*p){
12076af099aSliuyi 		if ((*p >= 'a') && (*p <= 'z'))
12176af099aSliuyi 			*p = *p - 'a' + 'A';
12276af099aSliuyi 		p++;
12376af099aSliuyi 	}
12476af099aSliuyi 	return szSrc;
12576af099aSliuyi }
12676af099aSliuyi void PrintData(PBYTE pData, int nSize)
12776af099aSliuyi {
12876af099aSliuyi 	char szPrint[17] = "\0";
12976af099aSliuyi 	int i;
13076af099aSliuyi 	for( i = 0; i < nSize; i++){
13176af099aSliuyi 		if(i % 16 == 0){
13276af099aSliuyi 			if(i / 16 > 0)
13376af099aSliuyi 				printf("     %s\r\n", szPrint);
13476af099aSliuyi 			printf("%08d ", i / 16);
13576af099aSliuyi 		}
13676af099aSliuyi 		printf("%02X ", pData[i]);
13776af099aSliuyi 		szPrint[i%16] = isprint(pData[i]) ? pData[i] : '.';
13876af099aSliuyi 	}
13976af099aSliuyi 	if(i / 16 > 0)
14076af099aSliuyi 		printf("     %s\r\n", szPrint);
14176af099aSliuyi }
14276af099aSliuyi 
14376af099aSliuyi bool StringToWideString(char *pszSrc, wchar_t *&pszDest)
14476af099aSliuyi {
14576af099aSliuyi 	if (!pszSrc)
14676af099aSliuyi 		return false;
14776af099aSliuyi 	int nSrcLen = strlen(pszSrc);
14876af099aSliuyi 	int nDestLen = nSrcLen * 2;
14976af099aSliuyi 
15076af099aSliuyi 	pszDest = NULL;
15176af099aSliuyi 	pszDest = new wchar_t[nDestLen];
15276af099aSliuyi 	if (!pszDest)
15376af099aSliuyi 		return false;
15476af099aSliuyi 	nDestLen = nDestLen * sizeof(wchar_t);
15576af099aSliuyi 	memset(pszDest, 0, nDestLen);
15676af099aSliuyi 	int iRet;
15776af099aSliuyi 	iconv_t cd;
15876af099aSliuyi 	cd = iconv_open("UTF-32", "UTF-8");
15976af099aSliuyi 	if((iconv_t)-1 == cd) {
16076af099aSliuyi 		delete []pszDest;
16176af099aSliuyi 		pszDest = NULL;
16276af099aSliuyi 	      return false;
16376af099aSliuyi 	 }
16476af099aSliuyi 	char *pIn, *pOut;
16576af099aSliuyi 	pIn = (char *)pszSrc;
16676af099aSliuyi 	pOut = (char *)pszDest;
16776af099aSliuyi 
16876af099aSliuyi 	iRet = iconv(cd, (char **)&pIn, (size_t *)&nSrcLen, (char **)&pOut, (size_t *)&nDestLen);
16976af099aSliuyi 
17076af099aSliuyi 	if(iRet == -1) {
17176af099aSliuyi 		delete []pszDest;
17276af099aSliuyi 		pszDest = NULL;
17376af099aSliuyi 		iconv_close(cd);
17476af099aSliuyi 		return false;
17576af099aSliuyi 	 }
17676af099aSliuyi 
17776af099aSliuyi 	 iconv_close(cd);
17876af099aSliuyi 
17976af099aSliuyi 	 return true;
18076af099aSliuyi }
18176af099aSliuyi bool WideStringToString(wchar_t *pszSrc, char *&pszDest)
18276af099aSliuyi {
18376af099aSliuyi 	if (!pszSrc)
18476af099aSliuyi 		return false;
18576af099aSliuyi 	int nSrcLen = wcslen(pszSrc);
18676af099aSliuyi 	int nDestLen = nSrcLen * 2;
18776af099aSliuyi 	nSrcLen = nSrcLen * sizeof(wchar_t);
18876af099aSliuyi 	pszDest = NULL;
18976af099aSliuyi 	pszDest = new char[nDestLen];
19076af099aSliuyi 	if (!pszDest)
19176af099aSliuyi 		return false;
19276af099aSliuyi 	memset(pszDest, 0, nDestLen);
19376af099aSliuyi 	int iRet;
19476af099aSliuyi 	iconv_t cd;
19576af099aSliuyi 	cd = iconv_open("UTF-8", "UTF-32");
19676af099aSliuyi 
19776af099aSliuyi 	if((iconv_t)-1 == cd) {
19876af099aSliuyi 		delete []pszDest;
19976af099aSliuyi 		pszDest = NULL;
20076af099aSliuyi 	      return false;
20176af099aSliuyi 	 }
20276af099aSliuyi 	char *pIn, *pOut;
20376af099aSliuyi 	pIn = (char *)pszSrc;
20476af099aSliuyi 	pOut = (char *)pszDest;
20576af099aSliuyi 	iRet = iconv(cd, (char **)&pIn, (size_t *)&nSrcLen, (char **)&pOut, (size_t *)&nDestLen);
20676af099aSliuyi 
20776af099aSliuyi 	if(iRet == -1) {
20876af099aSliuyi 		delete []pszDest;
20976af099aSliuyi 		pszDest = NULL;
21076af099aSliuyi 		iconv_close(cd);
21176af099aSliuyi 		return false;
21276af099aSliuyi 	 }
21376af099aSliuyi 
21476af099aSliuyi 	 iconv_close(cd);
21576af099aSliuyi 
21676af099aSliuyi 	 return true;
21776af099aSliuyi }
218c29e5f0fSliuyi int find_config_item(CONFIG_ITEM_VECTOR &vecItems, const char *pszName)
21976af099aSliuyi {
22076af099aSliuyi 	unsigned int i;
221c29e5f0fSliuyi 	for(i = 0; i < vecItems.size(); i++){
222c29e5f0fSliuyi 		if (strcasecmp(pszName, vecItems[i].szItemName) == 0){
22376af099aSliuyi 			return i;
22476af099aSliuyi 		}
22576af099aSliuyi 	}
22676af099aSliuyi 	return -1;
22776af099aSliuyi }
228c29e5f0fSliuyi void string_to_uuid(string strUUid, char *uuid)
229c29e5f0fSliuyi {
230c29e5f0fSliuyi 	unsigned int i;
231c29e5f0fSliuyi 	char value;
232c29e5f0fSliuyi 	memset(uuid, 0, 16);
233c29e5f0fSliuyi 	for (i =0; i < strUUid.size(); i++) {
234c29e5f0fSliuyi 		value = 0;
235c29e5f0fSliuyi 		if ((strUUid[i] >= '0')&&(strUUid[i] <= '9'))
236c29e5f0fSliuyi 			value = strUUid[i] - '0';
237c29e5f0fSliuyi 		if ((strUUid[i] >= 'a')&&(strUUid[i] <= 'f'))
238c29e5f0fSliuyi 			value = strUUid[i] - 'a' + 10;
239c29e5f0fSliuyi 		if ((strUUid[i] >= 'A')&&(strUUid[i] <= 'F'))
240c29e5f0fSliuyi 			value = strUUid[i] - 'A' + 10;
241c29e5f0fSliuyi 		if ((i % 2) == 0)
242c29e5f0fSliuyi 			uuid[i / 2] += (value << 4);
243c29e5f0fSliuyi 		else
244c29e5f0fSliuyi 			uuid[i / 2] += value;
245c29e5f0fSliuyi 	}
246c29e5f0fSliuyi 	unsigned int *p32;
247c29e5f0fSliuyi 	unsigned short *p16;
248c29e5f0fSliuyi 	p32 = (unsigned int*)uuid;
249c29e5f0fSliuyi 	*p32 = cpu_to_be32(*p32);
250c29e5f0fSliuyi 	p16 = (unsigned short *)(uuid + 4);
251c29e5f0fSliuyi 	*p16 = cpu_to_be16(*p16);
252c29e5f0fSliuyi 	p16 = (unsigned short *)(uuid + 6);
253c29e5f0fSliuyi 	*p16 = cpu_to_be16(*p16);
254c29e5f0fSliuyi }
25576af099aSliuyi 
25676af099aSliuyi bool parse_config(char *pConfig, CONFIG_ITEM_VECTOR &vecItem)
25776af099aSliuyi {
25876af099aSliuyi 
25976af099aSliuyi 	stringstream configStream(pConfig);
26076af099aSliuyi 	string strLine, strItemName, strItemValue;
26176af099aSliuyi 	string::size_type line_size,pos;
26276af099aSliuyi 	STRUCT_CONFIG_ITEM item;
26376af099aSliuyi 	vecItem.clear();
26476af099aSliuyi 	while (!configStream.eof()){
26576af099aSliuyi 		getline(configStream, strLine);
26676af099aSliuyi 		line_size = strLine.size();
26776af099aSliuyi 		if (line_size == 0)
26876af099aSliuyi 			continue;
26976af099aSliuyi 		if (strLine[line_size-1] == '\r'){
27076af099aSliuyi 			strLine = strLine.substr(0, line_size-1);
27176af099aSliuyi 		}
272c30d921cSKever Yang 		strLine.erase(0, strLine.find_first_not_of(" "));
273c30d921cSKever Yang 		strLine.erase(strLine.find_last_not_of(" ") + 1);
274c30d921cSKever Yang 		if (strLine.size()==0 )
275c30d921cSKever Yang 			continue;
276c30d921cSKever Yang 		if (strLine[0] == '#')
277c30d921cSKever Yang 			continue;
27876af099aSliuyi 		pos = strLine.find("=");
27976af099aSliuyi 		if (pos == string::npos){
28076af099aSliuyi 			continue;
28176af099aSliuyi 		}
28276af099aSliuyi 		strItemName = strLine.substr(0, pos);
28376af099aSliuyi 		strItemValue = strLine.substr(pos + 1);
28476af099aSliuyi 		strItemName.erase(0, strItemName.find_first_not_of(" "));
28576af099aSliuyi 		strItemName.erase(strItemName.find_last_not_of(" ") + 1);
28676af099aSliuyi 		strItemValue.erase(0, strItemValue.find_first_not_of(" "));
28776af099aSliuyi 		strItemValue.erase(strItemValue.find_last_not_of(" ") + 1);
28876af099aSliuyi 		if ((strItemName.size() > 0) && (strItemValue.size() > 0)){
28976af099aSliuyi 			strcpy(item.szItemName, strItemName.c_str());
29076af099aSliuyi 			strcpy(item.szItemValue, strItemValue.c_str());
29176af099aSliuyi 			vecItem.push_back(item);
29276af099aSliuyi 		}
29376af099aSliuyi 	}
29476af099aSliuyi 	return true;
29576af099aSliuyi 
29676af099aSliuyi }
29776af099aSliuyi bool parse_config_file(const char *pConfigFile, CONFIG_ITEM_VECTOR &vecItem)
29876af099aSliuyi {
29976af099aSliuyi 	FILE *file = NULL;
30076af099aSliuyi 	file = fopen(pConfigFile, "rb");
30176af099aSliuyi 	if( !file ){
30276af099aSliuyi 		if (g_pLogObject)
30332268622SAndreas Färber 			g_pLogObject->Record("%s failed, err=%d, can't open file: %s\r\n", __func__, errno, pConfigFile);
30476af099aSliuyi 		return false;
30576af099aSliuyi 	}
30676af099aSliuyi 	int iFileSize;
30776af099aSliuyi 	fseek(file, 0, SEEK_END);
30876af099aSliuyi 	iFileSize = ftell(file);
30976af099aSliuyi 	fseek(file, 0, SEEK_SET);
31076af099aSliuyi 	char *pConfigBuf = NULL;
31176af099aSliuyi 	pConfigBuf = new char[iFileSize + 1];
31276af099aSliuyi 	if (!pConfigBuf){
31376af099aSliuyi 		fclose(file);
31476af099aSliuyi 		return false;
31576af099aSliuyi 	}
31676af099aSliuyi 	memset(pConfigBuf, 0, iFileSize + 1);
31776af099aSliuyi 	int iRead;
31876af099aSliuyi 	iRead = fread(pConfigBuf, 1, iFileSize, file);
31976af099aSliuyi 	if (iRead != iFileSize){
32076af099aSliuyi 		if (g_pLogObject)
32132268622SAndreas Färber 			g_pLogObject->Record("%s failed, err=%d, read=%d, total=%d\r\n", __func__, errno, iRead, iFileSize);
32276af099aSliuyi 		fclose(file);
32376af099aSliuyi 		delete []pConfigBuf;
32476af099aSliuyi 		return false;
32576af099aSliuyi 	}
32676af099aSliuyi 	fclose(file);
32776af099aSliuyi 	bool bRet;
32876af099aSliuyi 	bRet = parse_config(pConfigBuf, vecItem);
32976af099aSliuyi 	delete []pConfigBuf;
33076af099aSliuyi 	return bRet;
33176af099aSliuyi }
332c30d921cSKever Yang bool ParsePartitionInfo(string &strPartInfo, string &strName, UINT &uiOffset, UINT &uiLen)
333c30d921cSKever Yang {
334c30d921cSKever Yang 	string::size_type pos,prevPos;
335c30d921cSKever Yang 	string strOffset,strLen;
336c30d921cSKever Yang 	int iCount;
337c30d921cSKever Yang 	prevPos = pos = 0;
338c30d921cSKever Yang 	if (strPartInfo.size() <= 0) {
339c30d921cSKever Yang 		return false;
340c30d921cSKever Yang 	}
341c30d921cSKever Yang 	pos = strPartInfo.find('@');
342c30d921cSKever Yang 	if (pos == string::npos) {
343c30d921cSKever Yang 		return false;
344c30d921cSKever Yang 	}
345c30d921cSKever Yang 	strLen = strPartInfo.substr(prevPos, pos - prevPos);
346c30d921cSKever Yang 	strLen.erase(0, strLen.find_first_not_of(" "));
347c30d921cSKever Yang 	strLen.erase(strLen.find_last_not_of(" ") + 1);
348c30d921cSKever Yang 	if (strchr(strLen.c_str(), '-')) {
349c30d921cSKever Yang 		uiLen = 0xFFFFFFFF;
350c30d921cSKever Yang 	} else {
351c30d921cSKever Yang 		iCount = sscanf(strLen.c_str(), "0x%x", &uiLen);
352c30d921cSKever Yang 		if (iCount != 1) {
353c30d921cSKever Yang 			return false;
354c30d921cSKever Yang 		}
355c30d921cSKever Yang 	}
356c30d921cSKever Yang 
357c30d921cSKever Yang 	prevPos = pos + 1;
358c30d921cSKever Yang 	pos = strPartInfo.find('(',prevPos);
359c30d921cSKever Yang 	if (pos == string::npos) {
360c30d921cSKever Yang 		return false;
361c30d921cSKever Yang 	}
362c30d921cSKever Yang 	strOffset = strPartInfo.substr(prevPos, pos - prevPos);
363c30d921cSKever Yang 	strOffset.erase(0, strOffset.find_first_not_of(" "));
364c30d921cSKever Yang 	strOffset.erase(strOffset.find_last_not_of(" ") + 1);
365c30d921cSKever Yang 	iCount = sscanf(strOffset.c_str(), "0x%x", &uiOffset);
366c30d921cSKever Yang 	if (iCount != 1) {
367c30d921cSKever Yang 		return false;
368c30d921cSKever Yang 	}
369c30d921cSKever Yang 	prevPos = pos + 1;
370c30d921cSKever Yang 	pos = strPartInfo.find(')', prevPos);
371c30d921cSKever Yang 	if (pos == string::npos) {
372c30d921cSKever Yang 		return false;
373c30d921cSKever Yang 	}
374c30d921cSKever Yang 	strName = strPartInfo.substr(prevPos, pos - prevPos);
375c30d921cSKever Yang 	strName.erase(0, strName.find_first_not_of(" "));
376c30d921cSKever Yang 	strName.erase(strName.find_last_not_of(" ") + 1);
377c30d921cSKever Yang 
378c30d921cSKever Yang 	return true;
379c30d921cSKever Yang }
380c29e5f0fSliuyi bool ParseUuidInfo(string &strUuidInfo, string &strName, string &strUUid)
381c29e5f0fSliuyi {
382c29e5f0fSliuyi 	string::size_type pos(0);
383c30d921cSKever Yang 
384c29e5f0fSliuyi 	if (strUuidInfo.size() <= 0) {
385c29e5f0fSliuyi 		return false;
386c29e5f0fSliuyi 	}
387c29e5f0fSliuyi 	pos = strUuidInfo.find('=');
388c29e5f0fSliuyi 	if (pos == string::npos) {
389c29e5f0fSliuyi 		return false;
390c29e5f0fSliuyi 	}
391c29e5f0fSliuyi 	strName = strUuidInfo.substr(0, pos);
392c29e5f0fSliuyi 	strName.erase(0, strName.find_first_not_of(" "));
393c29e5f0fSliuyi 	strName.erase(strName.find_last_not_of(" ") + 1);
394c29e5f0fSliuyi 
395c29e5f0fSliuyi 	strUUid = strUuidInfo.substr(pos+1);
396c29e5f0fSliuyi 	strUUid.erase(0, strUUid.find_first_not_of(" "));
397c29e5f0fSliuyi 	strUUid.erase(strUUid.find_last_not_of(" ") + 1);
398c29e5f0fSliuyi 
399c29e5f0fSliuyi 	while(true) {
400c29e5f0fSliuyi 		pos = 0;
401c29e5f0fSliuyi 		if( (pos = strUUid.find("-")) != string::npos)
402c29e5f0fSliuyi 			strUUid.replace(pos,1,"");
403c29e5f0fSliuyi 		else
404c29e5f0fSliuyi 			break;
405c29e5f0fSliuyi 	}
406c29e5f0fSliuyi 	if (strUUid.size() != 32)
407c29e5f0fSliuyi 		return false;
408c29e5f0fSliuyi 	return true;
409c29e5f0fSliuyi }
410c29e5f0fSliuyi 
411c29e5f0fSliuyi 
412c29e5f0fSliuyi bool parse_parameter(char *pParameter, PARAM_ITEM_VECTOR &vecItem, CONFIG_ITEM_VECTOR &vecUuidItem)
413c30d921cSKever Yang {
414c30d921cSKever Yang 	stringstream paramStream(pParameter);
415c30d921cSKever Yang 	bool bRet,bFind = false;
416c29e5f0fSliuyi 	string strLine, strPartition, strPartInfo, strPartName, strUUid;
417c30d921cSKever Yang 	string::size_type line_size, pos, posColon, posComma;
418c30d921cSKever Yang 	UINT uiPartOffset, uiPartSize;
419c30d921cSKever Yang 	STRUCT_PARAM_ITEM item;
420c29e5f0fSliuyi 	STRUCT_CONFIG_ITEM uuid_item;
421c30d921cSKever Yang 	vecItem.clear();
422c29e5f0fSliuyi 	vecUuidItem.clear();
423c30d921cSKever Yang 	while (!paramStream.eof()) {
424c30d921cSKever Yang 		getline(paramStream,strLine);
425c30d921cSKever Yang 		line_size = strLine.size();
426c30d921cSKever Yang 		if (line_size == 0)
427c30d921cSKever Yang 			continue;
428c30d921cSKever Yang 		if (strLine[line_size - 1] == '\r'){
429c30d921cSKever Yang 			strLine = strLine.substr(0, line_size - 1);
430c30d921cSKever Yang 		}
431c30d921cSKever Yang 		strLine.erase(0, strLine.find_first_not_of(" "));
432c30d921cSKever Yang 		strLine.erase(strLine.find_last_not_of(" ") + 1);
433c30d921cSKever Yang 		if (strLine.size()==0 )
434c30d921cSKever Yang 			continue;
435c30d921cSKever Yang 		if (strLine[0] == '#')
436c30d921cSKever Yang 			continue;
437c29e5f0fSliuyi 		pos = strLine.find("uuid:");
438c29e5f0fSliuyi 		if (pos != string::npos) {
439c29e5f0fSliuyi 			strPartInfo = strLine.substr(pos+5);
440c29e5f0fSliuyi 			bRet = ParseUuidInfo(strPartInfo, strPartName, strUUid);
441c29e5f0fSliuyi 			if (bRet) {
442c29e5f0fSliuyi 				strcpy(uuid_item.szItemName, strPartName.c_str());
443c29e5f0fSliuyi 				string_to_uuid(strUUid,uuid_item.szItemValue);
444c29e5f0fSliuyi 				vecUuidItem.push_back(uuid_item);
445c29e5f0fSliuyi 			}
446c29e5f0fSliuyi 			continue;
447c29e5f0fSliuyi 		}
448c29e5f0fSliuyi 
449c30d921cSKever Yang 		pos = strLine.find("mtdparts");
450c30d921cSKever Yang 		if (pos == string::npos) {
451c30d921cSKever Yang 			continue;
452c30d921cSKever Yang 		}
453c30d921cSKever Yang 		bFind = true;
454c30d921cSKever Yang 		posColon = strLine.find(':', pos);
455c30d921cSKever Yang 		if (posColon == string::npos) {
456c30d921cSKever Yang 			continue;
457c30d921cSKever Yang 		}
458c30d921cSKever Yang 		strPartition = strLine.substr(posColon + 1);
459c30d921cSKever Yang 		pos = 0;
460c30d921cSKever Yang 		posComma = strPartition.find(',', pos);
461c30d921cSKever Yang 		while (posComma != string::npos) {
462c30d921cSKever Yang 			strPartInfo = strPartition.substr(pos, posComma - pos);
463c30d921cSKever Yang 			bRet = ParsePartitionInfo(strPartInfo, strPartName, uiPartOffset, uiPartSize);
464c30d921cSKever Yang 			if (bRet) {
465c30d921cSKever Yang 				strcpy(item.szItemName, strPartName.c_str());
466c30d921cSKever Yang 				item.uiItemOffset = uiPartOffset;
467c30d921cSKever Yang 				item.uiItemSize = uiPartSize;
468c30d921cSKever Yang 				vecItem.push_back(item);
469c30d921cSKever Yang 			}
470c30d921cSKever Yang 			pos = posComma + 1;
471c30d921cSKever Yang 			posComma = strPartition.find(',', pos);
472c30d921cSKever Yang 		}
473c30d921cSKever Yang 		strPartInfo = strPartition.substr(pos);
474c30d921cSKever Yang 		if (strPartInfo.size() > 0) {
475c30d921cSKever Yang 			bRet = ParsePartitionInfo(strPartInfo, strPartName, uiPartOffset, uiPartSize);
476c30d921cSKever Yang 			if (bRet) {
477c30d921cSKever Yang 				strcpy(item.szItemName, strPartName.c_str());
478c30d921cSKever Yang 				item.uiItemOffset = uiPartOffset;
479c30d921cSKever Yang 				item.uiItemSize = uiPartSize;
480c30d921cSKever Yang 				vecItem.push_back(item);
481c30d921cSKever Yang 			}
482c30d921cSKever Yang 		}
483c30d921cSKever Yang 		break;
484c30d921cSKever Yang 	}
485c30d921cSKever Yang 	return bFind;
486c30d921cSKever Yang 
487c30d921cSKever Yang }
488c29e5f0fSliuyi bool parse_parameter_file(char *pParamFile, PARAM_ITEM_VECTOR &vecItem, CONFIG_ITEM_VECTOR &vecUuidItem)
489c30d921cSKever Yang {
490c30d921cSKever Yang 	FILE *file = NULL;
491c30d921cSKever Yang 	file = fopen(pParamFile, "rb");
492c30d921cSKever Yang 	if( !file ) {
493c30d921cSKever Yang 		if (g_pLogObject)
49432268622SAndreas Färber 			g_pLogObject->Record("%s failed, err=%d, can't open file: %s\r\n", __func__, errno, pParamFile);
495c30d921cSKever Yang 		return false;
496c30d921cSKever Yang 	}
497c30d921cSKever Yang 	int iFileSize;
498c30d921cSKever Yang 	fseek(file, 0, SEEK_END);
499c30d921cSKever Yang 	iFileSize = ftell(file);
500c30d921cSKever Yang 	fseek(file, 0, SEEK_SET);
501c30d921cSKever Yang 	char *pParamBuf = NULL;
502c30d921cSKever Yang 	pParamBuf = new char[iFileSize];
503c30d921cSKever Yang 	if (!pParamBuf) {
504c30d921cSKever Yang 		fclose(file);
505c30d921cSKever Yang 		return false;
506c30d921cSKever Yang 	}
507c30d921cSKever Yang 	int iRead;
508c30d921cSKever Yang 	iRead = fread(pParamBuf, 1, iFileSize, file);
509c30d921cSKever Yang 	if (iRead != iFileSize) {
510c30d921cSKever Yang 		if (g_pLogObject)
51132268622SAndreas Färber 			g_pLogObject->Record("%s failed, err=%d, read=%d, total=%d\r\n", __func__, errno,iRead,iFileSize);
512c30d921cSKever Yang 		fclose(file);
513c30d921cSKever Yang 		delete []pParamBuf;
514c30d921cSKever Yang 		return false;
515c30d921cSKever Yang 	}
516c30d921cSKever Yang 	fclose(file);
517c30d921cSKever Yang 	bool bRet;
518c29e5f0fSliuyi 	bRet = parse_parameter(pParamBuf, vecItem, vecUuidItem);
519c30d921cSKever Yang 	delete []pParamBuf;
520c30d921cSKever Yang 	return bRet;
521c30d921cSKever Yang }
5226ae612beSliuyi bool is_sparse_image(char *szImage)
5236ae612beSliuyi {
5246ae612beSliuyi 	FILE *file = NULL;
5256ae612beSliuyi 	sparse_header head;
5266ae612beSliuyi 	u32 uiRead;
5276ae612beSliuyi 	file = fopen(szImage, "rb");
5286ae612beSliuyi 	if( !file ) {
5296ae612beSliuyi 		if (g_pLogObject)
5306ae612beSliuyi 			g_pLogObject->Record("%s failed, err=%d, can't open file: %s\r\n", __func__, errno, szImage);
5316ae612beSliuyi 		return false;
5326ae612beSliuyi 	}
5336ae612beSliuyi 	uiRead = fread(&head, 1, sizeof(head), file);
5346ae612beSliuyi 	if (uiRead != sizeof(head)) {
5356ae612beSliuyi 		if (g_pLogObject)
5366ae612beSliuyi 			g_pLogObject->Record("%s failed, err=%d, read=%d, total=%d\r\n", __func__, errno, uiRead, sizeof(head));
5376ae612beSliuyi 		fclose(file);
5386ae612beSliuyi 		return false;
5396ae612beSliuyi 	}
5406ae612beSliuyi 	fclose(file);
5416ae612beSliuyi 	if (head.magic!=SPARSE_HEADER_MAGIC)
5426ae612beSliuyi 	{
5436ae612beSliuyi 		return false;
5446ae612beSliuyi 	}
5456ae612beSliuyi 	return true;
5466ae612beSliuyi 
5476ae612beSliuyi }
548c30d921cSKever Yang void gen_rand_uuid(unsigned char *uuid_bin)
549c30d921cSKever Yang {
550c30d921cSKever Yang 	efi_guid_t id;
551c30d921cSKever Yang 	unsigned int *ptr = (unsigned int *)&id;
552c30d921cSKever Yang 	unsigned int i;
553c30d921cSKever Yang 
554c30d921cSKever Yang 	/* Set all fields randomly */
555c30d921cSKever Yang 	for (i = 0; i < sizeof(id) / sizeof(*ptr); i++)
556c30d921cSKever Yang 		*(ptr + i) = cpu_to_be32(rand());
557c30d921cSKever Yang 
558c30d921cSKever Yang 	id.uuid.time_hi_and_version = (id.uuid.time_hi_and_version & 0x0FFF) | 0x4000;
559c30d921cSKever Yang 	id.uuid.clock_seq_hi_and_reserved = id.uuid.clock_seq_hi_and_reserved | 0x80;
560c30d921cSKever Yang 
561c30d921cSKever Yang 	memcpy(uuid_bin, id.raw, sizeof(id));
562c30d921cSKever Yang }
563c30d921cSKever Yang 
564c29e5f0fSliuyi void prepare_gpt_backup(u8 *master, u8 *backup)
565c29e5f0fSliuyi {
566c29e5f0fSliuyi 	gpt_header *gptMasterHead = (gpt_header *)(master + SECTOR_SIZE);
567c29e5f0fSliuyi 	gpt_header *gptBackupHead = (gpt_header *)(backup + 32 * SECTOR_SIZE);
568c29e5f0fSliuyi 	u32 calc_crc32;
569c29e5f0fSliuyi 	u64 val;
570c29e5f0fSliuyi 
571c29e5f0fSliuyi 	/* recalculate the values for the Backup GPT Header */
572c29e5f0fSliuyi 	val = le64_to_cpu(gptMasterHead->my_lba);
573c29e5f0fSliuyi 	gptBackupHead->my_lba = gptMasterHead->alternate_lba;
574c29e5f0fSliuyi 	gptBackupHead->alternate_lba = cpu_to_le64(val);
575c29e5f0fSliuyi 	gptBackupHead->partition_entry_lba = cpu_to_le64(le64_to_cpu(gptMasterHead->last_usable_lba) + 1);
576c29e5f0fSliuyi 	gptBackupHead->header_crc32 = 0;
577c29e5f0fSliuyi 
578c29e5f0fSliuyi 	calc_crc32 = crc32_le(0, (unsigned char *)gptBackupHead, le32_to_cpu(gptBackupHead->header_size));
579c29e5f0fSliuyi 	gptBackupHead->header_crc32 = cpu_to_le32(calc_crc32);
580c29e5f0fSliuyi }
5816ae612beSliuyi bool get_lba_from_gpt(u8 *master, char *pszName, u64 *lba, u64 *lba_end)
5826ae612beSliuyi {
5836ae612beSliuyi 	gpt_header *gptMasterHead = (gpt_header *)(master + SECTOR_SIZE);
5846ae612beSliuyi 	gpt_entry  *gptEntry  = NULL;
5856ae612beSliuyi 	u32 i,j;
5866ae612beSliuyi 	u8 zerobuf[GPT_ENTRY_SIZE];
5876ae612beSliuyi 	bool bFound = false;
5886ae612beSliuyi 	memset(zerobuf,0,GPT_ENTRY_SIZE);
5896ae612beSliuyi 
5906ae612beSliuyi 	for (i = 0; i < le32_to_cpu(gptMasterHead->num_partition_entries); i++) {
5916ae612beSliuyi 		gptEntry = (gpt_entry *)(master + 2 * SECTOR_SIZE + i * GPT_ENTRY_SIZE);
5926ae612beSliuyi 		if (memcmp(zerobuf, (u8 *)gptEntry, GPT_ENTRY_SIZE) == 0)
5936ae612beSliuyi 			break;
5946ae612beSliuyi 		for (j = 0; j < strlen(pszName); j++)
5956ae612beSliuyi 			if (gptEntry->partition_name[j] != pszName[j])
5966ae612beSliuyi 				break;
5976ae612beSliuyi 		if (gptEntry->partition_name[j] != 0)
5986ae612beSliuyi 			continue;
5996ae612beSliuyi 		if (j == strlen(pszName)) {
6006ae612beSliuyi 			bFound = true;
6016ae612beSliuyi 			break;
6026ae612beSliuyi 		}
6036ae612beSliuyi 	}
6046ae612beSliuyi 	if (bFound) {
6056ae612beSliuyi 		*lba = le64_to_cpu(gptEntry->starting_lba);
6066ae612beSliuyi 		*lba_end =  le64_to_cpu(gptEntry->ending_lba);
6076ae612beSliuyi 		return true;
6086ae612beSliuyi 	}
6096ae612beSliuyi 	return false;
6106ae612beSliuyi }
611c29e5f0fSliuyi void update_gpt_disksize(u8 *master, u8 *backup, u32 total_sector)
612c29e5f0fSliuyi {
613c29e5f0fSliuyi 	gpt_header *gptMasterHead = (gpt_header *)(master + SECTOR_SIZE);
614c29e5f0fSliuyi 	gpt_entry  *gptLastPartEntry  = NULL;
615c29e5f0fSliuyi 	u32 i;
616c29e5f0fSliuyi 	u64 old_disksize;
617c29e5f0fSliuyi 	u8 zerobuf[GPT_ENTRY_SIZE];
618c29e5f0fSliuyi 
619c29e5f0fSliuyi 	memset(zerobuf,0,GPT_ENTRY_SIZE);
620c29e5f0fSliuyi 	old_disksize = le64_to_cpu(gptMasterHead->alternate_lba) + 1;
621c29e5f0fSliuyi 	for (i = 0; i < le32_to_cpu(gptMasterHead->num_partition_entries); i++) {
622c29e5f0fSliuyi 		gptLastPartEntry = (gpt_entry *)(master + 2 * SECTOR_SIZE + i * GPT_ENTRY_SIZE);
623c29e5f0fSliuyi 		if (memcmp(zerobuf, (u8 *)gptLastPartEntry, GPT_ENTRY_SIZE) == 0)
624c29e5f0fSliuyi 			break;
625c29e5f0fSliuyi 	}
626c29e5f0fSliuyi 	i--;
627c29e5f0fSliuyi 	gptLastPartEntry = (gpt_entry *)(master + 2 * SECTOR_SIZE + i * sizeof(gpt_entry));
628c29e5f0fSliuyi 
629c29e5f0fSliuyi 	gptMasterHead->alternate_lba = cpu_to_le64(total_sector - 1);
630c29e5f0fSliuyi 	gptMasterHead->last_usable_lba = cpu_to_le64(total_sector- 34);
631c29e5f0fSliuyi 
632c29e5f0fSliuyi 	if (gptLastPartEntry->ending_lba == (old_disksize - 34)) {//grow partition
633c29e5f0fSliuyi 		gptLastPartEntry->ending_lba = cpu_to_le64(total_sector- 34);
634c29e5f0fSliuyi 		gptMasterHead->partition_entry_array_crc32 = cpu_to_le32(crc32_le(0, master + 2 * SECTOR_SIZE, GPT_ENTRY_SIZE * GPT_ENTRY_NUMBERS));
635c29e5f0fSliuyi 	}
636c29e5f0fSliuyi 	gptMasterHead->header_crc32 = 0;
637c29e5f0fSliuyi 	gptMasterHead->header_crc32 = cpu_to_le32(crc32_le(0, master + SECTOR_SIZE, sizeof(gpt_header)));
638c29e5f0fSliuyi 	memcpy(backup,master + 2 * SECTOR_SIZE, GPT_ENTRY_SIZE * GPT_ENTRY_NUMBERS);
639c29e5f0fSliuyi 	memcpy(backup + GPT_ENTRY_SIZE * GPT_ENTRY_NUMBERS, master + SECTOR_SIZE, SECTOR_SIZE);
640c29e5f0fSliuyi 	prepare_gpt_backup(master, backup);
641c29e5f0fSliuyi 
642c29e5f0fSliuyi }
643c29e5f0fSliuyi bool load_gpt_buffer(char *pParamFile, u8 *master, u8 *backup)
644c29e5f0fSliuyi {
645c29e5f0fSliuyi 	FILE *file = NULL;
646c29e5f0fSliuyi 	file = fopen(pParamFile, "rb");
647c29e5f0fSliuyi 	if( !file ) {
648c29e5f0fSliuyi 		if (g_pLogObject)
649c29e5f0fSliuyi 			g_pLogObject->Record("%s failed, err=%d, can't open file: %s\r\n", __func__, errno, pParamFile);
650c29e5f0fSliuyi 		return false;
651c29e5f0fSliuyi 	}
652c29e5f0fSliuyi 	int iFileSize;
653c29e5f0fSliuyi 	fseek(file, 0, SEEK_END);
654c29e5f0fSliuyi 	iFileSize = ftell(file);
655c29e5f0fSliuyi 	fseek(file, 0, SEEK_SET);
656c29e5f0fSliuyi 	if (iFileSize != 67 * SECTOR_SIZE) {
657c29e5f0fSliuyi 		if (g_pLogObject)
658c29e5f0fSliuyi 			g_pLogObject->Record("%s failed, wrong size file: %s\r\n", __func__, pParamFile);
659c29e5f0fSliuyi 		fclose(file);
660c29e5f0fSliuyi 		return false;
661c29e5f0fSliuyi 	}
662c29e5f0fSliuyi 
663c29e5f0fSliuyi 	int iRead;
664c29e5f0fSliuyi 	iRead = fread(master, 1, 34 * SECTOR_SIZE, file);
665c29e5f0fSliuyi 	if (iRead != 34 * SECTOR_SIZE) {
666c29e5f0fSliuyi 		if (g_pLogObject)
667c29e5f0fSliuyi 			g_pLogObject->Record("%s failed,read master gpt err=%d, read=%d, total=%d\r\n", __func__, errno,iRead, 34 * SECTOR_SIZE);
668c29e5f0fSliuyi 		fclose(file);
669c29e5f0fSliuyi 		return false;
670c29e5f0fSliuyi 	}
671c29e5f0fSliuyi 	iRead = fread(backup, 1, 33 * SECTOR_SIZE, file);
672c29e5f0fSliuyi 	if (iRead != 33 * SECTOR_SIZE) {
673c29e5f0fSliuyi 		if (g_pLogObject)
674c29e5f0fSliuyi 			g_pLogObject->Record("%s failed,read backup gpt err=%d, read=%d, total=%d\r\n", __func__, errno,iRead, 33 * SECTOR_SIZE);
675c29e5f0fSliuyi 		fclose(file);
676c29e5f0fSliuyi 		return false;
677c29e5f0fSliuyi 	}
678c29e5f0fSliuyi 	fclose(file);
679c29e5f0fSliuyi 	return true;
680c29e5f0fSliuyi }
681c29e5f0fSliuyi void create_gpt_buffer(u8 *gpt, PARAM_ITEM_VECTOR &vecParts, CONFIG_ITEM_VECTOR &vecUuid, u64 diskSectors)
682c30d921cSKever Yang {
683c30d921cSKever Yang 	legacy_mbr *mbr = (legacy_mbr *)gpt;
684c30d921cSKever Yang 	gpt_header *gptHead = (gpt_header *)(gpt + SECTOR_SIZE);
685c30d921cSKever Yang 	gpt_entry *gptEntry = (gpt_entry *)(gpt + 2 * SECTOR_SIZE);
686c30d921cSKever Yang 	u32 i,j;
687c29e5f0fSliuyi 	int pos;
688c30d921cSKever Yang 	string strPartName;
689c30d921cSKever Yang 	string::size_type colonPos;
690c30d921cSKever Yang 	/*1.protective mbr*/
691c30d921cSKever Yang 	memset(gpt, 0, SECTOR_SIZE);
692c30d921cSKever Yang 	mbr->signature = MSDOS_MBR_SIGNATURE;
693c30d921cSKever Yang 	mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT;
694c30d921cSKever Yang 	mbr->partition_record[0].start_sect = 1;
695c30d921cSKever Yang 	mbr->partition_record[0].nr_sects = (u32)-1;
696c30d921cSKever Yang 	/*2.gpt header*/
697c30d921cSKever Yang 	memset(gpt + SECTOR_SIZE, 0, SECTOR_SIZE);
698c30d921cSKever Yang 	gptHead->signature = cpu_to_le64(GPT_HEADER_SIGNATURE);
699c30d921cSKever Yang 	gptHead->revision = cpu_to_le32(GPT_HEADER_REVISION_V1);
700c30d921cSKever Yang 	gptHead->header_size = cpu_to_le32(sizeof(gpt_header));
701c30d921cSKever Yang 	gptHead->my_lba = cpu_to_le64(1);
702c30d921cSKever Yang 	gptHead->alternate_lba = cpu_to_le64(diskSectors - 1);
703c30d921cSKever Yang 	gptHead->first_usable_lba = cpu_to_le64(34);
704c30d921cSKever Yang 	gptHead->last_usable_lba = cpu_to_le64(diskSectors - 34);
705c30d921cSKever Yang 	gptHead->partition_entry_lba = cpu_to_le64(2);
706c30d921cSKever Yang 	gptHead->num_partition_entries = cpu_to_le32(GPT_ENTRY_NUMBERS);
707c30d921cSKever Yang 	gptHead->sizeof_partition_entry = cpu_to_le32(GPT_ENTRY_SIZE);
708c30d921cSKever Yang 	gptHead->header_crc32 = 0;
709c30d921cSKever Yang 	gptHead->partition_entry_array_crc32 = 0;
710c30d921cSKever Yang 	gen_rand_uuid(gptHead->disk_guid.raw);
711c30d921cSKever Yang 
712c30d921cSKever Yang 	/*3.gpt partition entry*/
713c30d921cSKever Yang 	memset(gpt + 2 * SECTOR_SIZE, 0, 32 * SECTOR_SIZE);
714c30d921cSKever Yang 	for (i = 0; i < vecParts.size(); i++) {
715c30d921cSKever Yang 		gen_rand_uuid(gptEntry->partition_type_guid.raw);
716c30d921cSKever Yang 		gen_rand_uuid(gptEntry->unique_partition_guid.raw);
717c30d921cSKever Yang 		gptEntry->starting_lba = cpu_to_le64(vecParts[i].uiItemOffset);
718c30d921cSKever Yang 		gptEntry->ending_lba = cpu_to_le64(gptEntry->starting_lba + vecParts[i].uiItemSize - 1);
719c30d921cSKever Yang 		gptEntry->attributes.raw = 0;
720c30d921cSKever Yang 		strPartName = vecParts[i].szItemName;
721c30d921cSKever Yang 		colonPos = strPartName.find_first_of(':');
722c30d921cSKever Yang 		if (colonPos != string::npos) {
723c30d921cSKever Yang 			if (strPartName.find("bootable") != string::npos)
724c30d921cSKever Yang 				gptEntry->attributes.raw = PART_PROPERTY_BOOTABLE;
725c29e5f0fSliuyi 			if (strPartName.find("grow") != string::npos)
726c29e5f0fSliuyi 				gptEntry->ending_lba = cpu_to_le64(diskSectors - 34);
727c30d921cSKever Yang 			strPartName = strPartName.substr(0, colonPos);
728c30d921cSKever Yang 			vecParts[i].szItemName[strPartName.size()] = 0;
729c30d921cSKever Yang 		}
730c30d921cSKever Yang 		for (j = 0; j < strlen(vecParts[i].szItemName); j++)
731c30d921cSKever Yang 			gptEntry->partition_name[j] = vecParts[i].szItemName[j];
732c29e5f0fSliuyi 		if ((pos = find_config_item(vecUuid, vecParts[i].szItemName)) != -1)
733c29e5f0fSliuyi 			memcpy(gptEntry->unique_partition_guid.raw, vecUuid[pos].szItemValue, 16);
734c30d921cSKever Yang 		gptEntry++;
735c30d921cSKever Yang 	}
736c30d921cSKever Yang 
737c30d921cSKever Yang 	gptHead->partition_entry_array_crc32 = cpu_to_le32(crc32_le(0, gpt + 2 * SECTOR_SIZE, GPT_ENTRY_SIZE * GPT_ENTRY_NUMBERS));
738c30d921cSKever Yang 	gptHead->header_crc32 = cpu_to_le32(crc32_le(0, gpt + SECTOR_SIZE, sizeof(gpt_header)));
739c30d921cSKever Yang 
740c30d921cSKever Yang }
741b38fe5fcSliuyi bool MakeSector0(PBYTE pSector, USHORT usFlashDataSec, USHORT usFlashBootSec, bool rc4Flag)
742c30d921cSKever Yang {
743c30d921cSKever Yang 	PRK28_IDB_SEC0 pSec0;
744c30d921cSKever Yang 	memset(pSector, 0, SECTOR_SIZE);
745c30d921cSKever Yang 	pSec0 = (PRK28_IDB_SEC0)pSector;
746c30d921cSKever Yang 
747c30d921cSKever Yang 	pSec0->dwTag = 0x0FF0AA55;
748b38fe5fcSliuyi 	pSec0->uiRc4Flag = rc4Flag;
749c30d921cSKever Yang 	pSec0->usBootCode1Offset = 0x4;
750c30d921cSKever Yang 	pSec0->usBootCode2Offset = 0x4;
751c30d921cSKever Yang 	pSec0->usBootDataSize = usFlashDataSec;
752c30d921cSKever Yang 	pSec0->usBootCodeSize = usFlashDataSec + usFlashBootSec;
753c30d921cSKever Yang 	return true;
754c30d921cSKever Yang }
755c30d921cSKever Yang 
756c30d921cSKever Yang 
757c30d921cSKever Yang bool MakeSector1(PBYTE pSector)
758c30d921cSKever Yang {
759c30d921cSKever Yang 	PRK28_IDB_SEC1 pSec1;
760c30d921cSKever Yang 	memset(pSector, 0, SECTOR_SIZE);
761c30d921cSKever Yang 	pSec1 = (PRK28_IDB_SEC1)pSector;
762c30d921cSKever Yang 
763c30d921cSKever Yang 	pSec1->usSysReservedBlock = 0xC;
764c30d921cSKever Yang 	pSec1->usDisk0Size = 0xFFFF;
765c30d921cSKever Yang 	pSec1->uiChipTag = 0x38324B52;
766c30d921cSKever Yang 	return true;
767c30d921cSKever Yang }
768c30d921cSKever Yang 
769c30d921cSKever Yang bool MakeSector2(PBYTE pSector)
770c30d921cSKever Yang {
771c30d921cSKever Yang 	PRK28_IDB_SEC2 pSec2;
772c30d921cSKever Yang 	memset(pSector, 0, SECTOR_SIZE);
773c30d921cSKever Yang 	pSec2 = (PRK28_IDB_SEC2)pSector;
774c30d921cSKever Yang 
775c30d921cSKever Yang 	strcpy(pSec2->szVcTag, "VC");
776c30d921cSKever Yang 	strcpy(pSec2->szCrcTag, "CRC");
777c30d921cSKever Yang 	return true;
778c30d921cSKever Yang }
779c30d921cSKever Yang 
780c30d921cSKever Yang bool MakeSector3(PBYTE pSector)
781c30d921cSKever Yang {
782c30d921cSKever Yang 	memset(pSector,0,SECTOR_SIZE);
783c30d921cSKever Yang 	return true;
784c30d921cSKever Yang }
785c30d921cSKever Yang 
786b38fe5fcSliuyi int MakeIDBlockData(PBYTE pDDR, PBYTE pLoader, PBYTE lpIDBlock, USHORT usFlashDataSec, USHORT usFlashBootSec, DWORD dwLoaderDataSize, DWORD dwLoaderSize, bool rc4Flag)
787c30d921cSKever Yang {
788c30d921cSKever Yang 	RK28_IDB_SEC0 sector0Info;
789c30d921cSKever Yang 	RK28_IDB_SEC1 sector1Info;
790c30d921cSKever Yang 	RK28_IDB_SEC2 sector2Info;
791c30d921cSKever Yang 	RK28_IDB_SEC3 sector3Info;
792c30d921cSKever Yang 	UINT i;
793b38fe5fcSliuyi 	MakeSector0((PBYTE)&sector0Info, usFlashDataSec, usFlashBootSec, rc4Flag);
794c30d921cSKever Yang 	MakeSector1((PBYTE)&sector1Info);
795c30d921cSKever Yang 	if (!MakeSector2((PBYTE)&sector2Info)) {
796c30d921cSKever Yang 		return -6;
797c30d921cSKever Yang 	}
798c30d921cSKever Yang 	if (!MakeSector3((PBYTE)&sector3Info)) {
799c30d921cSKever Yang 		return -7;
800c30d921cSKever Yang 	}
801c30d921cSKever Yang 	sector2Info.usSec0Crc = CRC_16((PBYTE)&sector0Info, SECTOR_SIZE);
802c30d921cSKever Yang 	sector2Info.usSec1Crc = CRC_16((PBYTE)&sector1Info, SECTOR_SIZE);
803c30d921cSKever Yang 	sector2Info.usSec3Crc = CRC_16((PBYTE)&sector3Info, SECTOR_SIZE);
804c30d921cSKever Yang 
805c30d921cSKever Yang 	memcpy(lpIDBlock, &sector0Info, SECTOR_SIZE);
806c30d921cSKever Yang 	memcpy(lpIDBlock + SECTOR_SIZE, &sector1Info, SECTOR_SIZE);
807c30d921cSKever Yang 	memcpy(lpIDBlock + SECTOR_SIZE * 3, &sector3Info, SECTOR_SIZE);
808b38fe5fcSliuyi 
809b38fe5fcSliuyi 	if (rc4Flag) {
810b38fe5fcSliuyi 		for (i = 0; i < dwLoaderDataSize/SECTOR_SIZE; i++)
811b38fe5fcSliuyi 			P_RC4(pDDR + i * SECTOR_SIZE, SECTOR_SIZE);
812b38fe5fcSliuyi 		for (i = 0; i < dwLoaderSize/SECTOR_SIZE; i++)
813b38fe5fcSliuyi 			P_RC4(pLoader + i * SECTOR_SIZE, SECTOR_SIZE);
814b38fe5fcSliuyi 	}
815b38fe5fcSliuyi 
816c30d921cSKever Yang 	memcpy(lpIDBlock + SECTOR_SIZE * 4, pDDR, dwLoaderDataSize);
817c30d921cSKever Yang 	memcpy(lpIDBlock + SECTOR_SIZE * (4 + usFlashDataSec), pLoader, dwLoaderSize);
818c30d921cSKever Yang 
819c30d921cSKever Yang 	sector2Info.uiBootCodeCrc = CRC_32((PBYTE)(lpIDBlock + SECTOR_SIZE * 4), sector0Info.usBootCodeSize * SECTOR_SIZE);
820c30d921cSKever Yang 	memcpy(lpIDBlock + SECTOR_SIZE * 2, &sector2Info, SECTOR_SIZE);
821c30d921cSKever Yang 	for(i = 0; i < 4; i++) {
822c30d921cSKever Yang 		if(i == 1) {
823c30d921cSKever Yang 			continue;
824c30d921cSKever Yang 		} else {
825c30d921cSKever Yang 			P_RC4(lpIDBlock + SECTOR_SIZE * i, SECTOR_SIZE);
826c30d921cSKever Yang 		}
827c30d921cSKever Yang 	}
828c30d921cSKever Yang 	return 0;
829c30d921cSKever Yang }
830c30d921cSKever Yang 
831c30d921cSKever Yang 
83276af099aSliuyi 
83376af099aSliuyi bool check_device_type(STRUCT_RKDEVICE_DESC &dev, UINT uiSupportType)
83476af099aSliuyi {
83576af099aSliuyi 	if ((dev.emUsbType & uiSupportType) == dev.emUsbType)
83676af099aSliuyi 		return true;
83776af099aSliuyi 	else
83876af099aSliuyi 	{
83976af099aSliuyi 		ERROR_COLOR_ATTR;
84032268622SAndreas Färber 		printf("The device does not support this operation!");
84176af099aSliuyi 		NORMAL_COLOR_ATTR;
84276af099aSliuyi 		printf("\r\n");
84376af099aSliuyi 		return false;
84476af099aSliuyi 	}
84576af099aSliuyi }
846c30d921cSKever Yang bool write_gpt(STRUCT_RKDEVICE_DESC &dev, char *szParameter)
847c30d921cSKever Yang {
848c30d921cSKever Yang 	u8 flash_info[SECTOR_SIZE], master_gpt[34 * SECTOR_SIZE], backup_gpt[33 * SECTOR_SIZE];
849c30d921cSKever Yang 	u32 total_size_sector;
850c30d921cSKever Yang 	CRKComm *pComm = NULL;
851c30d921cSKever Yang 	PARAM_ITEM_VECTOR vecItems;
852c29e5f0fSliuyi 	CONFIG_ITEM_VECTOR vecUuid;
853c30d921cSKever Yang 	int iRet;
854c30d921cSKever Yang 	bool bRet, bSuccess = false;
855c30d921cSKever Yang 	if (!check_device_type(dev, RKUSB_MASKROM))
856c30d921cSKever Yang 		return false;
857c30d921cSKever Yang 
858c30d921cSKever Yang 	pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
859c30d921cSKever Yang 	if (!bRet) {
860c30d921cSKever Yang 		ERROR_COLOR_ATTR;
861c30d921cSKever Yang 		printf("Creating Comm Object failed!");
862c30d921cSKever Yang 		NORMAL_COLOR_ATTR;
863c30d921cSKever Yang 		printf("\r\n");
864c30d921cSKever Yang 		return bSuccess;
865c30d921cSKever Yang 	}
86632268622SAndreas Färber 	printf("Writing gpt...\r\n");
867c30d921cSKever Yang 	//1.get flash info
868c30d921cSKever Yang 	iRet = pComm->RKU_ReadFlashInfo(flash_info);
869c30d921cSKever Yang 	if (iRet != ERR_SUCCESS) {
870c30d921cSKever Yang 		ERROR_COLOR_ATTR;
871c30d921cSKever Yang 		printf("Reading Flash Info failed!");
872c30d921cSKever Yang 		NORMAL_COLOR_ATTR;
873c30d921cSKever Yang 		printf("\r\n");
874c30d921cSKever Yang 		return bSuccess;
875c30d921cSKever Yang 	}
876c30d921cSKever Yang 	total_size_sector = *(u32 *)flash_info;
877c29e5f0fSliuyi 	if (strstr(szParameter, ".img")) {
878c29e5f0fSliuyi 		if (!load_gpt_buffer(szParameter, master_gpt, backup_gpt)) {
879c29e5f0fSliuyi 			ERROR_COLOR_ATTR;
880c29e5f0fSliuyi 			printf("Loading partition image failed!");
881c29e5f0fSliuyi 			NORMAL_COLOR_ATTR;
882c29e5f0fSliuyi 			printf("\r\n");
883c29e5f0fSliuyi 			return bSuccess;
884c29e5f0fSliuyi 		}
885c29e5f0fSliuyi 		update_gpt_disksize(master_gpt, backup_gpt, total_size_sector);
886c29e5f0fSliuyi 	} else {
887c30d921cSKever Yang 		//2.get partition from parameter
888c29e5f0fSliuyi 		bRet = parse_parameter_file(szParameter, vecItems, vecUuid);
889c30d921cSKever Yang 		if (!bRet) {
890c30d921cSKever Yang 			ERROR_COLOR_ATTR;
891c30d921cSKever Yang 			printf("Parsing parameter failed!");
892c30d921cSKever Yang 			NORMAL_COLOR_ATTR;
893c30d921cSKever Yang 			printf("\r\n");
894c30d921cSKever Yang 			return bSuccess;
895c30d921cSKever Yang 		}
896c29e5f0fSliuyi 		vecItems[vecItems.size()-1].uiItemSize = total_size_sector - 33;
897c30d921cSKever Yang 		//3.generate gpt info
898c29e5f0fSliuyi 		create_gpt_buffer(master_gpt, vecItems, vecUuid, total_size_sector);
899c30d921cSKever Yang 		memcpy(backup_gpt, master_gpt + 2* SECTOR_SIZE, 32 * SECTOR_SIZE);
900c30d921cSKever Yang 		memcpy(backup_gpt + 32 * SECTOR_SIZE, master_gpt + SECTOR_SIZE, SECTOR_SIZE);
901c29e5f0fSliuyi 		prepare_gpt_backup(master_gpt, backup_gpt);
902c29e5f0fSliuyi 	}
903c29e5f0fSliuyi 
904c30d921cSKever Yang 	//4. write gpt
905c30d921cSKever Yang 	iRet = pComm->RKU_WriteLBA(0, 34, master_gpt);
906c30d921cSKever Yang 	if (iRet != ERR_SUCCESS) {
907c30d921cSKever Yang 		ERROR_COLOR_ATTR;
908c30d921cSKever Yang 		printf("Writing master gpt failed!");
909c30d921cSKever Yang 		NORMAL_COLOR_ATTR;
910c30d921cSKever Yang 		printf("\r\n");
911c30d921cSKever Yang 		return bSuccess;
912c30d921cSKever Yang 	}
913c29e5f0fSliuyi 	iRet = pComm->RKU_WriteLBA(total_size_sector - 33, 33, backup_gpt);
914c30d921cSKever Yang 	if (iRet != ERR_SUCCESS) {
915c30d921cSKever Yang 		ERROR_COLOR_ATTR;
916c30d921cSKever Yang 		printf("Writing backup gpt failed!");
917c30d921cSKever Yang 		NORMAL_COLOR_ATTR;
918c30d921cSKever Yang 		printf("\r\n");
919c30d921cSKever Yang 		return bSuccess;
920c30d921cSKever Yang 	}
921c29e5f0fSliuyi 
922c30d921cSKever Yang 	bSuccess = true;
923c30d921cSKever Yang 	CURSOR_MOVEUP_LINE(1);
924c30d921cSKever Yang 	CURSOR_DEL_LINE;
92532268622SAndreas Färber 	printf("Writing gpt succeeded.\r\n");
926c30d921cSKever Yang 	return bSuccess;
927c30d921cSKever Yang }
92876af099aSliuyi 
92978884ef4SEddie Cai #include "boot_merger.h"
93078884ef4SEddie Cai #define ENTRY_ALIGN  (2048)
93178884ef4SEddie Cai options gOpts;
93278884ef4SEddie Cai 
93378884ef4SEddie Cai 
93478884ef4SEddie Cai char gSubfix[MAX_LINE_LEN] = OUT_SUBFIX;
93578884ef4SEddie Cai char* gConfigPath;
93678884ef4SEddie Cai uint8_t gBuf[MAX_MERGE_SIZE];
93778884ef4SEddie Cai 
93878884ef4SEddie Cai static inline void fixPath(char* path) {
93978884ef4SEddie Cai 	int i, len = strlen(path);
94078884ef4SEddie Cai 	for(i=0; i<len; i++) {
94178884ef4SEddie Cai 		if (path[i] == '\\')
94278884ef4SEddie Cai 			path[i] = '/';
94378884ef4SEddie Cai 		else if (path[i] == '\r' || path[i] == '\n')
94478884ef4SEddie Cai 			path[i] = '\0';
94578884ef4SEddie Cai 	}
94678884ef4SEddie Cai }
94778884ef4SEddie Cai 
94878884ef4SEddie Cai static bool parseChip(FILE* file) {
94978884ef4SEddie Cai 	if (SCANF_EAT(file) != 0) {
95078884ef4SEddie Cai 		return false;
95178884ef4SEddie Cai 	}
95278884ef4SEddie Cai 	if (fscanf(file, OPT_NAME "=%s", gOpts.chip) != 1) {
95378884ef4SEddie Cai 		return false;
95478884ef4SEddie Cai 	}
95578884ef4SEddie Cai 	printf("chip: %s\n", gOpts.chip);
95678884ef4SEddie Cai 	return true;
95778884ef4SEddie Cai }
95878884ef4SEddie Cai 
95978884ef4SEddie Cai static bool parseVersion(FILE* file) {
96078884ef4SEddie Cai 	if (SCANF_EAT(file) != 0) {
96178884ef4SEddie Cai 		return false;
96278884ef4SEddie Cai 	}
96378884ef4SEddie Cai 	if (fscanf(file, OPT_MAJOR "=%d", &gOpts.major) != 1)
96478884ef4SEddie Cai 		return false;
96578884ef4SEddie Cai 	if (SCANF_EAT(file) != 0) {
96678884ef4SEddie Cai 		return false;
96778884ef4SEddie Cai 	}
96878884ef4SEddie Cai 	if (fscanf(file, OPT_MINOR "=%d", &gOpts.minor) != 1)
96978884ef4SEddie Cai 		return false;
97078884ef4SEddie Cai 	printf("major: %d, minor: %d\n", gOpts.major, gOpts.minor);
97178884ef4SEddie Cai 	return true;
97278884ef4SEddie Cai }
97378884ef4SEddie Cai 
97478884ef4SEddie Cai static bool parse471(FILE* file) {
97578884ef4SEddie Cai 	int i, index, pos;
97678884ef4SEddie Cai 	char buf[MAX_LINE_LEN];
97778884ef4SEddie Cai 
97878884ef4SEddie Cai 	if (SCANF_EAT(file) != 0) {
97978884ef4SEddie Cai 		return false;
98078884ef4SEddie Cai 	}
98178884ef4SEddie Cai 	if (fscanf(file, OPT_NUM "=%d", &gOpts.code471Num) != 1)
98278884ef4SEddie Cai 		return false;
98378884ef4SEddie Cai 	printf("num: %d\n", gOpts.code471Num);
98478884ef4SEddie Cai 	if (!gOpts.code471Num)
98578884ef4SEddie Cai 		return true;
98678884ef4SEddie Cai 	if (gOpts.code471Num < 0)
98778884ef4SEddie Cai 		return false;
98878884ef4SEddie Cai 	gOpts.code471Path = (line_t*) malloc(sizeof(line_t) * gOpts.code471Num);
98978884ef4SEddie Cai 	for (i=0; i<gOpts.code471Num; i++) {
99078884ef4SEddie Cai 		if (SCANF_EAT(file) != 0) {
99178884ef4SEddie Cai 			return false;
99278884ef4SEddie Cai 		}
99378884ef4SEddie Cai 		if (fscanf(file, OPT_PATH "%d=%[^\r^\n]", &index, buf)
99478884ef4SEddie Cai 				!= 2)
99578884ef4SEddie Cai 			return false;
99678884ef4SEddie Cai 		index--;
99778884ef4SEddie Cai 		fixPath(buf);
99878884ef4SEddie Cai 		strcpy((char*)gOpts.code471Path[index], buf);
99978884ef4SEddie Cai 		printf("path%i: %s\n", index, gOpts.code471Path[index]);
100078884ef4SEddie Cai 	}
100178884ef4SEddie Cai 	pos = ftell(file);
100278884ef4SEddie Cai 	if (SCANF_EAT(file) != 0) {
100378884ef4SEddie Cai 		return false;
100478884ef4SEddie Cai 	}
100578884ef4SEddie Cai 	if (fscanf(file, OPT_SLEEP "=%d", &gOpts.code471Sleep) != 1)
100678884ef4SEddie Cai 		fseek(file, pos, SEEK_SET);
100778884ef4SEddie Cai 	printf("sleep: %d\n", gOpts.code471Sleep);
100878884ef4SEddie Cai 	return true;
100978884ef4SEddie Cai }
101078884ef4SEddie Cai 
101178884ef4SEddie Cai static bool parse472(FILE* file) {
101278884ef4SEddie Cai 	int i, index, pos;
101378884ef4SEddie Cai 	char buf[MAX_LINE_LEN];
101478884ef4SEddie Cai 
101578884ef4SEddie Cai 	if (SCANF_EAT(file) != 0) {
101678884ef4SEddie Cai 		return false;
101778884ef4SEddie Cai 	}
101878884ef4SEddie Cai 	if (fscanf(file, OPT_NUM "=%d", &gOpts.code472Num) != 1)
101978884ef4SEddie Cai 		return false;
102078884ef4SEddie Cai 	printf("num: %d\n", gOpts.code472Num);
102178884ef4SEddie Cai 	if (!gOpts.code472Num)
102278884ef4SEddie Cai 		return true;
102378884ef4SEddie Cai 	if (gOpts.code472Num < 0)
102478884ef4SEddie Cai 		return false;
102578884ef4SEddie Cai 	gOpts.code472Path = (line_t*) malloc(sizeof(line_t) * gOpts.code472Num);
102678884ef4SEddie Cai 	for (i=0; i<gOpts.code472Num; i++) {
102778884ef4SEddie Cai 		if (SCANF_EAT(file) != 0) {
102878884ef4SEddie Cai 			return false;
102978884ef4SEddie Cai 		}
103078884ef4SEddie Cai 		if (fscanf(file, OPT_PATH "%d=%[^\r^\n]", &index, buf)
103178884ef4SEddie Cai 				!= 2)
103278884ef4SEddie Cai 			return false;
103378884ef4SEddie Cai 		fixPath(buf);
103478884ef4SEddie Cai 		index--;
103578884ef4SEddie Cai 		strcpy((char*)gOpts.code472Path[index], buf);
103678884ef4SEddie Cai 		printf("path%i: %s\n", index, gOpts.code472Path[index]);
103778884ef4SEddie Cai 	}
103878884ef4SEddie Cai 	pos = ftell(file);
103978884ef4SEddie Cai 	if (SCANF_EAT(file) != 0) {
104078884ef4SEddie Cai 		return false;
104178884ef4SEddie Cai 	}
104278884ef4SEddie Cai 	if (fscanf(file, OPT_SLEEP "=%d", &gOpts.code472Sleep) != 1)
104378884ef4SEddie Cai 		fseek(file, pos, SEEK_SET);
104478884ef4SEddie Cai 	printf("sleep: %d\n", gOpts.code472Sleep);
104578884ef4SEddie Cai 	return true;
104678884ef4SEddie Cai }
104778884ef4SEddie Cai 
104878884ef4SEddie Cai static bool parseLoader(FILE* file) {
104978884ef4SEddie Cai 	int i, j, index, pos;
105078884ef4SEddie Cai 	char buf[MAX_LINE_LEN];
105178884ef4SEddie Cai 	char buf2[MAX_LINE_LEN];
105278884ef4SEddie Cai 
105378884ef4SEddie Cai 	if (SCANF_EAT(file) != 0) {
105478884ef4SEddie Cai 		return false;
105578884ef4SEddie Cai 	}
105678884ef4SEddie Cai 	pos = ftell(file);
105778884ef4SEddie Cai 	if (fscanf(file, OPT_NUM "=%d", &gOpts.loaderNum) != 1) {
105878884ef4SEddie Cai 		fseek(file, pos, SEEK_SET);
105978884ef4SEddie Cai 		if(fscanf(file, OPT_LOADER_NUM "=%d", &gOpts.loaderNum) != 1) {
106078884ef4SEddie Cai 			return false;
106178884ef4SEddie Cai 		}
106278884ef4SEddie Cai 	}
106378884ef4SEddie Cai 	printf("num: %d\n", gOpts.loaderNum);
106478884ef4SEddie Cai 	if (!gOpts.loaderNum)
106578884ef4SEddie Cai 		return false;
106678884ef4SEddie Cai 	if (gOpts.loaderNum < 0)
106778884ef4SEddie Cai 		return false;
106878884ef4SEddie Cai 	gOpts.loader = (name_entry*) malloc(sizeof(name_entry) * gOpts.loaderNum);
106978884ef4SEddie Cai 	for (i=0; i<gOpts.loaderNum; i++) {
107078884ef4SEddie Cai 		if (SCANF_EAT(file) != 0) {
107178884ef4SEddie Cai 			return false;
107278884ef4SEddie Cai 		}
107378884ef4SEddie Cai 		if (fscanf(file, OPT_LOADER_NAME "%d=%s", &index, buf)
107478884ef4SEddie Cai 				!= 2)
107578884ef4SEddie Cai 			return false;
107678884ef4SEddie Cai 		index--;
107778884ef4SEddie Cai 		strcpy(gOpts.loader[index].name, buf);
107878884ef4SEddie Cai 		printf("name%d: %s\n", index, gOpts.loader[index].name);
107978884ef4SEddie Cai 	}
108078884ef4SEddie Cai 	for (i=0; i<gOpts.loaderNum; i++) {
108178884ef4SEddie Cai 		if (SCANF_EAT(file) != 0) {
108278884ef4SEddie Cai 			return false;
108378884ef4SEddie Cai 		}
108478884ef4SEddie Cai 		if (fscanf(file, "%[^=]=%[^\r^\n]", buf, buf2)
108578884ef4SEddie Cai 				!= 2)
108678884ef4SEddie Cai 			return false;
108778884ef4SEddie Cai 		for (j=0; j<gOpts.loaderNum; j++) {
108878884ef4SEddie Cai 			if (!strcmp(gOpts.loader[j].name, buf)) {
108978884ef4SEddie Cai 				fixPath(buf2);
109078884ef4SEddie Cai 				strcpy(gOpts.loader[j].path, buf2);
109178884ef4SEddie Cai 				printf("%s=%s\n", gOpts.loader[j].name, gOpts.loader[j].path);
109278884ef4SEddie Cai 				break;
109378884ef4SEddie Cai 			}
109478884ef4SEddie Cai 		}
109578884ef4SEddie Cai 		if (j >= gOpts.loaderNum) {
109678884ef4SEddie Cai 			return false;
109778884ef4SEddie Cai 		}
109878884ef4SEddie Cai 	}
109978884ef4SEddie Cai 	return true;
110078884ef4SEddie Cai }
110178884ef4SEddie Cai 
110278884ef4SEddie Cai static bool parseOut(FILE* file) {
110378884ef4SEddie Cai 	if (SCANF_EAT(file) != 0) {
110478884ef4SEddie Cai 		return false;
110578884ef4SEddie Cai 	}
110678884ef4SEddie Cai 	if (fscanf(file, OPT_OUT_PATH "=%[^\r^\n]", gOpts.outPath) != 1)
110778884ef4SEddie Cai 		return false;
110878884ef4SEddie Cai 	fixPath(gOpts.outPath);
110978884ef4SEddie Cai 	printf("out: %s\n", gOpts.outPath);
111078884ef4SEddie Cai 	return true;
111178884ef4SEddie Cai }
111278884ef4SEddie Cai 
111378884ef4SEddie Cai 
111478884ef4SEddie Cai void printOpts(FILE* out) {
111578884ef4SEddie Cai 	int i;
111678884ef4SEddie Cai 	fprintf(out, SEC_CHIP "\n" OPT_NAME "=%s\n", gOpts.chip);
111778884ef4SEddie Cai 	fprintf(out, SEC_VERSION "\n" OPT_MAJOR "=%d\n" OPT_MINOR
111878884ef4SEddie Cai 			"=%d\n", gOpts.major, gOpts.minor);
111978884ef4SEddie Cai 
112078884ef4SEddie Cai 	fprintf(out, SEC_471 "\n" OPT_NUM "=%d\n", gOpts.code471Num);
112178884ef4SEddie Cai 	for (i=0 ;i<gOpts.code471Num ;i++) {
112278884ef4SEddie Cai 		fprintf(out, OPT_PATH "%d=%s\n", i+1, gOpts.code471Path[i]);
112378884ef4SEddie Cai 	}
112478884ef4SEddie Cai 	if (gOpts.code471Sleep > 0)
112578884ef4SEddie Cai 		fprintf(out, OPT_SLEEP "=%d\n", gOpts.code471Sleep);
112678884ef4SEddie Cai 
112778884ef4SEddie Cai 	fprintf(out, SEC_472 "\n" OPT_NUM "=%d\n", gOpts.code472Num);
112878884ef4SEddie Cai 	for (i=0 ;i<gOpts.code472Num ;i++) {
112978884ef4SEddie Cai 		fprintf(out, OPT_PATH "%d=%s\n", i+1, gOpts.code472Path[i]);
113078884ef4SEddie Cai 	}
113178884ef4SEddie Cai 	if (gOpts.code472Sleep > 0)
113278884ef4SEddie Cai 		fprintf(out, OPT_SLEEP "=%d\n", gOpts.code472Sleep);
113378884ef4SEddie Cai 
113478884ef4SEddie Cai 	fprintf(out, SEC_LOADER "\n" OPT_NUM "=%d\n", gOpts.loaderNum);
113578884ef4SEddie Cai 	for (i=0 ;i<gOpts.loaderNum ;i++) {
113678884ef4SEddie Cai 		fprintf(out, OPT_LOADER_NAME "%d=%s\n", i+1, gOpts.loader[i].name);
113778884ef4SEddie Cai 	}
113878884ef4SEddie Cai 	for (i=0 ;i<gOpts.loaderNum ;i++) {
113978884ef4SEddie Cai 		fprintf(out, "%s=%s\n", gOpts.loader[i].name, gOpts.loader[i].path);
114078884ef4SEddie Cai 	}
114178884ef4SEddie Cai 
114278884ef4SEddie Cai 	fprintf(out, SEC_OUT "\n" OPT_OUT_PATH "=%s\n", gOpts.outPath);
114378884ef4SEddie Cai }
114478884ef4SEddie Cai 
114578884ef4SEddie Cai static bool parseOpts(void) {
114678884ef4SEddie Cai 	bool ret = false;
114778884ef4SEddie Cai 	bool chipOk = false;
114878884ef4SEddie Cai 	bool versionOk = false;
114978884ef4SEddie Cai 	bool code471Ok = true;
115078884ef4SEddie Cai 	bool code472Ok = true;
115178884ef4SEddie Cai 	bool loaderOk = false;
115278884ef4SEddie Cai 	bool outOk = false;
115378884ef4SEddie Cai 	char buf[MAX_LINE_LEN];
115478884ef4SEddie Cai 
115578884ef4SEddie Cai 	char* configPath = (gConfigPath == (char*)NULL)? (char*)DEF_CONFIG_FILE: gConfigPath;
115678884ef4SEddie Cai 	FILE* file;
115778884ef4SEddie Cai 	file = fopen(configPath, "r");
115878884ef4SEddie Cai 	if (!file) {
115978884ef4SEddie Cai 		fprintf(stderr, "config (%s) not found!\n", configPath);
1160*08c0d218SKlaus Goger 		if (strcmp(configPath, (char*)DEF_CONFIG_FILE) == 0) {
116178884ef4SEddie Cai 			file = fopen(DEF_CONFIG_FILE, "w");
116278884ef4SEddie Cai 			if (file) {
116332268622SAndreas Färber 				fprintf(stderr, "creating defconfig\n");
116478884ef4SEddie Cai 				printOpts(file);
116578884ef4SEddie Cai 			}
116678884ef4SEddie Cai 		}
116778884ef4SEddie Cai 		goto end;
116878884ef4SEddie Cai 	}
116978884ef4SEddie Cai 
117032268622SAndreas Färber 	printf("Starting to parse...\n");
117178884ef4SEddie Cai 
117278884ef4SEddie Cai 	if (SCANF_EAT(file) != 0) {
117378884ef4SEddie Cai 		goto end;
117478884ef4SEddie Cai 	}
117578884ef4SEddie Cai 	while(fscanf(file, "%s", buf) == 1) {
117678884ef4SEddie Cai 		if (!strcmp(buf, SEC_CHIP)) {
117778884ef4SEddie Cai 			chipOk = parseChip(file);
117878884ef4SEddie Cai 			if (!chipOk) {
117978884ef4SEddie Cai 				printf("parseChip failed!\n");
118078884ef4SEddie Cai 				goto end;
118178884ef4SEddie Cai 			}
118278884ef4SEddie Cai 		} else if (!strcmp(buf, SEC_VERSION)) {
118378884ef4SEddie Cai 			versionOk = parseVersion(file);
118478884ef4SEddie Cai 			if (!versionOk) {
118578884ef4SEddie Cai 				printf("parseVersion failed!\n");
118678884ef4SEddie Cai 				goto end;
118778884ef4SEddie Cai 			}
118878884ef4SEddie Cai 		} else if (!strcmp(buf, SEC_471)) {
118978884ef4SEddie Cai 			code471Ok = parse471(file);
119078884ef4SEddie Cai 			if (!code471Ok) {
119178884ef4SEddie Cai 				printf("parse471 failed!\n");
119278884ef4SEddie Cai 				goto end;
119378884ef4SEddie Cai 			}
119478884ef4SEddie Cai 		} else if (!strcmp(buf, SEC_472)) {
119578884ef4SEddie Cai 			code472Ok = parse472(file);
119678884ef4SEddie Cai 			if (!code472Ok) {
119778884ef4SEddie Cai 				printf("parse472 failed!\n");
119878884ef4SEddie Cai 				goto end;
119978884ef4SEddie Cai 			}
120078884ef4SEddie Cai 		} else if (!strcmp(buf, SEC_LOADER)) {
120178884ef4SEddie Cai 			loaderOk = parseLoader(file);
120278884ef4SEddie Cai 			if (!loaderOk) {
120378884ef4SEddie Cai 				printf("parseLoader failed!\n");
120478884ef4SEddie Cai 				goto end;
120578884ef4SEddie Cai 			}
120678884ef4SEddie Cai 		} else if (!strcmp(buf, SEC_OUT)) {
120778884ef4SEddie Cai 			outOk = parseOut(file);
120878884ef4SEddie Cai 			if (!outOk) {
120978884ef4SEddie Cai 				printf("parseOut failed!\n");
121078884ef4SEddie Cai 				goto end;
121178884ef4SEddie Cai 			}
121278884ef4SEddie Cai 		} else if (buf[0] == '#') {
121378884ef4SEddie Cai 			continue;
121478884ef4SEddie Cai 		} else {
121578884ef4SEddie Cai 			printf("unknown sec: %s!\n", buf);
121678884ef4SEddie Cai 			goto end;
121778884ef4SEddie Cai 		}
121878884ef4SEddie Cai 		if (SCANF_EAT(file) != 0) {
121978884ef4SEddie Cai 			goto end;
122078884ef4SEddie Cai 		}
122178884ef4SEddie Cai 	}
122278884ef4SEddie Cai 
122378884ef4SEddie Cai 	if (chipOk && versionOk && code471Ok && code472Ok
122478884ef4SEddie Cai 			&& loaderOk && outOk)
122578884ef4SEddie Cai 		ret = true;
122678884ef4SEddie Cai end:
122778884ef4SEddie Cai 	if (file)
122878884ef4SEddie Cai 		fclose(file);
122978884ef4SEddie Cai 	return ret;
123078884ef4SEddie Cai }
123178884ef4SEddie Cai 
123278884ef4SEddie Cai bool initOpts(void) {
123378884ef4SEddie Cai 	//set default opts
123478884ef4SEddie Cai 	gOpts.major = DEF_MAJOR;
123578884ef4SEddie Cai 	gOpts.minor = DEF_MINOR;
123678884ef4SEddie Cai 	strcpy(gOpts.chip, DEF_CHIP);
123778884ef4SEddie Cai 	gOpts.code471Sleep = DEF_CODE471_SLEEP;
123878884ef4SEddie Cai 	gOpts.code472Sleep = DEF_CODE472_SLEEP;
123978884ef4SEddie Cai 	gOpts.code471Num = DEF_CODE471_NUM;
124078884ef4SEddie Cai 	gOpts.code471Path = (line_t*) malloc(sizeof(line_t) * gOpts.code471Num);
124178884ef4SEddie Cai 	strcpy((char*)gOpts.code471Path[0], DEF_CODE471_PATH);
124278884ef4SEddie Cai 	gOpts.code472Num = DEF_CODE472_NUM;
124378884ef4SEddie Cai 	gOpts.code472Path = (line_t*) malloc(sizeof(line_t) * gOpts.code472Num);
124478884ef4SEddie Cai 	strcpy((char*)gOpts.code472Path[0], DEF_CODE472_PATH);
124578884ef4SEddie Cai 	gOpts.loaderNum = DEF_LOADER_NUM;
124678884ef4SEddie Cai 	gOpts.loader = (name_entry*) malloc(sizeof(name_entry) * gOpts.loaderNum);
124778884ef4SEddie Cai 	strcpy(gOpts.loader[0].name, DEF_LOADER0);
124878884ef4SEddie Cai 	strcpy(gOpts.loader[0].path, DEF_LOADER0_PATH);
124978884ef4SEddie Cai 	strcpy(gOpts.loader[1].name, DEF_LOADER1);
125078884ef4SEddie Cai 	strcpy(gOpts.loader[1].path, DEF_LOADER1_PATH);
125178884ef4SEddie Cai 	strcpy(gOpts.outPath, DEF_OUT_PATH);
125278884ef4SEddie Cai 
125378884ef4SEddie Cai 	return parseOpts();
125478884ef4SEddie Cai }
125578884ef4SEddie Cai 
125678884ef4SEddie Cai /************merge code****************/
125778884ef4SEddie Cai 
125878884ef4SEddie Cai static inline uint32_t getBCD(unsigned short value) {
125978884ef4SEddie Cai 	uint8_t tmp[2] = {0};
126078884ef4SEddie Cai 	int i;
126178884ef4SEddie Cai 	uint32_t ret;
126278884ef4SEddie Cai 	//if (value > 0xFFFF) {
126378884ef4SEddie Cai 	//	return 0;
126478884ef4SEddie Cai 	//}
126578884ef4SEddie Cai 	for(i=0; i < 2; i++) {
126678884ef4SEddie Cai 		tmp[i] = (((value/10)%10)<<4) | (value%10);
126778884ef4SEddie Cai 		value /= 100;
126878884ef4SEddie Cai 	}
126978884ef4SEddie Cai 	ret = ((uint16_t)(tmp[1] << 8)) | tmp[0];
127078884ef4SEddie Cai 
127178884ef4SEddie Cai 	printf("ret: %x\n",ret);
127278884ef4SEddie Cai 	return ret&0xFF;
127378884ef4SEddie Cai }
127478884ef4SEddie Cai 
127578884ef4SEddie Cai static inline void str2wide(const char* str, uint16_t* wide, int len)
127678884ef4SEddie Cai {
127778884ef4SEddie Cai 	int i;
127878884ef4SEddie Cai 	for (i = 0; i < len; i++) {
127978884ef4SEddie Cai 		wide[i] = (uint16_t) str[i];
128078884ef4SEddie Cai 	}
128178884ef4SEddie Cai 	wide[len] = 0;
128278884ef4SEddie Cai }
128378884ef4SEddie Cai 
128478884ef4SEddie Cai static inline void getName(char* path, uint16_t* dst) {
128578884ef4SEddie Cai 	char* end;
128678884ef4SEddie Cai 	char* start;
128778884ef4SEddie Cai 	int len;
128878884ef4SEddie Cai 	if (!path || !dst)
128978884ef4SEddie Cai 		return;
129078884ef4SEddie Cai 	start = strrchr(path, '/');
129178884ef4SEddie Cai 	if (!start)
129278884ef4SEddie Cai 		start = path;
129378884ef4SEddie Cai 	else
129478884ef4SEddie Cai 		start++;
129578884ef4SEddie Cai 	end = strrchr(path, '.');
1296641cfa16SEddie Cai 	if (!end || (end < start))
129778884ef4SEddie Cai 		end = path + strlen(path);
129878884ef4SEddie Cai 	len = end - start;
129978884ef4SEddie Cai 	if (len >= MAX_NAME_LEN)
130078884ef4SEddie Cai 		len = MAX_NAME_LEN -1;
130178884ef4SEddie Cai 	str2wide(start, dst, len);
130278884ef4SEddie Cai 
130378884ef4SEddie Cai 
130478884ef4SEddie Cai 		char name[MAX_NAME_LEN];
130578884ef4SEddie Cai 		memset(name, 0, sizeof(name));
130678884ef4SEddie Cai 		memcpy(name, start, len);
130778884ef4SEddie Cai 		printf("path: %s, name: %s\n", path, name);
130878884ef4SEddie Cai 
130978884ef4SEddie Cai }
131078884ef4SEddie Cai 
131178884ef4SEddie Cai static inline bool getFileSize(const char *path, uint32_t* size) {
131278884ef4SEddie Cai 	struct stat st;
131378884ef4SEddie Cai 	if(stat(path, &st) < 0)
131478884ef4SEddie Cai 		return false;
131578884ef4SEddie Cai 	*size = st.st_size;
131678884ef4SEddie Cai 	printf("path: %s, size: %d\n", path, *size);
131778884ef4SEddie Cai 	return true;
131878884ef4SEddie Cai }
131978884ef4SEddie Cai 
132078884ef4SEddie Cai static inline rk_time getTime(void) {
132178884ef4SEddie Cai 	rk_time rkTime;
132278884ef4SEddie Cai 
132378884ef4SEddie Cai 	struct tm *tm;
132478884ef4SEddie Cai 	time_t tt = time(NULL);
132578884ef4SEddie Cai 	tm = localtime(&tt);
132678884ef4SEddie Cai 	rkTime.year = tm->tm_year + 1900;
132778884ef4SEddie Cai 	rkTime.month = tm->tm_mon + 1;
132878884ef4SEddie Cai 	rkTime.day = tm->tm_mday;
132978884ef4SEddie Cai 	rkTime.hour = tm->tm_hour;
133078884ef4SEddie Cai 	rkTime.minute = tm->tm_min;
133178884ef4SEddie Cai 	rkTime.second = tm->tm_sec;
133278884ef4SEddie Cai 	printf("%d-%d-%d %02d:%02d:%02d\n",
133378884ef4SEddie Cai 			rkTime.year, rkTime.month, rkTime.day,
133478884ef4SEddie Cai 			rkTime.hour, rkTime.minute, rkTime.second);
133578884ef4SEddie Cai 	return rkTime;
133678884ef4SEddie Cai }
133778884ef4SEddie Cai 
133878884ef4SEddie Cai static bool writeFile(FILE* outFile, const char* path, bool fix) {
133978884ef4SEddie Cai 	bool ret = false;
134078884ef4SEddie Cai 	uint32_t size = 0, fixSize = 0;
134178884ef4SEddie Cai 	uint8_t* buf;
134278884ef4SEddie Cai 
134378884ef4SEddie Cai 	FILE* inFile = fopen(path, "rb");
134478884ef4SEddie Cai 	if (!inFile)
134578884ef4SEddie Cai 		goto end;
134678884ef4SEddie Cai 
134778884ef4SEddie Cai 	if (!getFileSize(path, &size))
134878884ef4SEddie Cai 		goto end;
134978884ef4SEddie Cai 	if (fix) {
135078884ef4SEddie Cai 		fixSize = ((size - 1) / SMALL_PACKET + 1) * SMALL_PACKET;
135178884ef4SEddie Cai 		uint32_t tmp = fixSize % ENTRY_ALIGN;
135278884ef4SEddie Cai 		tmp = tmp ? (ENTRY_ALIGN - tmp): 0;
135378884ef4SEddie Cai 		fixSize +=tmp;
135478884ef4SEddie Cai 		memset(gBuf, 0, fixSize);
135578884ef4SEddie Cai 	} else {
135678884ef4SEddie Cai 		memset(gBuf, 0, size+ENTRY_ALIGN);
135778884ef4SEddie Cai 	}
135878884ef4SEddie Cai 	if (!fread(gBuf, size, 1, inFile))
135978884ef4SEddie Cai 		goto end;
136078884ef4SEddie Cai 
136178884ef4SEddie Cai 	if (fix) {
136278884ef4SEddie Cai 
136378884ef4SEddie Cai 		buf = gBuf;
136478884ef4SEddie Cai 		size = fixSize;
136578884ef4SEddie Cai 		while(1) {
136678884ef4SEddie Cai 			P_RC4(buf, fixSize < SMALL_PACKET ? fixSize : SMALL_PACKET);
136778884ef4SEddie Cai 			buf += SMALL_PACKET;
136878884ef4SEddie Cai 			if (fixSize <= SMALL_PACKET)
136978884ef4SEddie Cai 				break;
137078884ef4SEddie Cai 			fixSize -= SMALL_PACKET;
137178884ef4SEddie Cai 		}
137278884ef4SEddie Cai 	} else {
137378884ef4SEddie Cai 		uint32_t tmp = size % ENTRY_ALIGN;
137478884ef4SEddie Cai 		tmp = tmp ? (ENTRY_ALIGN - tmp): 0;
137578884ef4SEddie Cai 		size +=tmp;
137678884ef4SEddie Cai 		P_RC4(gBuf, size);
137778884ef4SEddie Cai 	}
137878884ef4SEddie Cai 
137978884ef4SEddie Cai 	if (!fwrite(gBuf, size, 1, outFile))
138078884ef4SEddie Cai 		goto end;
138178884ef4SEddie Cai 	ret = true;
138278884ef4SEddie Cai end:
138378884ef4SEddie Cai 	if (inFile)
138478884ef4SEddie Cai 		fclose(inFile);
138578884ef4SEddie Cai 	if (!ret)
138632268622SAndreas Färber 		printf("writing entry (%s) failed\n", path);
138778884ef4SEddie Cai 	return ret;
138878884ef4SEddie Cai }
138978884ef4SEddie Cai 
139078884ef4SEddie Cai static bool saveEntry(FILE* outFile, char* path, rk_entry_type type,
139178884ef4SEddie Cai 		uint16_t delay, uint32_t* offset, char* fixName, bool fix) {
139278884ef4SEddie Cai 	uint32_t size;
139378884ef4SEddie Cai 	rk_boot_entry entry;
139478884ef4SEddie Cai 
139532268622SAndreas Färber 	printf("writing: %s\n", path);
1396641cfa16SEddie Cai 	memset(&entry, 0, sizeof(rk_boot_entry));
139778884ef4SEddie Cai 	getName(fixName ? fixName: path, entry.name);
139878884ef4SEddie Cai 	entry.size = sizeof(rk_boot_entry);
139978884ef4SEddie Cai 	entry.type = type;
140078884ef4SEddie Cai 	entry.dataOffset = *offset;
140178884ef4SEddie Cai 	if (!getFileSize(path, &size)) {
140232268622SAndreas Färber 		printf("Saving entry (%s) failed:\n\tCannot get file size.\n", path);
140378884ef4SEddie Cai 		return false;
140478884ef4SEddie Cai 	}
140578884ef4SEddie Cai 	if (fix)
140678884ef4SEddie Cai 		size = ((size - 1) / SMALL_PACKET + 1) * SMALL_PACKET;
140778884ef4SEddie Cai 	uint32_t tmp = size % ENTRY_ALIGN;
140878884ef4SEddie Cai 	size += tmp ? (ENTRY_ALIGN - tmp): 0;
140932268622SAndreas Färber 	printf("alignment size: %d\n", size);
141078884ef4SEddie Cai 	entry.dataSize = size;
141178884ef4SEddie Cai 	entry.dataDelay = delay;
141278884ef4SEddie Cai 	*offset += size;
141378884ef4SEddie Cai 	fwrite(&entry, sizeof(rk_boot_entry), 1, outFile);
141478884ef4SEddie Cai 	return true;
141578884ef4SEddie Cai }
141678884ef4SEddie Cai 
141778884ef4SEddie Cai static inline uint32_t convertChipType(const char* chip) {
141878884ef4SEddie Cai 	char buffer[5];
141978884ef4SEddie Cai 	memset(buffer, 0, sizeof(buffer));
142078884ef4SEddie Cai 	snprintf(buffer, sizeof(buffer), "%s", chip);
142178884ef4SEddie Cai 	return buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
142278884ef4SEddie Cai }
142378884ef4SEddie Cai 
142478884ef4SEddie Cai static inline uint32_t getChipType(const char* chip) {
142578884ef4SEddie Cai 	printf("chip: %s\n", chip);
142678884ef4SEddie Cai 	int chipType = RKNONE_DEVICE;
142778884ef4SEddie Cai 	if(!chip) {
142878884ef4SEddie Cai 		goto end;
142978884ef4SEddie Cai 	}
143078884ef4SEddie Cai 	if (!strcmp(chip, CHIP_RK28)) {
143178884ef4SEddie Cai 		chipType = RK28_DEVICE;
143278884ef4SEddie Cai 	} else if (!strcmp(chip, CHIP_RK28)) {
143378884ef4SEddie Cai 		chipType = RK28_DEVICE;
143478884ef4SEddie Cai 	} else if (!strcmp(chip, CHIP_RK281X)) {
143578884ef4SEddie Cai 		chipType = RK281X_DEVICE;
143678884ef4SEddie Cai 	} else if (!strcmp(chip, CHIP_RKPANDA)) {
143778884ef4SEddie Cai 		chipType = RKPANDA_DEVICE;
143878884ef4SEddie Cai 	} else if (!strcmp(chip, CHIP_RK27)) {
143978884ef4SEddie Cai 		chipType = RK27_DEVICE;
144078884ef4SEddie Cai 	} else if (!strcmp(chip, CHIP_RKNANO)) {
144178884ef4SEddie Cai 		chipType = RKNANO_DEVICE;
144278884ef4SEddie Cai 	} else if (!strcmp(chip, CHIP_RKSMART)) {
144378884ef4SEddie Cai 		chipType = RKSMART_DEVICE;
144478884ef4SEddie Cai 	} else if (!strcmp(chip, CHIP_RKCROWN)) {
144578884ef4SEddie Cai 		chipType = RKCROWN_DEVICE;
144678884ef4SEddie Cai 	} else if (!strcmp(chip, CHIP_RKCAYMAN)) {
144778884ef4SEddie Cai 		chipType = RKCAYMAN_DEVICE;
144878884ef4SEddie Cai 	} else if (!strcmp(chip, CHIP_RK29)) {
144978884ef4SEddie Cai 		chipType = RK29_DEVICE;
145078884ef4SEddie Cai 	} else if (!strcmp(chip, CHIP_RK292X)) {
145178884ef4SEddie Cai 		chipType = RK292X_DEVICE;
145278884ef4SEddie Cai 	} else if (!strcmp(chip, CHIP_RK30)) {
145378884ef4SEddie Cai 		chipType = RK30_DEVICE;
145478884ef4SEddie Cai 	} else if (!strcmp(chip, CHIP_RK30B)) {
145578884ef4SEddie Cai 		chipType = RK30B_DEVICE;
145678884ef4SEddie Cai 	} else if (!strcmp(chip, CHIP_RK31)) {
145778884ef4SEddie Cai 		chipType = RK31_DEVICE;
145878884ef4SEddie Cai 	} else if (!strcmp(chip, CHIP_RK32)) {
145978884ef4SEddie Cai 		chipType = RK32_DEVICE;
146078884ef4SEddie Cai 	} else {
146178884ef4SEddie Cai 		chipType = convertChipType(chip + 2);
146278884ef4SEddie Cai 	}
146378884ef4SEddie Cai 
146478884ef4SEddie Cai end:
146578884ef4SEddie Cai 	printf("type: 0x%x\n", chipType);
146678884ef4SEddie Cai 	if (chipType == RKNONE_DEVICE) {
146732268622SAndreas Färber 		printf("chip type not supported!\n");
146878884ef4SEddie Cai 	}
146978884ef4SEddie Cai 	return chipType;
147078884ef4SEddie Cai }
147178884ef4SEddie Cai 
147278884ef4SEddie Cai static inline void getBoothdr(rk_boot_header* hdr) {
147378884ef4SEddie Cai 	memset(hdr, 0, sizeof(rk_boot_header));
147478884ef4SEddie Cai 	hdr->tag = TAG;
147578884ef4SEddie Cai 	hdr->size = sizeof(rk_boot_header);
147678884ef4SEddie Cai 	hdr->version = (getBCD(gOpts.major) << 8) | getBCD(gOpts.minor);
147778884ef4SEddie Cai 	hdr->mergerVersion = MERGER_VERSION;
147878884ef4SEddie Cai 	hdr->releaseTime = getTime();
147978884ef4SEddie Cai 	hdr->chipType = getChipType(gOpts.chip);
148078884ef4SEddie Cai 
148178884ef4SEddie Cai 	hdr->code471Num = gOpts.code471Num;
148278884ef4SEddie Cai 	hdr->code471Offset = sizeof(rk_boot_header);
148378884ef4SEddie Cai 	hdr->code471Size = sizeof(rk_boot_entry);
148478884ef4SEddie Cai 
148578884ef4SEddie Cai 	hdr->code472Num = gOpts.code472Num;
148678884ef4SEddie Cai 	hdr->code472Offset = hdr->code471Offset + gOpts.code471Num * hdr->code471Size;
148778884ef4SEddie Cai 	hdr->code472Size = sizeof(rk_boot_entry);
148878884ef4SEddie Cai 
148978884ef4SEddie Cai 	hdr->loaderNum = gOpts.loaderNum;
149078884ef4SEddie Cai 	hdr->loaderOffset = hdr->code472Offset + gOpts.code472Num * hdr->code472Size;
149178884ef4SEddie Cai 	hdr->loaderSize = sizeof(rk_boot_entry);
149278884ef4SEddie Cai #ifndef USE_P_RC4
149378884ef4SEddie Cai 	hdr->rc4Flag = 1;
149478884ef4SEddie Cai #endif
149578884ef4SEddie Cai }
149678884ef4SEddie Cai 
149778884ef4SEddie Cai static inline uint32_t getCrc(const char* path) {
149878884ef4SEddie Cai 	uint32_t size = 0;
149978884ef4SEddie Cai 	uint32_t crc = 0;
150078884ef4SEddie Cai 
150178884ef4SEddie Cai 	FILE* file = fopen(path, "rb");
150278884ef4SEddie Cai 	getFileSize(path, &size);
150378884ef4SEddie Cai 	if (!file)
150478884ef4SEddie Cai 		goto end;
150578884ef4SEddie Cai 	if (!fread(gBuf, size, 1, file))
150678884ef4SEddie Cai 		goto end;
150778884ef4SEddie Cai 	crc = CRC_32(gBuf, size);
150878884ef4SEddie Cai 	printf("crc: 0x%08x\n", crc);
150978884ef4SEddie Cai end:
151078884ef4SEddie Cai 	if (file)
151178884ef4SEddie Cai 		fclose(file);
151278884ef4SEddie Cai 	return crc;
151378884ef4SEddie Cai }
151478884ef4SEddie Cai 
151578884ef4SEddie Cai bool mergeBoot(void) {
151678884ef4SEddie Cai 	uint32_t dataOffset;
151778884ef4SEddie Cai 	bool ret = false;
151878884ef4SEddie Cai 	int i;
151978884ef4SEddie Cai 	FILE* outFile;
152078884ef4SEddie Cai 	uint32_t crc;
152178884ef4SEddie Cai 	rk_boot_header hdr;
152278884ef4SEddie Cai 
152378884ef4SEddie Cai 	if (!initOpts())
152478884ef4SEddie Cai 		return false;
152578884ef4SEddie Cai 	{
152678884ef4SEddie Cai 		char* subfix = strstr(gOpts.outPath, OUT_SUBFIX);
152778884ef4SEddie Cai 		char version[MAX_LINE_LEN];
152878884ef4SEddie Cai 		snprintf(version, sizeof(version), "%s", gSubfix);
152978884ef4SEddie Cai 		if (subfix && !strcmp(subfix, OUT_SUBFIX)) {
153078884ef4SEddie Cai 			subfix[0] = '\0';
153178884ef4SEddie Cai 		}
153278884ef4SEddie Cai 		strcat(gOpts.outPath, version);
153378884ef4SEddie Cai 		printf("fix opt: %s\n", gOpts.outPath);
153478884ef4SEddie Cai 	}
153578884ef4SEddie Cai 
153678884ef4SEddie Cai 	printf("---------------\nUSING CONFIG:\n");
153778884ef4SEddie Cai 	printOpts(stdout);
153878884ef4SEddie Cai 	printf("---------------\n\n");
153978884ef4SEddie Cai 
154078884ef4SEddie Cai 
154178884ef4SEddie Cai 	outFile = fopen(gOpts.outPath, "wb+");
154278884ef4SEddie Cai 	if (!outFile) {
154332268622SAndreas Färber 		printf("Opening output file (%s) failed\n", gOpts.outPath);
154478884ef4SEddie Cai 		goto end;
154578884ef4SEddie Cai 	}
154678884ef4SEddie Cai 
154778884ef4SEddie Cai 	getBoothdr(&hdr);
154832268622SAndreas Färber 	printf("Writing header...\n");
154978884ef4SEddie Cai 	fwrite(&hdr, 1, sizeof(rk_boot_header), outFile);
155078884ef4SEddie Cai 
155178884ef4SEddie Cai 	dataOffset = sizeof(rk_boot_header) +
155278884ef4SEddie Cai 		(gOpts.code471Num + gOpts.code472Num + gOpts.loaderNum) *
155378884ef4SEddie Cai 		sizeof(rk_boot_entry);
155478884ef4SEddie Cai 
155532268622SAndreas Färber 	printf("Writing code 471 entry...\n");
155678884ef4SEddie Cai 	for (i=0; i<gOpts.code471Num; i++) {
155778884ef4SEddie Cai 		if (!saveEntry(outFile, (char*)gOpts.code471Path[i], ENTRY_471, gOpts.code471Sleep,
155878884ef4SEddie Cai 					&dataOffset, NULL, false))
155978884ef4SEddie Cai 			goto end;
156078884ef4SEddie Cai 	}
156132268622SAndreas Färber 	printf("Writing code 472 entry...\n");
156278884ef4SEddie Cai 	for (i=0; i<gOpts.code472Num; i++) {
156378884ef4SEddie Cai 		if (!saveEntry(outFile, (char*)gOpts.code472Path[i], ENTRY_472, gOpts.code472Sleep,
156478884ef4SEddie Cai 					&dataOffset, NULL, false))
156578884ef4SEddie Cai 			goto end;
156678884ef4SEddie Cai 	}
156732268622SAndreas Färber 	printf("Writing loader entry...\n");
156878884ef4SEddie Cai 	for (i=0; i<gOpts.loaderNum; i++) {
156978884ef4SEddie Cai 		if (!saveEntry(outFile, gOpts.loader[i].path, ENTRY_LOADER, 0,
157078884ef4SEddie Cai 					&dataOffset, gOpts.loader[i].name, true))
157178884ef4SEddie Cai 			goto end;
157278884ef4SEddie Cai 	}
157378884ef4SEddie Cai 
157432268622SAndreas Färber 	printf("Writing code 471...\n");
157578884ef4SEddie Cai 	for (i=0; i<gOpts.code471Num; i++) {
157678884ef4SEddie Cai 		if (!writeFile(outFile, (char*)gOpts.code471Path[i], false))
157778884ef4SEddie Cai 			goto end;
157878884ef4SEddie Cai 	}
157932268622SAndreas Färber 	printf("Writing code 472...\n");
158078884ef4SEddie Cai 	for (i=0; i<gOpts.code472Num; i++) {
158178884ef4SEddie Cai 		if (!writeFile(outFile, (char*)gOpts.code472Path[i], false))
158278884ef4SEddie Cai 			goto end;
158378884ef4SEddie Cai 	}
158432268622SAndreas Färber 	printf("Writing loader...\n");
158578884ef4SEddie Cai 	for (i=0; i<gOpts.loaderNum; i++) {
158678884ef4SEddie Cai 		if (!writeFile(outFile, gOpts.loader[i].path, true))
158778884ef4SEddie Cai 			goto end;
158878884ef4SEddie Cai 	}
158978884ef4SEddie Cai 	fflush(outFile);
159078884ef4SEddie Cai 
159132268622SAndreas Färber 	printf("Writing crc...\n");
159278884ef4SEddie Cai 	crc = getCrc(gOpts.outPath);
159378884ef4SEddie Cai 	if (!fwrite(&crc, sizeof(crc), 1, outFile))
159478884ef4SEddie Cai 		goto end;
159532268622SAndreas Färber 	printf("Done.\n");
159678884ef4SEddie Cai 	ret = true;
159778884ef4SEddie Cai end:
159878884ef4SEddie Cai 	if (outFile)
159978884ef4SEddie Cai 		fclose(outFile);
160078884ef4SEddie Cai 	return ret;
160178884ef4SEddie Cai }
160278884ef4SEddie Cai 
160378884ef4SEddie Cai /************merge code end************/
160478884ef4SEddie Cai /************unpack code***************/
160578884ef4SEddie Cai 
160678884ef4SEddie Cai static inline void wide2str(const uint16_t* wide, char* str, int len)
160778884ef4SEddie Cai {
160878884ef4SEddie Cai 	int i;
160978884ef4SEddie Cai 	for (i = 0; i < len; i++) {
161078884ef4SEddie Cai 		str[i] = (char) (wide[i] & 0xFF);
161178884ef4SEddie Cai 	}
161278884ef4SEddie Cai 	str[len] = 0;
161378884ef4SEddie Cai }
161478884ef4SEddie Cai 
161578884ef4SEddie Cai static bool unpackEntry(rk_boot_entry* entry, const char* name,
161678884ef4SEddie Cai 		FILE* inFile) {
161778884ef4SEddie Cai 	bool ret = false;
161878884ef4SEddie Cai 	int size, i;
161978884ef4SEddie Cai 	FILE* outFile = fopen(name, "wb+");
162078884ef4SEddie Cai 	if (!outFile)
162178884ef4SEddie Cai 		goto end;
162232268622SAndreas Färber 	printf("unpacking entry (%s)\n", name);
162378884ef4SEddie Cai 	fseek(inFile, entry->dataOffset, SEEK_SET);
162478884ef4SEddie Cai 	size = entry->dataSize;
162578884ef4SEddie Cai 	if (!fread(gBuf, size, 1, inFile))
162678884ef4SEddie Cai 		goto end;
162778884ef4SEddie Cai 	if (entry->type == ENTRY_LOADER) {
162878884ef4SEddie Cai 		for(i=0; i<size/SMALL_PACKET; i++)
162978884ef4SEddie Cai 			P_RC4(gBuf + i * SMALL_PACKET, SMALL_PACKET);
163078884ef4SEddie Cai 		if (size % SMALL_PACKET)
163178884ef4SEddie Cai 		{
163278884ef4SEddie Cai 			P_RC4(gBuf + i * SMALL_PACKET, size - SMALL_PACKET * 512);
163378884ef4SEddie Cai 		}
163478884ef4SEddie Cai 	} else {
163578884ef4SEddie Cai 		P_RC4(gBuf, size);
163678884ef4SEddie Cai 	}
163778884ef4SEddie Cai 	if (!fwrite(gBuf, size, 1, outFile))
163878884ef4SEddie Cai 		goto end;
163978884ef4SEddie Cai 	ret = true;
164078884ef4SEddie Cai end:
164178884ef4SEddie Cai 	if (outFile)
164278884ef4SEddie Cai 		fclose(outFile);
164378884ef4SEddie Cai 	return ret;
164478884ef4SEddie Cai }
164578884ef4SEddie Cai 
164678884ef4SEddie Cai bool unpackBoot(char* path) {
164778884ef4SEddie Cai 	bool ret = false;
164878884ef4SEddie Cai 	FILE* inFile = fopen(path, "rb");
164978884ef4SEddie Cai 	int entryNum, i;
165078884ef4SEddie Cai 	char name[MAX_NAME_LEN];
165178884ef4SEddie Cai 	rk_boot_entry* entrys;
165278884ef4SEddie Cai 	if (!inFile) {
165378884ef4SEddie Cai 		fprintf(stderr, "loader (%s) not found\n", path);
165478884ef4SEddie Cai 		goto end;
165578884ef4SEddie Cai 	}
165678884ef4SEddie Cai 
165778884ef4SEddie Cai 	rk_boot_header hdr;
165878884ef4SEddie Cai 	if (!fread(&hdr, sizeof(rk_boot_header), 1, inFile)) {
165932268622SAndreas Färber 		fprintf(stderr, "reading header failed\n");
166078884ef4SEddie Cai 		goto end;
166178884ef4SEddie Cai 	}
166278884ef4SEddie Cai 	printf("471 num:%d, 472 num:%d, loader num:%d\n", hdr.code471Num, hdr.code472Num, hdr.loaderNum);
166378884ef4SEddie Cai 	entryNum = hdr.code471Num + hdr.code472Num + hdr.loaderNum;
166478884ef4SEddie Cai 	entrys = (rk_boot_entry*) malloc(sizeof(rk_boot_entry) * entryNum);
166578884ef4SEddie Cai 	if (!fread(entrys, sizeof(rk_boot_entry) * entryNum, 1, inFile)) {
166632268622SAndreas Färber 		fprintf(stderr, "reading data failed\n");
166778884ef4SEddie Cai 		goto end;
166878884ef4SEddie Cai 	}
166978884ef4SEddie Cai 
167078884ef4SEddie Cai 	printf("entry num: %d\n", entryNum);
167178884ef4SEddie Cai 	for (i=0; i<entryNum; i++) {
167278884ef4SEddie Cai 		wide2str(entrys[i].name, name, MAX_NAME_LEN);
167378884ef4SEddie Cai 
167478884ef4SEddie Cai 		printf("entry: t=%d, name=%s, off=%d, size=%d\n",
167578884ef4SEddie Cai 				entrys[i].type, name, entrys[i].dataOffset,
167678884ef4SEddie Cai 				entrys[i].dataSize);
167778884ef4SEddie Cai 		if (!unpackEntry(entrys + i, name, inFile)) {
167832268622SAndreas Färber 			fprintf(stderr, "unpacking entry (%s) failed\n", name);
167978884ef4SEddie Cai 			goto end;
168078884ef4SEddie Cai 		}
168178884ef4SEddie Cai 	}
168278884ef4SEddie Cai 	printf("done\n");
168378884ef4SEddie Cai 	ret = true;
168478884ef4SEddie Cai end:
168578884ef4SEddie Cai 	if (inFile)
168678884ef4SEddie Cai 		fclose(inFile);
168778884ef4SEddie Cai 	return ret;
168878884ef4SEddie Cai }
168978884ef4SEddie Cai 
169076af099aSliuyi bool download_boot(STRUCT_RKDEVICE_DESC &dev, char *szLoader)
169176af099aSliuyi {
169276af099aSliuyi 	if (!check_device_type(dev, RKUSB_MASKROM))
169376af099aSliuyi 		return false;
169476af099aSliuyi 	CRKImage *pImage = NULL;
169576af099aSliuyi 	CRKBoot *pBoot = NULL;
169676af099aSliuyi 	bool bRet, bSuccess = false;
169776af099aSliuyi 	int iRet;
169876af099aSliuyi 
169976af099aSliuyi 	pImage = new CRKImage(szLoader, bRet);
170076af099aSliuyi 	if (!bRet){
170176af099aSliuyi 		ERROR_COLOR_ATTR;
170232268622SAndreas Färber 		printf("Opening loader failed, exiting download boot!");
170376af099aSliuyi 		NORMAL_COLOR_ATTR;
170476af099aSliuyi 		printf("\r\n");
170576af099aSliuyi 		return bSuccess;
170676af099aSliuyi 	} else {
170776af099aSliuyi 		pBoot = (CRKBoot *)pImage->m_bootObject;
170876af099aSliuyi 		CRKComm *pComm = NULL;
170976af099aSliuyi 		CRKDevice *pDevice = NULL;
171076af099aSliuyi 
171176af099aSliuyi 		dev.emDeviceType = pBoot->SupportDevice;
171276af099aSliuyi 		pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
171376af099aSliuyi 		if (!bRet) {
171476af099aSliuyi 			if (pImage)
171576af099aSliuyi 				delete pImage;
171676af099aSliuyi 			ERROR_COLOR_ATTR;
171776af099aSliuyi 			printf("Creating Comm Object failed!");
171876af099aSliuyi 			NORMAL_COLOR_ATTR;
171976af099aSliuyi 			printf("\r\n");
172076af099aSliuyi 			return bSuccess;
172176af099aSliuyi 		}
172276af099aSliuyi 
172376af099aSliuyi 		pDevice = new CRKDevice(dev);
172476af099aSliuyi 		if (!pDevice) {
172576af099aSliuyi 			if (pImage)
172676af099aSliuyi 				delete pImage;
172776af099aSliuyi 			if (pComm)
172876af099aSliuyi 				delete pComm;
172976af099aSliuyi 			ERROR_COLOR_ATTR;
173076af099aSliuyi 			printf("Creating device object failed!");
173176af099aSliuyi 			NORMAL_COLOR_ATTR;
173276af099aSliuyi 			printf("\r\n");
173376af099aSliuyi 			return bSuccess;
173476af099aSliuyi 		}
173576af099aSliuyi 
173676af099aSliuyi 		pDevice->SetObject(pImage, pComm, g_pLogObject);
173732268622SAndreas Färber 		printf("Downloading bootloader...\r\n");
173876af099aSliuyi 		iRet = pDevice->DownloadBoot();
173976af099aSliuyi 
174076af099aSliuyi 		CURSOR_MOVEUP_LINE(1);
174176af099aSliuyi 		CURSOR_DEL_LINE;
174276af099aSliuyi 		if (iRet == 0) {
174376af099aSliuyi 			bSuccess = true;
174432268622SAndreas Färber 			printf("Downloading bootloader succeeded.\r\n");
174576af099aSliuyi 		}
174676af099aSliuyi 		else
174732268622SAndreas Färber 			printf("Downloading bootloader failed!\r\n");
174876af099aSliuyi 
174976af099aSliuyi 		if (pImage)
175076af099aSliuyi 			delete pImage;
175176af099aSliuyi 		if(pDevice)
175276af099aSliuyi 			delete pDevice;
175376af099aSliuyi 	}
175476af099aSliuyi 	return bSuccess;
175576af099aSliuyi }
1756c30d921cSKever Yang bool upgrade_loader(STRUCT_RKDEVICE_DESC &dev, char *szLoader)
1757c30d921cSKever Yang {
1758c30d921cSKever Yang 	if (!check_device_type(dev, RKUSB_MASKROM))
1759c30d921cSKever Yang 		return false;
1760c30d921cSKever Yang 	CRKImage *pImage = NULL;
1761c30d921cSKever Yang 	CRKBoot *pBoot = NULL;
1762c30d921cSKever Yang 	CRKComm *pComm = NULL;
1763c30d921cSKever Yang 	bool bRet, bSuccess = false;
1764c30d921cSKever Yang 	int iRet;
1765c30d921cSKever Yang 	char index;
1766c30d921cSKever Yang 	USHORT usFlashDataSec, usFlashBootSec;
1767c30d921cSKever Yang 	DWORD dwLoaderSize, dwLoaderDataSize, dwDelay, dwSectorNum;
1768c30d921cSKever Yang 	char loaderCodeName[] = "FlashBoot";
1769c30d921cSKever Yang 	char loaderDataName[] = "FlashData";
1770c30d921cSKever Yang 	PBYTE loaderCodeBuffer = NULL;
1771c30d921cSKever Yang 	PBYTE loaderDataBuffer = NULL;
1772c30d921cSKever Yang 	PBYTE pIDBData = NULL;
1773c30d921cSKever Yang 	pImage = new CRKImage(szLoader, bRet);
1774c30d921cSKever Yang 	if (!bRet){
1775c30d921cSKever Yang 		ERROR_COLOR_ATTR;
177632268622SAndreas Färber 		printf("Opening loader failed, exiting upgrade loader!");
1777c30d921cSKever Yang 		NORMAL_COLOR_ATTR;
1778c30d921cSKever Yang 		printf("\r\n");
1779c30d921cSKever Yang 		goto Exit_UpgradeLoader;
1780c30d921cSKever Yang 	} else {
1781c30d921cSKever Yang 		pBoot = (CRKBoot *)pImage->m_bootObject;
1782c30d921cSKever Yang 		dev.emDeviceType = pBoot->SupportDevice;
1783c30d921cSKever Yang 		pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
1784c30d921cSKever Yang 		if (!bRet) {
1785c30d921cSKever Yang 			ERROR_COLOR_ATTR;
1786c30d921cSKever Yang 			printf("Creating Comm Object failed!");
1787c30d921cSKever Yang 			NORMAL_COLOR_ATTR;
1788c30d921cSKever Yang 			printf("\r\n");
1789c30d921cSKever Yang 			goto Exit_UpgradeLoader;
1790c30d921cSKever Yang 		}
1791c30d921cSKever Yang 
179232268622SAndreas Färber 		printf("Upgrading loader...\r\n");
1793c30d921cSKever Yang 		index = pBoot->GetIndexByName(ENTRYLOADER, loaderCodeName);
1794c30d921cSKever Yang 		if (index == -1) {
1795c30d921cSKever Yang 			if (g_pLogObject) {
179632268622SAndreas Färber 				g_pLogObject->Record("ERROR: %s --> Get LoaderCode Entry failed", __func__);
1797c30d921cSKever Yang 			}
1798c30d921cSKever Yang 			goto Exit_UpgradeLoader;
1799c30d921cSKever Yang 		}
1800c30d921cSKever Yang 		bRet = pBoot->GetEntryProperty(ENTRYLOADER, index, dwLoaderSize, dwDelay);
1801c30d921cSKever Yang 		if (!bRet) {
1802c30d921cSKever Yang 			if (g_pLogObject) {
180332268622SAndreas Färber 				g_pLogObject->Record("ERROR: %s --> Get LoaderCode Entry Size failed", __func__);
1804c30d921cSKever Yang 			}
1805c30d921cSKever Yang 			goto Exit_UpgradeLoader;
1806c30d921cSKever Yang 		}
1807c30d921cSKever Yang 
1808c30d921cSKever Yang 		loaderCodeBuffer = new BYTE[dwLoaderSize];
1809c30d921cSKever Yang 		memset(loaderCodeBuffer, 0, dwLoaderSize);
1810c30d921cSKever Yang 		if (!pBoot->GetEntryData(ENTRYLOADER, index, loaderCodeBuffer)) {
1811c30d921cSKever Yang 			if (g_pLogObject) {
181232268622SAndreas Färber 				g_pLogObject->Record("ERROR: %s --> Get LoaderCode Data failed", __func__);
1813c30d921cSKever Yang 			}
1814c30d921cSKever Yang 			goto Exit_UpgradeLoader;
1815c30d921cSKever Yang 		}
1816c30d921cSKever Yang 
1817c30d921cSKever Yang 		index = pBoot->GetIndexByName(ENTRYLOADER, loaderDataName);
1818c30d921cSKever Yang 		if (index == -1) {
1819c30d921cSKever Yang 			if (g_pLogObject) {
182032268622SAndreas Färber 				g_pLogObject->Record("ERROR: %s --> Get LoaderData Entry failed", __func__);
1821c30d921cSKever Yang 			}
1822c30d921cSKever Yang 			delete []loaderCodeBuffer;
1823c30d921cSKever Yang 			return -4;
1824c30d921cSKever Yang 		}
1825c30d921cSKever Yang 
1826c30d921cSKever Yang 		bRet = pBoot->GetEntryProperty(ENTRYLOADER, index, dwLoaderDataSize, dwDelay);
1827c30d921cSKever Yang 		if (!bRet) {
1828c30d921cSKever Yang 			if (g_pLogObject) {
182932268622SAndreas Färber 				g_pLogObject->Record("ERROR: %s --> Get LoaderData Entry Size failed", __func__);
1830c30d921cSKever Yang 			}
1831c30d921cSKever Yang 			goto Exit_UpgradeLoader;
1832c30d921cSKever Yang 		}
1833c30d921cSKever Yang 
1834c30d921cSKever Yang 		loaderDataBuffer = new BYTE[dwLoaderDataSize];
1835c30d921cSKever Yang 		memset(loaderDataBuffer, 0, dwLoaderDataSize);
1836c30d921cSKever Yang 		if (!pBoot->GetEntryData(ENTRYLOADER,index,loaderDataBuffer)) {
1837c30d921cSKever Yang 			if (g_pLogObject) {
183832268622SAndreas Färber 				g_pLogObject->Record("ERROR: %s --> Get LoaderData Data failed", __func__);
1839c30d921cSKever Yang 			}
1840c30d921cSKever Yang 			goto Exit_UpgradeLoader;
1841c30d921cSKever Yang 		}
1842c30d921cSKever Yang 
1843c30d921cSKever Yang 		usFlashDataSec = (ALIGN(dwLoaderDataSize, 2048)) / SECTOR_SIZE;
1844c30d921cSKever Yang 		usFlashBootSec = (ALIGN(dwLoaderSize, 2048)) / SECTOR_SIZE;
1845c30d921cSKever Yang 		dwSectorNum = 4 + usFlashDataSec + usFlashBootSec;
1846c30d921cSKever Yang 		pIDBData = new BYTE[dwSectorNum*SECTOR_SIZE];
1847c30d921cSKever Yang 		if (!pIDBData) {
1848c30d921cSKever Yang 			ERROR_COLOR_ATTR;
184932268622SAndreas Färber 			printf("Allocating memory failed!");
1850c30d921cSKever Yang 			NORMAL_COLOR_ATTR;
1851c30d921cSKever Yang 			printf("\r\n");
1852c30d921cSKever Yang 			goto Exit_UpgradeLoader;
1853c30d921cSKever Yang 		}
1854c30d921cSKever Yang 		memset(pIDBData, 0, dwSectorNum * SECTOR_SIZE);
1855b38fe5fcSliuyi 		iRet = MakeIDBlockData(loaderDataBuffer, loaderCodeBuffer, pIDBData, usFlashDataSec, usFlashBootSec, dwLoaderDataSize, dwLoaderSize, pBoot->Rc4DisableFlag);
1856c30d921cSKever Yang 		if (iRet != 0) {
1857c30d921cSKever Yang 			ERROR_COLOR_ATTR;
185832268622SAndreas Färber 			printf("Making idblock failed!");
1859c30d921cSKever Yang 			NORMAL_COLOR_ATTR;
1860c30d921cSKever Yang 			printf("\r\n");
1861c30d921cSKever Yang 			goto Exit_UpgradeLoader;
1862c30d921cSKever Yang 		}
1863c30d921cSKever Yang 		iRet = pComm->RKU_WriteLBA(64, dwSectorNum, pIDBData);
1864c30d921cSKever Yang 		CURSOR_MOVEUP_LINE(1);
1865c30d921cSKever Yang 		CURSOR_DEL_LINE;
1866c30d921cSKever Yang 		if (iRet == ERR_SUCCESS) {
1867b38fe5fcSliuyi 			//pComm->Reset_Usb_Device();
1868c30d921cSKever Yang 			bSuccess = true;
186932268622SAndreas Färber 			printf("Upgrading loader succeeded.\r\n");
1870c30d921cSKever Yang 		} else {
187132268622SAndreas Färber 			printf("Upgrading loader failed!\r\n");
1872c30d921cSKever Yang 			goto Exit_UpgradeLoader;
1873c30d921cSKever Yang 		}
1874c30d921cSKever Yang 	}
1875c30d921cSKever Yang Exit_UpgradeLoader:
1876c30d921cSKever Yang 	if (pImage)
1877c30d921cSKever Yang 		delete pImage;
1878c30d921cSKever Yang 	if (pComm)
1879c30d921cSKever Yang 		delete pComm;
1880c30d921cSKever Yang 	if (loaderCodeBuffer)
1881c30d921cSKever Yang 		delete []loaderCodeBuffer;
1882c30d921cSKever Yang 	if (loaderDataBuffer)
1883c30d921cSKever Yang 		delete []loaderDataBuffer;
1884c30d921cSKever Yang 	if (pIDBData)
1885c30d921cSKever Yang 		delete []pIDBData;
1886c30d921cSKever Yang 	return bSuccess;
1887c30d921cSKever Yang }
18883dc7e3ceSliuyi bool print_gpt(STRUCT_RKDEVICE_DESC &dev)
18893dc7e3ceSliuyi {
18903dc7e3ceSliuyi 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
18913dc7e3ceSliuyi 		return false;
18923dc7e3ceSliuyi 	u8 master_gpt[34 * SECTOR_SIZE];
18933dc7e3ceSliuyi 	gpt_header *gptHead = (gpt_header *)(master_gpt + SECTOR_SIZE);
18943dc7e3ceSliuyi 	bool bRet, bSuccess = false;
18953dc7e3ceSliuyi 	int iRet;
18963dc7e3ceSliuyi 	gpt_entry  *gptEntry  = NULL;
18973dc7e3ceSliuyi 	u32 i,j;
18983dc7e3ceSliuyi 	u8 zerobuf[GPT_ENTRY_SIZE];
18993dc7e3ceSliuyi 	memset(zerobuf,0,GPT_ENTRY_SIZE);
19003dc7e3ceSliuyi 	CRKComm *pComm = NULL;
19013dc7e3ceSliuyi 	char partName[36];
19023dc7e3ceSliuyi 	pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
19033dc7e3ceSliuyi 	if (!bRet) {
19043dc7e3ceSliuyi 		ERROR_COLOR_ATTR;
19053dc7e3ceSliuyi 		printf("Creating Comm Object failed!");
19063dc7e3ceSliuyi 		NORMAL_COLOR_ATTR;
19073dc7e3ceSliuyi 		printf("\r\n");
19083dc7e3ceSliuyi 		return bSuccess;
19093dc7e3ceSliuyi 	}
19103dc7e3ceSliuyi 	iRet = pComm->RKU_ReadLBA( 0, 34, master_gpt);
19113dc7e3ceSliuyi 	if(ERR_SUCCESS == iRet) {
19123dc7e3ceSliuyi 		if (gptHead->signature != le64_to_cpu(GPT_HEADER_SIGNATURE)) {
19133dc7e3ceSliuyi 			if (g_pLogObject)
19143dc7e3ceSliuyi 				g_pLogObject->Record("Error: invalid gpt signature");
19153dc7e3ceSliuyi 			printf("Invalid GPT signature!\r\n");
19163dc7e3ceSliuyi 			goto Exit_PrintGpt;
19173dc7e3ceSliuyi 		}
19183dc7e3ceSliuyi 
19193dc7e3ceSliuyi 	} else {
19203dc7e3ceSliuyi 		if (g_pLogObject)
19213dc7e3ceSliuyi 				g_pLogObject->Record("Error: read gpt failed, err=%d", iRet);
19223dc7e3ceSliuyi 		printf("Read GPT failed!\r\n");
19233dc7e3ceSliuyi 		goto Exit_PrintGpt;
19243dc7e3ceSliuyi 	}
19253dc7e3ceSliuyi 
19263dc7e3ceSliuyi 	printf("**********GPT Info**********\r\n");
19273dc7e3ceSliuyi 	printf("NO  LBA       Name                \r\n");
19283dc7e3ceSliuyi 	for (i = 0; i < le32_to_cpu(gptHead->num_partition_entries); i++) {
19293dc7e3ceSliuyi 		gptEntry = (gpt_entry *)(master_gpt + 2 * SECTOR_SIZE + i * GPT_ENTRY_SIZE);
19303dc7e3ceSliuyi 		if (memcmp(zerobuf, (u8 *)gptEntry, GPT_ENTRY_SIZE) == 0)
19313dc7e3ceSliuyi 			break;
19323dc7e3ceSliuyi 		memset(partName, 0 , 36);
19333dc7e3ceSliuyi 		j = 0;
19343dc7e3ceSliuyi 		while (gptEntry->partition_name[j]) {
19353dc7e3ceSliuyi 			partName[j] = (char)gptEntry->partition_name[j];
19363dc7e3ceSliuyi 			j++;
19373dc7e3ceSliuyi 		}
19383dc7e3ceSliuyi 		printf("%02d  %08X  %s\r\n", i, (u32)le64_to_cpu(gptEntry->starting_lba), partName);
19393dc7e3ceSliuyi 	}
19403dc7e3ceSliuyi 	bSuccess = true;
19413dc7e3ceSliuyi Exit_PrintGpt:
19423dc7e3ceSliuyi 	if (pComm)
19433dc7e3ceSliuyi 		delete pComm;
19443dc7e3ceSliuyi 	return bSuccess;
19453dc7e3ceSliuyi }
1946c30d921cSKever Yang 
194776af099aSliuyi bool erase_flash(STRUCT_RKDEVICE_DESC &dev)
194876af099aSliuyi {
194976af099aSliuyi 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
195076af099aSliuyi 		return false;
195176af099aSliuyi 	CRKImage *pImage = NULL;
195276af099aSliuyi 	bool bRet, bSuccess = false;
195376af099aSliuyi 	int iRet;
195476af099aSliuyi 	CRKScan *pScan = NULL;
195576af099aSliuyi 	pScan = new CRKScan();
195676af099aSliuyi 	pScan->SetVidPid();
195776af099aSliuyi 
195876af099aSliuyi 	CRKComm *pComm = NULL;
195976af099aSliuyi 	CRKDevice *pDevice = NULL;
196076af099aSliuyi 
196176af099aSliuyi 	pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
196276af099aSliuyi 	if (!bRet) {
196376af099aSliuyi 		if (pScan)
196476af099aSliuyi 			delete pScan;
196576af099aSliuyi 		ERROR_COLOR_ATTR;
196676af099aSliuyi 		printf("Creating Comm Object failed!");
196776af099aSliuyi 		NORMAL_COLOR_ATTR;
196876af099aSliuyi 		printf("\r\n");
196976af099aSliuyi 		return bSuccess;
197076af099aSliuyi 	}
197176af099aSliuyi 
197276af099aSliuyi 	pDevice = new CRKDevice(dev);
197376af099aSliuyi 	if (!pDevice) {
197476af099aSliuyi 		if (pComm)
197576af099aSliuyi 			delete pComm;
197676af099aSliuyi 		if (pScan)
197776af099aSliuyi 			delete pScan;
197876af099aSliuyi 		ERROR_COLOR_ATTR;
197976af099aSliuyi 		printf("Creating device object failed!");
198076af099aSliuyi 		NORMAL_COLOR_ATTR;
198176af099aSliuyi 		printf("\r\n");
198276af099aSliuyi 		return bSuccess;
198376af099aSliuyi 	}
198476af099aSliuyi 
198576af099aSliuyi 	pDevice->SetObject(pImage, pComm, g_pLogObject);
198676af099aSliuyi 	pDevice->CallBackPointer = ProgressInfoProc;
198776af099aSliuyi 
198832268622SAndreas Färber 	printf("Starting to erase flash...\r\n");
19896502326dSliuyi 	bRet = pDevice->GetFlashInfo();
19906502326dSliuyi 	if (!bRet) {
19916502326dSliuyi 		if (pDevice)
19926502326dSliuyi 			delete pDevice;
19936502326dSliuyi 		if (pScan)
19946502326dSliuyi 			delete pScan;
19956502326dSliuyi 		ERROR_COLOR_ATTR;
19966502326dSliuyi 		printf("Getting flash info from device failed!");
19976502326dSliuyi 		NORMAL_COLOR_ATTR;
19986502326dSliuyi 		printf("\r\n");
19996502326dSliuyi 		return bSuccess;
20006502326dSliuyi 	}
200176af099aSliuyi 	iRet = pDevice->EraseAllBlocks();
200276af099aSliuyi 	if (pDevice)
200376af099aSliuyi 		delete pDevice;
200476af099aSliuyi 
200576af099aSliuyi 	if (iRet == 0) {
200676af099aSliuyi 		if (pScan) {
200776af099aSliuyi 			pScan->SetVidPid();
200876af099aSliuyi 			pScan->Wait(dev, RKUSB_MASKROM, dev.usVid, dev.usPid);
200976af099aSliuyi 			delete pScan;
201076af099aSliuyi 		}
201176af099aSliuyi 		CURSOR_MOVEUP_LINE(1);
201276af099aSliuyi 		CURSOR_DEL_LINE;
201376af099aSliuyi 		bSuccess = true;
201432268622SAndreas Färber 		printf("Erasing flash complete.\r\n");
201576af099aSliuyi 	}
201676af099aSliuyi 
201776af099aSliuyi 	return bSuccess;
201876af099aSliuyi }
201976af099aSliuyi 
202076af099aSliuyi bool test_device(STRUCT_RKDEVICE_DESC &dev)
202176af099aSliuyi {
202276af099aSliuyi 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
202376af099aSliuyi 		return false;
202476af099aSliuyi 	CRKUsbComm *pComm = NULL;
202576af099aSliuyi 	bool bRet, bSuccess = false;
202676af099aSliuyi 	int iRet;
202776af099aSliuyi 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
202876af099aSliuyi 	if (bRet) {
202976af099aSliuyi 		iRet = pComm->RKU_TestDeviceReady();
203076af099aSliuyi 		if (iRet != ERR_SUCCESS) {
203176af099aSliuyi 			if (g_pLogObject)
203276af099aSliuyi 				g_pLogObject->Record("Error: RKU_TestDeviceReady failed, err=%d", iRet);
203332268622SAndreas Färber 			printf("Test Device failed!\r\n");
203476af099aSliuyi 		} else {
203576af099aSliuyi 			bSuccess = true;
203676af099aSliuyi 			printf("Test Device OK.\r\n");
203776af099aSliuyi 		}
203876af099aSliuyi 	} else {
203932268622SAndreas Färber 		printf("Test Device quit, creating comm object failed!\r\n");
204076af099aSliuyi 	}
204176af099aSliuyi 	if (pComm) {
204276af099aSliuyi 		delete pComm;
204376af099aSliuyi 		pComm = NULL;
204476af099aSliuyi 	}
204576af099aSliuyi 	return bSuccess;
204676af099aSliuyi }
204776af099aSliuyi bool reset_device(STRUCT_RKDEVICE_DESC &dev, BYTE subCode = RST_NONE_SUBCODE)
204876af099aSliuyi {
204976af099aSliuyi 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
205076af099aSliuyi 		return false;
205176af099aSliuyi 	CRKUsbComm *pComm = NULL;
205276af099aSliuyi 	bool bRet, bSuccess = false;
205376af099aSliuyi 	int iRet;
205476af099aSliuyi 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
205576af099aSliuyi 	if (bRet) {
205676af099aSliuyi 		iRet = pComm->RKU_ResetDevice(subCode);
205776af099aSliuyi 		if (iRet != ERR_SUCCESS) {
205876af099aSliuyi 			if (g_pLogObject)
205976af099aSliuyi 				g_pLogObject->Record("Error: RKU_ResetDevice failed, err=%d", iRet);
206032268622SAndreas Färber 			printf("Reset Device failed!\r\n");
206176af099aSliuyi 		} else {
206276af099aSliuyi 			bSuccess = true;
206376af099aSliuyi 			printf("Reset Device OK.\r\n");
206476af099aSliuyi 		}
206576af099aSliuyi 	} else {
206632268622SAndreas Färber 		printf("Reset Device quit, creating comm object failed!\r\n");
206776af099aSliuyi 	}
206876af099aSliuyi 	if (pComm) {
206976af099aSliuyi 		delete pComm;
207076af099aSliuyi 		pComm = NULL;
207176af099aSliuyi 	}
207276af099aSliuyi 	return bSuccess;
207376af099aSliuyi }
207476af099aSliuyi 
207576af099aSliuyi bool read_flash_id(STRUCT_RKDEVICE_DESC &dev)
207676af099aSliuyi {
207776af099aSliuyi 	CRKUsbComm *pComm = NULL;
207876af099aSliuyi 	bool bRet, bSuccess = false;
207976af099aSliuyi 	int iRet;
208076af099aSliuyi 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
208176af099aSliuyi 		return bSuccess;
208276af099aSliuyi 
208376af099aSliuyi 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
208476af099aSliuyi 	if (bRet) {
208576af099aSliuyi 		BYTE flashID[5];
208676af099aSliuyi 		iRet = pComm->RKU_ReadFlashID(flashID);
208776af099aSliuyi 		if (iRet != ERR_SUCCESS) {
208876af099aSliuyi 			if (g_pLogObject)
208976af099aSliuyi 				g_pLogObject->Record("Error: RKU_ReadFlashID failed, err=%d", iRet);
209032268622SAndreas Färber 			printf("Reading flash ID failed!\r\n");
209176af099aSliuyi 		} else {
209276af099aSliuyi 			printf("Flash ID: %02X %02X %02X %02X %02X\r\n", flashID[0], flashID[1], flashID[2], flashID[3], flashID[4]);
209376af099aSliuyi 			bSuccess = true;
209476af099aSliuyi 		}
209576af099aSliuyi 	} else {
209632268622SAndreas Färber 		printf("Read Flash ID quit, creating comm object failed!\r\n");
209776af099aSliuyi 	}
209876af099aSliuyi 	if (pComm) {
209976af099aSliuyi 		delete pComm;
210076af099aSliuyi 		pComm = NULL;
210176af099aSliuyi 	}
210276af099aSliuyi 	return bSuccess;
210376af099aSliuyi }
210476af099aSliuyi bool read_flash_info(STRUCT_RKDEVICE_DESC &dev)
210576af099aSliuyi {
210676af099aSliuyi 	CRKUsbComm *pComm = NULL;
210776af099aSliuyi 	bool bRet, bSuccess = false;
210876af099aSliuyi 	int iRet;
210976af099aSliuyi 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
211076af099aSliuyi 		return bSuccess;
211176af099aSliuyi 
211276af099aSliuyi 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
211376af099aSliuyi 	if (bRet) {
211476af099aSliuyi 		STRUCT_FLASHINFO_CMD info;
211576af099aSliuyi 		UINT uiRead;
211676af099aSliuyi 		iRet = pComm->RKU_ReadFlashInfo((BYTE *)&info, &uiRead);
211776af099aSliuyi 		if (iRet != ERR_SUCCESS) {
211876af099aSliuyi 			if (g_pLogObject)
211976af099aSliuyi 				g_pLogObject->Record("Error: RKU_ReadFlashInfo failed, err=%d", iRet);
212032268622SAndreas Färber 			printf("Read Flash Info failed!\r\n");
212176af099aSliuyi 		} else {
212276af099aSliuyi 			printf("Flash Info:\r\n");
212376af099aSliuyi 			if (info.bManufCode <= 7) {
212476af099aSliuyi 				printf("\tManufacturer: %s, value=%02X\r\n", szManufName[info.bManufCode], info.bManufCode);
212576af099aSliuyi 			}
212676af099aSliuyi 			else
212776af099aSliuyi 				printf("\tManufacturer: %s, value=%02X\r\n", "Unknown", info.bManufCode);
212876af099aSliuyi 
212976af099aSliuyi 			printf("\tFlash Size: %d MB\r\n", info.uiFlashSize / 2 / 1024);
213076af099aSliuyi 			printf("\tBlock Size: %d KB\r\n", info.usBlockSize / 2);
213176af099aSliuyi 			printf("\tPage Size: %d KB\r\n", info.bPageSize / 2);
213276af099aSliuyi 			printf("\tECC Bits: %d\r\n", info.bECCBits);
213376af099aSliuyi 			printf("\tAccess Time: %d\r\n", info.bAccessTime);
213476af099aSliuyi 			printf("\tFlash CS: ");
213576af099aSliuyi 			for(int i = 0; i < 8; i++) {
213676af099aSliuyi 				if( info.bFlashCS & (1 << i) )
213776af099aSliuyi 					printf("Flash<%d> ", i);
213876af099aSliuyi 			}
213976af099aSliuyi 			printf("\r\n");
214076af099aSliuyi 			bSuccess = true;
214176af099aSliuyi 		}
214276af099aSliuyi 	}else {
214332268622SAndreas Färber 		printf("Read Flash Info quit, creating comm object failed!\r\n");
214476af099aSliuyi 	}
214576af099aSliuyi 	if (pComm) {
214676af099aSliuyi 		delete pComm;
214776af099aSliuyi 		pComm = NULL;
214876af099aSliuyi 	}
214976af099aSliuyi 	return bSuccess;
215076af099aSliuyi }
215176af099aSliuyi bool read_chip_info(STRUCT_RKDEVICE_DESC &dev)
215276af099aSliuyi {
215376af099aSliuyi 	CRKUsbComm *pComm = NULL;
215476af099aSliuyi 	bool bRet, bSuccess = false;
215576af099aSliuyi 	int iRet;
215676af099aSliuyi 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
215776af099aSliuyi 		return bSuccess;
215876af099aSliuyi 
215976af099aSliuyi 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
216076af099aSliuyi 	if (bRet) {
216176af099aSliuyi 		BYTE chipInfo[16];
216276af099aSliuyi 		iRet = pComm->RKU_ReadChipInfo(chipInfo);
216376af099aSliuyi 		if (iRet != ERR_SUCCESS) {
216476af099aSliuyi 			if (g_pLogObject)
216576af099aSliuyi 				g_pLogObject->Record("Error: RKU_ReadChipInfo failed, err=%d", iRet);
216632268622SAndreas Färber 			printf("Read Chip Info failed!\r\n");
216776af099aSliuyi 		} else {
216876af099aSliuyi 			string strChipInfo;
216976af099aSliuyi 			g_pLogObject->PrintBuffer(strChipInfo, chipInfo, 16, 16);
217076af099aSliuyi 			printf("Chip Info: %s\r\n", strChipInfo.c_str());
217176af099aSliuyi 			bSuccess = true;
217276af099aSliuyi 		}
217376af099aSliuyi 	} else {
217432268622SAndreas Färber 		printf("Read Chip Info quit, creating comm object failed!\r\n");
217576af099aSliuyi 	}
217676af099aSliuyi 	if (pComm) {
217776af099aSliuyi 		delete pComm;
217876af099aSliuyi 		pComm = NULL;
217976af099aSliuyi 	}
218076af099aSliuyi 	return bSuccess;
218176af099aSliuyi }
21826ae612beSliuyi bool read_gpt(STRUCT_RKDEVICE_DESC &dev, u8 *pGpt)
21836ae612beSliuyi {
21846ae612beSliuyi 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
21856ae612beSliuyi 		return false;
21866ae612beSliuyi 	gpt_header *gptHead = (gpt_header *)(pGpt + SECTOR_SIZE);
21876ae612beSliuyi 	CRKUsbComm *pComm = NULL;
21886ae612beSliuyi 	bool bRet, bSuccess = false;
21896ae612beSliuyi 	int iRet;
21906ae612beSliuyi 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
21916ae612beSliuyi 	if (bRet) {
21926ae612beSliuyi 		iRet = pComm->RKU_ReadLBA( 0, 34, pGpt);
21936ae612beSliuyi 		if(ERR_SUCCESS == iRet) {
21946ae612beSliuyi 			if (gptHead->signature != le64_to_cpu(GPT_HEADER_SIGNATURE)) {
21956ae612beSliuyi 				if (g_pLogObject)
21966ae612beSliuyi 					g_pLogObject->Record("Error: invalid gpt signature");
21976ae612beSliuyi 				printf("Invalid GPT signature!\r\n");
21986ae612beSliuyi 				goto Exit_ReadGPT;
21996ae612beSliuyi 			}
22006ae612beSliuyi 
22016ae612beSliuyi 		} else {
22026ae612beSliuyi 			if (g_pLogObject)
22036ae612beSliuyi 					g_pLogObject->Record("Error: read gpt failed, err=%d", iRet);
22046ae612beSliuyi 			printf("Read GPT failed!\r\n");
22056ae612beSliuyi 			goto Exit_ReadGPT;
22066ae612beSliuyi 		}
22076ae612beSliuyi 		bSuccess = true;
22086ae612beSliuyi 	}
22096ae612beSliuyi Exit_ReadGPT:
22106ae612beSliuyi 	if (pComm) {
22116ae612beSliuyi 		delete pComm;
22126ae612beSliuyi 		pComm = NULL;
22136ae612beSliuyi 	}
22146ae612beSliuyi 	return bSuccess;
22156ae612beSliuyi }
221676af099aSliuyi bool read_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, UINT uiLen, char *szFile)
221776af099aSliuyi {
221876af099aSliuyi 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
221976af099aSliuyi 		return false;
222076af099aSliuyi 	CRKUsbComm *pComm = NULL;
222176af099aSliuyi 	FILE *file = NULL;
222276af099aSliuyi 	bool bRet, bFirst = true, bSuccess = false;
222376af099aSliuyi 	int iRet;
222476af099aSliuyi 	UINT iTotalRead = 0,iRead = 0;
222576af099aSliuyi 	int nSectorSize = 512;
222676af099aSliuyi 	BYTE pBuf[nSectorSize * DEFAULT_RW_LBA];
222776af099aSliuyi 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
222876af099aSliuyi 	if (bRet) {
222976af099aSliuyi 		if(szFile) {
223076af099aSliuyi 			file = fopen(szFile, "wb+");
223176af099aSliuyi 			if( !file ) {
223276af099aSliuyi 				printf("Read LBA failed, err=%d, can't open file: %s\r\n", errno, szFile);
223376af099aSliuyi 				goto Exit_ReadLBA;
223476af099aSliuyi 			}
223576af099aSliuyi 		}
223676af099aSliuyi 
223776af099aSliuyi 		while(uiLen > 0) {
223876af099aSliuyi 			memset(pBuf, 0, nSectorSize * DEFAULT_RW_LBA);
223976af099aSliuyi 			iRead = (uiLen >= DEFAULT_RW_LBA) ? DEFAULT_RW_LBA : uiLen;
224076af099aSliuyi 			iRet = pComm->RKU_ReadLBA( uiBegin + iTotalRead, iRead, pBuf);
224176af099aSliuyi 			if(ERR_SUCCESS == iRet) {
224276af099aSliuyi 				uiLen -= iRead;
224376af099aSliuyi 				iTotalRead += iRead;
224476af099aSliuyi 
224576af099aSliuyi 				if(szFile) {
224676af099aSliuyi 					fwrite(pBuf, 1, iRead * nSectorSize, file);
224776af099aSliuyi 					if (bFirst){
224876af099aSliuyi 						if (iTotalRead >= 1024)
224932268622SAndreas Färber 							printf("Read LBA to file (%d%%)\r\n", (iTotalRead / 1024) * 100 / ((uiLen + iTotalRead) / 1024));
225076af099aSliuyi 						else
225132268622SAndreas Färber 							printf("Read LBA to file (%d%%)\r\n", iTotalRead * 100 / (uiLen + iTotalRead));
225276af099aSliuyi 						bFirst = false;
225376af099aSliuyi 					} else {
225476af099aSliuyi 						CURSOR_MOVEUP_LINE(1);
225576af099aSliuyi 						CURSOR_DEL_LINE;
225676af099aSliuyi 						if (iTotalRead >= 1024)
225732268622SAndreas Färber 							printf("Read LBA to file (%d%%)\r\n", (iTotalRead / 1024) * 100 / ((uiLen + iTotalRead) / 1024));
225876af099aSliuyi 						else
225932268622SAndreas Färber 							printf("Read LBA to file (%d%%)\r\n", iTotalRead * 100 / (uiLen + iTotalRead));
226076af099aSliuyi 					}
226176af099aSliuyi 				}
226276af099aSliuyi 				else
226376af099aSliuyi 					PrintData(pBuf, nSectorSize * iRead);
226476af099aSliuyi 			} else {
226576af099aSliuyi 				if (g_pLogObject)
226676af099aSliuyi 					g_pLogObject->Record("Error: RKU_ReadLBA failed, err=%d", iRet);
226776af099aSliuyi 
226876af099aSliuyi 				printf("Read LBA failed!\r\n");
226976af099aSliuyi 				goto Exit_ReadLBA;
227076af099aSliuyi 			}
227176af099aSliuyi 		}
227276af099aSliuyi 		bSuccess = true;
227376af099aSliuyi 	} else {
227432268622SAndreas Färber 		printf("Read LBA quit, creating comm object failed!\r\n");
227576af099aSliuyi 	}
227676af099aSliuyi Exit_ReadLBA:
227776af099aSliuyi 	if (pComm) {
227876af099aSliuyi 		delete pComm;
227976af099aSliuyi 		pComm = NULL;
228076af099aSliuyi 	}
228176af099aSliuyi 	if (file)
228276af099aSliuyi 		fclose(file);
228376af099aSliuyi 	return bSuccess;
228476af099aSliuyi }
22856ae612beSliuyi bool erase_partition(CRKUsbComm *pComm, UINT uiOffset, UINT uiSize)
22866ae612beSliuyi {
22876ae612beSliuyi 	UINT uiErase=2048*64;
22886ae612beSliuyi 	bool bSuccess = true;
22896ae612beSliuyi 	int iRet;
22906ae612beSliuyi 	while (uiSize)
22916ae612beSliuyi 	{
22926ae612beSliuyi 		if (uiSize>=uiErase)
22936ae612beSliuyi 		{
22946ae612beSliuyi 			iRet = pComm->RKU_EraseLBA(uiOffset,uiErase);
22956ae612beSliuyi 			uiSize -= uiErase;
22966ae612beSliuyi 			uiOffset += uiErase;
22976ae612beSliuyi 		}
22986ae612beSliuyi 		else
22996ae612beSliuyi 		{
23006ae612beSliuyi 			iRet = pComm->RKU_EraseLBA(uiOffset,uiSize);
23016ae612beSliuyi 			uiSize = 0;
23026ae612beSliuyi 			uiOffset += uiSize;
23036ae612beSliuyi 		}
23046ae612beSliuyi 		if (iRet!=ERR_SUCCESS)
23056ae612beSliuyi 		{
23066ae612beSliuyi 			if (g_pLogObject)
23076ae612beSliuyi 			{
23086ae612beSliuyi 				g_pLogObject->Record("ERROR:erase_partition failed,err=%d",iRet);
23096ae612beSliuyi 			}
23106ae612beSliuyi 			bSuccess = false;
23116ae612beSliuyi 			break;
23126ae612beSliuyi 		}
23136ae612beSliuyi 	}
23146ae612beSliuyi 	return bSuccess;
23156ae612beSliuyi 
23166ae612beSliuyi }
23176ae612beSliuyi bool EatSparseChunk(FILE *file, chunk_header &chunk)
23186ae612beSliuyi {
23196ae612beSliuyi 	UINT uiRead;
23206ae612beSliuyi 	uiRead = fread(&chunk, 1, sizeof(chunk_header), file);
23216ae612beSliuyi 	if (uiRead != sizeof(chunk_header)) {
23226ae612beSliuyi 		if (g_pLogObject)
23236ae612beSliuyi 		{
23246ae612beSliuyi 			g_pLogObject->Record("Error:EatSparseChunk failed,err=%d", errno);
23256ae612beSliuyi 		}
23266ae612beSliuyi 		return false;
23276ae612beSliuyi 	}
23286ae612beSliuyi 	return true;
23296ae612beSliuyi }
23306ae612beSliuyi bool EatSparseData(FILE *file, PBYTE pBuf, DWORD dwSize)
23316ae612beSliuyi {
23326ae612beSliuyi 	UINT uiRead;
23336ae612beSliuyi 	uiRead = fread(pBuf, 1, dwSize, file);
23346ae612beSliuyi 	if (uiRead!=dwSize)
23356ae612beSliuyi 	{
23366ae612beSliuyi 		if (g_pLogObject)
23376ae612beSliuyi 		{
23386ae612beSliuyi 			g_pLogObject->Record("Error:EatSparseData failed,err=%d",errno);
23396ae612beSliuyi 		}
23406ae612beSliuyi 		return false;
23416ae612beSliuyi 	}
23426ae612beSliuyi 	return true;
23436ae612beSliuyi }
23446ae612beSliuyi 
23456ae612beSliuyi bool write_sparse_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, UINT uiSize, char *szFile)
23466ae612beSliuyi {
23476ae612beSliuyi 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
23486ae612beSliuyi 		return false;
23496ae612beSliuyi 	CRKUsbComm *pComm = NULL;
23506ae612beSliuyi 	FILE *file = NULL;
23516ae612beSliuyi 	bool bRet, bSuccess = false, bFirst = true;
23526ae612beSliuyi 	int iRet;
23536ae612beSliuyi 	u64 iTotalWrite = 0, iFileSize = 0;
23546ae612beSliuyi 	UINT iRead = 0, uiTransferSec, curChunk, i;
23556ae612beSliuyi 	UINT dwChunkDataSize, dwMaxReadWriteBytes, dwTransferBytes, dwFillByte, dwCrc;
23566ae612beSliuyi 	BYTE pBuf[SECTOR_SIZE * DEFAULT_RW_LBA];
23576ae612beSliuyi 	sparse_header header;
23586ae612beSliuyi 	chunk_header  chunk;
23596ae612beSliuyi 	dwMaxReadWriteBytes = DEFAULT_RW_LBA * SECTOR_SIZE;
23606ae612beSliuyi 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
23616ae612beSliuyi 	if (bRet) {
23626ae612beSliuyi 		bRet = erase_partition(pComm, uiBegin, uiSize);
23636ae612beSliuyi 		if (!bRet) {
23646ae612beSliuyi 			printf("%s failed, erase partition error\r\n", __func__);
23656ae612beSliuyi 			goto Exit_WriteSparseLBA;
23666ae612beSliuyi 		}
23676ae612beSliuyi 		file = fopen(szFile, "rb");
23686ae612beSliuyi 		if( !file ) {
23696ae612beSliuyi 			printf("%s failed, err=%d, can't open file: %s\r\n", __func__, errno, szFile);
23706ae612beSliuyi 			goto Exit_WriteSparseLBA;
23716ae612beSliuyi 		}
23726ae612beSliuyi 		fseeko(file, 0, SEEK_SET);
23736ae612beSliuyi 		iRead = fread(&header, 1, sizeof(header), file);
23746ae612beSliuyi 		if (iRead != sizeof(sparse_header))
23756ae612beSliuyi 		{
23766ae612beSliuyi 			if (g_pLogObject)
23776ae612beSliuyi 			{
23786ae612beSliuyi 				g_pLogObject->Record("ERROR:%s-->read sparse header failed,file=%s,err=%d", __func__, szFile, errno);
23796ae612beSliuyi 			}
23806ae612beSliuyi 			goto Exit_WriteSparseLBA;
23816ae612beSliuyi 		}
23826ae612beSliuyi 		iFileSize = header.blk_sz * (u64)header.total_blks;
23836ae612beSliuyi 		iTotalWrite = 0;
23846ae612beSliuyi 		curChunk = 0;
23856ae612beSliuyi 
23866ae612beSliuyi 		while(curChunk < header.total_chunks)
23876ae612beSliuyi 		{
23886ae612beSliuyi 			if (!EatSparseChunk(file, chunk)) {
23896ae612beSliuyi 				goto Exit_WriteSparseLBA;
23906ae612beSliuyi 			}
23916ae612beSliuyi 			curChunk++;
23926ae612beSliuyi 			switch (chunk.chunk_type) {
23936ae612beSliuyi 			case CHUNK_TYPE_RAW:
23946ae612beSliuyi 				dwChunkDataSize = chunk.total_sz - sizeof(chunk_header);
23956ae612beSliuyi 				while (dwChunkDataSize) {
23966ae612beSliuyi 					memset(pBuf, 0, dwMaxReadWriteBytes);
23976ae612beSliuyi 					if (dwChunkDataSize >= dwMaxReadWriteBytes) {
23986ae612beSliuyi 						dwTransferBytes = dwMaxReadWriteBytes;
23996ae612beSliuyi 						uiTransferSec = DEFAULT_RW_LBA;
24006ae612beSliuyi 					} else {
24016ae612beSliuyi 						dwTransferBytes = dwChunkDataSize;
24026ae612beSliuyi 						uiTransferSec = ((dwTransferBytes % SECTOR_SIZE == 0) ? (dwTransferBytes / SECTOR_SIZE) : (dwTransferBytes / SECTOR_SIZE + 1));
24036ae612beSliuyi 					}
24046ae612beSliuyi 					if (!EatSparseData(file, pBuf, dwTransferBytes)) {
24056ae612beSliuyi 						goto Exit_WriteSparseLBA;
24066ae612beSliuyi 					}
24076ae612beSliuyi 					iRet = pComm->RKU_WriteLBA(uiBegin, uiTransferSec, pBuf);
24086ae612beSliuyi 					if( ERR_SUCCESS == iRet ) {
24096ae612beSliuyi 						dwChunkDataSize -= dwTransferBytes;
24106ae612beSliuyi 						iTotalWrite += dwTransferBytes;
24116ae612beSliuyi 						uiBegin += uiTransferSec;
24126ae612beSliuyi 					} else {
24136ae612beSliuyi 						if (g_pLogObject) {
24146ae612beSliuyi 							g_pLogObject->Record("ERROR:%s-->RKU_WriteLBA failed,Written(%d),RetCode(%d)",  __func__, iTotalWrite, iRet);
24156ae612beSliuyi 						}
24166ae612beSliuyi 						goto Exit_WriteSparseLBA;
24176ae612beSliuyi 					}
24186ae612beSliuyi 					if (bFirst) {
24196ae612beSliuyi 						if (iTotalWrite >= 1024)
24206ae612beSliuyi 							printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
24216ae612beSliuyi 						else
24226ae612beSliuyi 							printf("Write LBA from file (%lld%%)\r\n", iTotalWrite * 100 / iFileSize);
24236ae612beSliuyi 						bFirst = false;
24246ae612beSliuyi 					} else {
24256ae612beSliuyi 						CURSOR_MOVEUP_LINE(1);
24266ae612beSliuyi 						CURSOR_DEL_LINE;
24276ae612beSliuyi 						printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
24286ae612beSliuyi 					}
24296ae612beSliuyi 				}
24306ae612beSliuyi 				break;
24316ae612beSliuyi 			case CHUNK_TYPE_FILL:
24326ae612beSliuyi 				dwChunkDataSize = chunk.chunk_sz * header.blk_sz;
24336ae612beSliuyi 				if (!EatSparseData(file, (PBYTE)&dwFillByte, 4)) {
24346ae612beSliuyi 					goto Exit_WriteSparseLBA;
24356ae612beSliuyi 				}
24366ae612beSliuyi 				while (dwChunkDataSize) {
24376ae612beSliuyi 					memset(pBuf, 0, dwMaxReadWriteBytes);
24386ae612beSliuyi 					if (dwChunkDataSize >= dwMaxReadWriteBytes) {
24396ae612beSliuyi 						dwTransferBytes = dwMaxReadWriteBytes;
24406ae612beSliuyi 						uiTransferSec = DEFAULT_RW_LBA;
24416ae612beSliuyi 					} else {
24426ae612beSliuyi 						dwTransferBytes = dwChunkDataSize;
24436ae612beSliuyi 						uiTransferSec = ((dwTransferBytes % SECTOR_SIZE == 0) ? (dwTransferBytes / SECTOR_SIZE) : (dwTransferBytes / SECTOR_SIZE + 1));
24446ae612beSliuyi 					}
24456ae612beSliuyi 					for (i = 0; i < dwTransferBytes / 4; i++) {
24466ae612beSliuyi 						*(DWORD *)(pBuf + i * 4) = dwFillByte;
24476ae612beSliuyi 					}
24486ae612beSliuyi 					iRet = pComm->RKU_WriteLBA(uiBegin, uiTransferSec, pBuf);
24496ae612beSliuyi 					if( ERR_SUCCESS == iRet ) {
24506ae612beSliuyi 						dwChunkDataSize -= dwTransferBytes;
24516ae612beSliuyi 						iTotalWrite += dwTransferBytes;
24526ae612beSliuyi 						uiBegin += uiTransferSec;
24536ae612beSliuyi 					} else {
24546ae612beSliuyi 						if (g_pLogObject) {
24556ae612beSliuyi 							g_pLogObject->Record("ERROR:%s-->RKU_WriteLBA failed,Written(%d),RetCode(%d)" ,__func__, iTotalWrite, iRet);
24566ae612beSliuyi 						}
24576ae612beSliuyi 						goto Exit_WriteSparseLBA;
24586ae612beSliuyi 					}
24596ae612beSliuyi 					if (bFirst) {
24606ae612beSliuyi 						if (iTotalWrite >= 1024)
24616ae612beSliuyi 							printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
24626ae612beSliuyi 						else
24636ae612beSliuyi 							printf("Write LBA from file (%lld%%)\r\n", iTotalWrite * 100 / iFileSize);
24646ae612beSliuyi 						bFirst = false;
24656ae612beSliuyi 					} else {
24666ae612beSliuyi 						CURSOR_MOVEUP_LINE(1);
24676ae612beSliuyi 						CURSOR_DEL_LINE;
24686ae612beSliuyi 						printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
24696ae612beSliuyi 					}
24706ae612beSliuyi 				}
24716ae612beSliuyi 				break;
24726ae612beSliuyi 			case CHUNK_TYPE_DONT_CARE:
24736ae612beSliuyi 				dwChunkDataSize = chunk.chunk_sz * header.blk_sz;
24746ae612beSliuyi 				iTotalWrite += dwChunkDataSize;
24756ae612beSliuyi 				uiTransferSec = ((dwChunkDataSize % SECTOR_SIZE == 0) ? (dwChunkDataSize / SECTOR_SIZE) : (dwChunkDataSize / SECTOR_SIZE + 1));
24766ae612beSliuyi 				uiBegin += uiTransferSec;
24776ae612beSliuyi 				if (bFirst) {
24786ae612beSliuyi 					if (iTotalWrite >= 1024)
24796ae612beSliuyi 						printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
24806ae612beSliuyi 					else
24816ae612beSliuyi 						printf("Write LBA from file (%lld%%)\r\n", iTotalWrite * 100 / iFileSize);
24826ae612beSliuyi 					bFirst = false;
24836ae612beSliuyi 				} else {
24846ae612beSliuyi 					CURSOR_MOVEUP_LINE(1);
24856ae612beSliuyi 					CURSOR_DEL_LINE;
24866ae612beSliuyi 					printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
24876ae612beSliuyi 				}
24886ae612beSliuyi 				break;
24896ae612beSliuyi 			case CHUNK_TYPE_CRC32:
24906ae612beSliuyi 				EatSparseData(file,(PBYTE)&dwCrc,4);
24916ae612beSliuyi 				break;
24926ae612beSliuyi 			}
24936ae612beSliuyi 		}
24946ae612beSliuyi 		bSuccess = true;
24956ae612beSliuyi 	} else {
24966ae612beSliuyi 		printf("Write LBA quit, creating comm object failed!\r\n");
24976ae612beSliuyi 	}
24986ae612beSliuyi Exit_WriteSparseLBA:
24996ae612beSliuyi 	if (pComm) {
25006ae612beSliuyi 		delete pComm;
25016ae612beSliuyi 		pComm = NULL;
25026ae612beSliuyi 	}
25036ae612beSliuyi 	if (file)
25046ae612beSliuyi 		fclose(file);
25056ae612beSliuyi 	return bSuccess;
25066ae612beSliuyi 
25076ae612beSliuyi }
25086ae612beSliuyi 
250976af099aSliuyi bool write_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, char *szFile)
251076af099aSliuyi {
251176af099aSliuyi 	if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
251276af099aSliuyi 		return false;
251376af099aSliuyi 	CRKUsbComm *pComm = NULL;
251476af099aSliuyi 	FILE *file = NULL;
251576af099aSliuyi 	bool bRet, bFirst = true, bSuccess = false;
251676af099aSliuyi 	int iRet;
251776af099aSliuyi 	long long iTotalWrite = 0, iFileSize = 0;
251876af099aSliuyi 	UINT iWrite = 0, iRead = 0;
251976af099aSliuyi 	UINT uiLen;
252076af099aSliuyi 	int nSectorSize = 512;
252176af099aSliuyi 	BYTE pBuf[nSectorSize * DEFAULT_RW_LBA];
252276af099aSliuyi 
252376af099aSliuyi 	pComm =  new CRKUsbComm(dev, g_pLogObject, bRet);
252476af099aSliuyi 	if (bRet) {
252576af099aSliuyi 		file = fopen(szFile, "rb");
252676af099aSliuyi 		if( !file ) {
252776af099aSliuyi 			printf("Write LBA failed, err=%d, can't open file: %s\r\n", errno, szFile);
252876af099aSliuyi 			goto Exit_WriteLBA;
252976af099aSliuyi 		}
253076af099aSliuyi 
253176af099aSliuyi 		iRet = fseeko(file, 0, SEEK_END);
253276af099aSliuyi 		iFileSize = ftello(file);
253376af099aSliuyi 		fseeko(file, 0, SEEK_SET);
253476af099aSliuyi 		while(iTotalWrite < iFileSize) {
253576af099aSliuyi 			memset(pBuf, 0, nSectorSize * DEFAULT_RW_LBA);
253676af099aSliuyi 			iWrite = iRead= fread(pBuf, 1, nSectorSize * DEFAULT_RW_LBA, file);
253776af099aSliuyi 			uiLen = ((iWrite % 512) == 0) ? (iWrite / 512) : (iWrite / 512 + 1);
253876af099aSliuyi 			iRet = pComm->RKU_WriteLBA( uiBegin, uiLen, pBuf);
253976af099aSliuyi 			if(ERR_SUCCESS == iRet) {
254076af099aSliuyi 				uiBegin += uiLen;
254176af099aSliuyi 				iTotalWrite += iWrite;
254276af099aSliuyi 				if (bFirst) {
254376af099aSliuyi 					if (iTotalWrite >= 1024)
254476af099aSliuyi 						printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
254576af099aSliuyi 					else
254632268622SAndreas Färber 						printf("Write LBA from file (%lld%%)\r\n", iTotalWrite * 100 / iFileSize);
254776af099aSliuyi 					bFirst = false;
254876af099aSliuyi 				} else {
254976af099aSliuyi 					CURSOR_MOVEUP_LINE(1);
255076af099aSliuyi 					CURSOR_DEL_LINE;
255176af099aSliuyi 					printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
255276af099aSliuyi 				}
255376af099aSliuyi 			} else {
255476af099aSliuyi 				if (g_pLogObject)
255576af099aSliuyi 					g_pLogObject->Record("Error: RKU_WriteLBA failed, err=%d", iRet);
255676af099aSliuyi 
255776af099aSliuyi 				printf("Write LBA failed!\r\n");
255876af099aSliuyi 				goto Exit_WriteLBA;
255976af099aSliuyi 			}
256076af099aSliuyi 		}
256176af099aSliuyi 		bSuccess = true;
256276af099aSliuyi 	} else {
256332268622SAndreas Färber 		printf("Write LBA quit, creating comm object failed!\r\n");
256476af099aSliuyi 	}
256576af099aSliuyi Exit_WriteLBA:
256676af099aSliuyi 	if (pComm) {
256776af099aSliuyi 		delete pComm;
256876af099aSliuyi 		pComm = NULL;
256976af099aSliuyi 	}
257076af099aSliuyi 	if (file)
257176af099aSliuyi 		fclose(file);
257276af099aSliuyi 	return bSuccess;
257376af099aSliuyi }
257476af099aSliuyi 
257576af099aSliuyi void split_item(STRING_VECTOR &vecItems, char *pszItems)
257676af099aSliuyi {
257776af099aSliuyi 	string strItem;
257876af099aSliuyi 	char szItem[100];
257976af099aSliuyi 	char *pos = NULL, *pStart;
258076af099aSliuyi 	pStart = pszItems;
258176af099aSliuyi 	pos = strchr(pStart, ',');
258276af099aSliuyi 	while(pos != NULL) {
258376af099aSliuyi 		memset(szItem, 0, 100);
258476af099aSliuyi 		strncpy(szItem, pStart, pos - pStart);
258576af099aSliuyi 		strItem = szItem;
258676af099aSliuyi 		vecItems.push_back(strItem);
258776af099aSliuyi 		pStart = pos + 1;
258876af099aSliuyi 		if (*pStart == 0)
258976af099aSliuyi 			break;
259076af099aSliuyi 		pos = strchr(pStart, ',');
259176af099aSliuyi 	}
259276af099aSliuyi 	if (strlen(pStart) > 0) {
259376af099aSliuyi 		memset(szItem, 0, 100);
259476af099aSliuyi 		strncpy(szItem, pStart, strlen(pStart));
259576af099aSliuyi 		strItem = szItem;
259676af099aSliuyi 		vecItems.push_back(strItem);
259776af099aSliuyi 	}
259876af099aSliuyi }
2599c30d921cSKever Yang 
2600d71e8c20SEddie Cai void tag_spl(char *tag, char *spl)
2601d71e8c20SEddie Cai {
2602d71e8c20SEddie Cai 	FILE *file = NULL;
2603d71e8c20SEddie Cai 	int len;
2604d71e8c20SEddie Cai 
2605d71e8c20SEddie Cai 	if(!tag || !spl)
2606d71e8c20SEddie Cai 		return;
2607d71e8c20SEddie Cai 	len = strlen(tag);
2608d71e8c20SEddie Cai 	printf("tag len=%d\n",len);
2609d71e8c20SEddie Cai 	file = fopen(spl, "rb");
2610d71e8c20SEddie Cai 	if( !file ){
2611d71e8c20SEddie Cai 		return;
2612d71e8c20SEddie Cai 	}
2613d71e8c20SEddie Cai 	int iFileSize;
2614d71e8c20SEddie Cai 	fseek(file, 0, SEEK_END);
2615d71e8c20SEddie Cai 	iFileSize = ftell(file);
2616d71e8c20SEddie Cai 	fseek(file, 0, SEEK_SET);
2617d71e8c20SEddie Cai 	char *Buf = NULL;
2618d71e8c20SEddie Cai 	Buf = new char[iFileSize + len + 1];
2619d71e8c20SEddie Cai 	if (!Buf){
2620d71e8c20SEddie Cai 		fclose(file);
2621d71e8c20SEddie Cai 		return;
2622d71e8c20SEddie Cai 	}
2623d71e8c20SEddie Cai 	memset(Buf, 0, iFileSize + 1);
2624d71e8c20SEddie Cai 	memcpy(Buf, tag, len);
2625d71e8c20SEddie Cai 	int iRead;
2626d71e8c20SEddie Cai 	iRead = fread(Buf+len, 1, iFileSize, file);
2627d71e8c20SEddie Cai 	if (iRead != iFileSize){
2628d71e8c20SEddie Cai 		fclose(file);
2629d71e8c20SEddie Cai 		delete []Buf;
2630d71e8c20SEddie Cai 		return;
2631d71e8c20SEddie Cai 	}
2632d71e8c20SEddie Cai 	fclose(file);
2633d71e8c20SEddie Cai 
2634d71e8c20SEddie Cai 	len = strlen(spl);
263532268622SAndreas Färber 	char *taggedspl = new char[len + 5];
263632268622SAndreas Färber 	strcpy(taggedspl, spl);
263732268622SAndreas Färber 	strcpy(taggedspl + len, ".tag");
263832268622SAndreas Färber 	taggedspl[len+4] = 0;
263932268622SAndreas Färber 	printf("Writing tagged spl to %s\n", taggedspl);
2640d71e8c20SEddie Cai 
264132268622SAndreas Färber 	file = fopen(taggedspl, "wb");
2642d71e8c20SEddie Cai 	if( !file ){
264332268622SAndreas Färber 		delete []taggedspl;
2644d71e8c20SEddie Cai 		delete []Buf;
2645d71e8c20SEddie Cai 		return;
2646d71e8c20SEddie Cai 	}
2647d71e8c20SEddie Cai 	fwrite(Buf, 1, iFileSize+len, file);
2648d71e8c20SEddie Cai 	fclose(file);
264932268622SAndreas Färber 	delete []taggedspl;
2650d71e8c20SEddie Cai 	delete []Buf;
2651d71e8c20SEddie Cai 	printf("done\n");
2652d71e8c20SEddie Cai 	return;
2653d71e8c20SEddie Cai }
2654d71e8c20SEddie Cai 
265576af099aSliuyi bool handle_command(int argc, char* argv[], CRKScan *pScan)
265676af099aSliuyi {
265776af099aSliuyi 	string strCmd;
265876af099aSliuyi 	strCmd = argv[1];
265976af099aSliuyi 	ssize_t cnt;
266076af099aSliuyi 	bool bRet,bSuccess = false;
26618df2d64aSEddie Cai 	char *s;
26628df2d64aSEddie Cai 	int i, ret;
266376af099aSliuyi 	STRUCT_RKDEVICE_DESC dev;
26646ae612beSliuyi 	u8 master_gpt[34 * SECTOR_SIZE];
26656ae612beSliuyi 	u64 lba, lba_end;
266676af099aSliuyi 
266776af099aSliuyi 	transform(strCmd.begin(), strCmd.end(), strCmd.begin(), (int(*)(int))toupper);
26688df2d64aSEddie Cai 	s = (char*)strCmd.c_str();
26698df2d64aSEddie Cai 	for(i = 0; i < (int)strlen(s); i++)
26708df2d64aSEddie Cai 	        s[i] = toupper(s[i]);
267178884ef4SEddie Cai 
26728df2d64aSEddie Cai 	if((strcmp(strCmd.c_str(), "-H") == 0) || (strcmp(strCmd.c_str(), "--HELP")) == 0){
267376af099aSliuyi 		usage();
267476af099aSliuyi 		return true;
26758df2d64aSEddie Cai 	} else if((strcmp(strCmd.c_str(), "-V") == 0) || (strcmp(strCmd.c_str(), "--VERSION") == 0)) {
2676c30d921cSKever Yang 		printf("rkdeveloptool ver %s\r\n", PACKAGE_VERSION);
267776af099aSliuyi 		return true;
267878884ef4SEddie Cai 	} else if (strcmp(strCmd.c_str(), "PACK") == 0) {//pack boot loader
267978884ef4SEddie Cai 		mergeBoot();
268078884ef4SEddie Cai 
268178884ef4SEddie Cai 		return true;
268278884ef4SEddie Cai 	} else if (strcmp(strCmd.c_str(), "UNPACK") == 0) {//unpack boot loader
268378884ef4SEddie Cai 		string strLoader = argv[2];
268478884ef4SEddie Cai 
268578884ef4SEddie Cai 		unpackBoot((char*)strLoader.c_str());
268678884ef4SEddie Cai 		return true;
2687d71e8c20SEddie Cai 	} else if (strcmp(strCmd.c_str(), "TAGSPL") == 0) {//tag u-boot spl
2688d71e8c20SEddie Cai 		if (argc == 4) {
2689d71e8c20SEddie Cai 			string tag = argv[2];
2690d71e8c20SEddie Cai 			string spl = argv[3];
2691d71e8c20SEddie Cai 			printf("tag %s to %s\n", tag.c_str(), spl.c_str());
2692d71e8c20SEddie Cai 			tag_spl((char*)tag.c_str(), (char*)spl.c_str());
2693d71e8c20SEddie Cai 			return true;
2694d71e8c20SEddie Cai 		}
2695d71e8c20SEddie Cai 		printf("tagspl: parameter error\n");
2696d71e8c20SEddie Cai 		usage();
269776af099aSliuyi 	}
269876af099aSliuyi 	cnt = pScan->Search(RKUSB_MASKROM | RKUSB_LOADER);
269976af099aSliuyi 	if (cnt < 1) {
270076af099aSliuyi 		ERROR_COLOR_ATTR;
270132268622SAndreas Färber 		printf("Did not find any rockusb device, please plug device in!");
270276af099aSliuyi 		NORMAL_COLOR_ATTR;
270376af099aSliuyi 		printf("\r\n");
270476af099aSliuyi 		return bSuccess;
270576af099aSliuyi 	} else if (cnt > 1) {
270676af099aSliuyi 		ERROR_COLOR_ATTR;
270732268622SAndreas Färber 		printf("Found too many rockusb devices, please plug devices out!");
270876af099aSliuyi 		NORMAL_COLOR_ATTR;
270976af099aSliuyi 		printf("\r\n");
271076af099aSliuyi 		return bSuccess;
271176af099aSliuyi 	}
271276af099aSliuyi 
271376af099aSliuyi 	bRet = pScan->GetDevice(dev, 0);
271476af099aSliuyi 	if (!bRet) {
271576af099aSliuyi 		ERROR_COLOR_ATTR;
271632268622SAndreas Färber 		printf("Getting information about rockusb device failed!");
271776af099aSliuyi 		NORMAL_COLOR_ATTR;
271876af099aSliuyi 		printf("\r\n");
271976af099aSliuyi 		return bSuccess;
272076af099aSliuyi 	}
272176af099aSliuyi 
272276af099aSliuyi 	if(strcmp(strCmd.c_str(), "RD") == 0) {
272376af099aSliuyi 		if ((argc != 2) && (argc != 3))
272476af099aSliuyi 			printf("Parameter of [RD] command is invalid, please check help!\r\n");
272576af099aSliuyi 		else {
272676af099aSliuyi 			if (argc == 2)
272776af099aSliuyi 				bSuccess = reset_device(dev);
272876af099aSliuyi 			else {
272976af099aSliuyi 				UINT uiSubCode;
273076af099aSliuyi 				char *pszEnd;
273176af099aSliuyi 				uiSubCode = strtoul(argv[2], &pszEnd, 0);
273276af099aSliuyi 				if (*pszEnd)
273376af099aSliuyi 					printf("Subcode is invalid, please check!\r\n");
273476af099aSliuyi 				else {
273576af099aSliuyi 					if (uiSubCode <= 5)
273676af099aSliuyi 						bSuccess = reset_device(dev, uiSubCode);
273776af099aSliuyi 					else
273876af099aSliuyi 						printf("Subcode is invalid, please check!\r\n");
273976af099aSliuyi 				}
274076af099aSliuyi 			}
274176af099aSliuyi 		}
274276af099aSliuyi 	} else if(strcmp(strCmd.c_str(), "TD") == 0) {
274376af099aSliuyi 		bSuccess = test_device(dev);
274476af099aSliuyi 	} else if (strcmp(strCmd.c_str(), "RID") == 0) {//Read Flash ID
274576af099aSliuyi 		bSuccess = read_flash_id(dev);
274676af099aSliuyi 	} else if (strcmp(strCmd.c_str(), "RFI") == 0){//Read Flash Info
274776af099aSliuyi 		bSuccess = read_flash_info(dev);
274876af099aSliuyi 	} else if (strcmp(strCmd.c_str(), "RCI") == 0) {//Read Chip Info
274976af099aSliuyi 		bSuccess = read_chip_info(dev);
275076af099aSliuyi 	} else if(strcmp(strCmd.c_str(), "DB") == 0) {
275176af099aSliuyi 		if (argc > 2) {
275276af099aSliuyi 			string strLoader;
275376af099aSliuyi 			strLoader = argv[2];
275476af099aSliuyi 			bSuccess = download_boot(dev, (char *)strLoader.c_str());
275576af099aSliuyi 		} else if (argc == 2) {
2756c29e5f0fSliuyi 			ret = find_config_item(g_ConfigItemVec, "loader");
275776af099aSliuyi 			if (ret == -1)
275832268622SAndreas Färber 				printf("Did not find loader item in config!\r\n");
275976af099aSliuyi 			else
276076af099aSliuyi 				bSuccess = download_boot(dev, g_ConfigItemVec[ret].szItemValue);
276176af099aSliuyi 		} else
276276af099aSliuyi 			printf("Parameter of [DB] command is invalid, please check help!\r\n");
2763c30d921cSKever Yang 	} else if(strcmp(strCmd.c_str(), "GPT") == 0) {
2764c30d921cSKever Yang 		if (argc > 2) {
2765c30d921cSKever Yang 			string strParameter;
2766c30d921cSKever Yang 			strParameter = argv[2];
2767c30d921cSKever Yang 			bSuccess = write_gpt(dev, (char *)strParameter.c_str());
2768c30d921cSKever Yang 		} else
2769c30d921cSKever Yang 			printf("Parameter of [GPT] command is invalid, please check help!\r\n");
2770c30d921cSKever Yang 	} else if(strcmp(strCmd.c_str(), "UL") == 0) {
2771c30d921cSKever Yang 		if (argc > 2) {
2772c30d921cSKever Yang 			string strLoader;
2773c30d921cSKever Yang 			strLoader = argv[2];
2774c30d921cSKever Yang 			bSuccess = upgrade_loader(dev, (char *)strLoader.c_str());
2775c30d921cSKever Yang 		} else
2776c30d921cSKever Yang 			printf("Parameter of [UL] command is invalid, please check help!\r\n");
277776af099aSliuyi 	} else if(strcmp(strCmd.c_str(), "EF") == 0) {
277876af099aSliuyi 		if (argc == 2) {
277976af099aSliuyi 			bSuccess = erase_flash(dev);
278076af099aSliuyi 		} else
278176af099aSliuyi 			printf("Parameter of [EF] command is invalid, please check help!\r\n");
278276af099aSliuyi 	} else if(strcmp(strCmd.c_str(), "WL") == 0) {
278376af099aSliuyi 		if (argc == 4) {
278476af099aSliuyi 			UINT uiBegin;
278576af099aSliuyi 			char *pszEnd;
278676af099aSliuyi 			uiBegin = strtoul(argv[2], &pszEnd, 0);
278776af099aSliuyi 			if (*pszEnd)
278876af099aSliuyi 				printf("Begin is invalid, please check!\r\n");
278976af099aSliuyi 			else
279076af099aSliuyi 				bSuccess = write_lba(dev, uiBegin, argv[3]);
279176af099aSliuyi 		} else
279276af099aSliuyi 			printf("Parameter of [WL] command is invalid, please check help!\r\n");
27936ae612beSliuyi 	} else if(strcmp(strCmd.c_str(), "WLX") == 0) {
27946ae612beSliuyi 		if (argc == 4) {
27956ae612beSliuyi 			bRet = read_gpt(dev, master_gpt);
27966ae612beSliuyi 			if (bRet) {
27976ae612beSliuyi 				bRet = get_lba_from_gpt(master_gpt, argv[2], &lba, &lba_end);
27986ae612beSliuyi 				if (bRet) {
27996ae612beSliuyi 					if (is_sparse_image(argv[3]))
28006ae612beSliuyi 						bSuccess = write_sparse_lba(dev, (u32)lba, (u32)(lba_end - lba + 1), argv[3]);
28016ae612beSliuyi 					else
28026ae612beSliuyi 						bSuccess = write_lba(dev, (u32)lba, argv[3]);
28036ae612beSliuyi 				} else
28046ae612beSliuyi 					printf("No found %s partition\r\n", argv[2]);
28056ae612beSliuyi 			}
28066ae612beSliuyi 		} else
28076ae612beSliuyi 			printf("Parameter of [WLX] command is invalid, please check help!\r\n");
280876af099aSliuyi 	} else if (strcmp(strCmd.c_str(), "RL") == 0) {//Read LBA
280976af099aSliuyi 		char *pszEnd;
281076af099aSliuyi 		UINT uiBegin, uiLen;
281176af099aSliuyi 		if (argc != 5)
281276af099aSliuyi 			printf("Parameter of [RL] command is invalid, please check help!\r\n");
281376af099aSliuyi 		else {
281476af099aSliuyi 			uiBegin = strtoul(argv[2], &pszEnd, 0);
281576af099aSliuyi 			if (*pszEnd)
281676af099aSliuyi 				printf("Begin is invalid, please check!\r\n");
281776af099aSliuyi 			else {
281876af099aSliuyi 				uiLen = strtoul(argv[3], &pszEnd, 0);
281976af099aSliuyi 				if (*pszEnd)
282076af099aSliuyi 					printf("Len is invalid, please check!\r\n");
282176af099aSliuyi 				else {
282276af099aSliuyi 					bSuccess = read_lba(dev, uiBegin, uiLen, argv[4]);
282376af099aSliuyi 				}
282476af099aSliuyi 			}
282576af099aSliuyi 		}
28263dc7e3ceSliuyi 	} else if(strcmp(strCmd.c_str(), "PGPT") == 0) {
28273dc7e3ceSliuyi 		if (argc == 2) {
28283dc7e3ceSliuyi 			bSuccess = print_gpt(dev);
28293dc7e3ceSliuyi 		} else
28303dc7e3ceSliuyi 			printf("Parameter of [PGPT] command is invalid, please check help!\r\n");
283176af099aSliuyi 	} else {
28329bc231bdSAndreas Färber 		printf("command is invalid!\r\n");
28339bc231bdSAndreas Färber 		usage();
283476af099aSliuyi 	}
283576af099aSliuyi 	return bSuccess;
283676af099aSliuyi }
283776af099aSliuyi 
283876af099aSliuyi 
283976af099aSliuyi int main(int argc, char* argv[])
284076af099aSliuyi {
284176af099aSliuyi 	CRKScan *pScan = NULL;
284276af099aSliuyi 	int ret;
284376af099aSliuyi 	char szProgramProcPath[100];
284476af099aSliuyi 	char szProgramDir[256];
284576af099aSliuyi 	string strLogDir,strConfigFile;
284676af099aSliuyi 	struct stat statBuf;
284776af099aSliuyi 
284876af099aSliuyi 	g_ConfigItemVec.clear();
284976af099aSliuyi 	sprintf(szProgramProcPath, "/proc/%d/exe", getpid());
285076af099aSliuyi 	if (readlink(szProgramProcPath, szProgramDir, 256) == -1)
285176af099aSliuyi 		strcpy(szProgramDir, ".");
285276af099aSliuyi 	else {
285376af099aSliuyi 		char *pSlash;
285476af099aSliuyi 		pSlash = strrchr(szProgramDir, '/');
285576af099aSliuyi 		if (pSlash)
285676af099aSliuyi 			*pSlash = '\0';
285776af099aSliuyi 	}
285876af099aSliuyi 	strLogDir = szProgramDir;
285976af099aSliuyi 	strLogDir +=  "/log/";
286076af099aSliuyi 	strConfigFile = szProgramDir;
286176af099aSliuyi 	strConfigFile += "/config.ini";
286276af099aSliuyi 	if (opendir(strLogDir.c_str()) == NULL)
286376af099aSliuyi 		mkdir(strLogDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH);
2864e5ee8cc0Sliuyi 	g_pLogObject = new CRKLog(strLogDir.c_str(), "log",true);
286576af099aSliuyi 
286676af099aSliuyi 	if(stat(strConfigFile.c_str(), &statBuf) < 0) {
286776af099aSliuyi 		if (g_pLogObject) {
286876af099aSliuyi 			g_pLogObject->Record("Error: failed to stat config.ini, err=%d", errno);
286976af099aSliuyi 		}
287076af099aSliuyi 	} else if (S_ISREG(statBuf.st_mode)) {
287176af099aSliuyi 		parse_config_file(strConfigFile.c_str(), g_ConfigItemVec);
287276af099aSliuyi 	}
287376af099aSliuyi 
287476af099aSliuyi 	ret = libusb_init(NULL);
287576af099aSliuyi 	if (ret < 0) {
287676af099aSliuyi 		if (g_pLogObject) {
287776af099aSliuyi 			g_pLogObject->Record("Error: libusb_init failed, err=%d", ret);
287876af099aSliuyi 			delete g_pLogObject;
287976af099aSliuyi 		}
288076af099aSliuyi 		return -1;
288176af099aSliuyi 	}
288276af099aSliuyi 
288376af099aSliuyi 	pScan = new CRKScan();
288476af099aSliuyi 	if (!pScan) {
288576af099aSliuyi 		if (g_pLogObject) {
288632268622SAndreas Färber 			g_pLogObject->Record("Error: failed to create object for searching device");
288776af099aSliuyi 			delete g_pLogObject;
288876af099aSliuyi 		}
288976af099aSliuyi 		libusb_exit(NULL);
289076af099aSliuyi 		return -2;
289176af099aSliuyi 	}
289276af099aSliuyi 	pScan->SetVidPid();
289376af099aSliuyi 
289476af099aSliuyi 	if (argc == 1)
289576af099aSliuyi 		usage();
289676af099aSliuyi 	else if (!handle_command(argc, argv, pScan))
289776af099aSliuyi 			return -0xFF;
289876af099aSliuyi 	if (pScan)
289976af099aSliuyi 		delete pScan;
290076af099aSliuyi 	if (g_pLogObject)
290176af099aSliuyi 		delete g_pLogObject;
290276af099aSliuyi 	libusb_exit(NULL);
290376af099aSliuyi 	return 0;
290476af099aSliuyi }
2905