U-Boot FDT Overlays: Preserve Fresh Inputs Before an Apply Can Mutate Them
An overlay application fails, so the boot script retries using the
same memory addresses. That retry can be invalid even when the original
files were correct: overlay application mutates its inputs, and its
error path can invalidate both trees.
This article examines manual working-FDT overlays in U-Boot v2025.01.
It concerns the bootloader selected for a Buildroot product, not live
modification of U-Boot’s control tree or Linux runtime overlay
management.

Resolve symbols before
changing memory
The official
overlay guide describes compiling symbol-based base trees and
overlays with the device-tree compiler’s -@ option. This
retains information needed to resolve references to labels from another
tree.
The actual libfdt
overlay implementation distinguishes external fixups from other
targeting mechanisms. An overlay without external fixups can skip that
fixup step, and a fragment can identify its target by path. Therefore
“every possible overlay always needs a symbol lookup” is too broad.
For the intended overlay, inspect whether it contains external
fixups, which base symbols they require, and whether its target paths
exist. A base tree with a similar board name is not sufficient: symbol
names and paths are part of the overlay’s input contract.
Reserve real growth space
The manual workflow selects the base as the working FDT and expands
its available space before applying the overlay. The guide explicitly
requires enough room for that growth without overlapping another
object.
A resize command adjusts the tree representation; it does not
allocate new physical memory around the existing address. Keep the
overlay, base working buffer and other boot artifacts outside each
other’s full ranges. Size the base buffer for the resulting merged tree,
not just the original file.
Do not use the command’s example addresses as board-independent
defaults. Derive addresses from the product’s memory layout, and account
for any later overlays that need additional capacity.
Successful
application consumes the overlay too
fdt_overlay_apply() adjusts overlay phandles and
references before merging nodes into the base. On success, it
deliberately invalidates the overlay’s magic. The modified base is the
output; the same overlay buffer is not a reusable pristine input.
This matters when applying one overlay to two alternative base trees
or retrying after another stage rejects the boot attempt. Reload or copy
the original overlay for each application. Saving only the original base
leaves the second attempt dependent on an overlay buffer already
consumed by the first.
Overlay order should also be explicit. A preceding overlay can
introduce symbols or nodes referenced by a later one, while later
changes can alter earlier properties. Qualify the ordered set that the
product uses, rather than testing each overlay independently and
assuming the combination is equivalent.
Failure is not
transactional rollback
After mutation begins, the function’s common error path invalidates
both the overlay and base. It does not reconstruct their original
contents. Early header-probe failures can return before this mutation
path, so not every rejected call performs identical writes;
nevertheless, a caller should not treat failure as a promise that its
buffers remain reusable.
The fdt
command handler applies the overlay to working_fdt and
returns failure if the apply helper fails. A script must consume that
status before proceeding to boot with the tree.
A robust retry starts from preserved source copies or reloads both
inputs, restores the required growth space and repeats the intended
sequence. Continuing with a partially modified tree is not a recovery
strategy.
Test the retry, not only
the happy path
The most revealing cases are a missing external symbol, an absent
target path and insufficient base capacity. After each rejected
application, verify that the boot path stops and that its retry
reconstructs fresh buffers. Separately test applying the same overlay
twice from independent pristine copies.
For an ordered overlay set, introduce a failure in the later member
and confirm that recovery rebuilds the whole intended base-plus-overlay
sequence. A successful first member does not make the partially
completed combination an approved fallback.
These are proposed tests, not executed results. The central design
decision is ownership: keep immutable overlay artifacts separate from
mutable apply buffers, and let only a completely accepted merged tree
reach the next boot stage.