Skip to content

ihex.py

ofrak.core.ihex

Ihex (GenericBinary) dataclass

Intel HEX is a binary blob packaging format encoded in ASCII. It splits binary data into records, which are lines of ASCII representing in hex the byte count, address, type, checksums of stored data. It is typically used for flashing firmware.

printf "Hello world!" | bin2hex.py -

:0C00000048656C6C6F20776F726C642197 :00000001FF

IhexAnalyzer (Analyzer)

Extract Intel HEX parameters

analyze(self, resource, config=None) async

Analyze a resource for to extract specific ResourceAttributes.

Users should not call this method directly; rather, they should run Resource.run or Resource.analyze.

Parameters:

Name Type Description Default
resource Resource

The resource that is being analyzed

required
config None

Optional config for analyzing. If an implementation provides a default, this default will always be used when config would otherwise be None. Note that a copy of the default config will be passed, so the default config values cannot be modified persistently by a component run.

None

Returns:

Type Description
IhexProgram

The analysis results

Source code in ofrak/core/ihex.py
async def analyze(self, resource: Resource, config: None = None) -> IhexProgram:
    raw_ihex = await resource.get_parent()
    ihex_program, _ = _binfile_analysis(await raw_ihex.get_data(), self)
    return ihex_program

IhexIdentifier (Identifier)

Regex-test the entire resource to check if it satisfies intel-hex formatting.

This identifier tags any Resource whose first two lines match the ihex format.

identify(self, resource, config=None) async

Perform identification on the given resource.

Users should not call this method directly; rather, they should run Resource.identify.

Parameters:

Name Type Description Default
resource Resource required
config

Optional config for identifying. If an implementation provides a default, this default will always be used when config would otherwise be None. Note that a copy of the default config will be passed, so the default config values cannot be modified persistently by a component run.

None
Source code in ofrak/core/ihex.py
async def identify(self, resource: Resource, config=None) -> None:
    matched_ihex = await resource.search_data(self._INTEL_HEX_PATTERN, max_matches=1)
    if matched_ihex:
        offset, bytes = matched_ihex[0]
        # Only tag if pattern starts at offset 0 of resource
        if offset == 0:
            resource.add_tag(Ihex)

IhexPacker (Packer)

Pack a binary blob representation of an Intel HEX program back into an Intel HEX file.

pack(self, resource, config=None) async

Pack the given resource.

Users should not call this method directly; rather, they should run Resource.run or Resource.pack.

Parameters:

Name Type Description Default
resource Resource required
config

Optional config for packing. If an implementation provides a default, this default will always be used when config would otherwise be None. Note that a copy of the default config will be passed, so the default config values cannot be modified persistently by a component run.

None
Source code in ofrak/core/ihex.py
async def pack(self, resource: Resource, config=None) -> None:
    program_child = await resource.get_only_child_as_view(IhexProgram)
    vaddr_offset = -program_child.address_limits.start
    binfile = BinFile()
    binfile.execution_start_address = program_child.start_addr
    for seg in program_child.segments:
        seg_data = await program_child.resource.get_data(seg.translate(vaddr_offset))
        binfile.add_binary(seg_data, seg.start)

    new_data = binfile.as_ihex()
    if new_data.endswith("\n"):
        new_data = new_data[:-1]
    new_data = new_data.encode("utf-8")
    old_data_len = await resource.get_data_length()
    resource.queue_patch(Range(0, old_data_len), new_data)

IhexProgram (Program) dataclass

IhexProgram(address_limits: ofrak_type.range.Range, start_addr: Optional[int], segments: List[ofrak_type.range.Range])

IhexProgramPacker (Packer)

Pack the segments of an Intel HEX program back into a binary blob. Recomputes segment size and program address range based on the actual segments at the time of packing.

pack(self, resource, config=None) async

Pack the given resource.

Users should not call this method directly; rather, they should run Resource.run or Resource.pack.

Parameters:

Name Type Description Default
resource Resource required
config

Optional config for packing. If an implementation provides a default, this default will always be used when config would otherwise be None. Note that a copy of the default config will be passed, so the default config values cannot be modified persistently by a component run.

None
Source code in ofrak/core/ihex.py
async def pack(self, resource: Resource, config=None) -> None:
    updated_segments = []
    min_vaddr = sys.maxsize
    max_vaddr = 0
    for segment_r in await resource.get_children_as_view(
        ProgramSection, r_filter=ResourceFilter.with_tags(ProgramSection)
    ):
        seg_length = await segment_r.resource.get_data_length()
        seg_start = segment_r.virtual_address
        updated_segments.append(Range.from_size(seg_start, seg_length))
        min_vaddr = min(min_vaddr, seg_start)
        max_vaddr = max(max_vaddr, seg_start + seg_length)
    ihex_prog = await resource.view_as(IhexProgram)
    ihex_prog.segments = updated_segments
    ihex_prog.address_limits = Range(min_vaddr, max_vaddr)
    resource.add_view(ihex_prog)

IhexProgramUnpacker (Unpacker)

Unpack the individual segments from an Intel HEX Program's binary blob.

unpack(self, resource, config=None) async

Unpack the given resource.

Users should not call this method directly; rather, they should run Resource.run or Resource.unpack.

Parameters:

Name Type Description Default
resource Resource

The resource that is being unpacked

required
config

Optional config for unpacking. If an implementation provides a default, this default will always be used when config would otherwise be None. Note that a copy of the default config will be passed, so the default config values cannot be modified persistently by a component run.

None
Source code in ofrak/core/ihex.py
async def unpack(self, resource: Resource, config=None):
    ihex_program = await resource.view_as(IhexProgram)
    for seg_vaddr_range in ihex_program.segments:
        # Segment is mapped into the program at an offset starting at the difference between
        # the segment's vaddr range and the program's base address
        segment_data_range = seg_vaddr_range.translate(-ihex_program.address_limits.start)
        await resource.create_child_from_view(
            ProgramSection(seg_vaddr_range.start, seg_vaddr_range.length()),
            data_range=segment_data_range,
        )

IhexUnpacker (Unpacker)

Unpack an Intel HEX file, converting into raw bytes with padding bytes added to fill the gaps between segments. The result is a Program made up of a binary blob representing the entire memory space that the ihex file would load.

unpack(self, resource, config=None) async

Unpack the given resource.

Users should not call this method directly; rather, they should run Resource.run or Resource.unpack.

Parameters:

Name Type Description Default
resource Resource

The resource that is being unpacked

required
config

Optional config for unpacking. If an implementation provides a default, this default will always be used when config would otherwise be None. Note that a copy of the default config will be passed, so the default config values cannot be modified persistently by a component run.

None
Source code in ofrak/core/ihex.py
async def unpack(self, resource: Resource, config=None):
    ihex_program, binfile = _binfile_analysis(await resource.get_data(), self)

    await resource.create_child_from_view(ihex_program, data=bytes(binfile.as_binary()))