This is a continuation of the discussion that started in reply to my patch adding basic device trees for Pixel 10 phones [1].
Problem statement: ------------------
We would like an officially accepted scheme that lets us more efficiently ship compiled device trees for a handful of related products by breaking the device trees up into a common "base" device tree and then applying "overlay" device trees atop the base to make a full and complete device tree.
To make it more concrete, we'd like to build a "base" device tree that describes a SoC and then have the overlays be enough to make a full description of a board. In theory, one could also imagine wanting to expand this to 3 or more levels (perhaps SoC, baseboard, derived boards), though this is not planned at this time.
The primary reason for wanting to break device trees like this is efficiency of the shipped binary device trees. A large portion of a final device tree just describes the SoC. We save space in the final compiled device trees if they don't need to contain as much duplicated information.
A secondary reason for wanting to break device trees like this is to more nicely handle when a board has a socketed SoC that can be replaced with a finite (and small) number of different SoCs (usually revisions of the same SoC). Even if this secondary reason is considered invalid or too difficult, the primary reason still describes a compelling need.
In order to make this proposal work, it's expected that a bootloader will understand the scheme and will know how to combine the overlay atop the base before passing a complete device tree to the main OS.
Current state of the art (downstream): --------------------------------------
In Android, we do a pretty good job of solving the stated problem using device tree overlays. We describe the SoCs in "dts" files and compile them into "dtb"s. We describe boards in "dtso" files and compile them into "dtbo" files. A bootloader can handle identifying the correct base and overlay (the scheme for doing this is a separate but related topic) and applying the overlay atop the base "dtb". This solution is fully implemented downstream for Android phones and is well documented [2].
The issues I'm aware of with the current state of the art are:
1. In order for the base device tree to pass schema validation on its own we'd need to document the top-level compatible strings in the device tree. It is the opinion of at least some device tree maintainers that a SoC doesn't qualify as a top-level compatible string. This prevents the device trees from landing in an officially sanctioned location.
2. It is also possible we may fail schema validation for the base SoC tree if the schema marks a property as "required" but that property needs to be filled out by the board (perhaps a "-supply" is marked as "required", since most "-supply" properties are filled in by the board. I'm not sure this is a big issue, but it's something to think about.
3. It's unclear if there is any official "ABI" promised here once we've compiled and validated the base device tree on its own. Will people assume that they can have out-of-tree overlays derived from the base SoC tree and that those out-of-tree overlays will continue to work across changes / cleanups to the base? NOTE: this is a pre-existing question for existing device tree overlay usage, but the sheer quantity of nodes/properties that a board would be expected to overlay/modify in the base make the problem more prominent.
4. We want the final device tree's top-level compatible to be all the compatible strings from the board followed by all of the compatible strings for the SoC. When the board's overlay is applied to the base SoC tree, though, the board's top-level compatible fully replaces the compatible from the base SoC tree. This can be solved today for non-socketed boards by just duplicating the SoC compatible strings in the board overlays. We can't solve this today for socketed boards, though we can simply make sure that no software drivers rely on the specific SoC compatible string being present and thus we can ignore the problem.
None of the above problems are big enough to have prevented widespread use of this scheme in downstream Android.
Current state of the art (upstream): ------------------------------------
Upstream if we have a pile of related boards, we do allow deduplicating things at a source-code level with "dtsi" files. We can have a SoC "dtsi" file and that file is included by all boards that use that SoC. When it comes time to validate or ship things, though, we only work with full devices trees. This means that we ship duplicated information.
Proposal: ---------
1. Allow the top-level compatible string of an "incomplete" device tree to be documented so it can be validated on its own by tools. It's understood that this SoC is not a board by itself and we'd never boot a full OS with this device tree without adding an overlay that changes the top-level compatible. Add a top-level property to the device tree (perhaps "incomplete-compatible;") to indicate that the tree is not complete without an overlay.
2. If it turns out to be needed (hopefully it's not), allow some type of syntax in yaml files that allows a property to be marked as "required" in a "complete" device tree but not in an "incomplete" device tree. Alternatively, we could discourage marking properties as "required" if they're expected to be filled in by a board.
3. Define that there is no promised ABI between "incomplete" device trees and anything not stored with them. Specifically, all valid combinations of "incomplete" device trees with overlays to complete them should be enumerated together with the "incomplete" device tree.
4. When applying an overlay to a device tree that's "incomplete", the top level overlay will be merged instead of replaced.
Example for 2 levels:
base (incomplete) compatible: "socvendor,mysoc-rev1", "socvendor,mysoc"; overlay compatible: "boardvendor,myboard-rev1", "boardvendor,myboard"; merged compatible: "boardvendor,myboard-rev1", "boardvendor,myboard", "socvendor,mysoc-rev1", "socvendor,mysoc";
Possible example if we support 3 levels:
SoC (incomplete) compatible: "socvendor,mysoc-rev1", "socvendor,mysoc" overlay1 (incomplete) compatible: "referencevendor,referencecodename"; overlay2 compatible: "boardvendor,myboard-rev1", "boardvendor,myboard" merged compatible: "boardvendor,myboard-rev1", "boardvendor,myboard", "referencevendor,reference-codename", "socvendor,mysoc-rev1", "socvendor,mysoc";
Obviously in the 3-level scheme we need to know the order that overlays are applied, but that's true for overlays today anyway.
The above proposal takes the current downstream "state of the art" and addresses the known issues, solving the original problem statement.
Other thoughts: ---------------
If you don't like the proposal, I'd be interested in knowing if you have other ideas for solving the original problem statement, or if you simply think the problem we're trying to solve here is an invalid one.
I'm happy to post up another revision of my Pixel 10 device trees following this proof of concept (or other ones). My v1 was _very_ close to this, but didn't have the "incomplete-compatible;" property and didn't implement top-level compatible merging.
[1] https://lore.kernel.org/r/20251111112158.1.I72a0b72562b85d02fee424fed939fea9... [2] https://source.android.com/docs/core/architecture/dto/partitions
- When applying an overlay to a device tree that's "incomplete", the
top level overlay will be merged instead of replaced.
Example for 2 levels:
base (incomplete) compatible: "socvendor,mysoc-rev1", "socvendor,mysoc"; overlay compatible: "boardvendor,myboard-rev1", "boardvendor,myboard"; merged compatible: "boardvendor,myboard-rev1", "boardvendor,myboard", "socvendor,mysoc-rev1", "socvendor,mysoc";
Possible example if we support 3 levels:
SoC (incomplete) compatible: "socvendor,mysoc-rev1", "socvendor,mysoc" overlay1 (incomplete) compatible: "referencevendor,referencecodename"; overlay2 compatible: "boardvendor,myboard-rev1", "boardvendor,myboard" merged compatible: "boardvendor,myboard-rev1", "boardvendor,myboard", "referencevendor,reference-codename", , "socvendor,mysoc";
Sorry, I only cursorily followed the previous discussion so I may have missed the exact need for this part. But I would caution against any proposal that changes the basic rules of how an overlay is applied. The definition of how overlays work has (I think?) been stable for over a decade now, and is implemented in bootloaders that often cannot easily be updated. I absolutely support your effort to get more upstream standardization for managing base device trees and overlays (which I think need to be flexible for arbitrary layers, not just SoC and board), but let's not break the overlay code in old bootloaders while doing it.
Is there really a need to merge the compatible strings in your case? I think in the vast majority of platform identification cases, code only cares about matching the most precise string (i.e. "boardvendor,myboard-rev1"). If we do feel like having the whole chain of identification is necessary, it could be achieved by just copy&pasting the extra strings into the overlay file. If we have cross-validation between base and overlay source files we could also have the validation check that the overlays correctly contain all compatible strings from their base tree. If we know that the base trees aren't standalone anyway, we could also just invent other property names that identify them (e.g. `soc-compatible = "socvendor,mysoc";`). Anything other than breaking the overlay format would be preferable in my opinion.
I also feel like we need a better standardized way to tie base device trees to overlays, like your `/loaders` node proposal in an earlier email, although maybe that's an orthogonal discussion (but related, especially if there's supposed to be cross-validation between base trees and overlays). The compatible string is just not a scalable way for bootloaders to make this determination, there may be a lot more differentiation than just "SoC" and "board", and the scheme almost certainly needs to be platform/bootloader-specific because every hardware vendor has their own ideas about how to group and reuse parts of a platform. This information doesn't necessarily need to be *in* the device tree, it could also just be in a separate YAML file in the same repo (since bootloaders will almost certainly want to have it transformed into their own out-of-band descriptor at build-time anyway, so that they can compress the device tree itself and don't have to decompress each one for matching), but it needs to be somewhere.
Hi,
On Tue, Nov 18, 2025 at 3:48 PM Julius Werner jwerner@chromium.org wrote:
- When applying an overlay to a device tree that's "incomplete", the
top level overlay will be merged instead of replaced.
Example for 2 levels:
base (incomplete) compatible: "socvendor,mysoc-rev1", "socvendor,mysoc"; overlay compatible: "boardvendor,myboard-rev1", "boardvendor,myboard"; merged compatible: "boardvendor,myboard-rev1", "boardvendor,myboard", "socvendor,mysoc-rev1", "socvendor,mysoc";
Possible example if we support 3 levels:
SoC (incomplete) compatible: "socvendor,mysoc-rev1", "socvendor,mysoc" overlay1 (incomplete) compatible: "referencevendor,referencecodename"; overlay2 compatible: "boardvendor,myboard-rev1", "boardvendor,myboard" merged compatible: "boardvendor,myboard-rev1", "boardvendor,myboard", "referencevendor,reference-codename", , "socvendor,mysoc";
Sorry, I only cursorily followed the previous discussion so I may have missed the exact need for this part. But I would caution against any proposal that changes the basic rules of how an overlay is applied. The definition of how overlays work has (I think?) been stable for over a decade now, and is implemented in bootloaders that often cannot easily be updated. I absolutely support your effort to get more upstream standardization for managing base device trees and overlays (which I think need to be flexible for arbitrary layers, not just SoC and board), but let's not break the overlay code in old bootloaders while doing it.
Is there really a need to merge the compatible strings in your case? I think in the vast majority of platform identification cases, code only cares about matching the most precise string (i.e. "boardvendor,myboard-rev1"). If we do feel like having the whole chain of identification is necessary, it could be achieved by just copy&pasting the extra strings into the overlay file. If we have cross-validation between base and overlay source files we could also have the validation check that the overlays correctly contain all compatible strings from their base tree. If we know that the base trees aren't standalone anyway, we could also just invent other property names that identify them (e.g. `soc-compatible = "socvendor,mysoc";`). Anything other than breaking the overlay format would be preferable in my opinion.
I'm certainly not dead-set on it and I definitely realize it would be a pain. ...though it wouldn't necessarily "break" the format--you just wouldn't be able to use any "incomplete" DTBs unless you implemented this new feature.
From my point of view, the main issue the merging solves is handling "socketed" boards that could have any of a small number of SoCs plugged into them (usually minor revs of the same SoC). It's not the absolutely most critical use case in the world, but I know that we will need it in-house and I'm trying to come up with a solution that will work everywhere. Once we decide to go with a downstream solution just for that one use case then there's no reason not to do everything else in a downstream manner.
Personally, I've never really loved that the SoC compatible strings are conventionally just jammed onto the end of the top-level compatible and I'm totally happy with it being elsewhere (a different property, a different node, etc). Mostly I ended up with this merging scheme because I thought that was what DT folks were pushing for. If I'm wrong then I'm more than happy with a different scheme.
I also feel like we need a better standardized way to tie base device trees to overlays, like your `/loaders` node proposal in an earlier email, although maybe that's an orthogonal discussion (but related, especially if there's supposed to be cross-validation between base trees and overlays). The compatible string is just not a scalable way for bootloaders to make this determination, there may be a lot more differentiation than just "SoC" and "board", and the scheme almost certainly needs to be platform/bootloader-specific because every hardware vendor has their own ideas about how to group and reuse parts of a platform. This information doesn't necessarily need to be *in* the device tree, it could also just be in a separate YAML file in the same repo (since bootloaders will almost certainly want to have it transformed into their own out-of-band descriptor at build-time anyway, so that they can compress the device tree itself and don't have to decompress each one for matching), but it needs to be somewhere.
Yes, I totally agree and this is an important conversation to have too. I still like the "/loaders" proposal but I'm not dead-set on it.
That being said, the two problems are separate even if they're related to each other. I was attempting to focus on allowing the base DTBs to land first and once we get agreement then move onto the second. I'll also note that Chen-Yu is talking about the problem at Linux Plumbers. I won't be there, but I'm going to try to attend that session remotely.
-Doug
boot-architecture@lists.linaro.org