176af099aSliuyi /* 276af099aSliuyi * (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd 376af099aSliuyi * Seth Liu 2017.03.01 476af099aSliuyi * 576af099aSliuyi * SPDX-License-Identifier: GPL-2.0+ 676af099aSliuyi */ 776af099aSliuyi #include "RKImage.h" 876af099aSliuyi 9*21b25fd4SDave Murphy UINT CRKImage::GetVersion() 1076af099aSliuyi { 1176af099aSliuyi return m_version; 1276af099aSliuyi } 13*21b25fd4SDave Murphy UINT CRKImage::GetMergeVersion() 1476af099aSliuyi { 1576af099aSliuyi return m_mergeVersion; 1676af099aSliuyi } 1776af099aSliuyi STRUCT_RKTIME CRKImage::GetReleaseTime() 1876af099aSliuyi { 1976af099aSliuyi return m_releaseTime; 2076af099aSliuyi } 2176af099aSliuyi ENUM_RKDEVICE_TYPE CRKImage::GetSupportDevice() 2276af099aSliuyi { 2376af099aSliuyi return m_supportDevice; 2476af099aSliuyi } 2576af099aSliuyi ENUM_OS_TYPE CRKImage::GetOsType() 2676af099aSliuyi { 2776af099aSliuyi UINT *pOsType; 2876af099aSliuyi pOsType = (UINT *)&m_reserved[4]; 2976af099aSliuyi return (ENUM_OS_TYPE)*pOsType; 3076af099aSliuyi } 3176af099aSliuyi 3276af099aSliuyi USHORT CRKImage::GetBackupSize() 3376af099aSliuyi { 3476af099aSliuyi USHORT *pBackupSize; 3576af099aSliuyi pBackupSize = (USHORT *)&m_reserved[12]; 3676af099aSliuyi return *pBackupSize; 3776af099aSliuyi } 38*21b25fd4SDave Murphy UINT CRKImage::GetBootOffset() 3976af099aSliuyi { 4076af099aSliuyi return m_bootOffset; 4176af099aSliuyi } 42*21b25fd4SDave Murphy UINT CRKImage::GetBootSize() 4376af099aSliuyi { 4476af099aSliuyi return m_bootSize; 4576af099aSliuyi } 46*21b25fd4SDave Murphy UINT CRKImage::GetFWOffset() 4776af099aSliuyi { 4876af099aSliuyi return m_fwOffset; 4976af099aSliuyi } 5076af099aSliuyi long long CRKImage::GetFWSize() 5176af099aSliuyi { 5276af099aSliuyi return m_fwSize; 5376af099aSliuyi } 5476af099aSliuyi bool CRKImage::SaveBootFile(string filename) 5576af099aSliuyi { 5676af099aSliuyi FILE *file = NULL; 5776af099aSliuyi int iRead; 5876af099aSliuyi file = fopen(filename.c_str(), "wb+"); 5976af099aSliuyi if (!file) { 6076af099aSliuyi return false; 6176af099aSliuyi } 6276af099aSliuyi BYTE buffer[1024]; 6376af099aSliuyi DWORD dwBufferSize = 1024; 6476af099aSliuyi DWORD dwBootSize = m_bootSize; 6576af099aSliuyi DWORD dwReadSize; 6676af099aSliuyi fseek(m_pFile, m_bootOffset, SEEK_SET); 6776af099aSliuyi do { 6876af099aSliuyi dwReadSize = (dwBootSize >= 1024) ? dwBufferSize : dwBootSize; 6976af099aSliuyi iRead = fread(buffer, 1, dwReadSize, m_pFile); 7076af099aSliuyi if (iRead != (int)dwReadSize) { 7176af099aSliuyi fclose(file); 7276af099aSliuyi return false; 7376af099aSliuyi } 7476af099aSliuyi fwrite(buffer, 1, dwReadSize, file); 7576af099aSliuyi dwBootSize -= dwReadSize; 7676af099aSliuyi } while(dwBootSize > 0); 7776af099aSliuyi fclose(file); 7876af099aSliuyi return true; 7976af099aSliuyi } 8076af099aSliuyi bool CRKImage::SaveFWFile(string filename) 8176af099aSliuyi { 8276af099aSliuyi FILE *file = NULL; 8376af099aSliuyi int iRead; 8476af099aSliuyi file = fopen(filename.c_str(), "wb+"); 8576af099aSliuyi if (!file) { 8676af099aSliuyi return false; 8776af099aSliuyi } 8876af099aSliuyi BYTE buffer[1024]; 8976af099aSliuyi DWORD dwBufferSize = 1024; 9076af099aSliuyi long long dwFWSize = m_fwSize; 9176af099aSliuyi DWORD dwReadSize; 9276af099aSliuyi fseeko(m_pFile, m_fwOffset, SEEK_SET); 9376af099aSliuyi do { 9476af099aSliuyi dwReadSize = (dwFWSize >= 1024) ? dwBufferSize : dwFWSize; 9576af099aSliuyi iRead = fread(buffer, 1, dwReadSize, m_pFile); 9676af099aSliuyi if (iRead != (int)dwReadSize) { 9776af099aSliuyi fclose(file); 9876af099aSliuyi return false; 9976af099aSliuyi } 10076af099aSliuyi fwrite(buffer, 1, dwReadSize, file); 10176af099aSliuyi dwFWSize -= dwReadSize; 10276af099aSliuyi } while (dwFWSize > 0); 10376af099aSliuyi fclose(file); 10476af099aSliuyi return true; 10576af099aSliuyi } 10676af099aSliuyi bool CRKImage::GetData(long long dwOffset, DWORD dwSize, PBYTE lpBuffer) 10776af099aSliuyi { 10876af099aSliuyi if ( (dwOffset < 0) || (dwSize == 0) ) { 10976af099aSliuyi return false; 11076af099aSliuyi } 11176af099aSliuyi if ( dwOffset+dwSize > m_fileSize) { 11276af099aSliuyi return false; 11376af099aSliuyi } 11476af099aSliuyi fseeko(m_pFile, dwOffset, SEEK_SET); 11576af099aSliuyi UINT uiActualRead; 11676af099aSliuyi uiActualRead = fread(lpBuffer,1, dwSize, m_pFile); 11776af099aSliuyi if (dwSize != uiActualRead){ 11876af099aSliuyi return false; 11976af099aSliuyi } 12076af099aSliuyi return true; 12176af099aSliuyi } 12276af099aSliuyi void CRKImage::GetReservedData(PBYTE &lpData, USHORT &usSize) 12376af099aSliuyi { 12476af099aSliuyi lpData = m_reserved; 12576af099aSliuyi usSize = IMAGE_RESERVED_SIZE; 12676af099aSliuyi } 12776af099aSliuyi 12876af099aSliuyi CRKImage::CRKImage(string filename, bool &bCheck) 12976af099aSliuyi { 13076af099aSliuyi Version.setContainer(this); 13176af099aSliuyi Version.getter(&CRKImage::GetVersion); 13276af099aSliuyi MergeVersion.setContainer(this); 13376af099aSliuyi MergeVersion.getter(&CRKImage::GetMergeVersion); 13476af099aSliuyi ReleaseTime.setContainer(this); 13576af099aSliuyi ReleaseTime.getter(&CRKImage::GetReleaseTime); 13676af099aSliuyi SupportDevice.setContainer(this); 13776af099aSliuyi SupportDevice.getter(&CRKImage::GetSupportDevice); 13876af099aSliuyi OsType.setContainer(this); 13976af099aSliuyi OsType.getter(&CRKImage::GetOsType); 14076af099aSliuyi BackupSize.setContainer(this); 14176af099aSliuyi BackupSize.getter(&CRKImage::GetBackupSize); 14276af099aSliuyi BootOffset.setContainer(this); 14376af099aSliuyi BootOffset.getter(&CRKImage::GetBootOffset); 14476af099aSliuyi BootSize.setContainer(this); 14576af099aSliuyi BootSize.getter(&CRKImage::GetBootSize); 14676af099aSliuyi FWOffset.setContainer(this); 14776af099aSliuyi FWOffset.getter(&CRKImage::GetFWOffset); 14876af099aSliuyi FWSize.setContainer(this); 14976af099aSliuyi FWSize.getter(&CRKImage::GetFWSize); 15076af099aSliuyi SignFlag.setContainer(this); 15176af099aSliuyi SignFlag.getter(&CRKImage::GetSignFlag); 15276af099aSliuyi struct stat statBuf; 15376af099aSliuyi m_bootObject = NULL; 15476af099aSliuyi m_pFile = NULL; 15576af099aSliuyi m_bSignFlag = false; 15676af099aSliuyi 15776af099aSliuyi m_signMd5Size = 0; 15876af099aSliuyi memset(m_md5, 0, 32); 15976af099aSliuyi memset(m_signMd5, 0, 256); 16076af099aSliuyi 16176af099aSliuyi char szName[256]; 16276af099aSliuyi strcpy(szName, filename.c_str()); 16376af099aSliuyi if(stat(szName, &statBuf) < 0) { 16476af099aSliuyi bCheck = false; 16576af099aSliuyi return; 16676af099aSliuyi } 16776af099aSliuyi if (S_ISDIR(statBuf.st_mode)) { 16876af099aSliuyi bCheck = false; 16976af099aSliuyi return; 17076af099aSliuyi } 17176af099aSliuyi m_fileSize = statBuf.st_size; 17276af099aSliuyi 17376af099aSliuyi bool bOnlyBootFile=false; 17476af099aSliuyi transform(filename.begin(), filename.end(), filename.begin(), (int(*)(int))tolower); 17576af099aSliuyi if (filename.find(".bin") != string::npos) { 17676af099aSliuyi bOnlyBootFile = true; 17776af099aSliuyi } 17876af099aSliuyi 17976af099aSliuyi m_pFile = fopen(szName, "rb"); 18076af099aSliuyi if (!m_pFile) { 18176af099aSliuyi bCheck = false; 18276af099aSliuyi return; 18376af099aSliuyi } 18476af099aSliuyi 18576af099aSliuyi int nMd5DataSize, iRead; 18676af099aSliuyi long long ulFwSize; 18776af099aSliuyi STRUCT_RKIMAGE_HEAD imageHead; 18876af099aSliuyi if (!bOnlyBootFile) { 18976af099aSliuyi fseeko(m_pFile, 0, SEEK_SET); 19076af099aSliuyi iRead = fread((PBYTE)(&imageHead), 1, sizeof(STRUCT_RKIMAGE_HEAD), m_pFile); 19176af099aSliuyi if (iRead != sizeof(STRUCT_RKIMAGE_HEAD)) { 19276af099aSliuyi bCheck = false; 19376af099aSliuyi return; 19476af099aSliuyi } 19576af099aSliuyi if ( imageHead.uiTag != 0x57464B52 ) { 19676af099aSliuyi bCheck = false; 19776af099aSliuyi return; 19876af099aSliuyi } 19976af099aSliuyi if ((imageHead.reserved[14] == 'H') && (imageHead.reserved[15] == 'I')) { 20076af099aSliuyi ulFwSize = *((DWORD *)(&imageHead.reserved[16])); 20176af099aSliuyi ulFwSize <<= 32; 20276af099aSliuyi ulFwSize += imageHead.dwFWOffset; 20376af099aSliuyi ulFwSize += imageHead.dwFWSize; 20476af099aSliuyi } else 20576af099aSliuyi ulFwSize = imageHead.dwFWOffset + imageHead.dwFWSize; 20676af099aSliuyi nMd5DataSize = GetImageSize() - ulFwSize; 20776af099aSliuyi if (nMd5DataSize >= 160) { 20876af099aSliuyi m_bSignFlag = true; 20976af099aSliuyi m_signMd5Size = nMd5DataSize - 32; 21076af099aSliuyi fseeko(m_pFile, ulFwSize, SEEK_SET); 21176af099aSliuyi iRead = fread(m_md5, 1, 32, m_pFile); 21276af099aSliuyi if (iRead != 32) { 21376af099aSliuyi bCheck = false; 21476af099aSliuyi return; 21576af099aSliuyi } 21676af099aSliuyi iRead = fread(m_signMd5, 1, nMd5DataSize - 32, m_pFile); 21776af099aSliuyi if (iRead != (nMd5DataSize - 32)) { 21876af099aSliuyi bCheck = false; 21976af099aSliuyi return; 22076af099aSliuyi } 22176af099aSliuyi } else { 22276af099aSliuyi fseeko(m_pFile, -32, SEEK_END); 22376af099aSliuyi iRead = fread(m_md5, 1, 32, m_pFile); 22476af099aSliuyi if (iRead != 32) { 22576af099aSliuyi bCheck = false; 22676af099aSliuyi return; 22776af099aSliuyi } 22876af099aSliuyi } 22976af099aSliuyi 23076af099aSliuyi m_version = imageHead.dwVersion; 23176af099aSliuyi m_mergeVersion = imageHead.dwMergeVersion; 23276af099aSliuyi m_releaseTime.usYear = imageHead.stReleaseTime.usYear; 23376af099aSliuyi m_releaseTime.ucMonth = imageHead.stReleaseTime.ucMonth; 23476af099aSliuyi m_releaseTime.ucDay = imageHead.stReleaseTime.ucDay; 23576af099aSliuyi m_releaseTime.ucHour = imageHead.stReleaseTime.ucHour; 23676af099aSliuyi m_releaseTime.ucMinute = imageHead.stReleaseTime.ucMinute; 23776af099aSliuyi m_releaseTime.ucSecond = imageHead.stReleaseTime.ucSecond; 23876af099aSliuyi m_supportDevice = imageHead.emSupportChip; 23976af099aSliuyi m_bootOffset = imageHead.dwBootOffset; 24076af099aSliuyi m_bootSize = imageHead.dwBootSize; 24176af099aSliuyi m_fwOffset = imageHead.dwFWOffset; 24276af099aSliuyi m_fwSize = ulFwSize - m_fwOffset; 24376af099aSliuyi memcpy(m_reserved, imageHead.reserved, IMAGE_RESERVED_SIZE); 24476af099aSliuyi } else { 24576af099aSliuyi m_bootOffset = 0; 24676af099aSliuyi m_bootSize = m_fileSize; 24776af099aSliuyi } 24876af099aSliuyi 24976af099aSliuyi PBYTE lpBoot; 25076af099aSliuyi lpBoot = new BYTE[m_bootSize]; 25176af099aSliuyi fseeko(m_pFile, m_bootOffset, SEEK_SET); 25276af099aSliuyi iRead = fread(lpBoot, 1, m_bootSize, m_pFile); 25376af099aSliuyi if (iRead != (int)m_bootSize) { 25476af099aSliuyi bCheck = false; 25576af099aSliuyi return; 25676af099aSliuyi } 25776af099aSliuyi bool bRet; 25876af099aSliuyi m_bootObject = new CRKBoot(lpBoot, m_bootSize, bRet); 25976af099aSliuyi if (!bRet) { 26076af099aSliuyi bCheck = false; 26176af099aSliuyi return; 26276af099aSliuyi } 26376af099aSliuyi if (bOnlyBootFile) { 26476af099aSliuyi m_supportDevice = m_bootObject->SupportDevice; 26576af099aSliuyi UINT *pOsType; 26676af099aSliuyi pOsType = (UINT *)&m_reserved[4]; 26776af099aSliuyi *pOsType = (UINT)RK_OS; 26876af099aSliuyi fclose(m_pFile); 26976af099aSliuyi m_pFile = NULL; 27076af099aSliuyi } 27176af099aSliuyi bCheck = true; 27276af099aSliuyi } 27376af099aSliuyi CRKImage::~CRKImage() 27476af099aSliuyi { 27576af099aSliuyi if (m_pFile) { 27676af099aSliuyi fclose(m_pFile); 27776af099aSliuyi m_pFile = NULL; 27876af099aSliuyi } 27976af099aSliuyi if (m_bootObject) { 28076af099aSliuyi delete m_bootObject; 28176af099aSliuyi m_bootObject = NULL; 28276af099aSliuyi } 28376af099aSliuyi } 28476af099aSliuyi 28576af099aSliuyi long long CRKImage::GetImageSize() 28676af099aSliuyi { 28776af099aSliuyi return m_fileSize; 28876af099aSliuyi } 28976af099aSliuyi int CRKImage::GetMd5Data(PBYTE &lpMd5, PBYTE &lpSignMd5) 29076af099aSliuyi { 29176af099aSliuyi lpMd5 = m_md5; 29276af099aSliuyi lpSignMd5 = m_signMd5; 29376af099aSliuyi return m_signMd5Size; 29476af099aSliuyi } 29576af099aSliuyi bool CRKImage::GetSignFlag() 29676af099aSliuyi { 29776af099aSliuyi return m_bSignFlag; 29876af099aSliuyi } 299