Skip to content

Add wolfTPM fwTPM on AMD Zynq-7000 Cortex-A9 (ZC702) with wolfCrypt SRAM PUF - #7

Open
dgarske wants to merge 1 commit into
mainfrom
zc702
Open

Add wolfTPM fwTPM on AMD Zynq-7000 Cortex-A9 (ZC702) with wolfCrypt SRAM PUF#7
dgarske wants to merge 1 commit into
mainfrom
zc702

Conversation

@dgarske

@dgarske dgarske commented Aug 13, 2026

Copy link
Copy Markdown
Member

Summary

A bare-metal firmware-TPM 2.0 server (wolfTPM fwtpm) running on a single Cortex-A9 of an AMD Zynq-7000 (ZC702), driven from a host over UART with the same raw swtpm + Microsoft-simulator ("mssim") framing as the existing STM32H5 and Mi-V ports, so the stock wolfTPM swtpm client drives it unmodified.

Distinguishing feature: PUF-derived NV integrity key

The TPM NV-journal integrity key is a device-unique key derived from the Cortex-A9 on-chip-memory (OCM) SRAM power-on state, using wolfCrypt's configurable SRAM PUF (a BCH(127,k,t) fuzzy extractor plus HKDF). No root key is stored in flash - it is regenerated from silicon on each boot. Persistent NV and the PUF helper data live in QSPI flash (-DFWTPM_NV_QSPI).

What is included

  • Self-contained bare-metal A9 HAL (wolfSSL-authored, no vendor BSP): polled Cadence UART console, MPCore Global Timer time base and A9 cycle-counter entropy timer, SVC reset/startup with cache/VFP bring-up, and a flat MMU map (required for correct printf).
  • fwTPM HAL wiring: clock (Global Timer), NV backends (volatile RAM default, persistent QSPI opt-in), and the OCM SRAM PUF integrity-key source, plus a synthetic PUF regression (-DFWTPM_PUF_SELFTEST) with selectable BCH profile.
  • Host-side clients (swtpm bridge, caps/PCR/GetRandom, NV persistence check) and a hello sanity image.
  • Optional post-quantum build (-DFWTPM_ENABLE_PQC) for an ECC + ML-DSA / ML-KEM TPM instead of the default RSA + ECC.

Hardware validation

Validated on the ZC702 bench over JTAG (prebuilt FSBL does ps7_init, app loaded over the top): fwTPM boots, self-test passes, and the SRAM PUF regenerates a stable device-unique integrity key across boots.

Notes

Self-contained bare-metal server model (the dual-A9 second core and PetaLinux are not used; the coprocessor + Linux-client model is the separate ZCU102 R5 example). No vendor BSP is redistributed; wolfSSL and wolfTPM are consumed as sibling source trees.

@dgarske dgarske self-assigned this Aug 13, 2026
Copilot AI lite review requested due to automatic review settings August 13, 2026 20:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Adds a bare-metal wolfTPM fwTPM server port for AMD Zynq-7000 (ZC702) Cortex-A9, including a sibling “hello” bring-up image and host-side UART tooling, with optional QSPI-backed NV storage and an SRAM-PUF–derived NV integrity key.

Changes:

  • Introduces Zynq-7000 bare-metal HAL (startup, MMU, UART, timers, newlib retarget) plus a hello-world heartbeat image.
  • Adds fwTPM firmware (UART swtpm/mssim framing), SRAM PUF integration (incl. synthetic selftest), and NV backends (RAM default, QSPI optional).
  • Adds host-side Python utilities (swtpm TCP↔UART bridge, UART functional test, NV persistence test) and documentation.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
