/* * Copyright 2019 Rockchip Electronics Co., Ltd * Dayao Ji * * SPDX-License-Identifier: GPL-2.0+ */ #include #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); }