Greetings @bw908,
When using torizoncore-builder with custom dts, it would appear that it overrides one of the default dtb files with the requisite changes.
It’s actually a bit more complicated then that. So when TorizonCore Builder deploys a new DTS file, it does so to do this location in the filesystem:
# test.dtb is the new device tree I deployed
torizon@apalis-imx6-05228985:~$ ls /usr/lib/modules/5.4.193-5.7.0+git.f5d73fd6e9f8/dtb/
imx6q-apalis-eval.dtb imx6q-apalis-ixora-v1.1.dtb overlays overlays.txt test.dtb
When OSTree initializes the new deployment it then creates a copy of these device tree files in the location you are familiar with:
torizon@apalis-imx6-05228985:~$ ls /boot/ostree/torizon-ee10f9fd418bae0e9674b4b3bd6edb3b732e00cc9a0df318da42e79d2f8a657a/dtb/
imx6q-apalis-eval.dtb imx6q-apalis-ixora-v1.1.dtb overlays overlays.txt test.dtb
Then as a final step TorizonCore Builder hardcodes the new device tree file in the boot script so that it is chosen:
Boot Script
torizon@apalis-imx6-05228985:~$ cat /usr/lib/ostree-boot/uEnv.txt
fdtfile=test.dtb
kernel_image_type=zImage
overlays_file=“overlays.txt”
otaroot=1
set_bootargs=env set bootcmd_args env set bootargs ${defargs} root=LABEL=otaroot rootfstype=ext4 ${bootargs} ${tdxargs}
set_kernel_load_addr=if test ${kernel_image_type} = “Image.gz”; then
env set kernel_addr_load ${loadaddr};
env set bootcmd_unzip_k ‘unzip $kernel_addr_load $kernel_addr_r’;
else
env set kernel_addr_load ${kernel_addr_r};
env set bootcmd_unzip_k ‘;’;
fi || true
load_overlay=load ${devtype} ${devnum}:${otaroot} ${loadaddr} /boot${fdtdir}/${overlays_file}; env import -t ${loadaddr} ${filesize}
apply_overlays=fdt addr ${fdt_addr_r} && fdt resize 0x20000 &&
for overlay_file in ${fdt_overlays}; do
echo “Applying Overlay: ${overlay_file}” &&
load ${devtype} ${devnum}:${otaroot} ${loadaddr} /boot${fdtdir}/overlays/${overlay_file} && fdt apply ${loadaddr};
done;
bootcmd_load_k=load ${devtype} ${devnum}:${otaroot} ${kernel_addr_load} “/boot”${kernel_image}
bootcmd_load_r=load ${devtype} ${devnum}:${otaroot} ${ramdisk_addr_r} “/boot”${ramdisk_image}; env set ramdisk_size ${filesize}
check kernel_image2 to avoid booting from other then default emmc in case of
bootlimit is reached and there is no other deployed image
check_rollback_needed=if test -n “${kernel_image2}” && test “${rollback}” = “1”; then
echo “Rollback enabled. Booting previously deployed version.”;
env set kernel_image ${kernel_image2};
env set ramdisk_image ${ramdisk_image2};
env set bootargs ${bootargs2};
env set fdtdir ${fdtdir2};
env set fdt_file ${fdt_file2};
env set fdtfile ${fdtfile2};
fi || true
set_fdt_path=if test -n “${fdtdir}”; then
env set fdt_path /boot${fdtdir}/${fdtfile};
else
env set fdt_path /boot${fdt_file};
fi || true
bootcmd_dtb=load ${devtype} ${devnum}:${otaroot} ${fdt_addr_r} ${fdt_path};
if test ${skip_fdt_overlays} != 1; then
if test -e ${devtype} ${devnum}:${otaroot} /boot${fdtdir}/${overlays_file}; then
run load_overlay && run apply_overlays || true;
fi || true;
fi || true
set_bootargs_custom=if test -n “${fdt_overlays}”; then
for overlay_file in ${fdt_overlays}; do
if test “${overlay_file}” = “custom-kargs_overlay.dtbo”; then
if fdt get value custom_kargs /chosen/ bootargs_custom; then
env set bootargs ${bootargs} ${custom_kargs};
fi;
fi;
done;
fi || true
board_fixups=if test “${board}” = “verdin-imx8mm”; then
if test “${fdtfile}” = “imx8mm-verdin-nonwifi-v1.1-dahlia.dtb”; then
env set fdtfile imx8mm-verdin-nonwifi-dahlia.dtb;
elif test “${fdtfile}” = “imx8mm-verdin-nonwifi-v1.1-dev.dtb”; then
env set fdtfile imx8mm-verdin-nonwifi-dev.dtb;
elif test “${fdtfile}” = “imx8mm-verdin-wifi-v1.1-dahlia.dtb”; then
env set fdtfile imx8mm-verdin-wifi-dahlia.dtb;
elif test “${fdtfile}” = “imx8mm-verdin-wifi-v1.1-dev.dtb”; then
env set fdtfile imx8mm-verdin-wifi-dev.dtb;
fi;
fi || true
bootcmd_boot=bootz ${kernel_addr_r} ${ramdisk_addr_r}:${ramdisk_size} ${fdt_addr_r}
bootcmd_run=run board_fixups && run check_rollback_needed && run set_bootargs && run set_fdt_path &&
run bootcmd_dtb && run bootcmd_args && run set_bootargs_custom && run set_kernel_load_addr &&
run bootcmd_load_k && run bootcmd_unzip_k && run bootcmd_load_r && run bootcmd_boot
This effectively overwrites whatever fdtfile
is set as in the U-boot environment.
Now back to your overall question. TorizonCore Builder is only designed to deploy one new custom device tree at a time. If you attempt to deploy a second after the first, the first one will be removed from the deployment in favor of the 2nd one. To deploy multiple new device trees at once currently you’d either need to do a Yocto build that does this. Or you could inject new device tree files using raw OSTree commands similar to how TorizonCore Builder does under the hood, though this could be messy.
As for choosing which device tree you want to use on boot. As you said you’d need custom U-Boot and/or boot script logic in order to do this. To modify the U-Boot environment or the boot script in a free-form way is currently outside of the capabilities of TorizonCore Builder. Furthermore, U-Boot lives outside of OSTree so this really only leaves Yocto as a viable option to customizing this.
Now with all that said, it would appear that you’d need at a minimum a custom image that has all your device tree variants deployed along with custom boot logic to choose and load the correct device tree file. With this in theory, you could have a single image for multiple hardware variants. I’m not sure if this is particularly “simpler” or “easier” than having different images for different hardware variants.
Best Regards,
Jeremias