U-Boot FIT images
REA inventories U-Boot Flattened Image Tree (FIT, .itb) files through inspect-artifact / inspect_artifact, and materializes the stored bytes of each image through extract-artifact / extract_artifact. Decoding is static and needs no external tool.
rea inspect-artifact ./boot.itb --json
rea inspect-artifact ./boot.itb --detail summary --evidence_output evidence.json --json
rea extract-artifact ./boot.itb --jsonFor MCP, open the file with open_binary, then call inspect_artifact. Summary delivery retains the complete Evidence; use parent_evidence_id with inspect_analysis_view to read selected images and fields. extract_artifact returns a fresh output_root containing one raw file per image. FIT summaries use the current projection identity; there is no pre-coverage FIT summary variant.
Recognition
A FIT is a flattened devicetree (FDT v16 or v17) with a top-level /images node. Recognition walks the structure block within the first 4 KiB of the file only; the file name does not matter. A devicetree whose /images node begins after 4 KiB, a devicetree without /images, and any other FDT version stay on the plain devicetree route: open_binary refuses them and inspect_devicetree still parses them. A U-Boot control DTB that contains /images is treated as a FIT. The container format is fit.
Recognition is a probe. The complete devicetree parse decides, so a file whose prefix declares /images but whose structure is malformed fails as a malformed FIT rather than falling back to plain classification.
Images and metadata
Each child of /images is one inventory entry named images/<unit-name>.bin, listed in devicetree order. Its bytes come from exactly one data source:
| Source | Stored bytes |
|---|---|
data | The embedded property value |
data-offset | data-size bytes at data-offset past the devicetree end, aligned to 4 (mkimage -E) |
data-position | data-size bytes at data-position from the start of the file (mkimage -p) |
data-position is read as U-Boot reads it: an offset from the start of the FIT, not a machine address.
Image format_metadata (fit-image) records index, name, description, type, arch, os, compression, load and entry, the data_source, the raw declared_offset for external data, image_data (the shared-data link), cipher_present, cipher_algo, hash_algorithms, hashes_verified, hashes_unverified, signature_count, signatures_unreadable and signature_algorithms. Algorithm lists are arrays. Nullable declaration fields are absent unless named in unreadable_fields, which records parsing failures per field. Hash or signature warnings do not make unrelated declarations unknown. load and entry fold one or two 32-bit cells into a lowercase 0x… value, as U-Boot does, independent of #address-cells.
Root format_metadata (fit) records fdt_version, fdt_totalsize, external_data_base (the aligned devicetree end), the root description, timestamp (seconds since 1970) and address_cells, plus default_configuration and configurations. A missing description or timestamp is null.
Image bytes are reported as stored. Compressed images are not decompressed and ciphered images are not decrypted: entries report encrypted: false and the cipher declaration in cipher_present and algorithm in cipher_algo. A missing or malformed algorithm stays null; it does not establish unciphered bytes. Embedded image-data links require byte-identical stored properties; external links require matching physical ranges.
The extracted file holds the stored bytes. Direct-analysis suggestions require compression: "none" and cipher_present: false.
Hashes and signatures
Hash subnodes are children whose name starts with hash. Inventory verifies crc32 (4 bytes, big-endian), md5, sha1, sha256, sha384 and sha512 over the stored bytes, the same bytes mkimage hashed after any ciphering. All hashes of an image are computed in one streamed pass while the inventory is prepared, so a mismatch fails the whole inventory, naming the image, hash node, algorithm, and the declared and computed values. A supported algorithm whose value has the wrong length also fails.
Other algorithms such as crc16-ccitt, crc8 or sm3_256, a hash without a readable algo, and a hash without a value are not verified; each is counted in hashes_unverified and reported as an image limitation.
Signature subnodes (names starting with signature) on images and configurations retain the total declaration count, readable algorithms and signatures_unreadable. Missing or malformed algorithms carry source limitations so unknown declarations remain distinguishable from absence. Signatures are never verified.
Configurations
/configurations is optional. Each child records its name, description, and the image references kernel, firmware, fdt (base plus overlays), ramdisk and loadables, always as lists, plus its signature algorithms. compatible, fpga, script, cmdline and load-only are not reported. A reference to a name that is not an /images child, and a default that names no configuration, are reported as limitations and kept as declared. Each configuration carries unresolved_reference_count; dangling references share one configuration-level diagnostic while every original reference remains available.
Facts, limitations and failures
| Situation | Outcome |
|---|---|
Malformed devicetree, truncated header, totalsize past the end of the file | Fails as malformed |
No data source, more than one data source, external data without data-size | Fails as malformed |
data-offset, data-position or data-size not one 32-bit cell, image-data not one string | Fails as malformed |
| External data outside the file, overlapping the devicetree or another image | Fails as malformed |
Two images with an identical external range linked by image-data | Accepted as shared data |
A dangling, chained or mismatched image-data link | Fails as malformed |
| Hash mismatch, or a supported hash value with the wrong length | Fails integrity |
| Unsupported, algorithm-less or value-less hashes | Unverified, reported as a limitation |
Malformed description, type, arch, os, compression, load, entry or timestamp | null, reported as a limitation |
| Dangling configuration reference, missing default configuration | Reported as a limitation |
Failures apply to the whole file and return no partial inventory.
Limits
The devicetree, including any embedded image data, must be at most 16 MiB; a larger totalsize fails as a memory limit. Store large images externally (mkimage -E): external data of any size is streamed from the file and never loaded into memory. A FIT may declare at most 1,024 images and 1,024 configurations, and an image at most 8 hash nodes; the devicetree parser's node, property and depth bounds also apply. The sum of declared image sizes is bounded by the shared archive expansion budget. These are fixed resource bounds with no runtime override. Configurable ceilings are tracked in #6176.
Analyzing an image
Inventory does not execute anything, and load and entry are declarations. After extraction:
- inspect
flat_dtimages withinspect_devicetree; - open an uncompressed image with
open_binaryusing formatraw-binary, an architecture matching its declaredarch, andentry_pointset to its declaredloadaddress; raw-binary maps file offset 0 and seeds analysis atentry_point. Automatic suggestions require nonempty bytes, an admitted architecture/address/extent, and a declared entry that is absent or equal to load. Distinct or unreadable entry declarations remain in Evidence without a raw-loader suggestion, since this loader cannot represent separate mapping and analysis entry addresses.
Comparison
Use the shared compare-artifacts / compare_artifacts workflow for exact component paths and stored content identities. Neither extraction nor an external firmware engine is required. This compares the bytes exposed by this FIT reader; it does not inspect files inside a compressed root filesystem, match renamed components, or establish runtime equivalence.
CLI
Retain each complete inspection while returning a summary:
rea inspect-artifact /absolute/baseline.itb --detail summary \
--evidence_output /absolute/baseline-evidence.json --json
rea inspect-artifact /absolute/candidate.itb --detail summary \
--evidence_output /absolute/candidate-evidence.json --jsonThe CLI returns a {summary, evidence_bundle} receipt. Use each response's summary.normalized_result.parent_evidence_id as the corresponding evidence_id below. Save this request as comparison.json, replacing the paths and IDs with the returned values, then run rea compare-artifacts comparison.json --json. Evidence-file paths must be absolute. Naming the exact complete parent avoids ambiguity when a bundle contains several inspection or inventory records.
{
"left": {
"kind": "evidence-file",
"path": "/absolute/baseline-evidence.json",
"evidence_id": "COMPLETE_BASELINE_EVIDENCE_ID"
},
"right": {
"kind": "evidence-file",
"path": "/absolute/candidate-evidence.json",
"evidence_id": "COMPLETE_CANDIDATE_EVIDENCE_ID"
}
}MCP
For each file, call open_binary with its path, then inspect_artifact with {"detail":"summary"}. Opening the second file retains the first inspection's Evidence. Compare the two complete parent IDs without resending their graphs:
{
"name": "compare_artifacts",
"arguments": {
"left": {
"kind": "retained-evidence",
"evidence_id": "COMPLETE_BASELINE_EVIDENCE_ID"
},
"right": {
"kind": "retained-evidence",
"evidence_id": "COMPLETE_CANDIDATE_EVIDENCE_ID"
}
}
}The result counts unchanged, added, removed, changed, unknown and contradictory paths, returning every delta inline with source Evidence links. The root . is the outer FIT and is counted separately from images/<unit-name>.bin. A changed outer hash therefore does not imply every component changed. Additions and removals require complete container-entry coverage; ambiguous duplicate paths or missing observations cannot prove absence or equivalence.
Artifact comparison includes an image's payload interpretation, including load and entry declarations. Equivalent external offset forms and inventory positions leave those declarations unchanged. Unavailable interpretations remain unknown, while independently known changes survive; a changed row with an availability dimension does not establish the unavailable field's value.
For supporting facts, batch selected paths rather than requesting the entire inspection again:
{
"name": "inspect_analysis_view",
"arguments": {
"source": {
"kind": "retained-evidence",
"evidence_id": "COMPLETE_BASELINE_EVIDENCE_ID"
},
"view": {
"kind": "inventory",
"collection": "occurrences",
"logical_paths": ["images/kernel-1.bin", "images/fdt-1.bin"],
"fields": [
"artifact_id",
"logical_path",
"hash_status",
"source_location",
"source_path"
],
"offset": 0,
"limit": 64
}
}
}Read collection: "nodes" with those artifact_ids and fields: ["sha256", "size"] to obtain content facts. Join by artifact_id, not array position. Continue using the returned page metadata when necessary. Source locations are ranges in the original FIT, not decoded filesystem offsets. Complete Evidence remains available through the retained parent and export_evidence_bundle. Summary and field selection reduce delivery only; they do not skip inventory hashing or change coverage.
Verification
Synthetic fixtures with computed hashes cover embedded, data-offset and data-position layouts, shared data, overlap and bounds failures, every verified hash algorithm, configurations, resource limits, inventory, extraction and reader lifecycle. CLI and stdio MCP tests exercise the same artifact provider and advertised schemas. Real U-Boot mkimage 2023.01 output has also been verified for embedded, -E -B 0x200, and -E -p 0x2000 -B 0x200 layouts, with byte-exact extraction checked against dumpimage. The OpenWrt 24.10.3 ABT ASR3000 recovery FIT was checked against mkimage, fdtget and dumpimage, including its kernel, initrd and devicetree. No image was executed.
For small containers, complete delivery avoids an additional view request. Choose summary and selected views when the omitted facts justify that extra request; summary delivery does not reduce the underlying inventory work.
The component comparison workflow was additionally checked on the official OpenWrt 24.10.0 and 24.10.1abt_asr3000-initramfs-recovery.itb images (8,519,680 and 8,585,216 bytes). Their SHA-256 values are 083b174e81ed373f2d2f2ea5366f9291767d95375383528fd6b9955ad815b85a and 41129cce68ad6269e5c8c48ef110f97682d6c4202ff2198bfd0d300c3dac132a. An independent FDT byte-range/hash oracle found changed kernel and initrd bytes and an identical DTB; REA reported those two changed components, the changed outer . and one unchanged component. A controlled copy changing only the root timestamp reported only . changed and all three components unchanged. Public CLI comparison of the exported source Evidence matched the MCP Evidence exactly; summary and selected inventory views matched the independent ranges and hashes. These checks did not decompress either initrd or execute the firmware.