/* * Copyright 2019 Rockchip Electronics Co., Ltd * Dayao Ji * * SPDX-License-Identifier: GPL-2.0+ */ #include "rkupdate/RKAndroidDevice.h" #define tole(x) (x) /*factor is 0xedb88320*/ bool CRKAndroidDevice::bGptFlag = 0; 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( ;iRKU_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[(int)i] = iIndex; m_oldIDBCounts++; iStart = iIndex+1; } return m_oldIDBCounts; } bool CRKAndroidDevice::ReserveIDBlock(char iBlockIndex,char iIdblockPos) { char i; CHAR iRet; for(i=iIdblockPos; iRecord(_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;im_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 ((m_oldSec3)) { 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;iRecord(_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;iRecord(_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; iRecord(_T("INFO:WriteIDBlock in")); } (void)bErase; //STRUCT_END_WRITE_SECTOR end_write_sector_data; //BYTE writeBuf[16*1024]; UINT uiOffset,uiTotal,uiBegin; //UINT uiBufferSize=16*1024; int iRet,i; uiTotal = dwSectorNum*SECTOR_SIZE; uiOffset = 0; uiBegin = 0; for(i=0;i<=4;i++) { iRet = m_pComm->RKU_WriteLBALoader(64+i*1024,dwSectorNum,lpIDBlock); if (iRet!=ERR_SUCCESS) { if (m_pLog) m_pLog->Record(_T("ERROR:WriteIDBlock-->RKU_WriteLBA failed!")); return -1; } } 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; for(i=0; i<8; i++) { if( m_flashInfo.bFlashCS&(1<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;iRecord(_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; } } 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); 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; } } int CRKAndroidDevice::DownloadImage() { long long dwFwOffset; bool bRet; dwFwOffset = m_pImage->FWOffset; STRUCT_RKIMAGE_HDR rkImageHead; STRUCT_RKIMAGE_ITEM *pDownloadItem; u_int8 headerData[64*1024]; u_int8* pHeaderData=headerData; int iHeadSize,iHeadMetaSize; iHeadSize = sizeof(STRUCT_RKIMAGE_HDR); char szPrompt[100]; 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.manufacturer[56]==0x55)&&(rkImageHead.manufacturer[57]==0x66)) { u_int16 *pItemRemain; pItemRemain = (u_int16 *)(&rkImageHead.manufacturer[58]); rkImageHead.item_count += *pItemRemain; } iHeadMetaSize = iHeadSize = sizeof(STRUCT_RKIMAGE_HDR)-sizeof(STRUCT_RKIMAGE_ITEM)*MAX_PACKAGE_FILES; iHeadSize += rkImageHead.item_count*sizeof(STRUCT_RKIMAGE_ITEM); iHeadSize = CALC_UNIT(iHeadSize, RK_PAGE_SIZE)*RK_PAGE_SIZE; bRet = m_pImage->GetData(dwFwOffset,iHeadSize,(u_int8*)pHeaderData); if ( !bRet ) { if (m_pLog) { m_pLog->Record("ERROR:DownloadImage-->GetData for header failed"); } return -1; } printf("DownloadImage rkImageHead.item_count=%d \n", rkImageHead.item_count); if ( rkImageHead.item_count<=0 ) { if (m_pLog) { m_pLog->Record(_T("ERROR:DownloadImage-->No Found item")); } return -2; } m_dwBackupOffset = 0xFFFFFFFF; int i; bool bFound=false,bFoundSystem=false,bFoundUserData=false; int iParamPos=-1; long long uiTotalSize=0; long long ulItemSize; UINT uiSparseFlag = 0; for ( i=0;iflash_offset!=0xFFFFFFFF ) { if ( strcmp(pDownloadItem->name,PARTNAME_PARAMETER)==0) { bFound = true; iParamPos = i; } else { if (strcmp(pDownloadItem->name,PARTNAME_SYSTEM)==0) { bFoundSystem = true; } if (strcmp(pDownloadItem->name,PARTNAME_USERDATA)==0) { bFoundUserData = true; } if (strcmp(pDownloadItem->name,PARTNAME_BACKUP)==0) { m_dwBackupOffset = pDownloadItem->flash_offset; } if (pDownloadItem->file[55]=='H') { ulItemSize = *((DWORD *)(&pDownloadItem->file[56])); ulItemSize <<= 32; ulItemSize += pDownloadItem->size; } if (IsSparseImage(*pDownloadItem)) { uiSparseFlag += (1<Record(_T("ERROR:DownloadImage-->get sparse size failed,file=%s"),pDownloadItem->name); } return -14; } } else ulItemSize = pDownloadItem->size; uiTotalSize += ulItemSize; } } } if ( !bFound ) { if (m_pLog) { m_pLog->Record(_T("ERROR:DownloadImage-->No Found Parameter file")); } return -3; } pDownloadItem = (STRUCT_RKIMAGE_ITEM *)(pHeaderData+iHeadMetaSize+iParamPos*sizeof(STRUCT_RKIMAGE_ITEM)); if (!MakeParamFileBuffer(*pDownloadItem)) { if (m_pLog) { m_pLog->Record(_T("ERROR:DownloadImage-->MakeParamFileBuffer failed")); } return -12; } GptFlag = GetParameterGptFlag(*pDownloadItem); bGptFlag = GptFlag; if (!GptFlag) { if (!CheckParamPartSize(pHeaderData+iHeadMetaSize,iParamPos,rkImageHead.item_count)) { 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); long long uiCurrentByte=0; for ( i=0;iflash_offset==0xFFFFFFFF ) { continue; } if (i==iParamPos) { if (m_pCallback) { sprintf(szPrompt,"%s writing... \n",pDownloadItem->name); m_pCallback(szPrompt); } if (GptFlag) { bRet = RKA_Gpt_Download(*pDownloadItem,uiCurrentByte,uiTotalSize); if ( !bRet ) { if (m_pLog) { m_pLog->Record(_T("ERROR:DownloadImage-->RKA_Gpt_Download failed")); m_pCallback("ERROR:DownloadImage-->RKA_Gpt_Download failed \n"); } return -4; } } else { bRet = RKA_Param_Download(*pDownloadItem,uiCurrentByte,uiTotalSize); if ( !bRet ) { if (m_pLog) { m_pLog->Record(_T(" ERROR:DownloadImage-->RKA_Param_Download failed")); m_pCallback("ERROR:DownloadImage-->RKA_Param_Download failed \n"); } // if(m_pCallback) // { // sprintf(szPrompt,"%s writing... failed",rkImageHead.item[i].name); // m_pCallback(szPrompt); // } return -4; } } } else { if (pDownloadItem->file[55]=='H') { ulItemSize = *((DWORD *)(&pDownloadItem->file[56])); ulItemSize <<= 32; ulItemSize += pDownloadItem->size; } else ulItemSize = pDownloadItem->size; if (ulItemSize>0) { if (m_pCallback) { sprintf(szPrompt,"%s writing... \n",pDownloadItem->name); m_pCallback(szPrompt); } if (uiSparseFlag & (1<Record(_T("ERROR:DownloadImage-->RKA_File_Download failed(%s)"),pDownloadItem->name); } m_pCallback("ERROR:DownloadImage-->RKA_File_Download failed(%s) \n",pDownloadItem->name); return -5; } } } } m_pComm->RKU_ReopenLBAHandle(); if (m_pProcessCallback) m_pProcessCallback(1,0); if (m_pProcessCallback) m_pProcessCallback(0.4,60); uiCurrentByte = 0; for ( i=0;iflash_offset==0xFFFFFFFF ) { continue; } if (i==iParamPos) { if (m_pCallback) { sprintf(szPrompt,"%s checking... \n",pDownloadItem->name); m_pCallback(szPrompt); } if (GptFlag) { bRet = RKA_Gpt_Check(*pDownloadItem,uiCurrentByte,uiTotalSize); if ( !bRet ) { if (m_pLog) { m_pLog->Record(_T("ERROR:DownloadImage-->RKA_Gpt_Check failed")); } m_pCallback("ERROR:DownloadImage-->RKA_Gpt_Check failed \n"); return -6; } } else { bRet = RKA_Param_Check(*pDownloadItem,uiCurrentByte,uiTotalSize); if ( !bRet ) { if (m_pLog) { m_pLog->Record(_T("ERROR:DownloadImage-->RKA_Param_Check failed")); } m_pCallback("ERROR:DownloadImage-->RKA_Param_Check failed \n"); return -6; } } } else { if (pDownloadItem->file[55]=='H') { ulItemSize = *((DWORD *)(&pDownloadItem->file[56])); ulItemSize <<= 32; ulItemSize += pDownloadItem->size; } else ulItemSize = pDownloadItem->size; if (ulItemSize>0) { if (m_pCallback) { sprintf(szPrompt,"%s checking... \n",pDownloadItem->name); m_pCallback(szPrompt); } if (uiSparseFlag & (1<Record(_T("ERROR:DownloadImage-->RKA_File_Check failed(%s)"),pDownloadItem->name); } m_pCallback("ERROR:DownloadImage-->RKA_File_Check failed(%s) \n",pDownloadItem->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() { #if 0 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 vecUpgradePartition; vecUpgradePartition.clear(); char szPrompt[100]; int iHeadSize; 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:UpgradePartition-->GetData failed")); } return -1; } if ( rkImageHead.item_count<=0 ) { if (m_pLog) { m_pLog->Record(_T("ERROR:UpgradePartition-->No Found item")); } return -2; } m_dwBackupOffset = 0xFFFFFFFF; int i; vector::iterator iter; bool bFound=false,bFoundSystem=false,bFoundUserData=false; int iParamPos=-1; long long uiTotalSize=0; long long ulItemSize; for ( i=0;irkImageHead.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) { bFound = true; iParamPos = i; } else { if (strcmp(rkImageHead.item[i].name,PARTNAME_SYSTEM)==0) { bFoundSystem = true; } if (strcmp(rkImageHead.item[i].name,PARTNAME_MISC)==0) { dwFlagSector = rkImageHead.item[i].flash_offset + rkImageHead.item[i].part_size -4; } if (strcmp(rkImageHead.item[i].name,PARTNAME_USERDATA)==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 ( !bFound ) { 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=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; #else return 0; #endif } 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<0) { iEraseBlockNum = (uiBlockCountRecord(_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;i0) { 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;iRKU_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 ( iFWOffset; 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 to download %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; while ( uifileBufferSize>0 ) { memset(pBuffer,0,uiBufferSize); if ( uifileBufferSizeGetData(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)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; m_pCallback("RKA_File_Download entry.name=%s DONE! \n", 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; (void)totalByte; m_pCallback("RKA_File_Check entry.name=%s \n", entry.name); 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 ( uifileBufferSizeRKU_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; } m_pCallback("RKA_File_Check entry.name=%s DONE! \n", entry.name); 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; (void)totalByte; 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 ( uiFileSizeRKU_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; (void)totalByte; 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 ( uiFileSizeRKU_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; (void)entry; (void)totalByte; 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); if (m_pLog) { m_pLog->Record(_T("INFO:RKA_Gpt_Download-->disk_sector=%u \n)"),m_flashInfo.uiFlashSize*2048); } 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, m_flashInfo.uiFlashSize*2048); 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; } if (m_pLog) { m_pLog->Record(_T("ERROR:RKA_Gpt_Download-->write gpt master successfully!")); } iRet = m_pComm->RKU_WriteLBA(m_flashInfo.uiFlashSize*2048-33,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); if (m_pLog) { m_pLog->Record(_T("ERROR:RKA_Gpt_Download-->write gpt backup also successfully!")); } 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; (void)entry; (void)totalByte; 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.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(u_int8* pItemBuffer,int iParamPos,int iItemCount) { #if 0 // UINT uiParamPartSize; // int i; // uiParamPartSize = 0xFFFFFFFF; // for (i=0;irkImageHead.item[iParamPos].part_size/8*512)//是否满足存放8份 { return false; } return true; #else u_int32 uiParamPartSize; STRUCT_RKIMAGE_ITEM *pItem; int i; uiParamPartSize = 0xFFFFFFFF; for (i=0;iflash_offsetflash_offset; } } } pItem = (STRUCT_RKIMAGE_ITEM *)(pItemBuffer + iParamPos*sizeof(STRUCT_RKIMAGE_ITEM)); if (!GetParameterPartSize(*pItem)) return false; if (m_uiParamFileSize > pItem->part_size/8*512) { return false; } return true; #endif } 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;iRKU_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;jnFactor[nRsaByte-j-1]; for(j=0;jeFactor[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; } long long CRKAndroidDevice::GetSparseImageSize(STRUCT_RKIMAGE_ITEM &entry) { bool bRet; sparse_header header; DWORD dwFWOffset; long long ulEntryStartOffset; 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; } bRet = m_pImage->GetData(ulEntryStartOffset,sizeof(header),(PBYTE)&header); if (!bRet) { if (m_pLog) { m_pLog->Record(_T("ERROR:IsSparseImage-->getdata failed")); } return -1; } return header.blk_sz * header.total_blks; } bool CRKAndroidDevice::IsSparseImage(STRUCT_RKIMAGE_ITEM &entry) { bool bRet; sparse_header header; DWORD dwFWOffset; long long ulEntryStartOffset; 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; } bRet = m_pImage->GetData(ulEntryStartOffset,sizeof(header),(PBYTE)&header); if (!bRet) { if (m_pLog) { m_pLog->Record(_T("ERROR:IsSparseImage-->getdata failed")); } return false; } if (header.magic!=SPARSE_HEADER_MAGIC) { return false; } return true; } int CRKAndroidDevice:: getEmmc() { char bootmode[256]; int result = 0; property_get("ro.boot.mode", bootmode, "unknown"); printf("bootmode = %s \n", bootmode); if(!strcmp(bootmode, "nvme")) { result = 2; } else if(!strcmp(bootmode, "emmc")) { result = 1; }else { result = 0; } return result; } bool CRKAndroidDevice::ErasePartition_discard(STRUCT_RKIMAGE_ITEM &entry) { u64 uifileBufferSize; int iRet; uifileBufferSize = entry.part_size * SECTOR_SIZE; m_pCallback("INFO:ErasePartition %s,offset=0x%x,size=%llu, part_size=0x%x \n", entry.name, entry.flash_offset, uifileBufferSize, entry.part_size); iRet = m_pComm->RKU_EraseBlock_discard(entry.flash_offset, entry.part_size); if( iRet!=ERR_SUCCESS ){ printf("erase block fail\n"); return false; } return true; } bool CRKAndroidDevice::ErasePartition(STRUCT_RKIMAGE_ITEM &entry) { UINT uiLBATransferSize=(LBA_TRANSFER_SIZE)*m_uiLBATimes; UINT uiLBASector = uiLBATransferSize/SECTOR_SIZE; int iRet; UINT uiBufferSize=uiLBATransferSize; u64 uifileBufferSize; BYTE byRWMethod=RWMETHOD_IMAGE; uifileBufferSize = entry.part_size * SECTOR_SIZE; if (m_pLog) { m_pLog->Record(_T(" INFO:ErasePartition %s,offset=0x%x,size=%llu, part_size=0x%x"),entry.name,entry.flash_offset,uifileBufferSize, entry.part_size); } m_pCallback("INFO:ErasePartition %s,offset=0x%x,size=%llu, part_size=0x%x \n",entry.name,entry.flash_offset,uifileBufferSize, entry.part_size); PBYTE pBuffer=NULL; pBuffer = new BYTE[uiBufferSize]; if (!pBuffer) { if (m_pLog) { m_pLog->Record(_T("ERROR:ErasePartition-->New memory failed")); } m_pCallback("ERROR:ErasePartition-->New memory failed \n"); return false; } UINT uiBegin,uiLen,uiWriteByte; long long uiEntryOffset; uiBegin = entry.flash_offset; uiLen = 0;uiWriteByte = 0;uiEntryOffset=0; while ( uifileBufferSize>0 ) { memset(pBuffer,0,uiBufferSize); if ( uifileBufferSizeRKU_WriteLBA(uiBegin,uiLen,pBuffer,byRWMethod); if( iRet!=ERR_SUCCESS ) { if (m_pLog) { m_pLog->Record(_T("ERROR:ErasePartition-->RKU_WriteLBA failed,Written(%d),RetCode(%d)"),uiEntryOffset,iRet); } m_pCallback("ERROR:ErasePartition-->RKU_WriteLBA failed,Written(%d),RetCode(%d) \n",uiEntryOffset,iRet); delete []pBuffer; pBuffer = NULL; return false; } uifileBufferSize -= uiWriteByte; uiEntryOffset += uiWriteByte; uiBegin += uiLen; } delete []pBuffer; pBuffer = NULL; return true; } bool CRKAndroidDevice::EraseSparseRegion(const char* volume,const char* directory) { #if 0 //bool bSuccess = true; //if volume is system.then set volume is "",because system as root if(strcmp("/system", volume) == 0) volume = "/"; printf("EraseSparseRegion volume is %s\n",volume); if(format_volume(volume, directory) == 0){ printf("EraseSparseRegion format_volume is ok!!!\n"); return true; }else{ printf("EraseSparseRegion format_volume is failed!!!\n"); return false; } #else (void)volume; (void)directory; if (m_pLog) { m_pLog->Record(_T(" INFO:EraseSparseRegion is deprecated, shall not be here! \n")); } m_pCallback("INFO:EraseSparseRegion is deprecated, shall not be here! \n"); return false; #endif } bool CRKAndroidDevice::RKA_SparseFile_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,i; bool bRet; UINT uiBufferSize=uiLBATransferSize; long long uifileBufferSize; DWORD dwFWOffset; long long ulEntryStartOffset; sparse_header header; chunk_header chunk; //dwLayerID = GetLayerID(); (void)totalByte; m_pCallback("RKA_SparseFile_Download entry.name=%s \n", entry.name); 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; //get sparse header bRet = m_pImage->GetData(ulEntryStartOffset,sizeof(header),(PBYTE)&header); if (!bRet) { if (m_pLog) { m_pLog->Record(_T("ERROR:RKA_SparseFile_Download-->get sparse header failed,partition=%s"),entry.name); m_pCallback("ERROR:RKA_SparseFile_Download-->get sparse header failed,partition=%s \n",entry.name); } return false; } uifileBufferSize = header.blk_sz * header.total_blks; if (m_pLog) { m_pLog->Record(_T("INFO:Start to download %s,offset=0x%x,size=%llu"),entry.name,entry.flash_offset,uifileBufferSize); m_pCallback("INFO:Start to download %s,offset=0x%x,size=%llu \n",entry.name,entry.flash_offset,uifileBufferSize); } //erase system partition #if 0 if ( !strcmp(entry.name, "system") && !EraseSparseRegion("/system",NULL)) { if (m_pLog) { m_pLog->Record(_T(" ERROR:RKA_SparseFile_Download-->EraseSparseRegion failed")); } return false; } #else if(m_pComm->m_bEmmc == 1) { if(!ErasePartition_discard(entry)) { if (m_pLog) { m_pLog->Record(_T(" ERROR:RKA_SparseFile_Download-->ErasePartition_discard failed")); } m_pCallback("ERROR:RKA_SparseFile_Download-->ErasePartition_discard failed \n"); return false; } } else { if(!ErasePartition(entry)) { if (m_pLog) { m_pLog->Record(_T(" ERROR:RKA_SparseFile_Download-->ErasePartition failed")); } m_pCallback("ERROR:RKA_SparseFile_Download-->ErasePartition failed \n"); return false; } } #endif 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_SparseFile_Download-->New memory failed")); } m_pCallback("ERROR:RKA_SparseFile_Download-->New memory failed \n"); return false; } UINT uiBegin,uiLen,uiWriteByte,uiCurChunk,uiChunkDataSize,uiFillByte,uiCrc; long long uiEntryOffset; uiCurChunk = 0; uiBegin = entry.flash_offset; uiLen = 0;uiWriteByte = 0;uiEntryOffset=sizeof(header); m_pCallback("INFO:RKA_SparseFile_Download-->total_chunks=%u \n", header.total_chunks); while ( uiCurChunkGetData(ulEntryStartOffset+uiEntryOffset,sizeof(chunk),(PBYTE)&chunk); if (!bRet) { if (m_pLog) { m_pLog->Record(_T(" ERROR:RKA_SparseFile_Download-->get sparse chunk failed")); } m_pCallback("ERROR:RKA_SparseFile_Download-->get sparse chunk failed \n"); delete []pBuffer; pBuffer = NULL; return false; } uiCurChunk++; uiEntryOffset += sizeof(chunk); switch (chunk.chunk_type) { case CHUNK_TYPE_RAW: uiChunkDataSize = chunk.total_sz - sizeof(chunk_header); while (uiChunkDataSize) { memset(pBuffer,0,uiBufferSize); if ( uiChunkDataSizeGetData(ulEntryStartOffset+uiEntryOffset,uiWriteByte,pBuffer)) { if (m_pLog) { m_pLog->Record(_T("ERROR:RKA_SparseFile_Download-->get chunk data failed,chunk=%d"),uiCurChunk); } m_pCallback("ERROR:RKA_SparseFile_Download-->get chunk data failed,chunk=%d \n",uiCurChunk); delete []pBuffer; pBuffer = NULL; return false; } uiEntryOffset += uiWriteByte; iRet = m_pComm->RKU_WriteLBA(uiBegin,uiLen,pBuffer,byRWMethod); if( iRet!=ERR_SUCCESS ) { if (m_pLog) { m_pLog->Record(_T("ERROR:RKA_SparseFile_Download-->RKU_WriteLBA failed,RetCode(%d),chunk=%d"),iRet,uiCurChunk); } m_pCallback("ERROR:RKA_SparseFile_Download-->RKU_WriteLBA failed,RetCode(%d),chunk=%d \n",iRet,uiCurChunk); delete []pBuffer; pBuffer = NULL; return false; } uiBegin += uiLen; currentByte += uiWriteByte; uiChunkDataSize -= uiWriteByte; } break; case CHUNK_TYPE_FILL: uiChunkDataSize = chunk.chunk_sz * header.blk_sz; if (!m_pImage->GetData(ulEntryStartOffset+uiEntryOffset,4,(PBYTE)&uiFillByte)) { if (m_pLog) { m_pLog->Record(_T("ERROR:RKA_SparseFile_Download-->get fill byte failed,chunk=%d"),uiCurChunk); } m_pCallback("ERROR:RKA_SparseFile_Download-->get fill byte failed,chunk=%d \n",uiCurChunk); delete []pBuffer; pBuffer = NULL; return false; } uiEntryOffset += 4; while (uiChunkDataSize) { memset(pBuffer,0,uiBufferSize); if ( uiChunkDataSizeRKU_WriteLBA(uiBegin,uiLen,pBuffer,byRWMethod); if( iRet!=ERR_SUCCESS ) { if (m_pLog) { m_pLog->Record(_T(" ERROR:RKA_SparseFile_Download-->RKU_WriteLBA failed,RetCode(%d),chunk=%d"),iRet,uiCurChunk); } m_pCallback("ERROR:RKA_SparseFile_Download-->RKU_WriteLBA failed,RetCode(%d),chunk=%d \n",iRet,uiCurChunk); delete []pBuffer; pBuffer = NULL; return false; } uiBegin += uiLen; currentByte += uiWriteByte; uiChunkDataSize -= uiWriteByte; } break; case CHUNK_TYPE_DONT_CARE: uiChunkDataSize = chunk.chunk_sz * header.blk_sz; currentByte += uiChunkDataSize; uiLen = ( (uiChunkDataSize%SECTOR_SIZE==0) ? (uiChunkDataSize/SECTOR_SIZE) : (uiChunkDataSize/SECTOR_SIZE+1) ); uiBegin += uiLen; break; case CHUNK_TYPE_CRC32: bRet = m_pImage->GetData(ulEntryStartOffset+uiEntryOffset,4,(PBYTE)&uiCrc); uiEntryOffset += 4; break; } } delete []pBuffer; pBuffer = NULL; m_pCallback("RKA_SparseFile_Download entry.name=%s DONE! \n", entry.name); return true; } bool CRKAndroidDevice::RKA_SparseFile_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,i; bool bRet; UINT uiBufferSize=uiLBATransferSize; long long uifileBufferSize; DWORD dwFWOffset; long long ulEntryStartOffset; sparse_header header; chunk_header chunk; (void)totalByte; m_pCallback("RKA_SparseFile_Check entry.name=%s \n", entry.name); 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; //get sparse header bRet = m_pImage->GetData(ulEntryStartOffset,sizeof(header),(PBYTE)&header); if (!bRet) { if (m_pLog) { m_pLog->Record(_T(" ERROR:RKA_SparseFile_Check-->get sparse header failed,partition=%s"),entry.name); } m_pCallback("ERROR:RKA_SparseFile_Check-->get sparse header failed,partition=%s \n",entry.name); return false; } uifileBufferSize = header.blk_sz * header.total_blks; if (m_pLog) { m_pLog->Record(_T("INFO:Start to check %s,offset=0x%x,size=%I64u"),entry.name,entry.flash_offset,uifileBufferSize); } m_pCallback("INFO:Start to check %s,offset=0x%x,size=%I64u \n",entry.name,entry.flash_offset,uifileBufferSize); 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_SparseFile_Check-->New memory failed")); } m_pCallback("ERROR:RKA_SparseFile_Check-->New memory failed \n"); return false; } PBYTE pBufferFromFlash=NULL; pBufferFromFlash = new BYTE[uiBufferSize]; if (!pBufferFromFlash) { if (m_pLog) { m_pLog->Record(_T("ERROR:RKA_SparseFile_Check-->New memory failed")); } m_pCallback("ERROR:RKA_SparseFile_Check-->New memory failed \n"); delete []pBufferFromFile; return false; } UINT uiBegin,uiLen,uiWriteByte,uiCurChunk,uiChunkDataSize,uiFillByte,uiCrc; long long uiEntryOffset; uiBegin = entry.flash_offset; uiCurChunk = 0; uiLen = 0;uiWriteByte = 0;uiEntryOffset=sizeof(header); while ( uiCurChunkGetData(ulEntryStartOffset+uiEntryOffset,sizeof(chunk),(PBYTE)&chunk); if (!bRet) { if (m_pLog) { m_pLog->Record(_T("ERROR:RKA_SparseFile_Check-->get sparse chunk failed")); } m_pCallback("ERROR:RKA_SparseFile_Check-->get sparse chunk failed \n"); delete []pBufferFromFile; delete []pBufferFromFlash; return false; } uiCurChunk++; uiEntryOffset += sizeof(chunk); switch (chunk.chunk_type) { case CHUNK_TYPE_RAW: uiChunkDataSize = chunk.total_sz - sizeof(chunk_header); while (uiChunkDataSize) { if ( uiChunkDataSizeGetData(ulEntryStartOffset+uiEntryOffset,uiWriteByte,pBufferFromFile)) { if (m_pLog) { m_pLog->Record(_T("ERROR:RKA_SparseFile_Check-->get chunk data failed,chunk=%d"),uiCurChunk); } m_pCallback("ERROR:RKA_SparseFile_Check-->get chunk data failed,chunk=%d \n",uiCurChunk); delete []pBufferFromFile; delete []pBufferFromFlash; return false; } uiEntryOffset += uiWriteByte; iRet = m_pComm->RKU_ReadLBA(uiBegin,uiLen,pBufferFromFlash,byRWMethod); if( iRet!=ERR_SUCCESS ) { if (m_pLog) { m_pLog->Record(_T(" ERROR:RKA_SparseFile_Check-->RKU_ReadLBA failed,RetCode(%d),chunk=%d"),iRet,uiCurChunk); } m_pCallback("ERROR:RKA_SparseFile_Check-->RKU_ReadLBA failed,RetCode(%d),chunk=%d \n",iRet,uiCurChunk); delete []pBufferFromFile; delete []pBufferFromFlash; return false; } if ( memcmp(pBufferFromFile,pBufferFromFlash,uiWriteByte)!=0 ) { if (m_pLog) { m_pLog->Record(_T(" ERROR:RKA_SparseFile_Check-->Memcmp failed,chunk=%d uiBegin=0x%x \n"),uiCurChunk, uiBegin); } m_pCallback("ERROR:RKA_SparseFile_Check-->Memcmp failed,chunk=%d uiBegin=0x%x\n",uiCurChunk, uiBegin); if (m_pLog) { 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 = m_pLog->LogSavePath; strFile += szDateTime; strFile += _T("file.bin"); m_pLog->SaveBuffer( strFile,pBufferFromFile,uiWriteByte ); //strFile = m_pLog->LogSavePath; strFile += szDateTime; strFile += _T("flash.bin"); m_pLog->SaveBuffer( strFile,pBufferFromFlash,uiWriteByte ); } delete []pBufferFromFile; delete []pBufferFromFlash; return false; } currentByte += uiWriteByte; uiChunkDataSize -= uiWriteByte; uiBegin += uiLen; } break; case CHUNK_TYPE_FILL: uiChunkDataSize = chunk.chunk_sz * header.blk_sz; if (!m_pImage->GetData(ulEntryStartOffset+uiEntryOffset,4,(PBYTE)&uiFillByte)) { if (m_pLog) { m_pLog->Record(_T(" ERROR:RKA_SparseFile_Check-->get fill byte failed,chunk=%d"),uiCurChunk); } m_pCallback("ERROR:RKA_SparseFile_Check-->get fill byte failed,chunk=%d \n",uiCurChunk); delete []pBufferFromFile; delete []pBufferFromFlash; return false; } uiEntryOffset += 4; while (uiChunkDataSize) { if ( uiChunkDataSizeRKU_ReadLBA(uiBegin,uiLen,pBufferFromFlash,byRWMethod); if( iRet!=ERR_SUCCESS ) { if (m_pLog) { m_pLog->Record(_T(" ERROR:RKA_SparseFile_Check-->RKU_ReadLBA failed,RetCode(%d),chunk=%d"),iRet,uiCurChunk); } m_pCallback("ERROR:RKA_SparseFile_Check-->RKU_ReadLBA failed,RetCode(%d),chunk=%d \n",iRet,uiCurChunk); delete []pBufferFromFile; delete []pBufferFromFlash; return false; } if ( memcmp(pBufferFromFile,pBufferFromFlash,uiWriteByte)!=0 ) { if (m_pLog) { m_pLog->Record(_T(" ERROR:RKA_SparseFile_Check-->Memcmp failed,chunk=%d uiBegin=%0x%x"),uiCurChunk, uiBegin); } m_pCallback("ERROR:RKA_SparseFile_Check-->Memcmp failed,chunk=%d uiBegin=%0x%x",uiCurChunk, uiBegin); if (m_pLog) { 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 = m_pLog->LogSavePath; strFile += szDateTime; strFile += _T("file.bin"); m_pLog->SaveBuffer( strFile,pBufferFromFile,uiWriteByte ); //strFile = m_pLog->LogSavePath; strFile += szDateTime; strFile += _T("flash.bin"); m_pLog->SaveBuffer( strFile,pBufferFromFlash,uiWriteByte ); } delete []pBufferFromFile; delete []pBufferFromFlash; return false; } currentByte += uiWriteByte; uiChunkDataSize -= uiWriteByte; uiBegin += uiLen; } break; case CHUNK_TYPE_DONT_CARE: uiChunkDataSize = chunk.chunk_sz * header.blk_sz; currentByte += uiChunkDataSize; uiLen = ( (uiChunkDataSize%SECTOR_SIZE==0) ? (uiChunkDataSize/SECTOR_SIZE) : (uiChunkDataSize/SECTOR_SIZE+1) ); uiBegin += uiLen; break; case CHUNK_TYPE_CRC32: bRet = m_pImage->GetData(ulEntryStartOffset+uiEntryOffset,4,(PBYTE)&uiCrc); uiEntryOffset += 4; break; } } delete []pBufferFromFile; delete []pBufferFromFlash; m_pCallback("RKA_SparseFile_Check entry.name=%s Done! \n", entry.name); return true; } 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, u64 diskSectors) { gpt_header *gptBackupHead = (gpt_header *)(backup + 32 * SECTOR_SIZE); u32 calc_crc32; (void)master; /* recalculate the values for the Backup GPT Header */ gptBackupHead->my_lba = cpu_to_le64(diskSectors - 1); gptBackupHead->alternate_lba = cpu_to_le64(1); gptBackupHead->partition_entry_lba = cpu_to_le64(diskSectors - 34 + 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,backup_gpt_secs; tstring strPartName; string::size_type iPos; if (diskSectors>=0x800000) { backup_gpt_secs = 64; } else{ backup_gpt_secs = 33; } printf("create_gpt_buffer backup_gpt_secs=%d\n", backup_gpt_secs); /*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 - backup_gpt_secs -1); 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; 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; }