mirror of
https://github.com/morluto/rea.git
synced 2026-11-03 05:16:16 +00:00
* feat(artifacts): inventory and extract U-Boot FIT images open_binary refused U-Boot Flattened Image Tree files as an unsupported format, so inspect_artifact and extract_artifact could not list or recover a FIT's kernel, devicetree, ramdisk and loadable images. Recognize an FDT v16/v17 with a top-level /images node and parse it with the existing parseDevicetree. Each /images child becomes an inventory entry named images/<unit-name>.bin that extracts its stored bytes from embedded data, data-offset (past the 4-aligned devicetree end) or data-position (from the file start). Image format_metadata records the declared type, arch, os, compression, load and entry; root metadata records the description, timestamp and configurations. crc32, md5, sha1, sha256, sha384 and sha512 hash nodes are verified in one streamed pass per image; other algorithms are reported unverified. Signatures are reported, not verified, and nothing is decompressed, decrypted or executed. Data outside the file, overlapping or duplicate image data, a missing or repeated data source and hash mismatches fail closed. The devicetree is bounded by the fixed 16 MiB allowance; external image data is streamed from disk. Refs #7129 * fix(artifacts): bound FIT configuration references and suggest analysis only for plain images * fix(artifacts): retain buffered FIT stream cancellation * test(artifacts): gate FIT faults on the observed read phase * fix(artifacts): verify FIT links and summary identities * fix(artifacts): bound FIT diagnostics and retain unknown signatures * fix(artifacts): compare FIT declarations and resolved data links * fix(artifacts): admit FIT raw probes through the shared loader contract * fix(artifacts): preserve FIT field availability independently * fix(artifacts): isolate nested entry metadata from reader facts --------- Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com> Co-authored-by: gensokyo-dev <342580529+users.noreply.github.com>
173 lines
9.9 KiB
Markdown
173 lines
9.9 KiB
Markdown
# 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.
|
|
|
|
```sh
|
|
rea inspect-artifact ./boot.itb --json
|
|
rea inspect-artifact ./boot.itb --detail summary --evidence_output evidence.json --json
|
|
rea extract-artifact ./boot.itb --json
|
|
```
|
|
|
|
For 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`](devicetree.md) 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](https://github.com/morluto/rea/issues/6176).
|
|
|
|
## Analyzing an image
|
|
|
|
Inventory does not execute anything, and `load` and `entry` are declarations.
|
|
After extraction:
|
|
|
|
- inspect `flat_dt` images with [`inspect_devicetree`](devicetree.md);
|
|
- open an uncompressed image with `open_binary` using format `raw-binary`, an
|
|
architecture matching its declared `arch`, and `entry_point` set to its
|
|
declared `load` address; raw-binary maps file offset 0 and seeds analysis at
|
|
`entry_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
|
|
|
|
Artifact comparison reports changes to 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.
|
|
|
|
## 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.
|