1366 lines
36 KiB
C++
Raw Permalink Normal View History

2025-05-10 21:49:39 +08:00
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <uuid/uuid.h>
#include "RKAndroidDevice.h"
#define OTP_NODE_PATH "/sys/bus/nvmem/devices/rockchip-otp0/nvmem"
UpgradeCallbackFunc g_callback = NULL;
UpgradeProgressCallbackFunc g_progress_callback = NULL;
/* RK3308 loader update*/
int IsRK3308_Platform()
{
int fd = -1;
int len;
char buff[32];
fd = open(OTP_NODE_PATH, O_RDONLY);
if (fd < 0)
{
printf("Open OTP node fail!\n");
return false;
}
len = read(fd, buff, sizeof(buff));
if (len != sizeof(buff))
{
printf("read OTP node data fail\n");
}
close(fd);
if (buff[0] == 'R' && buff[1] == 'K' && buff[2] == 0x33 && buff[3] == 0x08)
{
return 1;
}
else
{
int i = 0;
for (size_t i = 0; i < 32; i++)
{
if (i % 16 == 0 && i != 0)
{
printf("\n");
}
printf("%x ", buff[i]);
}
}
return 0;
}
int Compatible_rk3308bs_loader()
{
int fd = -1;
int len;
char buff[32];
fd = open(OTP_NODE_PATH, O_RDONLY);
if (fd < 0)
{
printf("Open OTP node fail!\n");
return false;
}
printf("%s: \n", __func__);
len = read(fd, buff, sizeof(buff));
if (len != sizeof(buff))
{
printf("read OTP node data fail\n");
}
close(fd);
printf("OTP node data Info: %x \n", buff[28]);
return (buff[28] & 0x38) && (buff[28] & 0xc0);
}
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);
uuid_t guidValue;
uuid_generate(guidValue);
memcpy(pGuid, (BYTE *)guidValue, 16);
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();
while (!paramStream.eof())
{
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 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;
}
#if 0 //chad.ma close
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;
}
#endif
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)
{
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;
}
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;
bool bRet;
BYTE output[256];
string strOutput;
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;
}
}
extern int sdBootUpdate;
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;
bool bUpdateLoader = true;
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...");
pImage = new CRKImage(strFw, bRet);
if (!bRet)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->new CRKImage failed!");
goto EXIT_UPGRADE;
}
pComm = new CRKUsbComm(pLog);
if (!pComm)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->new CRKComm failed!");
goto EXIT_UPGRADE;
}
pDevice = new CRKAndroidDevice(device);
if (!pDevice)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->new CRKAndroidDevice failed!");
goto EXIT_UPGRADE;
}
pDevice->SetObject(pImage, pComm, pLog);
if (!pComm->RKU_IsEmmcFlash()) //chad.ma if is Emmc flash don't create UUID.
{
if (CreateUid(uid))
{
pDevice->Uid = uid;
pLog->PrintBuffer(strUid, uid, RKDEVICE_UID_LEN);
pLog->Record("uid:%s", strUid.c_str());
}
}
pDevice->m_pCallback = (UpgradeCallbackFunc)pCallback;
pDevice->m_pProcessCallback = (UpgradeProgressCallbackFunc)pProgressCallback;
pLog->Record("Get FlashInfo...");
bRet = pDevice->GetFlashInfo();
if (!bRet)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->GetFlashInfo failed!");
goto EXIT_UPGRADE;
}
bUpdateLoader = pDevice->IsExistBootloaderInFw();
if (IsRK3308_Platform() && Compatible_rk3308bs_loader())
{
bool bFound_3308bs_loader = false;
const char *rk3308bs_loader = "rk3308bs_loader";
DWORD rk3308bs_loaderOffset = 0;
DWORD rk3308bs_loaderSize = 0;
bUpdateLoader = false;
if (pDevice->IsExistPartitionInFw(rk3308bs_loader, rk3308bs_loaderOffset, rk3308bs_loaderSize))
{
printf("Found RK3308bs loader in fw and offset :%d size :%d.\n",
rk3308bs_loaderOffset, rk3308bs_loaderSize);
if (pImage->m_bootObject)
{
delete pImage->m_bootObject;
bool bRet;
PBYTE lpBoot;
lpBoot = new BYTE[rk3308bs_loaderSize];
long offset = rk3308bs_loaderOffset + pImage->GetFWOffset();
fseeko64(pImage->GetFWFileHandle(), offset, SEEK_SET);
size_t ret = fread(lpBoot, 1, rk3308bs_loaderSize, pImage->GetFWFileHandle());
if (ret != rk3308bs_loaderSize)
{
printf("%s : read error\n", __func__);
}
pImage->m_bootObject = new CRKBoot(lpBoot, rk3308bs_loaderSize, bRet);
if (!bRet)
{
printf("CRKImage :Error! new CRKBoot fail!\n");
return false;
}
bUpdateLoader = true;
}
}
}
#ifndef USE_SIGNATURE_FW
if (bUpdateLoader)
{
printf("############### update bootloader start ############\n");
pLog->Record("IDBlock Preparing...");
printf("\t\t############### IDBlock Preparing...\n");
iRet = pDevice->PrepareIDB();
if (iRet != ERR_SUCCESS)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->PrepareIDB failed!");
goto EXIT_UPGRADE;
}
pLog->Record("IDBlock Writing...");
printf("\t\t############### IDBlock Writing...\n");
iRet = pDevice->DownloadIDBlock();
if (iRet != ERR_SUCCESS)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->DownloadIDBlock failed!");
goto EXIT_UPGRADE;
}
printf("############### update bootloader Success############\n");
if (strFw.find(_T(".bin")) != tstring::npos)
{
pLog->Record("INFO:do_rk_firmware_upgrade-->Download loader only success!");
bSuccess = true;
return bSuccess;
}
}
iRet = pDevice->DownloadImage();
if (iRet != ERR_SUCCESS)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->DownloadImage failed!");
goto EXIT_UPGRADE;
}
#else
printf("use signature firmware to update.\n");
iRet = pDevice->DownloadImage();
if (iRet != ERR_SUCCESS)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->DownloadImage failed!");
goto EXIT_UPGRADE;
}
if (bUpdateLoader)
{
printf("############### update bootloader start ############\n");
pLog->Record("IDBlock Preparing...");
printf("\t\t ############### IDBlock Preparing...\n");
iRet = pDevice->PrepareIDB();
if (iRet != ERR_SUCCESS)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->PrepareIDB failed!");
goto EXIT_UPGRADE;
}
pLog->Record("IDBlock Writing...");
printf("\t\t ############### IDBlock Writing...\n");
iRet = pDevice->DownloadIDBlock();
if (iRet != ERR_SUCCESS)
{
pLog->Record("ERROR:do_rk_firmware_upgrade-->DownloadIDBlock failed!");
goto EXIT_UPGRADE;
}
printf("############### update bootloader Success############\n");
if (strFw.find(_T(".bin")) != tstring::npos)
{
pLog->Record("INFO:do_rk_firmware_upgrade-->Download loader only success!");
bSuccess = true;
return bSuccess;
}
}
#endif
bSuccess = true;
EXIT_UPGRADE:
if (bSuccess)
{
pLog->Record("Finish to upgrade firmware.");
}
else
{
pLog->Record("Fail to upgrade firmware!");
}
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)
{
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;
}
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;
const char *strPartSys = PARTNAME_SYSTEM;
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 *)strPartSys, 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;
}