Skip to content

Commit

Permalink
unpacker: add FIT image support
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewjlamarche committed Oct 30, 2024
1 parent 21fb851 commit a63c9d2
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 0 deletions.
53 changes: 53 additions & 0 deletions fact_extractor/plugins/unpacking/uboot/code/fit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""
This plugin unpacks Flattened Image Trees.
"""

from pathlib import Path

import libfdt as fdt
from common_helper_files import write_binary_to_file

NAME = 'FIT'
MIME_PATTERNS = ['linux/device-tree']
VERSION = '0.1'


def unpack_function(file_path, tmp_dir):
"""
file_path specifies the input file.
tmp_dir must be used to store the extracted files.
Optional: Return a dict with meta information
"""

file = Path(file_path)

try:
with file.open('rb') as f:
fit_data = f.read()

dtb = fdt.Fdt(fit_data)
root_offset = dtb.path_offset('/')
subnode_offset = dtb.first_subnode(root_offset)
while True:
try:
component_offset = dtb.first_subnode(subnode_offset)
while True:
try:
outfile = Path(tmp_dir) / dtb.get_name(component_offset)
write_binary_to_file(bytes(dtb.getprop(component_offset, 'data')), outfile)
component_offset = dtb.next_subnode(component_offset)
except fdt.FdtException:
break
subnode_offset = dtb.next_subnode(subnode_offset)
except fdt.FdtException:
break
except OSError as io_error:
return {'output': f'failed to read file: {io_error!s}'}

return {'output': 'successfully unpacked FIT image'}


# ----> Do not edit below this line <----
def setup(unpack_tool):
for item in MIME_PATTERNS:
unpack_tool.register_plugin(item, (unpack_function, NAME, VERSION))
Binary file not shown.
23 changes: 23 additions & 0 deletions fact_extractor/plugins/unpacking/uboot/test/test_plugin_fit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from pathlib import Path

from test.unit.unpacker.test_unpacker import TestUnpackerBase

TEST_DATA_DIR = Path(__file__).parent / 'data'

EXPECTED_FILE_COUNT = 3


class TestFITUnpacker(TestUnpackerBase):
def test_unpacker_selection_generic(self):
self.check_unpacker_selection('linux/device-tree', 'FIT')

def test_extraction(self):
test_file_path = Path(TEST_DATA_DIR) / 'fit.itb'
extracted_files, meta_data = self.unpacker.extract_files_from_file(str(test_file_path), self.tmp_dir.name)

assert meta_data['plugin_used'] == 'FIT', 'wrong plugin applied'

assert len(extracted_files) == EXPECTED_FILE_COUNT, 'not all files extracted'
assert all(
Path(element).name in ['kernel', 'fdt', 'rootfs'] for element in extracted_files
), 'not all files extracted'
1 change: 1 addition & 0 deletions requirements-unpackers.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ bincopy~=20.0.0
extract-dtb~=1.2.3
# uefi
uefi-firmware~=1.11
pylibfdt ~= 1.7.1

0 comments on commit a63c9d2

Please sign in to comment.