1160 lines
43 KiB
C++
1160 lines
43 KiB
C++
/*******************************************************************************
|
|
* intelhexclass - class definitions *
|
|
* *
|
|
* A class to handle the encoding and decoding of an Intel HEX format file as *
|
|
* generated by many tool chains for embedded processors and microcontrollers. *
|
|
* *
|
|
* This class is constructed based upon the definition given in the document *
|
|
* 'Hexadecimal Object File Format Specification', Revision A, January 6, 1988, *
|
|
* © 1998 Intel Corporation *
|
|
*------------------------------------------------------------------------------*
|
|
* class intelhex *
|
|
* Member Functions: *
|
|
* *
|
|
*******************************************************************************/
|
|
|
|
/******************************************************************************/
|
|
/*! \file intelhexclass.h
|
|
* \author Stuart Cording aka CODINGHEAD
|
|
*
|
|
* A class to handle the encoding, decoding and manipulatio of an Intel HEX
|
|
* format file as generated by many tool chains for embedded processors and
|
|
* microcontrollers.
|
|
*
|
|
* This class is constructed based upon the definition given in the document
|
|
* 'Hexadecimal Object File Format Specification', Revision A, January 6, 1988,
|
|
* © 1998 Intel Corporation.
|
|
********************************************************************************
|
|
* \note See the git versioning notes for version information
|
|
*
|
|
*******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* INTEL HEX CLASS MODULE
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#ifndef INTELHEXCLASS_MODULE_PRESENT__
|
|
#define INTELHEXCLASS_MODULE_PRESENT__
|
|
|
|
/*******************************************************************************
|
|
* INCLUDE FILES
|
|
*******************************************************************************/
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <list>
|
|
|
|
/*******************************************************************************
|
|
* EXTERNS
|
|
*******************************************************************************/
|
|
|
|
|
|
/*******************************************************************************
|
|
* DEFAULT CONFIGURATION
|
|
*******************************************************************************/
|
|
|
|
|
|
/*******************************************************************************
|
|
* DEFINES
|
|
*******************************************************************************/
|
|
|
|
using namespace std;
|
|
|
|
/******************************************************************************/
|
|
/*! \cond
|
|
* class - intelhex
|
|
* \endcond
|
|
*
|
|
* \brief Class to decode, encode and manipulate Intel HEX format files.
|
|
*
|
|
* The Intel HEX class allows the user to stream in the content of an Intel HEX
|
|
* file so that its content can by analysed more easily than trying to decode
|
|
* the Intel HEX file in a text editor. In conjunction with a suitable
|
|
* application it is possible to create content, analyse content and even compare
|
|
* the content of files with one another.
|
|
*******************************************************************************/
|
|
class intelhex {
|
|
/**********************************************************************/
|
|
/*! \brief Output stream overload operator.
|
|
*
|
|
* Operator overloaded to encode any data held in memory into the Intel
|
|
* HEX format for storage on disk
|
|
*
|
|
* \sa operator>>()
|
|
*
|
|
* \param dataOut - Output stream for to store the decoded file
|
|
* information
|
|
* \param ihLocal - Points to this class so that friend function has
|
|
* access to private class members
|
|
*
|
|
* \retval - pointer to output stream
|
|
***********************************************************************/
|
|
friend ostream& operator<<(ostream& dataOut,
|
|
intelhex& ihLocal);
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Input stream overload operator.
|
|
*
|
|
* Operator overloaded to decode data streamed in from a file in the
|
|
* Intel HEX format into memory
|
|
*
|
|
* \sa operator<<()
|
|
*
|
|
* \param dataIn - Input stream for the encoded file information
|
|
* \param ihLocal - Points to this class so that friend function has
|
|
* access to private class members
|
|
*
|
|
* \retval - pointer to input stream
|
|
***********************************************************************/
|
|
friend istream& operator>>(istream& dataIn,
|
|
intelhex& ihLocal);
|
|
|
|
private:
|
|
/**********************************************************************/
|
|
/*! \brief Container for decoded Intel HEX content.
|
|
*
|
|
* STL map holding the addresses found in the Intel HEX file and the
|
|
* associated data byte stored at that address
|
|
***********************************************************************/
|
|
map<unsigned long, unsigned char> ihContent;
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Iterator for the container holding the decoded Intel HEX
|
|
* content.
|
|
*
|
|
* This iterator is used by the class to point to the location in memory
|
|
* currently being used to read or write data. If no file has been
|
|
* loaded into memory, it points to the start of ihContent.
|
|
***********************************************************************/
|
|
map<unsigned long, unsigned char>::iterator ihIterator;
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Pair for the container holding the decoded Intel HEX content.
|
|
*
|
|
* This is used to acquire the result of an attempt to insert new data
|
|
* into ihContent. Since the ihContent is a map STL, it can't allow
|
|
* data to be assigned to the same address more than once. In this way we
|
|
* can ensure that no address in a file is falsely assigned data more
|
|
* than once.
|
|
***********************************************************************/
|
|
pair<map<unsigned long, unsigned char>::iterator,bool> ihReturn;
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Stores segment base address of Intel HEX file.
|
|
*
|
|
* The segment base address is a 32-bit address to which the current
|
|
* load offset (as found in a Data Record line of the Intel HEX file) is
|
|
* added to calculate the actual address of the data. The Data Records
|
|
* can only point to a 64kByte address, so the segment base address
|
|
* expands the addressing to 4GB. This variable always holds the last
|
|
* address accessed. This variable is only used during file decoding
|
|
* and encoding in the operator<< and operator>> class member friend
|
|
* functions.
|
|
***********************************************************************/
|
|
unsigned long segmentBaseAddress;
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Stores the content of the CS/IP Registers, if used.
|
|
*
|
|
* Used to store the content of the CS and IS Register for HEX files
|
|
* created for x286 or earlier Intel processors. This information is
|
|
* retrieved from the Start Segment Address Record or can be defined
|
|
* by the user using the setStartSegmentAddress() function.
|
|
* The found element defines if these registers hold valid data or not.
|
|
*
|
|
* \param csRegister - content of the CS register
|
|
* \param ipRegister - content of the IP register
|
|
* \param exists - defines if values for the above registers have
|
|
* been written (true) or not (false)
|
|
*
|
|
* \sa getStartSegmentAddress(), setStartSegmentAddress()
|
|
***********************************************************************/
|
|
struct {
|
|
unsigned short csRegister;
|
|
unsigned short ipRegister;
|
|
bool exists;
|
|
} startSegmentAddress;
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Stores the content of the EIP Register, if used.
|
|
*
|
|
* Used to store the content of the EIP Register for HEX files created
|
|
* for x386 Intel processors. This information is retrieved from the
|
|
* the Start Linear Address Record or can be defined by using the
|
|
* setStartLinearAddress() function.
|
|
* The found element defines if this register holds valid data or not.
|
|
*
|
|
* \param eipRegister - content of the EIP register
|
|
* \param exists - defines if a value for the above register has
|
|
* been written (true) or not (false)
|
|
*
|
|
* \sa getStartLinearAddress(), setStartLinearAddress()
|
|
***********************************************************************/
|
|
struct {
|
|
unsigned long eipRegister;
|
|
bool exists;
|
|
} startLinearAddress;
|
|
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Structure to hold warning messages.
|
|
*
|
|
* Holds warning messages generated during encoding/decoding process and
|
|
* number of messages currently present in system
|
|
*
|
|
* \param ihWarnings - list of warning messages as strings
|
|
* \param noOfWarnings - no of warning messages still present in
|
|
* the list
|
|
***********************************************************************/
|
|
struct {
|
|
list<string> ihWarnings;
|
|
unsigned long noOfWarnings;
|
|
} msgWarning;
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Structure to hold error messages.
|
|
*
|
|
* Holds error messages generated during encoding/decoding process and
|
|
* number of messages currently present in system
|
|
*
|
|
* \param ihErrors - list of error messages as strings
|
|
* \param noOferrors - no of error messages still present in the
|
|
* list
|
|
***********************************************************************/
|
|
struct {
|
|
list<string> ihErrors;
|
|
unsigned long noOfErrors;
|
|
} msgError;
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Note that EOF record is found.
|
|
*
|
|
* Used to note that the EOF record was found in order to ensure that it
|
|
* doesn't appear twice during encoding.
|
|
***********************************************************************/
|
|
bool foundEof;
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Select verbose mode.
|
|
*
|
|
* Used during development to display messages as the incoming data
|
|
* stream is decoded
|
|
***********************************************************************/
|
|
bool verbose;
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Select segment address mode.
|
|
*
|
|
* If true, use the segment addressing mode when encoding files.
|
|
* otherwise the default linear address mode will be used. Please refer
|
|
* to Intel's Hexadecimal Object File Format Specifiation for further
|
|
* information.
|
|
***********************************************************************/
|
|
bool segmentAddressMode;
|
|
|
|
/***********************************************************************
|
|
* \brief Converts a 2 char string to its HEX value.
|
|
*
|
|
* Converts a two byte string to its equivalent value in hexadecimal
|
|
*
|
|
* \param value - a two character, valid ASCII representation of
|
|
* a hexadecimal value
|
|
*
|
|
* \retval 'value' valid - 8-bit value
|
|
* \retval 'value' invalid - 0x00 and calls addWarning()
|
|
*
|
|
* \note
|
|
* This function will post a warning message using the warning handling
|
|
* system addWarning() if:
|
|
* -# The string contains anything other that exactly two characters
|
|
* -# The string contains anything other than the characters 0-9, a-f
|
|
* and A-F
|
|
*
|
|
* \sa ulToHexString(), ucToHexString(), ulToString()
|
|
***********************************************************************/
|
|
unsigned char stringToHex(string value);
|
|
|
|
/***********************************************************************
|
|
* \brief Converts an unsigned long to a string in HEX format.
|
|
*
|
|
* Takes the received paramter and converts it into its equivalent value
|
|
* represented in ASCII and formatted in hexadecimal. Return value is an
|
|
* 8 character long string, prefaced with '0's where necessary.
|
|
*
|
|
* \param value - a value between 0x0000000 and 0xFFFFFFFF
|
|
*
|
|
* \retval - 8-character long string
|
|
*
|
|
* \note
|
|
* Alpha characters are capitalised.
|
|
*
|
|
* \sa
|
|
* stringToHex(), ucToHexString(), ulToString()
|
|
***********************************************************************/
|
|
string ulToHexString(unsigned long value);
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Converts an unsigned char to a string in HEX format.
|
|
*
|
|
* Takes the received paramter and converts it into its equivalent value
|
|
* represented in ASCII and formatted in hexadecimal. Return value is a
|
|
* 2 character long string, prefaced with '0' where necessary.
|
|
*
|
|
* \param value - a value between 0x00 and 0xFF
|
|
*
|
|
* \retval - 2-character long string
|
|
*
|
|
* \note
|
|
* Alpha characters are capitalised.
|
|
*
|
|
* \sa
|
|
* stringToHex(), ulToHexString(), ulToString()
|
|
***********************************************************************/
|
|
string ucToHexString(unsigned char value);
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Converts an unsigned long to a string in DEC format.
|
|
*
|
|
* Takes the received paramter and converts it into its equivalent value
|
|
* represented in ASCII and formatted in decimal. Return value will never
|
|
* be longer than a 48 character long string.
|
|
*
|
|
* \param value - value to be converted
|
|
*
|
|
* \retval - ASCII string representation of value
|
|
*
|
|
* \sa
|
|
* stringToHex(), ulToHexString(), ucToHexString()
|
|
***********************************************************************/
|
|
string ulToString(unsigned long value);
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Decodes the data content of a data record.
|
|
*
|
|
* Takes the data element of a data record in string format, converts
|
|
* each 2 char element into a single byte and then inserts that byte of
|
|
* data into the ihContent STL map.
|
|
*
|
|
* \sa encodeDataRecord()
|
|
*
|
|
* \param recordLength - Number of bytes in this record as extracted
|
|
* from this line in the Intel HEX file
|
|
* \param loadOffset - The offset from the segment base address for
|
|
* the first byte in this record
|
|
* \param data - The data content of the record in a string
|
|
***********************************************************************/
|
|
void decodeDataRecord(unsigned char recordLength,
|
|
unsigned long loadOffset,
|
|
string::const_iterator data);
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Add a warning message to the warning message list.
|
|
*
|
|
*
|
|
* \param warningMessage - the text to be added for this warning
|
|
***********************************************************************/
|
|
void addWarning(string warningMessage);
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Add an error message to the error message list.
|
|
*
|
|
* \param errorMessage - the text to be added for this error
|
|
***********************************************************************/
|
|
void addError(string errorMessage);
|
|
|
|
public:
|
|
/**********************************************************************/
|
|
/*! \brief intelhex Class Constructor.
|
|
*
|
|
* Important initialisation steps performed here:
|
|
* - clear segment base address to zero
|
|
* - clear all x86 start address registers to zero
|
|
* - note that there are, as yet, no errors or warnings
|
|
* - note that the EOF record has not yet been found
|
|
* - set verbode mode to 'false' (default)
|
|
* - initialise class ihIterator
|
|
***********************************************************************/
|
|
intelhex()
|
|
{
|
|
/* Initialise the segment base address to zero */
|
|
segmentBaseAddress = 0;
|
|
/* Clear content of register variables used with the 'Start Segment'
|
|
* and 'Start Linear' address records */
|
|
startSegmentAddress.ipRegister = 0;
|
|
startSegmentAddress.csRegister = 0;
|
|
startSegmentAddress.exists = false;
|
|
startLinearAddress.eipRegister = 0;
|
|
startLinearAddress.exists = false;
|
|
/* Set up error and warning handling variables */
|
|
msgWarning.noOfWarnings = 0;
|
|
msgError.noOfErrors = 0;
|
|
/* Note that the EOF record has not been found yet */
|
|
foundEof = false;
|
|
/* Set verbose mode to off */
|
|
verbose = false;
|
|
/* Set segment address mode to false (default) */
|
|
segmentAddressMode = false;
|
|
/* Ensure ihContent is cleared and point ihIterator at it */
|
|
ihContent.clear();
|
|
ihContent.begin();
|
|
ihIterator = ihContent.begin();
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief intelhex Class Deconstructor.
|
|
*
|
|
* Currently the deconstructor is intentially empty.
|
|
***********************************************************************/
|
|
~intelhex()
|
|
{
|
|
/* Currently nothing */
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief intelhex Class Copy Constructor.
|
|
*
|
|
* Copy constructor copies all essential elements for the class.
|
|
***********************************************************************/
|
|
intelhex(const intelhex &ihSource)
|
|
{
|
|
/* Initialise the segment base address */
|
|
segmentBaseAddress = ihSource.segmentBaseAddress;
|
|
/* Initialise content of register variables used with the 'Start Segment'
|
|
* and 'Start Linear' address records */
|
|
startSegmentAddress.ipRegister = ihSource.startSegmentAddress.ipRegister;
|
|
startSegmentAddress.csRegister = ihSource.startSegmentAddress.csRegister;
|
|
startSegmentAddress.exists = ihSource.startSegmentAddress.exists;
|
|
startLinearAddress.eipRegister = ihSource.startLinearAddress.eipRegister;
|
|
startLinearAddress.exists = ihSource.startLinearAddress.exists;
|
|
/* Set up error and warning handling variables */
|
|
msgWarning.noOfWarnings = ihSource.msgWarning.noOfWarnings;
|
|
msgWarning.ihWarnings = ihSource.msgWarning.ihWarnings;
|
|
msgError.noOfErrors = ihSource.msgError.noOfErrors;
|
|
msgError.ihErrors = ihSource.msgError.ihErrors;
|
|
/* Note that the EOF record has not been found yet */
|
|
foundEof = ihSource.foundEof;
|
|
/* Set verbose mode to off */
|
|
verbose = ihSource.verbose;
|
|
/* Set segment address mode to false (default) */
|
|
segmentAddressMode = ihSource.segmentAddressMode;
|
|
/* Copy HEX file content variables */
|
|
ihContent = ihSource.ihContent;
|
|
ihIterator = ihSource.ihIterator;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief intelhex Class Assignment Operator.
|
|
*
|
|
* Implements the assignment operator so that the content of the Intel
|
|
* HEX file in memory can be copied to another 'intelhex' variable.
|
|
* You may want to keep a copy of the original data in memory and
|
|
* only manipulate a copy.
|
|
*
|
|
* \param ihSource - intelhex variable to be assigned to new
|
|
* variable
|
|
*
|
|
* \retval pointer to variable to which value is to be assigned
|
|
***********************************************************************/
|
|
intelhex& operator= (const intelhex &ihSource)
|
|
{
|
|
/* Check that we are not trying to assign ourself to ourself */
|
|
/* i.e. are the source/destination addresses the same like */
|
|
/* myData = myData; */
|
|
if (this == &ihSource)
|
|
return *this;
|
|
|
|
/* Initialise the segment base address */
|
|
segmentBaseAddress = ihSource.segmentBaseAddress;
|
|
/* Initialise content of register variables used with the 'Start Segment'
|
|
* and 'Start Linear' address records */
|
|
startSegmentAddress.ipRegister = ihSource.startSegmentAddress.ipRegister;
|
|
startSegmentAddress.csRegister = ihSource.startSegmentAddress.csRegister;
|
|
startSegmentAddress.exists = ihSource.startSegmentAddress.exists;
|
|
startLinearAddress.eipRegister = ihSource.startLinearAddress.eipRegister;
|
|
startLinearAddress.exists = ihSource.startLinearAddress.exists;
|
|
/* Set up error and warning handling variables */
|
|
msgWarning.noOfWarnings = ihSource.msgWarning.noOfWarnings;
|
|
msgWarning.ihWarnings = ihSource.msgWarning.ihWarnings;
|
|
msgError.noOfErrors = ihSource.msgError.noOfErrors;
|
|
msgError.ihErrors = ihSource.msgError.ihErrors;
|
|
/* Note that the EOF record has not been found yet */
|
|
foundEof = ihSource.foundEof;
|
|
/* Set verbose mode to off */
|
|
verbose = ihSource.verbose;
|
|
/* Set segment address mode to false (default) */
|
|
segmentAddressMode = ihSource.segmentAddressMode;
|
|
/* Copy HEX file content variables */
|
|
ihContent = ihSource.ihContent;
|
|
ihIterator = ihSource.ihIterator;
|
|
|
|
return *this;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Overloaded prefix increment operator
|
|
*
|
|
* Overloads the prefix increment operator to move interal iterator to
|
|
* next entry in the ihContent map
|
|
*
|
|
***********************************************************************/
|
|
intelhex& operator++()
|
|
{
|
|
++ihIterator;
|
|
|
|
return(*this);
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Overloaded postfix increment operator
|
|
*
|
|
* Overloads the postfix increment operator to move interal iterator to
|
|
* next entry in the ihContent map
|
|
*
|
|
***********************************************************************/
|
|
const intelhex operator++(int)
|
|
{
|
|
intelhex tmp(*this);
|
|
++(*this);
|
|
return(tmp);
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Overloaded prefix decrement operator
|
|
*
|
|
* Overloads the prefix decrement operator to move interal iterator to
|
|
* previous entry in the ihContent map
|
|
*
|
|
***********************************************************************/
|
|
intelhex& operator--()
|
|
{
|
|
--ihIterator;
|
|
|
|
return(*this);
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Overloaded postfix decrement operator
|
|
*
|
|
* Overloads the postfix decrement operator to move interal iterator to
|
|
* previous entry in the ihContent map
|
|
*
|
|
***********************************************************************/
|
|
const intelhex operator--(int)
|
|
{
|
|
intelhex tmp(*this);
|
|
--(*this);
|
|
return(tmp);
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Moves the address pointer to the first available address.
|
|
*
|
|
* The address pointer will be moved to the first available address in
|
|
* memory of the decoded file or of the data the user has inserted into
|
|
* memory for the purpose of encoding into the Intel HEX format.
|
|
*
|
|
* \sa end()
|
|
*
|
|
* \note This function has no effect if no file has been as yet decoded
|
|
* and no data has been inserted into memory.
|
|
***********************************************************************/
|
|
void begin()
|
|
{
|
|
if (ihContent.size() != 0)
|
|
{
|
|
ihIterator = ihContent.begin();
|
|
}
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Moves the address pointer to the last available address.
|
|
*
|
|
* The address pointer will be moved to the last available address in
|
|
* memory of the decoded file or of the data the user has inserted into
|
|
* memory for the purpose of encoding into the Intel HEX format.
|
|
*
|
|
* \sa begin()
|
|
*
|
|
* \note This function has no effect if no file has been as yet decoded
|
|
* and no data has been inserted into memory.
|
|
***********************************************************************/
|
|
void end()
|
|
{
|
|
if (!ihContent.empty())
|
|
{
|
|
ihIterator = ihContent.end();
|
|
--ihIterator;
|
|
}
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Returns current size of decoded file
|
|
*
|
|
* The quantity of bytes decoded thus far is returned.
|
|
***********************************************************************/
|
|
unsigned long size()
|
|
{
|
|
return static_cast<unsigned long>(ihContent.size());
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Checks if we have reached end of available data
|
|
*
|
|
* The internal pointer is checked to see if we have reached the end of
|
|
* the data held in memory
|
|
*
|
|
* \retval true - reached the end of the Intel HEX data in memory or no
|
|
* data in memory yet.
|
|
* \retval false - end of Intel HEX data in memory not yet reached.
|
|
***********************************************************************/
|
|
bool endOfData()
|
|
{
|
|
/* Return true if there is no data anyway */
|
|
bool result = true;
|
|
|
|
if (!ihContent.empty())
|
|
{
|
|
map<unsigned long, unsigned char>::iterator it \
|
|
= ihContent.end();
|
|
|
|
--it;
|
|
|
|
if (it != ihIterator)
|
|
{
|
|
result = false;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Indicates if the container for data is empty or not
|
|
*
|
|
* The map container is checked for content.
|
|
*
|
|
* \retval true - the container is empty - no data has been extracted.
|
|
* \retval false - there is data in the container.
|
|
***********************************************************************/
|
|
bool empty()
|
|
{
|
|
return ihContent.empty();
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Moves the address pointer to the desired address.
|
|
*
|
|
* Address pointer will take on the requested address if the address
|
|
* exists in the data stored in memory. If not, the address pointer does
|
|
* not change.
|
|
*
|
|
* \sa currentAddress()
|
|
*
|
|
* \param address - Desired new address for the address pointer
|
|
*
|
|
* \retval true - Address exists; pointer moved successfully
|
|
* \retval false - Address did not exist; pointer not moved
|
|
***********************************************************************/
|
|
bool jumpTo(unsigned long address)
|
|
{
|
|
bool result = false;
|
|
|
|
if (ihContent.size() != 0)
|
|
{
|
|
map<unsigned long, unsigned char>::iterator it;
|
|
it = ihContent.find(address);
|
|
if (it != ihContent.end())
|
|
{
|
|
result = true;
|
|
ihIterator = it;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Increments to next piece of data.
|
|
*
|
|
* Address pointer will take on the address of the next location for
|
|
* which there is data.
|
|
*
|
|
* \sa decrementAddress()
|
|
*
|
|
* \retval true - pointer was incremented; a new data value was found
|
|
* \retval false - end of available data reached; pointer is unchanged
|
|
***********************************************************************/
|
|
bool incrementAddress()
|
|
{
|
|
bool result = false;
|
|
|
|
/* If we have data */
|
|
if (ihContent.size() != 0)
|
|
{
|
|
/* If we're not already pointing to the end */
|
|
if (ihIterator != ihContent.end())
|
|
{
|
|
/* Increment iterator */
|
|
ihIterator++;
|
|
|
|
/* If we still haven't reached the end... */
|
|
if (ihIterator != ihContent.end())
|
|
{
|
|
/* Everything is ok! */
|
|
result = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If incrementation of the iterator was successful, return true */
|
|
return result;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Decrements to next piece of data.
|
|
*
|
|
* Address pointer will take on the address of the previous location for
|
|
* which there is data.
|
|
*
|
|
* \sa incrementAddress()
|
|
*
|
|
* \retval true - pointer was decremented; a new data value was found
|
|
* \retval false - start of available data reached; pointer is unchanged
|
|
***********************************************************************/
|
|
bool decrementAddress()
|
|
{
|
|
bool result = false;
|
|
|
|
/* If we have data */
|
|
if (ihContent.size() != 0)
|
|
{
|
|
/* If we're not already pointing to the start */
|
|
if (ihIterator != ihContent.begin())
|
|
{
|
|
/* Decrement iterator */
|
|
ihIterator--;
|
|
|
|
/* Everything is ok! */
|
|
result = true;
|
|
}
|
|
}
|
|
|
|
/* If incrementation of the iterator was successful, return true */
|
|
return result;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Returns the current address being pointed to.
|
|
*
|
|
* Current address will be returned.
|
|
*
|
|
* \sa jumpTo()
|
|
*
|
|
* \retval Current address being pointed to.
|
|
***********************************************************************/
|
|
unsigned long currentAddress()
|
|
{
|
|
return ihIterator->first;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Returns the lowest address currently available.
|
|
*
|
|
* Returns the first address that appears in the memory if there is data
|
|
* present. If not, no value will be returned.
|
|
*
|
|
* \sa endAddress()
|
|
*
|
|
* \param address - variable to hold address requested
|
|
*
|
|
* \retval true - address existed and returned value is valid
|
|
* \retval false - address did not exist and returned valid is not
|
|
* valid
|
|
***********************************************************************/
|
|
bool startAddress(unsigned long * address)
|
|
{
|
|
if (ihContent.size() != 0)
|
|
{
|
|
map<unsigned long, unsigned char>::iterator it;
|
|
|
|
it = ihContent.begin();
|
|
*address = (*it).first;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Returns the highest address currently available.
|
|
*
|
|
* Returns the last address that appears in the memory if there is data
|
|
* present. If not, no value will be returned.
|
|
*
|
|
* \param address - variable to hold address requested
|
|
*
|
|
* \retval true - address existed and returned value is valid
|
|
* \retval false - address did not exist and returned valid is not
|
|
* valid
|
|
*
|
|
* \sa startAddress()
|
|
***********************************************************************/
|
|
bool endAddress(unsigned long * address)
|
|
{
|
|
if (ihContent.size() != 0)
|
|
{
|
|
map<unsigned long, unsigned char>::reverse_iterator rit;
|
|
|
|
rit = ihContent.rbegin();
|
|
*address = (*rit).first;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Returns the data to which the iterator is currently pointing.
|
|
*
|
|
* Returns the data to which the internal iterator (pointer) is currently
|
|
* pointing. If no data is in memory, this function returns false.
|
|
*
|
|
* \param data - variable to hold data requested
|
|
*
|
|
* \retval true - data was available and returned value is valid
|
|
* \retval false - data was not available and returned valid is not
|
|
* valid
|
|
*
|
|
* \sa insertData(), overwriteData()
|
|
***********************************************************************/
|
|
bool getData(unsigned char * data)
|
|
{
|
|
if (!ihContent.empty() && (ihIterator != ihContent.end()))
|
|
{
|
|
*data = ihIterator->second;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Returns the data from the desired address.
|
|
*
|
|
* Returns the data for the desired address. If the address has no data
|
|
* assigned to it, the function returns false, the pointer to data is not
|
|
* written and the class's address pointer remains unchanged. If the
|
|
* address has data assigned to it, the pointer to data will be written
|
|
* with the data found and the class's address pointer will be moved to
|
|
* this new location.
|
|
*
|
|
* \param data - variable to hold data requested
|
|
* \param address - address to be queried for valid data
|
|
*
|
|
* \retval true - data was available and returned value is valid
|
|
* \retval false - data was not available and returned valid is not
|
|
* valid
|
|
*
|
|
* \sa insertData(), overwriteData()
|
|
***********************************************************************/
|
|
bool getData(unsigned char * data, unsigned long address)
|
|
{
|
|
bool found = false;
|
|
map<unsigned long, unsigned char>::iterator localIterator;
|
|
|
|
if (!ihContent.empty())
|
|
{
|
|
localIterator = ihContent.find(address);
|
|
|
|
if (localIterator != ihContent.end())
|
|
{
|
|
found = true;
|
|
ihIterator = localIterator;
|
|
*data = ihIterator->second;
|
|
}
|
|
}
|
|
|
|
return found;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Inserts desired byte at the current address pointer.
|
|
*
|
|
* Inserts byte of data at the current address pointer
|
|
*
|
|
* \param data - data byte to be inserted
|
|
*
|
|
* \retval true - data insertion was successful
|
|
* \retval false - data insertion failed
|
|
*
|
|
* \sa getAddress(), overwriteData()
|
|
***********************************************************************/
|
|
bool insertData(unsigned char data);
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Inserts desired byte at the desired address.
|
|
*
|
|
* Inserts byte of data at the desired address.
|
|
*
|
|
* \param data - data byte to be inserted
|
|
* \param address - address at which to insert data
|
|
*
|
|
* \retval true - data insertion was successful
|
|
* \retval false - data insertion failed
|
|
*
|
|
* \sa getAddress(), overwriteData()
|
|
***********************************************************************/
|
|
bool insertData(unsigned char data, unsigned long address);
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Forces insertion of desired byte at the current address pointer.
|
|
*
|
|
* Forces insertion of byte of data at the current address pointer
|
|
*
|
|
* \param data - data byte to be inserted
|
|
*
|
|
* \sa getAddress()
|
|
***********************************************************************/
|
|
void overwriteData(unsigned char data);
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Forces insertion of desired byte at the desired address.
|
|
*
|
|
* Forces insertion of byte of data at the desired address.
|
|
*
|
|
* \param data - data byte to be inserted
|
|
* \param address - address at which to insert data
|
|
*
|
|
* \sa getAddress()
|
|
***********************************************************************/
|
|
void overwriteData(unsigned char data, unsigned long address);
|
|
|
|
bool blankFill(unsigned char data);
|
|
|
|
bool blankFill(unsigned char * const data, unsigned long sizeOfData);
|
|
|
|
void blankFill(unsigned char * const data, unsigned long sizeOfData,
|
|
unsigned long endAddress);
|
|
|
|
bool blankFillRandom();
|
|
|
|
void blankFillRandom(unsigned long endAddress);
|
|
|
|
bool blankFillAddressLowByte();
|
|
|
|
void blankFillAddressLowByte(unsigned long endAddress);
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Returns number of unread warning messages.
|
|
*
|
|
* Number of unread warning messages will be returned.
|
|
*
|
|
* \sa popNextWarning(), getNoErrors(), popNextError()
|
|
***********************************************************************/
|
|
unsigned long getNoWarnings()
|
|
{
|
|
return msgWarning.noOfWarnings;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Returns number of unread error messages.
|
|
*
|
|
* Number of unread error messages will be returned.
|
|
*
|
|
* \sa popNextWarning(), getNoWarnings(), popNextError()
|
|
***********************************************************************/
|
|
unsigned long getNoErrors()
|
|
{
|
|
return msgError.noOfErrors;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Pop next warning message from the list of warnings.
|
|
*
|
|
* Next warning message is returned from the list of warnings. If there
|
|
* are no more warning in the list, the string will be unchanged.
|
|
*
|
|
* \param warning - variable to store warning string to be returned
|
|
*
|
|
* \retval true - more warning messages are available
|
|
* \retval false - no more warning messages are available
|
|
*
|
|
* \sa getNoWarnings(), getNoErrors(), popNextError()
|
|
***********************************************************************/
|
|
bool popNextWarning(string& warning)
|
|
{
|
|
if (msgWarning.noOfWarnings > 0)
|
|
{
|
|
warning = msgWarning.ihWarnings.front();
|
|
|
|
msgWarning.ihWarnings.pop_front();
|
|
|
|
msgWarning.noOfWarnings = msgWarning.ihWarnings.size();
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Pop next error message from the list of errors.
|
|
*
|
|
* Next error message is returned from the list of errors. If there are
|
|
* no more errors in the list, no string will be returned unchanged.
|
|
*
|
|
* \param error - variable to store error string to be returned
|
|
*
|
|
* \retval true - more error messages are available
|
|
* \retval false - no more error messages are available
|
|
*
|
|
* \sa getNoWarnings(), getNoErrors(), popNextError()
|
|
***********************************************************************/
|
|
bool popNextError(string& error)
|
|
{
|
|
if (msgError.noOfErrors > 0)
|
|
{
|
|
error = msgError.ihErrors.front();
|
|
|
|
msgError.ihErrors.pop_front();
|
|
|
|
msgError.noOfErrors = msgError.ihErrors.size();
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Returns segment start address for the IP and ES registers.
|
|
*
|
|
* If these values exist, they will be returned. If not, the function
|
|
* returns false.
|
|
*
|
|
* \param ipRegister - variable to store IP register's value
|
|
* \param csRegister - variable to store CS register's value
|
|
*
|
|
* \retval true - IP and CS registers have defined values
|
|
* \retval false - IP and CS registers do not contain values
|
|
*
|
|
* \sa getStartLinearAddress(), setStartSegmentAddress(),
|
|
* setStartLinearAddress()
|
|
***********************************************************************/
|
|
bool getStartSegmentAddress(unsigned short * ipRegister,
|
|
unsigned short * csRegister)
|
|
{
|
|
if (startSegmentAddress.exists == true)
|
|
{
|
|
*ipRegister = startSegmentAddress.ipRegister;
|
|
*csRegister = startSegmentAddress.csRegister;
|
|
}
|
|
|
|
return startSegmentAddress.exists;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Returns segment linear address for the EIP register.
|
|
*
|
|
* If this value exists, they will be returned. If not, the function
|
|
* returns false.
|
|
*
|
|
* \param eipRegister - variable to store EIP register's value
|
|
*
|
|
* \retval true - EIP register has defined value
|
|
* \retval false - EIP register do not contain value
|
|
*
|
|
* \sa getStartSegmentAddress(), setStartSegmentAddress(),
|
|
* setStartLinearAddress()
|
|
***********************************************************************/
|
|
bool getStartLinearAddress(unsigned long * eipRegister)
|
|
{
|
|
if (startLinearAddress.exists == true)
|
|
{
|
|
*eipRegister = startLinearAddress.eipRegister;
|
|
}
|
|
|
|
return startLinearAddress.exists;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Sets the segment start address for the IP and CS registers.
|
|
*
|
|
* Allows user to define or redefine the contents of the IP and CS
|
|
* registers
|
|
*
|
|
* \param ipRegister - desired IP register value
|
|
* \param csRegister - desired CS register value
|
|
*
|
|
* \sa getStartLinearAddress(), getStartSegmentAddress(),
|
|
* setStartLinearAddress()
|
|
***********************************************************************/
|
|
void setStartSegmentAddress(unsigned short ipRegister,
|
|
unsigned short csRegister)
|
|
{
|
|
startSegmentAddress.ipRegister = ipRegister;
|
|
startSegmentAddress.csRegister = csRegister;
|
|
startSegmentAddress.exists = true;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Sets the segment start address for the EIP register.
|
|
*
|
|
* Allows user to define or redefine the contents of the EIP register
|
|
*
|
|
* \param eipRegister - desired EIP register value
|
|
*
|
|
* \sa getStartSegmentAddress(), setStartSegmentAddress(),
|
|
* getStartLinearAddress()
|
|
***********************************************************************/
|
|
void setStartLinearAddress(unsigned long eipRegister)
|
|
{
|
|
startLinearAddress.eipRegister = eipRegister;
|
|
startLinearAddress.exists = true;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Turns on segment addressing mode during encoding.
|
|
*
|
|
* Uses the Segment Address Record during encoding.
|
|
***********************************************************************/
|
|
void segmentAddressingOn()
|
|
{
|
|
segmentAddressMode = true;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Turns on linear addressing mode during encoding.
|
|
*
|
|
* Uses the Linear Address Record during encoding.
|
|
***********************************************************************/
|
|
void linearAddressingOn()
|
|
{
|
|
segmentAddressMode = false;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Turns on textual output to cout during decoding.
|
|
*
|
|
* Per record single line output to cout during decoding of Intel HEX
|
|
* files.
|
|
***********************************************************************/
|
|
void verboseOn()
|
|
{
|
|
verbose = true;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/*! \brief Turns off textual output to cout during decoding.
|
|
*
|
|
* No output to cout during decoding of Intel HEX files.
|
|
***********************************************************************/
|
|
void verboseOff()
|
|
{
|
|
verbose = false;
|
|
}
|
|
};
|
|
#endif
|