U-Boot ARM64 Linux Handoff: Audit Registers, Cleanup and the Final Branch

The last serial line says that the kernel is starting, but Linux
produces no further output. That line is useful evidence of progress
inside U-Boot; it is not proof that the processor entered Linux with the
required register and machine state.

This article reviews the direct AArch64 Linux handoff in U-Boot
v2025.01 against Linux v6.12’s documented boot contract. It excludes the
EFI entry path, AArch32 kernels and arbitrary firmware payloads. For a
Buildroot product, record the selected U-Boot and kernel builds
together, including any secure firmware or board-specific handoff
changes.

The Linux entry contract, U-Boot cleanup hooks and the final architecture branch are checked separately before claiming kernel entry.

Begin with the receiver’s
contract

The Linux
v6.12 AArch64 boot document
defines the initial register values:
x0 contains the physical address of the device tree, while
x1 through x3 are zero. It also requires
non-secure EL1 or EL2 entry, masked interrupts and an inactive MMU.
Cache state and maintenance have additional requirements; “all caches
off” is not a complete replacement for reading them.

The same document requires DMA-capable devices to be quiesced. A
peripheral that continues writing into memory can undermine an otherwise
correct entry address. These requirements belong in the handoff review
even when a previous kernel happened to boot successfully.

Create a contract ledger with one row per relevant condition. For
each row, name the component responsible, the implementation location
and the evidence used to verify it. Secure firmware may establish part
of the state before U-Boot runs, while U-Boot or board code establishes
another part. Leaving responsibility implicit makes changes between
those components difficult to diagnose.

Follow the selected U-Boot
branch

In the tagged
ARM boot implementation
, the ARM64 boot_jump_linux()
path obtains the selected entry address and runs cleanup before its
final architecture transition. The AArch64 branch supplies the FDT
address followed by three zero arguments to the transition helper.

Configuration affects the path. The
CONFIG_ARMV8_SWITCH_TO_EL1 branch uses an additional
transition function, while the implementation also contains AArch32
handling that is outside this article’s scope. Review the generated
configuration and chosen image architecture, not merely a search result
containing one matching call.

Do not replace this sequence with a generic jump to the image
address. The entry address is only one part of the contract. A direct
jump from an unrelated command can omit preparation that the supported
Linux boot path performs.

The banner
appears before cleanup is finished

announce_and_cleanup() calls a board quiescence hook,
prints the kernel-start message, removes eligible active devices and
then calls cleanup_before_linux(). Thus the familiar
message precedes some cleanup work and the final transition.

The helper also supports a fake-go tracing path, with an explicit
marker in the printed message. In that mode, preparation can run without
taking the final kernel branch. Preserve the exact log rather than
reducing every message beginning with the same words to a single “kernel
launched” event.

For a silent failure, distinguish at least three observations:
reaching the cleanup helper, completing cleanup and reaching the
receiver’s first confirmed execution point. The last one requires
evidence from the receiving stage or a suitable debugger. It cannot be
inferred solely from the sender’s earlier print statement.

Check the
board-specific cleanup obligations

The generic board_quiesce_devices() definition in this
file is weak and empty. A board can override it. Device removal also
applies to devices carrying the relevant removal flags; it is not a
source-level guarantee that every possible external DMA engine has
stopped.

The ARMv8
cleanup implementation
invokes a board cleanup hook, disables
interrupts and follows configuration-dependent cache-maintenance paths.
This provides concrete locations to inspect, but the existence of the
function alone does not prove that every platform-specific coherency
requirement is satisfied.

Inventory the devices that U-Boot actually used, especially network
and storage engines with DMA capability. For each, identify the normal
removal or explicit board action that stops further access. Include
firmware-managed devices outside U-Boot’s ordinary driver-model
ownership. Keep this audit separate from whether the Linux driver will
eventually initialize the device.

Use evidence that
survives the transition

A proposed qualification record should capture the kernel and tree
identities, chosen architecture branch, entry address and relevant
machine-state observations. Record where each observation was obtained.
A debugger snapshot taken before cache cleanup proves a different point
from one taken immediately before the final branch.

When instrumentation is necessary, account for its own constraints. A
serial message added after a console has been quiesced may not be
reliable. A logging buffer can be overwritten or unavailable to the next
stage. Select a board-supported tracing method and document its memory
ownership and timing relative to cleanup.

Exercise cold and warm-start conditions where the product supports
both. A warm path can inherit device state that a reset cleared in the
cold test. Repeat after changes to active peripherals, secure firmware
and exception-level configuration. These are proposed qualification
cases; no register captures or board boots were performed here.

Keep the
conclusion narrower than the symptom

If the last evidence is the kernel-start banner, report that U-Boot
reached that print location. If cleanup completed but no receiver
evidence exists, report that boundary separately. A silent Linux console
can also reflect a console configuration problem, so it should not be
diagnosed as a handoff failure without further evidence.

A complete handoff review connects the receiver’s requirements to the
exact sender branch and its board hooks. That connection is more durable
than a successful jump address or a reassuring final message, because it
identifies which component must preserve each condition when the boot
chain changes.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *