Skip to content

Add Xilinx Zynq-7000 (ZC702) wolfBoot port#770

Open
dgarske wants to merge 1 commit intowolfSSL:masterfrom
dgarske:zynq7000
Open

Add Xilinx Zynq-7000 (ZC702) wolfBoot port#770
dgarske wants to merge 1 commit intowolfSSL:masterfrom
dgarske:zynq7000

Conversation

@dgarske
Copy link
Copy Markdown
Member

@dgarske dgarske commented May 2, 2026

Summary

Adds a wolfBoot port for the Xilinx Zynq-7000 SoC (Cortex-A9 dual-core, ARMv7-A 32-bit), verified end-to-end on the ZC702 Evaluation Kit (XC7Z020). wolfBoot replaces U-Boot in the Zynq-7000 boot flow -- BootROM loads FSBL, FSBL loads wolfBoot into DDR, wolfBoot verifies and chain-loads either a bare-metal app or a Linux kernel directly. There is no U-Boot stage. This is a distinct port from the existing ZynqMP/zynq target: different CPU architecture (A9 vs A53), different QSPI controller (XQspiPs vs XQspiPsu GQSPI), different SDHCI revision (Arasan v2.0 vs v3.0), different clock/reset infrastructure (SLCR vs CRL_APB), and a simpler boot model (FSBL -> wolfBoot, no PMUFW/BL31).

New features

  • New target TARGET=zynq7000 with full HAL, linker script, and Cortex-A9 startup support. hal/zynq7000.{c,h,ld} covers UART, QSPI, SDHCI, timer, cache, and chain-load handoff for the XC7Z020. Selected automatically via the CORTEX_A9 arch.mk block.
  • Two example configs, both verified on real ZC702 hardware, covering all four storage/payload combinations:
