Skip to content

Commit 36fd5d3

Browse files
committed
Support for wolfBoot ZynqMP (UltraScale+ MPSoC) SD Card
1 parent 2277dfa commit 36fd5d3

File tree

12 files changed

+838
-33
lines changed

12 files changed

+838
-33
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,3 +343,4 @@ image.ub
343343
*.pdi
344344
system-default.dtb
345345
test_output/
346+
sdcard.img

arch.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ ifeq ($(ARCH),AARCH64)
7878
HASH_HAL=1
7979
CFLAGS+=-DWOLFBOOT_ZYNQMP_CSU
8080
endif
81+
8182
endif
8283

8384
ifeq ($(TARGET),versal)
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# wolfBoot configuration for AMD ZynqMP ZCU102 - SD Card Boot
2+
# Zynq UltraScale+ MPSoC ZU9EG - Quad-core ARM Cortex-A53
3+
#
4+
# This configuration enables SD card boot for the ZynqMP:
5+
# FSBL -> PMUFW -> BL31 (EL3) -> wolfBoot (EL2) -> Linux (EL1)
6+
#
7+
# wolfBoot loads firmware images from MBR partitions on SD card.
8+
# Uses the generic SDHCI driver with SD1 controller (external SD slot on ZCU102).
9+
10+
ARCH?=AARCH64
11+
TARGET?=zynq
12+
13+
WOLFBOOT_VERSION?=0
14+
15+
# RSA 4096-bit with SHA3-384 (matching existing zynqmp.config)
16+
SIGN?=RSA4096
17+
HASH?=SHA3
18+
IMAGE_HEADER_SIZE?=1024
19+
20+
# Debug options
21+
DEBUG?=1
22+
DEBUG_SYMBOLS=1
23+
DEBUG_UART=1
24+
CFLAGS_EXTRA+=-DDEBUG_ZYNQ=1
25+
26+
# SD card support - use SDHCI driver
27+
DISK_SDCARD?=1
28+
DISK_EMMC?=0
29+
# ZynqMP Arasan SDHCI does not support CDSS/CDTL card detect test level.
30+
# Since FSBL booted from the same SD card, we know it is present.
31+
CFLAGS_EXTRA+=-DSDHCI_FORCE_CARD_DETECT
32+
# Note: Arasan SDHCI v3.0 does not support HV4E mode. The platform layer
33+
# in hal/zynq.c transparently redirects SRS22/SRS23 to SRS00 for legacy SDMA.
34+
35+
# Disable QSPI flash when using SD card
36+
EXT_FLASH?=0
37+
NO_XIP=1
38+
39+
# ELF loading support
40+
ELF?=1
41+
42+
# Boot Exception Level: transition from EL2 -> EL1 before jumping to app
43+
BOOT_EL1?=1
44+
45+
# General options
46+
VTOR?=1
47+
CORTEX_M0?=0
48+
NO_ASM?=0
49+
ALLOW_DOWNGRADE?=0
50+
NVM_FLASH_WRITEONCE?=0
51+
V?=0
52+
SPMATH?=1
53+
RAM_CODE?=0
54+
DUALBANK_SWAP?=0
55+
PKA?=0
56+
WOLFTPM?=0
57+
58+
# Toolchain
59+
USE_GCC=1
60+
CROSS_COMPILE=aarch64-none-elf-
61+
62+
# ============================================================================
63+
# Partition Layout - MBR
64+
# ============================================================================
65+
# SD Card partition layout (MBR):
66+
# Partition 1: boot (128MB, FAT32 LBA, bootable) - BOOT.BIN
67+
# Partition 2: OFP_A (200MB, Linux) - Primary signed image
68+
# Partition 3: OFP_B (200MB, Linux) - Update signed image
69+
# Partition 4: rootfs (remainder) - Linux root filesystem
70+
#
71+
# Use partition numbers instead of flash addresses
72+
# These are 0-based indices into the parsed partition array:
73+
# part[0]=boot, part[1]=OFP_A, part[2]=OFP_B, part[3]=rootfs
74+
WOLFBOOT_NO_PARTITIONS=1
75+
CFLAGS_EXTRA+=-DBOOT_PART_A=1
76+
CFLAGS_EXTRA+=-DBOOT_PART_B=2
77+
78+
# Disk read chunk size (512KB)
79+
CFLAGS_EXTRA+=-DDISK_BLOCK_SIZE=0x80000
80+
81+
# Linux rootfs is on partition 4 (SD1 = mmcblk1)
82+
CFLAGS_EXTRA+=-DLINUX_BOOTARGS_ROOT=\"/dev/mmcblk1p4\"
83+
84+
# ============================================================================
85+
# Boot Memory Layout
86+
# ============================================================================
87+
# wolfBoot runs from DDR at 0x8000000 (same as U-Boot, loaded via BL31)
88+
WOLFBOOT_ORIGIN=0x8000000
89+
90+
# Load Partition to RAM Address (Linux kernel loads here)
91+
WOLFBOOT_LOAD_ADDRESS?=0x10000000
92+
93+
# DTS (Device Tree) load address
94+
WOLFBOOT_LOAD_DTS_ADDRESS?=0x1000
95+
96+
# ============================================================================
97+
# Required for test-app (even with WOLFBOOT_NO_PARTITIONS=1)
98+
# ============================================================================
99+
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80200000
100+
WOLFBOOT_PARTITION_SIZE=0x4000000
101+
WOLFBOOT_SECTOR_SIZE=0x1000
102+
103+
# ============================================================================
104+
# Optional Debug Options (uncomment to enable)
105+
# ============================================================================
106+
# SDHCI driver debug logs
107+
#CFLAGS_EXTRA+=-DDEBUG_SDHCI
108+
# Disk layer debug logs
109+
#CFLAGS_EXTRA+=-DDEBUG_DISK
110+
# GPT partition debug logs
111+
#CFLAGS_EXTRA+=-DDEBUG_GPT
112+
# Disk read/write test at boot
113+
#CFLAGS_EXTRA+=-DDISK_TEST

