android13/bootable/recovery/rkupdate/Upgrade.cpp

1530 lines
35 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright 2019 Rockchip Electronics Co., Ltd
* Dayao Ji <jdy@rock-chips.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
//#include "RKImage.h"
//#include "RKLog.h"
//#include "RKComm.h"
#include "rkupdate/RKAndroidDevice.h"
//#include "rkrsa_api.h"
//#include "uuid/uuid.h"
#include "rkupdate/RKSparse.h"
UpgradeCallbackFunc g_callback=NULL;
UpgradeProgressCallbackFunc g_progress_callback=NULL;
bool CreateUid(PBYTE pUid)
{
if (!pUid)
{
return false;
}
memset(pUid,0,RKDEVICE_UID_LEN);
PBYTE pManufactory,pTime,pGuid,pCrc;
pManufactory = pUid;
pTime = pManufactory + 8;
pGuid = pTime + 4;
pCrc = pGuid + 16;
memcpy(pManufactory,"ROCKCHIP",8);
time_t now;
now = time(NULL);
memcpy(pTime,(BYTE *)&now,4);
#if 0
uuid_t guidValue;
uuid_generate(guidValue);
#else
unsigned char raw[16]={0};
gen_rand_uuid(raw);
#endif
#if 0
memcpy(pGuid,(BYTE *)guidValue,16);
#else
memcpy(pGuid,(BYTE *)raw,16);
#endif
USHORT usCrc=0;
usCrc = CRC_CCITT(pManufactory,28);
memcpy(pCrc,(BYTE *)&usCrc,2);
return true;
}
bool ParsePartitionInfo(string &strPartInfo,string &strName,UINT &uiOffset,UINT &uiLen)
{
string::size_type pos,prevPos;
string strOffset,strLen;
int iCount;
prevPos = pos = 0;
if (strPartInfo.size()<=0)
{
return false;
}
pos = strPartInfo.find('@');
if (pos==string::npos)
{
return false;
}
strLen = strPartInfo.substr(prevPos,pos-prevPos);
strLen.erase(0,strLen.find_first_not_of(_T(" ")));
strLen.erase(strLen.find_last_not_of(_T(" "))+1);
if (strchr(strLen.c_str(),'-'))
{
uiLen = 0xFFFFFFFF;
}
else
{
iCount = sscanf(strLen.c_str(),"0x%x",&uiLen);
if (iCount!=1)
{
return false;
}
}
prevPos = pos +1;
pos = strPartInfo.find('(',prevPos);
if (pos==string::npos)
{
return false;
}
strOffset = strPartInfo.substr(prevPos,pos-prevPos);
strOffset.erase(0,strOffset.find_first_not_of(_T(" ")));
strOffset.erase(strOffset.find_last_not_of(_T(" "))+1);
iCount = sscanf(strOffset.c_str(),"0x%x",&uiOffset);
if (iCount!=1)
{
return false;
}
prevPos = pos +1;
pos = strPartInfo.find(')',prevPos);
if (pos==string::npos)
{
return false;
}
strName = strPartInfo.substr(prevPos,pos-prevPos);
strName.erase(0,strName.find_first_not_of(_T(" ")));
strName.erase(strName.find_last_not_of(_T(" "))+1);
return true;
}
bool parse_parameter(char *pParameter,PARAM_ITEM_VECTOR &vecItem)
{
stringstream paramStream(pParameter);
bool bRet,bFind=false;
string strLine,strPartition,strPartInfo,strPartName;
string::size_type line_size,pos,posColon,posComma;
UINT uiPartOffset,uiPartSize;
STRUCT_PARAM_ITEM item;
vecItem.clear();
int i=0;
while (!paramStream.eof())
{
i++;
getline(paramStream,strLine);
line_size = strLine.size();
if (line_size==0)
{
continue;
}
if(strLine[0]=='#')
{
continue;
}
if (strLine[line_size-1]=='\r')
{
strLine = strLine.substr(0,line_size-1);
}
pos = strLine.find("mtdparts");
if (pos==string::npos)
{
continue;
}
bFind = true;
posColon = strLine.find(':',pos);
if (posColon==string::npos)
{
continue;
}
strPartition = strLine.substr(posColon+1);
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
pos = 0;
posComma = strPartition.find(',',pos);
while (posComma!=string::npos)
{
strPartInfo = strPartition.substr(pos,posComma-pos);
bRet = ParsePartitionInfo(strPartInfo,strPartName,uiPartOffset,uiPartSize);
if (bRet)
{
strcpy(item.szItemName,strPartName.c_str());
item.uiItemOffset = uiPartOffset;
item.uiItemSize = uiPartSize;
vecItem.push_back(item);
}
pos = posComma+1;
posComma = strPartition.find(',',pos);
}
strPartInfo = strPartition.substr(pos);
if (strPartInfo.size()>0)
{
bRet = ParsePartitionInfo(strPartInfo,strPartName,uiPartOffset,uiPartSize);
if (bRet)
{
strcpy(item.szItemName,strPartName.c_str());
item.uiItemOffset = uiPartOffset;
item.uiItemSize = uiPartSize;
vecItem.push_back(item);
}
}
break;
}
return bFind;
}
bool parse_Gptparameter(string str,PARAM_ITEM_VECTOR &vecItem)
{
bool bRet,bFind=false;
string strLine,strPartition,strPartInfo,strPartName;
string::size_type line_size,pos,posColon,posComma;
UINT uiPartOffset,uiPartSize;
ifstream fin(str);
STRUCT_PARAM_ITEM item;
vecItem.clear();
int i=0;
while (getline(fin,strLine))
{
i++;
printf("str = %s",strLine.c_str());
line_size = strLine.size();
if (line_size==0)
{
continue;
}
if(strLine[0]=='#')
{
continue;
}
if (strLine[line_size-1]=='\r')
{
strLine = strLine.substr(0,line_size-1);
}
pos = strLine.find("mtdparts");
if (pos==string::npos)
{
continue;
}
bFind = true;
posColon = strLine.find(':',pos);
if (posColon==string::npos)
{
continue;
}
strPartition = strLine.substr(posColon+1);
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
pos = 0;
posComma = strPartition.find(',',pos);
while (posComma!=string::npos)
{
strPartInfo = strPartition.substr(pos,posComma-pos);
bRet = ParsePartitionInfo(strPartInfo,strPartName,uiPartOffset,uiPartSize);
if (bRet)
{
strcpy(item.szItemName,strPartName.c_str());
item.uiItemOffset = uiPartOffset;
item.uiItemSize = uiPartSize;
vecItem.push_back(item);
}
pos = posComma+1;
posComma = strPartition.find(',',pos);
}
strPartInfo = strPartition.substr(pos);
if (strPartInfo.size()>0)
{
bRet = ParsePartitionInfo(strPartInfo,strPartName,uiPartOffset,uiPartSize);
if (bRet)
{
strcpy(item.szItemName,strPartName.c_str());
item.uiItemOffset = uiPartOffset;
item.uiItemSize = uiPartSize;
vecItem.push_back(item);
}
}
break;
}
return bFind;
}
bool get_parameter_loader( CRKComm *pComm,char *pParameter, int &nParamSize)
{
if ((nParamSize!=-1)&&(!pParameter))
{
return false;
}
BYTE paramHead[512];
DWORD *pParamTag=(DWORD *)paramHead;
DWORD *pParamSize=(DWORD *)(paramHead+4);
int iRet;
iRet = pComm->RKU_ReadLBA(0,1,paramHead);
if (iRet!=ERR_SUCCESS)
{
return false;
}
if (*pParamTag!=0x4D524150)
{
return false;
}
if (nParamSize==-1)
{//<2F><>ȡparameter<65><72>С
nParamSize = *pParamSize;
return true;
}
if (nParamSize<*pParamSize)
{
return false;
}
nParamSize = *pParamSize;
int nParamSec;
nParamSec = (nParamSize+12-1)/512+1;
PBYTE pBuffer=NULL;
pBuffer = new BYTE[nParamSec*512];
if (!pBuffer)
{
return false;
}
iRet = pComm->RKU_ReadLBA(0,nParamSec,pBuffer);
if (iRet!=ERR_SUCCESS)
{
delete []pBuffer;
pBuffer = NULL;
return false;
}
memcpy(pParameter,pBuffer+8,nParamSize);
delete []pBuffer;
pBuffer = NULL;
return true;
}
bool read_bytes_from_partition(DWORD dwPartitionOffset,long long ullstart,DWORD dwCount,PBYTE pOut,CRKComm *pComm)
{
int iRet;
UINT uiTransferSize = 16*1024;
UINT uiTransferSec = uiTransferSize/SECTOR_SIZE;
BYTE *pBuffer = NULL;
UINT uiBegin=dwPartitionOffset,uiLen,uiReadBytes=0,uiTmp;
DWORD dwWritePos=0;
pBuffer = new BYTE[uiTransferSize];
if (!pBuffer)
return false;
uiTmp = ullstart % 2048;
if (uiTmp==0)
{
uiBegin += ullstart / SECTOR_SIZE;
}
else
{
uiReadBytes = 2048 - uiTmp;
uiBegin += ((ullstart/2048)*4);
uiLen = 4;
iRet = pComm->RKU_ReadLBA(uiBegin,uiLen,pBuffer);
if (iRet!=ERR_SUCCESS)
{
delete []pBuffer;
return false;
}
if (dwCount>=uiReadBytes)
{
memcpy(pOut+dwWritePos,pBuffer+uiTmp,uiReadBytes);
dwWritePos += uiReadBytes;
dwCount -= uiReadBytes;
}
else
{
memcpy(pOut+dwWritePos,pBuffer+uiTmp,dwCount);
dwWritePos += dwCount;
dwCount = 0;
}
uiBegin += uiLen;
}
while (dwCount>0)
{
if (dwCount>=uiTransferSize)
{
uiReadBytes = uiTransferSize;
uiLen = uiTransferSec;
}
else
{
uiReadBytes = dwCount;
uiLen = BYTE2SECTOR(uiReadBytes);
}
iRet = pComm->RKU_ReadLBA(uiBegin,uiLen,pBuffer);
if (iRet!=ERR_SUCCESS)
{
delete []pBuffer;
return false;
}
memcpy(pOut+dwWritePos,pBuffer,uiReadBytes);
dwWritePos += uiReadBytes;
dwCount -= uiReadBytes;
uiBegin += uiLen;
}
delete []pBuffer;
return true;
}
bool check_fw_header(CRKComm *pComm,DWORD dwOffset,PSTRUCT_RKIMAGE_HDR pHeader,CRKLog *pLog=NULL)
{
int nHeaderSec = BYTE2SECTOR(sizeof(STRUCT_RKIMAGE_HDR));
char model[256]={0};
PBYTE pBuf=NULL;
pBuf = new BYTE[nHeaderSec*SECTOR_SIZE];
if (!pBuf)
return false;
int iRet;
iRet = pComm->RKU_ReadLBA(dwOffset,nHeaderSec,pBuf);
if (iRet!=ERR_SUCCESS)
{
delete []pBuf;
pBuf = NULL;
return false;
}
memcpy(pHeader,pBuf,sizeof(STRUCT_RKIMAGE_HDR));
delete []pBuf;
pBuf = NULL;
if (pHeader->tag!=RKIMAGE_TAG)
return false;
property_get("ro.product.model", model, "");
if (pLog)
pLog->Record(_T("model:%s\nbackup firmware model:%s\n"),model,pHeader->machine_model);
if(strcmp(model, pHeader->machine_model))
{
return false;
}
return true;
}
bool check_fw_crc(CRKComm *pComm,DWORD dwOffset,PSTRUCT_RKIMAGE_HDR pHeader,CRKLog *pLog=NULL)
{
int iRet;
long long ullRemain,ullCrcOffset;
if (pHeader->machine_model[29]=='H')
{
ullRemain = *((DWORD *)(&pHeader->machine_model[30]));
ullRemain <<= 32;
ullRemain += pHeader->size;
}
else
ullRemain = pHeader->size;
if (ullRemain<=0)
return false;
ullCrcOffset = ullRemain;
UINT uiTransferSize = 16*1024;
UINT uiTransferSec = uiTransferSize/SECTOR_SIZE;
BYTE *pBuffer = NULL;
BYTE oldCrc[4];
UINT uiBegin=dwOffset,uiLen,uiCrc=0,uiReadBytes=0;
pBuffer = new BYTE[uiTransferSize];
if (!pBuffer)
return false;
while(ullRemain>0)
{
if (ullRemain>=uiTransferSize)
{
uiReadBytes = uiTransferSize;
uiLen = uiTransferSec;
}
else
{
uiReadBytes = ullRemain;
uiLen = BYTE2SECTOR(uiReadBytes);
}
iRet = pComm->RKU_ReadLBA(uiBegin,uiLen,pBuffer);
if (iRet!=ERR_SUCCESS)
{
delete []pBuffer;
if (pLog)
pLog->Record(_T("ERROR:check_fw_crc-->RKU_ReadLBA failed,err=%d"),iRet);
return false;
}
uiCrc = CRC_32(pBuffer,uiReadBytes,uiCrc);
uiBegin += uiLen;
ullRemain -= uiReadBytes;
}
delete []pBuffer;
if (!read_bytes_from_partition(dwOffset,ullCrcOffset,4,oldCrc,pComm))
{
if (pLog)
pLog->Record(_T("ERROR:check_fw_crc-->read old crc failed"));
return false;
}
if (uiCrc!=*((UINT *)(oldCrc)))
return false;
return true;
}
bool download_backup_image(PARAM_ITEM_VECTOR &vecParam,char *pszItemName,DWORD dwBackupOffset,STRUCT_RKIMAGE_HDR &hdr,CRKComm *pComm,CRKLog *pLog=NULL)
{
DWORD dwToOffset,dwToSize;
int i,iRet;
if (g_progress_callback)
g_progress_callback(0.5,50);
for (i=0;i<vecParam.size();i++)
{
if (strcmp(pszItemName,vecParam[i].szItemName)==0)
{
dwToOffset = vecParam[i].uiItemOffset;
dwToSize = vecParam[i].uiItemSize;
break;
}
}
if (i>=vecParam.size())
{
if (pLog)
pLog->Record(_T("ERROR:download_backup_image-->no found dest partition."));
return false;
}
long long ullSrcPos,ullSrcSize;
for (i=0;i<hdr.item_count;i++)
{
if (strcmp(pszItemName,hdr.item[i].name)==0)
{
if (hdr.item[i].file[50]=='H')
{
ullSrcPos= *((DWORD *)(&hdr.item[i].file[51]));
ullSrcPos <<= 32;
ullSrcPos += hdr.item[i].offset;
}
else
{
ullSrcPos = hdr.item[i].offset;
}
if (hdr.item[i].file[55]=='H')
{
ullSrcSize= *((DWORD *)(&hdr.item[i].file[56]));
ullSrcSize <<= 32;
ullSrcSize += hdr.item[i].size;
}
else
{
ullSrcSize = hdr.item[i].size;
}
break;
}
}
if (i>=hdr.item_count)
{
if (pLog)
pLog->Record(_T("ERROR:download_backup_image-->no found source in the backup."));
return false;
}
long long ullRemain,ullstart,ullToStart;
UINT uiBegin,uiLen,uiTransferByte;
UINT uiBufferSize=16*1024;
BYTE buffer[16*1024];
BYTE readbuffer[16*1024];
//write image
ullRemain = ullSrcSize;
uiBegin = dwToOffset;
ullstart = ullSrcPos;
while(ullRemain>0)
{
if (ullRemain>=uiBufferSize)
{
uiTransferByte = uiBufferSize;
uiLen = 32;
}
else
{
uiTransferByte = ullRemain;
uiLen = BYTE2SECTOR(uiTransferByte);
}
if (!read_bytes_from_partition(dwBackupOffset,ullstart,uiTransferByte,buffer,pComm))
{
if (pLog)
pLog->Record(_T("ERROR:download_backup_image-->read data from backup failed."));
return false;
}
iRet = pComm->RKU_WriteLBA(uiBegin,uiLen,buffer);
if (iRet!=ERR_SUCCESS)
{
if (pLog)
pLog->Record(_T("ERROR:download_backup_image-->write data to partition failed."));
return false;
}
ullRemain -= uiTransferByte;
uiBegin += uiLen;
ullstart += uiTransferByte;
}
pComm->RKU_ReopenLBAHandle();
if (g_progress_callback)
g_progress_callback(1,0);
if (g_progress_callback)
g_progress_callback(0.4,30);
//check image
if (pLog)
pLog->Record(_T("Start to check system..."));
ullRemain = ullSrcSize;
ullToStart = 0;
ullstart = ullSrcPos;
while(ullRemain>0)
{
if (ullRemain>=uiBufferSize)
{
uiTransferByte = uiBufferSize;
}
else
{
uiTransferByte = ullRemain;
}
if (!read_bytes_from_partition(dwBackupOffset,ullstart,uiTransferByte,buffer,pComm))
{
if (pLog)
pLog->Record(_T("ERROR:download_backup_image-->read data from backup failed."));
return false;
}
if (!read_bytes_from_partition(dwToOffset,ullToStart,uiTransferByte,readbuffer,pComm))
{
if (pLog)
pLog->Record(_T("ERROR:download_backup_image-->read data from partition failed."));
return false;
}
if (memcmp(buffer,readbuffer,uiTransferByte)!=0)
{
if (pLog)
pLog->Record(_T("ERROR:download_backup_image-->compare data failed."));
return false;
}
ullRemain -= uiTransferByte;
ullToStart += uiTransferByte;
ullstart += uiTransferByte;
}
if (g_progress_callback)
g_progress_callback(1,0);
return true;
}
bool IsDeviceLock(CRKComm *pComm,bool &bLock)
{
bLock = false;(void)pComm;
return true;
#if 0
int iRet;
BYTE buffer[4];
iRet = pComm->RKU_GetLockFlag(buffer);
if (iRet!=ERR_SUCCESS)
return false;
DWORD *pFlag=(DWORD *)buffer;
if (*pFlag==1)
bLock = true;
else
bLock = false;
return true;
#endif
}
bool GetPubicKeyFromExternal(char *szDev,CRKLog *pLog,unsigned char *pKey,unsigned int &nKeySize)
{
int hDev=-1;
int j,ret,nRsaByte;
bool bSuccess=false;
BYTE bData[SECTOR_SIZE*8];
PRKANDROID_IDB_SEC0 pSec0=(PRKANDROID_IDB_SEC0)bData;
PRK_SECURE_HEADER pSecureHdr=(PRK_SECURE_HEADER)(bData+SECTOR_SIZE*4);
string strOutput;
if (!szDev)
{
printf("In GetPubicKeyFromExternal device=NULL\n");
return false;
}
else
printf("In GetPubicKeyFromExternal device=%s\n",szDev);
hDev= open(szDev,O_RDONLY,0);
if (hDev<0)
{
if (pLog)
pLog->Record(_T("ERROR:GetPubicKeyFromExternal-->open %s failed,err=%d"),szDev,errno);
goto Exit_GetPubicKeyFromExternal;
}
else
{
if (pLog)
pLog->Record(_T("INFO:GetPubicKeyFromExternal-->%s=%d"),szDev,hDev);
}
ret = lseek(hDev,64*512,SEEK_SET);
if (ret<0)
{
if (pLog)
pLog->Record(_T("ERROR:GetPubicKeyFromExternal-->seek IDBlock failed,err=%d"),errno);
goto Exit_GetPubicKeyFromExternal;
}
ret = read(hDev,bData,8*512);
if (ret!=8*512)
{
if (pLog)
pLog->Record(_T("ERROR:GetPubicKeyFromExternal-->read IDBlock failed,err=%d"),errno);
goto Exit_GetPubicKeyFromExternal;
}
// if (pLog)
// {
// pLog->PrintBuffer(strOutput,bData,512,16);
// pLog->Record("INFO:idb\n%s",strOutput.c_str());
// }
P_RC4(bData,SECTOR_SIZE);
// if (pLog)
// {
// pLog->PrintBuffer(strOutput,bData,512,16);
// pLog->Record("INFO:idb rc4\n%s",strOutput.c_str());
// }
if (pSec0->dwTag!=0x0FF0AA55)
{
if (pLog)
pLog->Record(_T("ERROR:GetPubicKeyFromExternal-->check IDBlock failed,tag=0x%x"),pSec0->dwTag);
goto Exit_GetPubicKeyFromExternal;
}
if (pSec0->uiRc4Flag==0)
{
for(j=0;j<4;j++)
P_RC4(bData+SECTOR_SIZE*(j+4),SECTOR_SIZE);
}
if (pSecureHdr->uiTag!=0x4B415352)
{
if (pLog)
pLog->Record(_T("ERROR:GetPubicKeyFromExternal-->check SecureHeader failed,tag=0x%x"),pSecureHdr->uiTag);
goto Exit_GetPubicKeyFromExternal;
}
nRsaByte = pSecureHdr->usRsaBit/8;
*((USHORT *)pKey) = pSecureHdr->usRsaBit;
for(j=0;j<nRsaByte;j++)
*(pKey+j+2) = pSecureHdr->nFactor[nRsaByte-j-1];
for(j=0;j<nRsaByte;j++)
*(pKey+j+2+nRsaByte) = pSecureHdr->eFactor[nRsaByte-j-1];
nKeySize = nRsaByte*2+2;
// if (pLog)
// {
// pLog->PrintBuffer(strOutput,pKey,nKeySize,16);
// pLog->Record("INFO:Key\n%s",strOutput.c_str());
// }
bSuccess = true;
Exit_GetPubicKeyFromExternal:
if (hDev!=-1)
close(hDev);
return bSuccess;
}
bool GetPubicKeyFromDevice(CRKLog *pLog,unsigned char *pKey,unsigned int &nKeySize)
{
bool bSuccess=false,bRet;
CRKComm *pComm=NULL;
CRKAndroidDevice *pDevice=NULL;
STRUCT_RKDEVICE_DESC device;
pComm = new CRKUsbComm(pLog);
if (!pComm)
{
pLog->Record("ERROR:GetPubicKeyFromDevice-->new CRKComm failed!");
goto EXIT_GetPubicKeyFromDevice;
}
pDevice = new CRKAndroidDevice(device);
if (!pDevice)
{
pLog->Record("ERROR:GetPubicKeyFromDevice-->new CRKAndroidDevice failed!");
goto EXIT_GetPubicKeyFromDevice;
}
pDevice->SetObject(NULL,pComm,pLog);
pDevice->m_pCallback = (UpgradeCallbackFunc)NULL;
pDevice->m_pProcessCallback = (UpgradeProgressCallbackFunc)NULL;
bRet = pDevice->GetPublicKey(pKey,nKeySize);
if (!bRet)
{
pLog->Record("ERROR:GetPubicKeyFromDevice-->GetPublicKey failed!");
goto EXIT_GetPubicKeyFromDevice;
}
bSuccess = true;
EXIT_GetPubicKeyFromDevice:
if (pDevice)
{
delete pDevice;
pDevice = NULL;
}
else if (pComm)
{
delete pComm;
pComm = NULL;
}
return bSuccess;
}
bool UnlockDevice(CRKImage *pImage,CRKLog *pLog,unsigned char *pKey,unsigned int nKeySize)
{
PBYTE pMd5,pSignMd5;
int nSignSize;
unsigned int nOutput = 0;
//bool bRet;
BYTE output[256];
string strOutput;
(void)nKeySize;
printf("in UnlockDevice\n");
if ((!pImage)||(!pKey))
return false;
nSignSize = pImage->GetMd5Data(pMd5,pSignMd5);
if (nSignSize==0)
{
if (pLog)
pLog->Record("Get signed info failed.");
return false;
}
//bRet= DoRsa(output,&nOutput,pSignMd5,nSignSize,pKey,nKeySize);
//if (!bRet)
//{
// if (pLog)
// pLog->Record("DoRsa failed.");
// return false;
//}
if(pLog)
{
pLog->PrintBuffer(strOutput,pMd5,32,16);
pLog->Record("INFO:Old Md5\n%s",strOutput.c_str());
pLog->PrintBuffer(strOutput,output+nOutput-32,32,16);
pLog->Record("INFO:New Md5\n%s",strOutput.c_str());
}
return true;
if (memcmp(pMd5,output+nOutput-32,32)==0)
return true;
else
return false;
}
bool do_rk_firmware_upgrade(char *szFw,void *pCallback,void *pProgressCallback,char *szBootDev)
{
bool bSuccess=false,bRet=false,bLock;
int iRet;
CRKImage *pImage=NULL;
CRKLog *pLog=NULL;
CRKAndroidDevice *pDevice=NULL;
CRKComm *pComm=NULL;
STRUCT_RKDEVICE_DESC device;
//BYTE key[514];
//UINT nKeySize=514;
BYTE uid[RKDEVICE_UID_LEN];
tstring strFw = szFw;
tstring strUid;
(void)szBootDev;
g_callback = (UpgradeCallbackFunc)pCallback;
g_progress_callback = (UpgradeProgressCallbackFunc)pProgressCallback;
if (g_progress_callback)
g_progress_callback(0.1,10);
pLog = new CRKLog();
if (!pLog)
goto EXIT_UPGRADE;
pLog->Record("Start to upgrade firmware...");
if (g_callback)
g_callback("Start to upgrade firmware... \n");
pImage = new CRKImage(strFw,bRet);
if (!bRet)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->new CRKImage failed!");
if (g_callback)
g_callback("ERROR:do_rk_firmware_upgrade-->new CRKImage failed! \n");
goto EXIT_UPGRADE;
}
pComm = new CRKUsbComm(pLog);
if (!pComm)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->new CRKComm failed!");
if (g_callback)
g_callback("ERROR:do_rk_firmware_upgrade-->new CRKComm failed! \n");
goto EXIT_UPGRADE;
}
if (IsDeviceLock(pComm,bLock))
{
if (bLock)
{
bRet = true;
pImage = new CRKImage(strFw,bRet);
if (!bRet)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->new CRKImage with check failed,%s!",szFw);
if (g_callback)
g_callback("ERROR:do_rk_firmware_upgrade-->new CRKImage with check failed,%s! \n",szFw);
goto EXIT_UPGRADE;
}
//bRet = GetPubicKeyFromExternal(szBootDev,pLog,key,nKeySize);
//if (!bRet)
//{
// if (szBootDev)
// pLog->Record("ERROR:do_rk_firmware_upgrade-->Get PubicKey failed,dev=%s!",szBootDev);
// else
// pLog->Record("ERROR:do_rk_firmware_upgrade-->Get PubicKey failed,dev=NULL!");
// goto EXIT_UPGRADE;
//}
//if(access("/res/publicKey.bin",F_OK) == 0){
// int fd = open("/tmp/publicKey.bin", O_RDONLY, 0);
// nKeySize = read(fd, key, 514);
//}else{
// printf("access /res/publicKey.bin failed!\n");
// goto EXIT_UPGRADE;
//}
//if (!UnlockDevice(pImage,pLog,key,nKeySize))
//{
// pLog->Record("ERROR:do_rk_firmware_upgrade-->UnlockDevice failed!");
// goto EXIT_UPGRADE;
//}
// if (pCallback)
// ((UpgradeCallbackFunc)pCallback)("pause");
}
else
{
pImage = new CRKImage(strFw,bRet);
if (!bRet)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->new CRKImage failed,%s!",szFw);
if (g_callback)
g_callback("ERROR:do_rk_firmware_upgrade-->new CRKImage failed,%s! \n",szFw);
goto EXIT_UPGRADE;
}
}
}
else
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->IsDeviceLock failed!");
if (g_callback)
g_callback("ERROR:do_rk_firmware_upgrade-->IsDeviceLock failed! \n");
goto EXIT_UPGRADE;
}
pDevice = new CRKAndroidDevice(device);
if (!pDevice)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->new CRKAndroidDevice failed!");
if (g_callback)
g_callback("ERROR:do_rk_firmware_upgrade-->new CRKAndroidDevice failed! \n");
goto EXIT_UPGRADE;
}
pDevice->SetObject(pImage,pComm,pLog);
if (CreateUid(uid))
{
pDevice->Uid = uid;
pLog->PrintBuffer(strUid,uid,RKDEVICE_UID_LEN);
pLog->Record("uid:%s",strUid.c_str());
if (g_callback)
g_callback("uid:%s \n",strUid.c_str());
}
pDevice->m_pCallback = (UpgradeCallbackFunc)pCallback;
pDevice->m_pProcessCallback = (UpgradeProgressCallbackFunc)pProgressCallback;
pLog->Record("Get FlashInfo...");
if (g_callback)
g_callback("Get FlashInfo... \n");
bRet = pDevice->GetFlashInfo();
if (!bRet)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->GetFlashInfo failed!");
if (g_callback)
g_callback("ERROR:do_rk_firmware_upgrade-->GetFlashInfo failed! \n");
goto EXIT_UPGRADE;
}
pLog->Record("IDBlock Preparing...");
if (g_callback)
g_callback("IDBlock Preparing... \n");
iRet = pDevice->PrepareIDB();
if (iRet!=ERR_SUCCESS)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->PrepareIDB failed!");
if (g_callback)
g_callback("ERROR:do_rk_firmware_upgrade-->PrepareIDB failed! \n");
goto EXIT_UPGRADE;
}
pLog->Record("IDBlock Writing...");
if (g_callback)
g_callback("IDBlock Writing... \n");
iRet = pDevice->DownloadIDBlock();
if (iRet!=ERR_SUCCESS)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->DownloadIDBlock failed!");
if (g_callback)
g_callback("ERROR:do_rk_firmware_upgrade-->DownloadIDBlock failed! \n");
goto EXIT_UPGRADE;
}
if (strFw.find(_T(".bin"))!=tstring::npos)
{
pLog->Record("INFO:do_rk_firmware_upgrade-->Download loader only success!");
if (g_callback)
g_callback("INFO:do_rk_firmware_upgrade-->Download loader only success! \n");
bSuccess = true;
return bSuccess;
}
if (g_callback)
g_callback("INFO:do_rk_firmware_upgrade begin DownloadImage... ! \n");
iRet = pDevice->DownloadImage();
if (iRet!=ERR_SUCCESS)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->DownloadImage failed!");
if (g_callback)
g_callback("ERROR:do_rk_firmware_upgrade-->DownloadImage failed! \n");
goto EXIT_UPGRADE;
}
bSuccess = true;
EXIT_UPGRADE:
if (bSuccess)
{
pLog->Record("Finish to upgrade firmware.");
if (g_callback)
g_callback("Finish to upgrade firmware. \n");
}
else
{
pLog->Record("Fail to upgrade firmware!");
if (g_callback)
g_callback("Fail to upgrade firmware! \n");
}
if (pLog)
{
delete pLog;
pLog = NULL;
}
if (pImage)
{
delete pImage;
pImage = NULL;
}
if (pDevice)
{
delete pDevice;
pDevice = NULL;
}
else
{
if (pComm)
{
delete pComm;
pComm = NULL;
}
}
return bSuccess;
}
bool do_rk_partition_upgrade(char *szFw,void *pCallback,void *pProgressCallback,char nBoot,char *szBootDev)
{
#if 0
bool bSuccess=false,bRet=false,bLock;
int iRet;
CRKImage *pImage=NULL;
CRKLog *pLog=NULL;
CRKAndroidDevice *pDevice=NULL;
CRKComm *pComm=NULL;
STRUCT_RKDEVICE_DESC device;
BYTE key[514];
UINT nKeySize=514;
tstring strFw = szFw;
vector<int> vecDownloadEntry;
vecDownloadEntry.clear();
g_callback = (UpgradeCallbackFunc)pCallback;
g_progress_callback = (UpgradeProgressCallbackFunc)pProgressCallback;
if (g_progress_callback)
g_progress_callback(0.1,5);
pLog = new CRKLog();
if (!pLog)
goto EXIT_DOWNLOAD;
pLog->Record("Start to upgrade partition...");
pComm = new CRKUsbComm(pLog);
if (!pComm)
{
pLog->Record("ERROR:do_rk_partition_upgrade-->new CRKComm failed!");
goto EXIT_DOWNLOAD;
}
if (IsDeviceLock(pComm,bLock))
{
if (bLock)
{
bRet = true;
pImage = new CRKImage(strFw,bRet);
if (!bRet)
{
pLog->Record("ERROR:do_rk_partition_upgrade-->new CRKImage with check failed,%s!",szFw);
goto EXIT_DOWNLOAD;
}
if(nBoot==0)//get key from nand or emmc
bRet = GetPubicKeyFromDevice(pLog,key,nKeySize);
else if((nBoot==1)||(nBoot==2))//get key from sd or usb disk
bRet = GetPubicKeyFromExternal(szBootDev,pLog,key,nKeySize);
else
bRet = false;
if (!bRet)
{
if (szBootDev)
pLog->Record("ERROR:do_rk_partition_upgrade-->Get PubicKey failed,boot=%d,dev=%s!",nBoot,szBootDev);
else
pLog->Record("ERROR:do_rk_partition_upgrade-->Get PubicKey failed,boot=%d,dev=NULL!",nBoot);
goto EXIT_DOWNLOAD;
}
if (!UnlockDevice(pImage,pLog,key,nKeySize))
{
pLog->Record("ERROR:do_rk_partition_upgrade-->UnlockDevice failed!");
goto EXIT_DOWNLOAD;
}
// if (pCallback)
// ((UpgradeCallbackFunc)pCallback)("pause");
}
else
{
pImage = new CRKImage(strFw,bRet);
if (!bRet)
{
pLog->Record("ERROR:do_rk_partition_upgrade-->new CRKImage failed,%s!",szFw);
goto EXIT_DOWNLOAD;
}
}
}
else
{
pLog->Record("ERROR:do_rk_partition_upgrade-->IsDeviceLock failed!");
goto EXIT_DOWNLOAD;
}
pDevice = new CRKAndroidDevice(device);
if (!pDevice)
{
pLog->Record("ERROR:do_rk_partition_upgrade-->new CRKAndroidDevice failed!");
goto EXIT_DOWNLOAD;
}
pDevice->SetObject(pImage,pComm,pLog);
pDevice->m_pCallback = (UpgradeCallbackFunc)pCallback;
pDevice->m_pProcessCallback = (UpgradeProgressCallbackFunc)pProgressCallback;
bRet = pDevice->GetFlashInfo();
if (!bRet)
{
pLog->Record("ERROR:do_rk_partition_upgrade-->GetFlashInfo failed!");
goto EXIT_DOWNLOAD;
}
iRet = pComm->RKU_ShowNandLBADevice();
pLog->Record("Info:do_rk_partition_upgrade-->RKU_ShowNandLBADevice ret=%d",iRet);
iRet = pDevice->UpgradePartition();
if (iRet!=ERR_SUCCESS)
{
pLog->Record("ERROR:do_rk_partition_upgrade-->DownloadImage failed!");
goto EXIT_DOWNLOAD;
}
bSuccess = true;
EXIT_DOWNLOAD:
if (bSuccess)
{
pLog->Record("Finish to upgrade partition.");
}
else
{
pLog->Record("Fail to upgrade partition!");
}
if (pLog)
{
delete pLog;
pLog = NULL;
}
if (pImage)
{
delete pImage;
pImage = NULL;
}
if (pDevice)
{
delete pDevice;
pDevice = NULL;
}
else
{
if (pComm)
{
delete pComm;
pComm = NULL;
}
}
return bSuccess;
#else
(void)nBoot;
return do_rk_firmware_upgrade(szFw,pCallback,pProgressCallback,szBootDev);
#endif
}
bool do_rk_backup_recovery(void *pCallback,void *pProgressCallback)
{
bool bSuccess=false,bRet;
int i,iRet;
CRKLog *pLog=NULL;
CRKComm *pComm=NULL;
char *pParam=NULL;
int nParamSize=-1;
DWORD dwBackupOffset=0;
PARAM_ITEM_VECTOR vecParam;
STRUCT_RKIMAGE_HDR hdr;
g_callback = (UpgradeCallbackFunc)pCallback;
g_progress_callback = (UpgradeProgressCallbackFunc)pProgressCallback;
if (g_progress_callback)
g_progress_callback(0.1,10);
pLog = new CRKLog();
if (!pLog)
goto EXIT_RECOVERY;
pLog->Record("Start to recovery from backup...");
pComm = new CRKUsbComm(pLog);
if (!pComm)
{
pLog->Record("ERROR:do_rk_backup_recovery-->new CRKComm failed!");
goto EXIT_RECOVERY;
}
iRet = pComm->RKU_ShowNandLBADevice();
pLog->Record("Info:do_rk_backup_recovery-->RKU_ShowNandLBADevice ret=%d",iRet);
pLog->Record("Start to read parameter...");
bRet = get_parameter_loader(pComm,pParam,nParamSize);
if (bRet)
{
pParam = new char[nParamSize];
if (pParam)
{
bRet = get_parameter_loader(pComm,pParam,nParamSize);
}
}
if (!bRet)
{
pLog->Record("Read parameter failed!");
goto EXIT_RECOVERY;
}
pLog->Record("Start to parse parameter...");
bRet = parse_parameter(pParam,vecParam);
if (!bRet)
{
pLog->Record("Parse parameter failed!");
goto EXIT_RECOVERY;
}
for (i=0;i<vecParam.size();i++)
{
if (strcmp(vecParam[i].szItemName,PARTNAME_BACKUP)==0)
{
dwBackupOffset = vecParam[i].uiItemOffset;
break;
}
}
if (dwBackupOffset==0)
{
pLog->Record("Get backup offset failed!");
goto EXIT_RECOVERY;
}
pLog->Record("Start to check firmware...");
if (!check_fw_header(pComm,dwBackupOffset,&hdr,pLog))
{
pLog->Record("Check firmware header failed!");
goto EXIT_RECOVERY;
}
if (!check_fw_crc(pComm,dwBackupOffset,&hdr,pLog))
{
pLog->Record("Check firmware crc failed!");
goto EXIT_RECOVERY;
}
pLog->Record("Start to write system...");
if(!download_backup_image(vecParam,(char*)PARTNAME_SYSTEM,dwBackupOffset,hdr,pComm,pLog))
{
pLog->Record("write system failed!");
goto EXIT_RECOVERY;
}
bSuccess = true;
EXIT_RECOVERY:
if (bSuccess)
{
pLog->Record("Finish to recovery from backup.");
}
else
{
pLog->Record("Fail to recovery from backup!");
}
if (pParam)
{
delete []pParam;
pParam = NULL;
}
if (pLog)
{
delete pLog;
pLog = NULL;
}
if (pComm)
{
delete pComm;
pComm = NULL;
}
return bSuccess;
}
bool do_rk_sparse_update(const char *partitionName, const char *src_path){
bool bSuccess=false, bRet;
int i, iRet;
CRKComm *pComm = NULL;
CRKLog *pLog = NULL;
PARAM_ITEM_VECTOR vecParam;
int nParamSize = -1;
char *pParam = NULL;
DWORD dwBackupOffset = 0;
pLog = new CRKLog();
if(!pLog)
goto EXIT_RECOVERY;
pLog->Record("Start to do_rk_sparse_update ...");
pComm = new CRKUsbComm(pLog);
if(!pComm)
{
pLog->Record("ERROR:do_rk_sparse_update-->new CRKComm failed!");
goto EXIT_RECOVERY;
}
iRet = pComm->RKU_ShowNandLBADevice();
pLog->Record("Info:do_rk_sparse_update-->RKU_ShowNandLBADevice ret=%d",iRet);
pLog->Record("Start to read parameter...");
bRet = get_parameter_loader(pComm, pParam, nParamSize);
if(bRet)
{
pParam = new char[nParamSize];
if (pParam)
{
bRet = get_parameter_loader(pComm, pParam, nParamSize);
}
}
if(!bRet)
{
pLog->Record("Read parameter failed!");
goto EXIT_RECOVERY;
}
pLog->Record("Start to parse parameter...");
bRet = parse_parameter(pParam, vecParam);
if(!bRet)
{
pLog->Record("Parse parameter failed!");
goto EXIT_RECOVERY;
}
for(i = 0;i < vecParam.size();i++)
{
if (strcmp(vecParam[i].szItemName, partitionName) == 0){
dwBackupOffset = vecParam[i].uiItemOffset;
break;
}
}
if(dwBackupOffset == 0){
pLog->Record("Get %s offset failed!", partitionName);
goto EXIT_RECOVERY;
}else{
printf("dwBackupOffset is %d.\n", dwBackupOffset);
//dwBackupOffset
RKSparse *sparse = new RKSparse(src_path);
if(sparse->SparseFile_Download(dwBackupOffset, pComm))
bSuccess = true;
delete sparse;
}
EXIT_RECOVERY:
if (bSuccess)
{
pLog->Record("Finish to recovery from backup.");
}
else
{
pLog->Record("Fail to recovery from backup!");
}
if (pParam)
{
delete []pParam;
pParam = NULL;
}
if (pLog)
{
delete pLog;
pLog = NULL;
}
if (pComm)
{
delete pComm;
pComm = NULL;
}
return bSuccess;
}
bool do_rk_gpt_update(char *szFw,void *pCallback,void *pProgressCallback,char *szBootDev){
bool bSuccess=false, bRet;
int iRet,iFileSize;
CRKImage *pImage=NULL;
CRKLog *pLog=NULL;
CRKAndroidDevice *pDevice=NULL;
CRKComm *pComm=NULL;
PARAM_ITEM_VECTOR vecParam;
//int nParamSize = -1;
//char *pParam = NULL;
//DWORD dwBackupOffset = 0;
BYTE *m_paramBuffer;
BYTE *m_gptBuffer = nullptr;
BYTE *backup_gpt;
PARAM_ITEM_VECTOR vecItems;
CONFIG_ITEM_VECTOR vecUuids;
long long uiFlashSize; //bit
tstring strFw = szFw;
// BYTE uid[RKDEVICE_UID_LEN];
tstring strUid;
//STRUCT_RKDEVICE_DESC device;
FILE *m_pFile;
DWORD uiActualRead;
(void)pCallback;(void)pProgressCallback;(void)szBootDev;
pLog->Record("ERROR:strFw======%s",szFw);
pLog = new CRKLog();
if (!pLog)
goto EXIT_UPGRADE;
pLog->Record("Start to do_rk_gpt_update ...");
pComm = new CRKUsbComm(pLog);
if (!pComm)
{
pLog->Record("ERROR:do_rk_gpt_update-->new CRKComm failed!");
goto EXIT_UPGRADE;
}
uiFlashSize = pComm->m_FlashSize;
pLog->Record("uiFlashSize ------------ %lld...",uiFlashSize);
if (!m_gptBuffer)
{
m_gptBuffer = new BYTE[SECTOR_SIZE*67];
if (!m_gptBuffer)
{
if (pLog)
{
pLog->Record(_T("ERROR:RKA_Gpt_Download-->new memory failed,err=%d)"),errno);
}
goto EXIT_UPGRADE;
}
}
memset(m_gptBuffer,0,SECTOR_SIZE*67);
//<2F>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
m_pFile = fopen(szFw,"rb");
fseek(m_pFile, 0, SEEK_END);
iFileSize=ftell(m_pFile);
m_paramBuffer = new BYTE[iFileSize];
memset(m_paramBuffer,0,iFileSize);
pLog->Record(_T("iFileSize is %d"),iFileSize);
fseek(m_pFile,0,SEEK_SET);
uiActualRead = fread(m_paramBuffer,1,iFileSize,m_pFile);
if(uiActualRead != iFileSize)
{
pLog->Record(_T("ERROR:RKA_Gpt_Download-->read parameter file fail,read is %d,total is %d!"),uiActualRead,iFileSize);
}
bRet = parse_parameter((char *)(m_paramBuffer+8),vecItems);
if (!bRet)
{
if (pLog)
{
pLog->Record(_T("ERROR:RKA_Gpt_Download-->parse_parameter failed)"));
}
goto EXIT_UPGRADE;
}
bRet = get_uuid_from_parameter((char *)(m_paramBuffer+8),vecUuids);
backup_gpt = m_gptBuffer+34*SECTOR_SIZE;
create_gpt_buffer(m_gptBuffer,vecItems,vecUuids,uiFlashSize/512);
memcpy(backup_gpt, m_gptBuffer + 2* SECTOR_SIZE, 32 * SECTOR_SIZE);
memcpy(backup_gpt + 32 * SECTOR_SIZE, m_gptBuffer + SECTOR_SIZE, SECTOR_SIZE);
prepare_gpt_backup(m_gptBuffer, backup_gpt, uiFlashSize/512);
iRet = pComm->RKU_WriteLBA(0,34,m_gptBuffer);
if (iRet!=ERR_SUCCESS)
{
if (pLog)
{
pLog->Record(_T("ERROR:RKA_Gpt_Download-->write gpt master failed,RetCode(%d)"),iRet);
}
goto EXIT_UPGRADE;
}
if (pLog)
{
pLog->Record(_T("INFO:RKA_Gpt_Download-->write gpt master successfully!"));
}
iRet = pComm->RKU_WriteLBA(uiFlashSize/512-33,33,backup_gpt);
if (iRet!=ERR_SUCCESS)
{
if (pLog)
{
pLog->Record(_T("ERROR:RKA_Gpt_Download-->write gpt backup failed,RetCode(%d)"),iRet);
}
goto EXIT_UPGRADE;
}
if (pLog)
{
pLog->Record(_T("INFO:RKA_Gpt_Download-->write gpt backup also successfully!"));
}
bSuccess = true;
EXIT_UPGRADE:
if (bSuccess)
{
pLog->Record("Finish to upgrade parameter.");
}
else
{
pLog->Record("Fail to upgrade parameter!");
}
if (pLog)
{
delete pLog;
pLog = NULL;
}
if (pImage)
{
delete pImage;
pImage = NULL;
}
if (pDevice)
{
delete pDevice;
pDevice = NULL;
}
else
{
if (pComm)
{
delete pComm;
pComm = NULL;
}
}
return bSuccess;
}