U-Boot Device Trees: Identify the Control Tree Before Fixing the OS Tree
A peripheral works after Linux starts but is absent in U-Boot.
Replacing the kernel’s device tree repeatedly does not change the
bootloader’s behavior. Before editing another node, determine which
device tree the failing stage actually consumes.
U-Boot v2025.01 distinguishes its control FDT from the working FDT
used for operating-system handoff. The same board can have closely
related descriptions without those objects being interchangeable. This
distinction is especially useful when integrating a U-Boot build into a
Buildroot product, where bootloader and kernel artifacts may be produced
and selected through different configuration paths.

Name the consumer, not
just the filename
The fdt
command documentation identifies the control tree as U-Boot’s own
configuration input, including driver model. The working tree is the one
passed to the operating system. Its -c flag selects the
control tree; without that flag, the command addresses the working
tree.
In a diagnostic record, write “control FDT used by this U-Boot build”
or “working FDT selected for this kernel attempt.” A generic entry such
as “board.dtb checked” leaves the most important question unanswered.
Also record the memory address and artifact origin separately: an
address identifies a runtime object, while a build path identifies a
candidate file.
Start with observation rather than mutation. A no-address
fdt addr invocation reports the current working address,
and fdt addr -c reports the control address when the
command is available. Those observations do not prove the contents are
correct, but they prevent an investigation from silently switching
between two objects.
Trace how the
control artifact is supplied
The tagged
devicetree-control documentation describes several supply
mechanisms. OF_SEPARATE produces a separate tree artifact
that is combined into the normal bootloader output.
OF_BOARD allows board code to provide the tree at runtime.
Other supported arrangements include embedding and an earlier-stage
bloblist. The selected configuration determines which explanation
applies.
Inspect the generated configuration and final deployed image, rather
than assuming a source filename was included. A release can compile the
correct tree but package an older bootloader binary. An earlier stage
can also supply the tree, making a local build output irrelevant to the
runtime object under investigation.
For each tree, preserve a short provenance chain: selected source,
U-Boot-specific additions, generated binary, packaging step and runtime
consumer. Do the same independently for the kernel tree. This is an
evidence exercise, not a requirement that both chains use identical
files.
A tree cannot supply an
absent driver
A valid peripheral node does not add code to the bootloader. The
control documentation explicitly separates build-time driver inclusion
from the configuration those drivers consume. A Linux driver and a
U-Boot driver can also have different capabilities even when they
describe the same hardware.
When a device is missing, inspect three categories separately. First,
confirm the needed U-Boot driver and dependent framework are compiled
for the relevant stage. Second, verify that the actual control tree
contains the intended node and required properties. Third, follow
binding and probing evidence to see whether the device becomes usable.
Editing a node cannot repair an omitted driver, and enabling a driver
does not repair an incorrect clock or reset description.
SPL adds another boundary. The tagged documentation explains that
early stages normally receive a reduced tree, or sometimes none, rather
than every node available to U-Boot proper. A device present after
relocation does not prove it was available when an earlier stage needed
it.
Avoid
treating a live control tree as a safe scratchpad
The command documentation warns that driver-model structures retain
pointers into the control tree. Changing that tree after initialization
can invalidate assumptions already held by the running bootloader. A
command that accepts an address is therefore not a general endorsement
of switching control trees interactively.
For routine qualification, change the build input and restart through
the supported initialization path. If a platform deliberately switches
trees, review its implementation and required driver-model
reinitialization. Do not infer that mechanism from a successful edit of
the working tree.
Likewise, expanding a tree requires adequate free memory at its
destination. A larger declared buffer does not create physical capacity.
Keep any working-tree modification within the product’s reviewed memory
layout and preserve required verification policy for the resulting boot
path.
Build a
two-tree comparison that answers the failure
Choose a single failing peripheral and compare only the properties
relevant to its consumer. Record its node path, status, address
translation, clocks, resets and any U-Boot-specific stage annotations
that the platform uses. Record the corresponding driver configuration
beside the properties. This avoids an unstructured diff of thousands of
unrelated nodes.
A proposed test sequence starts with the known failing bootloader
artifact and captures its tree identity and diagnostic output. Next,
rebuild only the intended control-tree or driver change and confirm the
deployed artifact identity before repeating the observation. Finally,
verify that the working tree still reaches the intended Linux image and
that Linux behavior has not regressed.
Include missing-node and unavailable-driver cases in a recoverable
fixture if those cases can be tested safely. The purpose is to ensure
the diagnostic process distinguishes them, not merely to obtain one
successful startup. No board executions or peripheral results are
claimed here.
Close the
investigation at the correct boundary
The final explanation should identify the tree, stage and driver
involved. “The device tree was wrong” is too broad to prevent
recurrence. A stronger record states which control artifact was
deployed, why the relevant driver could not use it, and which
independent evidence confirms the operating-system tree remained
correct.
Once those identities are explicit, bootloader and Linux debugging
stop competing over an ambiguous file. Each change can be reviewed
against the consumer that actually needs it.