docs/Targets.md

Lines changed: 216 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,28 +1984,50 @@ qemu-system-aarch64 -M raspi3b -m 1024 -serial stdio -kernel wolfboot_linux_rasp
19841984

19851985
## Xilinx Zynq UltraScale
19861986

1987-
Xilinx UltraScale+ ZCU102 (Aarch64)
1987+
AMD Zynq UltraScale+ MPSoC ZCU102 Evaluation Kit - Quad-core ARM Cortex-A53 (plus dual Cortex-R5).
19881988

1989-
See example .config file at `config/examples/zynqmp.config`.
1990-
1991-
Example build options (.config):
1989+
wolfBoot replaces U-Boot in the ZynqMP boot flow:
19921990
```
1993-
TARGET=zynq
1994-
ARCH=AARCH64
1995-
SIGN=RSA4096
1996-
HASH=SHA3
1991+
FSBL -> PMUFW -> BL31 (EL3) -> wolfBoot (EL2) -> Linux (EL1)
19971992
```
19981993

1999-
### Building Zynq with Xilinx tools (Vitis IDE)
1994+
wolfBoot runs from DDR at `0x8000000` (128MB, EL2, non-secure) for both QSPI and SD card boot. All clock, MIO, and DDR initialization is handled by the FSBL/PMUFW before wolfBoot starts.
1995+
1996+
This target supports **two boot paths**:
1997+
- **QSPI boot** (primary, production-style): `config/examples/zynqmp.config`
1998+
- **SD card boot** (MBR, A/B images): `config/examples/zynqmp_sdcard.config`
1999+
2000+
### Prerequisites
2001+
2002+
1. **Xilinx Vitis 2024.1 or newer**
2003+
- Set `VITIS_PATH` environment variable: `export VITIS_PATH=/opt/Xilinx/Vitis/2024.1`
2004+
2. **Toolchain**: `aarch64-none-elf-gcc`
2005+
3. **Pre-built firmware** (FSBL, PMUFW, BL31):
2006+
```sh
2007+
git clone --branch xlnx_rel_v2024.2 https://github.com/Xilinx/soc-prebuilt-firmware.git
2008+
export PREBUILT_DIR=$(pwd)/../soc-prebuilt-firmware/zcu102-zynqmp
2009+
```
2010+
2011+
### Configuration Options
2012+
2013+
Key configuration options:
2014+
2015+
- `ARCH=AARCH64` - ARM 64-bit architecture
2016+
- `TARGET=zynq` - ZynqMP platform target
2017+
- `SIGN=RSA4096` - RSA 4096-bit signatures
2018+
- `HASH=SHA3` - SHA3-384 hashing
2019+
- `ELF=1` - ELF loading support
2020+
2021+
### Building with Xilinx tools (Vitis IDE)
20002022

