#include "RKAndroidDevice.h"
|
#define tole(x) (x)
|
#define look_for_userdata(name) \
|
memcmp(name, PARTNAME_USERDATA, sizeof(PARTNAME_USERDATA) - 1)
|
|
|
/*factor is 0xedb88320*/
|
bool CRKAndroidDevice::bGptFlag = 0;
|
extern int sdBootUpdate;
|
|
char name[PART_NAME];// ·ÖÇøÃû³Æ
|
char file[RELATIVE_PATH];// Ïà¶Ô·¾¶Ãû£¬ÌáÈ¡ÎļþʱÓõ½
|
unsigned int part_size;//·ÖÇøÕ¼ÓÃÉÈÇøÊý
|
unsigned int offset;// ÎļþÔÚImageÖÐµÄÆ«ÒÆ
|
unsigned int flash_offset;// ÉÕдµ½FlashÖеÄλÖÃ(ÒÔsectorΪµ¥Î»)
|
unsigned int usespace;// ÎļþÕ¼Óÿռ䣨°´PAGE¶ÔÆë)
|
unsigned int size;// ×Ö½ÚÊý£¬Êµ¼ÊÎļþ´óС
|
|
#ifdef USE_SIGNATURE_FW
|
RK_UPDATE_ORDER gstUpdateOrder[] =
|
{
|
{1, "rootfs", {"", "", 0, 0, 0, 0, 0}, 0},
|
{2, "boot", {"", "", 0, 0, 0, 0, 0}, 0},
|
{3, "uboot", {"", "", 0, 0, 0, 0, 0}, 0},
|
{4, "bootloader", {"", "", 0, 0, 0, 0, 0}, 0},
|
};
|
#endif
|
|
unsigned int crc32table_le[] =
|
{
|
tole(0x00000000L), tole(0x77073096L), tole(0xee0e612cL), tole(0x990951baL),
|
tole(0x076dc419L), tole(0x706af48fL), tole(0xe963a535L), tole(0x9e6495a3L),
|
tole(0x0edb8832L), tole(0x79dcb8a4L), tole(0xe0d5e91eL), tole(0x97d2d988L),
|
tole(0x09b64c2bL), tole(0x7eb17cbdL), tole(0xe7b82d07L), tole(0x90bf1d91L),
|
tole(0x1db71064L), tole(0x6ab020f2L), tole(0xf3b97148L), tole(0x84be41deL),
|
tole(0x1adad47dL), tole(0x6ddde4ebL), tole(0xf4d4b551L), tole(0x83d385c7L),
|
tole(0x136c9856L), tole(0x646ba8c0L), tole(0xfd62f97aL), tole(0x8a65c9ecL),
|
tole(0x14015c4fL), tole(0x63066cd9L), tole(0xfa0f3d63L), tole(0x8d080df5L),
|
tole(0x3b6e20c8L), tole(0x4c69105eL), tole(0xd56041e4L), tole(0xa2677172L),
|
tole(0x3c03e4d1L), tole(0x4b04d447L), tole(0xd20d85fdL), tole(0xa50ab56bL),
|
tole(0x35b5a8faL), tole(0x42b2986cL), tole(0xdbbbc9d6L), tole(0xacbcf940L),
|
tole(0x32d86ce3L), tole(0x45df5c75L), tole(0xdcd60dcfL), tole(0xabd13d59L),
|
tole(0x26d930acL), tole(0x51de003aL), tole(0xc8d75180L), tole(0xbfd06116L),
|
tole(0x21b4f4b5L), tole(0x56b3c423L), tole(0xcfba9599L), tole(0xb8bda50fL),
|
tole(0x2802b89eL), tole(0x5f058808L), tole(0xc60cd9b2L), tole(0xb10be924L),
|
tole(0x2f6f7c87L), tole(0x58684c11L), tole(0xc1611dabL), tole(0xb6662d3dL),
|
tole(0x76dc4190L), tole(0x01db7106L), tole(0x98d220bcL), tole(0xefd5102aL),
|
tole(0x71b18589L), tole(0x06b6b51fL), tole(0x9fbfe4a5L), tole(0xe8b8d433L),
|
tole(0x7807c9a2L), tole(0x0f00f934L), tole(0x9609a88eL), tole(0xe10e9818L),
|
tole(0x7f6a0dbbL), tole(0x086d3d2dL), tole(0x91646c97L), tole(0xe6635c01L),
|
tole(0x6b6b51f4L), tole(0x1c6c6162L), tole(0x856530d8L), tole(0xf262004eL),
|
tole(0x6c0695edL), tole(0x1b01a57bL), tole(0x8208f4c1L), tole(0xf50fc457L),
|
tole(0x65b0d9c6L), tole(0x12b7e950L), tole(0x8bbeb8eaL), tole(0xfcb9887cL),
|
tole(0x62dd1ddfL), tole(0x15da2d49L), tole(0x8cd37cf3L), tole(0xfbd44c65L),
|
tole(0x4db26158L), tole(0x3ab551ceL), tole(0xa3bc0074L), tole(0xd4bb30e2L),
|
tole(0x4adfa541L), tole(0x3dd895d7L), tole(0xa4d1c46dL), tole(0xd3d6f4fbL),
|
tole(0x4369e96aL), tole(0x346ed9fcL), tole(0xad678846L), tole(0xda60b8d0L),
|
tole(0x44042d73L), tole(0x33031de5L), tole(0xaa0a4c5fL), tole(0xdd0d7cc9L),
|
tole(0x5005713cL), tole(0x270241aaL), tole(0xbe0b1010L), tole(0xc90c2086L),
|
tole(0x5768b525L), tole(0x206f85b3L), tole(0xb966d409L), tole(0xce61e49fL),
|
tole(0x5edef90eL), tole(0x29d9c998L), tole(0xb0d09822L), tole(0xc7d7a8b4L),
|
tole(0x59b33d17L), tole(0x2eb40d81L), tole(0xb7bd5c3bL), tole(0xc0ba6cadL),
|
tole(0xedb88320L), tole(0x9abfb3b6L), tole(0x03b6e20cL), tole(0x74b1d29aL),
|
tole(0xead54739L), tole(0x9dd277afL), tole(0x04db2615L), tole(0x73dc1683L),
|
tole(0xe3630b12L), tole(0x94643b84L), tole(0x0d6d6a3eL), tole(0x7a6a5aa8L),
|
tole(0xe40ecf0bL), tole(0x9309ff9dL), tole(0x0a00ae27L), tole(0x7d079eb1L),
|
tole(0xf00f9344L), tole(0x8708a3d2L), tole(0x1e01f268L), tole(0x6906c2feL),
|
tole(0xf762575dL), tole(0x806567cbL), tole(0x196c3671L), tole(0x6e6b06e7L),
|
tole(0xfed41b76L), tole(0x89d32be0L), tole(0x10da7a5aL), tole(0x67dd4accL),
|
tole(0xf9b9df6fL), tole(0x8ebeeff9L), tole(0x17b7be43L), tole(0x60b08ed5L),
|
tole(0xd6d6a3e8L), tole(0xa1d1937eL), tole(0x38d8c2c4L), tole(0x4fdff252L),
|
tole(0xd1bb67f1L), tole(0xa6bc5767L), tole(0x3fb506ddL), tole(0x48b2364bL),
|
tole(0xd80d2bdaL), tole(0xaf0a1b4cL), tole(0x36034af6L), tole(0x41047a60L),
|
tole(0xdf60efc3L), tole(0xa867df55L), tole(0x316e8eefL), tole(0x4669be79L),
|
tole(0xcb61b38cL), tole(0xbc66831aL), tole(0x256fd2a0L), tole(0x5268e236L),
|
tole(0xcc0c7795L), tole(0xbb0b4703L), tole(0x220216b9L), tole(0x5505262fL),
|
tole(0xc5ba3bbeL), tole(0xb2bd0b28L), tole(0x2bb45a92L), tole(0x5cb36a04L),
|
tole(0xc2d7ffa7L), tole(0xb5d0cf31L), tole(0x2cd99e8bL), tole(0x5bdeae1dL),
|
tole(0x9b64c2b0L), tole(0xec63f226L), tole(0x756aa39cL), tole(0x026d930aL),
|
tole(0x9c0906a9L), tole(0xeb0e363fL), tole(0x72076785L), tole(0x05005713L),
|
tole(0x95bf4a82L), tole(0xe2b87a14L), tole(0x7bb12baeL), tole(0x0cb61b38L),
|
tole(0x92d28e9bL), tole(0xe5d5be0dL), tole(0x7cdcefb7L), tole(0x0bdbdf21L),
|
tole(0x86d3d2d4L), tole(0xf1d4e242L), tole(0x68ddb3f8L), tole(0x1fda836eL),
|
tole(0x81be16cdL), tole(0xf6b9265bL), tole(0x6fb077e1L), tole(0x18b74777L),
|
tole(0x88085ae6L), tole(0xff0f6a70L), tole(0x66063bcaL), tole(0x11010b5cL),
|
tole(0x8f659effL), tole(0xf862ae69L), tole(0x616bffd3L), tole(0x166ccf45L),
|
tole(0xa00ae278L), tole(0xd70dd2eeL), tole(0x4e048354L), tole(0x3903b3c2L),
|
tole(0xa7672661L), tole(0xd06016f7L), tole(0x4969474dL), tole(0x3e6e77dbL),
|
tole(0xaed16a4aL), tole(0xd9d65adcL), tole(0x40df0b66L), tole(0x37d83bf0L),
|
tole(0xa9bcae53L), tole(0xdebb9ec5L), tole(0x47b2cf7fL), tole(0x30b5ffe9L),
|
tole(0xbdbdf21cL), tole(0xcabac28aL), tole(0x53b39330L), tole(0x24b4a3a6L),
|
tole(0xbad03605L), tole(0xcdd70693L), tole(0x54de5729L), tole(0x23d967bfL),
|
tole(0xb3667a2eL), tole(0xc4614ab8L), tole(0x5d681b02L), tole(0x2a6f2b94L),
|
tole(0xb40bbe37L), tole(0xc30c8ea1L), tole(0x5a05df1bL), tole(0x2d02ef8dL)
|
};
|
CHAR CRKAndroidDevice::FindIDBlock(char pos, char &IDBlockPos)
|
{
|
BYTE bData[SECTOR_SIZE * 4];
|
int iRet = ERR_SUCCESS;
|
int i = FindValidBlocks(pos, 1);
|
if (i < 0)
|
{
|
return -1;
|
}
|
for (; i < IDBLOCK_TOP; i = FindValidBlocks(i + 1, 1))
|
{
|
if (i < 0)
|
{
|
break;
|
}
|
memset(bData, 0, SECTOR_SIZE * 4);
|
iRet = m_pComm->RKU_ReadSector(i * m_flashInfo.uiSectorPerBlock, 4, bData);
|
|
if (ERR_SUCCESS != iRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:FindIDBlock-->RKU_ReadSector %x failed,RetCode(%d)"), i * m_flashInfo.uiSectorPerBlock, iRet);
|
}
|
return -1;//Êý¾Ý¶Áȡʧ°Ü
|
}
|
RKANDROID_IDB_SEC0 *pSec0;
|
pSec0 = (RKANDROID_IDB_SEC0 *)bData;
|
P_RC4((BYTE *)pSec0, SECTOR_SIZE);
|
// if (bData[514]==0x69)//0x69='i'
|
if (pSec0->dwTag == 0x0FF0AA55)
|
{
|
//Ôö¼ÓÅжÏtag
|
RKANDROID_IDB_SEC1 *pSec;
|
pSec = (RKANDROID_IDB_SEC1 *)(bData + SECTOR_SIZE);
|
if (pSec->uiChipTag == 0x38324B52)
|
{
|
IDBlockPos = i;
|
return 0;//ÕÒµ½idb
|
}
|
else
|
{
|
continue;//tag²»¶Ô
|
}
|
}
|
|
}
|
return -1;
|
}
|
char CRKAndroidDevice::FindAllIDB()
|
{
|
char i, iIndex, iStart = 0;
|
CHAR iRet;
|
m_oldIDBCounts = 0;
|
for (i = 0; i < 5; i++)
|
{
|
iRet = FindIDBlock(iStart, iIndex);
|
if (iRet < 0)
|
{
|
return m_oldIDBCounts;
|
}
|
|
m_idBlockOffset[i] = iIndex;
|
m_oldIDBCounts++;
|
iStart = iIndex + 1;
|
}
|
|
return m_oldIDBCounts;
|
}
|
bool CRKAndroidDevice::ReserveIDBlock(char iBlockIndex, char iIdblockPos)
|
{
|
char i;
|
CHAR iRet;
|
for (i = iIdblockPos; i < IDB_BLOCKS; i++)
|
{
|
iRet = iBlockIndex = FindValidBlocks(iBlockIndex, m_flashInfo.usPhyBlokcPerIDB);
|
if (iRet < 0)
|
{
|
return false;
|
}
|
m_idBlockOffset[i] = iBlockIndex;
|
iBlockIndex += m_flashInfo.usPhyBlokcPerIDB;
|
}
|
return true;
|
}
|
bool CRKAndroidDevice::CalcIDBCount()
|
{
|
bool bRet;
|
UINT uiIdSectorNum;//ID BLOCK»ù±¾Çø
|
|
bRet = GetLoaderSize();
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:CalcIDBCount-->GetLoaderSize failed"));
|
}
|
return false;
|
}
|
bRet = GetLoaderDataSize();
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:CalcIDBCount-->GetLoaderDataSize failed"));
|
}
|
return false;
|
}
|
if (m_pImage->m_bootObject->IsNewIDBFlag())
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("INFO:CalcIDBCount IsNewIDBFlag is true"));
|
}
|
bRet = GetLoaderHeadSize();
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:CalcIDBCount-->GetLoaderHeadSize failed"));
|
}
|
return false;
|
}
|
uiIdSectorNum = m_usFlashHeadSec + m_usFlashDataSec + m_usFlashBootSec;
|
}
|
else
|
{
|
uiIdSectorNum = 4 + m_usFlashDataSec + m_usFlashBootSec;
|
}
|
|
m_flashInfo.uiSecNumPerIDB = uiIdSectorNum;
|
m_flashInfo.usPhyBlokcPerIDB = CALC_UNIT(uiIdSectorNum, m_flashInfo.usValidSecPerBlock);
|
return true;
|
}
|
bool CRKAndroidDevice::OffsetIDBlock(char pos)
|
{
|
int iBlockIndex, i;
|
for (i = 0; i < m_flashInfo.usPhyBlokcPerIDB; i++)
|
{
|
m_flashInfo.blockState[m_idBlockOffset[pos] + i] = 1; //±ê¼ÇÉÏ»µ¿é
|
}
|
iBlockIndex = m_idBlockOffset[pos] + m_flashInfo.usPhyBlokcPerIDB;
|
for (i = pos; i < 5; i++)
|
{
|
iBlockIndex = FindValidBlocks(iBlockIndex, m_flashInfo.usPhyBlokcPerIDB);
|
if (iBlockIndex < 0)
|
{
|
return false;
|
}
|
m_idBlockOffset[i] = iBlockIndex;
|
iBlockIndex += m_flashInfo.usPhyBlokcPerIDB;
|
}
|
|
return true;
|
}
|
bool CRKAndroidDevice::GetLoaderSize()
|
{
|
if (!m_pImage)
|
{
|
return false;
|
}
|
CHAR index;
|
bool bRet;
|
tchar loaderName[] = _T("FlashBoot");
|
index = m_pImage->m_bootObject->GetIndexByName(ENTRYLOADER, loaderName);
|
if (index == -1)
|
{
|
return false;
|
}
|
DWORD dwDelay;
|
bRet = m_pImage->m_bootObject->GetEntryProperty(ENTRYLOADER, index, m_dwLoaderSize, dwDelay);
|
if (bRet)
|
{
|
m_usFlashBootSec = PAGEALIGN(BYTE2SECTOR(m_dwLoaderSize)) * 4;
|
}
|
return bRet;
|
}
|
bool CRKAndroidDevice::GetLoaderDataSize()
|
{
|
if (!m_pImage)
|
{
|
return false;
|
}
|
CHAR index;
|
bool bRet;
|
tchar loaderName[] = _T("FlashData");
|
index = m_pImage->m_bootObject->GetIndexByName(ENTRYLOADER, loaderName);
|
if (index == -1)
|
{
|
return false;
|
}
|
DWORD dwDelay;
|
bRet = m_pImage->m_bootObject->GetEntryProperty(ENTRYLOADER, index, m_dwLoaderDataSize, dwDelay);
|
if (bRet)
|
{
|
m_usFlashDataSec = PAGEALIGN(BYTE2SECTOR(m_dwLoaderDataSize)) * 4;
|
}
|
return bRet;
|
}
|
|
bool CRKAndroidDevice::GetLoaderHeadSize()
|
{
|
if (!m_pImage)
|
{
|
return false;
|
}
|
char index;
|
bool bRet;
|
tchar loaderName[] = _T("FlashHead");
|
index = m_pImage->m_bootObject->GetIndexByName(ENTRYLOADER, loaderName);
|
if (index == -1)
|
{
|
return false;
|
}
|
DWORD dwDelay;
|
bRet = m_pImage->m_bootObject->GetEntryProperty(ENTRYLOADER, index, m_dwLoaderHeadSize, dwDelay);
|
if (bRet)
|
{
|
m_usFlashHeadSec = PAGEALIGN(BYTE2SECTOR(m_dwLoaderHeadSize)) * 4;
|
}
|
return bRet;
|
}
|
|
CRKAndroidDevice::CRKAndroidDevice(STRUCT_RKDEVICE_DESC &device): CRKDevice(device)
|
{
|
m_oldSec0 = NULL;
|
m_oldSec1 = NULL;
|
m_oldSec2 = NULL;
|
m_oldSec3 = NULL;
|
m_dwLoaderSize = 0;
|
m_dwLoaderDataSize = 0;
|
m_dwLoaderHeadSize = 0;
|
m_oldIDBCounts = 0;
|
m_usFlashBootSec = 0;
|
m_usFlashDataSec = 0;
|
m_usFlashHeadSec = 0;
|
m_dwBackupOffset = 0xFFFFFFFF;
|
m_paramBuffer = NULL;
|
m_pCallback = NULL;
|
m_pProcessCallback = NULL;
|
}
|
CRKAndroidDevice::~CRKAndroidDevice()
|
{
|
if (m_oldSec0)
|
{
|
delete m_oldSec0;
|
m_oldSec0 = NULL;
|
}
|
if (m_oldSec1)
|
{
|
delete m_oldSec1;
|
m_oldSec1 = NULL;
|
}
|
if (m_oldSec2)
|
{
|
delete m_oldSec2;
|
m_oldSec2 = NULL;
|
}
|
if (m_oldSec3)
|
{
|
delete m_oldSec3;
|
m_oldSec3 = NULL;
|
}
|
if (m_paramBuffer)
|
{
|
delete []m_paramBuffer;
|
m_paramBuffer = NULL;
|
}
|
}
|
bool CRKAndroidDevice::GetOldSectorData()
|
{
|
BYTE bData[SECTOR_SIZE * 4];
|
|
if (m_oldIDBCounts <= 0)
|
{
|
return false;
|
}
|
|
if (!GetWriteBackData(m_oldIDBCounts, bData))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:GetOldSectorData-->GetWriteBackData failed"));
|
}
|
return false;//Êý¾Ý¶Áȡʧ°Ü
|
}
|
PBYTE pSec;
|
if (!m_oldSec0)
|
{
|
m_oldSec0 = new RKANDROID_IDB_SEC0;
|
}
|
pSec = (PBYTE)(m_oldSec0);
|
memset(pSec, 0, SECTOR_SIZE);
|
memcpy(pSec, bData, SECTOR_SIZE);
|
P_RC4(pSec, SECTOR_SIZE);
|
|
if (!m_oldSec1)
|
{
|
m_oldSec1 = new RKANDROID_IDB_SEC1;
|
}
|
pSec = (PBYTE)(m_oldSec1);
|
memset(pSec, 0, SECTOR_SIZE);
|
memcpy(pSec, bData + 512, SECTOR_SIZE);
|
|
if (!m_oldSec2)
|
{
|
m_oldSec2 = new RKANDROID_IDB_SEC2;
|
}
|
pSec = (PBYTE)(m_oldSec2);
|
memset(pSec, 0, SECTOR_SIZE);
|
memcpy(pSec, bData + 512 * 2, SECTOR_SIZE);
|
P_RC4(pSec, SECTOR_SIZE);
|
|
if (!m_oldSec3)
|
{
|
m_oldSec3 = new RKANDROID_IDB_SEC3;
|
}
|
pSec = (PBYTE)(m_oldSec3);
|
memset(pSec, 0, SECTOR_SIZE);
|
memcpy(pSec, bData + 512 * 3, SECTOR_SIZE);
|
P_RC4(pSec, SECTOR_SIZE);
|
|
return true;
|
|
}
|
bool CRKAndroidDevice::MakeSector0(PBYTE pSector)
|
{
|
PRKANDROID_IDB_SEC0 pSec0;
|
memset(pSector, 0, SECTOR_SIZE);
|
pSec0 = (PRKANDROID_IDB_SEC0)pSector;
|
|
pSec0->dwTag = 0x0FF0AA55;
|
if (m_pImage->m_bootObject->Rc4DisableFlag)
|
{
|
pSec0->uiRc4Flag = 1;
|
}
|
pSec0->usBootCode1Offset = 0x4;
|
pSec0->usBootCode2Offset = 0x4;
|
pSec0->usBootDataSize = m_usFlashDataSec;
|
pSec0->usBootCodeSize = m_usFlashDataSec + m_usFlashBootSec;
|
|
// pSec0->usCrc = CRC_16(pSector,SECTOR_SIZE-2);
|
return true;
|
}
|
|
void CRKAndroidDevice::MakeSector1(PBYTE pSector)
|
{
|
PRKANDROID_IDB_SEC1 pSec1;
|
memset(pSector, 0, SECTOR_SIZE);
|
pSec1 = (PRKANDROID_IDB_SEC1)pSector;
|
USHORT usSysReserved;
|
if ((m_idBlockOffset[4] + 1) % 12 == 0)
|
{
|
usSysReserved = m_idBlockOffset[4] + 13;
|
}
|
else
|
{
|
usSysReserved = ((m_idBlockOffset[4] + 1) / 12 + 1) * 12;
|
}
|
if (usSysReserved > IDBLOCK_TOP)
|
{
|
usSysReserved = IDBLOCK_TOP;
|
}
|
pSec1->usSysReservedBlock = usSysReserved;
|
|
|
pSec1->usDisk0Size = 0;
|
pSec1->usDisk1Size = 0;
|
pSec1->usDisk2Size = 0;
|
pSec1->usDisk3Size = 0;
|
pSec1->uiChipTag = 0x38324B52;
|
pSec1->uiMachineId = 0;
|
pSec1->usLoaderYear = UshortToBCD(((STRUCT_RKTIME)m_pImage->m_bootObject->ReleaseTime).usYear);
|
pSec1->usLoaderDate = ByteToBCD(((STRUCT_RKTIME)m_pImage->m_bootObject->ReleaseTime).ucMonth);
|
pSec1->usLoaderDate = (pSec1->usLoaderDate << 8) | ByteToBCD(((STRUCT_RKTIME)m_pImage->m_bootObject->ReleaseTime).ucDay);
|
pSec1->usLoaderVer = m_pImage->m_bootObject->Version;
|
if (m_oldSec1)
|
{
|
pSec1->usLastLoaderVer = m_oldSec1->usLoaderVer;
|
pSec1->usReadWriteTimes = m_oldSec1->usReadWriteTimes + 1;
|
}
|
else
|
{
|
pSec1->usLastLoaderVer = 0;
|
pSec1->usReadWriteTimes = 1;
|
}
|
pSec1->uiFlashSize = m_flashInfo.uiFlashSize * 2 * 1024;
|
pSec1->usBlockSize = m_flashInfo.usBlockSize * 2;
|
pSec1->bPageSize = m_flashInfo.uiPageSize * 2;
|
pSec1->bECCBits = m_flashInfo.bECCBits;
|
pSec1->bAccessTime = m_flashInfo.bAccessTime;
|
|
pSec1->usFlashInfoLen = 0;
|
pSec1->usFlashInfoOffset = 0;
|
|
|
pSec1->usIdBlock0 = m_idBlockOffset[0];
|
pSec1->usIdBlock1 = m_idBlockOffset[1];
|
pSec1->usIdBlock2 = m_idBlockOffset[2];
|
pSec1->usIdBlock3 = m_idBlockOffset[3];
|
pSec1->usIdBlock4 = m_idBlockOffset[4];
|
}
|
bool CRKAndroidDevice::MakeSector2(PBYTE pSector)
|
{
|
PRKANDROID_IDB_SEC2 pSec2;
|
pSec2 = (PRKANDROID_IDB_SEC2)pSector;
|
|
pSec2->usInfoSize = 0;
|
memset(pSec2->bChipInfo, 0, CHIPINFO_LEN);
|
|
if (m_oldSec2)
|
{
|
memcpy(pSec2->reserved, m_oldSec2->reserved, RKANDROID_SEC2_RESERVED_LEN);
|
pSec2->usSec3CustomDataOffset = m_oldSec2->usSec3CustomDataOffset;
|
pSec2->usSec3CustomDataSize = m_oldSec2->usSec3CustomDataSize;
|
}
|
else
|
{
|
memset(pSec2->reserved, 0, RKANDROID_SEC2_RESERVED_LEN);
|
pSec2->usSec3CustomDataOffset = m_usWriteBackCustomDataOffset;
|
pSec2->usSec3CustomDataSize = m_usWriteBackCustomDataSize;
|
}
|
|
strcpy(pSec2->szVcTag, "VC");
|
strcpy(pSec2->szCrcTag, "CRC");
|
return true;
|
}
|
bool CRKAndroidDevice::MakeSector3(PBYTE pSector)
|
{
|
PRKANDROID_IDB_SEC3 pSec3;
|
memset(pSector, 0, SECTOR_SIZE);
|
pSec3 = (PRKANDROID_IDB_SEC3)pSector;
|
|
if (m_oldSec3)
|
{
|
memcpy(pSector, (PBYTE)m_oldSec3, SECTOR_SIZE);
|
}
|
else
|
{
|
if (m_backupBuffer)
|
{
|
memcpy(pSector, (PBYTE)m_backupBuffer, SECTOR_SIZE);
|
}
|
}
|
|
|
if (m_uid)
|
{
|
if ((m_oldSec3) || (m_backupBuffer))
|
{
|
if (!CheckUid(pSec3->uidSize, pSec3->uid))
|
{
|
pSec3->uidSize = RKDEVICE_UID_LEN;
|
memcpy(pSec3->uid, m_uid, RKDEVICE_UID_LEN);
|
}
|
}
|
else
|
{
|
pSec3->uidSize = RKDEVICE_UID_LEN;
|
memcpy(pSec3->uid, m_uid, RKDEVICE_UID_LEN);
|
}
|
}
|
|
return true;
|
}
|
int CRKAndroidDevice::MakeIDBlockData(PBYTE lpIDBlock)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("INFO:MakeIDBlockData in"));
|
}
|
RKANDROID_IDB_SEC0 sector0Info;
|
RKANDROID_IDB_SEC1 sector1Info;
|
RKANDROID_IDB_SEC2 sector2Info;
|
RKANDROID_IDB_SEC3 sector3Info;
|
|
if (!m_pImage)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeIDBlockData-->Image is invalid"));
|
}
|
return -1;
|
}
|
CHAR index;
|
tchar loaderCodeName[] = _T("FlashBoot");
|
index = m_pImage->m_bootObject->GetIndexByName(ENTRYLOADER, loaderCodeName);
|
if (index == -1)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeIDBlockData-->Get LoaderCode Entry failed"));
|
}
|
return -2;
|
}
|
PBYTE loaderCodeBuffer;
|
loaderCodeBuffer = new BYTE[m_dwLoaderSize];
|
memset(loaderCodeBuffer, 0, m_dwLoaderSize);
|
if (!m_pImage->m_bootObject->GetEntryData(ENTRYLOADER, index, loaderCodeBuffer))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeIDBlockData-->Get LoaderCode Data failed"));
|
}
|
delete []loaderCodeBuffer;
|
return -3;
|
}
|
|
tchar loaderDataName[] = _T("FlashData");
|
index = m_pImage->m_bootObject->GetIndexByName(ENTRYLOADER, loaderDataName);
|
if (index == -1)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeIDBlockData-->Get LoaderData Entry failed"));
|
}
|
delete []loaderCodeBuffer;
|
return -4;
|
}
|
PBYTE loaderDataBuffer;
|
loaderDataBuffer = new BYTE[m_dwLoaderDataSize];
|
memset(loaderDataBuffer, 0, m_dwLoaderDataSize);
|
if (!m_pImage->m_bootObject->GetEntryData(ENTRYLOADER, index, loaderDataBuffer))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeIDBlockData-->Get LoaderData Data failed"));
|
}
|
delete []loaderDataBuffer;
|
delete []loaderCodeBuffer;
|
return -5;
|
}
|
|
////////////// Éú³ÉÊý¾Ý ////////////////////////////////////////////
|
UINT i;
|
MakeSector0((PBYTE)§or0Info);
|
MakeSector1((PBYTE)§or1Info);
|
if (!MakeSector2((PBYTE)§or2Info))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeIDBlockData-->MakeSector2 failed"));
|
}
|
return -6;
|
}
|
if (!MakeSector3((PBYTE)§or3Info))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeIDBlockData-->MakeSector3 failed"));
|
}
|
return -7;
|
}
|
sector2Info.usSec0Crc = CRC_16((PBYTE)§or0Info, SECTOR_SIZE);
|
sector2Info.usSec1Crc = CRC_16((PBYTE)§or1Info, SECTOR_SIZE);
|
sector2Info.usSec3Crc = CRC_16((PBYTE)§or3Info, SECTOR_SIZE);
|
|
memcpy(lpIDBlock, §or0Info, SECTOR_SIZE);
|
memcpy(lpIDBlock + SECTOR_SIZE, §or1Info, SECTOR_SIZE);
|
// memcpy(lpIDBlock+SECTOR_SIZE*2, §or2Info, SECTOR_SIZE);
|
memcpy(lpIDBlock + SECTOR_SIZE * 3, §or3Info, SECTOR_SIZE);
|
|
if (sector0Info.uiRc4Flag)
|
{
|
//close rc4 encryption
|
for (i = 0; i < m_dwLoaderDataSize / SECTOR_SIZE; i++)
|
{
|
P_RC4(loaderDataBuffer + SECTOR_SIZE * i, SECTOR_SIZE);
|
}
|
for (i = 0; i < m_dwLoaderSize / SECTOR_SIZE; i++)
|
{
|
P_RC4(loaderCodeBuffer + SECTOR_SIZE * i, SECTOR_SIZE);
|
}
|
}
|
|
memcpy(lpIDBlock + SECTOR_SIZE * 4, loaderDataBuffer, m_dwLoaderDataSize);
|
memcpy(lpIDBlock + SECTOR_SIZE * (4 + m_usFlashDataSec), loaderCodeBuffer, m_dwLoaderSize);
|
|
sector2Info.uiBootCodeCrc = CRC_32((PBYTE)(lpIDBlock + SECTOR_SIZE * 4), sector0Info.usBootCodeSize * SECTOR_SIZE);
|
memcpy(lpIDBlock + SECTOR_SIZE * 2, §or2Info, SECTOR_SIZE);
|
|
for (i = 0; i < 4; i++)
|
{
|
if (i == 1)
|
{
|
continue;
|
}
|
else
|
{
|
P_RC4(lpIDBlock + SECTOR_SIZE * i, SECTOR_SIZE);
|
}
|
}
|
|
delete []loaderDataBuffer;
|
delete []loaderCodeBuffer;
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("INFO:MakeIDBlockData out"));
|
}
|
return 0;
|
}
|
|
int CRKAndroidDevice::MakeNewIDBlockData(PBYTE lpIDBlock)
|
{
|
int i;
|
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("INFO:MakeNewIDBlockData in"));
|
}
|
|
if (!m_pImage)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeNewIDBlockData-->Image is invalid"));
|
}
|
return -1;
|
}
|
char index;
|
tchar loaderCodeName[] = _T("FlashBoot");
|
index = m_pImage->m_bootObject->GetIndexByName(ENTRYLOADER, loaderCodeName);
|
if (index == -1)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeNewIDBlockData-->Get LoaderCode Entry failed"));
|
}
|
return -2;
|
}
|
PBYTE loaderCodeBuffer;
|
loaderCodeBuffer = new BYTE[m_dwLoaderSize];
|
memset(loaderCodeBuffer, 0, m_dwLoaderSize);
|
if (!m_pImage->m_bootObject->GetEntryData(ENTRYLOADER, index, loaderCodeBuffer))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeNewIDBlockData-->Get LoaderCode Data failed"));
|
}
|
delete []loaderCodeBuffer;
|
return -3;
|
}
|
|
tchar loaderDataName[] = _T("FlashData");
|
index = m_pImage->m_bootObject->GetIndexByName(ENTRYLOADER, loaderDataName);
|
if (index == -1)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeNewIDBlockData-->Get LoaderData Entry failed"));
|
}
|
delete []loaderCodeBuffer;
|
return -4;
|
}
|
PBYTE loaderDataBuffer;
|
loaderDataBuffer = new BYTE[m_dwLoaderDataSize];
|
memset(loaderDataBuffer, 0, m_dwLoaderDataSize);
|
if (!m_pImage->m_bootObject->GetEntryData(ENTRYLOADER, index, loaderDataBuffer))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeNewIDBlockData-->Get LoaderData Data failed"));
|
}
|
delete []loaderDataBuffer;
|
delete []loaderCodeBuffer;
|
return -5;
|
}
|
|
tchar loaderHeadName[] = _T("FlashHead");
|
index = m_pImage->m_bootObject->GetIndexByName(ENTRYLOADER, loaderHeadName);
|
if (index == -1)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeNewIDBlockData-->Get LoaderHead Entry failed"));
|
}
|
delete []loaderDataBuffer;
|
delete []loaderCodeBuffer;
|
return -6;
|
}
|
PBYTE loaderHeadBuffer;
|
loaderHeadBuffer = new BYTE[m_dwLoaderHeadSize];
|
memset(loaderHeadBuffer, 0, m_dwLoaderHeadSize);
|
if (!m_pImage->m_bootObject->GetEntryData(ENTRYLOADER, index, loaderHeadBuffer))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeNewIDBlockData-->Get LoaderHead Data failed"));
|
}
|
delete []loaderDataBuffer;
|
delete []loaderCodeBuffer;
|
delete []loaderHeadBuffer;
|
return -7;
|
}
|
|
if (m_pImage->m_bootObject->Rc4DisableFlag)
|
{
|
//close rc4 encryption
|
for (i = 0; i < m_dwLoaderHeadSize / SECTOR_SIZE; i++)
|
{
|
P_RC4(loaderHeadBuffer + SECTOR_SIZE * i, SECTOR_SIZE);
|
}
|
for (i = 0; i < m_dwLoaderDataSize / SECTOR_SIZE; i++)
|
{
|
P_RC4(loaderDataBuffer + SECTOR_SIZE * i, SECTOR_SIZE);
|
}
|
for (i = 0; i < m_dwLoaderSize / SECTOR_SIZE; i++)
|
{
|
P_RC4(loaderCodeBuffer + SECTOR_SIZE * i, SECTOR_SIZE);
|
}
|
}
|
memcpy(lpIDBlock, loaderHeadBuffer, m_dwLoaderHeadSize);
|
memcpy(lpIDBlock + SECTOR_SIZE * m_usFlashHeadSec, loaderDataBuffer, m_dwLoaderDataSize);
|
memcpy(lpIDBlock + SECTOR_SIZE * (m_usFlashHeadSec + m_usFlashDataSec), loaderCodeBuffer, m_dwLoaderSize);
|
|
|
delete []loaderDataBuffer;
|
delete []loaderCodeBuffer;
|
delete []loaderHeadBuffer;
|
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("INFO:MakeNewIDBlockData out"));
|
}
|
return 0;
|
}
|
|
bool CRKAndroidDevice::MakeSpareData(PBYTE lpIDBlock, DWORD dwSectorNum, PBYTE lpSpareBuffer)
|
{
|
int i = 0;
|
BYTE bchOutBuf[512 + 3 + 13];
|
BYTE bchInBuf[512 + 3];
|
|
for (i = 0; i < dwSectorNum; i++)
|
{
|
memcpy(bchInBuf, lpIDBlock + 512 * i, 512);
|
bchInBuf[514] = ((i == 0) ? 'i' : 0xff);
|
bchInBuf[512] = 0xff;
|
bchInBuf[513] = 0xff;
|
//¶ÔbchInBuf½øÐÐBCH±àÂ루Éú³É13¸ö×ֽڵıàÂ룩£¬Éú³ÉµÄbchOutBuf(528 Bytes)
|
//ÓÉbchInBuf(515 Bytes)ÓëBCH±àÂë(13 Bytes)×é³É
|
bch_encode(bchInBuf, bchOutBuf);
|
memcpy(lpSpareBuffer + i * 16 + 3, bchOutBuf + 515, 13);
|
}
|
lpSpareBuffer[2] = 'i';
|
return true;
|
}
|
|
int CRKAndroidDevice::WriteIDBlock(PBYTE lpIDBlock, DWORD dwSectorNum, bool bErase)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("INFO:WriteIDBlock in"));
|
m_pLog->Record(_T("INFO:---------------------"));
|
}
|
|
UINT uiBufferSize = 16 * 1024;
|
int iRet, i, nTryCount = 3;
|
UINT uiTotal;
|
uiTotal = dwSectorNum * SECTOR_SIZE;
|
|
while (nTryCount > 0)
|
{
|
m_pLog->Record(_T("dwSectorNum=%d"), dwSectorNum);
|
m_pLog->Record(_T("uiTotal=%d\n"), uiTotal);
|
|
//iRet = m_pComm->RKU_EndWriteSector((BYTE*)&end_write_sector_data);
|
for (i = 0; i <= 4; i++)
|
{
|
iRet = m_pComm->RKU_LoaderWriteLBA(64 + i * 1024, dwSectorNum, lpIDBlock);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:WriteIDBlock-->RKU_WriteSector failed!"));
|
}
|
return -1;
|
}
|
}
|
|
if (iRet == ERR_SUCCESS)
|
{
|
break;
|
}
|
nTryCount--;
|
}
|
|
if (nTryCount <= 0)
|
{
|
return -2;
|
}
|
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("INFO:WriteIDBlock out"));
|
}
|
return 0;
|
}
|
|
int CRKAndroidDevice::PrepareIDB()
|
{
|
int i;
|
generate_gf();
|
gen_poly();
|
string strInfo = "";
|
char szTmp[32];
|
bool bFirstCS = false;
|
|
#if 0 //chad.ma closed 2018/09/27
|
for (i = 0; i < 8; i++)
|
{
|
if (m_flashInfo.bFlashCS & (1 << i))
|
{
|
if (i == 0)
|
{
|
bFirstCS = true;
|
}
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("INFO:CS(%d)\t\t(%dMB)\t\t(%s)"), i + 1, m_flashInfo.uiFlashSize, m_flashInfo.szManufacturerName);
|
}
|
}
|
}
|
if (!bFirstCS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:PrepareIDB-->No Found 1st Flash CS"));
|
}
|
return -1;
|
}
|
|
if (!BuildBlockStateMap(0))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:PrepareIDB-->BuildBlockStateMap failed"));
|
}
|
return -2;
|
}
|
|
FindAllIDB();
|
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:PrepareIDB-->IDblock count=%d."), m_oldIDBCounts);
|
}
|
|
memset(m_backupBuffer, 0, SECTOR_SIZE);
|
|
if (m_oldIDBCounts > 0)
|
{
|
if (m_pLog)
|
{
|
strInfo = "";
|
for (i = 0; i < m_oldIDBCounts; i++)
|
{
|
sprintf(szTmp, "%d ", m_idBlockOffset[i]);
|
strInfo += szTmp;
|
}
|
m_pLog->Record(_T("ERROR:PrepareIDB-->IDblock offset=%s."), strInfo.c_str());
|
}
|
BYTE buffer[4 * SECTOR_SIZE];
|
PRKANDROID_IDB_SEC3 pSec;
|
PRKANDROID_IDB_SEC2 pSec2;
|
pSec2 = (PRKANDROID_IDB_SEC2)(buffer + 2 * SECTOR_SIZE);
|
pSec = (PRKANDROID_IDB_SEC3)(buffer + 3 * SECTOR_SIZE);
|
|
if (!GetWriteBackData(m_oldIDBCounts, buffer))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:PrepareIDB-->GetWriteBackData failed"));
|
}
|
return -3;
|
}
|
P_RC4((PBYTE)pSec2, SECTOR_SIZE);
|
P_RC4((PBYTE)pSec, SECTOR_SIZE);
|
IsExistSector3Crc(pSec2);
|
|
m_usWriteBackCrc = CRC_16((PBYTE)pSec, SECTOR_SIZE);
|
if (m_bExistSector3Crc)
|
{
|
m_usWriteBackCustomDataOffset = pSec2->usSec3CustomDataOffset;
|
m_usWriteBackCustomDataSize = pSec2->usSec3CustomDataSize;
|
if (m_usSector3Crc != m_usWriteBackCrc)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:PrepareIDB-->Check sector3 crc failed"));
|
}
|
}
|
}
|
memcpy(m_backupBuffer, pSec, SECTOR_SIZE);
|
}
|
else
|
{
|
FindBackupBuffer();
|
}
|
|
if (m_oldIDBCounts > 0)
|
{
|
if (!GetOldSectorData())
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:PrepareIDB-->GetOldSectorData failed"));
|
}
|
return -4;
|
}
|
}
|
#endif
|
|
if (!CalcIDBCount())
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:PrepareIDB-->CalcIDBCount failed"));
|
}
|
return -5;
|
}
|
if (!ReserveIDBlock())
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:PrepareIDB-->ReserveIDBlock failed"));
|
}
|
return -6;
|
}
|
if (m_pLog)
|
{
|
strInfo = "";
|
for (i = 0; i < 5; i++)
|
{
|
sprintf(szTmp, "%d ", m_idBlockOffset[i]);
|
strInfo += szTmp;
|
}
|
m_pLog->Record(_T("ERROR:PrepareIDB-->New IDblock offset=%s."), strInfo.c_str());
|
}
|
|
return 0;
|
}
|
|
int CRKAndroidDevice::DownloadIDBlock()
|
{
|
DWORD dwSectorNum;
|
dwSectorNum = m_flashInfo.uiSecNumPerIDB;
|
|
PBYTE pIDBData = NULL;
|
pIDBData = new BYTE[dwSectorNum * SECTOR_SIZE];
|
if (!pIDBData)
|
{
|
return -1;
|
}
|
|
int iRet = 0;
|
memset(pIDBData, 0, dwSectorNum * SECTOR_SIZE);
|
|
// iRet = MakeIDBlockData(pIDBData);
|
if (m_pImage->m_bootObject->IsNewIDBFlag())
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("INFO:DownloadIDBlock-->IsNewIDBFlag is true"), iRet);
|
}
|
iRet = MakeNewIDBlockData(pIDBData);
|
}
|
else
|
{
|
iRet = MakeIDBlockData(pIDBData);
|
}
|
|
if (iRet != 0)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:DownloadIDBlock-->MakeIDBlockData failed,RetCode(%d)"), iRet);
|
}
|
return -2;
|
}
|
|
iRet = WriteIDBlock(pIDBData, dwSectorNum, false);
|
delete []pIDBData;
|
if (iRet == 0)
|
{
|
return 0;
|
}
|
else
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:DownloadIDBlock-->WriteIDBlock failed,RetCode(%d)"), iRet);
|
}
|
//BufferWriteBack();
|
return -3;
|
}
|
}
|
|
bool CRKAndroidDevice::IsExistPartitionInFw(const char *partName, UINT &offset, UINT &size)
|
{
|
bool bRet;
|
long long dwFwOffset;
|
bool bFound = false;
|
STRUCT_RKIMAGE_HDR rkImageHead;
|
int iHeadSize;
|
|
dwFwOffset = m_pImage->FWOffset;
|
iHeadSize = sizeof(STRUCT_RKIMAGE_HDR);
|
|
bRet = m_pImage->GetData(dwFwOffset, iHeadSize, (PBYTE)&rkImageHead);
|
if (!bRet)
|
{
|
return false;
|
}
|
if (rkImageHead.item_count <= 0)
|
{
|
return false;
|
}
|
|
/* get partition size and offset in fw data to buffer */
|
long long partitionSize;
|
long long partitionOffset;
|
|
for (int i = 0; i < rkImageHead.item_count; i++)
|
{
|
if (strncmp(rkImageHead.item[i].name, partName, strlen(partName)) != 0)
|
{
|
continue;
|
}
|
|
if (rkImageHead.item[i].file[55] == 'H')
|
{
|
partitionSize = *((DWORD *)(&rkImageHead.item[i].file[56]));
|
partitionSize <<= 32;
|
partitionSize += rkImageHead.item[i].size;
|
}
|
else
|
{
|
partitionSize = rkImageHead.item[i].size;
|
}
|
|
partitionOffset = rkImageHead.item[i].offset;
|
offset = (UINT)partitionOffset;
|
size = (UINT)partitionSize;
|
bFound = true;
|
|
break;
|
}
|
|
return bFound;
|
}
|
|
bool CRKAndroidDevice::IsExistBootloaderInFw()
|
{
|
bool bRet;
|
long long dwFwOffset;
|
bool bExistLoader = false;
|
FILE *pfPackageFile = NULL;
|
STRUCT_RKIMAGE_HDR rkImageHead;
|
PBYTE pBuffer = NULL;
|
int iHeadSize;
|
|
dwFwOffset = m_pImage->FWOffset;
|
iHeadSize = sizeof(STRUCT_RKIMAGE_HDR);
|
bRet = m_pImage->GetData(dwFwOffset, iHeadSize, (PBYTE)&rkImageHead);
|
|
if (!bRet)
|
{
|
return false;
|
}
|
if (rkImageHead.item_count <= 0)
|
{
|
return false;
|
}
|
|
const char *package_name = "/tmp/package-file";
|
pfPackageFile = fopen(package_name, "wb+");
|
if (!pfPackageFile)
|
{
|
printf("open %s fail !\n", package_name);
|
return false;
|
}
|
|
/* get package-file data to buffer */
|
long long fileBufferSize;
|
long long entryStartOffset;
|
unsigned int uiBufferSize = LBA_TRANSFER_SIZE;
|
|
for (int i = 0; i < rkImageHead.item_count; i++)
|
{
|
if (strcmp(rkImageHead.item[i].name, "package-file") != 0)
|
{
|
continue;
|
}
|
|
if (rkImageHead.item[i].file[55] == 'H')
|
{
|
fileBufferSize = *((DWORD *)(&rkImageHead.item[i].file[56]));
|
fileBufferSize <<= 32;
|
fileBufferSize += rkImageHead.item[i].size;
|
}
|
else
|
{
|
fileBufferSize = rkImageHead.item[i].size;
|
}
|
|
if (fileBufferSize > 0)
|
{
|
DWORD dwFwOffset;
|
dwFwOffset = m_pImage->FWOffset;
|
if (rkImageHead.item[i].file[50] == 'H')
|
{
|
entryStartOffset = *((DWORD *)(&rkImageHead.item[i].file[51]));
|
entryStartOffset <<= 32;
|
entryStartOffset += rkImageHead.item[i].offset;
|
entryStartOffset += m_pImage->FWOffset;
|
}
|
else
|
{
|
entryStartOffset = m_pImage->FWOffset;
|
entryStartOffset += rkImageHead.item[i].offset;
|
}
|
|
pBuffer = new BYTE[uiBufferSize];
|
if (!pBuffer)
|
{
|
printf("Err: No enough memory!\n");
|
goto END;
|
}
|
|
unsigned int uiWroteByte = 0;
|
long long uiEntryOffset = 0;
|
while (fileBufferSize > 0)
|
{
|
memset(pBuffer, 0, uiBufferSize);
|
if (fileBufferSize < uiBufferSize)
|
{
|
uiWroteByte = fileBufferSize;
|
}
|
else
|
{
|
uiWroteByte = uiBufferSize;
|
}
|
|
bRet = m_pImage->GetData(dwFwOffset + rkImageHead.item[i].offset + uiEntryOffset,
|
uiWroteByte, pBuffer);
|
if (!bRet)
|
{
|
goto END;
|
}
|
|
/* write package-file to file */
|
size_t size_wr = 0;
|
if (!strcmp(rkImageHead.item[i].name, PARTNAME_PARAMETER))
|
{
|
size_wr = fwrite(pBuffer + 8, 1, uiWroteByte - 12, pfPackageFile);
|
}
|
else
|
{
|
size_wr = fwrite(pBuffer, 1, uiWroteByte, pfPackageFile);
|
}
|
|
if (size_wr != uiWroteByte)
|
{
|
printf(" ### save %s fail!!! ###\n", rkImageHead.item[i].name);
|
goto END;
|
}
|
|
fileBufferSize -= uiWroteByte;
|
uiEntryOffset += uiWroteByte;
|
}
|
}
|
|
/* judge whether exist bootloader string in package-file */
|
ssize_t read;
|
size_t len = 0;
|
char *line = NULL;
|
fseek(pfPackageFile, 0, SEEK_SET);
|
while ((read = getline(&line, &len, pfPackageFile)) != -1)
|
{
|
printf("%s", line);
|
int i = 0;
|
|
if (strstr(line, INCLUDE_LOADER) == NULL)
|
{
|
continue;
|
}
|
for (i = 0; i < read; i++)
|
{
|
if (line[i] == '#')
|
{
|
bExistLoader = false;
|
break;
|
}
|
if (line[i] == 'b')
|
{
|
bExistLoader = true;
|
break;
|
}
|
}
|
}
|
if (line)
|
{
|
free(line);
|
}
|
}
|
|
END:
|
if (pfPackageFile)
|
{
|
fclose(pfPackageFile);
|
}
|
if (pBuffer)
|
{
|
delete []pBuffer;
|
pBuffer = NULL;
|
}
|
return bExistLoader;
|
}
|
|
static bool isInOrderList(char *partName)
|
{
|
bool bExist = false;
|
int i = 0;
|
#ifdef USE_SIGNATURE_FW
|
for (; i < ARRAY_LENGTH(gstUpdateOrder); i++)
|
{
|
if (!strcmp(partName, gstUpdateOrder[i].partName))
|
{
|
bExist = true;
|
break;
|
}
|
}
|
#endif
|
return bExist;
|
}
|
|
int CRKAndroidDevice::DownloadImage()
|
{
|
long long dwFwOffset;
|
bool bRet;
|
dwFwOffset = m_pImage->FWOffset;
|
STRUCT_RKIMAGE_HDR rkImageHead;
|
int i;
|
int iHeadSize;
|
char szPrompt[100];
|
int iParamPos = -1;
|
bool bFoundParam = false;
|
bool bFwFromUserdata = false;
|
long long uiTotalSize = 0;
|
long long ulItemSize;
|
|
iHeadSize = sizeof(STRUCT_RKIMAGE_HDR);
|
if (m_pProcessCallback)
|
{
|
m_pProcessCallback(0.1, 5);
|
}
|
bRet = m_pImage->GetData(dwFwOffset, iHeadSize, (PBYTE)&rkImageHead);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:DownloadImage-->GetData failed"));
|
}
|
return -1;
|
}
|
if (rkImageHead.item_count <= 0)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:DownloadImage-->No Found item"));
|
}
|
return -2;
|
}
|
|
if (!memcmp(m_pImage->GetFwPath(), "/userdata", 9) ||
|
!memcmp(m_pImage->GetFwPath(), "/data", 5))
|
{
|
bFwFromUserdata = true;
|
}
|
|
m_dwBackupOffset = 0xFFFFFFFF;
|
for (i = 0; i < rkImageHead.item_count; i++)
|
{
|
if (rkImageHead.item[i].flash_offset != 0xFFFFFFFF)
|
{
|
if (strcmp(rkImageHead.item[i].name, PARTNAME_PARAMETER) == 0)
|
{
|
bFoundParam = true;
|
iParamPos = i;
|
}
|
else
|
{
|
if (strcmp(rkImageHead.item[i].name, PARTNAME_BACKUP) == 0)
|
{
|
m_dwBackupOffset = rkImageHead.item[i].flash_offset;
|
}
|
|
if (strcmp(rkImageHead.item[i].name, PARTNAME_RECOVERY) == 0 ||
|
strcmp(rkImageHead.item[i].name, PARTNAME_MISC) == 0)
|
{
|
//if find "recovery" or "misc" partition, we ignore,
|
//recovery.img update processing in normal system.
|
//misc.img not process here.
|
if (!sdBootUpdate)
|
{
|
continue;
|
}
|
}
|
|
// if fw is in userdata and fw have userdata partiton, we ignore update userdata partition.
|
if (look_for_userdata(rkImageHead.item[i].name) == 0 && bFwFromUserdata)
|
continue;
|
|
if (rkImageHead.item[i].file[55] == 'H')
|
{
|
ulItemSize = *((DWORD *)(&rkImageHead.item[i].file[56]));
|
ulItemSize <<= 32;
|
ulItemSize += rkImageHead.item[i].size;
|
}
|
else
|
{
|
ulItemSize = rkImageHead.item[i].size;
|
}
|
|
#ifdef USE_SIGNATURE_FW
|
for (int idx = 0; idx < ARRAY_LENGTH(gstUpdateOrder); idx++)
|
{
|
if (!strcmp(rkImageHead.item[i].name, gstUpdateOrder[idx].partName))
|
{
|
gstUpdateOrder[idx].stItem = rkImageHead.item[i];
|
gstUpdateOrder[idx].ulItemSize = ulItemSize;
|
}
|
}
|
#endif
|
|
uiTotalSize += ulItemSize;
|
}
|
}
|
}
|
|
if (!bFoundParam)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:DownloadImage-->No Found Parameter file"));
|
}
|
return -3;
|
}
|
|
if (!MakeParamFileBuffer(rkImageHead.item[iParamPos]))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:DownloadImage-->MakeParamFileBuffer failed"));
|
}
|
return -12;
|
}
|
|
GptFlag = GetParameterGptFlag(rkImageHead.item[iParamPos]);
|
bGptFlag = GptFlag;
|
printf(">>>>>>>> bGptFlag = %d, lineno = %d\n", bGptFlag, __LINE__);
|
printf(">>>>>>>> CRKAndroidDevice::bGptFlag = %d \n", CRKAndroidDevice::bGptFlag);
|
if (!GptFlag)
|
{
|
if (!CheckParamPartSize(rkImageHead, iParamPos))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:DownloadImage-->CheckParamPartSize failed"));
|
}
|
return -13;
|
}
|
uiTotalSize += (8 * m_uiParamFileSize);
|
}
|
else
|
{
|
uiTotalSize += (SECTOR_SIZE * 67);
|
}
|
m_uiLBATimes = 1;
|
if (m_pProcessCallback)
|
{
|
m_pProcessCallback(0.4, 60);
|
}
|
|
/*
|
* **************************************************************
|
*
|
* upgrade partiton fw data
|
*
|
* **************************************************************
|
*/
|
long long uiCurrentByte = 0;
|
for (i = 0; i < rkImageHead.item_count; i++)
|
{
|
if (m_pProcessCallback)
|
{
|
m_pProcessCallback((double)uiCurrentByte / (double)uiTotalSize, 0);
|
}
|
if (rkImageHead.item[i].flash_offset == 0xFFFFFFFF)
|
{
|
continue;
|
}
|
|
if (i == iParamPos)
|
{
|
if (m_pCallback)
|
{
|
sprintf(szPrompt, "%s writing...\n", rkImageHead.item[i].name);
|
m_pCallback(szPrompt);
|
}
|
if (GptFlag)
|
{
|
m_pLog->Record(_T("########### RKA_Gpt_Download #########"));
|
bRet = RKA_Gpt_Download(rkImageHead.item[i], uiCurrentByte, uiTotalSize);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:DownloadImage-->RKA_Gpt_Download failed"));
|
}
|
return -4;
|
}
|
}
|
else
|
{
|
bRet = RKA_Param_Download(rkImageHead.item[i], uiCurrentByte, uiTotalSize);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T(" ERROR:DownloadImage-->RKA_Param_Download failed"));
|
}
|
// if(m_pCallback)
|
// {
|
// sprintf(szPrompt,"%s writing... failed",rkImageHead.item[i].name);
|
// m_pCallback(szPrompt);
|
// }
|
return -4;
|
}
|
}
|
}
|
else
|
{
|
if (strcmp(rkImageHead.item[i].name, PARTNAME_RECOVERY) == 0 ||
|
strcmp(rkImageHead.item[i].name, PARTNAME_MISC) == 0)
|
{
|
if (!sdBootUpdate)
|
{
|
//if not sd boot update image, we will ignore download partiton.
|
//chad.ma add for ignore 'recovery' or 'misc' or 'userdata' partition update at here.
|
m_pLog->Record(_T("INFO:## Ignore [ %s ] download ##"), rkImageHead.item[i].name);
|
continue;
|
}
|
}
|
|
// if fw is in userdata and fw have userdata partiton, we ignore check userdata partition.
|
if (look_for_userdata(rkImageHead.item[i].name) == 0 && bFwFromUserdata)
|
continue;
|
|
#ifdef USE_SIGNATURE_FW
|
if (isInOrderList(rkImageHead.item[i].name))
|
{
|
continue;
|
}
|
#endif
|
|
m_pLog->Record(_T("INFO:###### Downloading %s #######"), rkImageHead.item[i].name);
|
|
if (rkImageHead.item[i].file[55] == 'H')
|
{
|
ulItemSize = *((DWORD *)(&rkImageHead.item[i].file[56]));
|
ulItemSize <<= 32;
|
ulItemSize += rkImageHead.item[i].size;
|
}
|
else
|
{
|
ulItemSize = rkImageHead.item[i].size;
|
}
|
|
if (ulItemSize > 0)
|
{
|
if (m_pCallback)
|
{
|
sprintf(szPrompt, "%s writing...\n", rkImageHead.item[i].name);
|
m_pCallback(szPrompt);
|
}
|
bRet = RKA_File_Download(rkImageHead.item[i], uiCurrentByte, uiTotalSize);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:DownloadImage-->RKA_File_Download failed(%s)"),
|
rkImageHead.item[i].name);
|
}
|
return -5;
|
}
|
m_pLog->Record(_T("INFO:###### Download %s Done #######"), rkImageHead.item[i].name);
|
}
|
}
|
}
|
|
#ifdef USE_SIGNATURE_FW
|
for (int idx = 0; idx < ARRAY_LENGTH(gstUpdateOrder); idx++)
|
{
|
if (gstUpdateOrder[idx].ulItemSize > 0)
|
{
|
m_pLog->Record(_T("INFO:###### Downloading %s #######"), rkImageHead.item[i].name);
|
if (m_pCallback)
|
{
|
sprintf(szPrompt, "%s writing...\n", gstUpdateOrder[idx].partName);
|
m_pCallback(szPrompt);
|
}
|
bRet = RKA_File_Download(gstUpdateOrder[idx].stItem, uiCurrentByte, uiTotalSize);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:DownloadImage-->RKA_File_Download failed(%s)"),
|
gstUpdateOrder[idx].partName);
|
}
|
return -5;
|
}
|
m_pLog->Record(_T("INFO:###### Download %s Done #######"), gstUpdateOrder[idx].partName);
|
}
|
}
|
#endif
|
|
/*
|
* **************************************************************
|
*
|
* Check partiton fw data
|
*
|
* **************************************************************
|
*/
|
m_pComm->RKU_ReopenLBAHandle();
|
if (m_pProcessCallback)
|
{
|
m_pProcessCallback(1, 0);
|
}
|
if (m_pProcessCallback)
|
{
|
m_pProcessCallback(0.4, 60);
|
}
|
uiCurrentByte = 0;
|
for (i = 0; i < rkImageHead.item_count; i++)
|
{
|
if (m_pProcessCallback)
|
{
|
m_pProcessCallback((double)uiCurrentByte / (double)uiTotalSize, 0);
|
}
|
if (rkImageHead.item[i].flash_offset == 0xFFFFFFFF)
|
{
|
continue;
|
}
|
if (i == iParamPos)
|
{
|
if (m_pCallback)
|
{
|
sprintf(szPrompt, "%s checking...\n", rkImageHead.item[i].name);
|
m_pCallback(szPrompt);
|
}
|
if (GptFlag)
|
{
|
bRet = RKA_Gpt_Check(rkImageHead.item[i], uiCurrentByte, uiTotalSize);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:DownloadImage-->RKA_Gpt_Check failed"));
|
}
|
return -6;
|
}
|
}
|
else
|
{
|
bRet = RKA_Param_Check(rkImageHead.item[i], uiCurrentByte, uiTotalSize);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:DownloadImage-->RKA_Param_Check failed"));
|
}
|
return -6;
|
}
|
}
|
}
|
else
|
{
|
if (strcmp(rkImageHead.item[i].name, PARTNAME_RECOVERY) == 0 ||
|
strcmp(rkImageHead.item[i].name, PARTNAME_MISC) == 0 ||
|
look_for_userdata(rkImageHead.item[i].name) == 0)
|
{
|
if (!sdBootUpdate)
|
{
|
//not sdboot update image , we will ignore check partiton.
|
//chad.ma add for ignore 'recovery' or 'misc' or 'userdata' partition check at here.
|
m_pLog->Record(_T("INFO:# Ignore [ %s ] Check #"), rkImageHead.item[i].name);
|
continue;
|
}
|
}
|
|
if (rkImageHead.item[i].file[55] == 'H')
|
{
|
ulItemSize = *((DWORD *)(&rkImageHead.item[i].file[56]));
|
ulItemSize <<= 32;
|
ulItemSize += rkImageHead.item[i].size;
|
}
|
else
|
{
|
ulItemSize = rkImageHead.item[i].size;
|
}
|
if (ulItemSize > 0)
|
{
|
if (m_pCallback)
|
{
|
sprintf(szPrompt, "%s checking...\n", rkImageHead.item[i].name);
|
m_pCallback(szPrompt);
|
}
|
bRet = RKA_File_Check(rkImageHead.item[i], uiCurrentByte, uiTotalSize);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:DownloadImage-->RKA_File_Check failed(%s)"), rkImageHead.item[i].name);
|
}
|
return -7;
|
}
|
}
|
}
|
}
|
if (m_pProcessCallback)
|
{
|
m_pProcessCallback(1, 0);
|
}
|
|
return 0;
|
}
|
|
bool CRKAndroidDevice::write_partition_upgrade_flag(DWORD dwOffset, BYTE *pMd5, UINT uiFlag)
|
{
|
BYTE flagSector[SECTOR_SIZE];
|
int iRet;
|
memset(flagSector, 0, SECTOR_SIZE);
|
memcpy(flagSector, pMd5, 32);
|
memcpy(flagSector + 32, (BYTE *)(&uiFlag), 4);
|
iRet = m_pComm->RKU_WriteLBA(dwOffset, 1, flagSector);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record("ERROR:write_partition_upgrade_flag-->RKU_WriteLBA failed,err=%d", iRet);
|
}
|
return false;
|
}
|
return true;
|
}
|
bool CRKAndroidDevice::read_partition_upgrade_flag(DWORD dwOffset, BYTE *pMd5, UINT *uiFlag)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record("INFO:read_partition_upgrade_flag in");
|
}
|
BYTE flagSector[SECTOR_SIZE];
|
int iRet;
|
iRet = m_pComm->RKU_ReadLBA(dwOffset, 1, flagSector);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record("ERROR:read_partition_upgrade_flag-->RKU_ReadLBA failed,err=%d", iRet);
|
}
|
return false;
|
}
|
memcpy(pMd5, flagSector, 32);
|
(*uiFlag) = *((UINT *)(flagSector + 32));
|
if (m_pLog)
|
{
|
m_pLog->Record("INFO:read_partition_upgrade_flag out,flag=0x%x", *uiFlag);
|
}
|
return true;
|
}
|
|
int CRKAndroidDevice::UpgradePartition()
|
{
|
long long dwFwOffset;
|
bool bRet, bSameFw = false;
|
BYTE localMd5[32];
|
BYTE *fwMd5, *fwSignMd5;
|
UINT uiFlag;
|
DWORD dwFlagSector = 0;
|
dwFwOffset = m_pImage->FWOffset;
|
STRUCT_RKIMAGE_HDR rkImageHead;
|
vector<int> vecUpgradePartition;
|
vecUpgradePartition.clear();
|
char szPrompt[100];
|
int iHeadSize = 0;
|
if (m_pProcessCallback)
|
{
|
m_pProcessCallback(0.1, 5);
|
}
|
|
iHeadSize = sizeof(STRUCT_RKIMAGE_HDR);
|
bRet = m_pImage->GetData(dwFwOffset, iHeadSize, (PBYTE)&rkImageHead);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:UpgradePartition-->GetData failed"));
|
}
|
return -1;
|
}
|
if (rkImageHead.item_count <= 0)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:UpgradePartition-->No Found partition item"));
|
}
|
return -2;
|
}
|
|
int i;
|
vector<int>::iterator iter;
|
m_dwBackupOffset = 0xFFFFFFFF;
|
int iParamPos = - 1;
|
long long uiTotalSize = 0;
|
long long ulItemSize = 0;
|
bool bFoundParam = false, bFoundSystem = false, bFoundUserData = false;
|
for (i = 0; i < rkImageHead.item_count; i++)
|
{
|
if (rkImageHead.item[i].flash_offset != 0xFFFFFFFF)
|
{
|
for (iter = vecUpgradePartition.begin(); iter != vecUpgradePartition.end(); iter++)
|
{
|
if (rkImageHead.item[*iter].flash_offset > rkImageHead.item[i].flash_offset)
|
{
|
iter = vecUpgradePartition.insert(iter, i);
|
break;
|
}
|
}
|
|
if (iter == vecUpgradePartition.end())
|
{
|
vecUpgradePartition.push_back(i);
|
}
|
if (strcmp(rkImageHead.item[i].name, PARTNAME_PARAMETER) == 0)
|
{
|
bFoundParam = true;
|
iParamPos = i;
|
}
|
else
|
{
|
if (strcmp(rkImageHead.item[i].name, PARTNAME_SYSTEM) == 0 ||
|
!strcmp(rkImageHead.item[i].name, PARTNAME_ROOTFS))
|
{
|
bFoundSystem = true;
|
}
|
if (strcmp(rkImageHead.item[i].name, PARTNAME_MISC) == 0)
|
{
|
dwFlagSector = rkImageHead.item[i].flash_offset + rkImageHead.item[i].part_size - 4;
|
}
|
if (look_for_userdata(rkImageHead.item[i].name) == 0)
|
{
|
bFoundUserData = true;
|
}
|
|
if (strcmp(rkImageHead.item[i].name, PARTNAME_BACKUP) == 0)
|
{
|
m_dwBackupOffset = rkImageHead.item[i].flash_offset;
|
}
|
|
if (rkImageHead.item[i].file[55] == 'H')
|
{
|
ulItemSize = *((DWORD *)(&rkImageHead.item[i].file[56]));
|
ulItemSize <<= 32;
|
ulItemSize += rkImageHead.item[i].size;
|
}
|
else
|
{
|
ulItemSize = rkImageHead.item[i].size;
|
}
|
uiTotalSize += ulItemSize;
|
}
|
}
|
}
|
|
if (!bFoundParam)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:UpgradePartition-->No Found Parameter file"));
|
}
|
return -3;
|
}
|
|
if (!MakeParamFileBuffer(rkImageHead.item[iParamPos]))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:UpgradePartition-->MakeParamFileBuffer failed"));
|
}
|
return -12;
|
}
|
|
if (!CheckParamPartSize(rkImageHead, iParamPos))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:UpgradePartition-->CheckParamPartSize failed"));
|
}
|
return -13;
|
}
|
uiTotalSize += (8 * m_uiParamFileSize); //¼ÓÉϲÎÊýÎļþÐèÒªµÄ´óС
|
m_uiLBATimes = 1;
|
m_pImage->GetMd5Data(fwMd5, fwSignMd5);
|
if (dwFlagSector != 0)
|
{
|
if (read_partition_upgrade_flag(dwFlagSector, localMd5, &uiFlag))
|
{
|
if (memcmp(localMd5, fwMd5, 32) == 0)
|
{
|
bSameFw = true;
|
}
|
}
|
}
|
if (m_pProcessCallback)
|
{
|
m_pProcessCallback(0.8, 90);
|
}
|
long long uiCurrentByte = 0;
|
for (i = 0; i < vecUpgradePartition.size(); i++)
|
{
|
if (m_pProcessCallback)
|
{
|
m_pProcessCallback((double)uiCurrentByte / (double)uiTotalSize, 0);
|
}
|
if (vecUpgradePartition[i] == iParamPos)
|
{
|
if ((bSameFw) && (uiFlag >= rkImageHead.item[vecUpgradePartition[i]].flash_offset))
|
{
|
uiCurrentByte += (8 * m_uiParamFileSize);
|
continue;
|
}
|
if (m_pCallback)
|
{
|
sprintf(szPrompt, "%s writing...\n", rkImageHead.item[vecUpgradePartition[i]].name);
|
m_pCallback(szPrompt);
|
}
|
bRet = RKA_Param_Download(rkImageHead.item[vecUpgradePartition[i]], uiCurrentByte, uiTotalSize);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T(" ERROR:UpgradePartition-->RKA_Param_Download failed"));
|
}
|
return -4;
|
}
|
m_pComm->RKU_ReopenLBAHandle();
|
if (m_pCallback)
|
{
|
sprintf(szPrompt, "%s checking...\n", rkImageHead.item[vecUpgradePartition[i]].name);
|
m_pCallback(szPrompt);
|
}
|
uiCurrentByte -= (8 * m_uiParamFileSize);
|
bRet = RKA_Param_Check(rkImageHead.item[vecUpgradePartition[i]], uiCurrentByte, uiTotalSize);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:UpgradePartition-->RKA_Param_Check failed"));
|
}
|
return -6;
|
}
|
}
|
else
|
{
|
if (rkImageHead.item[vecUpgradePartition[i]].file[55] == 'H')
|
{
|
ulItemSize = *((DWORD *)(&rkImageHead.item[vecUpgradePartition[i]].file[56]));
|
ulItemSize <<= 32;
|
ulItemSize += rkImageHead.item[vecUpgradePartition[i]].size;
|
}
|
else
|
{
|
ulItemSize = rkImageHead.item[vecUpgradePartition[i]].size;
|
}
|
if ((bSameFw) && (uiFlag >= rkImageHead.item[vecUpgradePartition[i]].flash_offset))
|
{
|
uiCurrentByte += ulItemSize;
|
continue;
|
}
|
|
if (ulItemSize > 0)
|
{
|
if (m_pCallback)
|
{
|
sprintf(szPrompt, "%s writing...\n", rkImageHead.item[vecUpgradePartition[i]].name);
|
m_pCallback(szPrompt);
|
}
|
bRet = RKA_File_Download(rkImageHead.item[vecUpgradePartition[i]], uiCurrentByte, uiTotalSize);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:UpgradePartition-->RKA_File_Download failed(%s)"), rkImageHead.item[vecUpgradePartition[i]].name);
|
}
|
return -5;
|
}
|
m_pComm->RKU_ReopenLBAHandle();
|
if (m_pCallback)
|
{
|
sprintf(szPrompt, "%s checking...\n", rkImageHead.item[vecUpgradePartition[i]].name);
|
m_pCallback(szPrompt);
|
}
|
uiCurrentByte -= ulItemSize;
|
bRet = RKA_File_Check(rkImageHead.item[vecUpgradePartition[i]], uiCurrentByte, uiTotalSize);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:UpgradePartition-->RKA_File_Check failed(%s)"), rkImageHead.item[vecUpgradePartition[i]].name);
|
}
|
return -7;
|
}
|
}
|
else
|
{
|
continue;
|
}
|
}
|
if (dwFlagSector != 0)
|
{
|
write_partition_upgrade_flag(dwFlagSector, fwMd5, rkImageHead.item[vecUpgradePartition[i]].flash_offset);
|
}
|
}
|
if (m_pProcessCallback)
|
{
|
m_pProcessCallback(1, 0);
|
}
|
return 0;
|
}
|
int CRKAndroidDevice::EraseIDB()
|
{
|
DWORD dwEraseCounts;
|
if (m_oldIDBCounts > 0)
|
{
|
dwEraseCounts = m_oldSec1->usSysReservedBlock;
|
}
|
else
|
{
|
dwEraseCounts = IDBLOCK_TOP;
|
}
|
if (m_bEmmc)
|
{
|
if (EraseEmmcBlock(0, 0, dwEraseCounts) != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:EraseIDB-->EraseEmmcBlock failed"));
|
}
|
return -1;
|
}
|
}
|
else
|
{
|
if (!EraseMutilBlock(0, 0, dwEraseCounts, false))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:EraseIDB-->EraseMutilBlock failed"));
|
}
|
return -1;
|
}
|
}
|
|
return 0;
|
}
|
int CRKAndroidDevice::EraseAllBlocks()
|
{
|
int i;
|
UINT uiBlockCount;
|
int iRet = ERR_SUCCESS, iErasePos = 0, iEraseBlockNum = 0, iEraseTimes = 0, iCSIndex = 0;
|
BYTE bCSCount = 0;
|
for (i = 0; i < 8; i++)
|
{
|
if (m_flashInfo.bFlashCS & (1 << i))
|
{
|
bCSCount++;
|
}
|
}
|
|
for (i = 0; i < 8; i++)
|
{
|
if (m_flashInfo.bFlashCS & (1 << i))
|
{
|
uiBlockCount = m_flashInfo.uiBlockNum;
|
iErasePos = 0;
|
iEraseTimes = 0;
|
while (uiBlockCount > 0)
|
{
|
iEraseBlockNum = (uiBlockCount < MAX_ERASE_BLOCKS) ? uiBlockCount : MAX_ERASE_BLOCKS;
|
if (m_bEmmc)
|
{
|
iRet = EraseEmmcBlock(i, iErasePos, iEraseBlockNum);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:EraseAllBlocks-->EraseEmmcBlock failed,RetCode(%d)"), iRet);
|
}
|
return -1;
|
}
|
}
|
else
|
{
|
iRet = m_pComm->RKU_EraseBlock(i, iErasePos, iEraseBlockNum, ERASE_FORCE);
|
if ((iRet != ERR_SUCCESS) && (iRet != ERR_FOUND_BAD_BLOCK))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:EraseAllBlocks-->RKU_EraseBlock failed,RetCode(%d)"), iRet);
|
}
|
return -1;
|
}
|
}
|
|
iErasePos += iEraseBlockNum;
|
uiBlockCount -= iEraseBlockNum;
|
iEraseTimes++;
|
}
|
iCSIndex++;
|
}
|
}
|
|
return 0;
|
}
|
|
bool CRKAndroidDevice::BufferWriteBack()
|
{
|
FindAllIDB();
|
if (m_oldIDBCounts > 0)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:BufferWriteBack-->Found IDB"));
|
}
|
return true;
|
}
|
if (m_usWriteBackCrc == 0)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("INFO:BufferWriteBack-->Crc is zero"));
|
}
|
return true;
|
}
|
BYTE pWriteBackBuffer[2 * SECTOR_SIZE];
|
|
char *pszTag = (char *)pWriteBackBuffer;
|
USHORT *pValue = (USHORT *)(pWriteBackBuffer + 4);
|
|
memset(pWriteBackBuffer, 0, 2 * SECTOR_SIZE);
|
|
|
strcpy(pszTag, "CRC");
|
*pValue = m_usWriteBackCrc;
|
pValue++;
|
*pValue = m_usWriteBackCustomDataOffset;
|
pValue++;
|
*pValue = m_usWriteBackCustomDataSize;
|
memcpy(pWriteBackBuffer + SECTOR_SIZE, m_backupBuffer, SECTOR_SIZE);
|
|
STRUCT_END_WRITE_SECTOR end_write_sector_data;
|
BYTE writeBuf[8 * SECTOR_SIZE];
|
UINT uiOffset, uiTotal, uiWriteByte, uiCrc;
|
int iRet, i, nTryCount = 3;
|
uiTotal = 2 * SECTOR_SIZE;
|
uiCrc = CRC_32(pWriteBackBuffer, uiTotal);
|
end_write_sector_data.uiSize = uiTotal;
|
end_write_sector_data.uiCrc = uiCrc;
|
for (i = WBBUFFER_BOTTOM; i < WBBUFFER_TOP; i++)
|
{
|
end_write_sector_data.uiBlock[i] = i;
|
}
|
while (nTryCount > 0)
|
{
|
uiOffset = 0;
|
uiTotal = 2 * SECTOR_SIZE;
|
while (uiTotal > 0)
|
{
|
if (uiTotal >= 2048)
|
{
|
uiWriteByte = 2048;
|
}
|
else
|
{
|
uiWriteByte = uiTotal;
|
}
|
|
memcpy(writeBuf + 8, pWriteBackBuffer + uiOffset, uiWriteByte);
|
iRet = m_pComm->RKU_WriteLBA(64 + uiOffset, uiWriteByte, writeBuf);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:BufferWriteBack-->RKU_WriteSector failed!"));
|
}
|
return false;
|
}
|
uiOffset += uiWriteByte;
|
uiTotal -= uiWriteByte;
|
}
|
//iRet = m_pComm->RKU_EndWriteSector((BYTE*)&end_write_sector_data);
|
if (iRet == ERR_SUCCESS)
|
{
|
break;
|
}
|
nTryCount--;
|
}
|
if (nTryCount <= 0)
|
{
|
return false;
|
}
|
|
return true;
|
}
|
bool CRKAndroidDevice::FindBackupBuffer()
|
{
|
int i, iRet;
|
bool bRet;
|
BYTE buffer[2 * SECTOR_SIZE];
|
for (i = WBBUFFER_BOTTOM; i < WBBUFFER_TOP; i++)
|
{
|
memset(buffer, 0, 2 * SECTOR_SIZE);
|
iRet = m_pComm->RKU_ReadSector(i * m_flashInfo.uiSectorPerBlock, 2, buffer);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:FindBackupBuffer-->RKU_ReadSector failed,RetCode(%d)"), iRet);
|
}
|
continue;
|
}
|
else
|
{
|
PSTRUCT_RKANDROID_WBBUFFER pWriteBack;
|
pWriteBack = (PSTRUCT_RKANDROID_WBBUFFER)buffer;
|
char *pszCrcTag = (char *)buffer;
|
if (pWriteBack->dwTag == 0x38324B52)
|
{
|
bRet = CheckCrc16(buffer, SECTOR_SIZE - 2, pWriteBack->usCrc);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:FindBackupBuffer-->Check Crc Failed"));
|
}
|
// continue;
|
}
|
PRKANDROID_IDB_SEC3 pSec = (PRKANDROID_IDB_SEC3)m_backupBuffer;
|
pSec->usSNSize = pWriteBack->usSnSize;
|
memcpy(pSec->sn, pWriteBack->btSnData, RKDEVICE_SN_LEN);
|
memset(pSec->reserved, 0, RKANDROID_SEC3_RESERVED_LEN);
|
memcpy(pSec->reserved + 6, pWriteBack->btReserve, RKANDROID_SEC3_RESERVED_LEN - 6);
|
pSec->imeiSize = pWriteBack->btImeiSize;
|
memcpy(pSec->imei, pWriteBack->btImeiData, RKDEVICE_IMEI_LEN);
|
pSec->uidSize = pWriteBack->btUidSize;
|
memcpy(pSec->uid, pWriteBack->btUidData, RKDEVICE_UID_LEN);
|
pSec->blueToothSize = pWriteBack->btBlueToothSize;
|
memcpy(pSec->blueToothAddr, pWriteBack->btBlueToothData, RKDEVICE_BT_LEN);
|
pSec->macSize = pWriteBack->btMacSize;
|
memcpy(pSec->macAddr, pWriteBack->btMacData, RKDEVICE_MAC_LEN);
|
m_usWriteBackCrc = CRC_16(m_backupBuffer, SECTOR_SIZE);
|
}
|
else if (strcmp(pszCrcTag, "CRC") == 0)
|
{
|
m_usWriteBackCrc = *((USHORT *)(buffer + 4));
|
m_usWriteBackCustomDataOffset = *((USHORT *)(buffer + 6));
|
m_usWriteBackCustomDataSize = *((USHORT *)(buffer + 8));
|
bRet = CheckCrc16(buffer + SECTOR_SIZE, SECTOR_SIZE, m_usWriteBackCrc);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:FindBackupBuffer-->Check Crc Failed"));
|
}
|
m_usWriteBackCrc = CRC_16(buffer + SECTOR_SIZE + SPARE_SIZE, SECTOR_SIZE);
|
// continue;
|
}
|
memcpy(m_backupBuffer, buffer + SECTOR_SIZE, SECTOR_SIZE);
|
}
|
else
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("INFO:FindBackupBuffer-->No Found Tag"));
|
}
|
continue;
|
}
|
|
break;
|
}
|
}
|
if (i < WBBUFFER_TOP)
|
{
|
return true;
|
}
|
else
|
{
|
return false;
|
}
|
}
|
|
bool CRKAndroidDevice::RKA_File_Download(STRUCT_RKIMAGE_ITEM &entry, long long ¤tByte, long long totalByte)
|
{
|
UINT uiLBATransferSize = (LBA_TRANSFER_SIZE) * m_uiLBATimes;
|
UINT uiLBASector = uiLBATransferSize / SECTOR_SIZE;
|
int iRet;
|
bool bRet;
|
UINT uiBufferSize = uiLBATransferSize;
|
long long uifileBufferSize;
|
long long ulEntryStartOffset;
|
DWORD dwFWOffset;
|
dwFWOffset = m_pImage->FWOffset;
|
if (entry.file[50] == 'H')
|
{
|
ulEntryStartOffset = *((DWORD *)(&entry.file[51]));
|
ulEntryStartOffset <<= 32;
|
ulEntryStartOffset += entry.offset;
|
ulEntryStartOffset += m_pImage->FWOffset;
|
}
|
else
|
{
|
ulEntryStartOffset = m_pImage->FWOffset;
|
ulEntryStartOffset += entry.offset;
|
}
|
if (entry.file[55] == 'H')
|
{
|
uifileBufferSize = *((DWORD *)(&entry.file[56]));
|
uifileBufferSize <<= 32;
|
uifileBufferSize += entry.size;
|
}
|
else
|
{
|
uifileBufferSize = entry.size;
|
}
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("INFO:Start updating [ %s ],offset=0x%x,size=%llu"), entry.name, entry.flash_offset, uifileBufferSize);
|
}
|
|
BYTE byRWMethod = RWMETHOD_IMAGE;
|
|
if (entry.flash_offset > m_dwBackupOffset)
|
{
|
byRWMethod = RWMETHOD_LBA;
|
}
|
|
PBYTE pBuffer = NULL;
|
pBuffer = new BYTE[uiBufferSize];
|
if (!pBuffer)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_File_Download-->New memory failed"));
|
}
|
return false;
|
}
|
|
bool bUser = false;
|
// if (strcmp(entry.name,PARTNAME_MISC)==0)
|
// {
|
// currentByte += uifileBufferSize;
|
// return true;
|
// }
|
if (strcmp(entry.name, PARTNAME_USER) == 0)
|
{
|
bUser = true;
|
}
|
|
UINT uiBegin, uiLen, uiWriteByte;
|
long long uiEntryOffset;
|
|
uiBegin = entry.flash_offset;
|
uiLen = 0;
|
uiWriteByte = 0;
|
uiEntryOffset = 0;
|
#ifdef USE_SIMULATE_POWER_OFF
|
UINT cnt = 5;
|
long long itemTotalsize;
|
bool isInOrder = false;
|
itemTotalsize = uifileBufferSize;
|
isInOrder = isInOrderList(entry.name);
|
#endif
|
|
while (uifileBufferSize > 0)
|
{
|
#ifdef USE_SIMULATE_POWER_OFF
|
if (isInOrder && uifileBufferSize < itemTotalsize / 2)
|
{
|
while (cnt > 0)
|
{
|
if (m_pLog)
|
{
|
printf("******************************************************\n");
|
printf("current is %s upgrading\n", entry.name);
|
printf("This is simulate abnormal power off test\n");
|
printf("left --- %ds ---\n", cnt);
|
printf("******************************************************\n");
|
}
|
sleep(1);
|
cnt--;
|
}
|
}
|
#endif
|
memset(pBuffer, 0, uiBufferSize);
|
if (uifileBufferSize < uiBufferSize)
|
{
|
uiWriteByte = uifileBufferSize;
|
uiLen = ((uiWriteByte % SECTOR_SIZE == 0) ? (uiWriteByte / SECTOR_SIZE) : (uiWriteByte / SECTOR_SIZE + 1));
|
}
|
else
|
{
|
uiWriteByte = uiBufferSize;
|
uiLen = uiLBASector;
|
}
|
bRet = m_pImage->GetData(dwFWOffset + entry.offset + uiEntryOffset, uiWriteByte, pBuffer);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_File_Download-->GetFileData failed"));
|
}
|
delete []pBuffer;
|
pBuffer = NULL;
|
return false;
|
}
|
if (bUser)
|
{
|
if ((pBuffer[0] == 0xEB) && (pBuffer[1] == 0x58) && (pBuffer[2] == 0x90))
|
{
|
//fat user image
|
iRet = m_pComm->RKU_TestDeviceReady((DWORD *)&m_uiUserSectors, NULL, TU_GETUSERSECTOR_SUBCODE);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_File_Download-->Get user sectors failed,RetCode(%d)"), iRet);
|
}
|
|
delete []pBuffer;
|
pBuffer = NULL;
|
return false;
|
}
|
if ((m_uiUserSectors == 0) || (m_uiUserSectors == (DWORD) -1))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_File_Download-->User size is wrong,value=0x%x"), m_uiUserSectors);
|
}
|
|
delete []pBuffer;
|
pBuffer = NULL;
|
return false;
|
}
|
if (m_uiUserSectors <= uiBegin)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_File_Download-->Available total is smaller than user offset"));
|
}
|
|
delete []pBuffer;
|
pBuffer = NULL;
|
return false;
|
}
|
m_uiUserSectors -= uiBegin;
|
|
PBYTE pDbr, pCopyDbr;
|
pDbr = pBuffer;
|
pCopyDbr = pBuffer + SECTOR_SIZE * 6;
|
if (*(UINT *)(pDbr + 32) < m_uiUserSectors)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_File_Download-->Original size is smaller than current user size"));
|
}
|
|
delete []pBuffer;
|
pBuffer = NULL;
|
return false;
|
}
|
|
(*(UINT *)(pDbr + 32)) = m_uiUserSectors;
|
(*(UINT *)(pCopyDbr + 32)) = m_uiUserSectors;
|
}
|
|
bUser = false;
|
}
|
|
iRet = m_pComm->RKU_WriteLBA(uiBegin, uiLen, pBuffer, byRWMethod);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_File_Download-->RKU_WriteLBA failed,Written(%d),RetCode(%d)"), uiEntryOffset, iRet);
|
}
|
|
delete []pBuffer;
|
pBuffer = NULL;
|
return false;
|
}
|
uifileBufferSize -= uiWriteByte;
|
uiEntryOffset += uiWriteByte;
|
uiBegin += uiLen;
|
currentByte += uiWriteByte;
|
}
|
|
delete []pBuffer;
|
pBuffer = NULL;
|
|
// if (m_pLog)
|
// {
|
// m_pLog->Record(_T("INFO:[ %s ] upgrade Done!"), entry.name);
|
// }
|
return true;
|
}
|
|
bool CRKAndroidDevice::RKA_File_Check(STRUCT_RKIMAGE_ITEM &entry, long long ¤tByte, long long totalByte)
|
{
|
UINT uiLBATransferSize = (LBA_TRANSFER_SIZE) * m_uiLBATimes;
|
UINT uiLBASector = uiLBATransferSize / SECTOR_SIZE;
|
int iRet;
|
bool bRet;
|
UINT uiBufferSize = uiLBATransferSize;
|
long long uifileBufferSize;
|
long long ulEntryStartOffset;
|
DWORD dwFWOffset;
|
dwFWOffset = m_pImage->FWOffset;
|
if (entry.file[50] == 'H')
|
{
|
ulEntryStartOffset = *((DWORD *)(&entry.file[51]));
|
ulEntryStartOffset <<= 32;
|
ulEntryStartOffset += entry.offset;
|
ulEntryStartOffset += m_pImage->FWOffset;
|
}
|
else
|
{
|
ulEntryStartOffset = m_pImage->FWOffset;
|
ulEntryStartOffset += entry.offset;
|
}
|
if (entry.file[55] == 'H')
|
{
|
uifileBufferSize = *((DWORD *)(&entry.file[56]));
|
uifileBufferSize <<= 32;
|
uifileBufferSize += entry.size;
|
}
|
else
|
{
|
uifileBufferSize = entry.size;
|
}
|
|
BYTE byRWMethod = RWMETHOD_IMAGE;
|
if (entry.flash_offset > m_dwBackupOffset)
|
{
|
byRWMethod = RWMETHOD_LBA;
|
}
|
|
PBYTE pBufferFromFile = NULL;
|
pBufferFromFile = new BYTE[uiBufferSize];
|
if (!pBufferFromFile)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_File_Check-->New memory failed"));
|
}
|
return false;
|
}
|
PBYTE pBufferFromFlash = NULL;
|
pBufferFromFlash = new BYTE[uiBufferSize];
|
if (!pBufferFromFlash)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_File_Check-->New memory failed"));
|
}
|
delete []pBufferFromFile;
|
return false;
|
}
|
|
bool bUser = false;
|
// if (strcmp(entry.name,PARTNAME_MISC)==0)
|
// {
|
// currentByte += uifileBufferSize;
|
// return true;
|
// }
|
if (strcmp(entry.name, PARTNAME_USER) == 0)
|
{
|
bUser = true;
|
if ((entry.name[PART_NAME - 2] == 'N') && (entry.name[PART_NAME - 1] == 'C'))
|
{
|
//no check user
|
currentByte += uifileBufferSize;
|
return true;
|
}
|
}
|
|
UINT uiBegin, uiLen, uiWriteByte;
|
long long uiEntryOffset;
|
uiBegin = entry.flash_offset;
|
uiLen = 0;
|
uiWriteByte = 0;
|
uiEntryOffset = 0;
|
while (uifileBufferSize > 0)
|
{
|
if (uifileBufferSize < uiBufferSize)
|
{
|
uiWriteByte = uifileBufferSize;
|
uiLen = ((uiWriteByte % SECTOR_SIZE == 0) ? (uiWriteByte / SECTOR_SIZE) : (uiWriteByte / SECTOR_SIZE + 1));
|
}
|
else
|
{
|
uiWriteByte = uiBufferSize;
|
uiLen = uiLBASector;
|
}
|
|
|
memset(pBufferFromFile, 0, uiBufferSize);
|
memset(pBufferFromFlash, 0, uiBufferSize);
|
|
iRet = m_pComm->RKU_ReadLBA(uiBegin, uiLen, pBufferFromFlash, byRWMethod);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_File_Check-->RKU_ReadLBA failed,Read(%d),RetCode(%d)"), uiEntryOffset, iRet);
|
}
|
delete []pBufferFromFile;
|
delete []pBufferFromFlash;
|
return false;
|
}
|
bRet = m_pImage->GetData(dwFWOffset + entry.offset + uiEntryOffset, uiWriteByte, pBufferFromFile);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_File_Check-->GetFileData failed"));
|
}
|
delete []pBufferFromFile;
|
delete []pBufferFromFlash;
|
return false;
|
}
|
if (bUser)
|
{
|
if ((pBufferFromFile[0] == 0xEB) && (pBufferFromFile[1] == 0x58) && (pBufferFromFile[2] == 0x90))
|
{
|
//fat user image
|
PBYTE pDbr, pCopyDbr;
|
pDbr = pBufferFromFile;
|
pCopyDbr = pBufferFromFile + SECTOR_SIZE * 6;
|
|
(*(UINT *)(pDbr + 32)) = m_uiUserSectors;
|
(*(UINT *)(pCopyDbr + 32)) = m_uiUserSectors;
|
}
|
|
bUser = false;
|
}
|
|
if (memcmp(pBufferFromFile, pBufferFromFlash, uiWriteByte) != 0)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_File_Check-->Memcmp failed,Read(%d)"), uiEntryOffset);
|
tchar szDateTime[100];
|
tstring strFile;
|
time_t now;
|
struct tm timeNow;
|
time(&now);
|
localtime_r(&now, &timeNow);
|
_stprintf(szDateTime, _T("%02d-%02d-%02d"), timeNow.tm_hour, timeNow.tm_min, timeNow.tm_sec);
|
|
strFile = szDateTime;
|
strFile += _T("/tmp/file.bin");
|
m_pLog->SaveBuffer(strFile, pBufferFromFile, uiWriteByte);
|
|
strFile = szDateTime;
|
strFile += _T("/tmp/flash.bin");
|
m_pLog->SaveBuffer(strFile, pBufferFromFlash, uiWriteByte);
|
}
|
delete []pBufferFromFile;
|
delete []pBufferFromFlash;
|
return false;
|
}
|
// if (uiBegin == entry.flash_offset)
|
// {
|
// tstring strFile;
|
// strFile = "/tmp/";
|
// strFile += entry.name;
|
// strFile += ".img";
|
// m_pLog->SaveBuffer( strFile,pBufferFromFlash,uiWriteByte );
|
// m_pLog->Record("%s=%x %x %x %x",entry.name,pBufferFromFlash[0],pBufferFromFlash[1],pBufferFromFlash[2],pBufferFromFlash[3]);
|
// }
|
|
currentByte += uiWriteByte;
|
uiEntryOffset += uiWriteByte;
|
uifileBufferSize -= uiWriteByte;
|
uiBegin += uiLen;
|
|
}
|
|
delete []pBufferFromFile;
|
delete []pBufferFromFlash;
|
return true;
|
}
|
|
bool CRKAndroidDevice::RKA_Param_Download(STRUCT_RKIMAGE_ITEM &entry, long long ¤tByte, long long totalByte)
|
{
|
//д5·Ý²ÎÊýÎļþ
|
UINT uiLBATransferSize = (LBA_TRANSFER_SIZE) * m_uiLBATimes;
|
UINT uiLBASector = uiLBATransferSize / SECTOR_SIZE;
|
int iRet, i;
|
BYTE byRWMethod = RWMETHOD_IMAGE;
|
if (entry.flash_offset > m_dwBackupOffset)
|
{
|
byRWMethod = RWMETHOD_LBA;
|
}
|
|
UINT uiTransfer;
|
UINT uiStepSec = entry.part_size / 8;
|
// if (m_pLog)
|
// {
|
// m_pLog->Record(_T("INFO:RKA_Param_Download-->step=%d"),uiStepSec);
|
// }
|
|
UINT uiLen, uiWriteByte, uiFileSize;
|
UINT uiBegin;
|
for (i = 0; i < 8; i++)
|
{
|
uiFileSize = m_uiParamFileSize;
|
uiBegin = entry.flash_offset + uiStepSec * i;
|
uiLen = 0;
|
uiWriteByte = 0;
|
uiTransfer = 0;
|
// if (m_pLog)
|
// {
|
// m_pLog->Record(_T("INFO:RKA_Param_Download-->no %d,offset=%d"),i+1,uiBegin);
|
// }
|
while (uiFileSize > 0)
|
{
|
if (uiFileSize < uiLBATransferSize)
|
{
|
uiWriteByte = uiFileSize;
|
uiLen = ((uiWriteByte % 512 == 0) ? (uiWriteByte / 512) : (uiWriteByte / 512 + 1));
|
}
|
else
|
{
|
uiWriteByte = uiLBATransferSize;
|
uiLen = uiLBASector;
|
}
|
iRet = m_pComm->RKU_WriteLBA(uiBegin, uiLen, m_paramBuffer + uiTransfer, byRWMethod); //ÿ´Î¶¼ÒªÐ´32ÉÈÇø,°´page¶ÔÆë
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_Param_Download-->RKU_WriteLBA failed,Written(%d),RetCode(%d)"), uiTransfer, iRet);
|
}
|
|
return false;
|
}
|
|
uiTransfer += uiWriteByte;
|
currentByte += uiWriteByte;
|
uiBegin += uiLen;
|
uiFileSize -= uiWriteByte;
|
|
}
|
}
|
|
return true;
|
}
|
bool CRKAndroidDevice::RKA_Param_Check(STRUCT_RKIMAGE_ITEM &entry, long long ¤tByte, long long totalByte)
|
{
|
UINT uiLBATransferSize = (LBA_TRANSFER_SIZE) * m_uiLBATimes;
|
UINT uiLBASector = uiLBATransferSize / SECTOR_SIZE;
|
int iRet, i;
|
UINT uiReadBufferSize = uiLBATransferSize;
|
BYTE byRWMethod = RWMETHOD_IMAGE;
|
if (entry.flash_offset > m_dwBackupOffset)
|
{
|
byRWMethod = RWMETHOD_LBA;
|
}
|
|
PBYTE pRead = NULL;
|
pRead = new BYTE[uiReadBufferSize];
|
if (!pRead)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_Param_Check-->New ReadBuffer failed"));
|
}
|
return false;
|
}
|
|
UINT uiTransfer;
|
UINT uiStepSec = entry.part_size / 8;
|
|
UINT uiLen, uiWriteByte, uiFileSize;
|
UINT uiBegin;
|
for (i = 0; i < 8; i++)
|
{
|
uiFileSize = m_uiParamFileSize;
|
uiBegin = entry.flash_offset + uiStepSec * i;
|
uiLen = 0;
|
uiWriteByte = 0;
|
uiTransfer = 0;
|
// if (m_pLog)
|
// {
|
// m_pLog->Record(_T("INFO:RKA_Param_Check-->no %d,offset=%d"),i+1,uiBegin);
|
// }
|
while (uiFileSize > 0)
|
{
|
memset(pRead, 0, uiReadBufferSize);
|
if (uiFileSize < uiLBATransferSize)
|
{
|
uiWriteByte = uiFileSize;
|
uiLen = ((uiWriteByte % 512 == 0) ? (uiWriteByte / 512) : (uiWriteByte / 512 + 1));
|
}
|
else
|
{
|
uiWriteByte = uiLBATransferSize;
|
uiLen = uiLBASector;
|
}
|
iRet = m_pComm->RKU_ReadLBA(uiBegin, uiLen, pRead, byRWMethod);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_Param_Check-->RKU_ReadLBA failed,Read(%d),RetCode(%d)"), uiTransfer, iRet);
|
}
|
delete []pRead;
|
return false;
|
}
|
if (memcmp(pRead, m_paramBuffer + uiTransfer, uiWriteByte) != 0)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_Param_Check-->Memcmp failed,Read(%d)"), uiTransfer);
|
tchar szDateTime[100];
|
tstring strFile;
|
time_t now;
|
struct tm timeNow;
|
time(&now);
|
localtime_r(&now, &timeNow);
|
_stprintf(szDateTime, _T("%02d-%02d-%02d"), timeNow.tm_hour + 1, timeNow.tm_min + 1, timeNow.tm_sec + 1);
|
|
strFile = szDateTime;
|
strFile += _T("/tmp/file.bin");
|
m_pLog->SaveBuffer(strFile, m_paramBuffer + uiTransfer, uiWriteByte);
|
|
strFile = szDateTime;
|
strFile += _T("/tmp/flash.bin");
|
m_pLog->SaveBuffer(strFile, pRead, uiWriteByte);
|
}
|
|
delete []pRead;
|
return false;
|
|
}
|
// if (m_pLog)
|
// {
|
// string strSrc,strDst;
|
// if (uiWriteByte>16)
|
// {
|
// m_pLog->PrintBuffer(strSrc,pRead,16);
|
// m_pLog->PrintBuffer(strDst,m_paramBuffer+uiTransfer,16);
|
// }
|
// else
|
// {
|
// m_pLog->PrintBuffer(strSrc,pRead,uiWriteByte);
|
// m_pLog->PrintBuffer(strDst,m_paramBuffer+uiTransfer,uiWriteByte);
|
// }
|
// m_pLog->Record("Read:%s",strSrc.c_str());
|
// m_pLog->Record("Compare:%s",strDst.c_str());
|
// }
|
uiTransfer += uiWriteByte;
|
currentByte += uiWriteByte;
|
uiBegin += uiLen;
|
uiFileSize -= uiWriteByte;
|
|
}
|
}
|
|
delete []pRead;
|
return true;
|
}
|
|
bool CRKAndroidDevice::RKA_Gpt_Download(STRUCT_RKIMAGE_ITEM &entry, long long ¤tByte, long long totalByte)
|
{
|
UINT uiLBATransferSize = (LBA_TRANSFER_SIZE) * m_uiLBATimes;
|
UINT uiLBALoopLimit = (LBA_LOOP_SIZE) / uiLBATransferSize;
|
UINT uiLBASector = uiLBATransferSize / SECTOR_SIZE;
|
int iRet;
|
bool bRet;
|
PARAM_ITEM_VECTOR vecItems;
|
CONFIG_ITEM_VECTOR vecUuids;
|
BYTE byRWMethod = RWMETHOD_IMAGE;
|
BYTE *backup_gpt;
|
|
if (!m_gptBuffer)
|
{
|
m_gptBuffer = new BYTE[SECTOR_SIZE * 67];
|
if (!m_gptBuffer)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_Gpt_Download-->new memory failed,err=%d)"), errno);
|
}
|
return false;
|
}
|
}
|
memset(m_gptBuffer, 0, SECTOR_SIZE * 67);
|
bRet = parse_parameter((char *)(m_paramBuffer + 8), vecItems);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_Gpt_Download-->parse_parameter failed)"));
|
}
|
return false;
|
}
|
bRet = get_uuid_from_parameter((char *)(m_paramBuffer + 8), vecUuids);
|
backup_gpt = m_gptBuffer + 34 * SECTOR_SIZE;
|
|
//create_gpt_buffer(m_gptBuffer,vecItems,vecUuids,m_flashInfo.uiFlashSize*2048);
|
create_gpt_buffer(m_gptBuffer, vecItems, vecUuids, m_flashInfo.uiBlockNum);
|
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_paramBuffer, backup_gpt);
|
|
iRet = m_pComm->RKU_WriteLBA(0, 34, m_gptBuffer);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_Gpt_Download-->write gpt master failed,RetCode(%d)"), iRet);
|
}
|
return false;
|
}
|
|
DWORD dwPos;
|
//dwPos = m_flashInfo.uiFlashSize*2048-33;
|
dwPos = m_flashInfo.uiBlockNum - 33;
|
iRet = m_pComm->RKU_WriteLBA(dwPos, 33, backup_gpt);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_Gpt_Download-->write gpt backup failed,RetCode(%d)"), iRet);
|
}
|
return false;
|
}
|
currentByte += (SECTOR_SIZE * 67);
|
|
return true;
|
}
|
bool CRKAndroidDevice::RKA_Gpt_Check(STRUCT_RKIMAGE_ITEM &entry, long long ¤tByte, long long totalByte)
|
{
|
UINT uiLBATransferSize = (LBA_TRANSFER_SIZE) * m_uiLBATimes;
|
UINT uiLBALoopLimit = (LBA_LOOP_SIZE) / uiLBATransferSize;
|
UINT uiLBASector = uiLBATransferSize / SECTOR_SIZE;
|
int iRet;
|
BYTE byRWMethod = RWMETHOD_IMAGE;
|
|
PBYTE pRead = NULL;
|
pRead = new BYTE[34 * SECTOR_SIZE];
|
if (!pRead)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_Gpt_Check-->New ReadBuffer failed,err=%d"), errno);
|
}
|
return false;
|
}
|
iRet = m_pComm->RKU_ReadLBA(0, 34, pRead);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_Gpt_Download-->read gpt master failed,RetCode(%d)"), iRet);
|
}
|
delete []pRead;
|
return false;
|
}
|
if (memcmp(m_gptBuffer, pRead, 34 * SECTOR_SIZE) != 0)
|
{
|
if (m_pLog)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_Gpt_Download-->compare gpt master failed"));
|
}
|
tchar szDateTime[100];
|
tstring strFile;
|
time_t now;
|
struct tm timeNow;
|
time(&now);
|
localtime_r(&now, &timeNow);
|
_stprintf(szDateTime, _T("%02d-%02d-%02d"), timeNow.tm_hour + 1, timeNow.tm_min + 1, timeNow.tm_sec + 1);
|
strFile = m_pLog->LogSavePath;
|
strFile += szDateTime;
|
strFile += _T("file.bin");
|
m_pLog->SaveBuffer(strFile, m_gptBuffer, 34 * SECTOR_SIZE);
|
strFile = m_pLog->LogSavePath;
|
strFile += szDateTime;
|
strFile += _T("flash.bin");
|
m_pLog->SaveBuffer(strFile, pRead, 34 * SECTOR_SIZE);
|
}
|
delete []pRead;
|
return false;
|
}
|
|
iRet = m_pComm->RKU_ReadLBA(m_flashInfo.uiBlockNum - 33, 33, pRead);
|
//iRet = m_pComm->RKU_ReadLBA(m_flashInfo.uiFlashSize*2048-33,33,pRead);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_Gpt_Download-->read gpt backup failed,RetCode(%d)"), iRet);
|
}
|
delete []pRead;
|
return false;
|
}
|
if (memcmp(m_gptBuffer + 34 * SECTOR_SIZE, pRead, 33 * SECTOR_SIZE) != 0)
|
{
|
if (m_pLog)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:RKA_Gpt_Download-->compare gpt backup failed"));
|
}
|
tchar szDateTime[100];
|
tstring strFile;
|
time_t now;
|
struct tm timeNow;
|
time(&now);
|
localtime_r(&now, &timeNow);
|
_stprintf(szDateTime, _T("%02d-%02d-%02d"), timeNow.tm_hour + 1, timeNow.tm_min + 1, timeNow.tm_sec + 1);
|
strFile = m_pLog->LogSavePath;
|
strFile += szDateTime;
|
strFile += _T("file.bin");
|
m_pLog->SaveBuffer(strFile, m_gptBuffer + 34 * SECTOR_SIZE, 33 * SECTOR_SIZE);
|
strFile = m_pLog->LogSavePath;
|
strFile += szDateTime;
|
strFile += _T("flash.bin");
|
m_pLog->SaveBuffer(strFile, pRead, 33 * SECTOR_SIZE);
|
}
|
delete []pRead;
|
return false;
|
}
|
currentByte += (SECTOR_SIZE * 67);
|
|
delete []pRead;
|
return true;
|
}
|
|
bool CRKAndroidDevice::MakeParamFileBuffer(STRUCT_RKIMAGE_ITEM &entry)
|
{
|
bool bRet;
|
UINT uiFileBufferSize;
|
DWORD dwFWOffset;
|
|
dwFWOffset = m_pImage->FWOffset;
|
uiFileBufferSize = 2 * entry.size;
|
m_uiParamFileSize = entry.size;
|
PBYTE pBuffer = NULL;
|
pBuffer = new BYTE[uiFileBufferSize];
|
if (!pBuffer)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeParamFileBuffer-->New memory failed"));
|
}
|
return false;
|
}
|
memset(pBuffer, 0, uiFileBufferSize);
|
bRet = m_pImage->GetData(dwFWOffset + entry.offset, entry.size, pBuffer);
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeParamFileBuffer-->GetFileData failed"));
|
}
|
delete[] pBuffer;
|
pBuffer = NULL;
|
return false;
|
}
|
//ÅжÏÊÇ·ñÒªÐÞ¸ÄParamterÎļþÄÚÈÝ,ÊÖ»úÉý¼¶ÐèÒª½«paramterÎļþÖеÄpartition²¿·ÖÊý¾Ý¸Ä³ÉÒÔ×Ö½ÚΪµ¥Î»½øÐÐÆ«ÒÆ
|
|
UINT uiParamSec;
|
if (m_uiParamFileSize % 512 == 0)
|
{
|
uiParamSec = m_uiParamFileSize / 512;
|
}
|
else
|
{
|
uiParamSec = (m_uiParamFileSize + 512) / 512;
|
}
|
|
if (m_paramBuffer)
|
{
|
delete []m_paramBuffer;
|
m_paramBuffer = NULL;
|
}
|
m_paramBuffer = new BYTE[uiParamSec * 512];
|
if (!m_paramBuffer)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:MakeParamFileBuffer-->new memory failed"));
|
}
|
delete []pBuffer;
|
return false;
|
}
|
memset(m_paramBuffer, 0, uiParamSec * 512);
|
memcpy(m_paramBuffer, pBuffer, m_uiParamFileSize);
|
delete []pBuffer;
|
return true;
|
}
|
bool CRKAndroidDevice::CheckParamPartSize(STRUCT_RKIMAGE_HDR &rkImageHead, int iParamPos)
|
{
|
// UINT uiParamPartSize;
|
// int i;
|
// uiParamPartSize = 0xFFFFFFFF;
|
// for (i=0;i<rkImageHead.item_count;i++)
|
// {
|
// if (i!=iParamPos)
|
// {
|
// if (rkImageHead.item[i].flash_offset<uiParamPartSize)
|
// {
|
// uiParamPartSize = rkImageHead.item[i].flash_offset;
|
// }
|
// }
|
// }
|
if (!GetParameterPartSize(rkImageHead.item[iParamPos]))
|
{
|
return false;
|
}
|
if (m_uiParamFileSize > rkImageHead.item[iParamPos].part_size / 8 * 512) //ÊÇ·ñÂú×ã´æ·Å8·Ý
|
{
|
return false;
|
}
|
|
return true;
|
}
|
bool CRKAndroidDevice::IsExistSector3Crc(PRKANDROID_IDB_SEC2 pSec)
|
{
|
if (!pSec)
|
{
|
return false;
|
}
|
|
if (strcmp(pSec->szCrcTag, "CRC") == 0)
|
{
|
m_bExistSector3Crc = true;
|
m_usSector3Crc = pSec->usSec3Crc;
|
}
|
return true;
|
}
|
bool CRKAndroidDevice::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(" "));
|
strLen.erase(strLen.find_last_not_of(" ") + 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(" "));
|
strOffset.erase(strOffset.find_last_not_of(" ") + 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(" "));
|
strName.erase(strName.find_last_not_of(" ") + 1);
|
|
return true;
|
}
|
bool CRKAndroidDevice::GetParameterPartSize(STRUCT_RKIMAGE_ITEM ¶mItem)
|
{
|
PBYTE pParamBuf = NULL;
|
pParamBuf = new BYTE[paramItem.size - 12 + 1];
|
if (!pParamBuf)
|
{
|
return false;
|
}
|
memset(pParamBuf, 0, paramItem.size - 12 + 1);
|
bool bRet;
|
bRet = m_pImage->GetData(m_pImage->FWOffset + paramItem.offset + 8, paramItem.size - 12, pParamBuf);
|
if (!bRet)
|
{
|
delete []pParamBuf;
|
return false;
|
}
|
string strParamFile = (char *)pParamBuf;
|
stringstream paramStream(strParamFile);
|
delete []pParamBuf;
|
|
string strLine, strPartition, strPartInfo, strPartName;
|
string::size_type line_size, pos, posColon, posComma;
|
UINT uiPartOffset, uiPartSize;
|
while (!paramStream.eof())
|
{
|
getline(paramStream, strLine);
|
line_size = strLine.size();
|
if (line_size <= 0)
|
{
|
continue;
|
}
|
if (strLine[line_size - 1] == '\r')
|
{
|
strLine = strLine.substr(0, line_size - 1);
|
}
|
if (strLine.size() <= 0)
|
{
|
continue;
|
}
|
if (strLine[0] == '#')
|
{
|
continue;
|
}
|
pos = strLine.find("mtdparts");
|
if (pos == string::npos)
|
{
|
continue;
|
}
|
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)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:GetParameterPartSize-->ParsePartitionInfo failed"));
|
}
|
return false;
|
}
|
paramItem.part_size = uiPartOffset;
|
return true;
|
}
|
}
|
return false;
|
}
|
|
bool CRKAndroidDevice::GetPublicKey(unsigned char *pKey, unsigned int &nKeySize)
|
{
|
int i, j, iRet, nRsaByte;
|
bool bRet;
|
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;
|
bRet = GetFlashInfo();
|
if (!bRet)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:GetPublicKey-->GetFlashInfo failed"));
|
}
|
return false;
|
}
|
if (!BuildBlockStateMap(0))
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:GetPublicKey-->BuildBlockStateMap failed"));
|
}
|
return false;
|
}
|
|
FindAllIDB();
|
// sleep(1);
|
// if (m_pLog)
|
// {
|
// m_pLog->Record(_T("INFO:GetPublicKey-->IDblock count=%d."),m_oldIDBCounts);
|
// }
|
if (m_oldIDBCounts <= 0)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:GetPublicKey-->IDblock count=%d."), m_oldIDBCounts);
|
}
|
return false;
|
}
|
for (i = 0; i < m_oldIDBCounts; i++)
|
{
|
iRet = m_pComm->RKU_ReadSector(m_idBlockOffset[i] * m_flashInfo.uiSectorPerBlock, 8, bData);
|
// sleep(1);
|
if (iRet != ERR_SUCCESS)
|
{
|
if (m_pLog)
|
{
|
m_pLog->Record(_T("ERROR:GetPublicKey-->RKU_ReadSector failed,RetCode(%d)"), iRet);
|
}
|
return false;
|
}
|
|
P_RC4(bData, SECTOR_SIZE);
|
|
if (pSec0->uiRc4Flag == 0)
|
{
|
// if (m_pLog)
|
// {
|
// m_pLog->PrintBuffer(strOutput,bData+4*512,512,16);
|
// m_pLog->Record("INFO:secure header\n%s",strOutput.c_str());
|
// }
|
for (j = 0; j < 4; j++)
|
{
|
P_RC4(bData + SECTOR_SIZE * (j + 4), SECTOR_SIZE);
|
}
|
// if (m_pLog)
|
// {
|
// m_pLog->PrintBuffer(strOutput,bData+4*512,512,16);
|
// m_pLog->Record("INFO:secure header rc4\n%s",strOutput.c_str());
|
// }
|
}
|
// if (m_pLog)
|
// {
|
// m_pLog->Record("INFO:secure header tag=0x%x",pSecureHdr->uiTag);
|
// }
|
if (pSecureHdr->uiTag == 0x4B415352)
|
{
|
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 (m_pLog)
|
// {
|
// m_pLog->PrintBuffer(strOutput,pKey,nKeySize,16);
|
// m_pLog->Record("INFO:Key\n%s",strOutput.c_str());
|
// }
|
return true;
|
}
|
|
}
|
|
return false;
|
}
|
|
bool CRKAndroidDevice::GetParameterGptFlag(STRUCT_RKIMAGE_ITEM ¶mItem)
|
{
|
PBYTE pParamBuf = NULL;
|
bool bGpt = false;
|
pParamBuf = new BYTE[paramItem.size - 12 + 1];
|
if (!pParamBuf)
|
{
|
return false;
|
}
|
memset(pParamBuf, 0, paramItem.size - 12 + 1);
|
bool bRet;
|
bRet = m_pImage->GetData(m_pImage->FWOffset + paramItem.offset + 8, paramItem.size - 12, pParamBuf);
|
if (!bRet)
|
{
|
delete []pParamBuf;
|
return false;
|
}
|
string strParamFile = (char *)pParamBuf;
|
stringstream paramStream(strParamFile);
|
delete []pParamBuf;
|
|
|
string strLine;
|
string::size_type pos, line_size;
|
while (!paramStream.eof())
|
{
|
getline(paramStream, strLine);
|
line_size = strLine.size();
|
if (line_size <= 0)
|
{
|
continue;
|
}
|
if (strLine[line_size - 1] == '\r')
|
{
|
strLine = strLine.substr(0, line_size - 1);
|
}
|
if (strLine.size() <= 0)
|
{
|
continue;
|
}
|
if (strLine[0] == '#')
|
{
|
continue;
|
}
|
transform(strLine.begin(), strLine.end(), strLine.begin(), (int(*)(int))toupper);
|
pos = strLine.find("TYPE");
|
if (pos == string::npos)
|
{
|
continue;
|
}
|
if ((pos = strLine.find("GPT")) != string::npos)
|
{
|
bGpt = true;
|
break;
|
}
|
else
|
{
|
continue;
|
}
|
}
|
return bGpt;
|
}
|
|
#define DO_CRC(x) crc = tab[ (crc ^ (x)) & 255 ] ^ (crc>>8)
|
unsigned int crc32_le(unsigned int crc, unsigned char *p, unsigned int len)
|
{
|
unsigned int *b = (unsigned int *)p;
|
unsigned int *tab = crc32table_le;
|
crc = crc ^ 0xFFFFFFFF;
|
if ((((long)b) & 3 && len))
|
{
|
do
|
{
|
unsigned char *p = (unsigned char *)b;
|
DO_CRC(*p++);
|
b = (unsigned int *)p;
|
} while ((--len) && ((long)b) & 3);
|
}
|
if ((len >= 4))
|
{
|
unsigned int save_len = len & 3;
|
len = len >> 2;
|
--b;
|
do
|
{
|
crc ^= *++b;
|
DO_CRC(0);
|
DO_CRC(0);
|
DO_CRC(0);
|
DO_CRC(0);
|
} while (--len);
|
b++;
|
len = save_len;
|
}
|
if (len)
|
{
|
do
|
{
|
unsigned char *p = (unsigned char *)b;
|
DO_CRC(*p++);
|
b = (unsigned int *)p;
|
} while (--len);
|
}
|
crc = crc ^ 0xFFFFFFFF;
|
return crc;
|
|
}
|
void prepare_gpt_backup(u8 *master, u8 *backup)
|
{
|
gpt_header *gptMasterHead = (gpt_header *)(master + SECTOR_SIZE);
|
gpt_header *gptBackupHead = (gpt_header *)(backup + 32 * SECTOR_SIZE);
|
u32 calc_crc32;
|
u64 val;
|
|
/* recalculate the values for the Backup GPT Header */
|
val = le64_to_cpu(gptMasterHead->my_lba);
|
gptBackupHead->my_lba = gptMasterHead->alternate_lba;
|
gptBackupHead->alternate_lba = cpu_to_le64(val);
|
gptBackupHead->partition_entry_lba = cpu_to_le64(le64_to_cpu(gptMasterHead->last_usable_lba) + 1);
|
gptBackupHead->header_crc32 = 0;
|
|
calc_crc32 = crc32_le(0, (unsigned char *)gptBackupHead, le32_to_cpu(gptBackupHead->header_size));
|
gptBackupHead->header_crc32 = cpu_to_le32(calc_crc32);
|
}
|
void gen_rand_uuid(unsigned char *uuid_bin)
|
{
|
efi_guid_t id;
|
unsigned int *ptr = (unsigned int *)&id;
|
unsigned int i;
|
|
/* Set all fields randomly */
|
for (i = 0; i < sizeof(id) / sizeof(*ptr); i++)
|
{
|
*(ptr + i) = cpu_to_be32(rand());
|
}
|
|
id.uuid.time_hi_and_version = (id.uuid.time_hi_and_version & 0x0FFF) | 0x4000;
|
id.uuid.clock_seq_hi_and_reserved = id.uuid.clock_seq_hi_and_reserved | 0x80;
|
|
memcpy(uuid_bin, id.raw, sizeof(id));
|
}
|
void create_gpt_buffer(u8 *gpt, PARAM_ITEM_VECTOR &vecParts, CONFIG_ITEM_VECTOR &vecUuid, u64 diskSectors)
|
{
|
legacy_mbr *mbr = (legacy_mbr *)gpt;
|
gpt_header *gptHead = (gpt_header *)(gpt + SECTOR_SIZE);
|
gpt_entry *gptEntry = (gpt_entry *)(gpt + 2 * SECTOR_SIZE);
|
u32 i, j;
|
int pos;
|
tstring strPartName;
|
string::size_type iPos;
|
/*1.protective mbr*/
|
memset(gpt, 0, SECTOR_SIZE);
|
mbr->signature = MSDOS_MBR_SIGNATURE;
|
mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT;
|
mbr->partition_record[0].start_sect = 1;
|
mbr->partition_record[0].nr_sects = (u32) - 1;
|
/*2.gpt header*/
|
memset(gpt + SECTOR_SIZE, 0, SECTOR_SIZE);
|
gptHead->signature = cpu_to_le64(GPT_HEADER_SIGNATURE);
|
gptHead->revision = cpu_to_le32(GPT_HEADER_REVISION_V1);
|
gptHead->header_size = cpu_to_le32(sizeof(gpt_header));
|
gptHead->my_lba = cpu_to_le64(1);
|
gptHead->alternate_lba = cpu_to_le64(diskSectors - 1);
|
gptHead->first_usable_lba = cpu_to_le64(34);
|
gptHead->last_usable_lba = cpu_to_le64(diskSectors - 34);
|
gptHead->partition_entry_lba = cpu_to_le64(2);
|
gptHead->num_partition_entries = cpu_to_le32(GPT_ENTRY_NUMBERS);
|
gptHead->sizeof_partition_entry = cpu_to_le32(GPT_ENTRY_SIZE);
|
gptHead->header_crc32 = 0;
|
gptHead->partition_entry_array_crc32 = 0;
|
gen_rand_uuid(gptHead->disk_guid.raw);
|
|
/*3.gpt partition entry*/
|
memset(gpt + 2 * SECTOR_SIZE, 0, 32 * SECTOR_SIZE);
|
for (i = 0; i < vecParts.size(); i++)
|
{
|
gen_rand_uuid(gptEntry->partition_type_guid.raw);
|
gen_rand_uuid(gptEntry->unique_partition_guid.raw);
|
gptEntry->starting_lba = cpu_to_le64(vecParts[i].uiItemOffset);
|
gptEntry->ending_lba = cpu_to_le64(gptEntry->starting_lba + vecParts[i].uiItemSize - 1);
|
gptEntry->attributes.raw = 0;
|
strPartName = vecParts[i].szItemName;
|
iPos = strPartName.find(_T(':'));
|
if (iPos != tstring::npos)
|
{
|
transform(strPartName.begin(), strPartName.end(), strPartName.begin(), (int(*)(int))tolower);
|
if (strPartName.find(_T("bootable")) != tstring::npos)
|
{
|
gptEntry->attributes.raw = PART_PROPERTY_BOOTABLE;
|
}
|
if (strPartName.find(_T("grow")) != tstring::npos)
|
{
|
gptEntry->ending_lba = cpu_to_le64(diskSectors - 34);
|
}
|
strPartName = strPartName.substr(0, iPos);
|
vecParts[i].szItemName[strPartName.size()] = 0;
|
}
|
for (j = 0; j < _tcslen(vecParts[i].szItemName); j++)
|
{
|
gptEntry->partition_name[j] = vecParts[i].szItemName[j];
|
}
|
if ((pos = find_uuid_item(vecUuid, vecParts[i].szItemName)) != -1)
|
{
|
memcpy(gptEntry->unique_partition_guid.raw, vecUuid[pos].szItemValue, 16);
|
}
|
gptEntry++;
|
}
|
|
gptHead->partition_entry_array_crc32 = cpu_to_le32(crc32_le(0, gpt + 2 * SECTOR_SIZE, GPT_ENTRY_SIZE * GPT_ENTRY_NUMBERS));
|
gptHead->header_crc32 = cpu_to_le32(crc32_le(0, gpt + SECTOR_SIZE, sizeof(gpt_header)));
|
|
}
|
bool ParseUuidInfo(string &strUuidInfo, string &strName, string &strUUid)
|
{
|
string::size_type pos(0);
|
|
if (strUuidInfo.size() <= 0)
|
{
|
return false;
|
}
|
pos = strUuidInfo.find('=');
|
if (pos == string::npos)
|
{
|
return false;
|
}
|
strName = strUuidInfo.substr(0, pos);
|
strName.erase(0, strName.find_first_not_of(" "));
|
strName.erase(strName.find_last_not_of(" ") + 1);
|
|
strUUid = strUuidInfo.substr(pos + 1);
|
strUUid.erase(0, strUUid.find_first_not_of(" "));
|
strUUid.erase(strUUid.find_last_not_of(" ") + 1);
|
|
while (true)
|
{
|
pos = 0;
|
if ((pos = strUUid.find("-")) != string::npos)
|
{
|
strUUid.replace(pos, 1, "");
|
}
|
else
|
{
|
break;
|
}
|
}
|
if (strUUid.size() != 32)
|
{
|
return false;
|
}
|
return true;
|
}
|
void string_to_uuid(string strUUid, char *uuid)
|
{
|
unsigned int i;
|
char value;
|
memset(uuid, 0, 16);
|
for (i = 0; i < strUUid.size(); i++)
|
{
|
value = 0;
|
if ((strUUid[i] >= '0') && (strUUid[i] <= '9'))
|
{
|
value = strUUid[i] - '0';
|
}
|
if ((strUUid[i] >= 'a') && (strUUid[i] <= 'f'))
|
{
|
value = strUUid[i] - 'a' + 10;
|
}
|
if ((strUUid[i] >= 'A') && (strUUid[i] <= 'F'))
|
{
|
value = strUUid[i] - 'A' + 10;
|
}
|
if ((i % 2) == 0)
|
{
|
uuid[i / 2] += (value << 4);
|
}
|
else
|
{
|
uuid[i / 2] += value;
|
}
|
}
|
unsigned int *p32;
|
unsigned short *p16;
|
p32 = (unsigned int *)uuid;
|
*p32 = cpu_to_be32(*p32);
|
p16 = (unsigned short *)(uuid + 4);
|
*p16 = cpu_to_be16(*p16);
|
p16 = (unsigned short *)(uuid + 6);
|
*p16 = cpu_to_be16(*p16);
|
}
|
bool get_uuid_from_parameter(char *pParameter, CONFIG_ITEM_VECTOR &vecItem)
|
{
|
stringstream paramStream(pParameter);
|
bool bRet;
|
string strLine, strUUid, strPartInfo, strPartName;
|
string::size_type line_size, pos, posColon, posComma;
|
STRUCT_CONFIG_ITEM uuid_item;
|
vecItem.clear();
|
while (!paramStream.eof())
|
{
|
getline(paramStream, strLine);
|
line_size = strLine.size();
|
if (line_size == 0)
|
{
|
continue;
|
}
|
if (strLine[line_size - 1] == '\r')
|
{
|
strLine = strLine.substr(0, line_size - 1);
|
}
|
pos = strLine.find("uuid:");
|
if (pos != string::npos)
|
{
|
strPartInfo = strLine.substr(pos + 5);
|
bRet = ParseUuidInfo(strPartInfo, strPartName, strUUid);
|
if (bRet)
|
{
|
strcpy(uuid_item.szItemName, strPartName.c_str());
|
string_to_uuid(strUUid, uuid_item.szItemValue);
|
vecItem.push_back(uuid_item);
|
}
|
}
|
}
|
return (vecItem.size() > 0);
|
}
|
int find_uuid_item(CONFIG_ITEM_VECTOR &vecItems, char *pszName)
|
{
|
unsigned int i;
|
for (i = 0; i < vecItems.size(); i++)
|
{
|
if (strcasecmp(pszName, vecItems[i].szItemName) == 0)
|
{
|
return i;
|
}
|
}
|
return -1;
|
}
|