Skip to content

Provision and build declared device-tree overlays - #183

Open
jetm wants to merge 3 commits into
mainfrom
eng-2134-device-tree-overlays
Open

Provision and build declared device-tree overlays#183
jetm wants to merge 3 commits into
mainfrom
eng-2134-device-tree-overlays

Conversation

@jetm

@jetm jetm commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Problem

The CLI had no support for the device-tree-overlay feature: it neither provisioned the SDK overlay tooling nor compiled and delivered overlays during a runtime build.

Solution

When an extension declares device_tree_overlays, provision the SDK wrapper and per-BSP delivery hook during sdk install, then compile and deliver each declared overlay during avocado build.

Key changes

  • sdk/install: provision device-tree-overlay tooling (nativesdk-avocado-dtc-overlay plus the delivery-hook package) from extension declarations
  • runtime/build: compile and deliver declared device-tree overlays into the OS bundle
  • runtime/build: search the SDK stone dir for BSP boot artifacts - see the note below, this commit's motivation changed after it was written

Reviewer notes

Top of the device-tree-overlay stack (ENG-2134). Both dependencies are now merged - stone#28 and meta-avocado#245 - so this no longer waits on anything to be reviewable.

Why aa2d49a is in this PR

It was written for a Raspberry Pi failure, File 'u-boot.bin' not found in any input directory for FAT image, on the theory that nothing staged u-boot into stone's input dir. That theory was wrong. A real rpi5 build showed avocado-img-bootfiles already ships u-boot.bin and bootfiles/*, reachable through avocado-runtime's RDEPENDS; the project that failed simply had not declared avocado-runtime. meta-avocado#274 chased the same wrong premise from the BSP side and is closed for that reason.

The commit stays because a different consumer turned up and this time the gap is real. On Tegra the base DTB genuinely is absent from the runtime input dir - the .dtb files under runtimes/<rt>/devicetree/ are AGX Orin parts, and only tegraflash-bsp carries the Orin Nano one - and the overlay delivery hook has to read it to merge overlays into it. meta-avocado#293 stages that BSP into the SDK stone dir; this commit is the half that reads it. The runtime/build.rs comment describing itself as "the consumer half of a two-part change" is accurate, and #293 is the other half.

Merge order is not a constraint: without #293 the directory holds nothing new, so the search is inert rather than broken.

Verification

  • raspberrypi5: build path end to end - wrapper compiles the .dtbo, hook delivers and claims it, os-bundle.aos finalizes. Re-run green after the Jetson work as a regression gate.
  • Jetson Orin Nano Developer Kit (P3767-0005), on-device: paired positive and negative. With the overlay declared, /proc/device-tree/hello-overlay/avocado,marker reads the declared value on the running board; with the declaration removed and nothing else changed, the node is absent. Requires meta-avocado#292 and #293.

The Jetson result is worth one line of emphasis for a reviewer of this PR specifically: every build-path assertion this code emits passed for two full rounds while the board booted with no overlay applied. The unclaimed-overlay guard here is what makes a missing delivery loud; it cannot detect a delivery that lands in the wrong place. Only reading the running kernel's device tree did.

Known gap, not introduced here

avocado runtime provision cannot flash a Jetson from its container. The production path passes no --privileged - the occurrence in provision.rs is inside #[cfg(test)] - so libusb fails at could not retrieve chip ID. With --privileged added by hand, signing and RCM boot report success but the target never boots the pushed initrd or exports its LUN. The identical sequence run host-side succeeds every time, and every Jetson flash behind the verification above was host-side.

This is pre-existing on main and out of scope here, but it means the documented CLI provisioning path is not the path the Jetson result was obtained through. Tracked separately.

jetm added 2 commits August 12, 2026 15:31
Shipping a custom device-tree overlay previously meant forking the BSP:
the CLI had no notion of one, so a .dtbo could not be compiled from the
project or routed onto the boot medium. Add a declarative path. An
extension declares its overlays under `device_tree_overlays`, and the
runtime build compiles each one, stages it, hands off to the board's
delivery hook, and fails the build if anything went undelivered.