20012023
See [IDE/XilinxSDK/README.md](/IDE/XilinxSDK/README.md) for using Xilinx IDE
20022024

2003-
### Building Zynq with gcc-aarch64-linux-gnu
2025+
### Building with gcc-aarch64-linux-gnu
20042026

20052027
Requires `gcc-aarch64-linux-gnu` package.
20062028
Use `make CROSS_COMPILE=aarch64-linux-gnu-`
20072029

2008-
### Building Zynq with QNX
2030+
### Building with QNX
20092031

20102032
```sh
20112033
source ~/qnx700/qnxsdp-env.sh
@@ -2014,17 +2036,197 @@ make clean
20142036
make CROSS_COMPILE=aarch64-unknown-nto-qnx7.0.0-
20152037
```
20162038

2017-
#### Testing Zynq with QEMU
2039+
### QSPI Boot (default)
2040+
2041+
Use `config/examples/zynqmp.config`.
2042+
2043+
```sh
2044+
cp config/examples/zynqmp.config .config
2045+
make clean
2046+
make
2047+
```
2048+
2049+
**QSPI layout**
2050+
| Partition | Size | Address | Description |
2051+
|-------------|--------|-------------|--------------------------------|
2052+
| Bootloader | - | 0x8000000 | wolfBoot in DDR (loaded by FSBL) |
2053+
| Primary | 42MB | 0x800000 | Boot partition in QSPI |
2054+
| Update | 42MB | 0x3A00000 | Update partition in QSPI |
2055+
| Swap | - | 0x63E0000 | Swap area in QSPI |
2056+
2057+
**Build BOOT.BIN for QSPI**
2058+
2059+
See [IDE/XilinxSDK/README.md](/IDE/XilinxSDK/README.md) for creating BOOT.BIN with the Xilinx IDE, or use the existing BIF file:
2060+
2061+
```sh
2062+
cp ${PREBUILT_DIR}/zynqmp_fsbl.elf .
2063+
cp ${PREBUILT_DIR}/pmufw.elf .
2064+
cp ${PREBUILT_DIR}/bl31.elf .
2065+
2066+
source ${VITIS_PATH}/settings64.sh
2067+
bootgen -arch zynqmp -image ./IDE/XilinxSDK/boot.bif -w -o BOOT.BIN
2068+
```
2069+
2070+
**Signing**
20182071

2072+
```sh
2073+
tools/keytools/sign --rsa4096 --sha3 /path/to/vmlinux.bin wolfboot_signing_private_key.der 1
20192074
```
2075+
2076+
**Testing with QEMU**
2077+
2078+
```sh
20202079
qemu-system-aarch64 -machine xlnx-zcu102 -cpu cortex-a53 -serial stdio -display none \
20212080
-device loader,file=wolfboot.bin,cpu-num=0
2081+
```
20222082

