2025-05-10 21:49:39 +08:00

411 lines
11 KiB
C++

#include "RKImage.h"
#include "MD5Checksum.h"
extern int IsRK3308_Platform();
extern int Compatible_rk3308bs_loader();
DWORD CRKImage::GetVersion()
{
return m_version;
}
DWORD CRKImage::GetMergeVersion()
{
return m_mergeVersion;
}
STRUCT_RKTIME CRKImage::GetReleaseTime()
{
return m_releaseTime;
}
ENUM_RKDEVICE_TYPE CRKImage::GetSupportDevice()
{
return m_supportDevice;
}
ENUM_OS_TYPE CRKImage::GetOsType()
{
UINT *pOsType;
pOsType = (UINT *)&m_reserved[4];
return (ENUM_OS_TYPE) * pOsType;
}
USHORT CRKImage::GetBackupSize()
{
USHORT *pBackupSize;
pBackupSize = (USHORT *)&m_reserved[12];
return *pBackupSize;
}
DWORD CRKImage::GetBootOffset()
{
return m_bootOffset;
}
DWORD CRKImage::GetBootSize()
{
return m_bootSize;
}
DWORD CRKImage::GetFWOffset()
{
return m_fwOffset;
}
long long CRKImage::GetFWSize()
{
return m_fwSize;
}
FILE *CRKImage::GetFWFileHandle()
{
return m_pFile;
}
char *CRKImage::GetFwPath()
{
return m_imgPath;
}
bool CRKImage::Md5Check(long long nCheckSize)
{
printf("In Md5Check\n");
tstring strNewMd5 = _T("");
strNewMd5 = CMD5Checksum::GetMD5(m_pFile, nCheckSize);
if (strNewMd5.size() == 32)
{
BYTE newMd5[32];
memcpy(newMd5, strNewMd5.c_str(), 32);
int i, j;
printf("New Md5:\n");
for (i = 0; i < 2; i++)
{
for (j = 0; j < 16; j++)
{
printf("%02X ", newMd5[i * 16 + j]);
}
printf("\r\n");
}
printf("Old Md5:\n");
for (i = 0; i < 2; i++)
{
for (j = 0; j < 16; j++)
{
printf("%02X ", m_md5[i * 16 + j]);
}
printf("\r\n");
}
if (memcmp(newMd5, m_md5, 32) != 0)
{
return false;
}
else
{
return true;
}
}
else
{
return false;
}
}
bool CRKImage::SaveBootFile(tstring filename)
{
FILE *file = NULL;
file = fopen(filename.c_str(), _T("wb+"));
if (!file)
{
return false;
}
BYTE buffer[1024];
DWORD dwBufferSize = 1024;
DWORD dwBootSize = m_bootSize;
DWORD dwReadSize;
fseek(m_pFile, m_bootOffset, SEEK_SET);
do
{
dwReadSize = (dwBootSize >= 1024) ? dwBufferSize : dwBootSize;
size_t ret = fread(buffer, 1, dwReadSize, m_pFile);
if (ret != dwReadSize)
{
printf("fread error: read:%d, req read:%d", ret, dwReadSize);
}
fwrite(buffer, 1, dwReadSize, file);
dwBootSize -= dwReadSize;
} while (dwBootSize > 0);
fclose(file);
return true;
}
bool CRKImage::SaveFWFile(tstring filename)
{
FILE *file = NULL;
file = fopen(filename.c_str(), _T("wb+"));
if (!file)
{
return false;
}
BYTE buffer[1024];
DWORD dwBufferSize = 1024;
long long dwFWSize = m_fwSize;
DWORD dwReadSize;
fseeko(m_pFile, m_fwOffset, SEEK_SET);
do
{
dwReadSize = (dwFWSize >= 1024) ? dwBufferSize : dwFWSize;
size_t ret = fread(buffer, 1, dwReadSize, m_pFile);
if (ret != dwReadSize)
{
printf("fread error: read:%d, req read:%d", ret, dwReadSize);
}
fwrite(buffer, 1, dwReadSize, file);
dwFWSize -= dwReadSize;
} while (dwFWSize > 0);
fclose(file);
return true;
}
bool CRKImage::GetData(long long dwOffset, DWORD dwSize, PBYTE lpBuffer)
{
if (dwOffset < 0 || dwSize == 0)
{
return false;
}
if (dwOffset + dwSize > m_fileSize)
{
return false;
}
fseeko64(m_pFile, dwOffset, SEEK_SET);
UINT uiActualRead;
uiActualRead = fread(lpBuffer, 1, dwSize, m_pFile);
if (dwSize != uiActualRead)
{
return false;
}
return true;
}
void CRKImage::GetReservedData(PBYTE &lpData, USHORT &usSize)
{
lpData = m_reserved;
usSize = IMAGE_RESERVED_SIZE;
}
int CRKImage::GetMd5Data(PBYTE &lpMd5, PBYTE &lpSignMd5)
{
lpMd5 = m_md5;
lpSignMd5 = m_signMd5;
return m_signMd5Size;
}
CRKImage::CRKImage(tstring filename, bool &bCheck)
{
Version.setContainer(this);
Version.getter(&CRKImage::GetVersion);
MergeVersion.setContainer(this);
MergeVersion.getter(&CRKImage::GetMergeVersion);
ReleaseTime.setContainer(this);
ReleaseTime.getter(&CRKImage::GetReleaseTime);
SupportDevice.setContainer(this);
SupportDevice.getter(&CRKImage::GetSupportDevice);
OsType.setContainer(this);
OsType.getter(&CRKImage::GetOsType);
BackupSize.setContainer(this);
BackupSize.getter(&CRKImage::GetBackupSize);
BootOffset.setContainer(this);
BootOffset.getter(&CRKImage::GetBootOffset);
BootSize.setContainer(this);
BootSize.getter(&CRKImage::GetBootSize);
FWOffset.setContainer(this);
FWOffset.getter(&CRKImage::GetFWOffset);
FWSize.setContainer(this);
FWSize.getter(&CRKImage::GetFWSize);
FwPath.setContainer(this);
FwPath.getter(&CRKImage::GetFwPath);
bool bDoMdb5Check = bCheck;
struct stat64 statBuf;
m_bootObject = NULL;
m_pFile = NULL;
m_signMd5Size = 0;
memset(m_md5, 0, 32);
memset(m_signMd5, 0, 256);
tchar szName[256];
_tcscpy(szName, filename.c_str());
if (stat64(szName, &statBuf) < 0)
{
bCheck = false;
printf("CRKImage : stat <%s> happen error.error_reason = %s\n", szName, strerror(errno));
return;
}
if (S_ISDIR(statBuf.st_mode))
{
bCheck = false;
printf("CRKImage : Error! stat mode is DIR\n");
return;
}
m_fileSize = statBuf.st_size;
memcpy(m_imgPath, szName, sizeof(szName));
bool bOnlyBootFile = false;
transform(filename.begin(), filename.end(), filename.begin(), (int(*)(int))tolower);
if (filename.find(_T(".bin")) != tstring::npos)
{
bOnlyBootFile = true;
}
m_pFile = fopen(szName, "rb");
if (!m_pFile)
{
bCheck = false;
printf("CRKImage : fopen <%s> fail,will try use fopen64 \n", szName);
m_pFile = fopen64(szName, "rb");
if (!m_pFile)
{
bCheck = false;
printf("CRKImage : fopen64 <%s> fail\n", szName);
return;
}
}
//code will be error if firmware is signed.md5 is not last 32 byte.
// fseeko(m_pFile,-32,SEEK_END);
// fread(m_md5,1,32,m_pFile);
// fseeko(m_pFile,0,SEEK_SET);
// if (!Md5Check())
// {
// bCheck = false;
// return;
// }
int nMd5DataSize;
long long ulFwSize;
STRUCT_RKIMAGE_HEAD imageHead;
if (!bOnlyBootFile)
{
fseeko64(m_pFile, 0, SEEK_SET);
size_t ret = fread((PBYTE)(&imageHead), 1, sizeof(STRUCT_RKIMAGE_HEAD), m_pFile);
if (ret != sizeof(STRUCT_RKIMAGE_HEAD))
{
return;
}
if (imageHead.uiTag != 0x57464B52)
{
bCheck = false;
printf("CRKImage :Error! imageHead.uiTag != 0x57464B52\n");
return;
}
if ((imageHead.reserved[14] == 'H') && (imageHead.reserved[15] == 'I'))
{
ulFwSize = *((DWORD *)(&imageHead.reserved[16]));
ulFwSize <<= 32;
ulFwSize += imageHead.dwFWOffset;
ulFwSize += imageHead.dwFWSize;
}
else
{
ulFwSize = imageHead.dwFWOffset + imageHead.dwFWSize;
}
nMd5DataSize = GetImageSize() - ulFwSize;
if (nMd5DataSize >= 160)
{
//sign image
m_bSignFlag = true;
m_signMd5Size = nMd5DataSize - 32;
fseeko64(m_pFile, ulFwSize, SEEK_SET);
size_t ret = fread(m_md5, 1, 32, m_pFile);
if (ret != 32)
{
printf("%s:read error\n", __func__);
}
ret = fread(m_signMd5, 1, nMd5DataSize - 32, m_pFile);
if (ret != nMd5DataSize - 32)
{
printf("%s :ret = %d\n", __func__, ret);
}
}
else
{
fseeko64(m_pFile, -32, SEEK_END);
size_t read = fread(m_md5, 1, 32, m_pFile);
if (read != 32)
{
printf("%s: read error\n", __func__);
}
}
if (bDoMdb5Check)
{
if (!Md5Check(ulFwSize))
{
printf("Md5Check update.img ulFwSize:%ld", ulFwSize);
//bCheck = false;
//return;
bCheck = true;
}
}
m_version = imageHead.dwVersion;
m_mergeVersion = imageHead.dwMergeVersion;
m_releaseTime.usYear = imageHead.stReleaseTime.usYear;
m_releaseTime.ucMonth = imageHead.stReleaseTime.ucMonth;
m_releaseTime.ucDay = imageHead.stReleaseTime.ucDay;
m_releaseTime.ucHour = imageHead.stReleaseTime.ucHour;
m_releaseTime.ucMinute = imageHead.stReleaseTime.ucMinute;
m_releaseTime.ucSecond = imageHead.stReleaseTime.ucSecond;
m_supportDevice = imageHead.emSupportChip;
m_bootOffset = imageHead.dwBootOffset;
m_bootSize = imageHead.dwBootSize;
m_fwOffset = imageHead.dwFWOffset;
m_fwSize = ulFwSize - m_fwOffset;
memcpy(m_reserved, imageHead.reserved, IMAGE_RESERVED_SIZE);
}
else
{
m_bootOffset = 0;
m_bootSize = m_fileSize;
}
PBYTE lpBoot;
lpBoot = new BYTE[m_bootSize];
fseeko64(m_pFile, m_bootOffset, SEEK_SET);
size_t ret = fread(lpBoot, 1, m_bootSize, m_pFile);
if (ret != m_bootSize)
{
printf("%s : read error\n", __func__);
}
bool bRet;
m_bootObject = new CRKBoot(lpBoot, m_bootSize, bRet);
if (!bRet)
{
bCheck = false;
printf("CRKImage :Error! new CRKBoot fail!\n");
return;
}
if (bOnlyBootFile)
{
m_supportDevice = m_bootObject->SupportDevice;
UINT *pOsType;
pOsType = (UINT *)&m_reserved[4];
*pOsType = (UINT)RK_OS;
fclose(m_pFile);
m_pFile = NULL;
}
bCheck = true;
}
CRKImage::~CRKImage()
{
if (m_pFile)
{
fclose(m_pFile);
m_pFile = NULL;
}
if (m_bootObject)
{
delete m_bootObject;
m_bootObject = NULL;
}
}
long long CRKImage::GetImageSize()
{
return m_fileSize;
}