MemoryMap

MemoryMap

MemoryMap Represents the contents of a memory layout, with main focus into (possibly sparse) blocks of data.
A MemoryMap acts as a subclass of Map. In every entry of it, the key is the starting address of a data block (an integer number), and the value is the Uint8Array with the data for that block.
The main rationale for this is that a .hex file can contain a single block of contiguous data starting at memory address 0 (and it's the common case for simple .hex files), but complex files with several non-contiguous data blocks are also possible, thus the need for a data structure on top of the Uint8Arrays.
In order to parse .hex files, use the MemoryMap.fromHex static factory method. In order to write .hex files, create a new MemoryMap and call its MemoryMap.asHexString method.

Constructor

new MemoryMap(blocks)

Source:
Parameters:
Name Type Description
blocks Iterable The initial value for the memory blocks inside this MemoryMap. All keys must be numeric, and all values must be instances of Uint8Array. Optionally it can also be a plain Object with only numeric keys.
Example
import MemoryMap from 'nrf-intel-hex';

let memMap1 = new MemoryMap();
let memMap2 = new MemoryMap([[0, new Uint8Array(1,2,3,4)]]);
let memMap3 = new MemoryMap({0: new Uint8Array(1,2,3,4)});
let memMap4 = new MemoryMap({0xCF0: new Uint8Array(1,2,3,4)});

Extends

  • Map

Methods

(static) flattenOverlaps(overlaps) → {MemoryMap}

Given the output of the overlapMemoryMaps (a Map of address to an Array of (id, Uint8Array) tuples), returns a MemoryMap. This discards the IDs in the process.
The output Map contains as many entries as the input one (using the same addresses as keys), but the value for each entry will be the Uint8Array of the last tuple for each address in the input data.
The scenario is wanting to join together several parsed .hex files, not worrying about their overlaps.
Source:
Parameters:
Name Type Description
overlaps Map.Array.<mixed, Uint8Array> The (possibly overlapping) input memory blocks
Returns:
Type:
MemoryMap
The flattened memory blocks

(static) fromHex(hexText, maxBlockSizeopt) → {MemoryMap}

Parses a string containing data formatted in "Intel HEX" format, and returns an instance of MemoryMap.
The insertion order of keys in the MemoryMap is guaranteed to be strictly ascending. In other words, when iterating through the MemoryMap, the addresses will be ordered in ascending order.
The parser has an opinionated behaviour, and will throw a descriptive error if it encounters some malformed input. Check the project's README file for details.
If maxBlockSize is given, any contiguous data block larger than that will be split in several blocks.
Source:
Parameters:
Name Type Attributes Default Description
hexText String The contents of a .hex file.
maxBlockSize Number <optional>
Infinity Maximum size of the returned Uint8Arrays.
Returns:
Type:
MemoryMap
Example
import MemoryMap from 'nrf-intel-hex';

let intelHexString =
    ":100000000102030405060708090A0B0C0D0E0F1068\n" +
    ":00000001FF";

let memMap = MemoryMap.fromHex(intelHexString);

for (let [address, dataBlock] of memMap) {
    console.log('Data block at ', address, ', bytes: ', dataBlock);
}

(static) fromPaddedUint8Array(bytes, padByteopt, minPadLengthopt) → {MemoryMap}

Given one Uint8Array, looks through its contents and returns a new MemoryMap, stripping away those regions where there are only padding bytes.
The start of the input Uint8Array is assumed to be offset zero for the output.
The use case here is dumping memory from a working device and try to see the "interesting" memory regions it has. This assumes that there is a constant, predefined padding byte value being used in the "non-interesting" regions. In other words: this will work as long as the dump comes from a flash memory which has been previously erased (thus 0xFFs for padding), or from a previously blanked HDD (thus 0x00s for padding).
This method uses subarray on the input data, and thus does not allocate memory for the Uint8Arrays.
Source:
Parameters:
Name Type Attributes Default Description
bytes Uint8Array The input data
padByte Number <optional>
0xFF The value of the byte assumed to be used as padding
minPadLength Number <optional>
64 The minimum number of consecutive pad bytes to be considered actual padding
Returns:
Type:
MemoryMap

(static) overlapMemoryMaps(memoryMaps) → {Map.Array.<mixed, Uint8Array>}

Given a Map of MemoryMaps, indexed by a alphanumeric ID, returns a Map of address to tuples (Arrayss of length 2) of the form (id, Uint8Array)s.
The scenario for using this is having several MemoryMaps, from several calls to hexToArrays, each having a different identifier. This function locates where those memory block sets overlap, and returns a Map containing addresses as keys, and arrays as values. Each array will contain 1 or more (id, Uint8Array) tuples: the identifier of the memory block set that has data in that region, and the data itself. When memory block sets overlap, there will be more than one tuple.
The Uint8Arrays in the output are subarrays of the input data; new memory is not allocated for them.
The insertion order of keys in the output Map is guaranteed to be strictly ascending. In other words, when iterating through the Map, the addresses will be ordered in ascending order.
When two blocks overlap, the corresponding array of tuples will have the tuples ordered in the insertion order of the input Map of block sets.
Source:
Parameters:
Name Type Description
memoryMaps Map.MemoryMap The input memory block sets
Returns:
Type:
Map.Array.<mixed, Uint8Array>
The map of possibly overlapping memory blocks
Example
import MemoryMap from 'nrf-intel-hex';

let memMap1 = MemoryMap.fromHex( hexdata1 );
let memMap2 = MemoryMap.fromHex( hexdata2 );
let memMap3 = MemoryMap.fromHex( hexdata3 );

let maps = new Map([
 ['file A', blocks1],
 ['file B', blocks2],
 ['file C', blocks3]
]);

let overlappings = MemoryMap.overlapMemoryMaps(maps);

for (let [address, tuples] of overlappings) {
    // if 'tuples' has length > 1, there is an overlap starting at 'address'

    for (let [address, tuples] of overlappings) {
        let [id, bytes] = tuple;
        // 'id' in this example is either 'file A', 'file B' or 'file C'
    }
}

asHexString(lineSizeopt) → {String}

Returns a String of text representing a .hex file.
The writer has an opinionated behaviour. Check the project's README file for details.
Source:
Parameters:
Name Type Attributes Default Description
lineSize Number <optional>
16 Maximum number of bytes to be encoded in each data record. Must have a value between 1 and 255, as per the specification.
Returns:
Type:
String
String of text with the .hex representation of the input binary data
Example
import MemoryMap from 'nrf-intel-hex';

let memMap = new MemoryMap();
let bytes = new Uint8Array(....);
memMap.set(0x0FF80000, bytes); // The block with 'bytes' will start at offset 0x0FF80000

let string = memMap.asHexString();

clone() → {MemoryMap}

Performs a deep copy of the current MemoryMap, returning a new one with exactly the same contents, but allocating new memory for each of its Uint8Arrays.
Source:
Returns:
Type:
MemoryMap

contains(memMap) → {Boolean}

Checks whether the current memory map contains the one given as a parameter.
"Contains" means that all the offsets that have a byte value in the given memory map have a value in the current memory map, and that the byte values are the same.
An empty memory map is always contained in any other memory map.
Returns boolean true if the memory map is contained, false otherwise.
Source:
Parameters:
Name Type Description
memMap MemoryMap The memory map to check
Returns:
Type:
Boolean

getUint32(offset, littleEndianopt) → {Number|undefined}

Locates the Uint8Array which contains the given offset, and returns the four bytes held at that offset, as a 32-bit unsigned integer.
Behaviour is similar to DataView.prototype.getUint32, except that this operates over a MemoryMap instead of over an ArrayBuffer, and that this may return undefined if the address is not entirely contained within one of the Uint8Arrays.
Source:
Parameters:
Name Type Attributes Default Description
offset Number The memory offset to read the data
littleEndian Boolean <optional>
false Whether to fetch the 4 bytes as a little- or big-endian integer
Returns:
Type:
Number | undefined
An unsigned 32-bit integer number

join(maxBlockSizeopt) → {MemoryMap}

Returns a new instance of MemoryMap, containing the same data, but concatenating together those memory blocks that are adjacent.
The insertion order of keys in the MemoryMap is guaranteed to be strictly ascending. In other words, when iterating through the MemoryMap, the addresses will be ordered in ascending order.
If maxBlockSize is given, blocks will be concatenated together only until the joined block reaches this size in bytes. This means that the output MemoryMap might have more entries than the input one.
If there is any overlap between blocks, an error will be thrown.
The returned MemoryMap will use newly allocated memory.
Source:
Parameters:
Name Type Attributes Default Description
maxBlockSize Number <optional>
Infinity Maximum size of the Uint8Arrays in the returned MemoryMap.
Returns:
Type:
MemoryMap

paginate(pageSizeopt, padopt) → {MemoryMap}

Returns a new instance of MemoryMap, where:
  • Each key (the start address of each Uint8Array) is a multiple of pageSize
  • The size of each Uint8Array is exactly pageSize
  • Bytes from the input map to bytes in the output
  • Bytes not in the input are replaced by a padding value

The scenario is wanting to prepare pages of bytes for a write operation, where the write operation affects a whole page/sector at once.
The insertion order of keys in the output MemoryMap is guaranteed to be strictly ascending. In other words, when iterating through the MemoryMap, the addresses will be ordered in ascending order.
The Uint8Arrays in the output will be newly allocated.
Source:
Parameters:
Name Type Attributes Default Description
pageSize Number <optional>
1024 The size of the output pages, in bytes
pad Number <optional>
0xFF The byte value to use for padding
Returns:
Type:
MemoryMap

slice(address, length) → {MemoryMap}

Returns a new instance of MemoryMap, containing only data between the addresses address and address + length. Behaviour is similar to Array.prototype.slice, in that the return value is a portion of the current MemoryMap.
The returned MemoryMap might be empty.
Internally, this uses subarray, so new memory is not allocated.
Source:
Parameters:
Name Type Description
address Number The start address of the slice
length Number The length of memory map to slice out
Returns:
Type:
MemoryMap

slicePad(address, length, padByteopt) → {MemoryMap}

Returns a new instance of Uint8Array, containing only data between the addresses address and address + length. Any byte without a value in the input MemoryMap will have a value of padByte.
This method allocates new memory.
Source:
Parameters:
Name Type Attributes Default Description
address Number The start address of the slice
length Number The length of memory map to slice out
padByte Number <optional>
0xFF The value of the byte assumed to be used as padding
Returns:
Type:
MemoryMap