Xilinx/fwtpm-zc702-a9/firmware/hello/zynq7000-ddr.ld Adds DDR linker script for hello-world image.
Xilinx/fwtpm-zc702-a9/firmware/hello/main.c Implements UART banner + global-timer heartbeat sanity test.
Xilinx/fwtpm-zc702-a9/firmware/hello/Makefile Builds the hello-world image with the common HAL.
Xilinx/fwtpm-zc702-a9/firmware/fwtpm-a9/zynq7000-fwtpm.ld Adds DDR linker script sized for fwTPM (larger heap/stack).
Xilinx/fwtpm-zc702-a9/firmware/fwtpm-a9/user_settings.h Defines wolfSSL/wolfTPM build configuration for bare-metal + PUF/MemUse.
Xilinx/fwtpm-zc702-a9/firmware/fwtpm-a9/main.c Implements fwTPM init, self-test, and UART swtpm/mssim command server.
Xilinx/fwtpm-zc702-a9/firmware/fwtpm-a9/host-client/swtpm_uart_bridge.py Adds TCP mssim ↔ UART bridge for existing wolfTPM swtpm clients.
Xilinx/fwtpm-zc702-a9/firmware/fwtpm-a9/host-client/fwtpm_uart_test.py Adds direct UART functional test client (caps/PCR/random).
Xilinx/fwtpm-zc702-a9/firmware/fwtpm-a9/host-client/fwtpm_nv_persist_test.py Adds TPM NV persistence test over UART.
Xilinx/fwtpm-zc702-a9/firmware/fwtpm-a9/fwtpm_puf_selftest.c Adds on-target synthetic SRAM PUF regression (build-time opt-in).
Xilinx/fwtpm-zc702-a9/firmware/fwtpm-a9/fwtpm_puf.h Declares PUF init/key hook + helper persistence seam.
Xilinx/fwtpm-zc702-a9/firmware/fwtpm-a9/fwtpm_puf.c Implements OCM SRAM PUF enroll/reconstruct and integrity-key derivation.
Xilinx/fwtpm-zc702-a9/firmware/fwtpm-a9/fwtpm_nv_ram.c Implements volatile RAM-backed NV HAL.
Xilinx/fwtpm-zc702-a9/firmware/fwtpm-a9/fwtpm_nv_qspi.c Implements QSPI-backed NV HAL + persistent PUF helper store.
Xilinx/fwtpm-zc702-a9/firmware/fwtpm-a9/fwtpm_clock_zynq.c Implements fwTPM clock HAL + sleep shim + entropy timer.
Xilinx/fwtpm-zc702-a9/firmware/fwtpm-a9/Makefile Builds fwTPM image from sibling wolfSSL/wolfTPM source trees.
Xilinx/fwtpm-zc702-a9/firmware/common/zynq_uart.h Declares minimal polled Cadence UART API.
Xilinx/fwtpm-zc702-a9/firmware/common/zynq_uart.c Implements polled Cadence UART driver (+ optional baud configuration).
Xilinx/fwtpm-zc702-a9/firmware/common/zynq_time.h Declares Global Timer + PMU cycle-counter timing API.
Xilinx/fwtpm-zc702-a9/firmware/common/zynq_time.c Implements Global Timer ticks/ms/delays and PMU cycle counter enable/read.
Xilinx/fwtpm-zc702-a9/firmware/common/zynq7000.h Adds Zynq-7000 address/clock definitions (UART, timers, QSPI, OCM).
Xilinx/fwtpm-zc702-a9/firmware/common/startup.S Adds bare-metal A9 reset/startup: vectors, stacks, cache/MMU/VFP, BSS, main.
Xilinx/fwtpm-zc702-a9/firmware/common/retarget.c Adds newlib syscall stubs (stdio→UART, _sbrk heap, gettimeofday).
Xilinx/fwtpm-zc702-a9/firmware/common/mmu.c Adds minimal 1MB-section MMU mapping enabling Normal DDR for printf correctness.
Xilinx/fwtpm-zc702-a9/README.md Adds ZC702 fwTPM build/run docs and design notes.
Xilinx/fwtpm-zc702-a9/.gitignore Ignores build artifacts and Python cache files for the new port.
README.md Links the new ZC702 port from the repo root README.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


uint64_t zynq_millis(void)
{
return zynq_global_ticks() / (uint64_t)(ZYNQ_GLOBAL_TIMER_FREQ / 1000u);
Comment on lines +216 to +221
if (cmdSize < 10 || cmdSize > FWTPM_MAX_COMMAND_SIZE) {
if (cmdSize > 10U) {
UartDrain(cmdSize - 10U);
}
UartSend(g_tpmRcFailure, sizeof(g_tpmRcFailure));
continue;
Comment on lines +286 to +294
cmdSize = LoadU32BE(hdr);
if (cmdSize == 0 || cmdSize > FWTPM_MAX_COMMAND_SIZE) {
if (cmdSize > 0U) {
UartDrain(cmdSize);
}
StoreU32BE(rspHdr, 0);
UartSend(rspHdr, 4);
UartSendAck();
continue;
Comment on lines +237 to +246
static int spi_flash_wait_ready(void)
{
uint8_t status = 0xFF;
do {
if (spi_flash_status(&status) != 0) {
return -1;
}
} while ((status & SPI_STATUS_WIP) != 0);
return 0;
}
Comment on lines +268 to +271
static int qspi_addr_safe(uint32_t address)
{
return (address >= FWTPM_QSPI_MIN_SAFE);
}
Comment thread Xilinx/fwtpm-zc702-a9/README.md Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants