rkdeveloptool/RKDevice.cpp

676 lines
17 KiB
C++
Raw Permalink Normal View History

/*
* (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd
* Seth Liu 2017.03.01
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include "RKDevice.h"
const char* szManufName[] =
{
"SAMSUNG",
"TOSHIBA",
"HYNIX",
"INFINEON",
"MICRON",
"RENESAS",
"ST",
"INTEL"
};
void CRKDevice::SetVendorID(USHORT value)
{
m_vid = value;
}
void CRKDevice::SetProductID(USHORT value)
{
m_pid = value;
}
void CRKDevice::SetDeviceType(ENUM_RKDEVICE_TYPE value)
{
m_device = value;
}
void CRKDevice::SetOsType(ENUM_OS_TYPE value)
{
m_os = value;
}
void CRKDevice::SetUsbType(ENUM_RKUSB_TYPE value)
{
m_usb = value;
}
void CRKDevice::SetBcdUsb(USHORT value)
{
m_bcdUsb = value;
}
void CRKDevice::SetLayerName(char *value)
{
strcpy(m_layerName,value);
}
void CRKDevice::SetLocationID(DWORD value)
{
m_locationID = value;
}
void CRKDevice::SetCallBackPointer(ProgressPromptCB value)
{
if (value)
{
m_callBackProc = value;
}
}
CRKLog* CRKDevice::GetLogObjectPointer()
{
return m_pLog;
}
CRKComm* CRKDevice::GetCommObjectPointer()
{
return m_pComm;
}
USHORT CRKDevice::GetVendorID()
{
return m_vid;
}
USHORT CRKDevice::GetProductID()
{
return m_pid;
}
ENUM_RKDEVICE_TYPE CRKDevice::GetDeviceType()
{
return m_device;
}
ENUM_OS_TYPE CRKDevice::GetOsType()
{
return m_os;
}
ENUM_RKUSB_TYPE CRKDevice::GetUsbType()
{
return m_usb;
}
USHORT CRKDevice::GetBcdUsb()
{
return m_bcdUsb;
}
DWORD CRKDevice::GetLocationID()
{
return m_locationID;
}
char* CRKDevice::GetLayerName()
{
return m_layerName;
}
string CRKDevice::GetLayerString(DWORD dwLocationID)
{
char szLocation[32] = "\0";
sprintf(szLocation, "%d-%d", dwLocationID >> 8, dwLocationID & 0xff);
return szLocation;
}
CRKDevice::CRKDevice(STRUCT_RKDEVICE_DESC &device)
{
VendorID.setContainer(this);
VendorID.getter(&CRKDevice::GetVendorID);
VendorID.setter(&CRKDevice::SetVendorID);
ProductID.setContainer(this);
ProductID.getter(&CRKDevice::GetProductID);
ProductID.setter(&CRKDevice::SetProductID);
DeviceType.setContainer(this);
DeviceType.getter(&CRKDevice::GetDeviceType);
DeviceType.setter(&CRKDevice::SetDeviceType);
UsbType.setContainer(this);
UsbType.getter(&CRKDevice::GetUsbType);
UsbType.setter(&CRKDevice::SetUsbType);
LayerName.setContainer(this);
LayerName.getter(&CRKDevice::GetLayerName);
LayerName.setter(&CRKDevice::SetLayerName);
BcdUsb.setContainer(this);
BcdUsb.getter(&CRKDevice::GetBcdUsb);
BcdUsb.setter(&CRKDevice::SetBcdUsb);
LocationID.setContainer(this);
LocationID.getter(&CRKDevice::GetLocationID);
LocationID.setter(&CRKDevice::SetLocationID);
OsType.setContainer(this);
OsType.getter(&CRKDevice::GetOsType);
OsType.setter(&CRKDevice::SetOsType);
LogObjectPointer.setContainer(this);
LogObjectPointer.getter(&CRKDevice::GetLogObjectPointer);
CommObjectPointer.setContainer(this);
CommObjectPointer.getter(&CRKDevice::GetCommObjectPointer);
CallBackPointer.setContainer(this);
CallBackPointer.setter(&CRKDevice::SetCallBackPointer);
m_vid = device.usVid;
m_pid = device.usPid;
m_usb = device.emUsbType;
m_device = device.emDeviceType;
m_bcdUsb = device.usbcdUsb;
m_locationID = device.uiLocationID;
strcpy(m_layerName, GetLayerString(m_locationID).c_str());
memset(m_flashInfo.blockState, 0, IDBLOCK_TOP);
m_flashInfo.usPhyBlokcPerIDB = 1;
m_flashInfo.uiSecNumPerIDB = 0;
m_callBackProc = NULL;
m_chipData = NULL;
m_pImage = NULL;
m_pLog = NULL;
m_pComm = NULL;
m_pFlashInfoData = NULL;
m_usFlashInfoDataLen = 0;
m_usFlashInfoDataOffset = 0;
m_bEmmc = false;
m_bDirectLba = false;
m_bFirst4mAccess = false;
}
CRKDevice::~CRKDevice()
{
if (m_pComm) {
delete m_pComm;
m_pComm = NULL;
}
if (m_chipData) {
delete []m_chipData;
m_chipData = NULL;
}
if (m_pFlashInfoData) {
delete []m_pFlashInfoData;
m_pFlashInfoData = NULL;
}
}
bool CRKDevice::SetObject(CRKImage *pImage, CRKComm *pComm, CRKLog *pLog)
{
if (!pComm) {
return false;
}
m_pImage = pImage;
m_pComm = pComm;
m_pLog = pLog;
if (m_pImage) {
m_os = m_pImage->OsType;
} else
m_os = RK_OS;
return true;
}
int CRKDevice::EraseEmmcBlock(UCHAR ucFlashCS, DWORD dwPos, DWORD dwCount)
{
int sectorOffset,nWrittenBlcok,iRet;
BYTE emptyData[4 * (SECTOR_SIZE+SPARE_SIZE)];
memset(emptyData, 0xff, 4 * (SECTOR_SIZE + SPARE_SIZE));
nWrittenBlcok = 0;
while (dwCount > 0) {
sectorOffset = (ucFlashCS * m_flashInfo.uiBlockNum + dwPos + nWrittenBlcok) * m_flashInfo.uiSectorPerBlock;
iRet = m_pComm->RKU_WriteSector(sectorOffset, 4, emptyData);
if ((iRet != ERR_SUCCESS) && (iRet != ERR_FOUND_BAD_BLOCK)) {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:EraseEmmcBlock-->RKU_WriteSector failed, RetCode(%d)", m_layerName, iRet);
}
return iRet;
}
dwCount--;
nWrittenBlcok++;
}
return ERR_SUCCESS;
}
int CRKDevice::EraseEmmcByWriteLBA(DWORD dwSectorPos, DWORD dwCount)
{
int nWritten,iRet;
BYTE emptyData[32 * SECTOR_SIZE];
memset(emptyData, 0xff, 32 * SECTOR_SIZE);
while (dwCount > 0) {
nWritten = (dwCount < 32) ? dwCount : 32;
iRet = m_pComm->RKU_WriteLBA(dwSectorPos, nWritten, emptyData);
if (iRet != ERR_SUCCESS) {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:EraseEmmcByWriteLBA-->RKU_WriteLBA failed, RetCode(%d)", m_layerName, iRet);
}
return iRet;
}
dwCount -= nWritten;
dwSectorPos += nWritten;
}
return ERR_SUCCESS;
}
bool CRKDevice::EraseEmmc()
{
UINT uiCount,uiEraseCount,uiSectorOffset,uiTotalCount;
UINT uiErase=1024*32;
int iRet=ERR_SUCCESS,iLoopTimes=0;
uiTotalCount = uiCount = m_flashInfo.uiFlashSize*2*1024;
uiSectorOffset = 0;
DWORD dwLayerID;
dwLayerID = m_locationID;
ENUM_CALL_STEP emCallStep = CALL_FIRST;
while (uiCount)
{
if (uiCount >= uiErase)
{
uiEraseCount = uiErase;
}
else
uiEraseCount = uiCount;
iRet = m_pComm->RKU_EraseLBA(uiSectorOffset, uiEraseCount);
if (iRet != ERR_SUCCESS) {
if (m_pLog) {
m_pLog->Record("ERROR:EraseEmmc-->RKU_EraseLBA failed,RetCode(%d),offset=0x%x,count=0x%x",iRet, uiSectorOffset, uiEraseCount);
}
return false;
}
uiCount -= uiEraseCount;
uiSectorOffset += uiEraseCount;
iLoopTimes++;
if (iLoopTimes % 8 == 0) {
if (m_callBackProc) {
m_callBackProc(dwLayerID, ERASEFLASH_PROGRESS, uiTotalCount, uiSectorOffset, emCallStep);
emCallStep = CALL_MIDDLE;
}
}
}
if (m_callBackProc) {
emCallStep = CALL_LAST;
m_callBackProc(dwLayerID, ERASEFLASH_PROGRESS, uiTotalCount, uiTotalCount, emCallStep);
}
return true;
}
bool CRKDevice::GetFlashInfo()
{
STRUCT_FLASHINFO_CMD info;
BYTE flashID[5];
int iRet;
UINT uiRead;
iRet = m_pComm->RKU_ReadFlashInfo((PBYTE)&info, &uiRead);
if( ERR_SUCCESS == iRet ) {
if ((info.usBlockSize == 0) || (info.bPageSize == 0)) {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:GetFlashInfo-->RKU_ReadFlashInfo failed,pagesize or blocksize is zero", m_layerName);
}
return false;
}
if (info.bManufCode <= 7) {
strcpy(m_flashInfo.szManufacturerName, szManufName[info.bManufCode]);
} else {
strcpy(m_flashInfo.szManufacturerName, "UNKNOWN");
}
m_flashInfo.uiFlashSize = info.uiFlashSize / 2 / 1024;
m_flashInfo.uiPageSize = info.bPageSize / 2;
m_flashInfo.usBlockSize = info.usBlockSize / 2;
m_flashInfo.bECCBits = info.bECCBits;
m_flashInfo.bAccessTime = info.bAccessTime;
m_flashInfo.uiBlockNum = m_flashInfo.uiFlashSize * 1024 / m_flashInfo.usBlockSize;
m_flashInfo.uiSectorPerBlock = info.usBlockSize;
m_flashInfo.bFlashCS = info.bFlashCS;
m_flashInfo.usValidSecPerBlock = (info.usBlockSize / info.bPageSize) * 4;
if (m_pFlashInfoData) {
delete []m_pFlashInfoData;
m_pFlashInfoData = NULL;
}
m_usFlashInfoDataLen = BYTE2SECTOR(uiRead);
m_pFlashInfoData = new BYTE[SECTOR_SIZE * m_usFlashInfoDataLen];
memset(m_pFlashInfoData, 0, SECTOR_SIZE * m_usFlashInfoDataLen);
memcpy(m_pFlashInfoData, (PBYTE)&info, uiRead);
if (m_pLog) {
string strFlashInfo;
m_pLog->PrintBuffer(strFlashInfo, m_pFlashInfoData, 11);
m_pLog->Record("<LAYER %s> INFO:FlashInfo:%s", m_layerName, strFlashInfo.c_str());
}
} else {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:GetFlashInfo-->RKU_ReadFlashInfo failed, RetCode(%d)", m_layerName, iRet);
}
return false;
}
iRet = m_pComm->RKU_ReadFlashID(flashID);
if( ERR_SUCCESS == iRet ) {
DWORD *pID = (DWORD *)flashID;
if (*pID==0x434d4d45)/*emmc*/ {
m_bEmmc = true;
} else
m_bEmmc = false;
} else {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:GetFlashInfo-->RKU_ReadFlashID failed, RetCode(%d)", m_layerName, iRet);
}
return false;
}
return true;
}
bool CRKDevice::TestDevice()
{
int iResult, iTryCount;
DWORD dwTotal, dwCurrent, dwLayerID;
dwLayerID = m_locationID;
ENUM_CALL_STEP emCallStep = CALL_FIRST;
do {
iTryCount = 3;
while (iTryCount > 0) {
iResult = m_pComm->RKU_TestDeviceReady(&dwTotal, &dwCurrent);
if ((iResult == ERR_SUCCESS) || (iResult == ERR_DEVICE_UNREADY)) {
break;
}
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:TestDevice-->RKU_TestDeviceReady failed, RetCode(%d)", m_layerName, iResult);
}
iTryCount--;
sleep(1);
}
if (iTryCount <= 0) {
return false;
}
if (iResult == ERR_SUCCESS) {
if (emCallStep == CALL_MIDDLE) {
if (m_callBackProc) {
dwCurrent = dwTotal;
emCallStep = CALL_LAST;
m_callBackProc(dwLayerID, TESTDEVICE_PROGRESS, dwTotal, dwCurrent, emCallStep);
}
}
break;
}
if (dwCurrent>dwTotal) {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:TestDevice-->RKU_TestDeviceReady failed,Total=%d, Current=%d", m_layerName, dwTotal, dwCurrent);
}
return false;
}
if (UsbType == RKUSB_LOADER) {
if (dwTotal == 0) {
if (m_pLog)
{
m_pLog->Record("<LAYER %s> ERROR:TestDevice-->RKU_TestDeviceReady failed, Total is zero", m_layerName);
}
return false;
}
}
if (m_callBackProc)
{
m_callBackProc(dwLayerID, TESTDEVICE_PROGRESS, dwTotal, dwCurrent, emCallStep);
emCallStep = CALL_MIDDLE;
}
sleep(1);
}while(iResult == ERR_DEVICE_UNREADY);
return true;
}
bool CRKDevice::ResetDevice()
{
int iRet;
iRet = m_pComm->RKU_ResetDevice();
if (iRet == ERR_SUCCESS) {
return true;
} else {
bool bRet = false;
if ((iRet == -2) || (iRet == -4)) {
bRet = true;
}
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:ResetDevice-->RKU_ResetDevice failed, RetCode(%d)", m_layerName, iRet);
}
return bRet;
}
}
bool CRKDevice::PowerOffDevice()
{
int iRet;
iRet = m_pComm->RKU_ResetDevice(RST_POWEROFF_SUBCODE);
if (iRet == ERR_SUCCESS) {
return true;
} else {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:PowerOffDevice-->RKU_ResetDevice failed, RetCode(%d)", m_layerName, iRet);
}
return false;
}
}
bool CRKDevice::CheckChip()
{
int iRet;
BYTE bChipInfo[CHIPINFO_LEN];
ENUM_RKDEVICE_TYPE curDeviceType = RKNONE_DEVICE;
memset(bChipInfo, 0, CHIPINFO_LEN);
iRet = m_pComm->RKU_ReadChipInfo(bChipInfo);
if (iRet == ERR_SUCCESS) {
if (!m_chipData) {
m_chipData = new BYTE[CHIPINFO_LEN];
}
memset(m_chipData, 0, CHIPINFO_LEN);
memcpy(m_chipData, bChipInfo, CHIPINFO_LEN);
DWORD *pValue;
pValue = (DWORD *)(&bChipInfo[0]);
if ((ENUM_RKDEVICE_TYPE)(*pValue) == m_device) {
return true;
}
if (*pValue == 0x524B3237) {
curDeviceType = RK27_DEVICE;
} else if (*pValue == 0x32373341) {
curDeviceType = RKCAYMAN_DEVICE;
} else if (*pValue == 0x524B3238) {
curDeviceType = RK28_DEVICE;
} else if (*pValue == 0x32383158) {
curDeviceType = RK281X_DEVICE;
} else if (*pValue == 0x32383242) {
curDeviceType = RKPANDA_DEVICE;
} else if (*pValue == 0x32393058) {
curDeviceType = RK29_DEVICE;
} else if (*pValue == 0x32393258) {
curDeviceType = RK292X_DEVICE;
} else if (*pValue == 0x33303041) {
curDeviceType = RK30_DEVICE;
} else if (*pValue == 0x33313041) {
curDeviceType = RK30B_DEVICE;
} else if (*pValue == 0x33313042) {
curDeviceType = RK31_DEVICE;
} else if (*pValue == 0x33323041) {
curDeviceType = RK32_DEVICE;
} else if (*pValue == 0x32363243) {
curDeviceType = RKSMART_DEVICE;
} else if (*pValue == 0x6E616E6F) {
curDeviceType = RKNANO_DEVICE;
} else if (*pValue == 0x4E4F5243) {
curDeviceType = RKCROWN_DEVICE;
}
if (curDeviceType == m_device){
return true;
} else {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:CheckChip-->Chip is not match, firmware(0x%x), device(0x%x)", m_layerName, m_device, *pValue);
}
return false;
}
}
else {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:CheckChip-->RKU_ReadChipInfo failed,RetCode(%d)", m_layerName, iRet);
}
return false;
}
}
int CRKDevice::DownloadBoot()
{
UCHAR i;
DWORD dwSize, dwDelay;
PBYTE pBuffer = NULL;
for ( i = 0; i < m_pImage->m_bootObject->Entry471Count; i++ ) {
if ( !m_pImage->m_bootObject->GetEntryProperty(ENTRY471, i, dwSize, dwDelay) ) {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:DownloadBoot-->GetEntry471Property failed,index(%d)", m_layerName, i);
}
return -2;
}
if (dwSize>0) {
pBuffer = new BYTE[dwSize];
if ( !m_pImage->m_bootObject->GetEntryData(ENTRY471, i, pBuffer) ) {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:DownloadBoot-->GetEntry471Data failed,index(%d)", m_layerName, i);
}
delete []pBuffer;
return -3;
}
if ( !Boot_VendorRequest(0x0471,pBuffer,dwSize) ) {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:DownloadBoot-->Boot_VendorRequest471 failed,index(%d)", m_layerName, i);
}
delete []pBuffer;
return -4;
}
delete []pBuffer;
pBuffer = NULL;
if (dwDelay>0) {
usleep(dwDelay * 1000);
}
}
}
for ( i=0; i < m_pImage->m_bootObject->Entry472Count; i++ ) {
if ( !m_pImage->m_bootObject->GetEntryProperty(ENTRY472, i, dwSize, dwDelay) ) {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:DownloadBoot-->GetEntry472Property failed,index(%d)", m_layerName, i);
}
return -2;
}
if (dwSize > 0) {
pBuffer = new BYTE[dwSize];
if ( !m_pImage->m_bootObject->GetEntryData(ENTRY472, i, pBuffer) ) {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:DownloadBoot-->GetEntry472Data failed,index(%d)", m_layerName, i);
}
delete []pBuffer;
return -3;
}
if ( !Boot_VendorRequest(0x0472, pBuffer, dwSize) ) {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:DownloadBoot-->Boot_VendorRequest472 failed,index(%d)", m_layerName, i);
}
delete []pBuffer;
return -4;
}
delete []pBuffer;
pBuffer = NULL;
if (dwDelay > 0) {
usleep(dwDelay * 1000);
}
}
}
sleep(1);
return 0;
}
bool CRKDevice::Boot_VendorRequest( DWORD requestCode, PBYTE pBuffer, DWORD dwDataSize)
{
int iRet;
iRet = m_pComm->RKU_DeviceRequest(requestCode, pBuffer, dwDataSize);
return (iRet == ERR_SUCCESS) ? true : false;
}
int CRKDevice::EraseAllBlocks(bool force_block_erase)
{
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++;
}
}
ReadCapability();
DWORD dwLayerID;
dwLayerID = LocationID;
ENUM_CALL_STEP emCallStep = CALL_FIRST;
if (!force_block_erase) {
if ((m_bEmmc)||(m_bDirectLba)) {
if (!EraseEmmc()) {
if (m_pLog) {
m_pLog->Record("<LAYER %s> ERROR:EraseAllBlocks-->EraseEmmc failed", m_layerName);
}
return -1;
}
return 0;
}
}
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;
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("<LAYER %s> ERROR:EraseAllBlocks-->RKU_EraseBlock failed,RetCode(%d)", m_layerName, iRet);
}
return -1;
}
iErasePos += iEraseBlockNum;
uiBlockCount -= iEraseBlockNum;
iEraseTimes++;
if (iEraseTimes % 8 == 0) {
if (m_callBackProc) {
m_callBackProc(dwLayerID, ERASEFLASH_PROGRESS, m_flashInfo.uiBlockNum * bCSCount, iCSIndex * m_flashInfo.uiBlockNum + iErasePos, emCallStep);
emCallStep = CALL_MIDDLE;
}
}
}
iCSIndex++;
}
}
if (m_callBackProc) {
emCallStep = CALL_LAST;
m_callBackProc(dwLayerID, ERASEFLASH_PROGRESS, m_flashInfo.uiBlockNum * bCSCount, iCSIndex * m_flashInfo.uiBlockNum, emCallStep);
}
return 0;
}
bool CRKDevice::ReadCapability()
{
int ret;
BYTE data[8];
ret = m_pComm->RKU_ReadCapability(data);
if (ret != ERR_SUCCESS)
{
if (m_pLog)
{
m_pLog->Record("ERROR:ReadCapability-->RKU_ReadCapability failed,err(%d)", ret);
}
return false;
}
if (data[0] & 0x1)
{
m_bDirectLba = true;
}
else
m_bDirectLba = false;
if (data[0] & 0x4)
{
m_bFirst4mAccess = true;
}
else
m_bFirst4mAccess = false;
return true;
}