ihex.py
ofrak.core.ihex
Ihex (Program)
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)
Extracts and analyzes Intel HEX program metadata including the starting and ending addresses of all segments, individual segment sizes, the overall address range covered by the program, and any gaps between segments. Intel HEX files can have non-contiguous address ranges. Use to understand the memory layout described by an Intel HEX file, identify which memory regions contain data, find gaps that will be filled with padding, or determine the total memory space required. Useful before unpacking or when planning memory modifications.
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 |
|---|---|
Ihex |
The analysis results |
Source code in ofrak/core/ihex.py
async def analyze(self, resource: Resource, config: None = None) -> Ihex:
ihex, _ = _binfile_analysis(await resource.get_data(), self)
return ihex
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, 0, 0x2000, 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 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:
ihex = await resource.view_as(Ihex)
binfile = BinFile()
segments = await resource.get_children_as_view(
CodeRegion, r_filter=ResourceFilter.with_tags(CodeRegion)
)
if len(list(segments)) == 0: # probably means that the ihex was never unpacked
raw_ihex = await resource.get_data()
binfile.add_ihex(raw_ihex.decode("utf-8"))
else:
for segment_r in segments:
seg_data = await segment_r.resource.get_data()
binfile.add_binary(seg_data, segment_r.virtual_address)
binfile.execution_start_address = ihex.start_addr
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)
IhexUnpacker (Unpacker)
Extracts individual memory segments from an Intel HEX program's binary representation, separating the continuous memory image into distinct addressable sections. Each segment corresponds to a contiguous region of memory defined in the original HEX file.
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):
_, binfile = _binfile_analysis(await resource.get_data(), self)
for segment in binfile.segments:
segment_data = bytes(binfile.as_binary())[
segment.minimum_address
- binfile.minimum_address : segment.maximum_address
- binfile.minimum_address
]
await resource.create_child_from_view(
CodeRegion(
segment.minimum_address, segment.maximum_address - segment.minimum_address
),
data=segment_data,
)