Placement is at the extension level, alongside the sibling `overlay`
key, because a runtime's `packages` list is frequently a bare list of
names with nowhere to hang per-overlay objects. The name is a validated
basename because it is reused verbatim as the .dtbo filename and the
boot-loader argument.

Compilation is generated into the in-container build script rather than
run in Rust: the dtc/cpp toolchain, the kernel dt-bindings, and the
delivery hook all live in the SDK container. The script calls the
nativesdk-avocado-dtc-overlay wrapper per overlay, writes an
overlays.manifest.json, runs the single fixed-path per-BSP hook
($OECORE_TARGET_SYSROOT/usr/libexec/avocado/device-tree-overlay-deliver),
and passes the hook-emitted stone fragment through `stone bundle
--overlay`. Two failure modes are hard errors, not silent successes:
overlays declared with no hook installed, and overlays staged but left
unclaimed by the hook.

Fold the declarations and each .dtso's content hash into the
runtime-build input hash. Overlays are compiled at runtime-build time,
so without this an added or edited overlay would leave the stamp valid
and ship the previous bundle unchanged.

Signed-off-by: Javier Tia <javier@peridio.com>
When an extension declared device_tree_overlays, the CLI compiled and
delivered the overlays at runtime-build time but never installed the tools
that step needs: the nativesdk-avocado-dtc-overlay SDK wrapper and the
per-BSP avocado-dtc-overlay-deliver hook had to be staged into the SDK by
hand, so a clean install could not build a declared overlay. The
target-sysroot install that would carry the hook was also gated on an
active compile section, which a no-#include overlay does not require, so a
pure path/phandle overlay got no target-sysroot at all.

Scan the active extension set (not a single runtime's enabled list, since
the SDK install spans every runtime) for device_tree_overlays and, when any
declares them, add nativesdk-avocado-dtc-overlay to the SDK packages and
avocado-dtc-overlay-deliver to the target-sysroot, widening the
target-sysroot trigger to fire on a declaration as well as a compile
section. nativesdk-dtc is pulled by the wrapper's RDEPENDS and stone is a
baseline SDK package, so neither is listed. A BSP that ships no hook
package now fails at install time rather than at the build-time backstop.

Signed-off-by: Javier Tia <javier@peridio.com>
@jetm
jetm force-pushed the eng-2134-device-tree-overlays branch from 5d58ff7 to 208191e Compare August 12, 2026 21:35
A BSP's stone-<arch>.json references boot artifacts this build does not
produce - u-boot.bin and bootfiles/ on Raspberry Pi - while the only
input directory passed to stone is the runtime dir, which holds just what
the build made: rootfs, kernel, initramfs, var. Anything else the
manifest names fails resolution with "File 'u-boot.bin' not found in any
input directory for FAT image", and the runtime build dies at finalize.

Add the SDK's own stone dir as a second input. That is where a BSP recipe
would stage artifacts it wants a manifest to be able to name, and it is
already where the manifest itself is read from, so the two stay together.

This is the consumer half of a two-part change and does nothing on its
own: meta-avocado's avocado-sdk-target currently installs only the stone
JSON there, so no new file resolves from the added directory yet. It is
still the right half to land separately - stone resolves first-match-wins
across -i directories, so an extra input carrying nothing cannot change
what any current build resolves - but the finalize failure it targets
stays until the BSP recipe stages u-boot.bin and bootfiles/ into that
directory. The comment says so rather than leaving the next reader to
conclude the gap is closed.

Signed-off-by: Javier Tia <floss@jetm.me>
@jetm

jetm commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Producer half is up: avocado-linux/meta-avocado#274 stages u-boot.bin and bootfiles/ into the SDK stone dir, which is the directory this PR adds as a stone -i input.

Either half alone is inert and neither regresses a current build (stone resolves first-match-wins across -i dirs, so until both land the added directory carries nothing new), so they can merge in either order.

@jetm
jetm marked this pull request as ready for review August 15, 2026 19:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant