#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);
|
//ÌáÈ¡·ÖÇøÐÅÏ¢
|
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)
|
{
|
//»ñÈ¡parameter´óС
|
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;
|
}
|