Add fwTPM example for Xilinx ZCU102 Cortex-R5 (lock-step)#3
Open
dgarske wants to merge 2 commits into
Open
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a new end-to-end fwTPM example targeting the Xilinx ZCU102 where Linux (A53) loads and communicates with a bare-metal Cortex-R5 lock-step fwTPM instance via Linux remoteproc + OpenAMP RPMsg, along with a PetaLinux project and a Linux-side smoke test.
Changes:
- Added ZCU102 R5 lock-step bare-metal fwTPM firmware (resource table, MPU setup, RPMsg transport, NV HALs, linker script, build system).
- Added a self-contained PetaLinux 2025.2 project (DT overlay carveouts/lock-step/IPI mailbox + recipes for firmware staging and smoke test + kernel config fragment).
- Added host-side helpers and documentation (SD deploy script, READMEs, repo top-level README entry, gitignore updates).
Reviewed changes
Copilot reviewed 46 out of 49 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| Xilinx/fwtpm-zcu102-r5/README.md | ZCU102 fwTPM architecture/build/boot documentation for the new example. |
| Xilinx/fwtpm-zcu102-r5/deploy-to-sdcard.sh | Host script to deploy PetaLinux artifacts to an SD card. |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/Makefile | Build rules for the R5 bare-metal fwTPM firmware (Tier-1 objects, Tier-2 ELF link). |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/boot.S | R5 reset/vector entry and TCM stub for remoteproc reload robustness. |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/lscript.ld | Linker script for rproc DDR carveout + TCM vectors + trace/resource sections. |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/mpu_setup.c | Minimal ARMv7-R MPU programming for Normal-NC + Device regions. |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/main.c | Firmware entry: MPU init, HAL registration, fwTPM init, RPMsg server loop. |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/user_settings.h | wolfSSL/wolfTPM build-time configuration for bare-metal R5. |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/fwtpm_clock_zynqmp.c | Clock HAL (PMU CCNT) and RNG seed callback. |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/fwtpm_nv_ram.c | Volatile RAM-backed NV HAL (V1 fallback). |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/fwtpm_nv_qspi.c | QSPI-backed NV HAL skeleton using XQspiPsu. |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/fwtpm_rpmsg.c | OpenAMP RPMsg endpoint bridging to FWTPM_ProcessCommand + poll loop. |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/platform_info.c | libmetal device registration + remoteproc ops + IPI helpers for OpenAMP. |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/rsc_table.c | remoteproc resource table (rpmsg vdev + optional trace ring). |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/bsp_stubs.c | Newlib/BSP stubs: _sbrk + outbyte() -> trace buffer ring. |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/zcu102_r5.h | Local header for platform HAL APIs used across firmware sources. |
| Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/include/xparameters.h | Hand-rolled minimal platform constants and carveout addresses. |
| Xilinx/fwtpm-zcu102-r5/petalinux/README.md | Instructions for building and validating the included PetaLinux project. |
| Xilinx/fwtpm-zcu102-r5/petalinux/.gitignore | Ignores PetaLinux build outputs/imported hardware, preserves key configs. |
| Xilinx/fwtpm-zcu102-r5/petalinux/.petalinux/metadata | Captures PetaLinux version and project metadata for the committed project. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/attributes | PetaLinux project attributes (e.g., defconfig selection). |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/configs/config | Committed PetaLinux system configuration used as build input. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/configs/flash_parts.txt | Flash layout config for PetaLinux tooling. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/configs/rootfsconfigs/user-rootfsconfig | Rootfs config list (user-rootfsconfig) for the project. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/README | Meta-user layer README (currently template content). |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/COPYING.MIT | MIT license text for the meta-user layer template. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/conf/layer.conf | Yocto layer configuration for meta-user (scarthgap compatibility). |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/conf/petalinuxbsp.conf | Adds fwtpm-r5 and fwtpm-rpmsg-test packages to IMAGE_INSTALL. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/conf/user-rootfsconfig | Meta-user rootfs package listing file. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/recipes-bsp/device-tree/device-tree.bbappend | Hooks in system-user.dtsi overlay for the device-tree build. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/recipes-bsp/device-tree/device-tree-sdt.inc | SDT include wiring for extra DT include files. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi | DT overlay: lock-step cluster mode, carveouts, IPI mailbox, QSPI partition, GEM3 PHY. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/recipes-bsp/fwtpm-r5/fwtpm-r5_0.1.0.bb | Recipe to stage the prebuilt R5 ELF into firmware directory for remoteproc. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/recipes-apps/fwtpm-rpmsg-test/fwtpm-rpmsg-test_0.1.0.bb | Recipe to build/install the RPMsg smoke-test client. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/recipes-apps/fwtpm-rpmsg-test/files/fwtpm_rpmsg_test.c | Source for the smoke-test client (duplicate of linux-client version). |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/recipes-kernel/linux/linux-xlnx_%.bbappend | Adds kernel feature fragments (bsp.cfg + openamp.cfg). |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/recipes-kernel/linux/linux-xlnx/bsp.cfg | Empty kernel fragment placeholder referenced by bbappend. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/recipes-kernel/linux/linux-xlnx/openamp.cfg | Kernel config fragment enabling remoteproc/rpmsg/mailbox. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/recipes-bsp/u-boot/u-boot-xlnx_%.bbappend | U-Boot bbappend adding platform-top.h and bsp.cfg. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/recipes-bsp/u-boot/files/platform-top.h | U-Boot platform-top config header inclusion shim. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/recipes-bsp/u-boot/files/bsp.cfg | U-Boot config selection for platform-top. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/recipes-bsp/u-boot/files/0001-ubifs-distroboot-support.patch | U-Boot patch file (currently not wired into bbappend). |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/meta-xilinx-tools/recipes-bsp/uboot-device-tree/uboot-device-tree.bbappend | Adds a DT include for the U-Boot device-tree build. |
| Xilinx/fwtpm-zcu102-r5/petalinux/project-spec/meta-user/meta-xilinx-tools/recipes-bsp/uboot-device-tree/files/system-user.dtsi | Minimal U-Boot DT include overlay file. |
| Xilinx/fwtpm-zcu102-r5/linux-client/Makefile | Standalone build for the A53 Linux smoke-test client. |
| Xilinx/fwtpm-zcu102-r5/linux-client/fwtpm_rpmsg_test.c | Standalone A53 Linux RPMsg smoke-test client source. |
| README.md | Top-level repo README updated to mention the new ZCU102 example. |
| .gitignore | Repo gitignore updated for ZCU102 example build artifacts (BSP/hw/petalinux outputs/client binary). |
Comments suppressed due to low confidence (2)
Xilinx/fwtpm-zcu102-r5/README.md:211
- In the Memory Map table, the QSPI fwtpm-nv partition is listed at 0x07F00000, but system-user.dtsi defines it at 0x07FF0000. This discrepancy can cause readers to partition flash incorrectly and (if the QSPI HAL is enabled) can lead to writes to the wrong offset; please make the address consistent everywhere.
| RPMsg buffer pool | 0x3EE08000 | 256 KiB | shared payload buffers |
| QSPI fwtpm-nv | 0x07F00000 | 64 KiB | persistent NV (R5 owns) |
Xilinx/fwtpm-zcu102-r5/firmware/fwtpm-r5/fwtpm_nv_qspi.c:253
- This file uses printf() for QSPI init errors, but the port documentation indicates newlib stdio is not usable on this bare-metal R5 (no _write backend). If printf isn’t wired to outbyte/xil_printf, these diagnostics may hang precisely when flash init fails; prefer xil_printf/outbyte-based logging for error reporting here.
cfg = XQspiPsu_LookupConfig(XPAR_XQSPIPSU_0_BASEADDR);
if (cfg == NULL) {
printf("XQspiPsu LookupConfig failed\n");
return -1;
}
rc = XQspiPsu_CfgInitialize(&g_qspi, cfg, cfg->BaseAddress);
if (rc != XST_SUCCESS) {
printf("XQspiPsu CfgInitialize failed: %d\n", rc);
return rc;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds two production-class wolfTPM firmware TPM (fwTPM) examples to
wolftpm-examples, each demonstrating a different deployment topology. Together they cover the two canonical ways to run wolfTPM as a software TPM 2.0 server inside the same SoC as the application:mssim-style framed transport over UART. NSC veneers gate every secure-side call.remoteproc. Persistent NV is in QSPI flash. Both TCG TPM 2.0 v1.85 PQC primitives (ML-KEM 512/768/1024, ML-DSA 44/65/87) are enabled.Architecture
STM32/fwtpm-stm32h5/— TrustZone-isolated fwTPMpartition_stm32h563xx.hcarves NS/S address space.fwtpm_nsc.{c,h}; every TPM2 command crosses the secure gate.Xilinx/fwtpm-zcu102-r5/— AMP fwTPM on R5 lock-step + OpenAMP RPMsgKey design choices, all observable on hardware:
xlnx,cluster-mode=<1>+xlnx,tcm-mode=<1>combine RPU0+RPU1 into one logical safety-class processor with 256 KiB merged TCM at0x00000000. Singleremoteproc0instance manages both cores.0x3ED00000(rproc_0_reserved) holds R5 .text + .rodata + .data + .bss + heap + stack + 32 KiB trace ring. RPMsg vrings (16 KiB each) and 256 KiB rpmsg buffer pool sit at0x3EE00000+, deliberately outside the firmware carveout so APU vring writes never collide with R5 .bss.0xF0000000covering the full LPD aperture (GIC400 at0xF9000000+ IPI at0xFF300000+ UART/QSPI/CSU at0xFF000000+). Caches stay off so the trace ring stays APU-coherent without dcache flushes.XScuGic+ IPI ISR (XPAR_PSU_IPI_1_INT_ID = 65) wakes the R5 fromwfi. Server loop drains both vrings viaremoteproc_get_notification(RSC_NOTIFY_ID_ANY)then sleeps again. R5 idles near 0% CPU between TPM commands instead of busy-polling._boot): vector table at TCM0x0000_0000(where the R5 cold-reset vector fetches), TCM-resident reset stub clears stale CP15 MPU state before jumping to DDR_entry, IRQ stub saves caller-saved + lr-4 and dispatches to_irq_dispatchin C.pmu_eemi.cissuesPM_REQUEST_NODE(NODE_QSPI=0x2D)to PMUFW over the RPU0 IPI block beforeXQspiPsu_LookupConfig, so the controller's clock + power domain are up regardless of whether Linux'sspi-zynqmp-qspidriver is enabled in DTS. Build withmake elf EXTRA_CFLAGS=-DFWTPM_NV_QSPI. Default build uses the volatile RAM HAL.WOLFTPM_V185+WOLFSSL_HAVE_MLKEM+HAVE_DILITHIUM+ SHA3/SHAKE128/256 enabled inuser_settings.h; firmware advertises full ML-KEM 512/768/1024 and ML-DSA 44/65/87 via the v1.85PT_ML_PARAMETER_SETScapability.petalinux/): system-user.dtsi with the lock-step rproc + carveouts + IPI mailbox + qspi disabled; openamp.cfg kernel fragment forREMOTEPROC + RPMSG_CHAR + ZYNQMP_IPI_MBOX; recipes-bsp/fwtpm-r5 stages the R5 ELF in/lib/firmware/; recipes-apps/fwtpm-rpmsg-test installs the smoke client. SD root onmmcblk0p4.fwtpm_rpmsg_test.c— raw TPM2 wire-format smoke (Startup / SelfTest / GetRandom / GetCapability /--pqcaddsPT_ML_PARAMETER_SETSprobe).fwtpm_pqc_test.c+build-pqc-test.sh— wolfTPM2 wrapper round-trip (ML-KEM-768 encap/decap + ML-DSA-65 sign/verify) over an rpmsgTPM2_IoCb. Reproducible cross-build of static aarch64 binary against sibling wolfssl + wolftpm with the right--enable-pqc --disable-fwtpm --disable-autodetectcombo to keep the simple 5-argTPM2HalIoCbtypedef active.Shared design points
Both ports share the same wolfTPM fwTPM core:
WOLFCRYPT_ONLY,SINGLE_THREADED,NO_FILESYSTEM,WOLFSSL_USER_IO.WOLFSSL_SP,WOLFSSL_SP_MATH_ALL,WOLFSSL_SP_SMALL,SP_WORD_SIZE=32).HASH_DRBGseeded from a platform-specific entropy callback (STM32 RNG peripheral on H5; PMU CCNT jitter on R5 — replaceable with PSU CSU TRNG via PMU mailbox in a follow-on).src/fwtpm/layer dispatches TPM2 commands and routes to wolfCrypt for crypto.Test results
STM32H5 NUCLEO-H563ZI (single-MCU, TZEN=1)
Hardware-verified on
NUCLEO-H563ZIwithtest_uart_tpm.pyover USB-UART:TPM2_Startup(SU_CLEAR)TPM2_SelfTest(NO)TPM2_GetRandom(32)TPM2_GetCapability(MANUFACTURER)ZCU102 R5 lock-step (AMP fwTPM via OpenAMP RPMsg)
Hardware-verified on a stock ZCU102 (XCZU9EG-2FFVB1156I), 2026-05-15, lock-step R5 with custom PetaLinux 2025.2 image:
remoteproc startboots R5 ELF; trace ring shows bannergic_init done->FWTPM_Init done->rpmsg readyfwtpm_rpmsg_testbaseline 4 cmds (Startup/SelfTest/GetRandom/GetCap)fwtpm_rpmsg_test --pqcadvertisesPT_ML_PARAMETER_SETS = 0x3Fwfiserver loop responds to APU rpmsg writesmmcblk0p4rootfs)R5 trace ring (verbatim, sequential):