ZynqMP ZCU102 SD-card Linux boot: EL2 handoff, SDHCI init, QSPI hardening#750
ZynqMP ZCU102 SD-card Linux boot: EL2 handoff, SDHCI init, QSPI hardening#750dgarske wants to merge 5 commits intowolfSSL:masterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Targets reliable SD-card Linux boot on Xilinx ZynqMP (ZCU102) by improving SDHCI init timing, adding timer support, patching DT bootargs at runtime, and ensuring ARM64 Linux entry requirements are met when booting from EL2.
Changes:
- Add SDHCI delays/retries to avoid CMD0 cold-boot timeout on Arasan SDHCI.
- Add ZynqMP timer + DTB
/chosen/bootargsruntime fixup to match wolfBoot partitioning. - Add EL2 cache clean + MMU/I/D-cache disable path before jumping to Linux.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 11 comments.
| File | Description |
|---|---|
| src/sdhci.c | Adds settle delays and CMD0 retry loop to stabilize SD card initialization timing. |
| src/boot_aarch64_start.S | Introduces an EL2 cleanup/jump helper to satisfy Linux boot protocol cache/MMU requirements. |
| src/boot_aarch64.c | Calls the EL2 cleanup/jump helper when booting from EL2. |
| hal/zynq.c | Implements DTB bootargs fixup and adds a microsecond timer using the ARMv8 generic timer. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #750
Scan targets checked: wolfboot-bugs, wolfboot-consttime, wolfboot-defaults, wolfboot-mutation, wolfboot-proptest, wolfboot-src, wolfboot-zeroize
Findings: 1
1 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Findings are non-blocking.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
04f54a3 to
f4f631f
Compare
Add the pieces needed to boot Linux end-to-end from the ZCU102 SD card
with wolfBoot at EL2:
* src/boot_aarch64_start.S: new el2_flush_and_disable_mmu helper that
cleans D-cache to PoC, invalidates I-cache to PoU, and clears
SCTLR_EL2.{M,C,I}, then returns. Satisfies the ARM64 Linux boot
protocol and is also correct for any other payload that sets up its
own translation (hypervisor, RTOS, later bootloader stage).
* src/boot_aarch64.c: call el2_flush_and_disable_mmu from do_boot() on
the EL2 direct-jump path before falling through to the br x4 block.
Also pull in hal/zynq.h and hal/nxp_ls1028a.h so the EL_HYPERVISOR /
BOOT_EL1 guards compile for those targets.
* hal/zynq.c: implement hal_dts_fixup() — set /chosen/bootargs from
LINUX_BOOTARGS (with a LINUX_BOOTARGS_ROOT default of /dev/mmcblk0p4)
and grow DTB totalsize by 512 bytes to give fdt_setprop() headroom
(matches hal/versal.c). Add hal_get_timer_us() via CNTPCT_EL0.
* src/sdhci.c: add a 1 ms settling delay after sdhci_platform_init()
and a CMD0 retry loop (up to 10 x 10 ms) so the ZCU102 Arasan
controller reliably detects the card after the slot-type change +
soft reset.
* config/examples/zynqmp_sdcard.config: stay at EL2 by default (comment
out BOOT_EL1), default rootfs to /dev/mmcblk0p4, turn DEBUG off.
* hal/versal.c: correct the default LINUX_BOOTARGS_ROOT to
/dev/mmcblk0p4 to match the shipped MBR layout.
* docs/Targets.md: note the unconditional EL2 cleanup in the ZynqMP
and Versal SD-card sections.
Behavior change: non-Linux AArch64 EL2 payloads now enter with MMU
off and caches clean instead of inheriting wolfBoot's tables. No
in-tree payload relies on the old state leakage.
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #750
Scan targets checked: wolfboot-bugs, wolfboot-src
No new issues found in the changed files. ✅
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
hal/zynq.c:
- Route IOU_TAPDLY_BYPASS writes through pmu_request at EL<=2 in the
<=40 MHz and <=100 MHz branches (previously only done at <=150 MHz);
the register is equally unwritable from EL2/EL1 at lower clocks.
- Add qspi_flash_reset() (RESET_ENABLE 0x66 + RESET_MEMORY 0x99),
called per chip in qspi_init so the flash starts from a known state
regardless of what FSBL/BootROM left behind (XIP, 4-byte addr,
auto-boot).
- Drop unused 'reg' in csu_aes and 'ms' in csu_init so
-Werror=unused-variable builds (OPTIMIZATION_LEVEL=0 / DEBUG=1) pass.
hal/zynq.ld:
- Move wolfBoot ORIGIN from 0x08000000 to 0x10000000. Large FIT images
(kernel load=0x00200000, payload >~126 MB) would sweep across
0x08000000 at handoff and overwrite wolfBoot's own code.
tools/scripts/zcu102/zcu102-ca53-qspi.cmm:
- Rewrite against the Lauterbach TRACE32 ZCU102 QSPI demo: PREPAREONLY
entry mode, single/dual toggle, READ_ID_TEST, separate flash dialogs
for BOOT.BIN (offset 0) and test-app/image_v1_signed.bin.
- Document the ~128 MB TRACE32 temp-memory ceiling on FLASHFILE.Create:
larger files must be split externally and loaded in chunks.
The previous commit moved WOLFBOOT_ORIGIN from 0x8000000 to 0x10000000 to match the linker script, but WOLFBOOT_LOAD_ADDRESS is also 0x10000000. This causes wolfBoot to overwrite itself when loading the firmware image (32MB FIT written to 0x10000000 overwrites wolfBoot's .text at the same address mid-read, hanging the boot). Revert to 0x8000000 (128MB, same as U-Boot) and update linker script to match. WOLFBOOT_LOAD_ADDRESS at 0x10000000 is safely above wolfBoot's 2MB footprint at 0x8000000-0x8200000.
End-to-end fixes for booting Linux from an SD card on the ZynqMP ZCU102
with wolfBoot at EL2, plus QSPI-boot and large-FIT hardening uncovered
during bring-up.
EL2 handoff
src/boot_aarch64_start.S): newel2_flush_and_disable_mmucleans D-cache to PoC, invalidates I-cacheto PoU, clears
SCTLR_EL2.{M,C,I}. Required by the ARM64 Linux bootprotocol. Called from
do_boot()on the EL2 direct-jump path.config/examples/zynqmp_sdcard.config): default to EL2(comment out
BOOT_EL1) to match the PetaLinux U-Boot flow andpreserve KVM/hypervisor use of EL2.
Device-tree fixups
hal_dts_fixup()(hal/zynq.c): inject/chosen/bootargsfromLINUX_BOOTARGS; grow DTB totalsize by 512 bytes forfdt_setprop()headroom. Only defined whenMMU && __WOLFBOOT.hal_get_timer_us(): ARMv8 generic-timer read viaCNTPCT_EL0with a 100 MHz fallback when
CNTFRQ_EL0is not programmed.SDHCI reliability
so the Arasan controller consistently detects the card after the
slot-type change / soft reset.
SDHCI_DMA_THRESHOLDlowered to 4 KB so multi-block reads use SDMAinstead of PIO, sidestepping the Arasan BRR re-poll race under
-Os/-O2.SDHCI_DMA_BUFF_BOUNDARYauto-derived from the threshold; documentedoverride uses the raw register value (
0x7000) so it is safe inside#ifexpressions.QSPI hardening (
hal/zynq.c)qspi_flash_reset()(0x66RESET_ENABLE +0x99RESET_MEMORY)per chip in
qspi_init, so the flash starts from a known stateregardless of what FSBL/BootROM left behind (XIP, 4-byte addressing,
auto-boot probing).
IOU_TAPDLY_BYPASSwrites now route throughpmu_requestat EL≤2 inthe ≤40 MHz and ≤100 MHz branches (previously only the ≤150 MHz
branch handled this); the register is equally unwritable from EL2/EL1
at lower clocks.
Linker layout (
hal/zynq.ld)ORIGINmoved from0x08000000→0x10000000with a 2 MBreservation. Kernels loaded at
0x00200000with payloads >~126 MBwould otherwise memcpy across
0x08000000and clobber wolfBoot's own.textduring handoff.WOLFBOOT_ORIGINinconfig/examples/zynqmp_sdcard.configaligned to0x10000000to match the linker (sofactory.bin/factory.srecencode the correct load address).
TRACE32 tooling (
tools/scripts/zcu102/zcu102-ca53-qspi.cmm)PREPAREONLYentry, single/dual toggle,
READ_ID_TESTfor single-flash variants,separate dialogs for
BOOT.BINat offset 0 andtest-app/image_v1_signed.binat the partition boot address.FLASHFILE.Create: larger files must be split externally (e.g. viadd) and loaded in chunks.Versal alignment
hal/versal.cdefaultLINUX_BOOTARGS_ROOTrestored to/dev/mmcblk0p2(matching the prior Versal layout); a comment pointsto
/dev/mmcblk0p4for configs using the 4-partition OFP_A/OFP_Blayout.
hal_dts_fixup()no longer masksfdt_find_node_offseterrors —only
-FDT_ERR_NOTFOUNDfalls through tofdt_add_subnode()(applied to both
hal/zynq.candhal/versal.c).Docs (
docs/Targets.md)EL2 cleanup behavior for ZynqMP and Versal SD-card sections.
Behavior changes
inheriting wolfBoot's translation tables. No in-tree payload relies
on the old state leakage.
SDHCI_DMA_THRESHOLDlowered to 4 KB (was 512 KB): virtually allmulti-block reads go through SDMA.
ORIGINis 0x10000000 (was 0x08000000) onhal/zynq.ld;WOLFBOOT_ORIGINinzynqmp_sdcard.configfollows.Verification
Load address 0x10000000, kernel brings up rootfs on/dev/mmcblk0p4.zynqmp.config,zynqmp_sdcard.config,versal_vmk180.config,versal_vmk180_sdcard.configall build clean(via
.github/workflows/test-configs.yml).