#include "HexFile.h" #include #include #include "CRC32.h" #define USE_BIG_RECORDS #define MAX_RECORDS_IN_BIG_RECORDS 512 //16 bytes by record, 512 bytes by row --> 16 rows / big record CHexFile::CHexFile(void) { mFileOpened = false; mFileParsed = false; mRecordsListValid = false; mHighAddress = 0; mDiscardedRecords = 0; mTotalParsedRecords = 0; mFirmwareCRC = 0; } CHexFile::~CHexFile(void) { for(int i = 0; i < mRecordsList.size(); i++) delete mRecordsList.at(i); } int CHexFile::CloseOpenedHexFile() { for(int i = 0; i < mRecordsList.size(); i++) delete mRecordsList.at(i); mRecordsList.clear(); mFileOpened = false; mFileParsed = false; mHexfileHandle = 0; mRecordsListValid = false; mHighAddress = 0; mDiscardedRecords = 0; mTotalParsedRecords = 0; return 1; } int CHexFile::OpenDataFile(QString FilePath, bool CloseIfAlreadyParsed) { //Check if file exists if(QFile::exists(FilePath) == false) return 0; if(mFileParsed == true) { if(CloseIfAlreadyParsed == false) { return 0; } else { CloseOpenedHexFile(); } } mHexfileHandle = new QFile(FilePath); if(mHexfileHandle->open(QIODevice::ReadOnly|QIODevice::Text|QIODevice::Unbuffered) == false) { delete mHexfileHandle; mHexfileHandle = 0; qDebug("Cannot open specified HEX file..."); return 0; } mHexFileSize = mHexfileHandle->size(); mFileOpened = true; mRecordsTableSize = 0; mFirmwareDataSize = 0; return ParseData(); mHexfileHandle->close(); } int CHexFile::ParseData(void) { if(!mFileOpened) return 0; int Ret; bool Finished = false; unsigned int CurAddress; // CArray TempArray; QList TempList; QString RecordString; QTextStream RecordFileStream(mHexfileHandle); // CArchive ar(&mHexfileHandle,CArchive::load); while(!Finished) { CHexRecord *NewRecord = new CHexRecord; RecordString.clear(); // ar.ReadString(mRecordString); RecordString = RecordFileStream.readLine(); // Ret = NewRecord.DecodeRawRecord(&mRecordString,mHighAddress); Ret = NewRecord->DecodeRawRecord(&RecordString,mHighAddress); mTotalParsedRecords++; switch(Ret) { case CHexRecord::RET_DATA_RECORD: { #ifdef USE_BIG_RECORDS TempList.append(NewRecord); // mRecordsTable[mRecordsTableSize] = NewRecord; // mRecordsTableSize++; #else mRecordsList.append(NewRecord); mRecordsTable[mRecordsTableSize] = NewRecord; mRecordsTableSize++; #endif break; } case CHexRecord::RET_EOF_RECORD: { mHexfileHandle->close(); mFileOpened = false; delete mHexfileHandle; mRecordsListValid = true; Finished = true; delete NewRecord; break; } case CHexRecord::RET_EXTENDED_LINEAR_ADDRESS: { // mHighAddress = NewRecord.GetExtenedAddress(); mHighAddress = NewRecord->GetExtenedAddress(); CurAddress = mHighAddress; delete NewRecord; break; } case CHexRecord::RET_IGNORED_ALL_FF_RECORD: { delete NewRecord; mDiscardedRecords++; break; } case CHexRecord::RET_EXTENDED_ADDRESS: case CHexRecord::RET_START_SEGMENT_ADDRESS: case CHexRecord::RET_START_LINEAR_ADDRESS: case CHexRecord::RET_UNKNOWN_RECORD_TYPE: case CHexRecord::RET_INVALID_RECORD: case CHexRecord::RET_BAD_RECORD_CHECKSUM: case CHexRecord::RET_UNMANAGED_RECORD_TYPE: { mHexfileHandle->close(); mFileOpened = false; delete mHexfileHandle; Finished = true; //MessageBox(NULL,"Parsing Error", "Cannot Parse Hex File",MB_OK); QMessageBox::warning(0,"Parsing Error","Cannot parse HEX file",QMessageBox::Ok); delete NewRecord; return 0; break; } } } #ifdef USE_BIG_RECORDS int i; int RecordCount; CHexRecord *TempRecordPtr; CHexRecord *BigRecord = new CHexRecord; CCRC32 Crc32Engine; TempRecordPtr = TempList.at(0); CurAddress = TempRecordPtr->GetStartAddress(); *BigRecord = *TempRecordPtr; RecordCount = 1; for(i = 1; i < TempList.size(); i++) { // if(CurAddress == 0x1d0097F0) // { // CurAddress = CurAddress; // } CurAddress += (TempRecordPtr->GetRecordSizeInBytes()); TempRecordPtr = TempList.at(i); if(CurAddress == TempRecordPtr->GetStartAddress() && RecordCountAppendRecord(TempRecordPtr); RecordCount++; } else { RecordCount = 1; //Init to 1 because we load the record right below... mRecordsList.append(BigRecord); BigRecord = new CHexRecord; if(i == TempList.size()-1) //Manage the last record. { *BigRecord = *TempRecordPtr; mRecordsList.append(BigRecord); BigRecord->mRecordSize += TempRecordPtr->mRecordSize; } else { *BigRecord = *TempRecordPtr; CurAddress = TempRecordPtr->GetStartAddress(); } } } #endif for(i = 0; i < TempList.size(); i++) { delete TempList[i]; } // for(i = 0; i < mRecordsList.size(); i++) // { // mFirmwareDataSize += mRecordsList.at(i)->GetRecordSizeInBytes(); // } FilterRecords(0x1D004000,0x1D07FFFF); QByteArray RawShit = GetRawData(false); mFirmwareDataSize = RawShit.size(); unsigned int testcrc = CRC_START_32; for(unsigned int i = 0; i < mFirmwareDataSize; i++) { testcrc = Crc32Engine.UpdateCRC32(testcrc,RawShit[i]); } testcrc ^= 0xffffffffL; mFirmwareCRC = Crc32Engine.ComputeCRC32((const unsigned char *)RawShit.data(),RawShit.size()); mFileParsed = true; return 1; } int CHexFile::FilterRecords(unsigned int StartAddress, unsigned int EndAddress) { if(mRecordsList.isEmpty() == true) { return 0; } bool done = false; int i = 0; while(done == false) { if(mRecordsList.at(i)->GetStartAddress() < StartAddress || mRecordsList.at(i)->GetStartAddress() > EndAddress) { //Record is outside filter area, delete it... delete mRecordsList.at(i); mRecordsList.removeAt(i); } else { i++; } if(i == mRecordsList.size()) { done = true; break; } } return 1; } unsigned int CHexFile::GetNBRecords(void) { // return mRecordsTableSize; return mRecordsList.size(); } unsigned long CHexFile::GetFileSize(void) { return mHexFileSize; } unsigned int CHexFile::GetDataCRC32() { return mFirmwareCRC; } CHexRecord * CHexFile::GetRecord(int RecordIndex, int &Status) { if(RecordIndex > mRecordsList.size()) // if(RecordIndex > mRecordsTableSize) { Status = ERR_INDEX_OUT_OF_BOUND; return 0; } //CHexRecord *mRecordPtr = (CHexRecord*)&mRecordsList.GetAt(RecordIndex); CHexRecord *mRecordPtr = mRecordsList.at(RecordIndex); // CHexRecord *mRecordPtr = mRecordsTable[RecordIndex]; return mRecordPtr; } QByteArray CHexFile::GetRawData(bool IncludeHeader) { QByteArray Data; Data.clear(); if(IncludeHeader) { QDataStream Strm(&Data,QIODevice::WriteOnly); //Header Strm << HEX_FILE_HEADER_CODE; //Flags Strm << (int)0x0000; //TODO: Manage that //Nb Records Strm << GetNBRecords(); //Firmware size Strm << GetFirmwareSize(); //Version Strm << (int)0x00; //TODO: Manage that //CRC32 Strm << GetDataCRC32(); } for(int i = 0; i < mRecordsList.size(); i++) { Data.append(mRecordsList.at(i)->GetRecord()); } return Data; } QString CHexFile::GetHexFileInfoString() { QString string; string.clear(); if(HexDataValid() == false) return QString("No file loaded\n"); for(int i = 0; i < mRecordsList.size(); i++) { CHexRecord *rec = mRecordsList.at(i); unsigned int StartAddress = rec->GetStartAddress(); unsigned int Size = rec->GetRecordSizeInBytes(); unsigned int EndAddress = StartAddress + Size; string.append(QString("Record %1: Start = [0x%2], Length = [%3], End = 0x%4\n").arg(i).arg(StartAddress,0,16).arg(Size).arg(EndAddress,0,16)); } string.prepend("-------------------------------------------------------------\n"); string.append("-------------------------------------------------------------\n"); return string; }