1
0
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

214 lines
6.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright 2019 Rockchip Electronics Co., Ltd
* Dayao Ji <jdy@rock-chips.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <iostream>
#include "rkupdate/RKSparse.h"
#include "rkupdate/RKDevice.h"
using namespace std;
RKSparse::RKSparse(const char* filePath){
// 1. 打开文件
m_pFile = fopen(filePath, "rb");
fileName = filePath;
// 2. 设置m_header
readfile(0, sizeof(m_header), (PBYTE)&m_header);
// 3. 设置m_chunk
readfile(0 + sizeof(m_header), sizeof(m_chunk), (PBYTE)&m_chunk);
};
RKSparse::~RKSparse(){
if(m_pFile != NULL){
fclose(m_pFile);
}
remove(fileName);
sync();
}
bool RKSparse::IsSparseImage(){
if(m_header.magic != SPARSE_HEADER_MAGIC)
{
printf("Image isn't Sparse.\n");
return false;
}else{
printf("Image is Sparse.\n");
return true;
}
}
long long RKSparse::GetSparseImageSize(){
return m_header.blk_sz * m_header.total_blks;
}
bool RKSparse::SparseFile_Download(DWORD dwPos, CRKComm *pComm){
UINT uiLBATransferSize = (LBA_TRANSFER_SIZE) * 1;
UINT uiBufferSize = uiLBATransferSize; // buffer 的长度
UINT uiLBASector = uiLBATransferSize/SECTOR_SIZE;
UINT uiCurChunk; //当前块的计数
UINT uiChunkDataSize, uiWriteByte, uiLen, uiBegin, uiFillByte, uiCrc;
int iRet, i;
long long uiEntryOffset; //数据的偏移量
chunk_header chunk;
PBYTE pBuffer = NULL;
uiEntryOffset = sizeof(m_header);
uiCurChunk = 0;
uiLen = 0;
uiWriteByte = 0;
uiBegin = dwPos;
//申请buffer用来放置要写入的数据
pBuffer = new BYTE[uiBufferSize];
if(pBuffer == NULL){
printf("Failed ==== new Buffer %s:%d.\n", __func__, __LINE__);
return false;
}
while(uiCurChunk < m_header.total_chunks){
bool bRet = false;
bRet = readfile(uiEntryOffset, sizeof(chunk), (PBYTE)&chunk);
if(!bRet){
printf("Failed ==== readfile %s:%d.\n", __func__, __LINE__);
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); //当前chunk 数据长度
while (uiChunkDataSize)
{
memset(pBuffer, 0, uiBufferSize);
if(uiChunkDataSize < uiBufferSize )
{
uiWriteByte = uiChunkDataSize;
uiLen = ( (uiWriteByte%SECTOR_SIZE==0) ? (uiWriteByte/SECTOR_SIZE) : (uiWriteByte/SECTOR_SIZE+1) );
}
else
{
uiWriteByte = uiBufferSize;
uiLen = uiLBASector;
}
if (!readfile(uiEntryOffset, uiWriteByte, pBuffer))
{
printf("ERROR:get chunk data failed,chunk=%d, %s:%d",uiCurChunk, __func__, __LINE__);
delete []pBuffer;
pBuffer = NULL;
return false;
}
uiEntryOffset += uiWriteByte;
iRet = pComm->RKU_WriteLBA(uiBegin, uiLen, pBuffer, 0);
if( iRet!=ERR_SUCCESS )
{
printf("ERROR:RKA_SparseFile_Download-->RKU_WriteLBA failed,RetCode(%d),chunk=%d", iRet, uiCurChunk);
delete []pBuffer;
pBuffer = NULL;
return false;
}
uiBegin += uiLen;
//currentByte += uiWriteByte;
uiChunkDataSize -= uiWriteByte;
}
break;
case CHUNK_TYPE_FILL:
uiChunkDataSize = chunk.chunk_sz * m_header.blk_sz;
if (readfile(uiEntryOffset, 4, (PBYTE)&uiFillByte))
{
printf("ERROR:RKA_SparseFile_Download-->get fill byte failed,chunk=%d", uiCurChunk);
delete []pBuffer;
pBuffer = NULL;
return false;
}
uiEntryOffset += 4;
while(uiChunkDataSize)
{
memset(pBuffer, 0, uiBufferSize);
if (uiChunkDataSize < uiBufferSize )
{
uiWriteByte = uiChunkDataSize;
uiLen = ( (uiWriteByte%SECTOR_SIZE==0) ? (uiWriteByte/SECTOR_SIZE) : (uiWriteByte/SECTOR_SIZE+1) );
}
else
{
uiWriteByte = uiBufferSize;
uiLen = uiLBASector;
}
for (i = 0; i < uiWriteByte/4; i++)
{
*(UINT *)(pBuffer + i*4) = uiFillByte;
}
uiEntryOffset += uiWriteByte;
iRet = pComm->RKU_WriteLBA(uiBegin, uiLen, pBuffer, 0);
if(iRet != ERR_SUCCESS)
{
printf(" ERROR:RKA_SparseFile_Download-->RKU_WriteLBA failed,RetCode(%d),chunk=%d", iRet, uiCurChunk);
delete []pBuffer;
pBuffer = NULL;
return false;
}
uiBegin += uiLen;
//currentByte += uiWriteByte;
uiChunkDataSize -= uiWriteByte;
}
break;
case CHUNK_TYPE_DONT_CARE:
uiChunkDataSize = chunk.chunk_sz * m_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 = readfile(uiEntryOffset, 4, (PBYTE)&uiCrc);
uiEntryOffset += 4;
break;
}
}
printf("======%s:%d====== success.\n", __func__, __LINE__);
return true;
}
bool RKSparse::readfile(long long dwOffset, DWORD dwSize, PBYTE lpBuffer){
if (dwOffset < 0 || dwSize == 0)
{
return false;
}
//if ( dwOffset + dwSize > m_fileSize)
//{
// return false;
//}
fseeko(m_pFile, dwOffset, SEEK_SET);
UINT uiActualRead;
uiActualRead = fread(lpBuffer, 1, dwSize, m_pFile);
if (dwSize!=uiActualRead)
{
printf("readfile failed.\n");
return false;
}
return true;
}
void RKSparse::display(){
printf("in RKSparse display.\n");
printf("m_header->magic is %x.\n", m_header.magic);
}