Sunday, October 1, 2023

Managing device tree overlays with Yocto

If you have your DT overlay files in the kernel recipe, and have to hardcode their names etc., it clutters the kernel recipe *.bbappend, not to mention the overlays you have to maintain in the recipe files. But you can clean it up (at least I did it the way shown here for our i.MX8 platforms).

Note: some_arch, some_proc_vendor, SOME_DEPLOY_LOC etc. in the following example are arbitrary and just for generic demo purposes. Use the real values in your case.

Move the DT overlays to kernel source

The MACHINE some_machine in the machine configuration file conf/machine/some_machine.conf has following DT overlays moved to the kernel source tree. Note that we have them in the some_machine directory, which is the same as the MACHINE variable value for its build.

arch/some_arch/boot/dts/some_proc_vendor/overlays/some_machine
├── Makefile
├── some_overlay.dts
└── another_overlay.dts

Update KERNEL_DEVICETREE to pick the DT overlays for the machine

- We will not add (hardcode) DT overlay names to KERNEL_DEVICETREE so they are available after parsing the recipe
- Instead, we will update it in the datastore
- Use the datastore d.appendVar("X", "value") to update the variable KERNEL_DEVICETREE before the kernel compilation starts
- Use prefuncs as mentioned in https://stackoverflow.com/a/61039212/2571705 so the KERNEL_DEVICETREE variable changes are not local to this update task
- It will now build any overlays for the machine

python add_dt_overlays() {
    source = d.getVar('S', True)
    machine = d.getVar('MACHINE', True)
    path = source + "/arch/some_arch/boot/dts/some_proc_vendor/overlays/" + machine

    with os.scandir(path) as it:
        for entry in it:
            if entry.name.endswith(".dts") and entry.is_file():
                dtb = " some_proc_vendor/overlays/" + machine + "/" + os.path.splitext(entry.name)[0] + ".dtb"
                bb.debug(1, "dt overlay: %s" % dtb)
                d.appendVar('KERNEL_DEVICETREE', dtb)
}

do_compile[prefuncs] += "add_dt_overlays"

Deploy them to the desired location in the installation phase

do_install_append() {
	install -d ${D}${SOME_DEPLOY_LOC}/dtbo
	# Deploy overlay dtbs if any
	if [ -d ${B}/arch/some_arch/boot/dts/some_proc_vendor/overlays/${MACHINE} ]; then
		install -m 0644 ${B}/arch/some_arch/boot/dts/some_proc_vendor/overlays/${MACHINE}/*.dtb ${D}${SOME_DEPLOY_LOC}/dtbo
	fi
}