Config Storage Payloads Verified on hardware
config/examples/zynq7000.config QSPI NOR (16 MB N25Q128A) bare-metal AND Linux yes (cold-boot bare-metal heartbeat; Linux 6.1.70 SMP init through to rootfs panic)
config/examples/zynq7000_sdcard.config SD card (MBR) bare-metal AND Linux yes (same as above, off SD)
  • Single config covers bare-metal and Linux. With LINUX_PAYLOAD=1 MMU=1 ELF=1 set in both configs, the same wolfBoot binary boots either a signed bare-metal .bin or a signed Linux zImage, picking the right register handoff at chain-load time. Bare-metal apps don't pay any runtime cost beyond ~5 KB of unused FDT/MMU code.
  • XQspiPs driver (hal/zynq7000.c, the older Linear/Static QSPI on Z7, not the GQSPI on ZynqMP). Two paths: I/O mode for short command ops (RDID/RDSR/WREN/SE/PP) using the TXD1/TXD2/TXD3 auto-start FIFOs, and Linear/XIP mode for bulk reads via the memory-mapped 0xFC000000 window with 32-bit AXI reads + byte unpack (single-byte loads to the linear window are unreliable). Wired to ext_flash_read/write/erase; hal_flash_* are no-ops since Z7 has no internal flash.
  • Arasan SDHCI v2.0 driver hooks that translate the generic src/sdhci.c Cadence SD4HC register layout to the Arasan v2.0 standard SDHCI layout. Adds SLCR clock and reset for the SDIO0 controller, plus ARMv7 D-cache maintenance via CP15 for SDMA buffers. Handles the v2.0 quirks (3.3V-only, no UHS-I, masks UMS / 1.8V / sampling-clock / HV4E / A64 in SRS15, masks HSE in HostCtrl1).
  • Cortex-A9 Global Timer driver at PERIPHCLK = CPU_3x2x = 333.33 MHz on the default ZC702 FSBL clock plan. Feeds hal_get_timer_us() and the SDHCI driver's udelay().
  • Pure MBR SD-card layout (no GPT) for Linux/bare-metal boot off SD. The Z7 BootROM (UG821 ch.6.3) only accepts MBR with the first partition as FAT32 (type 0x0C, Active flag set) and BOOT.BIN as a regular file in that FAT32 root. wolfBoot's disk.c falls back to MBR parsing when no protective-GPT entry is present. BOOT_PART_A/BOOT_PART_B index the MBR entries (0-indexed) for the boot/update raw partitions.
  • Generic ARMv7-A startup in src/boot_arm32_start.S (was SAMA5D3-Cortex-A5-specific). Now handles per-mode stacks (IRQ/FIQ/ABT/UND/SVC), VBAR setup via cp15 c12.c0.0, SCTLR.{A,V,C,I} clearing, TLB / I-cache / branch-predictor invalidate, async-abort enable, and .data / .bss setup. Used by both SAMA5D3 (Cortex-A5) and Zynq-7000 (Cortex-A9). The previous SAMA5D3-specific startup path is retired (build-tested for SAMA5D3 regression at 22.6 KB).
  • ARM Linux boot ABI in do_boot (src/boot_arm32.c). New WOLFBOOT_LINUX_PAYLOAD #ifdef branch follows the kernel's documented register handoff: r0 = 0, r1 = ~0 (no machine ID, use DTB), r2 = DTB physical address, r3 = 0, entry point in r4. Default behaviour (legacy DTS-in-r0 for bare-metal) is preserved when the flag is unset. Single inline-asm block with proper operand and clobber annotations -- avoids the cross-asm volatile-block register lifetime problem the previous implementation had.
  • Appended-DTB Linux flow via tools/scripts/zynq7000/prepare_linux.sh. Defaults to APPENDED=1, which concatenates the DTB onto the zImage and signs the pair as one wolfBoot image. The kernel finds the DTB embedded in itself via CONFIG_ARM_APPENDED_DTB, independent of r2. This works around an ARMv7 zImage decompressor r2-loss observed on this kernel/load combo where __atags_pointer ends up 0 if we rely on the standard r2-as-DTB-pointer path. APPENDED=0 is plumbed through but currently has a known bug in shared update_ram.c (kept out of this PR -- happy to send as a follow-up).
  • Bring-up tooling under tools/scripts/zynq7000/:
    • zynq7000_qspi.bif -- bootgen template for BOOT.BIN (FSBL + wolfboot.elf), shared by all configs.
    • jtag_load.tcl -- xsdb script for JTAG-loaded development via Platform Cable II.
    • prepare_linux.sh -- signs zImage for the Linux flow (APPENDED-DTB or raw-DTB), uses a whitelisted awk parser to read partition addresses from .config (no eval, no shell-injection risk), exports IMAGE_HEADER_SIZE so the sign tool matches the running config.
    • prepare_sdcard.sh -- lays out a pure-MBR SD card (parted msdos + manual MBR type/active patch), formats p1 as FAT32, copies BOOT.BIN, dd's the signed image into raw partitions p2 and p3. Refuses /dev/sda, /dev/nvme*, /dev/mmcblk0, and non-removable block devices by default; explicit env-var overrides for the unusual cases (ALLOW_MMCBLK0=1, ALLOW_NON_REMOVABLE=1). Trims whitespace from lsblk -ndo RM output before the comparison so the removable check is robust.
  • Boot config banner in hal_init prints storage type, post-init clock, payload ABI, partition addresses, and Cortex-A9 GTimer frequency on every boot, so the UART log identifies which config the running image was built for.
  • DISK_BLOCK_SIZE=0x80000 (512 KB) in the SD config. The update_disk.c default of 512 B issues one disk_read (== one CMD17 PIO read) per 512 B chunk; for a 4.76 MB Linux zImage that's 9k+ commands and the card eventually times out (SRS12 bit 20 / EDT) under that pace. 512 KB chunks issue ~10 CMD18 SDMA transfers and complete in well under a second, matching what ZynqMP does.
  • Cortex-A9 test app at test-app/app_zynq7000.c + test-app/ARM-zynq7000.ld. Minimal banner + heartbeat dot loop over UART1 to validate the chain-load handoff, on either QSPI or SD. int main(void) __attribute__((noreturn)) for portability.
  • CI coverage: .github/workflows/test-configs.yml adds zynq7000_test and zynq7000_sdcard_test build jobs using the existing test-build.yml reusable workflow with arch: arm and the wolfboot-ci-arm container image -- same setup the SAMA5D3 build uses, no new toolchain needed.
  • Documentation: full docs/Targets.md "Xilinx Zynq-7000 (ZC702)" section covering prerequisites (Vitis settings64.sh, Platform Cable II driver install, prebuilt FSBL clone), JTAG bring-up, QSPI flashing recipe, DDR map, sample cold-boot UART output, TEST_EXT_FLASH selftest expected output, SD-card layout + Arasan v2.0 quirks, and a comparison table vs the ZynqMP port.

