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:
if not BINCOPY_INSTALLED:
raise ComponentMissingDependencyError(self, _BINCOPY_TOOL)
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: Union[NoneType, 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()))