From dad9124e62ec1b112923bb324c211b977611b66a Mon Sep 17 00:00:00 2001 From: Soumya Tripathy Date: Mon, 19 Oct 2026 18:20:59 +0530 Subject: [PATCH 01/10] UPSTREAM: modules: tfa: Add TFA_PLATFORM Kconfig and refactor FIP default commit 823997def97139854f9d16e01e2b4923cd3659bf upstream. Add CONFIG_TFA_PLATFORM as a generic string config for the TF-A PLAT parameter. This allows platforms to specify their TF-A platform via Kconfig instead of requiring board.cmake. Add CONFIG_TFA_BUILD_FIP=y to ARM FVP board defconfigs. Signed-off-by: Soumya Tripathy --- .../fvp_base_revc_2xaem_v8a_smp_ns_defconfig | 1 + .../fvp_base_revc_2xaem_v9a_smp_ns_defconfig | 1 + doc/releases/release-notes-4.5.rst | 7 +++++++ modules/trusted-firmware-a/Kconfig | 20 +++++++++++++++++++ 4 files changed, 29 insertions(+) diff --git a/boards/arm/fvp_base_revc_2xaem/fvp_base_revc_2xaem_v8a_smp_ns_defconfig b/boards/arm/fvp_base_revc_2xaem/fvp_base_revc_2xaem_v8a_smp_ns_defconfig index 31973c6ff16d..c4fd409664d8 100644 --- a/boards/arm/fvp_base_revc_2xaem/fvp_base_revc_2xaem_v8a_smp_ns_defconfig +++ b/boards/arm/fvp_base_revc_2xaem/fvp_base_revc_2xaem_v8a_smp_ns_defconfig @@ -20,6 +20,7 @@ CONFIG_UART_CONSOLE=y # Enable TFA CONFIG_ARMV8_A_NS=y CONFIG_BUILD_WITH_TFA=y +CONFIG_TFA_BUILD_FIP=y # Enable SMP CONFIG_SMP=y diff --git a/boards/arm/fvp_base_revc_2xaem/fvp_base_revc_2xaem_v9a_smp_ns_defconfig b/boards/arm/fvp_base_revc_2xaem/fvp_base_revc_2xaem_v9a_smp_ns_defconfig index 37aadc6d399b..57c032590e2e 100644 --- a/boards/arm/fvp_base_revc_2xaem/fvp_base_revc_2xaem_v9a_smp_ns_defconfig +++ b/boards/arm/fvp_base_revc_2xaem/fvp_base_revc_2xaem_v9a_smp_ns_defconfig @@ -20,6 +20,7 @@ CONFIG_UART_CONSOLE=y # Enable TFA CONFIG_ARMV8_A_NS=y CONFIG_BUILD_WITH_TFA=y +CONFIG_TFA_BUILD_FIP=y # Enable SMP CONFIG_SMP=y diff --git a/doc/releases/release-notes-4.5.rst b/doc/releases/release-notes-4.5.rst index 2c199cff0c90..351ae994be87 100644 --- a/doc/releases/release-notes-4.5.rst +++ b/doc/releases/release-notes-4.5.rst @@ -202,3 +202,10 @@ Other notable changes .. Any more descriptive subsystem or driver changes. Do you really want to write a paragraph or is it enough to link to the api/driver/Kconfig/board page above? + +Trusted Firmware-A +****************** + +* ``CONFIG_TFA_BUILD_FIP`` is introduced to configure FIP (Firmware Image Package) generation. + FIP generation is by default disabled, but can be enabled by setting ``CONFIG_TFA_BUILD_FIP=y`` + in ``prj.conf`` or for custom boards, in the board's ``_defconfig`` file. diff --git a/modules/trusted-firmware-a/Kconfig b/modules/trusted-firmware-a/Kconfig index f99366128dab..aec8498eb071 100644 --- a/modules/trusted-firmware-a/Kconfig +++ b/modules/trusted-firmware-a/Kconfig @@ -19,4 +19,24 @@ config TFA_MAKE_BUILD_TYPE_DEBUG help When enabled, the build type of TF-A would be debug. +config TFA_BUILD_FIP + bool "Generate FIP (Firmware Image Package)" + help + Generate ARM Firmware Image Package (FIP) containing all boot stages. + Platforms using FIP should enable this explicitly in their board + defconfig. + +config TFA_FIP_USE_BL33_ZEPHYR + bool "Include Zephyr as BL33 for TF-A FIP generation" + depends on TFA_BUILD_FIP + default y + help + Pass Zephyr binary as BL33 for TF-A FIP build. + +config TFA_PLATFORM + string + help + Platform name for TF-A build system (PLAT= parameter). + Boards should set this in their Kconfig.defconfig file. + endif # BUILD_WITH_TFA From e0421dd2440bbfd4d38c59ffc8baf8229ca04186 Mon Sep 17 00:00:00 2001 From: Soumya Tripathy Date: Mon, 19 Oct 2026 18:21:00 +0530 Subject: [PATCH 02/10] UPSTREAM: modules: tfa: Introduce tfa as standalone build apart from pos... commit d30a3f286b349b039209581a42745d94921ddd11 upstream. Refactor TF-A CMake build logic add support for FIP image generation as post build along with standalone build. Certain platform like TI SoCs (AM62L,AM62x,AM64x) use TF-A build artefacts as prerequsite for boot image generation. Signed-off-by: Soumya Tripathy --- modules/trusted-firmware-a/CMakeLists.txt | 75 +++++++++++++++++------ 1 file changed, 55 insertions(+), 20 deletions(-) diff --git a/modules/trusted-firmware-a/CMakeLists.txt b/modules/trusted-firmware-a/CMakeLists.txt index 1f97d6f99e6c..7820a5944c50 100644 --- a/modules/trusted-firmware-a/CMakeLists.txt +++ b/modules/trusted-firmware-a/CMakeLists.txt @@ -11,17 +11,6 @@ if(CONFIG_BUILD_WITH_TFA) set(tfa_image_info MAP "name: tfa, source-dir: ${ZEPHYR_TRUSTED_FIRMWARE_A_MODULE_DIR}") build_info(images VALUE ${tfa_image_info}) - ExternalProject_Add( - tfa - SOURCE_DIR ${ZEPHYR_TRUSTED_FIRMWARE_A_MODULE_DIR} - BINARY_DIR ${TFA_BINARY_DIR} - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - BUILD_ALWAYS True - USES_TERMINAL_BUILD True - ) - if(CONFIG_TFA_MAKE_BUILD_TYPE_DEBUG) set(TFA_BUILD_DEBUG "1") else() @@ -40,14 +29,60 @@ if(CONFIG_BUILD_WITH_TFA) set(TFA_EXTRA_ARGS "") endif() - set_property(GLOBAL APPEND PROPERTY extra_post_build_commands - COMMAND make -C ${ZEPHYR_TRUSTED_FIRMWARE_A_MODULE_DIR} - DEBUG=${TFA_BUILD_DEBUG} - CROSS_COMPILE=${CROSS_COMPILE} - BUILD_BASE=${TFA_BINARY_DIR} PLAT=${TFA_PLAT} - BL33=${CMAKE_BINARY_DIR}/zephyr/${KERNEL_BIN_NAME} - ${TFA_AARCH32_REGS} - ${TFA_EXTRA_ARGS} - all fip + if(NOT DEFINED TFA_PLAT) + set(TFA_PLAT "${CONFIG_TFA_PLATFORM}") + endif() + + find_program(MAKE_EXECUTABLE NAMES make REQUIRED) + + if(CMAKE_GENERATOR STREQUAL "Unix Makefiles") + set(MAKE_COMMAND "$(MAKE)") + else() + set(MAKE_COMMAND ${MAKE_EXECUTABLE}) + endif() + + # Build base command + set(TFA_BUILD_CMD_COMMON + ${MAKE_COMMAND} -C ${ZEPHYR_TRUSTED_FIRMWARE_A_MODULE_DIR} + DEBUG=${TFA_BUILD_DEBUG} + CROSS_COMPILE=${CROSS_COMPILE} + BUILD_BASE=${TFA_BINARY_DIR} + PLAT=${TFA_PLAT} + ${TFA_AARCH32_REGS} + ${TFA_EXTRA_ARGS} ) + + set(TFA_BUILD_CMD "") + set(TFA_POST_BUILD_MAKE_ARGS "") + + if(CONFIG_TFA_BUILD_FIP) + set(TFA_BUILD_CMD ${CMAKE_COMMAND} -E true) + if(CONFIG_TFA_FIP_USE_BL33_ZEPHYR) + list(APPEND TFA_POST_BUILD_MAKE_ARGS + BL33=${CMAKE_BINARY_DIR}/zephyr/${KERNEL_BIN_NAME} + ) + endif() + + list(APPEND TFA_POST_BUILD_MAKE_ARGS all fip) + else() + set(TFA_BUILD_CMD ${TFA_BUILD_CMD_COMMON} all) + endif() + + ExternalProject_Add( + tfa + SOURCE_DIR ${ZEPHYR_TRUSTED_FIRMWARE_A_MODULE_DIR} + BINARY_DIR ${TFA_BINARY_DIR} + CONFIGURE_COMMAND "" + BUILD_COMMAND ${TFA_BUILD_CMD} + INSTALL_COMMAND "" + BUILD_ALWAYS True + USES_TERMINAL_BUILD True + ) + + if(NOT "${TFA_POST_BUILD_MAKE_ARGS}" STREQUAL "") + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${TFA_BUILD_CMD_COMMON} + ${TFA_POST_BUILD_MAKE_ARGS} + ) + endif() endif() From 6c25871dcc939477374502c6fba0d5555cc76a8f Mon Sep 17 00:00:00 2001 From: Soumya Tripathy Date: Mon, 19 Oct 2026 19:10:31 +0530 Subject: [PATCH 03/10] UPSTREAM-PEND: soc: ti: k3: Add boot image generation scripts PR: 106763 Add Python scripts for generating TI K3 boot images: - rom_image_gen.py: Generates ROM-bootable X.509 signed images (tiboot3.bin and tispl.bin) from SPL/BL1, TIFS, board config, and application binaries. - ti_board_config.py: Converts YAML board configuration files (board-cfg, sec-cfg, pm-cfg, rm-cfg) to binary format for TI System Firmware (SYSFW). These scripts enable generation of bootable images for TI K3 SoC family. Signed-off-by: Soumya Tripathy --- soc/ti/k3/scripts/rom_image_gen.py | 669 +++++++++++++++++++++++++++ soc/ti/k3/scripts/ti_board_config.py | 369 +++++++++++++++ 2 files changed, 1038 insertions(+) create mode 100755 soc/ti/k3/scripts/rom_image_gen.py create mode 100755 soc/ti/k3/scripts/ti_board_config.py diff --git a/soc/ti/k3/scripts/rom_image_gen.py b/soc/ti/k3/scripts/rom_image_gen.py new file mode 100755 index 000000000000..4d1d5e6cff38 --- /dev/null +++ b/soc/ti/k3/scripts/rom_image_gen.py @@ -0,0 +1,669 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2026 Texas Instruments Incorporated + +"""Script to add x509 certificate TI ROM bootable images.""" + +import argparse +import os +import subprocess +import sys +from abc import ABC, abstractmethod +from re import sub +from typing import ClassVar + + +def _safe_output_path(path: str, base_dir: str) -> str: + """Validate output path against a trusted base directory.""" + canonical = os.path.realpath(path) + base = os.path.realpath(base_dir) + os.sep + if not canonical.startswith(base): + raise ValueError( + f"Output path {path!r} resolves to {canonical!r}, " + f"which is outside the build directory {base_dir!r}" + ) + return canonical + + +class SHA: + """SHA algorithm constants and utilities.""" + + SHA256 = "sha256" + SHA384 = "sha384" + SHA512 = "sha512" + SHA224 = "sha224" + + OIDS: ClassVar[dict[str, str]] = { + SHA256: "2.16.840.1.101.3.4.2.1", + SHA384: "2.16.840.1.101.3.4.2.2", + SHA512: "2.16.840.1.101.3.4.2.3", + SHA224: "2.16.840.1.101.3.4.2.4", + } + + @staticmethod + def calculate(file_path: str, sha_type: str = SHA512) -> str: + """Calculate SHA hash of a file.""" + if sha_type not in SHA.OIDS: + raise ValueError(f"Unsupported SHA type: {sha_type!r}") + # Using shell=False for security - pass command as list + sha_val = subprocess.check_output( + ["openssl", "dgst", f"-{sha_type}", "-hex", file_path], + stderr=subprocess.STDOUT, + ).decode() + return sub(r"^.*= ", "", sha_val).strip() + + +class DebugType: + """Debug type constants.""" + + DBG_PERM_DISABLE = "0" + DBG_SOC_DEFAULT = "1" + DBG_PUBLIC_ENABLE = "2" + DBG_FULL_ENABLE = "4" + + VALID_TYPES: ClassVar[dict[str, str]] = { + "DBG_PERM_DISABLE": DBG_PERM_DISABLE, + "DBG_SOC_DEFAULT": DBG_SOC_DEFAULT, + "DBG_PUBLIC_ENABLE": DBG_PUBLIC_ENABLE, + "DBG_FULL_ENABLE": DBG_FULL_ENABLE, + } + + +class X509Component(ABC): + """Base class for X509 certificate components.""" + + # Component type constants + COMP_TYPE_SPL = 1 + COMP_TYPE_SYSFW = 2 + COMP_TYPE_INNER_CERT = 3 + COMP_TYPE_APPLICATION = 17 # Also used for spldata in split architecture + COMP_TYPE_BOARDCFG = 18 + + def __init__( + self, + comp_type: int, + boot_core: int, + binary_path: str, + load_addr: str, + comp_opts: int = 0, + section_name: str | None = None, + ) -> None: + """Initialize X509 component. + + Args: + comp_type: Component type identifier + boot_core: Boot core ID + binary_path: Path to binary file + load_addr: Load address (hex string with 0x prefix) + comp_opts: Component options + section_name: Certificate section name (derived from class name if None) + """ + self.comp_type = comp_type + self.boot_core = boot_core + self.binary_path = os.path.realpath(binary_path) + self.load_addr = load_addr + self.comp_opts = comp_opts + self.section_name = ( + section_name + or self.__class__.__name__.replace( + "Component", + "", + ).lower() + ) + + def validate(self) -> None: + """Validate that the binary file exists.""" + if not os.path.exists(self.binary_path): + msg = f"Binary file not found: {self.binary_path}" + raise FileNotFoundError(msg) + + def get_size(self) -> int: + """Get size of the binary file.""" + return os.path.getsize(self.binary_path) + + def get_sha(self, sha_type: str = SHA.SHA512) -> str: + """Calculate SHA hash of the binary.""" + return SHA.calculate(self.binary_path, sha_type) + + def get_binary_data(self) -> bytes: + """Read binary data.""" + with open(self.binary_path, "rb") as f: + return f.read() + + @abstractmethod + def get_cert_extension_ref(self) -> str: + """Return the extension reference line for ext_boot_info.""" + + def get_cert_section(self, sha_type: str = SHA.SHA512) -> str: + """Generate the certificate section.""" + return f""" +[ {self.section_name} ] +compType = INTEGER:{self.comp_type} +bootCore = INTEGER:{self.boot_core} +compOpts = INTEGER:{self.comp_opts} +destAddr = FORMAT:HEX,OCT:{int(self.load_addr, 16):08X} +compSize = INTEGER:{self.get_size()} +shaType = OID:{SHA.OIDS[sha_type]} +shaValue = FORMAT:HEX,OCT:{self.get_sha(sha_type)} +""" + + +class SPLComponent(X509Component): + """SPL/ATF component (compType=1, bootCore=16).""" + + def __init__( + self, + binary_path: str, + load_addr: str, + dual_stage_boot: bool = False, + ) -> None: + """Initialize SPL component. + + Args: + binary_path: Path to SPL/ATF binary + load_addr: Load address + dual_stage_boot: Enable dual stage boot (sets comp_opts=160) + """ + comp_opts = 160 if dual_stage_boot else 0 + super().__init__( + comp_type=self.COMP_TYPE_SPL, + boot_core=16, + binary_path=binary_path, + load_addr=load_addr, + comp_opts=comp_opts, + section_name="spl", + ) + + def get_cert_extension_ref(self) -> str: + """Return extension reference.""" + return "spl = SEQUENCE:spl" + + +class SYSFWComponent(X509Component): + """SYSFW component (compType=2, bootCore=0).""" + + def __init__(self, binary_path: str, load_addr: str) -> None: + """Initialize SYSFW component.""" + super().__init__( + comp_type=self.COMP_TYPE_SYSFW, + boot_core=0, + binary_path=binary_path, + load_addr=load_addr, + section_name="sysfw", + ) + + def get_cert_extension_ref(self) -> str: + """Return extension reference.""" + return "fw = SEQUENCE:sysfw" + + +class BoardConfigComponent(X509Component): + """Board Config component (compType=18, bootCore=0).""" + + def __init__(self, binary_path: str, load_addr: str) -> None: + """Initialize BoardConfig component.""" + super().__init__( + comp_type=self.COMP_TYPE_BOARDCFG, + boot_core=0, + binary_path=binary_path, + load_addr=load_addr, + section_name="boardcfg", + ) + + def get_cert_extension_ref(self) -> str: + """Return extension reference.""" + return "bd2 = SEQUENCE:boardcfg" + + +class InnerCertComponent(X509Component): + """SYSFW Inner Certificate component (compType=3, bootCore=0).""" + + def __init__(self, binary_path: str) -> None: + """Initialize InnerCert component.""" + super().__init__( + comp_type=self.COMP_TYPE_INNER_CERT, + boot_core=0, + binary_path=binary_path, + load_addr="0x00000000", + section_name="sysfw_inner_cert", + ) + + def get_cert_extension_ref(self) -> str: + """Return extension reference.""" + return "bd1 = SEQUENCE:sysfw_inner_cert" + + +class ApplicationComponent(X509Component): + """Application/SPLData component (compType=17, bootCore=16). + + This component can be used for: + - Application binaries in standard architecture + - SPL data in split architecture + + The section name can be customized (e.g., 'application' or 'spl data'). + """ + + def __init__( + self, + binary_path: str, + load_addr: str, + section_name: str = "application", + ) -> None: + """Initialize Application component.""" + super().__init__( + comp_type=self.COMP_TYPE_APPLICATION, + boot_core=16, + binary_path=binary_path, + load_addr=load_addr, + section_name=section_name, + ) + + def get_cert_extension_ref(self) -> str: + """Return extension reference.""" + return f"bd3 = SEQUENCE:{self.section_name}" + + +class DebugExtension: + """Debug extension for X509 certificate.""" + + def __init__(self, debug_type: str, device_uid: str | None = None) -> None: + """Initialize debug extension. + + Args: + debug_type: Debug type from DebugType constants + device_uid: Device UID (64 hex chars, defaults to all zeros) + """ + if debug_type not in DebugType.VALID_TYPES: + msg = f"Invalid debug type: {debug_type}" + raise ValueError(msg) + self.debug_type = DebugType.VALID_TYPES[debug_type] + self.device_uid = device_uid or "0" * 64 + + def get_extension_ref(self) -> str: + """Return extension reference.""" + return "1.3.6.1.4.1.294.1.8 = ASN1:SEQUENCE:debug" + + def get_section(self) -> str: + """Return debug section.""" + return f""" +[ debug ] +debugUID = FORMAT:HEX,OCT:{self.device_uid} +debugType = INTEGER:{self.debug_type} +coreDbgEn = INTEGER:0 +coreDbgSecEn = INTEGER:0 +""" + + +class CertificateBuilder: + """Build X509 certificate template from components.""" + + # Distinguished name defaults + DEFAULT_DN: ClassVar[dict[str, str]] = { + "C": "US", + "ST": "TX", + "L": "Dallas", + "O": "Texas Instruments Incorporated", + "OU": "Processors", + "CN": "TI Support", + "emailAddress": "support@ti.com", + } + + def __init__(self, sha_type: str = SHA.SHA512, swrv: int = 1) -> None: + """Initialize certificate builder. + + Args: + sha_type: SHA algorithm to use + swrv: Software revision number + """ + self.sha_type = sha_type + self.swrv = swrv + self.components: list[X509Component] = [] + self.debug_ext: DebugExtension | None = None + + def add_component(self, component: X509Component) -> "CertificateBuilder": + """Add a component to the certificate (builder pattern).""" + component.validate() + self.components.append(component) + return self + + def set_debug(self, debug_type: str) -> "CertificateBuilder": + """Set debug extension.""" + self.debug_ext = DebugExtension(debug_type) + return self + + def get_total_size(self) -> int: + """Calculate total size of all components.""" + return sum(comp.get_size() for comp in self.components) + + def get_num_components(self) -> int: + """Get the number of components.""" + return len(self.components) + + def build_template(self) -> str: + """Build the complete X509 certificate template.""" + # Build extension references + ext_refs = [comp.get_cert_extension_ref() for comp in self.components] + + # Build component sections + sections = [comp.get_cert_section(self.sha_type) for comp in self.components] + + # Build debug extension if present + debug_ext_ref = self.debug_ext.get_extension_ref() if self.debug_ext else "" + debug_section = self.debug_ext.get_section() if self.debug_ext else "" + + # Build the template + template = f""" +[ req ] +distinguished_name = req_distinguished_name +x509_extensions = v3_ca +prompt = no +dirstring_type = nobmp + +[ req_distinguished_name ] +C = {self.DEFAULT_DN["C"]} +ST = {self.DEFAULT_DN["ST"]} +L = {self.DEFAULT_DN["L"]} +O = {self.DEFAULT_DN["O"]} +OU = {self.DEFAULT_DN["OU"]} +CN = {self.DEFAULT_DN["CN"]} +emailAddress = {self.DEFAULT_DN["emailAddress"]} + +[ v3_ca ] +basicConstraints = CA:true +1.3.6.1.4.1.294.1.3 = ASN1:SEQUENCE:swrv +1.3.6.1.4.1.294.1.9 = ASN1:SEQUENCE:ext_boot_info +{debug_ext_ref} + +[ swrv ] +swrv = INTEGER:{self.swrv} + +[ ext_boot_info ] +extImgSize = INTEGER:{self.get_total_size()} +numComp = INTEGER:{self.get_num_components()} +{chr(10).join(ext_refs)} +""" + + # Add all component sections + for section in sections: + template += section + + # Add debug section if present + if debug_section: + template += debug_section + + return template + + +class ROMImageGenerator: + """Generate ROM bootable combined image.""" + + def __init__(self, builder: CertificateBuilder) -> None: + """Initialize ROM image generator.""" + self.builder = builder + + def generate(self, key_file: str, output_file: str, build_dir: str) -> None: + """Generate the signed ROM image. + + Args: + key_file: Path to signing key (.pem) + output_file: Path to output ROM image + build_dir: Trusted CMake build directory for output path validation + + Build artifacts created (not deleted): + - .x509.conf - Certificate configuration template + - .x509.der - Signed X.509 certificate in DER format + """ + # Build certificate template + cert_template = self.builder.build_template() + + # Validate output against the trusted build directory + output_file = _safe_output_path(output_file, build_dir) + key_file = os.path.realpath(key_file) + + # Validate all inputs before touching the filesystem + if not key_file.lower().endswith(".pem"): + raise ValueError(f"Key file {key_file!r} must have a .pem extension") + if not os.path.isfile(key_file): + raise FileNotFoundError(f"Key file not found: {key_file}") + if self.builder.sha_type not in SHA.OIDS: + raise ValueError(f"Unsupported SHA type: {self.builder.sha_type!r}") + + # Create certificate artifacts in build directory (same dir as output) + # These are kept as build artifacts, not deleted + cert_config = f"{output_file}.x509.conf" + cert_file = f"{output_file}.x509.der" + + # Write certificate configuration template + with open(cert_config, "w") as f: + f.write(cert_template) + + try: + # Generate certificate using OpenSSL + cmd = [ + "openssl", + "req", + "-new", + "-x509", + "-key", + key_file, + "-nodes", + "-outform", + "DER", + "-out", + cert_file, + "-config", + cert_config, + f"-{self.builder.sha_type}", + ] + + subprocess.check_output(cmd, stderr=subprocess.STDOUT) + + # Concatenate certificate and all component binaries + with open(output_file, "wb") as out_fh: + # Write certificate + with open(cert_file, "rb") as cert_fh: + out_fh.write(cert_fh.read()) + + # Write all components in order + for component in self.builder.components: + out_fh.write(component.get_binary_data()) + + print(f"ROM image generated successfully: {output_file}") + print(f"Certificate template: {cert_config}") + print(f"Certificate (DER): {cert_file}") + print(f"Total components: {self.builder.get_num_components()}") + print(f"Total size: {self.builder.get_total_size()} bytes") + + except subprocess.CalledProcessError as e: + print(f"Error generating certificate: {e.output.decode()}") + raise + + +def main() -> int: + """Main entry point.""" + parser = argparse.ArgumentParser( + description="Creates a ROM-bootable combined image (SPL+SYSFW+BoardCfg)", + allow_abbrev=False, + ) + + # Required arguments + parser.add_argument( + "--spl-bin", + type=str, + required=True, + help="Path to the SPL/BL1 binary or the ATF binary", + ) + parser.add_argument( + "--spl-loadaddr", + type=str, + required=True, + help="Load address at which SPL/BL1 needs to be loaded", + ) + + parser.add_argument( + "--sysfw-bin", + type=str, + required=True, + help="Path to the sysfw binary", + ) + parser.add_argument( + "--sysfw-loadaddr", + type=str, + required=True, + help="Load address at which SYSFW needs to be loaded", + ) + + parser.add_argument( + "--boardcfg-blob", + type=str, + required=True, + help="Path to the boardcfg blob", + ) + parser.add_argument( + "--bcfg-loadaddr", + type=str, + required=True, + help="Load address at which BOARDCFG needs to be loaded", + ) + + parser.add_argument( + "--key", + type=str, + required=True, + help="Path to the signing key (.pem file)", + ) + parser.add_argument( + "--rom-image", + type=str, + required=True, + help="Output file combined ROM image", + ) + parser.add_argument( + "--build-dir", + type=str, + required=True, + help="CMake build directory (trusted base for output path validation)", + ) + + # Optional arguments + parser.add_argument( + "--sysfw-inner-cert", + type=str, + help="Path to the sysfw inner certificate", + ) + + parser.add_argument( + "--application-bin", + type=str, + help="Path to application binary or spldata (for split architecture)", + ) + parser.add_argument( + "--application-loadaddr", + type=str, + help="Load address for application binary or spldata", + ) + parser.add_argument( + "--application-name", + type=str, + default="application", + help=( + 'Section name for application component ' + '(default: "application", use "spl data" for split arch)' + ), + ) + + parser.add_argument( + "--swrv", + type=int, + default=1, + help="Software revision number (default: 1)", + ) + parser.add_argument( + "--debug", + type=str, + choices=list(DebugType.VALID_TYPES.keys()), + help="Debug options for the image", + ) + parser.add_argument( + "--dual-stage-boot", + action="store_true", + help="Enable dual stage ATF integrated ROM boot", + ) + parser.add_argument( + "--sha", + type=str, + default=SHA.SHA512, + choices=[SHA.SHA256, SHA.SHA384, SHA.SHA512, SHA.SHA224], + help="SHA algorithm to use (default: sha512)", + ) + + args = parser.parse_args() + + # Validate application arguments + if (args.application_bin is None) != (args.application_loadaddr is None): + parser.error( + "--application-bin and --application-loadaddr must be used together", + ) + + try: + # Build certificate + builder = CertificateBuilder(sha_type=args.sha, swrv=args.swrv) + + # Add required components (order matters!) + builder.add_component( + SPLComponent( + binary_path=args.spl_bin, + load_addr=args.spl_loadaddr, + dual_stage_boot=args.dual_stage_boot, + ), + ) + + builder.add_component( + SYSFWComponent( + binary_path=args.sysfw_bin, + load_addr=args.sysfw_loadaddr, + ), + ) + + # Add inner cert if present (must come before boardcfg per ROM requirements) + if args.sysfw_inner_cert: + builder.add_component( + InnerCertComponent( + binary_path=args.sysfw_inner_cert, + ), + ) + + builder.add_component( + BoardConfigComponent( + binary_path=args.boardcfg_blob, + load_addr=args.bcfg_loadaddr, + ), + ) + + # Add application/spldata if present + if args.application_bin: + builder.add_component( + ApplicationComponent( + binary_path=args.application_bin, + load_addr=args.application_loadaddr, + section_name=args.application_name, + ), + ) + + # Add debug extension if requested + if args.debug: + builder.set_debug(args.debug) + + # Generate ROM image + generator = ROMImageGenerator(builder) + generator.generate(args.key, args.rom_image, args.build_dir) + + except Exception as e: # noqa: BLE001 + print(f"Error: {e}") + return 1 + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/soc/ti/k3/scripts/ti_board_config.py b/soc/ti/k3/scripts/ti_board_config.py new file mode 100755 index 000000000000..ccdf5999ea47 --- /dev/null +++ b/soc/ti/k3/scripts/ti_board_config.py @@ -0,0 +1,369 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2026 Texas Instruments Incorporated + +"""TI K3 Board Configuration Binary Generator and Blob Creator. + +Converts YAML board configurations to binary format for TI K3 SYSFW. +Supports both single config mode and combined blob mode. +""" + +import argparse +import os +import struct +import sys + +try: + import yaml + from jsonschema import ValidationError, validate +except ImportError as e: + print(f"ERROR: Required Python package missing: {e}", file=sys.stderr) + print("Install: pip install pyyaml jsonschema", file=sys.stderr) + sys.exit(1) + +# Board config type identifiers per TI SYSFW specification +BOARDCFG = 0xB +BOARDCFG_RM = 0xC +BOARDCFG_SEC = 0xD +BOARDCFG_PM = 0xE + +# Descriptor format: type(u16), offset(u16), size(u16), devgrp(u8), reserved(u8) +BOARDCFG_DESC_FMT = ' str: + """Validate output path against a trusted base directory.""" + canonical = os.path.realpath(path) + base = os.path.realpath(base_dir) + os.sep + if not canonical.startswith(base): + raise ValueError( + f"Output path {path!r} resolves to {canonical!r}, " + f"which is outside the build directory {base_dir!r}" + ) + return canonical + + +class TIBoardConfigGenerator: + """Generates TI K3 board configuration binaries from YAML.""" + + def __init__(self, schema_file: str, config_file: str): + self.schema_file = os.path.realpath(schema_file) + self.config_file = os.path.realpath(config_file) + self.schema: dict[str, any] = {} + self.config: dict[str, any] = {} + + def load_files(self) -> None: + """Load and parse YAML schema and config files.""" + try: + with open(self.schema_file) as f: + self.schema = yaml.safe_load(f) + except Exception as e: + print(f"ERROR: Failed to load schema {self.schema_file}: {e}", file=sys.stderr) + sys.exit(1) + + try: + with open(self.config_file) as f: + self.config = yaml.safe_load(f) + except Exception as e: + print(f"ERROR: Failed to load config {self.config_file}: {e}", file=sys.stderr) + sys.exit(1) + + def validate_config(self) -> bool: + """Validate configuration against schema.""" + try: + validate(instance=self.config, schema=self.schema) + return True + except ValidationError as e: + print("ERROR: Configuration validation failed:", file=sys.stderr) + print(f" {e.message}", file=sys.stderr) + if e.path: + print(f" At: {' -> '.join(str(p) for p in e.path)}", file=sys.stderr) + return False + except Exception as e: + print(f"ERROR: Validation error: {e}", file=sys.stderr) + return False + + def _resolve_ref(self, ref: str) -> dict[str, any]: + """Resolve a JSON schema $ref like '#/definitions/u8'.""" + if not ref.startswith("#/"): + raise ValueError(f"Unsupported $ref: {ref}") + + path_parts = ref[2:].split('/') + current = self.schema + + for part in path_parts: + if part in current: + current = current[part] + else: + raise ValueError(f"Cannot resolve $ref: {ref}") + + return current + + def _get_type_size(self, type_def: dict[str, any]) -> int: + """Determine byte size (1, 2, or 4) from type definition.""" + max_val = type_def.get('maximum', 0xFFFFFFFF) + if max_val <= 0xFF: + return 1 # u8 + elif max_val <= 0xFFFF: + return 2 # u16 + else: + return 4 # u32 + + def _serialize_value(self, value: any, type_schema: dict[str, any]) -> bytes: + """Serialize a single integer value to little-endian bytes.""" + if '$ref' in type_schema: + ref_schema = self._resolve_ref(type_schema['$ref']) + size = self._get_type_size(ref_schema) + elif type_schema.get('type') == 'integer': + size = self._get_type_size(type_schema) + else: + raise ValueError(f"Unsupported type schema: {type_schema}") + + if not isinstance(value, int): + raise TypeError(f"Expected int, got {type(value).__name__}") + + return value.to_bytes(size, byteorder='little') + + def _serialize_object(self, obj: dict[str, any], obj_schema: dict[str, any]) -> bytes: + """Serialize an object (dictionary) to bytes depth-first.""" + result = bytearray() + for prop_name, prop_schema in obj_schema.get('properties', {}).items(): + if prop_name in obj: + result += self._serialize_any(obj[prop_name], prop_schema) + return bytes(result) + + def _serialize_array(self, arr: list, arr_schema: dict[str, any]) -> bytes: + """Serialize an array to bytes element-by-element.""" + result = bytearray() + items_schema = arr_schema.get('items', {}) + for item in arr: + result += self._serialize_any(item, items_schema) + return bytes(result) + + def _serialize_any(self, value: any, value_schema: dict[str, any]) -> bytes: + """Serialize any value to bytes based on its schema type.""" + if '$ref' in value_schema: + return self._serialize_value(value, value_schema) + + value_type = value_schema.get('type') + if value_type == 'object': + return self._serialize_object(value, value_schema) + elif value_type == 'array': + return self._serialize_array(value, value_schema) + elif value_type == 'integer': + return self._serialize_value(value, value_schema) + else: + raise ValueError(f"Unsupported type: {value_type}") + + def generate(self) -> bytes: + """Generate board configuration binary from loaded YAML.""" + result = bytearray() + for key in self.config: + if key in self.schema.get('properties', {}): + key_schema = self.schema['properties'][key] + result += self._serialize_any(self.config[key], key_schema) + return bytes(result) + + +def create_combined_blob( + config_binaries: list[tuple[bytes, int, str]], + output_file: str, + sw_rev: int, + devgrp: int, + verbose: bool, + base_dir: str, +) -> None: + """Create combined board config blob from multiple binaries. + + Blob structure follows TI SYSFW specification: + - Header: num_elems (u8) + sw_rev (u8) + - Descriptors: array of (type, offset, size, devgrp, reserved) + - Data: concatenated config binaries + """ + num_elems = len(config_binaries) + header_size = 2 + desc_size = struct.calcsize(BOARDCFG_DESC_FMT) + offset = header_size + (num_elems * desc_size) + + descriptors = bytearray() + config_data = bytearray() + + for binary_data, config_type, _ in config_binaries: + size = len(binary_data) + desc = struct.pack(BOARDCFG_DESC_FMT, config_type, offset, size, devgrp, 0) + descriptors += desc + config_data += binary_data + offset += size + + output_file = _safe_output_path(output_file, base_dir) + try: + with open(output_file, 'wb') as f: + f.write(struct.pack(' None: + """Validate that a file exists, exit with error if not.""" + if not os.path.exists(filepath): + print(f"ERROR: {description} not found: {filepath}", file=sys.stderr) + sys.exit(1) + + +def collect_configs_to_process(args) -> list[tuple[str, int, str]]: + """Collect configuration files to process from arguments.""" + configs = [] + if args.board_cfg: + configs.append((args.board_cfg, BOARDCFG, 'board-cfg')) + if args.sec_cfg: + configs.append((args.sec_cfg, BOARDCFG_SEC, 'sec-cfg')) + if args.pm_cfg: + configs.append((args.pm_cfg, BOARDCFG_PM, 'pm-cfg')) + if args.rm_cfg: + configs.append((args.rm_cfg, BOARDCFG_RM, 'rm-cfg')) + return configs + + +def validate_configs_exist(configs: list[tuple[str, int, str]]) -> None: + """Validate that all config files exist.""" + for yaml_path, _, name in configs: + validate_file_exists(yaml_path, f"{name} file") + + +def convert_config_to_binary(schema_file: str, yaml_path: str, name: str, verbose: bool) -> bytes: + """Convert a single YAML config to binary format.""" + if verbose: + print(f"Converting {name}: {yaml_path}") + + generator = TIBoardConfigGenerator(schema_file, yaml_path) + generator.load_files() + + if not generator.validate_config(): + print(f"ERROR: Validation failed for {name}", file=sys.stderr) + sys.exit(1) + + binary_data = generator.generate() + + if verbose: + print(f" Generated {len(binary_data)} bytes") + + return binary_data + + +def process_single_mode(args) -> None: + """Process single config YAML to binary mode.""" + validate_file_exists(args.config, "Config file") + + generator = TIBoardConfigGenerator(args.schema, args.config) + generator.load_files() + + if not generator.validate_config(): + sys.exit(1) + + binary_data = generator.generate() + + with open(_safe_output_path(args.output, args.build_dir), 'wb') as f: + f.write(binary_data) + + print(f"Generated: {args.output} ({len(binary_data)} bytes)") + + +def process_combined_mode(args) -> None: + """Process multiple YAMLs into combined blob mode.""" + configs_to_process = collect_configs_to_process(args) + validate_configs_exist(configs_to_process) + + config_binaries = [] + for yaml_path, config_type, name in configs_to_process: + binary_data = convert_config_to_binary(args.schema, yaml_path, name, args.verbose) + config_binaries.append((binary_data, config_type, name)) + + create_combined_blob( + config_binaries, args.output, args.sw_rev, args.devgrp, args.verbose, args.build_dir + ) + + +def validate_mode_selection(parser, single_mode: bool, combined_mode: bool) -> None: + """Validate that exactly one mode is selected.""" + if single_mode and combined_mode: + parser.error("Cannot use both single mode (--config) and combined mode") + if not single_mode and not combined_mode: + parser.error("Must specify either --config or at least one --board-cfg/--sec-cfg/etc") + + +def main(): + """Main entry point.""" + parser = argparse.ArgumentParser( + description="TI K3 Board Configuration Binary Generator", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Mode 1: Single Binary + %(prog)s --schema schema.yaml --config board-cfg.yaml --output board-cfg.bin + +Mode 2: Combined Blob (converts YAMLs and creates blob) + # AM62L: board + security + %(prog)s --schema schema.yaml --board-cfg board-cfg.yaml --sec-cfg sec-cfg.yaml -o combined.bin + + # AM62x: all 4 configs + %(prog)s --schema schema.yaml --board-cfg board-cfg.yaml --sec-cfg sec-cfg.yaml \\ + --pm-cfg pm-cfg.yaml --rm-cfg rm-cfg.yaml -o combined.bin + """, + allow_abbrev=False, + ) + + parser.add_argument('--schema', required=True, help='YAML schema file') + parser.add_argument('--config', help='Single config YAML (mode 1)') + parser.add_argument('--board-cfg', help='board-cfg.yaml (mode 2)') + parser.add_argument('--sec-cfg', help='sec-cfg.yaml (mode 2)') + parser.add_argument('--pm-cfg', help='pm-cfg.yaml (mode 2)') + parser.add_argument('--rm-cfg', help='rm-cfg.yaml (mode 2)') + parser.add_argument('--sw-rev', type=int, default=1, help='Software revision (default: 1)') + parser.add_argument('--devgrp', type=int, default=0, help='Device group (default: 0)') + parser.add_argument('-o', '--output', required=True, help='Output binary file') + parser.add_argument( + '--build-dir', + required=True, + help='CMake build directory (trusted base for output path validation)', + ) + parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output') + + args = parser.parse_args() + + validate_file_exists(args.schema, "Schema file") + + single_mode = args.config is not None + combined_mode = any([args.board_cfg, args.sec_cfg, args.pm_cfg, args.rm_cfg]) + + validate_mode_selection(parser, single_mode, combined_mode) + + if single_mode: + process_single_mode(args) + else: + process_combined_mode(args) + + +if __name__ == '__main__': + main() From b9f773b39e165eb09b2164e7e965d778fc29ea5e Mon Sep 17 00:00:00 2001 From: Soumya Tripathy Date: Mon, 19 Oct 2026 19:10:31 +0530 Subject: [PATCH 04/10] UPSTREAM-PEND: soc: ti: k3: Add development signing key PR: 106763 Add TI signing key (custMpk.pem) for generating X.509 certificates for TI K3 boot images. Signed-off-by: Soumya Tripathy --- soc/ti/k3/keys/custMpk.pem | 56 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 soc/ti/k3/keys/custMpk.pem diff --git a/soc/ti/k3/keys/custMpk.pem b/soc/ti/k3/keys/custMpk.pem new file mode 100644 index 000000000000..255a311ff8e9 --- /dev/null +++ b/soc/ti/k3/keys/custMpk.pem @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2026 Texas Instruments Incorporated +# +# TI K3 dummy/testing signing key +# +-----BEGIN RSA PRIVATE KEY----- +MIIJKQIBAAKCAgEAvxSuSdh/ctNrI83rSA5l3CJN8g5PgvbttfLd23yR+m5Z/9X3 +tt4EHYrM0pXZ0eDEwfhQv/9IDJEiUJpMe4vzlgooJrOk2eCpVUEa+z5bJ2y/ysBx +ry9yIu5GASVirT7HBPaxGLYswBJuD+KbPuWmoKgGRQNBF04WH6l01oRO1nmnELgR +qQ6SHyXdf7Hy0bnyaNgzWUuCfXfM0Zz6I7T7WIjyzerVFvIsdS36YsPBCW7gBnDg +tQcJmWLZ1uTnbG3IggdQk/fi2O3RX+PQns+TVNlf3V3ON2DxqxSKBHtlp7p/30VF +fEuhW65OxpQ9jE6H0pQ8pPOf2vzyNnznDa1aQjfxKoHQbqGnZwMeh+0Au3NKaCgx +ooKaowTB6If/RX6qwZ/UOwXHg/0hcf69fzjJFhlSDuYDM40dHsk2HM1OnYIpiM2b +Kr5sX3uysjp5AGp99a0anR7NWCrPXvROgKs7T9341N40osQg2VkZLYUCXh9osUyN +uREG6S12tViMUKg3bmZ4b4MwRk00n7QYSrm7+nvFrtYyEISEbD+agDM1/E281W5g +VFDPfm2AlwT6jwsg/b2YK6E3vVn9SuxFoQmLF8lyFDO3BV4SXeJaHc4hVPbh6tVV +qifrTQnfGUCCLmaJF2XZbrPWOE6NYRbWdNTeFl9RGdVCuIPSyN5LqWmXto0CAwEA +AQKCAgAzkAwcJ0z1GnId/lJQZno8NhGckRoJuEKbR8dwlCP8VUz6Ca5H7Y9kvXDa +Hs/hn+rYgP6hYOz7XyrIX2rmJ/T6dxEwqGeC1+o59FConcIRWHpE5zuGT6JYJL5F +TuZa48bm4v8VMQvQZOjIZpkIFwao8c6HTwKAnHTB5IN/48I2hCt+Cn3RhfoOZ7Rm +4gkpaSkt+7GXlhXHb82YfujNO+hbktEamhUYlQ9EK70Wa8aqmf3gHxO0JgsEFjW8 +lJaSnultlTW8SDcx3LMUUjCYumECk4oX/VlJfmKYjPlVjkr3QQ+Cm3nNucb4K4hc +c+JL+2ERhSj8RjXL7VgbNgdPnIjvQDJuTNqecTU8xWPYrkOLQpNibbLjnutLkhJz +fMyRtmDtrsey8WiCDuCHkPJ8/f8RjL2zWI9fzTDDIzdlEKouUFGOovaHVnbua6pn +hymcu9d9FV3p2rcbj0ivCs7e8j+vhSxFJEJoAbcQdXCTi/n2uR7pLtoMNiUzsejy +d46Uz+KEU920NTwE2z6JJq8I2vegnxjc7PDDrV3/5rK04B93aXiqvwWseCpxelrI +xaMkRHbXrIXRO6MXQ3N+zNq8Dg3hjGTTvaBKuwgvqLwlXY8+Aa3ooFzEOInIOSsI +XcWqXxt/tgZgsj9RwpC42t8kbA+BkbNk9EIUa+P5kEr2P/fO7QKCAQEA4EtArnOX +D6tQF8uTw8USOZC2P9s/ez1z4jRq3oKP0Kv4tJiuIObJ/dUvGVD7aM5v2xaCfhm8 +xpk09VPUgghfG5jR5qVvQr75kCNToJQudWi4ngk1HwKJzzTO11giFEdybvTUA+Pj +fmxCM0dYYqRWZoj0hLqXlUCwxE74BFIhJVjeYbf+nTQrqpllTLoW7MTZHzGx5SXx +4dNzyVAUH49Yt2D8mgXXCkf5sGLh762wj34b/rR10Kr4O5utGMZrfTRIbuQ1pNjU +m66baPzq+mC0BzqZEW70TgEb7lOr8rcVXLOi3r36omfd9/MHx7iZD6o3K1axSO15 +grD4ZrN7Ac3QJwKCAQEA2heCoBdpvy6YUk8AO2k8qDygTdmPQRuwjjT+Z2fMslBt +D7DkpKwZ6Bl9OclcpiiLHmH+hv65KqYg+tR0RRb7PcogB9El9x7yKkGTPZEYWGky +n8P84rJpKwjnwWQvPQktI1cs3YGvZA9DQTFBavRrwuzgd1oSJq5aPQ2tme0kMvWp +l1/B/cPK+PKCi/Wfisaze1TjijP9qIeUwkdNN6WLrLU3QgsGppcg2I7RQtAIikT6 +GkuiOQAvWMsrJVV6PNrVKz4fJDJ59Rz6jbDHZNi1MEYNxQoB/Pl7QIakbfjWpHLv +8Ey7cB2JKxjQy8tmyl8WNQVbXbE6daPXcMTUmaRAKwKCAQBv1lYMJmq+T2eCVen6 +BbvOpE+bi5EdvEiaFBTtmiBnpjg+pJq+oRU60h/H+c9CNR0lGxY6Fk9An4f+g6xE +ojP6KLsQzJCrsVny+wpp2TlJJcxYULMCIVvhy60PR0zG29E9biqBPhJjKUvhEcQK +e3LxcXyq6fdHXphFajLUxLbuTl+kTgBRFoBnclFGbsubh5PTsA3J+p+fQLZNPPar +veg4l82cZykQYU8pGkUaI3sUMYd3+zd7sqRP5JHs9pMGPRmY4YW2CsAIWIn5UZNB +ARMDP76vKKn8cyUgMuxb+9pU/OVLN2NPs4bEaZQJjAwV+YPEwldny7F47xEM9JVz +EtKlAoIBAQDUt62u3GdGE/p5/ZgqWoDRTyDEDfmN9aYFbmbdEP80xQE7FrxMaZhz +K7laja6SWmUm40nQ/c45bQQp4uLtKHcxU15egX7YRBTLZl5o5IasZR79ebnEm2O8 +l9kEZeU1USf3mmWmP4GExOZCRfqaiYA6BbUCdJXTqKdXeWnkAssV8UrS3JFoJHpq +yo7OWGqefyQ8nRW6jO9SW7uaqtUD+7H6aF5XSk3YWvusfdBZrHNH+fM/hpnZovaL +Us7ogTDS/laA8PyK37jYfMVdQhmZoU1Iomt3zkUWK3gt/aWPpfAlQf4Jka4YspZB +tNiijefaZ1hPqsPs5Joyd/YAhdsfaHc1AoIBAQCn/9j6RRjRaw0ip756oad4AXHz +XBwVB2CrY96qT6Hj9Sq7tGgdskqGkOQkAivBLBizUdcWv0t1yenOsSgasQeMlvlh +B8md9cLvpKXPB3HM3rTDH/xNXe0TpVKLf7SXC8HfDyIweHwMW3QgO2DWrvI4BV/T +ckBatRNQ90HxkqGFhC/Mp529lQlyg3ifxPxJsvZOyPMUnrflAvsKQk5c2ZiQg3nZ +h7I2pjSYgCl+Ib52l8p9bf1kcrVGgPM+auzm496i0RPobFeDBoBvSoznJktHJ7+3 +NnZH+jLiZCODiQPGtQUi+T6eIZUIJF0YASpsCCtUzXCxwW3lYIDNy7UlMivF +-----END RSA PRIVATE KEY----- From d8f4bad242472d094916dfdc081f2d992649f4ee Mon Sep 17 00:00:00 2001 From: Soumya Tripathy Date: Mon, 19 Oct 2026 19:10:31 +0530 Subject: [PATCH 05/10] UPSTREAM-PEND: boards: ti: am62l_evm: Add board configuration files PR: 106763 Add YAML-based board configuration files for AM62L EVM: - board-cfg.yaml: General board configuration - sec-cfg.yaml: Security configuration - schema.yaml: JSON schema for validating board config YAML files These files are processed by ti_board_config.py to generate binary blobs that are included in tiboot3.bin and tispl.bin boot images. Signed-off-by: Soumya Tripathy --- boards/ti/am62l_evm/support/board-cfg.yaml | 31 ++ boards/ti/am62l_evm/support/schema.yaml | 424 +++++++++++++++++++++ boards/ti/am62l_evm/support/sec-cfg.yaml | 379 ++++++++++++++++++ 3 files changed, 834 insertions(+) create mode 100644 boards/ti/am62l_evm/support/board-cfg.yaml create mode 100644 boards/ti/am62l_evm/support/schema.yaml create mode 100644 boards/ti/am62l_evm/support/sec-cfg.yaml diff --git a/boards/ti/am62l_evm/support/board-cfg.yaml b/boards/ti/am62l_evm/support/board-cfg.yaml new file mode 100644 index 000000000000..fb9b08045431 --- /dev/null +++ b/boards/ti/am62l_evm/support/board-cfg.yaml @@ -0,0 +1,31 @@ +# Copyright (c) 2026 Texas Instruments Incorporated +# SPDX-License-Identifier: Apache-2.0 +# +# Board configuration for the AM62Lx SoC +# +board-cfg: + rev: + boardcfg_abi_maj: 0x0 + boardcfg_abi_min: 0x1 + + control: + subhdr: + magic: 0xC1D3 + size: 7 + main_isolation_enable: 0x5A + main_isolation_hostid: 0x2 + + bm_writer_cfg: + subhdr: + magic: 0x7D8A + size: 5 + allowed_host: 10 + + reserved: [0, 0, 0, 0, 0, 0, 0] + + debug_cfg: + subhdr: + magic: 0x020C + size: 8 + trace_dst_enables: 0x00 + trace_src_enables: 0x00 diff --git a/boards/ti/am62l_evm/support/schema.yaml b/boards/ti/am62l_evm/support/schema.yaml new file mode 100644 index 000000000000..2a7b60e6beee --- /dev/null +++ b/boards/ti/am62l_evm/support/schema.yaml @@ -0,0 +1,424 @@ +# Copyright (c) 2026 Texas Instruments Incorporated +# SPDX-License-Identifier: Apache-2.0 +# +# Config schema for TI AM62L devices +# + + +definitions: + u8: + type: integer + minimum: 0 + maximum: 0xff + u16: + type: integer + minimum: 0 + maximum: 0xffff + u32: + type: integer + minimum: 0 + maximum: 0xffffffff + + +type: object +properties: + pm-cfg: + type: object + properties: + rev: + type: object + properties: + boardcfg_abi_maj: + $ref: "#/definitions/u8" + boardcfg_abi_min: + $ref: "#/definitions/u8" + board-cfg: + type: object + properties: + rev: + type: object + properties: + boardcfg_abi_maj: + $ref: "#/definitions/u8" + boardcfg_abi_min: + $ref: "#/definitions/u8" + control: + type: object + properties: + subhdr: + type: object + properties: + magic: + $ref: "#/definitions/u16" + size: + $ref: "#/definitions/u16" + main_isolation_enable: + $ref: "#/definitions/u8" + main_isolation_hostid: + $ref: "#/definitions/u16" + + bm_writer_cfg: + type: object + properties: + subhdr: + type: object + properties: + magic: + $ref: "#/definitions/u16" + size: + $ref: "#/definitions/u16" + allowed_host: + $ref: "#/definitions/u8" + + reserved: + type: array + minItems: 7 + maxItems: 7 + items: + $ref: "#/definitions/u8" + + debug_cfg: + type: object + properties: + subhdr: + type: object + properties: + magic: + $ref: "#/definitions/u16" + size: + $ref: "#/definitions/u16" + trace_dst_enables: + $ref: "#/definitions/u16" + trace_src_enables: + $ref: "#/definitions/u16" + + sec-cfg: + type: object + properties: + rev: + type: object + properties: + boardcfg_abi_maj: + $ref: "#/definitions/u8" + boardcfg_abi_min: + $ref: "#/definitions/u8" + + processor_acl_list: + type: object + properties: + subhdr: + type: object + properties: + magic: + $ref: "#/definitions/u16" + size: + $ref: "#/definitions/u16" + proc_acl_entries: + type: array + minItems: 32 + maxItems: 32 + items: + type: object + properties: + processor_id: + $ref: "#/definitions/u8" + proc_access_master: + $ref: "#/definitions/u8" + proc_access_secondary: + type: array + minItems: 3 + maxItems: 3 + items: + $ref: "#/definitions/u8" + host_hierarchy: + type: object + properties: + subhdr: + type: object + properties: + magic: + $ref: "#/definitions/u16" + size: + $ref: "#/definitions/u16" + host_hierarchy_entries: + type: array + minItems: 32 + maxItems: 32 + items: + type: object + properties: + host_id: + $ref: "#/definitions/u8" + supervisor_host_id: + $ref: "#/definitions/u8" + + otp_config: + type: object + properties: + subhdr: + type: object + properties: + magic: + $ref: "#/definitions/u16" + size: + $ref: "#/definitions/u16" + otp_entry: + type: array + minItems: 32 + maxItems: 32 + items: + type: object + properties: + host_id: + $ref: "#/definitions/u8" + host_perms: + $ref: "#/definitions/u8" + write_host_id: + $ref: "#/definitions/u8" + + dkek_config: + type: object + properties: + subhdr: + type: object + properties: + magic: + $ref: "#/definitions/u16" + size: + $ref: "#/definitions/u16" + allowed_hosts: + type: array + minItems: 4 + maxItems: 4 + items: + $ref: "#/definitions/u8" + allow_dkek_export_tisci: + $ref: "#/definitions/u8" + rsvd: + type: array + minItems: 3 + maxItems: 3 + items: + $ref: "#/definitions/u8" + + sa2ul_cfg: + type: object + properties: + subhdr: + type: object + properties: + magic: + $ref: "#/definitions/u16" + size: + $ref: "#/definitions/u16" + rsvd: + type: array + minItems: 2 + maxItems: 4 + items: + $ref: "#/definitions/u8" + enable_saul_psil_global_config_writes: + $ref: "#/definitions/u8" + auth_resource_owner: + $ref: "#/definitions/u8" + + sec_dbg_config: + type: object + properties: + subhdr: + type: object + properties: + magic: + $ref: "#/definitions/u16" + size: + $ref: "#/definitions/u16" + allow_jtag_unlock: + $ref: "#/definitions/u8" + allow_wildcard_unlock: + $ref: "#/definitions/u8" + allowed_debug_level_rsvd: + $ref: "#/definitions/u8" + rsvd: + $ref: "#/definitions/u8" + min_cert_rev: + $ref: "#/definitions/u32" + jtag_unlock_hosts: + type: array + minItems: 4 + maxItems: 4 + items: + $ref: "#/definitions/u8" + + + sec_handover_cfg: + type: object + properties: + subhdr: + type: object + properties: + magic: + $ref: "#/definitions/u16" + size: + $ref: "#/definitions/u16" + handover_msg_sender: + $ref: "#/definitions/u8" + handover_to_host_id: + $ref: "#/definitions/u8" + rsvd: + type: array + minItems: 4 + maxItems: 4 + items: + $ref: "#/definitions/u8" + + rm-cfg: + type: object + properties: + rm_boardcfg: + type: object + properties: + rev: + type: object + properties: + boardcfg_abi_maj: + $ref: "#/definitions/u8" + boardcfg_abi_min: + $ref: "#/definitions/u8" + + host_cfg: + type: object + properties: + subhdr: + type: object + properties: + magic: + $ref: "#/definitions/u16" + size: + $ref: "#/definitions/u16" + host_cfg_entries: + type: array + minItems: 0 + maxItems: 32 + items: + type: object + properties: + host_id: + $ref: "#/definitions/u8" + allowed_atype: + $ref: "#/definitions/u8" + allowed_qos: + $ref: "#/definitions/u16" + allowed_orderid: + $ref: "#/definitions/u32" + allowed_priority: + $ref: "#/definitions/u16" + allowed_sched_priority: + $ref: "#/definitions/u8" + resasg: + type: object + properties: + subhdr: + type: object + properties: + magic: + $ref: "#/definitions/u16" + size: + $ref: "#/definitions/u16" + resasg_entries_size: + $ref: "#/definitions/u16" + reserved: + $ref: "#/definitions/u16" + + resasg_entries: + type: array + minItems: 0 + maxItems: 468 + items: + type: object + properties: + start_resource: + $ref: "#/definitions/u16" + num_resource: + $ref: "#/definitions/u16" + type: + $ref: "#/definitions/u16" + host_id: + $ref: "#/definitions/u8" + reserved: + $ref: "#/definitions/u8" + + tifs-rm-cfg: + type: object + properties: + rm_boardcfg: + type: object + properties: + rev: + type: object + properties: + boardcfg_abi_maj: + $ref: "#/definitions/u8" + boardcfg_abi_min: + $ref: "#/definitions/u8" + + host_cfg: + type: object + properties: + subhdr: + type: object + properties: + magic: + $ref: "#/definitions/u16" + size: + $ref: "#/definitions/u16" + host_cfg_entries: + type: array + minItems: 0 + maxItems: 32 + items: + type: object + properties: + host_id: + $ref: "#/definitions/u8" + allowed_atype: + $ref: "#/definitions/u8" + allowed_qos: + $ref: "#/definitions/u16" + allowed_orderid: + $ref: "#/definitions/u32" + allowed_priority: + $ref: "#/definitions/u16" + allowed_sched_priority: + $ref: "#/definitions/u8" + resasg: + type: object + properties: + subhdr: + type: object + properties: + magic: + $ref: "#/definitions/u16" + size: + $ref: "#/definitions/u16" + resasg_entries_size: + $ref: "#/definitions/u16" + reserved: + $ref: "#/definitions/u16" + + resasg_entries: + type: array + minItems: 0 + maxItems: 468 + items: + type: object + properties: + start_resource: + $ref: "#/definitions/u16" + num_resource: + $ref: "#/definitions/u16" + type: + $ref: "#/definitions/u16" + host_id: + $ref: "#/definitions/u8" + reserved: + $ref: "#/definitions/u8" diff --git a/boards/ti/am62l_evm/support/sec-cfg.yaml b/boards/ti/am62l_evm/support/sec-cfg.yaml new file mode 100644 index 000000000000..c5937ecb9fbc --- /dev/null +++ b/boards/ti/am62l_evm/support/sec-cfg.yaml @@ -0,0 +1,379 @@ +# Copyright (c) 2026 Texas Instruments Incorporated +# SPDX-License-Identifier: Apache-2.0 +# +# Security board configuration for AM62Lx SoC +# + +sec-cfg: + rev: + boardcfg_abi_maj: 0x0 + boardcfg_abi_min: 0x1 + + processor_acl_list: + subhdr: + magic: 0xF1EA + size: 164 + + proc_acl_entries: + - # 1 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 2 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 3 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 4 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 5 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 6 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 7 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 8 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 9 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 10 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 11 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 12 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 13 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 14 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 15 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 16 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 17 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 18 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 19 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 20 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 21 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 22 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 23 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 24 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 25 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 26 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 27 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 28 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 29 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 30 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 31 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + - # 32 + processor_id: 0 + proc_access_master: 0 + proc_access_secondary: [0, 0, 0] + host_hierarchy: + subhdr: + magic: 0x8D27 + size: 68 + host_hierarchy_entries: + - # 1 + host_id: 0 + supervisor_host_id: 0 + - # 2 + host_id: 0 + supervisor_host_id: 0 + - # 3 + host_id: 0 + supervisor_host_id: 0 + - # 4 + host_id: 0 + supervisor_host_id: 0 + - # 5 + host_id: 0 + supervisor_host_id: 0 + - # 6 + host_id: 0 + supervisor_host_id: 0 + - # 7 + host_id: 0 + supervisor_host_id: 0 + - # 8 + host_id: 0 + supervisor_host_id: 0 + - # 9 + host_id: 0 + supervisor_host_id: 0 + - # 10 + host_id: 0 + supervisor_host_id: 0 + - # 11 + host_id: 0 + supervisor_host_id: 0 + - # 12 + host_id: 0 + supervisor_host_id: 0 + - # 13 + host_id: 0 + supervisor_host_id: 0 + - # 14 + host_id: 0 + supervisor_host_id: 0 + - # 15 + host_id: 0 + supervisor_host_id: 0 + - # 16 + host_id: 0 + supervisor_host_id: 0 + - # 17 + host_id: 0 + supervisor_host_id: 0 + - # 18 + host_id: 0 + supervisor_host_id: 0 + - # 19 + host_id: 0 + supervisor_host_id: 0 + - # 20 + host_id: 0 + supervisor_host_id: 0 + - # 21 + host_id: 0 + supervisor_host_id: 0 + - # 22 + host_id: 0 + supervisor_host_id: 0 + - # 23 + host_id: 0 + supervisor_host_id: 0 + - # 24 + host_id: 0 + supervisor_host_id: 0 + - # 25 + host_id: 0 + supervisor_host_id: 0 + - # 26 + host_id: 0 + supervisor_host_id: 0 + - # 27 + host_id: 0 + supervisor_host_id: 0 + - # 28 + host_id: 0 + supervisor_host_id: 0 + - # 29 + host_id: 0 + supervisor_host_id: 0 + - # 30 + host_id: 0 + supervisor_host_id: 0 + - # 31 + host_id: 0 + supervisor_host_id: 0 + - # 32 + host_id: 0 + supervisor_host_id: 0 + otp_config: + subhdr: + magic: 0x4081 + size: 69 + otp_entry: + - # 1 + host_id: 10 + host_perms: 2 + - # 2 + host_id: 10 + host_perms: 2 + - # 3 + host_id: 10 + host_perms: 2 + - # 4 + host_id: 10 + host_perms: 2 + - # 5 + host_id: 10 + host_perms: 2 + - # 6 + host_id: 10 + host_perms: 2 + - # 7 + host_id: 10 + host_perms: 2 + - # 8 + host_id: 10 + host_perms: 2 + - # 9 + host_id: 10 + host_perms: 2 + - # 10 + host_id: 10 + host_perms: 2 + - # 11 + host_id: 10 + host_perms: 2 + - # 12 + host_id: 10 + host_perms: 2 + - # 13 + host_id: 10 + host_perms: 2 + - # 14 + host_id: 10 + host_perms: 2 + - # 15 + host_id: 10 + host_perms: 2 + - # 16 + host_id: 10 + host_perms: 2 + - # 17 + host_id: 10 + host_perms: 2 + - # 18 + host_id: 10 + host_perms: 2 + - # 19 + host_id: 10 + host_perms: 2 + - # 20 + host_id: 10 + host_perms: 2 + - # 21 + host_id: 10 + host_perms: 2 + - # 22 + host_id: 10 + host_perms: 2 + - # 23 + host_id: 10 + host_perms: 2 + - # 24 + host_id: 10 + host_perms: 2 + - # 25 + host_id: 10 + host_perms: 2 + - # 26 + host_id: 10 + host_perms: 2 + - # 27 + host_id: 10 + host_perms: 2 + - # 28 + host_id: 10 + host_perms: 2 + - # 29 + host_id: 10 + host_perms: 2 + - # 30 + host_id: 10 + host_perms: 2 + - # 31 + host_id: 10 + host_perms: 2 + - # 32 + host_id: 10 + host_perms: 2 + write_host_id: 10 + dkek_config: + subhdr: + magic: 0x5170 + size: 12 + allowed_hosts: [128, 0, 0, 0] + allow_dkek_export_tisci: 0x5A + rsvd: [0, 0, 0] + sa2ul_cfg: + subhdr: + magic: 0x0 + size: 0 + auth_resource_owner: 0 + enable_saul_psil_global_config_writes: 0x0 + rsvd: [0, 0] + sec_dbg_config: + subhdr: + magic: 0x42AF + size: 16 + allow_jtag_unlock: 0x5A + allow_wildcard_unlock: 0x5A + allowed_debug_level_rsvd: 0 + rsvd: 0 + min_cert_rev: 0x0 + jtag_unlock_hosts: [0, 0, 0, 0] + sec_handover_cfg: + subhdr: + magic: 0x0 + size: 10 + handover_msg_sender: 0 + handover_to_host_id: 0 + rsvd: [0, 0, 0, 0] From ce074e2924bd62c27a745ba6e655553b010fca92 Mon Sep 17 00:00:00 2001 From: Soumya Tripathy Date: Mon, 19 Oct 2026 19:10:31 +0530 Subject: [PATCH 06/10] UPSTREAM-PEND: soc: ti: k3: Add Kconfig options for boot image generation PR: 106763 Add Kconfig options to control TI K3 boot image generation. Signed-off-by: Soumya Tripathy --- dts/arm64/ti/am62l3_a53.dtsi | 16 ++++++++ dts/arm64/ti/k3-boot-regions.dtsi | 23 +++++++++++ soc/ti/k3/Kconfig | 63 +++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 dts/arm64/ti/k3-boot-regions.dtsi diff --git a/dts/arm64/ti/am62l3_a53.dtsi b/dts/arm64/ti/am62l3_a53.dtsi index e22b9a185a4b..a28c1fbdcea3 100644 --- a/dts/arm64/ti/am62l3_a53.dtsi +++ b/dts/arm64/ti/am62l3_a53.dtsi @@ -12,6 +12,7 @@ #include #include #include +#include / { #address-cells = <1>; @@ -100,6 +101,21 @@ status = "okay"; }; }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + /* TF-A BL31 load region in DDR */ + tfa_reserved: tfa@80000000 { + reg = <0x80000000 DT_SIZE_K(512)>; + }; + }; + + chosen { + ti,k3-spl-load-region = &oc_sram; + }; }; &wkup_timer0 { diff --git a/dts/arm64/ti/k3-boot-regions.dtsi b/dts/arm64/ti/k3-boot-regions.dtsi new file mode 100644 index 000000000000..19bd4dc37994 --- /dev/null +++ b/dts/arm64/ti/k3-boot-regions.dtsi @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2026 Texas Instruments Incorporated + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + /* TIFS firmware load region in wakeup SRAM */ + tifs_reserved: tifs@40000 { + reg = <0x40000 DT_SIZE_K(384)>; + }; + + /* Board configuration blob load region in wakeup SRAM */ + boardcfg_reserved: boardcfg@6c000 { + reg = <0x6c000 DT_SIZE_K(16)>; + }; + }; +}; diff --git a/soc/ti/k3/Kconfig b/soc/ti/k3/Kconfig index 98f745d95843..b1251d32e638 100644 --- a/soc/ti/k3/Kconfig +++ b/soc/ti/k3/Kconfig @@ -16,4 +16,67 @@ config SOC_PART_NUMBER default "AM6442" if SOC_AM6442_M4 || SOC_AM6442_R5F0_0 || SOC_AM6442_R5F0_1 || SOC_AM6442_R5F1_0 || SOC_AM6442_R5F1_1 default "J721e" if SOC_J721E_MAIN_R5F0_0 +config SOC_FAMILY_TI_K3_TIFS_BIN + string "TIFS binary for particular soc" + default "ti-fs-firmware-am62lx-hs-enc.bin" if SOC_AM62L3_A53 + help + TIFS (TI Foundational security) firmware binary. + +config SOC_FAMILY_TI_K3_TIFS_CERT_BIN + string "TIFS inner certificate bin for particular soc" + default "ti-fs-firmware-am62lx-hs-cert.bin" if SOC_AM62L3_A53 + help + TIFS (TI Foundational security) inner certificate binary. + +config SOC_FAMILY_TI_K3_REQUIRES_SEC_CFG + bool + default y + help + Indicates if SoC requires security board configuration. + +config SOC_FAMILY_TI_K3_REQUIRES_PM_CFG + bool + default y if SOC_AM6234_A53 || SOC_AM6232_A53 || SOC_AM6254_A53 + help + Indicates if SoC requires power management board configuration. + +config SOC_FAMILY_TI_K3_REQUIRES_RM_CFG + bool + default y if SOC_AM6234_A53 || SOC_AM6232_A53 || SOC_AM6254_A53 + help + Indicates if SoC requires resource management board configuration. + +config SOC_FAMILY_TI_K3_BUILD_TIBOOT3 + bool "Generate tiboot3.bin first-stage bootloader" + depends on !SOC_AM62L3_A53 || BUILD_WITH_TFA + help + Generate tiboot3.bin (SPL/BL1 + TIFS + board configs). + +config SOC_FAMILY_TI_K3_SPL_BIN + string "SPL/BL1 binary path for tiboot3.bin" + depends on SOC_FAMILY_TI_K3_BUILD_TIBOOT3 + default "bl1.bin" if SOC_AM62L3_A53 && BUILD_WITH_TFA + default "" + help + Bootloader stage 1 binary for combined tiboot3.bin image. + +config SOC_FAMILY_TI_K3_BUILD_TISPL + bool "Generate tispl.bin combined application image" + depends on SOC_SERIES_AM62LX_A53 + depends on BUILD_WITH_TFA + help + Generate tispl.bin (BL31 + TIFS + board configs + Application binary). + +config SOC_FAMILY_TI_K3_CERT_KEY_PATH + string "X.509 certificate signing key path" + default "soc/ti/k3/keys/custMpk.pem" + help + Path to TI k3 keys in Zephyr base directory. + +config SOC_FAMILY_TI_K3_SW_REVISION + int "Software Revision" + default 1 + help + Software Revision for the x509 certificate + endif # SOC_FAMILY_TI_K3 From b54d84960864ee0489dfb598056e35587e23aeae Mon Sep 17 00:00:00 2001 From: Soumya Tripathy Date: Mon, 19 Oct 2026 19:10:31 +0530 Subject: [PATCH 07/10] UPSTREAM-PEND: modules: tfa: Introduce TARGET_BOARD parameter for tfa build PR: 106763 TI SoCs like AM62lx, AM62x, AM64x use TARGET_BOARD paramter as build parameter for TF-A build. Introduce TARGET_BOARD KConfig based build configuration. Signed-off-by: Soumya Tripathy --- modules/trusted-firmware-a/CMakeLists.txt | 8 ++++++++ modules/trusted-firmware-a/Kconfig | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/modules/trusted-firmware-a/CMakeLists.txt b/modules/trusted-firmware-a/CMakeLists.txt index 7820a5944c50..d8f35fa3f9e2 100644 --- a/modules/trusted-firmware-a/CMakeLists.txt +++ b/modules/trusted-firmware-a/CMakeLists.txt @@ -33,6 +33,10 @@ if(CONFIG_BUILD_WITH_TFA) set(TFA_PLAT "${CONFIG_TFA_PLATFORM}") endif() + if(NOT DEFINED TFA_TARGET_BOARD) + set(TFA_TARGET_BOARD "${CONFIG_TFA_TARGET_BOARD}") + endif() + find_program(MAKE_EXECUTABLE NAMES make REQUIRED) if(CMAKE_GENERATOR STREQUAL "Unix Makefiles") @@ -52,6 +56,10 @@ if(CONFIG_BUILD_WITH_TFA) ${TFA_EXTRA_ARGS} ) + if(NOT "${TFA_TARGET_BOARD}" STREQUAL "") + list(APPEND TFA_BUILD_CMD_COMMON TARGET_BOARD=${TFA_TARGET_BOARD}) + endif() + set(TFA_BUILD_CMD "") set(TFA_POST_BUILD_MAKE_ARGS "") diff --git a/modules/trusted-firmware-a/Kconfig b/modules/trusted-firmware-a/Kconfig index aec8498eb071..9cedbfb365cb 100644 --- a/modules/trusted-firmware-a/Kconfig +++ b/modules/trusted-firmware-a/Kconfig @@ -39,4 +39,10 @@ config TFA_PLATFORM Platform name for TF-A build system (PLAT= parameter). Boards should set this in their Kconfig.defconfig file. +config TFA_TARGET_BOARD + string + help + TF-A TARGET_BOARD parameter. Used by platforms that distinguish + multiple board variants under a single PLAT directory. + endif # BUILD_WITH_TFA From da1d79144cafab6d91f10d8ed4f370162df45017 Mon Sep 17 00:00:00 2001 From: Soumya Tripathy Date: Mon, 19 Oct 2026 19:10:31 +0530 Subject: [PATCH 08/10] UPSTREAM-PEND: soc: ti: k3: Add CMake build support for boot images PR: 106763 Add CMake infrastructure to generate TI K3 boot images (tiboot3.bin and tispl.bin) during Zephyr build process. Build targets: - tiboot3: Builds tiboot3.bin - tispl: Builds tispl.bin Signed-off-by: Soumya Tripathy --- soc/ti/k3/CMakeLists.txt | 246 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) diff --git a/soc/ti/k3/CMakeLists.txt b/soc/ti/k3/CMakeLists.txt index d83ec5c7dd8a..92e71a11d6e6 100644 --- a/soc/ti/k3/CMakeLists.txt +++ b/soc/ti/k3/CMakeLists.txt @@ -1,4 +1,250 @@ # Copyright (c) 2024 Nordic Semiconductor ASA +# Copyright (c) 2026 Texas Instruments Incorporated # SPDX-License-Identifier: Apache-2.0 +if(CONFIG_BUILD_WITH_TFA) + if(CONFIG_TFA_MAKE_BUILD_TYPE_DEBUG) + set(tfa_build_type "debug") + else() + set(tfa_build_type "release") + endif() + set(tfa_binary_dir ${CMAKE_BINARY_DIR}/tfa) + set(tfa_artifact_dir "${tfa_binary_dir}/${CONFIG_TFA_PLATFORM}/${CONFIG_TFA_TARGET_BOARD}/${tfa_build_type}") +endif() + +if(CONFIG_SOC_FAMILY_TI_K3_BUILD_TIBOOT3) + + # Load addresses from DTS reserved-memory nodes + dt_nodelabel(ti_k3_tifs_node NODELABEL "tifs_reserved") + dt_reg_addr(ti_k3_tifs_load_addr PATH "${ti_k3_tifs_node}") + dt_nodelabel(ti_k3_boardcfg_node NODELABEL "boardcfg_reserved") + dt_reg_addr(ti_k3_boardcfg_load_addr PATH "${ti_k3_boardcfg_node}") + dt_chosen(ti_k3_spl_node PROPERTY "ti,k3-spl-load-region") + dt_reg_addr(ti_k3_spl_load_addr PATH "${ti_k3_spl_node}") + + # Board config file paths (${BOARD_DIR}/support/) + set(ti_k3_board_cfg_schema "${BOARD_DIR}/support/schema.yaml") + set(ti_k3_board_cfg_yaml "${BOARD_DIR}/support/board-cfg.yaml") + set(ti_k3_sec_cfg_yaml "${BOARD_DIR}/support/sec-cfg.yaml") + set(ti_k3_pm_cfg_yaml "${BOARD_DIR}/support/pm-cfg.yaml") + set(ti_k3_rm_cfg_yaml "${BOARD_DIR}/support/rm-cfg.yaml") + + set(ti_k3_tifs_bin "${ZEPHYR_HAL_TI_MODULE_DIR}/zephyr/blobs/ti-sysfw/${CONFIG_SOC_FAMILY_TI_K3_TIFS_BIN}") + set(ti_k3_tifs_cert_bin "${ZEPHYR_HAL_TI_MODULE_DIR}/zephyr/blobs/ti-sysfw/${CONFIG_SOC_FAMILY_TI_K3_TIFS_CERT_BIN}") + + # Resolve key path relative to Zephyr base + set(ti_k3_cert_key_path "${ZEPHYR_BASE}/${CONFIG_SOC_FAMILY_TI_K3_CERT_KEY_PATH}") + + # Validate required files + set(ti_k3_missing "") + if(NOT EXISTS ${ti_k3_tifs_bin}) + list(APPEND ti_k3_missing "TIFS: ${CONFIG_SOC_FAMILY_TI_K3_TIFS_BIN}") + endif() + if(NOT EXISTS ${ti_k3_tifs_cert_bin}) + list(APPEND ti_k3_missing "TIFS cert: ${CONFIG_SOC_FAMILY_TI_K3_TIFS_CERT_BIN}") + endif() + if(NOT EXISTS "${ti_k3_cert_key_path}") + list(APPEND ti_k3_missing "signing key: ${ti_k3_cert_key_path}") + endif() + if(NOT EXISTS "${ti_k3_board_cfg_schema}") + list(APPEND ti_k3_missing "schema: ${ti_k3_board_cfg_schema}") + endif() + if(NOT EXISTS "${ti_k3_board_cfg_yaml}") + list(APPEND ti_k3_missing "board-cfg: ${ti_k3_board_cfg_yaml}") + endif() + if(CONFIG_SOC_FAMILY_TI_K3_REQUIRES_SEC_CFG AND NOT EXISTS "${ti_k3_sec_cfg_yaml}") + list(APPEND ti_k3_missing "sec-cfg: ${ti_k3_sec_cfg_yaml}") + endif() + if(CONFIG_SOC_FAMILY_TI_K3_REQUIRES_PM_CFG AND NOT EXISTS "${ti_k3_pm_cfg_yaml}") + list(APPEND ti_k3_missing "pm-cfg: ${ti_k3_pm_cfg_yaml}") + endif() + if(CONFIG_SOC_FAMILY_TI_K3_REQUIRES_RM_CFG AND NOT EXISTS "${ti_k3_rm_cfg_yaml}") + list(APPEND ti_k3_missing "rm-cfg: ${ti_k3_rm_cfg_yaml}") + endif() + + if(ti_k3_missing) + string(REPLACE ";" "\n - " ti_k3_missing_str "${ti_k3_missing}") + message(WARNING + "TI K3: Missing files for tiboot3.bin generation:\n - ${ti_k3_missing_str}\n" + "tiboot3.bin will NOT be generated. Run 'west blobs fetch hal_ti' to fetch firmware.") + else() + # Output paths + set(ti_k3_combined_boardcfg "${CMAKE_BINARY_DIR}/zephyr/tiboot3-boardcfg.bin") + set(ti_k3_tiboot3_bin "${CMAKE_BINARY_DIR}/zephyr/tiboot3.bin") + + # Build combined board config blob command + set(ti_k3_boardcfg_cmd + ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/scripts/ti_board_config.py + --schema ${ti_k3_board_cfg_schema} + --board-cfg ${ti_k3_board_cfg_yaml} + ) + if(CONFIG_SOC_FAMILY_TI_K3_REQUIRES_SEC_CFG) + list(APPEND ti_k3_boardcfg_cmd --sec-cfg ${ti_k3_sec_cfg_yaml}) + endif() + if(CONFIG_SOC_FAMILY_TI_K3_REQUIRES_PM_CFG) + list(APPEND ti_k3_boardcfg_cmd --pm-cfg ${ti_k3_pm_cfg_yaml}) + endif() + if(CONFIG_SOC_FAMILY_TI_K3_REQUIRES_RM_CFG) + list(APPEND ti_k3_boardcfg_cmd --rm-cfg ${ti_k3_rm_cfg_yaml}) + endif() + list(APPEND ti_k3_boardcfg_cmd --output ${ti_k3_combined_boardcfg} --build-dir ${CMAKE_BINARY_DIR}) + + # Generate combined board config blob + add_custom_command( + OUTPUT ${ti_k3_combined_boardcfg} + COMMAND ${ti_k3_boardcfg_cmd} + DEPENDS ${ti_k3_board_cfg_yaml} ${ti_k3_board_cfg_schema} + COMMENT "Generating tiboot3.bin board config blob" + ) + + if(CONFIG_BUILD_WITH_TFA) + set(ti_k3_spl_bin "${tfa_artifact_dir}/${CONFIG_SOC_FAMILY_TI_K3_SPL_BIN}") + else() + set(ti_k3_spl_bin "${CMAKE_BINARY_DIR}/zephyr/${CONFIG_SOC_FAMILY_TI_K3_SPL_BIN}") + endif() + + # Set dependencies (TFA required for AM62L, enforced by Kconfig) + set(ti_k3_tiboot3_depends ${ti_k3_combined_boardcfg}) + if(CONFIG_BUILD_WITH_TFA) + list(APPEND ti_k3_tiboot3_depends tfa) + endif() + + # Generate tiboot3.bin + add_custom_command( + OUTPUT ${ti_k3_tiboot3_bin} + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/scripts/rom_image_gen.py + --swrv ${CONFIG_SOC_FAMILY_TI_K3_SW_REVISION} + --spl-bin ${ti_k3_spl_bin} + --sysfw-bin ${ti_k3_tifs_bin} + --sysfw-inner-cert ${ti_k3_tifs_cert_bin} + --boardcfg-blob ${ti_k3_combined_boardcfg} + --spl-loadaddr ${ti_k3_spl_load_addr} + --sysfw-loadaddr ${ti_k3_tifs_load_addr} + --bcfg-loadaddr ${ti_k3_boardcfg_load_addr} + --key ${ti_k3_cert_key_path} + --rom-image ${ti_k3_tiboot3_bin} + --build-dir ${CMAKE_BINARY_DIR} + --dual-stage-boot + DEPENDS ${ti_k3_tiboot3_depends} + COMMENT "Generating tiboot3.bin" + ) + + add_custom_target(tiboot3 ALL DEPENDS ${ti_k3_tiboot3_bin}) + + endif() + +endif() + +if(CONFIG_SOC_FAMILY_TI_K3_BUILD_TISPL) + + # Load addresses from DTS reserved-memory nodes + dt_nodelabel(ti_k3_tfa_node NODELABEL "tfa_reserved") + dt_reg_addr(ti_k3_tfa_load_addr PATH "${ti_k3_tfa_node}") + dt_nodelabel(ti_k3_tifs_node NODELABEL "tifs_reserved") + dt_reg_addr(ti_k3_tifs_load_addr PATH "${ti_k3_tifs_node}") + dt_nodelabel(ti_k3_boardcfg_node NODELABEL "boardcfg_reserved") + dt_reg_addr(ti_k3_boardcfg_load_addr PATH "${ti_k3_boardcfg_node}") + dt_chosen(ti_k3_sram_path PROPERTY "zephyr,sram") + dt_reg_addr(ti_k3_app_load_addr PATH "${ti_k3_sram_path}") + + # Board config file paths (${BOARD_DIR}/support/) + set(ti_k3_board_cfg_schema "${BOARD_DIR}/support/schema.yaml") + set(ti_k3_board_cfg_yaml "${BOARD_DIR}/support/board-cfg.yaml") + set(ti_k3_sec_cfg_yaml "${BOARD_DIR}/support/sec-cfg.yaml") + set(ti_k3_pm_cfg_yaml "${BOARD_DIR}/support/pm-cfg.yaml") + set(ti_k3_rm_cfg_yaml "${BOARD_DIR}/support/rm-cfg.yaml") + # TIFS firmware paths (same as tiboot3) + set(ti_k3_tifs_bin "${ZEPHYR_HAL_TI_MODULE_DIR}/zephyr/blobs/ti-sysfw/${CONFIG_SOC_FAMILY_TI_K3_TIFS_BIN}") + set(ti_k3_tifs_cert_bin "${ZEPHYR_HAL_TI_MODULE_DIR}/zephyr/blobs/ti-sysfw/${CONFIG_SOC_FAMILY_TI_K3_TIFS_CERT_BIN}") + # Resolve key path relative to Zephyr base + set(ti_k3_cert_key_path "${ZEPHYR_BASE}/${CONFIG_SOC_FAMILY_TI_K3_CERT_KEY_PATH}") + # Validate required files + set(ti_k3_missing "") + if(NOT EXISTS ${ti_k3_tifs_bin}) + list(APPEND ti_k3_missing "TIFS: ${CONFIG_SOC_FAMILY_TI_K3_TIFS_BIN}") + endif() + if(NOT EXISTS ${ti_k3_tifs_cert_bin}) + list(APPEND ti_k3_missing "TIFS cert: ${CONFIG_SOC_FAMILY_TI_K3_TIFS_CERT_BIN}") + endif() + if(NOT EXISTS "${ti_k3_cert_key_path}") + list(APPEND ti_k3_missing "signing key: ${ti_k3_cert_key_path}") + endif() + if(NOT EXISTS "${ti_k3_board_cfg_schema}") + list(APPEND ti_k3_missing "schema: ${ti_k3_board_cfg_schema}") + endif() + if(NOT EXISTS "${ti_k3_board_cfg_yaml}") + list(APPEND ti_k3_missing "board-cfg: ${ti_k3_board_cfg_yaml}") + endif() + if(CONFIG_SOC_FAMILY_TI_K3_REQUIRES_SEC_CFG AND NOT EXISTS "${ti_k3_sec_cfg_yaml}") + list(APPEND ti_k3_missing "sec-cfg: ${ti_k3_sec_cfg_yaml}") + endif() + if(CONFIG_SOC_FAMILY_TI_K3_REQUIRES_PM_CFG AND NOT EXISTS "${ti_k3_pm_cfg_yaml}") + list(APPEND ti_k3_missing "pm-cfg: ${ti_k3_pm_cfg_yaml}") + endif() + if(CONFIG_SOC_FAMILY_TI_K3_REQUIRES_RM_CFG AND NOT EXISTS "${ti_k3_rm_cfg_yaml}") + list(APPEND ti_k3_missing "rm-cfg: ${ti_k3_rm_cfg_yaml}") + endif() + if(ti_k3_missing) + string(REPLACE ";" "\n - " ti_k3_missing_str "${ti_k3_missing}") + message(WARNING + "TI K3: Missing files for tispl.bin generation:\n - ${ti_k3_missing_str}\n" + "tispl.bin will NOT be generated. Run 'west blobs fetch hal_ti' to fetch firmware.") + else() + # Output paths + set(ti_k3_tispl_boardcfg "${CMAKE_BINARY_DIR}/zephyr/tispl-boardcfg.bin") + set(ti_k3_tispl_bin "${CMAKE_BINARY_DIR}/zephyr/tispl.bin") + # Build combined board config blob command (same as tiboot3) + set(ti_k3_tispl_boardcfg_cmd + ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/scripts/ti_board_config.py + --schema ${ti_k3_board_cfg_schema} + --board-cfg ${ti_k3_board_cfg_yaml} + ) + if(CONFIG_SOC_FAMILY_TI_K3_REQUIRES_SEC_CFG) + list(APPEND ti_k3_tispl_boardcfg_cmd --sec-cfg ${ti_k3_sec_cfg_yaml}) + endif() + if(CONFIG_SOC_FAMILY_TI_K3_REQUIRES_PM_CFG) + list(APPEND ti_k3_tispl_boardcfg_cmd --pm-cfg ${ti_k3_pm_cfg_yaml}) + endif() + if(CONFIG_SOC_FAMILY_TI_K3_REQUIRES_RM_CFG) + list(APPEND ti_k3_tispl_boardcfg_cmd --rm-cfg ${ti_k3_rm_cfg_yaml}) + endif() + list(APPEND ti_k3_tispl_boardcfg_cmd --output ${ti_k3_tispl_boardcfg} --build-dir ${CMAKE_BINARY_DIR}) + set(ti_k3_atf_bin "${tfa_artifact_dir}/bl31.bin") + set(ti_k3_app_bin "${CMAKE_BINARY_DIR}/zephyr/zephyr.bin") + # Generate tispl board config blob + add_custom_command( + OUTPUT ${ti_k3_tispl_boardcfg} + COMMAND ${ti_k3_tispl_boardcfg_cmd} + DEPENDS ${ti_k3_board_cfg_yaml} ${ti_k3_board_cfg_schema} + COMMENT "Generating tispl.bin board config blob" + ) + # Generate tispl.bin (depends on TFA artifacts and zephyr.bin) + add_custom_command( + OUTPUT ${ti_k3_tispl_bin} + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/scripts/rom_image_gen.py + --swrv ${CONFIG_SOC_FAMILY_TI_K3_SW_REVISION} + --spl-bin ${ti_k3_atf_bin} + --spl-loadaddr ${ti_k3_tfa_load_addr} + --sysfw-bin ${ti_k3_tifs_bin} + --sysfw-loadaddr ${ti_k3_tifs_load_addr} + --sysfw-inner-cert ${ti_k3_tifs_cert_bin} + --boardcfg-blob ${ti_k3_tispl_boardcfg} + --bcfg-loadaddr ${ti_k3_boardcfg_load_addr} + --application-bin ${ti_k3_app_bin} + --application-loadaddr ${ti_k3_app_load_addr} + --key ${ti_k3_cert_key_path} + --rom-image ${ti_k3_tispl_bin} + --build-dir ${CMAKE_BINARY_DIR} + --dual-stage-boot + DEPENDS + tfa + ${ti_k3_app_bin} + ${ti_k3_tispl_boardcfg} + COMMENT "Generating tispl.bin" + ) + # Wrapper target to ensure tispl.bin is built + add_custom_target(tispl ALL DEPENDS ${ti_k3_tispl_bin}) + endif() +endif() + add_subdirectory(./common) From cf7740673f50ec1e6eaaa98ca90aa78d172a92d0 Mon Sep 17 00:00:00 2001 From: Soumya Tripathy Date: Mon, 19 Oct 2026 19:10:31 +0530 Subject: [PATCH 09/10] UPSTREAM-PEND: boards: ti: am62l_evm: Add TF-A platform configuration PR: 106763 Set TFA_PLATFORM default to "k3low" for AM62L EVM in Kconfig.defconfig. Signed-off-by: Soumya Tripathy --- boards/ti/am62l_evm/Kconfig.defconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/boards/ti/am62l_evm/Kconfig.defconfig b/boards/ti/am62l_evm/Kconfig.defconfig index b3cbf2548f56..56a003236e39 100644 --- a/boards/ti/am62l_evm/Kconfig.defconfig +++ b/boards/ti/am62l_evm/Kconfig.defconfig @@ -20,4 +20,14 @@ endif # FLASH_MSPI_NOR endif # FLASH +if BUILD_WITH_TFA + +configdefault TFA_PLATFORM + default "k3low" + +configdefault TFA_TARGET_BOARD + default "am62lx-evm" + +endif # BUILD_WITH_TFA + endif # BOARD_AM62L_EVM From 7a69d16b2cc93db5dc33a8238593c43d11f3aa91 Mon Sep 17 00:00:00 2001 From: Soumya Tripathy Date: Mon, 19 Oct 2026 19:10:32 +0530 Subject: [PATCH 10/10] UPSTREAM-PEND: boards: ti: am62l_evm: Update documentation for boot images PR: 106763 Update AM62L EVM documentation to describe the dual-stage boot architecture and boot image generation process. Signed-off-by: Soumya Tripathy --- boards/ti/am62l_evm/doc/index.rst | 253 +++++++++++++++++++++++++++++- 1 file changed, 248 insertions(+), 5 deletions(-) diff --git a/boards/ti/am62l_evm/doc/index.rst b/boards/ti/am62l_evm/doc/index.rst index a269465ed3eb..351a09bb13de 100644 --- a/boards/ti/am62l_evm/doc/index.rst +++ b/boards/ti/am62l_evm/doc/index.rst @@ -85,8 +85,179 @@ Serial Port This board configuration uses a single serial communication channel with the MAIN domain UART (main_uart0). -SD Card -******* +Building and Booting +********************* + +Dual-Stage Boot Architecture +============================= + +The AM62L SoC uses a dual-stage boot architecture: + +**Stage 1: tiboot3.bin** + - Loaded by boot ROM from boot media (SD/eMMC/OSPI) + - Contains BL1 (first-stage bootloader) from TF-A + - Contains TIFS (TI Foundation Security firmware) + - Contains board configuration (security, power, resource management) + - Initializes SRAM, validates TIFS, loads Stage 2 into DDR + +**Stage 2: tispl.bin** + - Loaded by ROM into DDR memory + - Contains TF-A BL31 (ARM Trusted Firmware - secure monitor) + - Contains Zephyr application binary + +Building Boot Images +==================== + +Boot image generation (``tispl.bin``, ``tiboot3.bin``) is **not enabled by default**. +The TF-A revision bundled with Zephyr does not include AM62Lx board support. AM62Lx +board support is available in upstream TF-A, which must be configured separately in +``west.yml``. + +A standard build without any extra flags produces only the Zephyr application binary: + +.. zephyr-app-commands:: + :tool: west + :app: samples/hello_world + :board: am62l_evm/am62l3/a53 + :goals: build + :compact: + +Prerequisites +------------- + +Boot image generation requires ARM Trusted Firmware-A with AM62Lx support. Update +``west.yml`` to use upstream TF-A before enabling boot image generation, then run +``west update``: + +.. code-block:: yaml + + - name: trusted-firmware-a + url: https://review.trustedfirmware.org/TF-A/trusted-firmware-a + revision: master + path: modules/tee/tf-a/trusted-firmware-a + groups: + - tee + +Building +-------- + +**Generating tiboot3.bin (Stage 1)** + +Enable :kconfig:option:`CONFIG_BUILD_WITH_TFA` and +:kconfig:option:`CONFIG_SOC_FAMILY_TI_K3_BUILD_TIBOOT3` +to generate the ``tiboot3.bin`` Stage 1 bootloader (BL1 + TIFS + board configs): + +.. zephyr-app-commands:: + :tool: west + :app: samples/hello_world + :board: am62l_evm/am62l3/a53 + :goals: build + :gen-args: -DCONFIG_BUILD_WITH_TFA=y -DCONFIG_SOC_FAMILY_TI_K3_BUILD_TIBOOT3=y + :compact: + +**Generating tispl.bin (Stage 2)** + +Enable :kconfig:option:`CONFIG_BUILD_WITH_TFA` and +:kconfig:option:`CONFIG_SOC_FAMILY_TI_K3_BUILD_TISPL` +to generate the ``tispl.bin`` boot image (TF-A BL31 + Zephyr): + +.. zephyr-app-commands:: + :tool: west + :app: samples/hello_world + :board: am62l_evm/am62l3/a53 + :goals: build + :gen-args: -DCONFIG_BUILD_WITH_TFA=y -DCONFIG_SOC_FAMILY_TI_K3_BUILD_TISPL=y + :compact: + +To generate both boot images in a single build: + +.. zephyr-app-commands:: + :tool: west + :app: samples/hello_world + :board: am62l_evm/am62l3/a53 + :goals: build + :gen-args: -DCONFIG_BUILD_WITH_TFA=y -DCONFIG_SOC_FAMILY_TI_K3_BUILD_TISPL=y -DCONFIG_SOC_FAMILY_TI_K3_BUILD_TIBOOT3=y + :compact: + +When boot image generation is enabled, the build system will automatically: + +1. Build ARM Trusted Firmware-A (BL31, and BL1 if generating tiboot3.bin) +2. Generate board configuration blobs +3. Create ``tiboot3.bin`` (Stage 1 bootloader) - **if CONFIG_SOC_FAMILY_TI_K3_BUILD_TIBOOT3=y** +4. Create ``tispl.bin`` (Stage 2 with TF-A BL31 + Zephyr app) - **if CONFIG_SOC_FAMILY_TI_K3_BUILD_TISPL=y** + +Generated Boot Files +==================== + +A default build (no boot image flags) generates: + +.. code-block:: console + + build/zephyr/zephyr.bin # Zephyr application binary + +With :kconfig:option:`CONFIG_SOC_FAMILY_TI_K3_BUILD_TISPL` enabled: + +.. code-block:: console + + build/zephyr/zephyr.bin # Zephyr application binary + build/zephyr/tispl.bin # Stage 2 boot image (TF-A BL31 + Zephyr) + build/zephyr/bl31.bin # TF-A BL31 binary (intermediate) + +With :kconfig:option:`CONFIG_SOC_FAMILY_TI_K3_BUILD_TIBOOT3` also enabled: + +.. code-block:: console + + build/zephyr/tiboot3.bin # Stage 1 bootloader (BL1 + TIFS + board configs) + build/zephyr/bl1.bin # TF-A BL1 binary (intermediate) + +Booting from SD Card +******************** + +The AM62L EVM supports two boot methods: direct boot (no U-Boot) and U-Boot-based boot. + +Option 1: Direct Boot (No U-Boot) +================================== + +This method boots Zephyr directly using only the generated boot images. + +**Build Requirements:** + +To use direct boot, both ``tiboot3.bin`` and ``tispl.bin`` are required. Enable both +boot image configurations explicitly: + +.. code-block:: console + + west build -b am62l_evm/am62l3/a53 samples/hello_world -- \ + -DCONFIG_BUILD_WITH_TFA=y \ + -DCONFIG_SOC_FAMILY_TI_K3_BUILD_TISPL=y \ + -DCONFIG_SOC_FAMILY_TI_K3_BUILD_TIBOOT3=y + +**Preparation:** + +1. Prepare an SD card with a FAT32 boot partition +2. Copy the generated boot images to the SD card: + + .. code-block:: console + + cp build/zephyr/tiboot3.bin /media/boot/ + cp build/zephyr/tispl.bin /media/boot/ + +3. Insert the SD card and power on the board + +**Boot Sequence:** + +.. code-block:: text + + Boot ROM → tiboot3.bin (BL1 + TIFS) → tispl.bin (TF-A + Zephyr) + ↓ + Zephyr Running + +The boot ROM loads ``tiboot3.bin``, which initializes the hardware and loads +``tispl.bin`` into DDR. The TF-A BL31 then starts the Zephyr application at +0x82000000. No U-Boot is involved. + +Option 2: U-Boot-Based Boot +============================ Download TI's official `WIC`_ and flash the WIC file with an etching software onto an SD-card. @@ -99,10 +270,11 @@ Use U-Boot to load and start zephyr.bin: .. code-block:: console - fatload mmc 1:1 0x82000000 zephyr.bin; dcache flush; icache flush; dcache off; icache off; go 0x82000000 + fatload mmc 1:1 0x82000000 zephyr.bin; dcache flush; icache flush; dcache off; icache off; go 0x82000000 The Zephyr application should start running on the A53 core. + Debugging ********* @@ -118,11 +290,82 @@ The board is equipped with an XDS110 JTAG debugger. To debug a binary, utilize t To utilize this feature, you'll need OpenOCD version 0.12 or higher. Due to the possibility of older versions being available in package feeds, it's advisable to `build OpenOCD from source`_. + +Custom Board Configuration +*************************** + +Board configurations are defined in YAML files under ``boards/ti/am62l_evm/support/``: + +- ``board-cfg.yaml`` - General board configuration +- ``sec-cfg.yaml`` - Security configuration +- ``pm-cfg.yaml`` - Power management (not required for AM62L) +- ``rm-cfg.yaml`` - Resource management (not required for AM62L) + +To customize, edit these files and rebuild. The build system will automatically +regenerate the board configuration binary blob. + +Custom Signing Keys +=================== + +For production, replace the development signing key: + +.. code-block:: kconfig + + CONFIG_SOC_FAMILY_TI_K3_CERT_KEY_PATH="path/to/production_key.pem" + +The path is relative to the Zephyr base directory. The key must be RSA 2048-bit in PEM format. + +TF-A Build Configuration +========================= + +The following Kconfig option controls the TF-A build target board: + +**CONFIG_TFA_TARGET_BOARD** + TF-A TARGET_BOARD parameter (string, default: "am62lx-evm" for AM62L) + + This specifies the board name passed to TF-A's build system via the TARGET_BOARD parameter. + TF-A artifacts are always placed under a board-specific subdirectory: + ``build/tfa/${PLATFORM}/${TARGET_BOARD}/${BUILD_TYPE}/`` + (e.g., ``build/tfa/k3/am62lx-evm/release/``) + +Boot Image Structure +===================== + +**tiboot3.bin structure:** + +.. code-block:: text + + +------------------+ + | X.509 Certificate| (Signed with RSA key) + +------------------+ + | BL1 Binary | (TF-A first stage) + +------------------+ + | TIFS Firmware | (System firmware) + +------------------+ + | TIFS Inner Cert | (Firmware certificate) + +------------------+ + | Board Config | (Combined YAML configs) + +------------------+ + +**tispl.bin structure:** + +.. code-block:: text + + +------------------+ + | X.509 Certificate| (Signed with RSA key) + +------------------+ + | TF-A BL31 | (ARM Trusted Firmware) + +------------------+ + | TIFS Firmware | (System firmware) + +------------------+ + | Board Config | (Combined YAML configs) + +------------------+ + | Zephyr Binary | (Application code) + +------------------+ + References ********** -https://www.ti.com/tool/TMDS62LEVM - .. _AM62L EVM TRM: https://www.ti.com/lit/pdf/sprujb4