2083+
### SD Card Boot (MBR + A/B)
2084+
2085+
Use `config/examples/zynqmp_sdcard.config`. This uses the Arasan SDHCI controller (SD1 - external SD card slot on ZCU102) and an **MBR** partitioned SD card.
2086+
2087+
**Partition layout**
2088+
| Partition | Name | Size | Type | Contents |
2089+
|-----------|--------|-----------|-------------------------------|-------------------------------------------|
2090+
| 1 | boot | 128MB | FAT32 LBA (0x0c), bootable | BOOT.BIN (FSBL + PMUFW + BL31 + wolfBoot) |
2091+
| 2 | OFP_A | 200MB | Linux (0x83) | Primary signed firmware image |
2092+
| 3 | OFP_B | 200MB | Linux (0x83) | Update signed firmware image |
2093+
| 4 | rootfs | remainder | Linux (0x83) | Linux root filesystem |
2094+
2095+
**Build wolfBoot + sign test images**
2096+
```sh
2097+
cp config/examples/zynqmp_sdcard.config .config
2098+
make clean
2099+
make
2100+
2101+
make test-app/image.bin
2102+
IMAGE_HEADER_SIZE=1024 ./tools/keytools/sign --rsa4096 --sha3 test-app/image.elf wolfboot_signing_private_key.der 1
2103+
IMAGE_HEADER_SIZE=1024 ./tools/keytools/sign --rsa4096 --sha3 test-app/image.elf wolfboot_signing_private_key.der 2
20232104
```
20242105

2025-
#### Signing Zynq
2106+
**Build BOOT.BIN for SD card**
2107+
2108+
Copy the pre-built firmware and generate BOOT.BIN:
2109+
2110+
```sh
2111+
cp ${PREBUILT_DIR}/zynqmp_fsbl.elf .
2112+
cp ${PREBUILT_DIR}/pmufw.elf .
2113+
cp ${PREBUILT_DIR}/bl31.elf .
2114+
2115+
source ${VITIS_PATH}/settings64.sh
2116+
bootgen -arch zynqmp -image ./tools/scripts/zynqmp_sd_boot.bif -w -o BOOT.BIN
2117+
```
20262118

