From 928365a07eabd3ea6c3f13eb38e67cc413e412d1 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Fri, 11 Sep 2026 02:55:36 +0000 Subject: [PATCH 01/16] u-boot-qcom: build the OP-TEE lib so the OS gets the OP-TEE nodes U-Boot describes OP-TEE in its own devicetree and relies on optee_copy_fdt_nodes() to copy /firmware/optee and the optee reserved memory regions into the devicetree handed to the OS. That helper is part of OPTEE_LIB, which defaults to y with OPTEE but is merged here on top of an expanded .config, so the default never applies and the build ends up with OPTEE on and OPTEE_LIB off. Linux then never sees OP-TEE. Enable it explicitly. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Ricardo Salveti --- recipes-bsp/u-boot/files/tfa-optee.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/recipes-bsp/u-boot/files/tfa-optee.cfg b/recipes-bsp/u-boot/files/tfa-optee.cfg index 1e8364c11..f632dab06 100644 --- a/recipes-bsp/u-boot/files/tfa-optee.cfg +++ b/recipes-bsp/u-boot/files/tfa-optee.cfg @@ -2,3 +2,4 @@ # source TrustZone stack on Qcom platforms CONFIG_TEE=y CONFIG_OPTEE=y +CONFIG_OPTEE_LIB=y From f10e680603d52f68f0be7e05d5a9f868807bf4e2 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Thu, 13 Aug 2026 01:54:50 +0000 Subject: [PATCH 02/16] swiv-build-utility: add native SWIV ELF annotation tool Signing the U-Boot SPL as the Qualcomm TZ image requires a SWIV segment in the ELF first. Package the annotation tool from boot-firmware-ci so the u-boot recipe can run it. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ricardo Salveti --- .../swiv-build-utility_git.bb | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 recipes-devtools/swiv-build-utility/swiv-build-utility_git.bb diff --git a/recipes-devtools/swiv-build-utility/swiv-build-utility_git.bb b/recipes-devtools/swiv-build-utility/swiv-build-utility_git.bb new file mode 100644 index 000000000..8a3117d0f --- /dev/null +++ b/recipes-devtools/swiv-build-utility/swiv-build-utility_git.bb @@ -0,0 +1,23 @@ +SUMMARY = "Qualcomm SWIV (Software Image Version) ELF annotation tool" +DESCRIPTION = "Annotates a boot firmware ELF image with a SWIV segment, as \ +required by the Qualcomm secure boot chain before the image is signed \ +(e.g. U-Boot SPL signed as the TZ partition image)." +HOMEPAGE = "https://github.com/qualcomm-linux/boot-firmware-ci" +LICENSE = "BSD-3-Clause" +LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=223037c4be0bfc6cf757035432adf983" + +SRC_URI = "git://github.com/qualcomm-linux/boot-firmware-ci.git;branch=main;protocol=https" +SRCREV = "a0f007327c1ffc0b568def06c4b035b8d3fb05ac" + +INHIBIT_DEFAULT_DEPS = "1" + +inherit python3native + +do_install() { + install -Dm 0755 ${S}/tools/swiv_build_utility.py \ + ${D}${bindir}/swiv_build_utility +} + +RDEPENDS:${PN} = "python3-core" + +BBCLASSEXTEND = "native nativesdk" From 11b812f9c00e75a8682a60a473c03e64d0c559a5 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Thu, 13 Aug 2026 21:12:28 +0000 Subject: [PATCH 03/16] u-boot-qcom: sign the SPL for the Qualcomm boot chain When QCOM_UBOOT_SPL_FIT is set, stage BL31 and OP-TEE for the FIT that uboot-sign assembles, and prepare the SPL for the Qualcomm secure-boot chain: wrapped into an ELF, annotated with a SWIV segment, signed as the TZ image and deployed as u-boot-spl-.mbn. BL31 and OP-TEE come from per-platform recipes, so the SoC configuration names them. No machine enables the flow yet. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ricardo Salveti --- recipes-bsp/u-boot/u-boot-qcom_git.bb | 35 +++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/recipes-bsp/u-boot/u-boot-qcom_git.bb b/recipes-bsp/u-boot/u-boot-qcom_git.bb index bcc340450..924372103 100644 --- a/recipes-bsp/u-boot/u-boot-qcom_git.bb +++ b/recipes-bsp/u-boot/u-boot-qcom_git.bb @@ -3,6 +3,13 @@ require recipes-bsp/u-boot/u-boot.inc DEPENDS += "bc-native dtc-native gnutls-native python3-pyelftools-native qtestsign-native xxd-native" +QCOM_UBOOT_SPL_FIT ?= "0" +QCOM_UBOOT_SPL_FIT_ATF ?= "" +QCOM_UBOOT_SPL_FIT_TEE ?= "" + +# BL31 and OP-TEE go into the FIT, swiv annotates the SPL before signing. +DEPENDS += "${@bb.utils.contains('QCOM_UBOOT_SPL_FIT', '1', '${QCOM_UBOOT_SPL_FIT_ATF} ${QCOM_UBOOT_SPL_FIT_TEE} swiv-build-utility-native', '', d)}" + COMPATIBLE_MACHINE:aarch64 = "(qcom)" PV = "2026.07+2026.10-rc1+git" @@ -36,14 +43,38 @@ python __anonymous() { uboot_compile_config:append() { config_mbn_header=$(uboot_config_get_indexed_value "${BOARD_MBN_HEADER}" $i) - if [ -n "${config_mbn_header}" ]; then + if [ "${QCOM_UBOOT_SPL_FIT}" = "1" ]; then + # Where uboot-sign's /incbin/ defaults expect them. + install -m 0644 ${RECIPE_SYSROOT}/firmware/${QCOM_UBOOT_SPL_FIT_ATF}/bl31.bin ${B}/${builddir}/bl31.bin + install -m 0644 ${RECIPE_SYSROOT}${nonarch_base_libdir}/firmware/tee-raw.bin ${B}/${builddir}/tee-raw.bin + elif [ -n "${config_mbn_header}" ]; then export CRYPTOGRAPHY_OPENSSL_NO_LEGACY=1 qtestsign -${config_mbn_header} aboot -o ${B}/${builddir}/u-boot.mbn ${B}/${builddir}/u-boot.elf fi } +# Rebuild the SPL ELF after uboot-sign, add the SWIV segment and sign it as TZ. +uboot_assemble_fitimage_helper:append() { + if [ "${QCOM_UBOOT_SPL_FIT}" = "1" ]; then + mbn_header=$(uboot_config_get_indexed_value "${BOARD_MBN_HEADER}" $i) + [ -n "${mbn_header}" ] || mbn_header="v6" + + rm -f spl/u-boot-spl.elf + (unset LDFLAGS CFLAGS; oe_runmake -C ${S} O=${B}/${builddir} ${UBOOT_MAKE_OPTS} spl/u-boot-spl.elf) + + export CRYPTOGRAPHY_OPENSSL_NO_LEGACY=1 + swiv_build_utility u-boot-spl-swiv.elf spl/u-boot-spl.elf ${QCOM_UBOOT_SPL_SWIV_PLATFORM} + qtestsign -${mbn_header} tz -o u-boot-spl.mbn u-boot-spl-swiv.elf + rm -f u-boot-spl-swiv.elf + fi +} + uboot_deploy_config:append() { - if [ -f ${B}/${builddir}/u-boot.mbn ]; then + if [ "${QCOM_UBOOT_SPL_FIT}" = "1" ]; then + if [ -f ${B}/${builddir}/u-boot-spl.mbn ]; then + install -m 0644 ${B}/${builddir}/u-boot-spl.mbn ${DEPLOYDIR}/u-boot-spl-${type}.mbn + fi + elif [ -f ${B}/${builddir}/u-boot.mbn ]; then install -m 0644 ${B}/${builddir}/u-boot.mbn ${DEPLOYDIR}/u-boot-${type}.mbn fi } From 3fd5468ec4cf7cfd46015b1e1db1b383e319d6ed Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Thu, 13 Aug 2026 22:24:26 +0000 Subject: [PATCH 04/16] u-boot-qcom: verify the FIT signatures in the SPL The SPL only enforces the FIT signatures when built with CONFIG_SPL_FIT_SIGNATURE, which qcom_lemans_spl_defconfig does not set, so the key uboot-sign embeds into its device tree is carried unused. Add the fragment that turns verification on, pulled in exactly when the FIT is signed. It has to enable CONFIG_RSA as well: SPL_FIT_SIGNATURE only implies SPL_RSA, which is hidden behind "if RSA" in lib/rsa/Kconfig, so on its own it yields an SPL with no algorithm for rsa2048. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ricardo Salveti --- recipes-bsp/u-boot/files/spl-fit-signature.cfg | 3 +++ recipes-bsp/u-boot/u-boot-qcom_git.bb | 1 + 2 files changed, 4 insertions(+) create mode 100644 recipes-bsp/u-boot/files/spl-fit-signature.cfg diff --git a/recipes-bsp/u-boot/files/spl-fit-signature.cfg b/recipes-bsp/u-boot/files/spl-fit-signature.cfg new file mode 100644 index 000000000..a9b696a0e --- /dev/null +++ b/recipes-bsp/u-boot/files/spl-fit-signature.cfg @@ -0,0 +1,3 @@ +CONFIG_SPL_FIT_SIGNATURE=y +CONFIG_RSA=y +CONFIG_SPL_RSA=y diff --git a/recipes-bsp/u-boot/u-boot-qcom_git.bb b/recipes-bsp/u-boot/u-boot-qcom_git.bb index 924372103..b82628971 100644 --- a/recipes-bsp/u-boot/u-boot-qcom_git.bb +++ b/recipes-bsp/u-boot/u-boot-qcom_git.bb @@ -24,6 +24,7 @@ SRC_URI += " \ file://efi-rt-volatile-store.cfg \ ${@bb.utils.contains('MACHINE_FEATURES', 'optee', 'file://tfa-optee.cfg', '', d)} \ ${@bb.utils.contains('MACHINE_FEATURES', 'kvm', 'file://gunyah-exit.cfg', '', d)} \ + ${@bb.utils.contains('SPL_SIGN_ENABLE', '1', 'file://spl-fit-signature.cfg', '', d)} \ " python __anonymous() { From 7afc211378561b59cfb4617c8d59777419958790 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Thu, 13 Aug 2026 21:12:42 +0000 Subject: [PATCH 05/16] image_types_qcom: flash the boot images of the SPL FIT flow With the flow enabled the signed FIT goes to the uefi partition in place of the FIP, and the signed SPL replaces the TZ image. Guarded by QCOM_UBOOT_SPL_FIT, which no machine enables yet. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ricardo Salveti --- classes-recipe/image_types_qcom.bbclass | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/classes-recipe/image_types_qcom.bbclass b/classes-recipe/image_types_qcom.bbclass index 7e1e69f51..d48ace4d4 100644 --- a/classes-recipe/image_types_qcom.bbclass +++ b/classes-recipe/image_types_qcom.bbclass @@ -10,6 +10,10 @@ QCOM_CDT_FIRMWARE ?= "" PREFERRED_PROVIDER_virtual/qcom-capsule-firmware ?= "" QCOM_CAPSULE_FIRMWARE ?= "${PREFERRED_PROVIDER_virtual/qcom-capsule-firmware}" +QCOM_UBOOT_SPL_FIT ?= "0" +QCOM_UBOOT_SPL_IMAGE ?= "u-boot-spl-${UBOOT_CONFIG_DEFAULT}.mbn" +QCOM_UBOOT_FIT_IMAGE ?= "u-boot-fitImage" + QCOM_ESP_IMAGE ?= "${@bb.utils.contains("MACHINE_FEATURES", "efi", "esp-qcom-image", "", d)}" QCOM_ESP_FILE ?= "${@'${DEPLOY_DIR_IMAGE}/${QCOM_ESP_IMAGE}-${MACHINE}${IMAGE_NAME_SUFFIX}.vfat' if d.getVar('QCOM_ESP_IMAGE') else ''}" @@ -130,7 +134,14 @@ create_qcomflash_pkg() { bootloader_provider='${PREFERRED_PROVIDER_virtual/bootloader}' case "$bootloader_provider" in u-boot*) - bootloader_bin="${DEPLOY_DIR_IMAGE}/u-boot-${UBOOT_CONFIG_DEFAULT}.mbn" + if [ "${QCOM_UBOOT_SPL_FIT}" = "1" ]; then + bootloader_bin="${DEPLOY_DIR_IMAGE}/${QCOM_UBOOT_FIT_IMAGE}" + if [ -f "${DEPLOY_DIR_IMAGE}/${QCOM_UBOOT_SPL_IMAGE}" ]; then + install -m 0644 "${DEPLOY_DIR_IMAGE}/${QCOM_UBOOT_SPL_IMAGE}" tz.mbn + fi + else + bootloader_bin="${DEPLOY_DIR_IMAGE}/u-boot-${UBOOT_CONFIG_DEFAULT}.mbn" + fi ;; esac if [ -f "${bootloader_bin}" ]; then From 9a1f3e2d80f8df3f7d97d4f3573bbdb075b364fb Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Thu, 13 Aug 2026 21:12:42 +0000 Subject: [PATCH 06/16] trusted-firmware-a-qcom: build only bl31 for the SPL FIT flow In the SPL FIT flow the u-boot recipe assembles BL31, OP-TEE and U-Boot proper into a FIT, so TF-A only has to provide bl31.bin. The dependency on u-boot-qcom, which exists to pull u-boot.bin into the FIP, then has to go along with the FIP itself, or the two recipes depend on each other. Without a FIP there is nothing left for do_install to wrap and sign either. Defaults are unchanged for machines that do not set QCOM_UBOOT_SPL_FIT. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ricardo Salveti --- .../trusted-firmware-a-qcom.inc | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/dynamic-layers/meta-arm/recipes-bsp/trusted-firmware-a/trusted-firmware-a-qcom.inc b/dynamic-layers/meta-arm/recipes-bsp/trusted-firmware-a/trusted-firmware-a-qcom.inc index 9c7a968f7..58b695407 100644 --- a/dynamic-layers/meta-arm/recipes-bsp/trusted-firmware-a/trusted-firmware-a-qcom.inc +++ b/dynamic-layers/meta-arm/recipes-bsp/trusted-firmware-a/trusted-firmware-a-qcom.inc @@ -1,6 +1,11 @@ require recipes-bsp/trusted-firmware-a/trusted-firmware-a.inc -DEPENDS += "qtestsign-native u-boot-qcom" +DEPENDS += "qtestsign-native" + +# u-boot-qcom is only needed to pull u-boot.bin into the FIP. The SPL FIT flow +# builds no FIP, and u-boot-qcom depends on this recipe for bl31.bin, so keeping +# the dependency both ways would make bitbake reject the task graph. +DEPENDS += "${@bb.utils.contains('QCOM_UBOOT_SPL_FIT', '1', '', 'u-boot-qcom', d)}" PV = "2.15.0-qcom+git" @@ -18,7 +23,7 @@ python () { bb.fatal('FIP_ELF_ADDR must be set by the device recipe') } -TFA_BUILD_TARGET = "bl2 bl31 fip" +TFA_BUILD_TARGET = "${@bb.utils.contains('QCOM_UBOOT_SPL_FIT', '1', 'bl31', 'bl2 bl31 fip', d)}" TFA_SPD = "opteed" EXTRA_OEMAKE:append = " \ @@ -26,15 +31,18 @@ EXTRA_OEMAKE:append = " \ BL33=${DEPLOY_DIR_IMAGE}/u-boot.bin \ " -do_compile[depends] += " u-boot-qcom:do_deploy" +do_compile[depends] += "${@bb.utils.contains('QCOM_UBOOT_SPL_FIT', '1', '', 'u-boot-qcom:do_deploy', d)}" do_install:append() { - export CRYPTOGRAPHY_OPENSSL_NO_LEGACY=1 + # Nothing to wrap and sign without a FIP. + if [ "${QCOM_UBOOT_SPL_FIT}" != "1" ]; then + export CRYPTOGRAPHY_OPENSSL_NO_LEGACY=1 - ${OBJCOPY} -I binary -B aarch64 -O elf64-littleaarch64 ${D}${FIRMWARE_DIR}/fip.bin ${D}${FIRMWARE_DIR}/fip.o - ${LD} ${D}${FIRMWARE_DIR}/fip.o -o ${D}${FIRMWARE_DIR}/fip_unsigned.elf -EL -T ${S}/tools/qti/fip-elf.lds --defsym=ELFENTRY=${FIP_ELF_ADDR} -Ttext=${FIP_ELF_ADDR} - rm -f ${D}${FIRMWARE_DIR}/fip.o + ${OBJCOPY} -I binary -B aarch64 -O elf64-littleaarch64 ${D}${FIRMWARE_DIR}/fip.bin ${D}${FIRMWARE_DIR}/fip.o + ${LD} ${D}${FIRMWARE_DIR}/fip.o -o ${D}${FIRMWARE_DIR}/fip_unsigned.elf -EL -T ${S}/tools/qti/fip-elf.lds --defsym=ELFENTRY=${FIP_ELF_ADDR} -Ttext=${FIP_ELF_ADDR} + rm -f ${D}${FIRMWARE_DIR}/fip.o - qtestsign -v6 aboot -o ${D}${FIRMWARE_DIR}/fip.elf ${D}${FIRMWARE_DIR}/fip_unsigned.elf - rm -f ${D}${FIRMWARE_DIR}/fip_unsigned.elf + qtestsign -v6 aboot -o ${D}${FIRMWARE_DIR}/fip.elf ${D}${FIRMWARE_DIR}/fip_unsigned.elf + rm -f ${D}${FIRMWARE_DIR}/fip_unsigned.elf + fi } From 87de8bd3afa6d4dcf00cc2ee2420721f2022eed2 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Thu, 13 Aug 2026 22:45:09 +0000 Subject: [PATCH 07/16] conf: add the lemans SPL U-Boot configuration qcom_lemans_spl_defconfig builds a U-Boot SPL next to U-Boot proper. It is a sibling of qcom_lemans_defconfig rather than an extension of it, so it needs an entry of its own: U-Boot proper is carried inside a FIT and placed by the SPL, so the configuration neither pins the load address the flashed variant uses nor builds the ELF that gets signed for the uefi partition. That also makes it unusable on its own, so it is left out of the qcom-armv8a catchall. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ricardo Salveti --- conf/machine/include/qcom-u-boot-common.inc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/conf/machine/include/qcom-u-boot-common.inc b/conf/machine/include/qcom-u-boot-common.inc index fa83dcb62..44e664978 100644 --- a/conf/machine/include/qcom-u-boot-common.inc +++ b/conf/machine/include/qcom-u-boot-common.inc @@ -12,6 +12,7 @@ UBOOT_INITIAL_ENV = "" UBOOT_CONFIG[iq-615-evk] = "qcom_qcs615_defconfig" UBOOT_CONFIG[iq-8275-evk] = "qcom_qcs8300_defconfig" UBOOT_CONFIG[iq-9075-evk] = "qcom_lemans_defconfig" +UBOOT_CONFIG[iq-9075-evk-spl] = "qcom_lemans_spl_defconfig" UBOOT_CONFIG[qcs9100-ride-sx] = "qcom_lemans_defconfig" UBOOT_CONFIG[qcs615-ride] = "qcom_qcs615_defconfig" UBOOT_CONFIG[qcs6490-rb3gen2] = "qcm6490_defconfig" @@ -22,6 +23,7 @@ UBOOT_CONFIG[shikra-evk] = "qcom_shikra_defconfig" BOARD_MBN_HEADER[iq-615-evk] = "v6" BOARD_MBN_HEADER[iq-8275-evk] = "v6" BOARD_MBN_HEADER[iq-9075-evk] = "v6" +BOARD_MBN_HEADER[iq-9075-evk-spl] = "v6" BOARD_MBN_HEADER[qcs9100-ride-sx] = "v6" BOARD_MBN_HEADER[qcs615-ride] = "v6" BOARD_MBN_HEADER[qcs6490-rb3gen2] = "v6" From 735da7a1578311f00f030a9a16d4a0fa76cd14bb Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Thu, 13 Aug 2026 23:08:37 +0000 Subject: [PATCH 08/16] qcom-qcs9100: add the U-Boot SPL FIT memory layout Where the SPL FIT flow places BL31, OP-TEE and U-Boot proper, where the SPL itself is entered, which recipes provide BL31 and OP-TEE and which platform name the SWIV annotation uses all follow from the SoC rather than from the board, so keep them with the SoC configuration. Nothing reads them unless the machine also requires conf/machine/include/qcom-uboot-spl-fit.inc. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ricardo Salveti --- conf/machine/include/qcom-qcs9100.inc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/conf/machine/include/qcom-qcs9100.inc b/conf/machine/include/qcom-qcs9100.inc index aa7ed55a6..28c00b4f0 100644 --- a/conf/machine/include/qcom-qcs9100.inc +++ b/conf/machine/include/qcom-qcs9100.inc @@ -15,3 +15,19 @@ MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS += " \ MACHINE_EXTRA_RRECOMMENDS += " \ packagegroup-qcom-boot-additional \ " + +# Memory layout needed by the SPL FIT boot flow. +QCOM_UBOOT_SPL_ENTRY ?= "0x1c100000" +UBOOT_FIT_ARM_TRUSTED_FIRMWARE_LOADADDRESS ?= "0x1c200000" +UBOOT_FIT_ARM_TRUSTED_FIRMWARE_ENTRYPOINT ?= "0x1c200000" +UBOOT_FIT_TEE_LOADADDRESS ?= "0x1c300000" +UBOOT_FIT_TEE_ENTRYPOINT ?= "0x1c300000" +UBOOT_FIT_UBOOT_LOADADDRESS ?= "0xaf400000" +UBOOT_FIT_UBOOT_ENTRYPOINT ?= "0xaf400000" + +# Recipes providing BL31 and OP-TEE for the FIT. +QCOM_UBOOT_SPL_FIT_ATF ?= "trusted-firmware-a-qcom-lemans-evk" +QCOM_UBOOT_SPL_FIT_TEE ?= "optee-os-qcom-lemans" + +# Platform name for the SWIV annotation of the SPL ELF. +QCOM_UBOOT_SPL_SWIV_PLATFORM ?= "lemans" From 4435ebf117566cf8a23f6015e65893193b323f21 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Thu, 13 Aug 2026 23:08:37 +0000 Subject: [PATCH 09/16] conf: add the U-Boot SPL FIT machine include Collect the settings of the SPL FIT boot flow in one include, so that a machine opts in by requiring it and selecting a U-Boot configuration that builds an SPL. The XBL takes the SPL path only with the XBLConfig variant that has the "uboot_spl" flag set, which the boot firmware ships. Signing the FIT is off by default, as the boot images are already authenticated by the Qualcomm chain, where the XBL authenticates the SPL. No machine requires the include yet. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ricardo Salveti --- conf/machine/include/qcom-uboot-spl-fit.inc | 32 +++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 conf/machine/include/qcom-uboot-spl-fit.inc diff --git a/conf/machine/include/qcom-uboot-spl-fit.inc b/conf/machine/include/qcom-uboot-spl-fit.inc new file mode 100644 index 000000000..0ec72b9c2 --- /dev/null +++ b/conf/machine/include/qcom-uboot-spl-fit.inc @@ -0,0 +1,32 @@ +# Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause-Clear +# +# SPL FIT boot flow: the Qualcomm XBL loads the signed U-Boot SPL from tz_a, +# and the SPL loads a FIT holding BL31, OP-TEE and U-Boot proper from uefi_a +# and jumps to BL31. A machine opts in by requiring this file and selecting a +# ${UBOOT_CONFIG} whose defconfig has CONFIG_SPL=y. Load addresses and the +# other SoC specific inputs come from the SoC configuration. + +# Marker the u-boot-qcom and trusted-firmware-a-qcom recipes branch on. +QCOM_UBOOT_SPL_FIT = "1" + +# Assemble the FIT from BL31 and OP-TEE, staged by the u-boot recipe, and +# U-Boot proper. Signing it is off by default (SPL_SIGN_ENABLE), as the boot +# images are already authenticated by the Qualcomm chain; setting it to "1" +# also builds an SPL that enforces the signatures, see spl-fit-signature.cfg. +UBOOT_FITIMAGE_ENABLE = "1" +UBOOT_FIT_ARM_TRUSTED_FIRMWARE = "1" +UBOOT_FIT_TEE = "1" + +# BL31 boots first, and board_fit_config_name_match() in the qcom SPL selects +# the configuration by this description. +UBOOT_FIT_CONF_FIRMWARE = "atf" +UBOOT_FIT_CONF_DESC = "post-ddr" + +# The XBL takes the SPL path only with this XBLConfig variant, which the boot +# firmware ships next to the stock one. +QCOM_XBL_CONFIG = "xbl_config_spl.elf" + +# Wrapped into an ELF and signed as the tz.mbn boot image by the recipe. +SPL_BINARY = "spl/u-boot-spl.bin" From 2d5f2c35bb2a8806f92f8138242dac69a5d2da8e Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Sat, 5 Sep 2026 20:46:22 +0000 Subject: [PATCH 10/16] u-boot-scr-qcom-fit: allow booting the FIT with extra configurations bootm applies overlays when a base configuration is followed by feature configurations. Make that selection configurable, so a machine can have overlays applied before the kernel is booted. Empty keeps the default configuration of the FIT. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ricardo Salveti --- recipes-bsp/u-boot/u-boot-scr-qcom-fit.bb | 7 ++++++- recipes-bsp/u-boot/u-boot-scr-qcom-fit/boot.cmd.in | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/recipes-bsp/u-boot/u-boot-scr-qcom-fit.bb b/recipes-bsp/u-boot/u-boot-scr-qcom-fit.bb index ddb7961d7..56375820e 100644 --- a/recipes-bsp/u-boot/u-boot-scr-qcom-fit.bb +++ b/recipes-bsp/u-boot/u-boot-scr-qcom-fit.bb @@ -19,8 +19,13 @@ S = "${UNPACKDIR}" KERNEL_CMDLINE_EXTRA ?= "" QCOM_FIT_KERNEL_CMDLINE = "root=${QCOM_BOOTIMG_ROOTFS} rw rootwait console=${KERNEL_CONSOLE} ${KERNEL_CMDLINE_EXTRA}" +# Configurations bootm selects, as "#[#...]". Empty boots +# the default configuration of the FIT. +QCOM_FIT_BOOT_CONF ?= "" + do_compile() { - sed -e "s|@KERNEL_CMDLINE@|${QCOM_FIT_KERNEL_CMDLINE}|g" boot.cmd.in > boot.cmd + sed -e "s|@KERNEL_CMDLINE@|${QCOM_FIT_KERNEL_CMDLINE}|g" \ + -e "s|@FIT_CONF@|${QCOM_FIT_BOOT_CONF}|g" boot.cmd.in > boot.cmd mkimage -A ${UBOOT_ARCH} -T script -C none -n "Boot script" -d boot.cmd boot.scr } do_install[noexec] = "1" diff --git a/recipes-bsp/u-boot/u-boot-scr-qcom-fit/boot.cmd.in b/recipes-bsp/u-boot/u-boot-scr-qcom-fit/boot.cmd.in index 8d671226a..64cbb0234 100644 --- a/recipes-bsp/u-boot/u-boot-scr-qcom-fit/boot.cmd.in +++ b/recipes-bsp/u-boot/u-boot-scr-qcom-fit/boot.cmd.in @@ -8,4 +8,4 @@ setenv fdt_high 0x1ffffffff setenv bootargs "@KERNEL_CMDLINE@" load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} /fitImage -bootm ${kernel_addr_r} +bootm ${kernel_addr_r}@FIT_CONF@ From 03c6592a6b0db10c0ff5403e08667c607cad3864 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Sat, 5 Sep 2026 21:55:43 +0000 Subject: [PATCH 11/16] conf: hand the linux-qcom device trees to the kernel FIT image LINUX_QCOM_KERNEL_DEVICETREE holds the device trees that exist only in the linux-qcom kernels, and it is appended to KERNEL_DEVICETREE for those recipes alone, as adding them unconditionally would break a linux-yocto build. The FIT image recipe builds its configurations from KERNEL_DEVICETREE as well, so without the same treatment those device trees are built and deployed but never reach the FIT. Append them there too, keyed on the selected kernel so that a linux-yocto build is unaffected. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ricardo Salveti --- conf/machine/include/qcom-common.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/machine/include/qcom-common.inc b/conf/machine/include/qcom-common.inc index 661c3b123..f19bfd0ae 100644 --- a/conf/machine/include/qcom-common.inc +++ b/conf/machine/include/qcom-common.inc @@ -30,6 +30,7 @@ KERNEL_DEVICETREE:append:pn-linux-qcom = " ${LINUX_QCOM_KERNEL_DEVICETREE}" KERNEL_DEVICETREE:append:pn-linux-qcom-next = " ${LINUX_QCOM_KERNEL_DEVICETREE}" KERNEL_DEVICETREE:append:pn-linux-qcom-rt = " ${LINUX_QCOM_KERNEL_DEVICETREE}" KERNEL_DEVICETREE:append:pn-linux-qcom-next-rt = " ${LINUX_QCOM_KERNEL_DEVICETREE}" +KERNEL_DEVICETREE:append:pn-linux-yocto-fitimage = "${@' ' + (d.getVar('LINUX_QCOM_KERNEL_DEVICETREE') or '') if (d.getVar('PREFERRED_PROVIDER_virtual/kernel') or '').startswith('linux-qcom') else ''}" # Fastboot expects an ext4 image, which needs to be 4096 aligned IMAGE_FSTYPES ?= "ext4.gz" From 33eaa29455c3528978fb63d4f0bacf7aa38162d4 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Sat, 5 Sep 2026 22:46:23 +0000 Subject: [PATCH 12/16] ci: base: carry the SPL BSS padding fix for uboot-sign uboot-sign.bbclass reassembles the SPL as a plain concatenation of the nodtb image and the signed device tree, dropping the padding U-Boot puts between them when BSS is part of the image. The SPL FIT flow needs that padding: without it the device tree lands inside BSS and the SPL finds none, before the console is up. Carry it until the OE-core patch is merged. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ricardo Salveti --- ci/base.yml | 3 + ...he-SPL-BSS-padding-when-reassembling.patch | 67 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 patches/oe-core/0003-uboot-sign-keep-the-SPL-BSS-padding-when-reassembling.patch diff --git a/ci/base.yml b/ci/base.yml index ff5b5c4c6..3cd18e91f 100644 --- a/ci/base.yml +++ b/ci/base.yml @@ -18,6 +18,9 @@ repos: fix-igt-pause: repo: meta-qcom path: patches/oe-core/0001-igt-gpu-tools-fix-build-on-non-x86-platforms.patch + uboot-sign-spl-bss-padding: + repo: meta-qcom + path: patches/oe-core/0003-uboot-sign-keep-the-SPL-BSS-padding-when-reassembling.patch revert-python3-pycairo: repo: meta-qcom path: patches/oe-core/0001-Revert-python3-pycairo-inherit-python3-dir-not-pytho.patch diff --git a/patches/oe-core/0003-uboot-sign-keep-the-SPL-BSS-padding-when-reassembling.patch b/patches/oe-core/0003-uboot-sign-keep-the-SPL-BSS-padding-when-reassembling.patch new file mode 100644 index 000000000..7b5c110bd --- /dev/null +++ b/patches/oe-core/0003-uboot-sign-keep-the-SPL-BSS-padding-when-reassembling.patch @@ -0,0 +1,67 @@ +From f77a45eda09e5326b1ba564fe348d82a06219120 Mon Sep 17 00:00:00 2001 +From: Ricardo Salveti +Date: Thu, 13 Aug 2026 02:38:23 +0000 +Subject: [PATCH] uboot-sign: keep the SPL BSS padding when reassembling the + SPL binary + +concat_spl_dtb() rebuilds the SPL as a plain concatenation of the nodtb +image and the signed device tree. U-Boot only assembles it that way with +SPL_SEPARATE_BSS; otherwise BSS is part of the image and it pads between +the two, so that clearing BSS cannot overwrite the appended device tree. +Platforms loading the SPL as one contiguous image, such as Qualcomm SoCs, +need that layout: without the padding the device tree ends up inside BSS +and spl_early_init() finds none, before the console is up. + +Reassemble at the offset U-Boot used, taken from its own image as +SPL_WITH_DTB_BINARY, and fall back to the current behaviour when it did +not pad. + +AI-Generated: Uses Claude Code + +Signed-off-by: Ricardo Salveti +Upstream-Status: Submitted [https://lists.openembedded.org/g/openembedded-core/message/245194] +--- + meta/classes-recipe/uboot-sign.bbclass | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +diff --git a/meta/classes-recipe/uboot-sign.bbclass b/meta/classes-recipe/uboot-sign.bbclass +index 4da5d4c9f1..0e44f12d0e 100644 +--- a/meta/classes-recipe/uboot-sign.bbclass ++++ b/meta/classes-recipe/uboot-sign.bbclass +@@ -58,6 +58,8 @@ SPL_DTB_SYMLINK ?= "u-boot-spl-${MACHINE}.dtb" + SPL_NODTB_IMAGE ?= "u-boot-spl-nodtb-${MACHINE}-${PV}-${PR}.bin" + SPL_NODTB_BINARY ?= "u-boot-spl-nodtb.bin" + SPL_NODTB_SYMLINK ?= "u-boot-spl-nodtb-${MACHINE}.bin" ++# The SPL image as assembled by U-Boot, before signing. ++SPL_WITH_DTB_BINARY ?= "u-boot-spl-dtb.bin" + + # U-Boot fitImage description + UBOOT_FIT_DESC ?= "U-Boot fitImage for ${DISTRO_NAME}/${PV}/${MACHINE}" +@@ -250,7 +252,23 @@ deploy_dtb() { + + concat_spl_dtb() { + if [ -e "${SPL_DIR}/${SPL_NODTB_BINARY}" ] && [ -e "${SPL_DIR}/${SPL_DTB_BINARY}" ] ; then +- cat ${SPL_DIR}/${SPL_NODTB_BINARY} ${SPL_DIR}/${SPL_DTB_SIGNED} > "${SPL_BINARY}" ++ # U-Boot pads behind BSS before appending the device tree ++ # ($(SPL_BIN)-pad.bin in scripts/Makefile.xpl); keep that offset. ++ nodtb_size=$(stat -Lc %s ${SPL_DIR}/${SPL_NODTB_BINARY}) ++ dtb_offset=${nodtb_size} ++ ++ if [ -e "${SPL_DIR}/${SPL_WITH_DTB_BINARY}" ]; then ++ image_size=$(stat -Lc %s ${SPL_DIR}/${SPL_WITH_DTB_BINARY}) ++ dtb_size=$(stat -Lc %s ${SPL_DIR}/${SPL_DTB_BINARY}) ++ offset=$(expr ${image_size} - ${dtb_size}) ++ if [ ${offset} -gt ${nodtb_size} ]; then ++ dtb_offset=${offset} ++ fi ++ fi ++ ++ cp ${SPL_DIR}/${SPL_NODTB_BINARY} "${SPL_BINARY}" ++ truncate -s ${dtb_offset} "${SPL_BINARY}" ++ cat ${SPL_DIR}/${SPL_DTB_SIGNED} >> "${SPL_BINARY}" + else + bbwarn "Failure while adding public key to spl binary. Verified U-Boot boot won't be available." + fi +-- +2.43.0 + From 59f7b2f9691b9ed85d4afe8e2ccb03a512732488 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Sat, 5 Sep 2026 22:18:12 +0000 Subject: [PATCH 13/16] iq-9075-evk-open-fw-spl: boot via U-Boot SPL and a FIT Add a variant of the open-firmware machine that boots through a U-Boot SPL instead of the TF-A BL2/FIP loader, so that the first stage after the Qualcomm XBL is an open-source loader. It is a machine of its own rather than a change of iq-9075-evk-open-fw, because the two produce different boot images for the same board and both are worth keeping. qcs9100-ride-sx keeps the FIP flow as well: its XBL requires QCOM-signed boot images and resets right after handing off to the SPL. The XBL hands off without loading the hypervisor here, so Linux owns EL2. The base device tree describes the SMMU stream IDs for the case where the hypervisor set them up, and without the EL2 overlay the GPU fails to initialise and the DSP remoteprocs and the video codec fail to load their firmware, so bootm applies it on top of the base DTB. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ricardo Salveti --- conf/machine/iq-9075-evk-open-fw-spl.conf | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 conf/machine/iq-9075-evk-open-fw-spl.conf diff --git a/conf/machine/iq-9075-evk-open-fw-spl.conf b/conf/machine/iq-9075-evk-open-fw-spl.conf new file mode 100644 index 000000000..dbe674dc4 --- /dev/null +++ b/conf/machine/iq-9075-evk-open-fw-spl.conf @@ -0,0 +1,13 @@ +#@TYPE: Machine +#@NAME: Qualcomm IQ-9075 Evaluation Kit (EVK) with open boot firmware and U-Boot SPL +#@DESCRIPTION: Machine configuration for Qualcomm IQ-9075 Evaluation Kit (EVK) +# booting through a U-Boot SPL instead of the TF-A BL2/FIP loader + +require conf/machine/iq-9075-evk-open-fw.conf + +# Build U-Boot with an SPL and enable the flow that packs BL31 and OP-TEE into +# the FIT the SPL loads. +UBOOT_CONFIG = "iq-9075-evk-spl" +require conf/machine/include/qcom-uboot-spl-fit.inc + +QCOM_FIT_BOOT_CONF ?= "#conf-lemans-evk.dtb#conf-lemans-el2.dtbo" From 2761b86c77e53718b9ff2f13f07f0ef127b16c87 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Tue, 8 Sep 2026 21:15:00 +0000 Subject: [PATCH 14/16] ci: add the iq-9075-evk-open-fw-spl kas fragment Build the SPL variant next to the FIP based iq-9075-evk-open-fw, so that both boot flows keep building. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ricardo Salveti --- ci/iq-9075-evk-open-fw-spl.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 ci/iq-9075-evk-open-fw-spl.yml diff --git a/ci/iq-9075-evk-open-fw-spl.yml b/ci/iq-9075-evk-open-fw-spl.yml new file mode 100644 index 000000000..3b33ec494 --- /dev/null +++ b/ci/iq-9075-evk-open-fw-spl.yml @@ -0,0 +1,9 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/siemens/kas/master/kas/schema-kas.json + +header: + version: 14 + includes: + - ci/base.yml + - ci/meta-arm.yml + +machine: iq-9075-evk-open-fw-spl From 10ec74ef814ee236febf6194c3e5699fb2abd7c0 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Fri, 11 Sep 2026 21:45:21 +0000 Subject: [PATCH 15/16] packagegroup-machine-essential: add the TEE backed PAS driver qcom_pas_tee authenticates the DSP images through OP-TEE instead of the proprietary TrustZone, which is what the open firmware boot flows need. It sits next to qcom_q6v5_pas, so list it with the other generic qcom modules. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Ricardo Salveti --- recipes-bsp/packagegroups/packagegroup-machine-essential.bb | 1 + 1 file changed, 1 insertion(+) diff --git a/recipes-bsp/packagegroups/packagegroup-machine-essential.bb b/recipes-bsp/packagegroups/packagegroup-machine-essential.bb index cacc9aa77..f940980d2 100644 --- a/recipes-bsp/packagegroups/packagegroup-machine-essential.bb +++ b/recipes-bsp/packagegroups/packagegroup-machine-essential.bb @@ -62,6 +62,7 @@ RRECOMMENDS:${PN}-qcom-generic += " \ kernel-module-qcom-battmgr \ kernel-module-qcom-camss \ kernel-module-qcom-iris \ + kernel-module-qcom-pas-tee \ kernel-module-qcom-pd-mapper \ kernel-module-qcom-pmic-tcpm \ kernel-module-qcom-pon \ From 918799c13a6fe59a16c5aad3498a5d436eab9fc0 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Tue, 8 Sep 2026 21:15:00 +0000 Subject: [PATCH 16/16] ci: build iq-9075-evk-open-fw-spl with a kernel FIT image Add the CI row for the combination this variant exists for: a U-Boot SPL loading U-Boot proper, which in turn boots a U-Boot kernel FIT image. The default build keeps the regular kernel image. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ricardo Salveti --- .github/workflows/build-yocto.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/build-yocto.yml b/.github/workflows/build-yocto.yml index bb5881285..61b4c3dfe 100644 --- a/.github/workflows/build-yocto.yml +++ b/.github/workflows/build-yocto.yml @@ -442,6 +442,14 @@ jobs: type: default dirname: "" yamlfile: "" + - machine: iq-9075-evk-open-fw-spl + distro: + name: qcom-distro-kvm + yamlfile: ':ci/qcom-distro-kvm.yml' + kernel: + type: kernel-fit + dirname: "_kernel-fit" + yamlfile: ":ci/kernel-fit-image.yml" - machine: rb3gen2-core-kit distro: name: nodistro