Device Tree Overlays

In my local hackerspace I maintain a Raspberry Pi based system with some hardware extensions (mainly I2C devices). It’s running with Debian’s kernel and a patched device tree for the additional hardware components.

This is the ideal candidate for DT overlays, so that I can use the DT blob provided by Debian and automatically apply the custom changes in top. With DT overlays from configfs still not being available I thought about giving the U-Boot “fdt apply” command added by Maxime Ripard from Free Electrons a chance. So I rebuild U-Boot with overlay support enabled, but it turns out U-Boot’s support for patching the DT is quite limited. Also in case of any merge problems in the future, the system would hang in bootloader stage, which is not nice.

So I hacked together a small script using libfdt’s fdt_overlay_apply() function to merge the DT blob. Unfortunately that also did not work as expected. Device Tree overlays can target existing nodes using two different schemes, as described in this file.

The phandle based referencing only works if the base.dtb has been compiled with the “-@” option, which adds a symbol node for translation of phandle names. Since Debian’s device tree blobs have not been build this way, I have to use target-path based referencing instead. This is ok, until you need a phandle to an existing node.

In theory this could be solved using the following workaround:

base.dts

/dts-v1/; / { test1: test-node1 { subtest1: sub-test-node { demo-property; another-property; }; }; test2: test-node2 { subtest2: sub-test-node { demo-handle = <&subtest1>; }; }; };

overlay.dts

/dts-v1/; /plugin/; / { fragment@0 { target-path = “/test-node1”; overlay { new_ref_to_subtest: sub-test-node { another-property; }; sub-test-node2 { demo-handle = <&new_ref_to_subtest>; }; }; }; };

This can be compiled and merged perfectly fine using

dtc -I dts -O dtb -o overlay.dtb overlay.dts dtc -I dts -O dtb -o base.dtb base.dts fdt_overlay_apply(base.dtb, overlay.dtb);

But the generated DTB is wrong, which can be seen after decompiling (check the phandles and demo-handles):

combined.dts

/dts-v1/; / { test-node1 { sub-test-node2 { demo-handle = <0x2>; }; sub-test-node { demo-property; another-property; linux,phandle = <0x2>; phandle = <0x2>; }; }; test-node2 { sub-test-node { demo-handle = <0x1>; }; }; };

– Sebastian