2027-
`tools/keytools/sign --rsa4096 --sha3 /srv/linux-rpi4/vmlinux.bin wolfboot_signing_private_key.der 1`
2119+
The BIF file (`zynqmp_sd_boot.bif`) configures the boot chain:
2120+
- FSBL at A53-0 (bootloader)
2121+
- PMUFW at PMU
2122+
- BL31 at EL3 with TrustZone
2123+
- wolfBoot at EL2
2124+
2125+
**Create SD image**
2126+
```sh
2127+
dd if=/dev/zero of=sdcard.img bs=1M count=1024
2128+
sfdisk sdcard.img <<EOF
2129+
label: dos
2130+
unit: sectors
2131+
2132+
1 : start=2048, size=128M, type=c, bootable
2133+
2 : size=200M, type=83
2134+
3 : size=200M, type=83
2135+
4 : type=83
2136+
EOF
2137+
2138+
SECTOR2=$(sfdisk -d sdcard.img | awk '/sdcard.img2/ {for (i=1;i<=NF;i++) if ($i ~ /start=/) {gsub(/start=|,/, "", $i); print $i}}')
2139+
SECTOR3=$(sfdisk -d sdcard.img | awk '/sdcard.img3/ {for (i=1;i<=NF;i++) if ($i ~ /start=/) {gsub(/start=|,/, "", $i); print $i}}')
2140+
dd if=test-app/image_v1_signed.bin of=sdcard.img bs=512 seek=$SECTOR2 conv=notrunc
2141+
dd if=test-app/image_v2_signed.bin of=sdcard.img bs=512 seek=$SECTOR3 conv=notrunc
2142+
```
2143+
2144+
**Provision SD card**
2145+
```sh
2146+
sudo dd if=sdcard.img of=/dev/sdX bs=4M status=progress conv=fsync
2147+
sync
2148+
sudo mkfs.vfat -F 32 -n BOOT /dev/sdX1
2149+
sudo mount /dev/sdX1 /mnt
2150+
sudo cp BOOT.BIN /mnt/
2151+
sudo umount /mnt
2152+
sudo fdisk -l /dev/sdX
2153+
```
2154+
2155+
Or just mount and copy the BOOT.BIN and "dd" the partitions
2156+
2157+
```sh
2158+
# Mount the FAT boot partition and copy just the updated BOOT.BIN
2159+
sudo mount /dev/sdX1 /mnt && sudo cp BOOT.BIN /mnt/ && sudo umount /mnt && sync
2160+
2161+
# Write the signed image to partition 2 (P:A) and partition 3 (P:B)
2162+
sudo dd if=test-app/image_v1_signed.bin of=/dev/sdX2 bs=4k
2163+
sudo dd if=test-app/image_v1_signed.bin of=/dev/sdX3 bs=4k
2164+
```
2165+
2166+
**Boot Mode**
2167+
2168+
Set the ZCU102 boot mode switches (SW6) for SD card boot:
2169+
2170+
| Boot Mode | MODE Pins 3:0 | SW6[4:1] |
2171+
| --------- | ------------- | -------------- |
2172+
| JTAG | 0 0 0 0 | on, on, on, on |
2173+
| QSPI32 | 0 0 1 0 | on, on, off,on |
2174+
| SD1 | 1 1 1 0 | off,off,off,on |
2175+
2176+
**Debug**
2177+
2178+
Enable SDHCI debug output by uncommenting in the config:
2179+
```
2180+
CFLAGS_EXTRA+=-DDEBUG_SDHCI
2181+
CFLAGS_EXTRA+=-DDEBUG_DISK
2182+
```
2183+
2184+
**Example Boot Output**
2185+
2186+
```
2187+
wolfBoot Secure Boot
2188+
Current EL: 2
2189+
PMUFW Ver: 1.1
2190+
SDHCI: SDCard mode
2191+
Reading MBR...
2192+
Found MBR partition table
2193+
MBR part 1: type=0x0C, start=0x100000, size=128MB
2194+
MBR part 2: type=0x83, start=0x8100000, size=200MB
2195+
MBR part 3: type=0x83, start=0x14900000, size=200MB
2196+
MBR part 4: type=0x83, start=0x21100000, size=71MB
2197+
Total partitions on disk0: 4
2198+
Checking primary OS image in 0,1...
2199+
Checking secondary OS image in 0,2...
2200+
Versions, A:1 B:1
2201+
Load address 0x10000000
2202+
Attempting boot from P:A
2203+
Boot partition: 0x8038AA0 (sz 211096, ver 0x1, type 0x401)
2204+
Loading image from disk...done
2205+
Boot partition: 0x8038AA0 (sz 211096, ver 0x1, type 0x401)
2206+
Checking image integrity...done
2207+
Verifying image signature...done
2208+
Firmware Valid.
2209+
Loading elf at 0x10000000
2210+
Found valid elf64 (little endian)
2211+
Program Headers 1 (size 56)
2212+
Load 29888 bytes (offset 0x10000) to 0x10000000 (p 0x10000000)
2213+
Clear 17540 bytes at 0x10000000 (p 0x10000000)
2214+
Entry point 0x10000000
2215+
Booting at 10000000
2216+
do_boot: entry=0x10000000, EL=2
2217+
do_boot: dts=0x00000000
2218+
2219+
2220+
===========================================
2221+
wolfBoot Test Application - AMD ZynqMP
2222+
===========================================
2223+
2224+
Current EL: 2
2225+
Boot mode: Disk-based (MBR partitions)
2226+
Application running successfully!
2227+
2228+
Entering idle loop...
2229+
```
20282230

20292231

20302232
## Versal Gen 1 VMK180
@@ -2313,7 +2515,6 @@ make test-app/image.bin
23132515
dd if=/dev/zero of=sdcard.img bs=1M count=1024
23142516
sfdisk sdcard.img <<EOF
23152517
label: dos
2316-
unit: sectors
23172518
23182519
1 : start=2048, size=128M, type=c, bootable
23192520
2 : size=200M, type=83

0 commit comments

Comments
 (0)