Class MemoryContents
- java.lang.Object
-
- jmri.jmrit.MemoryContents
-
public class MemoryContents extends java.lang.Object
Models (and provides utility functions for) board memory as expressed in .hex files and .DMF files.Provides mechanisms to read and interpret firmware update files into an internal data structure. Provides mechanisms to in create firmware update files from an internal data structure. Provides mechanisms to allow other agents to access the data in the internal data structures for the purpose of sending the data to the device to be updated. Supports the Intel "I8HEX" file format and a derivative ".dmf" file format created by Digitrax.
Support for the Intel "I8HEX" format includes support for record types "00" and "01". The "I8HEX" format implements records with a LOAD OFFSET field of 16 bits. To support the full 24-bit addressing range provided by the LocoNet messaging protocol for firmware updates, this class is able to interpret record type "04" (Extended Linear Address) records for input files with 16-bit LOAD OFFSET fields. Record type "04" are typically found in the Intel "I32HEX" 32-bit addressing format. Because the class supports only 24 bits of address, interpretation of the "04" record type requires that the upper 8 bits of the 16-bit data field be 0.
Support for some .hex files emitted by some tool-sets requires support for the Extended Segment Address record type (record type "02"), which may be used in I16HEX format files. This version of the
readHex(java.lang.String)
method supports the Extended Segment Address record type ONLY when the segment specified in the data field is 0x0000.Support for the Digitrax ".DMF" format is an extension to the "I8HEX" support. This extension supports interpretation of the 24-bit LOAD OFFSET fields used in .DFM files. The class does not allow files with 24-bit LOAD OFFSET fields to use the "04" (Extended Linear Address) record type unless its data field is 0x0000.
Support for the ".DMF" format allows capture of Key/Value pairs which may be embedded in special comments within a .DMF file. This support is enabled for I8HEX files.
The class treats the information within a file's records as having "big-endian" address values in the record LOAD OFFSET field. The INFO or DATA field information is interpreted as 8-bit values, with the left-most value in the INFO or DATA field corresponding to the address specified by the record's LOAD OFFSET field plus the influence of the most recent previous Extended Linear Address record, if any.
The INFO or DATA field for Extended Linear Address records is interpreted as a big-endian value, where bits 7 thru 0 of the data field value are used as bits 23 thru 16 of the effective address, while bits 15 thru 0 of the effective address are from the 16-bit LOAD OFFSET of each data record. Bits 15 thru 8 of the Extended Linear Address record INFO or DATA field must be 0 because of the 24-bit address limitation of this implementation.
The class does not have to know anything about filenames or filename extensions. Instead, to read a file, an instantiating method will create a
File
object and pass that object toreadHex(java.lang.String)
. Similarly, when writing the contents of data storage to a file, the instantiating method will create aFile
and an associatedWriter
and pass theWriter
object towriteHex(java.io.Writer)
. The mechanisms implemented within this class do not know about or care about the filename or its extension and do not use that information as part of its file interpretation or file creation.The class is implemented with a maximum of 24 bits of address space, with up to 256 pages of up to 65536 bytes per page. A "sparse" implementation of memory is modeled, where only occupied pages are allocated within the Java system's memory.
The Intel "Hexadecimal Object File Format File Format Specification" uses the following terms for the fields of the record:- RECORD MARK
- first character of a record. ':'
- RECLEN
- a two-character specifier of the number of bytes of information in the "INFO or DATA" field. Immediately follows the RECORD MARK charcter. Since each byte within the "INFO or DATA" field is represented by two ASCII characters, the data field contains twice the RECLEN value number of ASCII characters.
- LOAD OFFSET
- specifies the 16-bit starting load offset of the data bytes.
This applies only to "Data" records, so this class requires that
this field must encode 0x0000 for all other record types. The LOAD
OFFSET field immediately follows the RECLEN field.
Note that for the 24-bit addressing format used with ".DMF" files, this field is a 24-bit starting load offset, represented by six ASCII characters, rather than the four ASCII characters specified in the Intel specification.
- RECTYP
- RECord TYPe - indicates the record type for this record. The RECTYPE field immediately follows the LOAD OFFSET field.
- INFO or DATA
- (Optional) field containing information or data which is appropriate to the RECTYP. Immediately follows the RECTYP field. contains RECLEN times 2 characters, where consecutive pairs of characters represent one byte of info or data.
- CHKSUM
- 8-bit Checksum, computed using the hexadecimal byte values represented by the character pairs in RECLEN, LOAD OFFSET, RECTYP, and INFO or DATA fields, such that the computed sum, when added to the CKSUM value, sums to an 8-bit value of 0x00.
Mnemonically, a properly formatted record would appear as:
:lloooott{dd}cc where: ':' is the RECORD MARK "ll" is the RECLEN "oooo" is the 16-bit LOAD OFFSET "tt" is the RECTYP "{dd}" is the INFO or DATA field, containing zero or more pairs of characters of Info or Data associated with the record "cc" is the CHKSUM
and a few examples of complaint records would be:
- :02041000FADE07
- :020000024010AC
- :00000001FF
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
MemoryContents.LoadOffsetFieldType
class
MemoryContents.MemoryFileAddressingFormatException
An exception for an unsupported addressing formatclass
MemoryContents.MemoryFileAddressingRangeException
An exception for an address outside of the supported rangeclass
MemoryContents.MemoryFileChecksumException
An exception for a record which has incorrect checksum.class
MemoryContents.MemoryFileException
Generalized class from which detailed exceptions are derived.class
MemoryContents.MemoryFileNoDataRecordsException
An exception for a file with no data recordsclass
MemoryContents.MemoryFileNoEOFRecordException
An exception for a file without an end-of-file recordclass
MemoryContents.MemoryFileRecordContentException
An exception for a record which has content which cannot be parsed.class
MemoryContents.MemoryFileRecordFoundAfterEOFRecord
An exception for a file containing at least one record after the EOF recordclass
MemoryContents.MemoryFileRecordLengthException
An exception for a data record where there are too many or too few characters versus the number of characters expected based on the record type field, LOAD OFFSET field size, and data count field.class
MemoryContents.MemoryFileUnknownRecordType
An exception for a record containing a record type which is not supported.
-
Constructor Summary
Constructors Constructor Description MemoryContents()
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description void
addKeyValueComment(java.lang.String keyName, java.lang.String value)
Updates the internal key/value storage to reflect the parameters.void
clear()
Clear out an imported Firmware File.java.lang.String
extractValueOfKey(java.lang.String keyName)
Finds the Value for a specified Key if that Key is found in the list of Key/Value pair comment lines.MemoryContents.LoadOffsetFieldType
getCurrentAddressFormat()
Returns the current addressing format setting.int
getLocation(int location)
Returns the value from the programmatic representation of memory for the specified location.boolean
isEmpty()
Reports whether the object has not been initialized with any data.boolean
locationInUse(int location)
Queries the programmatic representation of memory to determine if location is represented.int
nextContent(int location)
Return the address of the next location containing data, including the location in the argumentvoid
readHex(java.io.File file)
Perform a read of a .hex file information into JAVA memory.void
readHex(java.lang.String filename)
Perform a read of a .hex file information into JAVA memory.void
setAddressFormat(MemoryContents.LoadOffsetFieldType addressingType)
Configures the Addressing format used in the LOAD OFFSET field when writing to a .hex file using thewriteHex(java.io.Writer)
method.void
setLocation(int location, int value)
Modifies the programmatic representation of memory to reflect a specified value.java.lang.String
toString()
Summarize contentsvoid
writeComments(java.io.Writer writer)
Writes key/data pair information to an output filevoid
writeHex(java.io.Writer w)
Sends a character stream of an image of a programmatic representation of memory in the Intel "I8HEX" file format to a Writer.void
writeHex(java.io.Writer writer, boolean writeKeyVals, int blockSize)
Sends a character stream of key/value pairs (if requested) and an image of a programmatic representation of memory in either the Intel "I8HEX" or Digitrax ".DMF" file format to a Writer.
-
-
-
Constructor Detail
-
MemoryContents
public MemoryContents()
-
-
Method Detail
-
readHex
public void readHex(java.lang.String filename) throws java.io.FileNotFoundException, MemoryContents.MemoryFileRecordLengthException, MemoryContents.MemoryFileChecksumException, MemoryContents.MemoryFileUnknownRecordType, MemoryContents.MemoryFileRecordContentException, MemoryContents.MemoryFileNoDataRecordsException, MemoryContents.MemoryFileNoEOFRecordException, MemoryContents.MemoryFileRecordFoundAfterEOFRecord, MemoryContents.MemoryFileAddressingRangeException, java.io.IOException
Perform a read of a .hex file information into JAVA memory. Assumes that the file is of the Intel "I8HEX" format or the similar Digitrax ".DMF" format. Automatically infers the file type. Performs various checks upon the incoming data to help ensure proper interpretation of the file and to help detect corrupted files. Extracts "key/value" pair information from comments for use by the invoking method.Integrity checks include:
- Identification of LOAD OFFSET field type from first record
- Verification that all subsequent records use the same LOAD OFFSET field type
- Verification of checksum found at the end of each record
- Verification of supported record types
- Flagging of lines which are neither comment lines or records
- Identification of a missing EOF record
- Identification of any record after an EOF record
- Identification of a file without any data record
- Identification of any records which have extra characters after the checksum
When reading the file,
readHex(java.lang.String)
infers the addressing format from the first record found in the file, and future records are interpreted using that addressing format. It is not necessary to pre-configure the addressing format before reading the file. This is a departure from previous versions of this method.Blank lines are allowed and are ignored.
This code supports reading of files containing comments. Comment lines which begin with '#' are ignored.
Comment lines which * begin with '!' may encode Key/Value pair information. Such Key/Value pair information is used within the .DMF format to provide configuration information for firmware update mechanism. This class also extracts key/value pair comments "I8HEX" format files. After successful completion of the
readHex(java.lang.String)
call, then theextractValueOfKey(String keyName)
method may be used to inspect individual key values.Key/Value pair definition comment lines are of the format:
! KeyName: Value
- Parameters:
filename
- string containing complete filename with path- Throws:
java.io.FileNotFoundException
- if the file does not existMemoryContents.MemoryFileRecordLengthException
- if a record line is too long or shortMemoryContents.MemoryFileChecksumException
- if a record checksum does not match the computed record checksumMemoryContents.MemoryFileUnknownRecordType
- if a record contains an unsupported record typeMemoryContents.MemoryFileRecordContentException
- if a record contains inappropriate charactersMemoryContents.MemoryFileNoEOFRecordException
- if a file does not contain an EOF recordMemoryContents.MemoryFileNoDataRecordsException
- if a file does not contain any data recordsMemoryContents.MemoryFileRecordFoundAfterEOFRecord
- if a file contains records after the EOF recordMemoryContents.MemoryFileAddressingRangeException
- if a file contains an Extended Linear Address record outside of the supported address rangejava.io.IOException
- if a file cannot be opened via newBufferedReader
-
readHex
public void readHex(java.io.File file) throws java.io.FileNotFoundException, MemoryContents.MemoryFileRecordLengthException, MemoryContents.MemoryFileChecksumException, MemoryContents.MemoryFileUnknownRecordType, MemoryContents.MemoryFileRecordContentException, MemoryContents.MemoryFileNoDataRecordsException, MemoryContents.MemoryFileNoEOFRecordException, MemoryContents.MemoryFileRecordFoundAfterEOFRecord, MemoryContents.MemoryFileAddressingRangeException, java.io.IOException
Perform a read of a .hex file information into JAVA memory. Assumes that the file is of the Intel "I8HEX" format or the similar Digitrax ".DMF" format. Automatically infers the file type. Performs various checks upon the incoming data to help ensure proper interpretation of the file and to help detect corrupted files. Extracts "key/value" pair information from comments for use by the invoking method.Integrity checks include:
- Identification of LOAD OFFSET field type from first record
- Verification that all subsequent records use the same LOAD OFFSET field type
- Verification of checksum found at the end of each record
- Verification of supported record types
- Flagging of lines which are neither comment lines or records
- Identification of a missing EOF record
- Identification of any record after an EOF record
- Identification of a file without any data record
- Identification of any records which have extra characters after the checksum
When reading the file,
readHex(java.lang.String)
infers the addressing format from the first record found in the file, and future records are interpreted using that addressing format. It is not necessary to pre-configure the addressing format before reading the file. This is a departure from previous versions of this method.Blank lines are allowed and are ignored.
This code supports reading of files containing comments. Comment lines which begin with '#' are ignored.
Comment lines which * begin with '!' may encode Key/Value pair information. Such Key/Value pair information is used within the .DMF format to provide configuration information for firmware update mechanism. This class also extracts key/value pair comments "I8HEX" format files. After successful completion of this method, then the
#extractValueOfKey(String keyName)
method may be used to inspect individual key values.Key/Value pair definition comment lines are of the format:
! KeyName: Value
- Parameters:
file
- file to read- Throws:
java.io.FileNotFoundException
- if the file does not existMemoryContents.MemoryFileRecordLengthException
- if a record line is too long or shortMemoryContents.MemoryFileChecksumException
- if a record checksum does not match the computed record checksumMemoryContents.MemoryFileUnknownRecordType
- if a record contains an unsupported record typeMemoryContents.MemoryFileRecordContentException
- if a record contains inappropriate charactersMemoryContents.MemoryFileNoEOFRecordException
- if a file does not contain an EOF recordMemoryContents.MemoryFileNoDataRecordsException
- if a file does not contain any data recordsMemoryContents.MemoryFileRecordFoundAfterEOFRecord
- if a file contains records after the EOF recordMemoryContents.MemoryFileAddressingRangeException
- if a file contains an Extended Linear Address record outside of the supported address rangejava.io.IOException
- if a file cannot be opened via newBufferedReader
-
writeHex
public void writeHex(java.io.Writer w) throws java.io.IOException, MemoryContents.MemoryFileAddressingFormatException
Sends a character stream of an image of a programmatic representation of memory in the Intel "I8HEX" file format to a Writer.Number of bytes of data per data record is fixed at 16. Does not write any comment information to the file.
This method generates only RECTYPs "00" and "01", and does not generate any comment lines in its output.
- Parameters:
w
- Writer to which the character stream is sent- Throws:
java.io.IOException
- upon file access problemMemoryContents.MemoryFileAddressingFormatException
- if unsupported addressing format
-
writeHex
public void writeHex(java.io.Writer writer, boolean writeKeyVals, int blockSize) throws java.io.IOException, MemoryContents.MemoryFileAddressingFormatException
Sends a character stream of key/value pairs (if requested) and an image of a programmatic representation of memory in either the Intel "I8HEX" or Digitrax ".DMF" file format to a Writer.When selected for writing, the key/value pairs are provided at the beginning of the character stream. Note that comments of the key/value format implemented here is not in compliance with the "I8HEX" format.
The "I8HEX" format is used when the
loadOffsetFieldType
is configured for 16-bit addresses in the record LOAD OFFSET field. The ".DMF" format is used when theloadOffsetFieldType
is configured for 24-bit addresses in the record LOAD OFFSET field.The method generates only RECTYPs "00" and "01", and does not generate any comment lines in its output.
- Parameters:
writer
- Writer to which the character stream is sentwriteKeyVals
- determines whether key/value pairs (if any) are written at the beginning of the streamblockSize
- is the maximum number of bytes defined in a data record- Throws:
java.io.IOException
- upon file access problemMemoryContents.MemoryFileAddressingFormatException
- if unsupported addressing format
-
nextContent
public int nextContent(int location)
Return the address of the next location containing data, including the location in the argument- Parameters:
location
- indicates the address from which the next location is determined- Returns:
- the next location
-
setLocation
public void setLocation(int location, int value)
Modifies the programmatic representation of memory to reflect a specified value.- Parameters:
location
- location within programmatic representation of memory to modifyvalue
- value to be placed at location within programmatic representation of memory
-
locationInUse
public boolean locationInUse(int location)
Queries the programmatic representation of memory to determine if location is represented.- Parameters:
location
- location within programmatic representation of memory to inspect- Returns:
- true if location exists within programmatic representation of memory
-
getLocation
public int getLocation(int location)
Returns the value from the programmatic representation of memory for the specified location. Returns -1 if the specified location is not currently represented in the programmatic representation of memory.- Parameters:
location
- location within programmatic representation of memory to report- Returns:
- value found at the specified location.
-
isEmpty
public boolean isEmpty()
Reports whether the object has not been initialized with any data.- Returns:
- false if object contains data, true if no data stored in object.
-
extractValueOfKey
public java.lang.String extractValueOfKey(java.lang.String keyName)
Finds the Value for a specified Key if that Key is found in the list of Key/Value pair comment lines. The list of Key/Value pair comment lines is created while the input file is processed.Key/value pair information is extractable only from comments of the form:
! Key/Value
- Parameters:
keyName
- Key/value comment line, including the leading "! "- Returns:
- String containing Key name
-
addKeyValueComment
public void addKeyValueComment(java.lang.String keyName, java.lang.String value)
Updates the internal key/value storage to reflect the parameters. If the key already exists, its value is updated based on the parameter. If the key does not exist, a new key/value pair comment is added to the key/value storage list.- Parameters:
keyName
- key to usevalue
- value to store
-
setAddressFormat
public void setAddressFormat(MemoryContents.LoadOffsetFieldType addressingType)
Configures the Addressing format used in the LOAD OFFSET field when writing to a .hex file using thewriteHex(java.io.Writer)
method.Note that the
readHex(java.lang.String)
method infers the addressing format from the first record in the file and updates the stored address format based on the format found in the file.- Parameters:
addressingType
- addressing type to use
-
getCurrentAddressFormat
public MemoryContents.LoadOffsetFieldType getCurrentAddressFormat()
Returns the current addressing format setting. The current setting is established by the last occurrence of thesetAddressFormat(jmri.jmrit.MemoryContents.LoadOffsetFieldType)
method orreadHex(java.lang.String)
method invocation.- Returns:
- the current Addressing format setting
-
writeComments
public void writeComments(java.io.Writer writer) throws java.io.IOException
Writes key/data pair information to an output fileSince the key/value metadata is typically presented at the beginning of a firmware file, the method would typically be invoked before invocation of the writeHex method.
- Parameters:
writer
- Writer to which the character stream is sent- Throws:
java.io.IOException
- if problems writing data to file
-
toString
public java.lang.String toString()
Summarize contents- Overrides:
toString
in classjava.lang.Object
-
clear
public void clear()
Clear out an imported Firmware File. This may be used, when the instantiating object has evaluated the contents of a firmware file and found it to be inappropriate for updating to a device, to clear out the firmware image so that there is no chance that it can be updated to the device.
-
-