@dgarske dgarske self-assigned this May 2, 2026
Copilot AI review requested due to automatic review settings May 2, 2026 01:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds an initial wolfBoot port for Xilinx Zynq-7000 on the ZC702 board, extending the codebase with a new ARMv7-A / Cortex-A9 target that boots via the Xilinx FSBL, verifies images from QSPI, and chain-loads a staged payload from DDR.

Changes:

  • Adds a new zynq7000 target across the HAL, startup code, linker scripts, and build system for FSBL-loaded Cortex-A9 boot.
  • Introduces a Zynq-7000 QSPI/UART HAL, RAM-boot configuration, and a minimal test application for bring-up validation.
  • Documents the target, JTAG workflow, QSPI layout, and adds helper scripts for XSDB/bootgen usage.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tools/scripts/zc702/zc702_qspi.bif Adds a bootgen BIF template for packaging FSBL + wolfBoot into BOOT.BIN.
tools/scripts/zc702/jtag_load.tcl Adds an XSDB script for JTAG bring-up by running FSBL and loading wolfboot.elf into DDR.
test-app/app_zynq7000.c Adds a minimal bare-metal ZC702 test app that prints a boot banner and heartbeat on UART1.
test-app/Makefile Wires the new target into test-app builds with the ARM32 startup object and target linker script.
test-app/ARM-zynq7000.ld Adds the linker script for the staged Zynq-7000 test application in DDR.
src/boot_zynq7000_start.S Adds Zynq-7000-specific ARMv7-A startup, vector setup, stack initialization, and early CPU state handling.
src/boot_arm32.c Adjusts ARM32 inline assembly immediate syntax used during chain-load handoff.
hal/zynq7000.ld Adds the wolfBoot linker script for execution from DDR at the FSBL handoff address.
hal/zynq7000.h Defines Zynq-7000 register maps and bitfields for UART, QSPI, and related peripherals.
hal/zynq7000.c Implements the new Zynq-7000 HAL, including UART, QSPI external flash access, and boot-preparation logic.
docs/Targets.md Documents the new ZC702 target, configuration, memory map, JTAG flow, and expected output.
config/examples/zynq7000.config Adds an example configuration for ECC256/SHA256 RAM-boot from external QSPI flash.
arch.mk Adds target selection and Cortex-A9-specific compiler/object settings for zynq7000.
Makefile Includes the new target in the default main build outputs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread hal/zynq7000.c Outdated
@dgarske dgarske marked this pull request as ready for review May 6, 2026 22:08
@dgarske dgarske requested a review from Copilot May 6, 2026 22:08
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 9 comments.

Comment thread hal/zynq7000.c Outdated
Comment thread hal/zynq7000.c Outdated
Comment thread arch.mk Outdated
Comment thread arch.mk Outdated
Comment thread docs/Targets.md Outdated
Comment thread config/examples/zc702_sdcard.config Outdated
Comment thread tools/scripts/zc702/prepare_sdcard.sh Outdated
Comment thread tools/scripts/zc702/prepare_linux.sh Outdated
Comment thread test-app/app_zynq7000.c Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 8 comments.

Comment thread arch.mk Outdated
Comment thread test-app/ARM-zynq7000.ld Outdated
Comment thread src/boot_arm32.c
Comment thread tools/scripts/zynq7000/jtag_load.tcl
Comment thread tools/scripts/zc702/prepare_sdcard.sh Outdated
Comment thread tools/scripts/zc702/prepare_linux.sh Outdated
Comment thread docs/Targets.md Outdated
Comment thread docs/Targets.md Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 8 comments.

Comment thread test-app/Makefile
Comment thread hal/zynq7000.c
Comment thread hal/zynq7000.c
Comment thread hal/zynq7000.c
Comment thread hal/zynq7000.c
Comment thread hal/zynq7000.c
Comment thread config/examples/zynq7000_sdcard.config
Comment thread .github/workflows/test-configs.yml
@dgarske dgarske requested a review from danielinux May 8, 2026 23:39
@dgarske dgarske assigned danielinux and unassigned dgarske May 8, 2026
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.

3 participants