From fd12b11118683033572d706154ad77e290f162a3 Mon Sep 17 00:00:00 2001 From: MrWhite1987 Date: Wed, 14 May 2014 14:06:03 +0200 Subject: [PATCH 1/2] Support data overwriting overwriteData() method added Bugfix on generating HEX file. Byte order of linear address was wrong(?!) --- intelhex_class/intelhexclass.cpp | 32 +- intelhex_class/intelhexclass.cpp.bak | 1140 ++++++++++++++++++++++++++ 2 files changed, 1164 insertions(+), 8 deletions(-) create mode 100644 intelhex_class/intelhexclass.cpp.bak diff --git a/intelhex_class/intelhexclass.cpp b/intelhex_class/intelhexclass.cpp index 96d3e49..0a979dd 100644 --- a/intelhex_class/intelhexclass.cpp +++ b/intelhex_class/intelhexclass.cpp @@ -249,6 +249,22 @@ void intelhex::addError(string errorMessage) msgError.noOfErrors = msgError.ihErrors.size(); } +/******************************************************************************* +* Overwrite data at a given location +*******************************************************************************/ +void intelhex::overwriteData(unsigned char data, unsigned long address) +{ + map::iterator ihIterator; + + ihIterator = ihContent.find(address); + if(ihIterator != ihContent.end()) + { + ihContent.erase(address); + } + + ihReturn = ihContent.insert(pair(address, data)); +} + /******************************************************************************* * Decodes a data record read in from a file *******************************************************************************/ @@ -870,11 +886,11 @@ ostream& operator<<(ostream& dataOut, intelhex& ihLocal) thisRecord = ":02000004"; checksum = 0x02 + 0x04; - dataByte = static_cast(addressOffset & 0xFF); + dataByte = static_cast((addressOffset >> 8) & 0xFF); checksum += dataByte; thisRecord += ihLocal.ucToHexString(dataByte); - dataByte = static_cast((addressOffset >> 8) & 0xFF); + dataByte = static_cast(addressOffset & 0xFF); checksum += dataByte; thisRecord += ihLocal.ucToHexString(dataByte); @@ -889,11 +905,11 @@ ostream& operator<<(ostream& dataOut, intelhex& ihLocal) thisRecord = ":02000002"; checksum = 0x02 + 0x02; - dataByte = static_cast(addressOffset & 0xFF); + dataByte = static_cast((addressOffset >> 8) & 0xFF); checksum += dataByte; thisRecord += ihLocal.ucToHexString(dataByte); - dataByte = static_cast((addressOffset >> 8) & 0xFF); + dataByte = static_cast(addressOffset & 0xFF); checksum += dataByte; thisRecord += ihLocal.ucToHexString(dataByte); @@ -932,11 +948,11 @@ ostream& operator<<(ostream& dataOut, intelhex& ihLocal) thisRecord = ":02000004"; checksum = 0x02 + 0x04; - dataByte = static_cast(addressOffset & 0xFF); + dataByte = static_cast((addressOffset >> 8) & 0xFF); checksum += dataByte; thisRecord += ihLocal.ucToHexString(dataByte); - dataByte = static_cast((addressOffset >> 8) & 0xFF); + dataByte = static_cast(addressOffset & 0xFF); checksum += dataByte; thisRecord += ihLocal.ucToHexString(dataByte); @@ -962,11 +978,11 @@ ostream& operator<<(ostream& dataOut, intelhex& ihLocal) thisRecord = ":02000002"; checksum = 0x02 + 0x02; - dataByte = static_cast(addressOffset & 0xFF); + dataByte = static_cast((addressOffset >> 8) & 0xFF); checksum += dataByte; thisRecord += ihLocal.ucToHexString(dataByte); - dataByte = static_cast((addressOffset >> 8) & 0xFF); + dataByte = static_cast(addressOffset & 0xFF); checksum += dataByte; thisRecord += ihLocal.ucToHexString(dataByte); diff --git a/intelhex_class/intelhexclass.cpp.bak b/intelhex_class/intelhexclass.cpp.bak new file mode 100644 index 0000000..96d3e49 --- /dev/null +++ b/intelhex_class/intelhexclass.cpp.bak @@ -0,0 +1,1140 @@ +/******************************************************************************* +* +* INTEL HEX FILE CLASS MODULE +* +*******************************************************************************/ + +/******************************************************************************/ +/*! +* \file intelhexclass.cpp +* \mainpage +* \image html intelhexclass.png +* \image latex intelhexclass.eps +* \section intro Introduction +* The Intel HEX File class module is designed to encode, decode and manipulate +* the content of Intel HEX format files commonly generated by most toolchains +* for embedded processors and microcontrollers. +* +* It uses standard C++ streams to decode files and store them in memory, and +* encode data stored in memory back into an Intel HEX format file. Once the file +* content is in memory, the content can then be manipulated using the available +* API. +* +* With this class it is possible to create tools that can compare Intel HEX +* files, fill empty space with desired values, splice two or more files +* together to name a few possibilities. +* +* \section contactInfo Contact Information +* For more information and the latest release, please visit this projects home +* page at http://codinghead.github.com/Intel-HEX-Class +* To participate in the project or for other enquiries, please contact Stuart +* Cording at codinghead@gmail.com +* +* \section license Licensing Information +* Copyright (c) 2012 Stuart Cording +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* \section imageInfo Image Information +* Image chosen for this project comes from 'Henkster'. Original image is from +* http://www.sxc.hu/photo/504350 on stock.xchng. +* +* \author Stuart Cording aka CODINGHEAD +* +******************************************************************************** +* \note +* No notes to date (19th Jan 2012) +*******************************************************************************/ + +#include +#include +#include +#ifdef _MSC_FULL_VER +#include +#else +#include +#endif + +#include "intelhexclass.h" + +using namespace std; + +/******************************************************************************/ +/*! Possible record types for Intel HEX file. +* +* List of all possible record types that can be found in an Intel HEX file. +*******************************************************************************/ +enum intelhexRecordType { + DATA_RECORD, + END_OF_FILE_RECORD, + EXTENDED_SEGMENT_ADDRESS, + START_SEGMENT_ADDRESS, + EXTENDED_LINEAR_ADDRESS, + START_LINEAR_ADDRESS, + NO_OF_RECORD_TYPES +}; + +/******************************************************************************* +* Converts a 2 char string to its HEX value +*******************************************************************************/ +unsigned char intelhex::stringToHex(string value) +{ + unsigned char returnValue = 0; + string::iterator valueIterator; + + if(value.length() == 2) + { + valueIterator = value.begin(); + + for (int x=0; x < 2; x++) + { + /* Shift result variable 4 bits to the left */ + returnValue <<= 4; + + if (*valueIterator >= '0' && *valueIterator <= '9') + { + returnValue += + static_cast(*valueIterator - '0'); + } + else if (*valueIterator >= 'A' && *valueIterator <= 'F') + { + returnValue += + static_cast(*valueIterator - 'A' + 10); + } + else if (*valueIterator >= 'a' && *valueIterator <= 'f') + { + returnValue += + static_cast(*valueIterator - 'a' + 10); + } + else + { + /* Error occured - non-HEX value found */ + string message; + + message = "Can't convert byte 0x" + value + " @ 0x" + + ulToHexString(segmentBaseAddress) + " to hex."; + + addError(message); + + returnValue = 0; + } + + /* Iterate to next char in the string */ + ++valueIterator; + } + } + else + { + /* Error occured - more or less than two nibbles in the string */ + string message; + + message = value + " @ 0x" + ulToHexString(segmentBaseAddress) + + " isn't an 8-bit value."; + + addError(message); + } + + return returnValue; +} + +/******************************************************************************* +* Converts an unsigned long to a string in HEX format +*******************************************************************************/ +string intelhex::ulToHexString(unsigned long value) +{ + string returnString; + char localString[50]; + + returnString.erase(); + +#ifdef _MSC_FULL_VER + sprintf_s(localString, 49, "%08lX", value); +#else + snprintf(localString, 49, "%08lX", value); +#endif + + returnString.insert(0, localString); + + return returnString; +} + +/******************************************************************************* +* Converts an unsigned long to a string in DEC format +*******************************************************************************/ +string intelhex::ulToString(unsigned long value) +{ + string returnString; + char localString[50]; + + returnString.erase(); + +#ifdef _MSC_FULL_VER + sprintf_s(localString, 49, "%lu", value); +#else + snprintf(localString, 49, "%lu", value); +#endif + returnString.insert(0, localString); + + return returnString; +} + +/******************************************************************************* +* Converts an unsigned char to a string in HEX format +*******************************************************************************/ +string intelhex::ucToHexString(unsigned char value) +{ + string returnString; + char localString[50]; + + returnString.erase(); + +#ifdef _MSC_FULL_VER + sprintf_s(localString, 49, "%02X", value); +#else + snprintf(localString, 49, "%02X", value); +#endif + + returnString.insert(0, localString); + + return returnString; +} + +/******************************************************************************* +* Adds a warning to the list of warning messages +*******************************************************************************/ +void intelhex::addWarning(string warningMessage) +{ + string localMessage; + + /* Build the message and push the warning message onto the list */ + localMessage += ulToString(msgWarning.noOfWarnings + 1) + " Warning: " + + warningMessage; + + msgWarning.ihWarnings.push_back(localMessage); + + /* Update the number of warning messages */ + msgWarning.noOfWarnings = msgWarning.ihWarnings.size(); +} + +/******************************************************************************* +* Adds an error to the list of error messages +*******************************************************************************/ +void intelhex::addError(string errorMessage) +{ + string localMessage; + + /* Build the message and push the error message onto the list */ + localMessage += ulToString(msgError.noOfErrors + 1) + " Error: " + + errorMessage; + + msgError.ihErrors.push_back(localMessage); + + /* Update the number of error messages */ + msgError.noOfErrors = msgError.ihErrors.size(); +} + +/******************************************************************************* +* Decodes a data record read in from a file +*******************************************************************************/ +void intelhex::decodeDataRecord(unsigned char recordLength, + unsigned long loadOffset, + string::const_iterator data) +{ + /* Variable to store a byte of the record as a two char string */ + string sByteRead; + + /* Variable to store the byte of the record as an u.char */ + unsigned char byteRead; + + /* Calculate new SBA by clearing the low four bytes and then adding the */ + /* current loadOffset for this line of Intel HEX data */ + segmentBaseAddress &= ~(0xFFFFUL); + segmentBaseAddress += loadOffset; + + for (unsigned char x = 0; x < recordLength; x ++) + { + sByteRead.erase(); + + sByteRead = *data; + data++; + sByteRead += *data; + data++; + + byteRead = stringToHex(sByteRead); + + ihReturn=ihContent.insert( + pair(segmentBaseAddress, byteRead)); + + if (ihReturn.second==false) + { + /* If this address already contains the byte we are trying to */ + /* write, this is only a warning */ + if (ihReturn.first->second == byteRead) + { + string message; + + message = "Location 0x" + ulToHexString(segmentBaseAddress) + + " already contains data 0x" + sByteRead; + + addWarning(message); + } + /* Otherwise this is an error */ + else + { + string message; + + message = "Couldn't add 0x" + sByteRead + " @ 0x" + + ulToHexString(segmentBaseAddress) + + "; already contains 0x" + + ucToHexString(ihReturn.first->second); + + addError(message); + } + } + + /* Increment the segment base address */ + ++segmentBaseAddress; + } +} + +/******************************************************************************* +* Input Stream for Intel HEX File Decoding (friend function) +*******************************************************************************/ +istream& operator>>(istream& dataIn, intelhex& ihLocal) +{ + // Create a string to store lines of Intel Hex info + string ihLine; + /* Create a string to store a single byte of Intel HEX info */ + string ihByte; + // Create an iterator for this variable + string::iterator ihLineIterator; + // Create a line counter + unsigned long lineCounter = 0; + // Variable to hold a single byte (two chars) of data + unsigned char byteRead; + // Variable to calculate the checksum for each line + unsigned char intelHexChecksum; + // Variable to hold the record length + unsigned char recordLength; + // Variable to hold the load offset + unsigned long loadOffset; + // Variables to hold the record type + intelhexRecordType recordType; + + do + { + /* Clear the string before this next round */ + ihLine.erase(); + + /* Clear the checksum before processing this line */ + intelHexChecksum = 0; + + /* Get a line of data */ + dataIn >> ihLine; + + /* If the line contained some data, process it */ + if (ihLine.length() > 0) + { + /* Increment line counter */ + lineCounter++; + + /* Set string iterator to start of string */ + ihLineIterator = ihLine.begin(); + + /* Check that we have a ':' record mark at the beginning */ + if (*ihLineIterator != ':') + { + /* Add some warning code here */ + string message; + + message = "Line without record mark ':' found @ line " + + ihLocal.ulToString(lineCounter); + + ihLocal.addWarning(message); + + /* If this is the first line, let's simply give up. Chances */ + /* are this is not an Intel HEX file at all */ + if (lineCounter == 1) + { + message = "Intel HEX File decode aborted; ':' missing in " \ + "first line."; + ihLocal.addError(message); + + /* Erase ihLine content and break out of do...while loop */ + ihLine.erase(); + break; + } + } + else + { + /* Remove the record mark from the string as we don't need it */ + /* anymore */ + ihLine.erase(ihLineIterator); + } + + /* Run through the whole line to check the checksum */ + for (ihLineIterator = ihLine.begin(); + ihLineIterator != ihLine.end(); + /* Nothing - really! */ ) + { + /* Convert the line in pair of chars (making a single byte) */ + /* into single bytes, and then add to the checksum variable. */ + /* By adding all the bytes in a line together *including* the */ + /* checksum byte, we should get a result of '0' at the end. */ + /* If not, there is a checksum error */ + ihByte.erase(); + + ihByte = *ihLineIterator; + ++ihLineIterator; + /* Just in case there are an odd number of chars in the */ + /* just check we didn't reach the end of the string early */ + if (ihLineIterator != ihLine.end()) + { + ihByte += *ihLineIterator; + ++ihLineIterator; + + byteRead = ihLocal.stringToHex(ihByte); + + intelHexChecksum += byteRead; + } + else + { + string message; + + message = "Odd number of characters in line " + + ihLocal.ulToString(lineCounter); + + ihLocal.addError(message); + } + } + + /* Make sure the checksum was ok */ + if (intelHexChecksum == 0) + { + /* Reset iterator back to beginning of the line so we can now */ + /* decode it */ + ihLineIterator = ihLine.begin(); + + /* Clear all the variables associated with decoding a line of */ + /* Intel HEX code. */ + recordLength = 0; + loadOffset = 0; + + /* Get the record length */ + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + recordLength = ihLocal.stringToHex(ihByte); + + /* Get the load offset (2 bytes) */ + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + loadOffset = + static_cast(ihLocal.stringToHex(ihByte)); + loadOffset <<= 8; + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + loadOffset += + static_cast(ihLocal.stringToHex(ihByte)); + + /* Get the record type */ + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + recordType = + static_cast(ihLocal.stringToHex(ihByte)); + + /* Decode the INFO or DATA portion of the record */ + switch (recordType) + { + case DATA_RECORD: + ihLocal.decodeDataRecord(recordLength, loadOffset, + ihLineIterator); + if (ihLocal.verbose == true) + { + cout << "Data Record begining @ 0x" << + ihLocal.ulToHexString(loadOffset) << endl; + } + break; + + case END_OF_FILE_RECORD: + /* Check that the EOF record wasn't already found. If */ + /* it was, generate appropriate error */ + if (ihLocal.foundEof == false) + { + ihLocal.foundEof = true; + } + else + { + string message; + + message = "Additional End Of File record @ line " + + ihLocal.ulToString(lineCounter) + + " found."; + + ihLocal.addError(message); + } + /* Generate error if there were */ + if (ihLocal.verbose == true) + { + cout << "End of File" << endl; + } + break; + + case EXTENDED_SEGMENT_ADDRESS: + /* Make sure we have 2 bytes of data */ + if (recordLength == 2) + { + /* Extract the two bytes of the ESA */ + unsigned long extSegAddress = 0; + + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + extSegAddress = static_cast + (ihLocal.stringToHex(ihByte)); + extSegAddress <<= 8; + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + extSegAddress += static_cast + (ihLocal.stringToHex(ihByte)); + + /* ESA is bits 4-19 of the segment base address */ + /* (SBA), so shift left 4 bits */ + extSegAddress <<= 4; + + /* Update the SBA */ + ihLocal.segmentBaseAddress = extSegAddress; + } + else + { + /* Note the error */ + string message; + + message = "Extended Segment Address @ line " + + ihLocal.ulToString(lineCounter) + + " not 2 bytes as required."; + + ihLocal.addError(message); + } + if (ihLocal.verbose == true) + { + cout << "Ext. Seg. Address found: 0x" << + ihLocal.ulToHexString(ihLocal.segmentBaseAddress) + << endl; + } + + break; + + case START_SEGMENT_ADDRESS: + /* Make sure we have 4 bytes of data, and that no */ + /* Start Segment Address has been found to date */ + if (recordLength == 4 && + ihLocal.startSegmentAddress.exists == false) + { + /* Note that the Start Segment Address has been */ + /* found. */ + ihLocal.startSegmentAddress.exists = true; + /* Clear the two registers, just in case */ + ihLocal.startSegmentAddress.csRegister = 0; + ihLocal.startSegmentAddress.ipRegister = 0; + + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + ihLocal.startSegmentAddress.csRegister = + static_cast + (ihLocal.stringToHex(ihByte)); + ihLocal.startSegmentAddress.csRegister <<= 8; + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + ihLocal.startSegmentAddress.csRegister += + static_cast + (ihLocal.stringToHex(ihByte)); + + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + ihLocal.startSegmentAddress.ipRegister = + static_cast + (ihLocal.stringToHex(ihByte)); + ihLocal.startSegmentAddress.ipRegister <<= 8; + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + ihLocal.startSegmentAddress.ipRegister += + static_cast + (ihLocal.stringToHex(ihByte)); + } + /* Note an error if the start seg. address already */ + /* exists */ + else if (ihLocal.startSegmentAddress.exists == true) + { + string message; + + message = "Start Segment Address record appears again @ line " + + ihLocal.ulToString(lineCounter) + + "; repeated record ignored."; + + ihLocal.addError(message); + } + /* Note an error if the start lin. address already */ + /* exists as they should be mutually exclusive */ + if (ihLocal.startLinearAddress.exists == true) + { + string message; + + message = "Start Segment Address record found @ line " + + ihLocal.ulToString(lineCounter) + + " but Start Linear Address already exists."; + + ihLocal.addError(message); + } + /* Note an error if the record lenght is not 4 as */ + /* expected */ + if (recordLength != 4) + { + string message; + + message = "Start Segment Address @ line " + + ihLocal.ulToString(lineCounter) + + " not 4 bytes as required."; + + ihLocal.addError(message); + } + if (ihLocal.verbose == true) + { + cout << "Start Seg. Address - CS 0x" << + ihLocal.ulToHexString(ihLocal.startSegmentAddress.csRegister) << + " IP 0x" << + ihLocal.ulToHexString(ihLocal.startSegmentAddress.ipRegister) + << endl; + } + break; + + case EXTENDED_LINEAR_ADDRESS: + /* Make sure we have 2 bytes of data */ + if (recordLength == 2) + { + /* Extract the two bytes of the ELA */ + unsigned long extLinAddress = 0; + + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + extLinAddress = static_cast + (ihLocal.stringToHex(ihByte)); + extLinAddress <<= 8; + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + extLinAddress += static_cast + (ihLocal.stringToHex(ihByte)); + + /* ELA is bits 16-31 of the segment base address */ + /* (SBA), so shift left 16 bits */ + extLinAddress <<= 16; + + /* Update the SBA */ + ihLocal.segmentBaseAddress = extLinAddress; + } + else + { + /* Note the error */ + //cout << "Error in Ext. Lin. Address" << endl; + + string message; + + message = "Extended Linear Address @ line " + + ihLocal.ulToString(lineCounter) + + " not 2 bytes as required."; + + ihLocal.addError(message); + } + if (ihLocal.verbose == true) + { + cout << "Ext. Lin. Address 0x" << + ihLocal.ulToHexString(ihLocal.segmentBaseAddress) + << endl; + } + + break; + + case START_LINEAR_ADDRESS: + /* Make sure we have 4 bytes of data */ + if (recordLength == 4 && + ihLocal.startLinearAddress.exists == false) + { + /* Extract the four bytes of the SLA */ + ihLocal.startLinearAddress.eipRegister = 0; + + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + ihLocal.startLinearAddress.eipRegister = + static_cast + (ihLocal.stringToHex(ihByte)); + ihLocal.startLinearAddress.eipRegister <<= 8; + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + ihLocal.startLinearAddress.eipRegister += + static_cast + (ihLocal.stringToHex(ihByte)); + ihLocal.startLinearAddress.eipRegister <<= 8; + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + ihLocal.startLinearAddress.eipRegister += + static_cast + (ihLocal.stringToHex(ihByte)); + ihLocal.startLinearAddress.eipRegister <<= 8; + ihByte.erase(); + ihByte = *ihLineIterator; + ++ihLineIterator; + ihByte += *ihLineIterator; + ++ihLineIterator; + ihLocal.startLinearAddress.eipRegister += + static_cast + (ihLocal.stringToHex(ihByte)); + } + /* Note an error if the start seg. address already */ + /* exists */ + else if (ihLocal.startLinearAddress.exists == true) + { + string message; + + message = "Start Linear Address record appears again @ line " + + ihLocal.ulToString(lineCounter) + + "; repeated record ignored."; + + ihLocal.addError(message); + } + /* Note an error if the start seg. address already */ + /* exists as they should be mutually exclusive */ + if (ihLocal.startSegmentAddress.exists == true) + { + string message; + + message = "Start Linear Address record found @ line " + + ihLocal.ulToString(lineCounter) + + " but Start Segment Address already exists."; + + ihLocal.addError(message); + } + /* Note an error if the record lenght is not 4 as */ + /* expected */ + if (recordLength != 4) + { + string message; + + message = "Start Linear Address @ line " + + ihLocal.ulToString(lineCounter) + + " not 4 bytes as required."; + + ihLocal.addError(message); + } + if (ihLocal.verbose == true) + { + cout << "Start Lin. Address - EIP 0x" << + ihLocal.ulToHexString(ihLocal.startLinearAddress.eipRegister) + << endl; + } + break; + + default: + /* Handle the error here */ + if (ihLocal.verbose == true) + { + cout << "Unknown Record @ line " << + ihLocal.ulToString(lineCounter) << endl; + } + + + string message; + + message = "Unknown Intel HEX record @ line " + + ihLocal.ulToString(lineCounter); + + ihLocal.addError(message); + + break; + } + } + else + { + /* Note that the checksum contained an error */ + string message; + + message = "Checksum error @ line " + + ihLocal.ulToString(lineCounter) + + "; calculated 0x" + + ihLocal.ucToHexString(intelHexChecksum - byteRead) + + " expected 0x" + + ihLocal.ucToHexString(byteRead); + + ihLocal.addError(message); + } + } + } while (ihLine.length() > 0); + + if (ihLocal.verbose == true) + { + cout << "Decoded " << lineCounter << " lines from file." << endl; + } + + return(dataIn); +} + +/******************************************************************************* +* Output Stream for Intel HEX File Encoding (friend function) +*******************************************************************************/ +ostream& operator<<(ostream& dataOut, intelhex& ihLocal) +{ + /* Stores the address offset needed by the linear/segment address records */ + unsigned long addressOffset; + /* Iterator into the ihContent - where the addresses & data are stored */ + map::iterator ihIterator; + /* Holds string that represents next record to be written */ + string thisRecord; + /* Checksum calculation variable */ + unsigned char checksum; + + thisRecord.clear(); + + /* Check that there is some content to encode */ + if (ihLocal.ihContent.size() > 0) + { + /* Calculate the Linear/Segment address */ + ihIterator = ihLocal.ihContent.begin(); + addressOffset = (*ihIterator).first; + checksum = 0; + + /* Construct the first record to define the segment base address */ + if (ihLocal.segmentAddressMode == false) + { + unsigned char dataByte; + + addressOffset >>= 16; + + thisRecord = ":02000004"; + checksum = 0x02 + 0x04; + + dataByte = static_cast(addressOffset & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + dataByte = static_cast((addressOffset >> 8) & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF)); + } + else + { + unsigned char dataByte; + + addressOffset >>= 4; + + thisRecord = ":02000002"; + checksum = 0x02 + 0x02; + + dataByte = static_cast(addressOffset & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + dataByte = static_cast((addressOffset >> 8) & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF)); + } + + /* Output the record */ + dataOut << thisRecord << endl; + + /* Now loop through all the available data and insert into file */ + /* with maximum 16 bytes per line, and making sure to keep the */ + /* segment base address up to date */ + vector recordData; + unsigned long previousAddress; + unsigned long currentAddress; + unsigned long loadOffset; + + while(ihIterator != ihLocal.ihContent.end()) + { + /* Check to see if we need to start a new linear/segment section */ + loadOffset = (*ihIterator).first; + + /* If we are using the linear mode... */ + if (ihLocal.segmentAddressMode == false) + { + if ((loadOffset >> 16) != addressOffset) + { + unsigned char dataByte; + + thisRecord.clear(); + checksum = 0; + + addressOffset = loadOffset; + addressOffset >>= 16; + + thisRecord = ":02000004"; + checksum = 0x02 + 0x04; + + dataByte = static_cast(addressOffset & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + dataByte = static_cast((addressOffset >> 8) & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF)); + + /* Output the record */ + dataOut << thisRecord << endl; + } + } + /* ...otherwise assume segment mode */ + else + { + if ((loadOffset >> 4) != addressOffset) + { + unsigned char dataByte; + + thisRecord.clear(); + checksum = 0; + + addressOffset = loadOffset; + addressOffset >>= 4; + + thisRecord = ":02000002"; + checksum = 0x02 + 0x02; + + dataByte = static_cast(addressOffset & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + dataByte = static_cast((addressOffset >> 8) & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF)); + + /* Output the record */ + dataOut << thisRecord << endl; + } + } + + /* Prepare for encoding next data record */ + thisRecord.clear(); + checksum = 0; + recordData.clear(); + + /* We need to check where the data actually starts, but only the */ + /* bottom 16-bits; the other bits are in the segment/linear */ + /* address record */ + loadOffset = (*ihIterator).first & 0xFFFF; + + /* Loop through and collect up to 16 bytes of data */ + for (int x = 0; x < 16; x++) + { + currentAddress = (*ihIterator).first & 0xFFFF; + + recordData.push_back((*ihIterator).second); + + ihIterator++; + + /* Check that we haven't run out of data */ + if (ihIterator == ihLocal.ihContent.end()) + { + break; + } + + /* Check that the next address is consecutive */ + previousAddress = currentAddress; + currentAddress = (*ihIterator).first & 0xFFFF; + if (currentAddress != (previousAddress + 1)) + { + break; + } + + /* If we got here we have a consecutive address and can keep */ + /* building up the data portion of the data record */ + } + + /* Now we should have some data to encode; check first */ + if (recordData.size() > 0) + { + vector::iterator itData; + unsigned char dataByte; + + /* Start building data record */ + thisRecord = ":"; + + /* Start with the RECLEN record length */ + dataByte = static_cast(recordData.size()); + thisRecord += ihLocal.ucToHexString(dataByte); + checksum += dataByte; + + /* Then the LOAD OFFSET */ + dataByte = static_cast((loadOffset >> 8) & 0xFF); + thisRecord += ihLocal.ucToHexString(dataByte); + checksum += dataByte; + dataByte = static_cast(loadOffset & 0xFF); + thisRecord += ihLocal.ucToHexString(dataByte); + checksum += dataByte; + + /* Then the RECTYP record type (no need to add to checksum - */ + /* value is zero '00' */ + thisRecord += "00"; + + /* Now we add the data */ + for (itData = recordData.begin(); itData != recordData.end(); itData ++) + { + dataByte = (*itData); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + } + + /* Last bit - add the checksum */ + thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF)); + + /* Now write the record */ + dataOut << thisRecord << endl; + } + } + } + + /* If there is a segment start address, output the data */ + if (ihLocal.startSegmentAddress.exists == true) + { + unsigned char dataByte; + + thisRecord.clear(); + checksum = 0; + + thisRecord = ":04000003"; + checksum = 0x04 + 0x03; + + dataByte = static_cast((ihLocal.startSegmentAddress.csRegister >> 8) & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + dataByte = static_cast(ihLocal.startSegmentAddress.csRegister & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + dataByte = static_cast((ihLocal.startSegmentAddress.ipRegister >> 8) & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + dataByte = static_cast(ihLocal.startSegmentAddress.ipRegister & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + + /* Last bit - add the checksum */ + thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF)); + + /* Now write the record */ + dataOut << thisRecord << endl; + } + + /* If there is a linear start address, output the data */ + if (ihLocal.startLinearAddress.exists == true) + { + unsigned char dataByte; + + thisRecord.clear(); + checksum = 0; + + thisRecord = ":04000005"; + checksum = 0x04 + 0x05; + + dataByte = static_cast((ihLocal.startLinearAddress.eipRegister >> 24) & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + dataByte = static_cast((ihLocal.startLinearAddress.eipRegister >> 16) & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + dataByte = static_cast((ihLocal.startLinearAddress.eipRegister >> 8) & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + dataByte = static_cast(ihLocal.startLinearAddress.eipRegister & 0xFF); + checksum += dataByte; + thisRecord += ihLocal.ucToHexString(dataByte); + + + /* Last bit - add the checksum */ + thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF)); + + /* Now write the record */ + dataOut << thisRecord << endl; + } + + /* Whatever happened, we can always output the EOF record */ + dataOut << ":00000001FF" << endl; + + return (dataOut); +} + +/******************************************************************************* +* +* INTEL HEX FILE CLASS MODULE END +* +*******************************************************************************/ From 1f5cdc6199a131e59653d156413a4666001bd368 Mon Sep 17 00:00:00 2001 From: MrMarteng Date: Sat, 30 Apr 2022 11:46:38 +0200 Subject: [PATCH 2/2] Delete intelhexclass.cpp.bak --- intelhex_class/intelhexclass.cpp.bak | 1140 -------------------------- 1 file changed, 1140 deletions(-) delete mode 100644 intelhex_class/intelhexclass.cpp.bak diff --git a/intelhex_class/intelhexclass.cpp.bak b/intelhex_class/intelhexclass.cpp.bak deleted file mode 100644 index 96d3e49..0000000 --- a/intelhex_class/intelhexclass.cpp.bak +++ /dev/null @@ -1,1140 +0,0 @@ -/******************************************************************************* -* -* INTEL HEX FILE CLASS MODULE -* -*******************************************************************************/ - -/******************************************************************************/ -/*! -* \file intelhexclass.cpp -* \mainpage -* \image html intelhexclass.png -* \image latex intelhexclass.eps -* \section intro Introduction -* The Intel HEX File class module is designed to encode, decode and manipulate -* the content of Intel HEX format files commonly generated by most toolchains -* for embedded processors and microcontrollers. -* -* It uses standard C++ streams to decode files and store them in memory, and -* encode data stored in memory back into an Intel HEX format file. Once the file -* content is in memory, the content can then be manipulated using the available -* API. -* -* With this class it is possible to create tools that can compare Intel HEX -* files, fill empty space with desired values, splice two or more files -* together to name a few possibilities. -* -* \section contactInfo Contact Information -* For more information and the latest release, please visit this projects home -* page at http://codinghead.github.com/Intel-HEX-Class -* To participate in the project or for other enquiries, please contact Stuart -* Cording at codinghead@gmail.com -* -* \section license Licensing Information -* Copyright (c) 2012 Stuart Cording -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* \section imageInfo Image Information -* Image chosen for this project comes from 'Henkster'. Original image is from -* http://www.sxc.hu/photo/504350 on stock.xchng. -* -* \author Stuart Cording aka CODINGHEAD -* -******************************************************************************** -* \note -* No notes to date (19th Jan 2012) -*******************************************************************************/ - -#include -#include -#include -#ifdef _MSC_FULL_VER -#include -#else -#include -#endif - -#include "intelhexclass.h" - -using namespace std; - -/******************************************************************************/ -/*! Possible record types for Intel HEX file. -* -* List of all possible record types that can be found in an Intel HEX file. -*******************************************************************************/ -enum intelhexRecordType { - DATA_RECORD, - END_OF_FILE_RECORD, - EXTENDED_SEGMENT_ADDRESS, - START_SEGMENT_ADDRESS, - EXTENDED_LINEAR_ADDRESS, - START_LINEAR_ADDRESS, - NO_OF_RECORD_TYPES -}; - -/******************************************************************************* -* Converts a 2 char string to its HEX value -*******************************************************************************/ -unsigned char intelhex::stringToHex(string value) -{ - unsigned char returnValue = 0; - string::iterator valueIterator; - - if(value.length() == 2) - { - valueIterator = value.begin(); - - for (int x=0; x < 2; x++) - { - /* Shift result variable 4 bits to the left */ - returnValue <<= 4; - - if (*valueIterator >= '0' && *valueIterator <= '9') - { - returnValue += - static_cast(*valueIterator - '0'); - } - else if (*valueIterator >= 'A' && *valueIterator <= 'F') - { - returnValue += - static_cast(*valueIterator - 'A' + 10); - } - else if (*valueIterator >= 'a' && *valueIterator <= 'f') - { - returnValue += - static_cast(*valueIterator - 'a' + 10); - } - else - { - /* Error occured - non-HEX value found */ - string message; - - message = "Can't convert byte 0x" + value + " @ 0x" + - ulToHexString(segmentBaseAddress) + " to hex."; - - addError(message); - - returnValue = 0; - } - - /* Iterate to next char in the string */ - ++valueIterator; - } - } - else - { - /* Error occured - more or less than two nibbles in the string */ - string message; - - message = value + " @ 0x" + ulToHexString(segmentBaseAddress) + - " isn't an 8-bit value."; - - addError(message); - } - - return returnValue; -} - -/******************************************************************************* -* Converts an unsigned long to a string in HEX format -*******************************************************************************/ -string intelhex::ulToHexString(unsigned long value) -{ - string returnString; - char localString[50]; - - returnString.erase(); - -#ifdef _MSC_FULL_VER - sprintf_s(localString, 49, "%08lX", value); -#else - snprintf(localString, 49, "%08lX", value); -#endif - - returnString.insert(0, localString); - - return returnString; -} - -/******************************************************************************* -* Converts an unsigned long to a string in DEC format -*******************************************************************************/ -string intelhex::ulToString(unsigned long value) -{ - string returnString; - char localString[50]; - - returnString.erase(); - -#ifdef _MSC_FULL_VER - sprintf_s(localString, 49, "%lu", value); -#else - snprintf(localString, 49, "%lu", value); -#endif - returnString.insert(0, localString); - - return returnString; -} - -/******************************************************************************* -* Converts an unsigned char to a string in HEX format -*******************************************************************************/ -string intelhex::ucToHexString(unsigned char value) -{ - string returnString; - char localString[50]; - - returnString.erase(); - -#ifdef _MSC_FULL_VER - sprintf_s(localString, 49, "%02X", value); -#else - snprintf(localString, 49, "%02X", value); -#endif - - returnString.insert(0, localString); - - return returnString; -} - -/******************************************************************************* -* Adds a warning to the list of warning messages -*******************************************************************************/ -void intelhex::addWarning(string warningMessage) -{ - string localMessage; - - /* Build the message and push the warning message onto the list */ - localMessage += ulToString(msgWarning.noOfWarnings + 1) + " Warning: " - + warningMessage; - - msgWarning.ihWarnings.push_back(localMessage); - - /* Update the number of warning messages */ - msgWarning.noOfWarnings = msgWarning.ihWarnings.size(); -} - -/******************************************************************************* -* Adds an error to the list of error messages -*******************************************************************************/ -void intelhex::addError(string errorMessage) -{ - string localMessage; - - /* Build the message and push the error message onto the list */ - localMessage += ulToString(msgError.noOfErrors + 1) + " Error: " - + errorMessage; - - msgError.ihErrors.push_back(localMessage); - - /* Update the number of error messages */ - msgError.noOfErrors = msgError.ihErrors.size(); -} - -/******************************************************************************* -* Decodes a data record read in from a file -*******************************************************************************/ -void intelhex::decodeDataRecord(unsigned char recordLength, - unsigned long loadOffset, - string::const_iterator data) -{ - /* Variable to store a byte of the record as a two char string */ - string sByteRead; - - /* Variable to store the byte of the record as an u.char */ - unsigned char byteRead; - - /* Calculate new SBA by clearing the low four bytes and then adding the */ - /* current loadOffset for this line of Intel HEX data */ - segmentBaseAddress &= ~(0xFFFFUL); - segmentBaseAddress += loadOffset; - - for (unsigned char x = 0; x < recordLength; x ++) - { - sByteRead.erase(); - - sByteRead = *data; - data++; - sByteRead += *data; - data++; - - byteRead = stringToHex(sByteRead); - - ihReturn=ihContent.insert( - pair(segmentBaseAddress, byteRead)); - - if (ihReturn.second==false) - { - /* If this address already contains the byte we are trying to */ - /* write, this is only a warning */ - if (ihReturn.first->second == byteRead) - { - string message; - - message = "Location 0x" + ulToHexString(segmentBaseAddress) + - " already contains data 0x" + sByteRead; - - addWarning(message); - } - /* Otherwise this is an error */ - else - { - string message; - - message = "Couldn't add 0x" + sByteRead + " @ 0x" + - ulToHexString(segmentBaseAddress) + - "; already contains 0x" + - ucToHexString(ihReturn.first->second); - - addError(message); - } - } - - /* Increment the segment base address */ - ++segmentBaseAddress; - } -} - -/******************************************************************************* -* Input Stream for Intel HEX File Decoding (friend function) -*******************************************************************************/ -istream& operator>>(istream& dataIn, intelhex& ihLocal) -{ - // Create a string to store lines of Intel Hex info - string ihLine; - /* Create a string to store a single byte of Intel HEX info */ - string ihByte; - // Create an iterator for this variable - string::iterator ihLineIterator; - // Create a line counter - unsigned long lineCounter = 0; - // Variable to hold a single byte (two chars) of data - unsigned char byteRead; - // Variable to calculate the checksum for each line - unsigned char intelHexChecksum; - // Variable to hold the record length - unsigned char recordLength; - // Variable to hold the load offset - unsigned long loadOffset; - // Variables to hold the record type - intelhexRecordType recordType; - - do - { - /* Clear the string before this next round */ - ihLine.erase(); - - /* Clear the checksum before processing this line */ - intelHexChecksum = 0; - - /* Get a line of data */ - dataIn >> ihLine; - - /* If the line contained some data, process it */ - if (ihLine.length() > 0) - { - /* Increment line counter */ - lineCounter++; - - /* Set string iterator to start of string */ - ihLineIterator = ihLine.begin(); - - /* Check that we have a ':' record mark at the beginning */ - if (*ihLineIterator != ':') - { - /* Add some warning code here */ - string message; - - message = "Line without record mark ':' found @ line " + - ihLocal.ulToString(lineCounter); - - ihLocal.addWarning(message); - - /* If this is the first line, let's simply give up. Chances */ - /* are this is not an Intel HEX file at all */ - if (lineCounter == 1) - { - message = "Intel HEX File decode aborted; ':' missing in " \ - "first line."; - ihLocal.addError(message); - - /* Erase ihLine content and break out of do...while loop */ - ihLine.erase(); - break; - } - } - else - { - /* Remove the record mark from the string as we don't need it */ - /* anymore */ - ihLine.erase(ihLineIterator); - } - - /* Run through the whole line to check the checksum */ - for (ihLineIterator = ihLine.begin(); - ihLineIterator != ihLine.end(); - /* Nothing - really! */ ) - { - /* Convert the line in pair of chars (making a single byte) */ - /* into single bytes, and then add to the checksum variable. */ - /* By adding all the bytes in a line together *including* the */ - /* checksum byte, we should get a result of '0' at the end. */ - /* If not, there is a checksum error */ - ihByte.erase(); - - ihByte = *ihLineIterator; - ++ihLineIterator; - /* Just in case there are an odd number of chars in the */ - /* just check we didn't reach the end of the string early */ - if (ihLineIterator != ihLine.end()) - { - ihByte += *ihLineIterator; - ++ihLineIterator; - - byteRead = ihLocal.stringToHex(ihByte); - - intelHexChecksum += byteRead; - } - else - { - string message; - - message = "Odd number of characters in line " + - ihLocal.ulToString(lineCounter); - - ihLocal.addError(message); - } - } - - /* Make sure the checksum was ok */ - if (intelHexChecksum == 0) - { - /* Reset iterator back to beginning of the line so we can now */ - /* decode it */ - ihLineIterator = ihLine.begin(); - - /* Clear all the variables associated with decoding a line of */ - /* Intel HEX code. */ - recordLength = 0; - loadOffset = 0; - - /* Get the record length */ - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - recordLength = ihLocal.stringToHex(ihByte); - - /* Get the load offset (2 bytes) */ - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - loadOffset = - static_cast(ihLocal.stringToHex(ihByte)); - loadOffset <<= 8; - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - loadOffset += - static_cast(ihLocal.stringToHex(ihByte)); - - /* Get the record type */ - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - recordType = - static_cast(ihLocal.stringToHex(ihByte)); - - /* Decode the INFO or DATA portion of the record */ - switch (recordType) - { - case DATA_RECORD: - ihLocal.decodeDataRecord(recordLength, loadOffset, - ihLineIterator); - if (ihLocal.verbose == true) - { - cout << "Data Record begining @ 0x" << - ihLocal.ulToHexString(loadOffset) << endl; - } - break; - - case END_OF_FILE_RECORD: - /* Check that the EOF record wasn't already found. If */ - /* it was, generate appropriate error */ - if (ihLocal.foundEof == false) - { - ihLocal.foundEof = true; - } - else - { - string message; - - message = "Additional End Of File record @ line " + - ihLocal.ulToString(lineCounter) + - " found."; - - ihLocal.addError(message); - } - /* Generate error if there were */ - if (ihLocal.verbose == true) - { - cout << "End of File" << endl; - } - break; - - case EXTENDED_SEGMENT_ADDRESS: - /* Make sure we have 2 bytes of data */ - if (recordLength == 2) - { - /* Extract the two bytes of the ESA */ - unsigned long extSegAddress = 0; - - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - extSegAddress = static_cast - (ihLocal.stringToHex(ihByte)); - extSegAddress <<= 8; - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - extSegAddress += static_cast - (ihLocal.stringToHex(ihByte)); - - /* ESA is bits 4-19 of the segment base address */ - /* (SBA), so shift left 4 bits */ - extSegAddress <<= 4; - - /* Update the SBA */ - ihLocal.segmentBaseAddress = extSegAddress; - } - else - { - /* Note the error */ - string message; - - message = "Extended Segment Address @ line " + - ihLocal.ulToString(lineCounter) + - " not 2 bytes as required."; - - ihLocal.addError(message); - } - if (ihLocal.verbose == true) - { - cout << "Ext. Seg. Address found: 0x" << - ihLocal.ulToHexString(ihLocal.segmentBaseAddress) - << endl; - } - - break; - - case START_SEGMENT_ADDRESS: - /* Make sure we have 4 bytes of data, and that no */ - /* Start Segment Address has been found to date */ - if (recordLength == 4 && - ihLocal.startSegmentAddress.exists == false) - { - /* Note that the Start Segment Address has been */ - /* found. */ - ihLocal.startSegmentAddress.exists = true; - /* Clear the two registers, just in case */ - ihLocal.startSegmentAddress.csRegister = 0; - ihLocal.startSegmentAddress.ipRegister = 0; - - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - ihLocal.startSegmentAddress.csRegister = - static_cast - (ihLocal.stringToHex(ihByte)); - ihLocal.startSegmentAddress.csRegister <<= 8; - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - ihLocal.startSegmentAddress.csRegister += - static_cast - (ihLocal.stringToHex(ihByte)); - - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - ihLocal.startSegmentAddress.ipRegister = - static_cast - (ihLocal.stringToHex(ihByte)); - ihLocal.startSegmentAddress.ipRegister <<= 8; - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - ihLocal.startSegmentAddress.ipRegister += - static_cast - (ihLocal.stringToHex(ihByte)); - } - /* Note an error if the start seg. address already */ - /* exists */ - else if (ihLocal.startSegmentAddress.exists == true) - { - string message; - - message = "Start Segment Address record appears again @ line " + - ihLocal.ulToString(lineCounter) + - "; repeated record ignored."; - - ihLocal.addError(message); - } - /* Note an error if the start lin. address already */ - /* exists as they should be mutually exclusive */ - if (ihLocal.startLinearAddress.exists == true) - { - string message; - - message = "Start Segment Address record found @ line " + - ihLocal.ulToString(lineCounter) + - " but Start Linear Address already exists."; - - ihLocal.addError(message); - } - /* Note an error if the record lenght is not 4 as */ - /* expected */ - if (recordLength != 4) - { - string message; - - message = "Start Segment Address @ line " + - ihLocal.ulToString(lineCounter) + - " not 4 bytes as required."; - - ihLocal.addError(message); - } - if (ihLocal.verbose == true) - { - cout << "Start Seg. Address - CS 0x" << - ihLocal.ulToHexString(ihLocal.startSegmentAddress.csRegister) << - " IP 0x" << - ihLocal.ulToHexString(ihLocal.startSegmentAddress.ipRegister) - << endl; - } - break; - - case EXTENDED_LINEAR_ADDRESS: - /* Make sure we have 2 bytes of data */ - if (recordLength == 2) - { - /* Extract the two bytes of the ELA */ - unsigned long extLinAddress = 0; - - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - extLinAddress = static_cast - (ihLocal.stringToHex(ihByte)); - extLinAddress <<= 8; - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - extLinAddress += static_cast - (ihLocal.stringToHex(ihByte)); - - /* ELA is bits 16-31 of the segment base address */ - /* (SBA), so shift left 16 bits */ - extLinAddress <<= 16; - - /* Update the SBA */ - ihLocal.segmentBaseAddress = extLinAddress; - } - else - { - /* Note the error */ - //cout << "Error in Ext. Lin. Address" << endl; - - string message; - - message = "Extended Linear Address @ line " + - ihLocal.ulToString(lineCounter) + - " not 2 bytes as required."; - - ihLocal.addError(message); - } - if (ihLocal.verbose == true) - { - cout << "Ext. Lin. Address 0x" << - ihLocal.ulToHexString(ihLocal.segmentBaseAddress) - << endl; - } - - break; - - case START_LINEAR_ADDRESS: - /* Make sure we have 4 bytes of data */ - if (recordLength == 4 && - ihLocal.startLinearAddress.exists == false) - { - /* Extract the four bytes of the SLA */ - ihLocal.startLinearAddress.eipRegister = 0; - - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - ihLocal.startLinearAddress.eipRegister = - static_cast - (ihLocal.stringToHex(ihByte)); - ihLocal.startLinearAddress.eipRegister <<= 8; - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - ihLocal.startLinearAddress.eipRegister += - static_cast - (ihLocal.stringToHex(ihByte)); - ihLocal.startLinearAddress.eipRegister <<= 8; - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - ihLocal.startLinearAddress.eipRegister += - static_cast - (ihLocal.stringToHex(ihByte)); - ihLocal.startLinearAddress.eipRegister <<= 8; - ihByte.erase(); - ihByte = *ihLineIterator; - ++ihLineIterator; - ihByte += *ihLineIterator; - ++ihLineIterator; - ihLocal.startLinearAddress.eipRegister += - static_cast - (ihLocal.stringToHex(ihByte)); - } - /* Note an error if the start seg. address already */ - /* exists */ - else if (ihLocal.startLinearAddress.exists == true) - { - string message; - - message = "Start Linear Address record appears again @ line " + - ihLocal.ulToString(lineCounter) + - "; repeated record ignored."; - - ihLocal.addError(message); - } - /* Note an error if the start seg. address already */ - /* exists as they should be mutually exclusive */ - if (ihLocal.startSegmentAddress.exists == true) - { - string message; - - message = "Start Linear Address record found @ line " + - ihLocal.ulToString(lineCounter) + - " but Start Segment Address already exists."; - - ihLocal.addError(message); - } - /* Note an error if the record lenght is not 4 as */ - /* expected */ - if (recordLength != 4) - { - string message; - - message = "Start Linear Address @ line " + - ihLocal.ulToString(lineCounter) + - " not 4 bytes as required."; - - ihLocal.addError(message); - } - if (ihLocal.verbose == true) - { - cout << "Start Lin. Address - EIP 0x" << - ihLocal.ulToHexString(ihLocal.startLinearAddress.eipRegister) - << endl; - } - break; - - default: - /* Handle the error here */ - if (ihLocal.verbose == true) - { - cout << "Unknown Record @ line " << - ihLocal.ulToString(lineCounter) << endl; - } - - - string message; - - message = "Unknown Intel HEX record @ line " + - ihLocal.ulToString(lineCounter); - - ihLocal.addError(message); - - break; - } - } - else - { - /* Note that the checksum contained an error */ - string message; - - message = "Checksum error @ line " + - ihLocal.ulToString(lineCounter) + - "; calculated 0x" + - ihLocal.ucToHexString(intelHexChecksum - byteRead) + - " expected 0x" + - ihLocal.ucToHexString(byteRead); - - ihLocal.addError(message); - } - } - } while (ihLine.length() > 0); - - if (ihLocal.verbose == true) - { - cout << "Decoded " << lineCounter << " lines from file." << endl; - } - - return(dataIn); -} - -/******************************************************************************* -* Output Stream for Intel HEX File Encoding (friend function) -*******************************************************************************/ -ostream& operator<<(ostream& dataOut, intelhex& ihLocal) -{ - /* Stores the address offset needed by the linear/segment address records */ - unsigned long addressOffset; - /* Iterator into the ihContent - where the addresses & data are stored */ - map::iterator ihIterator; - /* Holds string that represents next record to be written */ - string thisRecord; - /* Checksum calculation variable */ - unsigned char checksum; - - thisRecord.clear(); - - /* Check that there is some content to encode */ - if (ihLocal.ihContent.size() > 0) - { - /* Calculate the Linear/Segment address */ - ihIterator = ihLocal.ihContent.begin(); - addressOffset = (*ihIterator).first; - checksum = 0; - - /* Construct the first record to define the segment base address */ - if (ihLocal.segmentAddressMode == false) - { - unsigned char dataByte; - - addressOffset >>= 16; - - thisRecord = ":02000004"; - checksum = 0x02 + 0x04; - - dataByte = static_cast(addressOffset & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - dataByte = static_cast((addressOffset >> 8) & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF)); - } - else - { - unsigned char dataByte; - - addressOffset >>= 4; - - thisRecord = ":02000002"; - checksum = 0x02 + 0x02; - - dataByte = static_cast(addressOffset & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - dataByte = static_cast((addressOffset >> 8) & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF)); - } - - /* Output the record */ - dataOut << thisRecord << endl; - - /* Now loop through all the available data and insert into file */ - /* with maximum 16 bytes per line, and making sure to keep the */ - /* segment base address up to date */ - vector recordData; - unsigned long previousAddress; - unsigned long currentAddress; - unsigned long loadOffset; - - while(ihIterator != ihLocal.ihContent.end()) - { - /* Check to see if we need to start a new linear/segment section */ - loadOffset = (*ihIterator).first; - - /* If we are using the linear mode... */ - if (ihLocal.segmentAddressMode == false) - { - if ((loadOffset >> 16) != addressOffset) - { - unsigned char dataByte; - - thisRecord.clear(); - checksum = 0; - - addressOffset = loadOffset; - addressOffset >>= 16; - - thisRecord = ":02000004"; - checksum = 0x02 + 0x04; - - dataByte = static_cast(addressOffset & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - dataByte = static_cast((addressOffset >> 8) & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF)); - - /* Output the record */ - dataOut << thisRecord << endl; - } - } - /* ...otherwise assume segment mode */ - else - { - if ((loadOffset >> 4) != addressOffset) - { - unsigned char dataByte; - - thisRecord.clear(); - checksum = 0; - - addressOffset = loadOffset; - addressOffset >>= 4; - - thisRecord = ":02000002"; - checksum = 0x02 + 0x02; - - dataByte = static_cast(addressOffset & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - dataByte = static_cast((addressOffset >> 8) & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF)); - - /* Output the record */ - dataOut << thisRecord << endl; - } - } - - /* Prepare for encoding next data record */ - thisRecord.clear(); - checksum = 0; - recordData.clear(); - - /* We need to check where the data actually starts, but only the */ - /* bottom 16-bits; the other bits are in the segment/linear */ - /* address record */ - loadOffset = (*ihIterator).first & 0xFFFF; - - /* Loop through and collect up to 16 bytes of data */ - for (int x = 0; x < 16; x++) - { - currentAddress = (*ihIterator).first & 0xFFFF; - - recordData.push_back((*ihIterator).second); - - ihIterator++; - - /* Check that we haven't run out of data */ - if (ihIterator == ihLocal.ihContent.end()) - { - break; - } - - /* Check that the next address is consecutive */ - previousAddress = currentAddress; - currentAddress = (*ihIterator).first & 0xFFFF; - if (currentAddress != (previousAddress + 1)) - { - break; - } - - /* If we got here we have a consecutive address and can keep */ - /* building up the data portion of the data record */ - } - - /* Now we should have some data to encode; check first */ - if (recordData.size() > 0) - { - vector::iterator itData; - unsigned char dataByte; - - /* Start building data record */ - thisRecord = ":"; - - /* Start with the RECLEN record length */ - dataByte = static_cast(recordData.size()); - thisRecord += ihLocal.ucToHexString(dataByte); - checksum += dataByte; - - /* Then the LOAD OFFSET */ - dataByte = static_cast((loadOffset >> 8) & 0xFF); - thisRecord += ihLocal.ucToHexString(dataByte); - checksum += dataByte; - dataByte = static_cast(loadOffset & 0xFF); - thisRecord += ihLocal.ucToHexString(dataByte); - checksum += dataByte; - - /* Then the RECTYP record type (no need to add to checksum - */ - /* value is zero '00' */ - thisRecord += "00"; - - /* Now we add the data */ - for (itData = recordData.begin(); itData != recordData.end(); itData ++) - { - dataByte = (*itData); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - } - - /* Last bit - add the checksum */ - thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF)); - - /* Now write the record */ - dataOut << thisRecord << endl; - } - } - } - - /* If there is a segment start address, output the data */ - if (ihLocal.startSegmentAddress.exists == true) - { - unsigned char dataByte; - - thisRecord.clear(); - checksum = 0; - - thisRecord = ":04000003"; - checksum = 0x04 + 0x03; - - dataByte = static_cast((ihLocal.startSegmentAddress.csRegister >> 8) & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - dataByte = static_cast(ihLocal.startSegmentAddress.csRegister & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - dataByte = static_cast((ihLocal.startSegmentAddress.ipRegister >> 8) & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - dataByte = static_cast(ihLocal.startSegmentAddress.ipRegister & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - - /* Last bit - add the checksum */ - thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF)); - - /* Now write the record */ - dataOut << thisRecord << endl; - } - - /* If there is a linear start address, output the data */ - if (ihLocal.startLinearAddress.exists == true) - { - unsigned char dataByte; - - thisRecord.clear(); - checksum = 0; - - thisRecord = ":04000005"; - checksum = 0x04 + 0x05; - - dataByte = static_cast((ihLocal.startLinearAddress.eipRegister >> 24) & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - dataByte = static_cast((ihLocal.startLinearAddress.eipRegister >> 16) & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - dataByte = static_cast((ihLocal.startLinearAddress.eipRegister >> 8) & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - dataByte = static_cast(ihLocal.startLinearAddress.eipRegister & 0xFF); - checksum += dataByte; - thisRecord += ihLocal.ucToHexString(dataByte); - - - /* Last bit - add the checksum */ - thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF)); - - /* Now write the record */ - dataOut << thisRecord << endl; - } - - /* Whatever happened, we can always output the EOF record */ - dataOut << ":00000001FF" << endl; - - return (dataOut); -} - -/******************************************************************************* -* -* INTEL HEX FILE CLASS MODULE END -* -*******************************************************************************/