From 32f720be45db9e47cab4c7259a07adc1714b1606 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 5 Aug 2026 09:49:59 -0700 Subject: [PATCH 1/3] Add Altera Agilex 5 TF-A boot port --- .github/workflows/test-build-agilex5.yml | 22 ++ .github/workflows/test-configs.yml | 6 + arch.mk | 13 +- config/examples/agilex5_013b_sdcard.config | 61 ++++ docs/Agilex5.md | 99 ++++++ docs/Targets.md | 20 ++ hal/agilex5.c | 339 +++++++++++++++++++++ hal/agilex5.h | 81 +++++ hal/agilex5.its | 39 +++ hal/agilex5.ld | 132 ++++++++ include/sdhci.h | 13 +- src/boot_aarch64.c | 2 + src/boot_aarch64_start.S | 25 +- src/sdhci.c | 46 ++- src/update_disk.c | 10 +- test-app/app_agilex5.c | 56 ++++ 16 files changed, 953 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/test-build-agilex5.yml create mode 100644 config/examples/agilex5_013b_sdcard.config create mode 100644 docs/Agilex5.md create mode 100644 hal/agilex5.c create mode 100644 hal/agilex5.h create mode 100644 hal/agilex5.its create mode 100644 hal/agilex5.ld create mode 100644 test-app/app_agilex5.c diff --git a/.github/workflows/test-build-agilex5.yml b/.github/workflows/test-build-agilex5.yml new file mode 100644 index 0000000000..08e6730448 --- /dev/null +++ b/.github/workflows/test-build-agilex5.yml @@ -0,0 +1,22 @@ +name: Agilex 5 wolfBoot build + +on: + workflow_dispatch: + pull_request: + paths: + - 'arch.mk' + - 'config/examples/agilex5_013b_sdcard.config' + - 'hal/agilex5.*' + - 'include/sdhci.h' + - 'src/boot_aarch64*' + - 'src/sdhci.c' + - 'src/update_disk.c' + - 'test-app/app_agilex5.c' + - '.github/workflows/test-build-agilex5.yml' + +jobs: + build: + uses: ./.github/workflows/test-build-aarch64.yml + with: + arch: aarch64 + config-file: ./config/examples/agilex5_013b_sdcard.config diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index be2a063c29..4de0c85fb7 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -8,6 +8,12 @@ on: jobs: + agilex5_test: + uses: ./.github/workflows/test-build-aarch64.yml + with: + arch: aarch64 + config-file: ./config/examples/agilex5_013b_sdcard.config + cypsoc6_test: uses: ./.github/workflows/test-build-psoc6.yml with: diff --git a/arch.mk b/arch.mk index 6838b57ae0..dbaba538f9 100644 --- a/arch.mk +++ b/arch.mk @@ -155,6 +155,17 @@ ifeq ($(ARCH),AARCH64) CFLAGS_EXTRA+=-DSDHCI_SDMA_DISABLED endif + ifeq ($(TARGET),agilex5) + # Altera Agilex 5: Cortex-A55, entered as non-secure BL33 at EL2 by + # the GSRD TF-A BL31 image. SPL owns DDR, clocks, pinmux and resets. + ARCH_FLAGS=-mcpu=cortex-a55+crypto -march=armv8.2-a+crypto \ + -mtune=cortex-a55 + CFLAGS+=$(ARCH_FLAGS) -DCORTEX_A55 + CFLAGS+=-DWOLFBOOT_DUALBOOT -DWOLFBOOT_UBOOT_LEGACY + # BL31 owns GICv3 and secondary-core/PSCI setup. Do not touch RVBAR. + CFLAGS+=-DSKIP_RVBAR=1 -DSKIP_GIC_INIT=1 + endif + ifeq ($(TARGET),nxp_ls1028a) ARCH_FLAGS=-mcpu=cortex-a72+crypto -march=armv8-a+crypto -mtune=cortex-a72 CFLAGS+=$(ARCH_FLAGS) -DCORTEX_A72 @@ -174,7 +185,7 @@ ifeq ($(ARCH),AARCH64) endif # Default ARM ASM setting for unrecognized AARCH64 targets - ifeq ($(filter zynq versal nxp_ls1028a,$(TARGET)),) + ifeq ($(filter zynq versal agilex5 nxp_ls1028a,$(TARGET)),) NO_ARM_ASM?=1 endif diff --git a/config/examples/agilex5_013b_sdcard.config b/config/examples/agilex5_013b_sdcard.config new file mode 100644 index 0000000000..681b9e51f3 --- /dev/null +++ b/config/examples/agilex5_013b_sdcard.config @@ -0,0 +1,61 @@ +# wolfBoot configuration for Altera Agilex 5 DK-A5E013BM16AEA (013B) +# +# SDM -> U-Boot SPL -> TF-A BL31 -> wolfBoot BL33/EL2 -> signed Linux FIT + +ARCH?=AARCH64 +TARGET?=agilex5 +WOLFBOOT_VERSION?=1 + +SIGN?=RSA4096 +HASH?=SHA3 +IMAGE_HEADER_SIZE?=1024 + +DEBUG?=1 +DEBUG_SYMBOLS=1 +DEBUG_UART=1 + +DISK_SDCARD?=1 +DISK_EMMC?=0 +EXT_FLASH?=0 +NO_XIP=1 +ELF?=1 +GZIP?=1 + +VTOR?=1 +NO_ASM?=0 +ALLOW_DOWNGRADE?=0 +NVM_FLASH_WRITEONCE?=0 +SPMATH?=1 +RAM_CODE?=0 +DUALBANK_SWAP?=0 +PKA?=0 +WOLFTPM?=0 + +USE_GCC=1 +CROSS_COMPILE?=aarch64-none-elf- + +# SPL/BL31 load this binary in place of U-Boot proper. These values must match +# the u-boot.itb BL33 load and entry properties. +WOLFBOOT_ORIGIN=0x80200000 + +# Signed payload staging, extracted Linux Image, and DTB do not overlap. +WOLFBOOT_LOAD_ADDRESS?=0x90000000 +WOLFBOOT_LOAD_DTS_ADDRESS?=0x8f000000 +WOLFBOOT_RAMBOOT_MAX_SIZE?=0x10000000 + +# MBR: p1 FAT boot, p2 signed A, p3 signed B, p4 Linux rootfs. +WOLFBOOT_NO_PARTITIONS=1 +CFLAGS_EXTRA+=-DBOOT_PART_A=1 -DBOOT_PART_B=2 +CFLAGS_EXTRA+=-DDISK_BLOCK_SIZE=0x80000 +CFLAGS_EXTRA+=-DLINUX_BOOTARGS_ROOT=\"/dev/mmcblk0p4\" + +# SD6HC uses SDMA for cache-coherent multi-block transfers. +CFLAGS_EXTRA+=-DSDHCI_FORCE_CARD_DETECT + +# Required by generic config checks even though disk partitions select A/B. +WOLFBOOT_PARTITION_BOOT_ADDRESS=0x90000000 +WOLFBOOT_PARTITION_SIZE=0x0c800000 +WOLFBOOT_SECTOR_SIZE=0x1000 + +# Uncomment during storage bring-up. +#CFLAGS_EXTRA+=-DDEBUG_SDHCI -DDEBUG_DISK diff --git a/docs/Agilex5.md b/docs/Agilex5.md new file mode 100644 index 0000000000..90362a7dcd --- /dev/null +++ b/docs/Agilex5.md @@ -0,0 +1,99 @@ +# Altera Agilex 5 + +The Agilex 5 port follows wolfBoot's established Cortex-A TF-A model. It does +not replace the platform first stage or TF-A: + +```text +SDM -> U-Boot SPL -> TF-A BL31/EL3 -> wolfBoot BL33/EL2 -> signed Linux FIT +``` + +SPL remains responsible for DDR, clocks, resets, pinmux, the SD6HC PHY and +loading the signed U-Boot FIT. BL31 remains responsible for EL3, GICv3, PSCI, +secondary CPUs and security-controller setup. The U-Boot-proper payload in the +FIT is replaced with `wolfboot.bin` at load/entry address `0x80200000`. + +## Build + +Use an isolated wolfBoot checkout with initialized wolfSSL submodules: + +```sh +cp config/examples/agilex5_013b_sdcard.config .config +make clean +make -j"$(nproc)" +``` + +The hosted build is also covered by the `Agilex 5 wolfBoot build` GitHub +Actions workflow. It installs the same freestanding AArch64 toolchain used by +the other Cortex-A ports and builds this configuration on every relevant +pull request; hardware is required only for the SD-card and Linux handoff +steps below. + +The default RSA-4096/SHA3-384 key is for development only. Production builds +must supply controlled signing keys and keep them separate from both the SDM +owner key and the SPL FIT-signing key. + +Create the Linux FIT from the GSRD `Image` and the exact board DTB, then sign +that FIT with wolfBoot's normal image-signing flow. Initialize both raw A/B +partitions with a valid signed image for the first boot. + +The checked-in `hal/agilex5.its` is a minimal FIT example. A GSRD production +image must use the GSRD-generated kernel load address and board DTB, then be +signed with the deployment key. Do not place private keys in the source tree +or the WIC. + +## GSRD integration + +Keep the GSRD `u-boot.itb` structure and signature intact: + +- retain the existing BL31 firmware node; +- replace only the U-Boot-proper/BL33 data with `wolfboot.bin`; +- retain load and entry `0x80200000`; +- rebuild and sign the ITB using the same GSRD/SPL trust configuration. + +Use a four-partition WIC: + +1. 128 MiB FAT boot partition containing the signed boot artifacts; +2. 200 MiB raw wolfBoot A partition; +3. 200 MiB raw wolfBoot B partition; +4. ext4 Linux root filesystem. + +The wolfSSL FCS packages belong in partition 4. libfcs is Linux userspace +software and is deliberately not linked into bare-metal wolfBoot. + +## Test order + +1. Cross-build the existing ZynqMP and Versal SD-card configurations to catch + shared AArch64 regressions, then build Agilex 5. +2. First boot a minimal signed payload that prints its exception level and + proves the generic timer and PSCI reset path. +3. Exercise SD reads in PIO mode, then valid, corrupt-signature, truncated and + oversized images. +4. Boot Linux and require the DTB in x0, x1-x3 zero, four online CPUs, working + PSCI reboot, and rootfs `/dev/mmcblk0p4`. +5. Build the complete WIC, inspect all four partitions, flash the whole card, + compare the complete image span, cold boot, and test A-to-B fallback by + corrupting only a disposable copy of A. +6. From the booted WIC run `/usr/bin/wolfcrypttest`. Require exit zero and + `ALTERA-FCS test passed!` to prove the Linux image still provides hardware + FCS offload. + +For the reproducible meta-wolfSSL customer flow, use +`recipes-wolfssl/wolfboot/agilex5/README.md` in the meta-wolfSSL checkout. It +covers the Kas fragment, the four-partition WIC inspection, whole-device flash +and byte comparison, virtual SDM owner-key reprovisioning after power loss, +and the target-side loader/FCS checks. wolfBoot itself does not link libfcs; +the FCS test belongs to the Linux image in WIC partition 4. + +Do not patch TF-A or take over GICv3, SMMU/firewall, mailbox, or PSCI ownership +without a reproduced hardware failure showing the stock GSRD contract is +insufficient. + +## CI and hardware boundary + +CI proves that the Agilex 5 configuration, linker script, startup assembly, +SDHCI changes, and test application remain buildable without Agilex hardware. +It cannot prove SPL DDR training, TF-A handoff, SDM services, signed FIT +verification, or FCS offload. Those require the GSRD image and the +DK-A5E013BM16AEA. Record the WIC hash, complete-card comparison, UART boot +log, target `uname`, loader output, and `wolfcrypttest` exit status and FCS +marker for a hardware release sign-off. diff --git a/docs/Targets.md b/docs/Targets.md index 1a30c364fc..4d38de3f20 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -4,6 +4,7 @@ This README describes configuration of supported targets. ## Supported Targets +* [Altera Agilex 5](#altera-agilex-5-013b) * [Simulated](#simulated) * [Analog Devices MAX32666](#analog-devices-max32666) * [Cortex-A53 / Raspberry PI 3](#cortex-a53--raspberry-pi-3-experimental) @@ -8707,3 +8708,22 @@ Boot success marked. Version: 1 | `FLAGS_HOME` | Keep boot flags in internal flash (required when `EXT_FLASH=1`). | | `MAX3266X_TPU` | Enable TPU hardware SHA256 acceleration (requires `MSDK_DIR`). | | `MAX3266X_OLD` | Build TPU acceleration against the older, deprecated Maxim SDK tree instead of the modern MSDK. | +## Altera Agilex 5 (013B) + +The Agilex 5 DK-A5E013BM16AEA port runs as the signed BL33 payload in the +GSRD handoff: SDM -> U-Boot SPL -> TF-A BL31 -> wolfBoot -> Linux FIT. SPL +owns DDR and controller initialization; TF-A owns EL3, GICv3 and PSCI. The +port keeps those responsibilities unchanged and loads signed A/B Linux FITs +from raw MBR partitions on the SD card. + +Build the hosted configuration with: + +```sh +cp config/examples/agilex5_013b_sdcard.config .config +make clean +make -j"$(nproc)" +``` + +See [docs/Agilex5.md](Agilex5.md) for the GSRD FIT/WIC layout, DT handoff, +hardware test order, and the boundary between the bare-metal bootloader and +the Linux libfcs/wolfSSL integration. diff --git a/hal/agilex5.c b/hal/agilex5.c new file mode 100644 index 0000000000..de8fccd0a1 --- /dev/null +++ b/hal/agilex5.c @@ -0,0 +1,339 @@ +/* agilex5.c + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1335, USA + */ + +#ifdef TARGET_agilex5 + +#include + +#include "fdt.h" +#include "hal.h" +#include "hal/agilex5.h" +#include "image.h" +#include "printf.h" + +#ifndef ARCH_AARCH64 +#error "wolfBoot Agilex 5 HAL requires ARCH=AARCH64" +#endif + +#ifndef LINUX_BOOTARGS +#ifndef LINUX_BOOTARGS_ROOT +#define LINUX_BOOTARGS_ROOT "/dev/mmcblk0p4" +#endif +#define LINUX_BOOTARGS \ + "earlycon=uart8250,mmio32,0x10c02000 console=ttyS0,115200 " \ + "root=" LINUX_BOOTARGS_ROOT " rootwait" +#endif + +#ifdef DEBUG_UART +#define UART_RBR 0U +#define UART_THR 0U +#define UART_LSR 5U +#define UART_LSR_THRE (1U << 5) +#define UART_LSR_TEMT (1U << 6) +#define UART_TIMEOUT 1000000U +#define UART_REG(_n) \ + (*(volatile uint32_t *)(AGILEX5_UART0_BASE + ((uintptr_t)(_n) << 2))) + +void uart_init(void) +{ + /* SPL configured the DesignWare APB UART, its clock and pinmux. */ +} + +void uart_write(const char *buf, uint32_t len) +{ + uint32_t i; + + for (i = 0; i < len; i++) { + uint32_t timeout = UART_TIMEOUT; + if (buf[i] == '\n') { + while (((UART_REG(UART_LSR) & UART_LSR_THRE) == 0U) && + (--timeout != 0U)) {} + UART_REG(UART_THR) = '\r'; + timeout = UART_TIMEOUT; + } + while (((UART_REG(UART_LSR) & UART_LSR_THRE) == 0U) && + (--timeout != 0U)) {} + UART_REG(UART_THR) = (uint32_t)(uint8_t)buf[i]; + } +} +#else +#define uart_init() do {} while (0) +#endif + +static uint64_t timer_count(void) +{ + uint64_t count; + __asm__ volatile("mrs %0, cntpct_el0" : "=r"(count)); + return count; +} + +static uint64_t timer_frequency(void) +{ + uint64_t frequency; + __asm__ volatile("mrs %0, cntfrq_el0" : "=r"(frequency)); + return frequency; +} + +uint64_t hal_get_timer_us(void) +{ + uint64_t frequency = timer_frequency(); + return (frequency != 0U) ? + ((timer_count() * 1000000ULL) / frequency) : 0U; +} + +void hal_init(void) +{ + uart_init(); +#if defined(DEBUG_UART) && defined(__WOLFBOOT) + wolfBoot_printf("\nwolfBoot Secure Boot - Altera Agilex 5\n"); + wolfBoot_printf("TF-A BL33 entry, current EL: %d\n", current_el()); +#endif +} + +void hal_prepare_boot(void) +{ +#ifdef DEBUG_UART + uint32_t timeout = UART_TIMEOUT; + while (((UART_REG(UART_LSR) & UART_LSR_TEMT) == 0U) && + (--timeout != 0U)) {} +#endif + __asm__ volatile("dsb sy" : : : "memory"); + __asm__ volatile("ic iallu" : : : "memory"); + __asm__ volatile("dsb sy" : : : "memory"); + __asm__ volatile("isb" : : : "memory"); +} + +#ifdef MMU +void *hal_get_dts_address(void) +{ + return (void *)WOLFBOOT_LOAD_DTS_ADDRESS; +} + +void *hal_get_dts_update_address(void) +{ +#ifdef WOLFBOOT_DTS_UPDATE_ADDRESS + return (void *)WOLFBOOT_DTS_UPDATE_ADDRESS; +#else + return NULL; +#endif +} + +#ifdef __WOLFBOOT +int hal_dts_fixup(void *dts_addr) +{ + struct fdt_header *fdt = (struct fdt_header *)dts_addr; + int off; + int ret = fdt_check_header(dts_addr); + + if (ret != 0) { + wolfBoot_printf("FDT: invalid header (%d)\n", ret); + return ret; + } + fdt_set_totalsize(fdt, + fdt_totalsize(fdt) + WOLFBOOT_FDT_FIXUP_HEADROOM); + + /* U-Boot normally patches the memory node after SPL has measured the + * LPDDR4. wolfBoot bypasses U-Boot and passes this DTB directly to + * Linux, so preserve the board's 1792 MiB memory map explicitly. */ + off = fdt_find_devtype(fdt, -1, "memory"); + if (off >= 0) { + uint64_t reg[2]; + + reg[0] = cpu_to_fdt64(AGILEX5_DDR_BASE); + reg[1] = cpu_to_fdt64(AGILEX5_DDR_SIZE); + ret = fdt_setprop(fdt, off, "reg", reg, sizeof(reg)); + if (ret != 0) { + wolfBoot_printf("FDT: failed to set memory (%d)\n", ret); + return ret; + } + wolfBoot_printf("FDT: Set memory, start=0x%lx, size=0x%lx\n", + (unsigned long)AGILEX5_DDR_BASE, + (unsigned long)AGILEX5_DDR_SIZE); + } + + /* The board DT contains an optional FPGA-backed gpio-leds node. The + * normal GSRD path programs the fabric in U-Boot before probing it; the + * direct wolfBoot handoff does not yet program that optional design. + * Keep Linux from touching an unconfigured fabric register while the + * HPS, FCS and storage paths remain available. */ + off = fdt_find_node_offset(fdt, -1, "leds"); + if (off >= 0) { + ret = fdt_fixup_str(fdt, off, "leds", "status", "disabled"); + if (ret != 0) { + wolfBoot_printf("FDT: failed to disable FPGA LEDs (%d)\n", ret); + return ret; + } + } + + off = fdt_find_node_offset(fdt, -1, "chosen"); + if (off == -FDT_ERR_NOTFOUND) + off = fdt_add_subnode(fdt, 0, "chosen"); + if (off < 0) + return off; + return fdt_fixup_str(fdt, off, "chosen", "bootargs", LINUX_BOOTARGS); +} +#endif +#endif + +void RAMFUNCTION hal_flash_unlock(void) {} +void RAMFUNCTION hal_flash_lock(void) {} + +int RAMFUNCTION hal_flash_write(uintptr_t address, const uint8_t *data, + int len) +{ + (void)address; + (void)data; + (void)len; + return -1; +} + +int RAMFUNCTION hal_flash_erase(uintptr_t address, int len) +{ + (void)address; + (void)len; + return -1; +} + +#if defined(DISK_SDCARD) || defined(DISK_EMMC) +#include "sdhci.h" + +#define AGILEX5_SDHCI_HRS05 0x014U +#define AGILEX5_SDHCI_HRS07 0x01CU +#define AGILEX5_SDHCI_HRS09 0x024U +#define AGILEX5_SDHCI_HRS10 0x028U +#define AGILEX5_SDHCI_HRS16 0x040U + +#define AGILEX5_SDHCI_PHY_DQ_TIMING 0x2000U +#define AGILEX5_SDHCI_PHY_DQS_TIMING 0x2004U +#define AGILEX5_SDHCI_PHY_GATE_LPBK_CTRL 0x2008U +#define AGILEX5_SDHCI_PHY_DLL_MASTER_CTRL 0x200CU +#define AGILEX5_SDHCI_PHY_DLL_SLAVE_CTRL 0x2010U + +#define AGILEX5_SDHCI_PHY_INIT_COMPLETE (1U << 1) +#define AGILEX5_SDHCI_PHY_SW_RESET (1U << 0) +#define AGILEX5_SDHCI_PHY_INIT_TIMEOUT 1000000U + +static void agilex5_sdhci_write_phy(uint32_t address, uint32_t value) +{ + sdhci_reg_write(SDHCI_HRS04, address); + sdhci_reg_write(AGILEX5_SDHCI_HRS05, value); +} + +static int agilex5_sdhci_phy_init(void) +{ + uint32_t reg; + uint32_t timeout = AGILEX5_SDHCI_PHY_INIT_TIMEOUT; + + reg = sdhci_reg_read(AGILEX5_SDHCI_HRS09); + reg &= ~AGILEX5_SDHCI_PHY_SW_RESET; + sdhci_reg_write(AGILEX5_SDHCI_HRS09, reg); + + /* Match the 013B SD default-speed settings used by its U-Boot DTS. */ + agilex5_sdhci_write_phy(AGILEX5_SDHCI_PHY_DQS_TIMING, 0x00780000U); + agilex5_sdhci_write_phy(AGILEX5_SDHCI_PHY_GATE_LPBK_CTRL, 0x81A40040U); + agilex5_sdhci_write_phy(AGILEX5_SDHCI_PHY_DLL_MASTER_CTRL, 0x00800004U); + agilex5_sdhci_write_phy(AGILEX5_SDHCI_PHY_DLL_SLAVE_CTRL, 0x00A000FEU); + + reg |= AGILEX5_SDHCI_PHY_SW_RESET; + sdhci_reg_write(AGILEX5_SDHCI_HRS09, reg); + while (((sdhci_reg_read(AGILEX5_SDHCI_HRS09) & + AGILEX5_SDHCI_PHY_INIT_COMPLETE) == 0U) && + (--timeout > 0U)) {} + if (timeout == 0U) + return -1; + + agilex5_sdhci_write_phy(AGILEX5_SDHCI_PHY_DQ_TIMING, 0x28000001U); + + reg = sdhci_reg_read(AGILEX5_SDHCI_HRS09); + reg &= ~((1U << 16) | (1U << 15) | (1U << 3) | (1U << 2)); + reg |= 0x0001800CU; + sdhci_reg_write(AGILEX5_SDHCI_HRS09, reg); + sdhci_reg_write(AGILEX5_SDHCI_HRS10, 0x00020000U); + sdhci_reg_write(AGILEX5_SDHCI_HRS16, 0x00000000U); + sdhci_reg_write(AGILEX5_SDHCI_HRS07, 0x00080000U); + + return 0; +} + +uint32_t sdhci_reg_read(uint32_t offset) +{ + return *(volatile uint32_t *)(AGILEX5_SDHCI_BASE + offset); +} + +void sdhci_reg_write(uint32_t offset, uint32_t value) +{ + *(volatile uint32_t *)(AGILEX5_SDHCI_BASE + offset) = value; +} + +void sdhci_platform_init(void) +{ + /* SPL initialized the host, clocks, reset and pinmux while loading BL31 + * and BL33. Preserve that live host state and restore the 013B PHY timing + * required after wolfBoot takes ownership from TF-A. */ + if (agilex5_sdhci_phy_init() != 0) + wolfBoot_printf("SDHCI: Cadence PHY initialization timed out\n"); +} + +void sdhci_platform_irq_init(void) +{ + /* The generic driver polls; BL31 retains ownership of GICv3 setup. */ +} + +void sdhci_platform_set_bus_mode(int is_emmc) +{ + (void)is_emmc; +} + +#ifndef SDHCI_SDMA_DISABLED +void sdhci_platform_dma_prepare(void *buf, uint32_t size, int is_write) +{ + uintptr_t addr; + uintptr_t start = (uintptr_t)buf & ~(CACHE_LINE_SIZE - 1U); + uintptr_t end = ((uintptr_t)buf + size + CACHE_LINE_SIZE - 1U) & + ~(CACHE_LINE_SIZE - 1U); + + for (addr = start; addr < end; addr += CACHE_LINE_SIZE) { + if (is_write != 0) + __asm__ volatile("dc cvac, %0" : : "r"(addr) : "memory"); + else + __asm__ volatile("dc civac, %0" : : "r"(addr) : "memory"); + } + __asm__ volatile("dsb sy" : : : "memory"); +} + +void sdhci_platform_dma_complete(void *buf, uint32_t size, int is_write) +{ + uintptr_t addr; + uintptr_t start = (uintptr_t)buf & ~(CACHE_LINE_SIZE - 1U); + uintptr_t end = ((uintptr_t)buf + size + CACHE_LINE_SIZE - 1U) & + ~(CACHE_LINE_SIZE - 1U); + + if (is_write == 0) { + for (addr = start; addr < end; addr += CACHE_LINE_SIZE) + __asm__ volatile("dc civac, %0" : : "r"(addr) : "memory"); + __asm__ volatile("dsb sy" : : : "memory"); + } +} +#endif +#endif + +#endif /* TARGET_agilex5 */ diff --git a/hal/agilex5.h b/hal/agilex5.h new file mode 100644 index 0000000000..2c19472147 --- /dev/null +++ b/hal/agilex5.h @@ -0,0 +1,81 @@ +/* agilex5.h + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1335, USA + */ + +#ifndef WOLFSSL_AGILEX5_H +#define WOLFSSL_AGILEX5_H + +#ifndef EL3_SECURE +#define EL3_SECURE 0 +#endif +#ifndef EL2_HYPERVISOR +#define EL2_HYPERVISOR 1 +#endif +#ifndef EL1_NONSECURE +#define EL1_NONSECURE 1 +#endif +#ifndef HYP_GUEST +#define HYP_GUEST 0 +#endif +#ifndef FPU_TRAP +#define FPU_TRAP 0 +#endif +#ifndef SKIP_GIC_INIT +#define SKIP_GIC_INIT 1 +#endif + +/* Preserve EL2 for Linux/KVM, matching the normal TF-A -> U-Boot handoff. */ +#if !defined(BOOT_EL1) && !defined(BOOT_EL2) +#define BOOT_EL2 1 +#endif +#if defined(BOOT_EL1) && defined(BOOT_EL2) +#error "BOOT_EL1 and BOOT_EL2 are mutually exclusive" +#endif + +#define AGILEX5_DDR_BASE 0x80000000UL +/* The DK-A5E013BM16AEA is fitted with 1792 MiB of LPDDR4. The SPL/U-Boot + * device tree normally fills this in at runtime; wolfBoot hands the DTB + * directly to Linux, so the fixed board size must be supplied here. */ +#define AGILEX5_DDR_SIZE 0x70000000UL +#define AGILEX5_UART0_BASE 0x10C02000UL +#define AGILEX5_UART1_BASE 0x10C02100UL +#define AGILEX5_SDHCI_BASE 0x10808000UL +#define CACHE_LINE_SIZE 64UL + +/* Preserve the SPL-initialized host and apply the Cadence command delay. */ +#define SDHCI_SKIP_HOST_RESET 1 +#define SDHCI_WAIT_AFTER_CMD_US 1000U + +#ifndef __ASSEMBLER__ +unsigned int current_el(void); +#endif + +#ifndef WOLFBOOT_LOAD_ADDRESS +#define WOLFBOOT_LOAD_ADDRESS 0x90000000UL +#endif +#ifndef WOLFBOOT_LOAD_DTS_ADDRESS +#define WOLFBOOT_LOAD_DTS_ADDRESS 0x8F000000UL +#endif +#ifndef WOLFBOOT_RAMBOOT_MAX_SIZE +#define WOLFBOOT_RAMBOOT_MAX_SIZE 0x10000000UL +#endif + +#endif /* WOLFSSL_AGILEX5_H */ diff --git a/hal/agilex5.its b/hal/agilex5.its new file mode 100644 index 0000000000..d906008640 --- /dev/null +++ b/hal/agilex5.its @@ -0,0 +1,39 @@ +/dts-v1/; + +/ { + description = "Altera Agilex 5 wolfBoot Linux payload"; + #address-cells = <1>; + + images { + kernel-1 { + description = "Linux kernel"; + data = /incbin/("../Image"); + type = "kernel"; + arch = "arm64"; + os = "linux"; + compression = "none"; + load = <0x82000000>; + entry = <0x82000000>; + hash-1 { algo = "sha256"; }; + }; + fdt-1 { + description = "Agilex 5 device tree"; + data = /incbin/("../socfpga_agilex5_socdk.dtb"); + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + load = <0x8f000000>; + hash-1 { algo = "sha256"; }; + }; + }; + + configurations { + default = "conf-1"; + conf-1 { + description = "Agilex 5 Linux"; + kernel = "kernel-1"; + fdt = "fdt-1"; + hash-1 { algo = "sha256"; }; + }; + }; +}; diff --git a/hal/agilex5.ld b/hal/agilex5.ld new file mode 100644 index 0000000000..d391974142 --- /dev/null +++ b/hal/agilex5.ld @@ -0,0 +1,132 @@ +/* agilex5.ld + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1335, USA + */ + +OUTPUT_FORMAT("elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(_vector_table) + +_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x20000; +_EL0_STACK_SIZE = 0x1000; +_EL1_STACK_SIZE = 0x2000; +_EL2_STACK_SIZE = 0x8000; + +MEMORY +{ + /* Matches CONFIG_TEXT_BASE and the BL33 load/entry in GSRD u-boot.itb. */ + DDR (rwx) : ORIGIN = 0x80200000, LENGTH = 0x200000 +} + +SECTIONS +{ + .text : { + _start_text = .; + KEEP (*(.vectors)) + *(.boot) + *(.text .text.*) + *(.gnu.linkonce.t.*) + *(.plt) + *(.ARM.extab*) + _end_text = .; + } > DDR + + .rodata : { + . = ALIGN(64); + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } > DDR + + .keystore : { + . = ALIGN(8); + KEEP (*(.keystore)) + } > DDR + + .data : { + . = ALIGN(64); + _start_data = .; + __data_start = .; + *(.data .data.*) + *(.sdata .sdata.*) + *(.got .got.*) + _end_data = .; + __data_end = .; + } > DDR + + .mmu_tbl0 (ALIGN(4096)) : { + *(.mmu_tbl0) + } > DDR + .mmu_tbl1 (ALIGN(4096)) : { + *(.mmu_tbl1) + } > DDR + .mmu_tbl2 (ALIGN(4096)) : { + *(.mmu_tbl2) + } > DDR + + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } > DDR + + .ramcode : { + . = ALIGN(64); + *(.ramcode .ramcode.*) + } > DDR + + .bss (NOLOAD) : { + . = ALIGN(64); + __bss_start__ = .; + _start_bss = .; + *(.bss .bss.*) + *(.sbss .sbss.*) + *(COMMON) + . = ALIGN(64); + __bss_end__ = .; + _end_bss = .; + } > DDR + + .heap (NOLOAD) : { + . = ALIGN(64); + _heap = .; + . += _HEAP_SIZE; + __heap_end = .; + } > DDR + + .stack (NOLOAD) : { + . = ALIGN(64); + . += 0x1000; + __el3_stack = .; + . += _EL2_STACK_SIZE; + __el2_stack = .; + . += _EL1_STACK_SIZE; + __el1_stack = .; + . += _EL0_STACK_SIZE; + __el0_stack = .; + } > DDR + + _end = .; + ASSERT(_end <= ORIGIN(DDR) + LENGTH(DDR), + "wolfBoot Agilex 5 image exceeds the 2 MiB BL33 reservation") +} + +PROVIDE(_start_vector = _start_text); +PROVIDE(__stack = __el2_stack); +PROVIDE(_stack_base = .); diff --git a/include/sdhci.h b/include/sdhci.h index 21e89ea40c..fad5162762 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -247,6 +247,8 @@ #define SDHCI_SRS11_SDCFSH_MASK (0x03U << 6) #define SDHCI_SRS11_DTCV_SHIFT 16 #define SDHCI_SRS11_DTCV_MASK (0x0FU << 16) +#define SDHCI_SRS11_RESET_CMD (1U << 25) +#define SDHCI_SRS11_RESET_DAT (1U << 26) #define SDHCI_SRS11_RESET_DAT_CMD ((1U << 25) | (1U << 26)) #define SDHCI_SRS11_RESET_ALL (1U << 24) @@ -471,6 +473,16 @@ void sdhci_reg_write(uint32_t offset, uint32_t val); /* Platform initialization (clocks, resets, pin mux, debounce) */ void sdhci_platform_init(void); +/* Preserve a host controller initialized by an earlier boot stage. */ +#ifndef SDHCI_SKIP_HOST_RESET +#define SDHCI_SKIP_HOST_RESET 0 +#endif + +/* Optional controller settling time after each command. */ +#ifndef SDHCI_WAIT_AFTER_CMD_US +#define SDHCI_WAIT_AFTER_CMD_US 0U +#endif + /* Platform interrupt setup (PLIC/NVIC/GIC/etc.) */ void sdhci_platform_irq_init(void); @@ -480,4 +492,3 @@ void sdhci_platform_set_bus_mode(int is_emmc); #endif /* DISK_SDCARD || DISK_EMMC */ #endif /* SDHCI_H */ - diff --git a/src/boot_aarch64.c b/src/boot_aarch64.c index 4e6c9e2ea2..13e9d21db3 100644 --- a/src/boot_aarch64.c +++ b/src/boot_aarch64.c @@ -32,6 +32,8 @@ * compile in for the active target. */ #if defined(TARGET_versal) #include "hal/versal.h" +#elif defined(TARGET_agilex5) +#include "hal/agilex5.h" #elif defined(TARGET_zynq) #include "hal/zynq.h" #elif defined(TARGET_nxp_ls1028a) diff --git a/src/boot_aarch64_start.S b/src/boot_aarch64_start.S index e3ddb9259e..14b1dc9b4a 100644 --- a/src/boot_aarch64_start.S +++ b/src/boot_aarch64_start.S @@ -30,6 +30,10 @@ #include "hal/versal.h" #endif +#ifdef TARGET_agilex5 +#include "hal/agilex5.h" +#endif + #ifdef TARGET_nxp_ls1028a #include "hal/nxp_ls1028a.h" #endif @@ -83,9 +87,9 @@ .set L2Table, MMUTableL2 .set vector_base, _vector_table -#ifdef TARGET_versal +#if defined(TARGET_versal) || defined(TARGET_agilex5) /* Versal: RVBAR is handled by PLM, not accessible from APU in JTAG mode */ -/* Cortex-A72 timestamp clock frequency (from Versal HW) */ +/* BL31 has already programmed CNTFRQ_EL0 on BL33-entry platforms. */ .set counterfreq, 100000000 #else .set rvbar_base, 0xFD5C0040 @@ -672,6 +676,14 @@ MMUTableL2: .set SECT, 0 +#ifdef TARGET_agilex5 +/* Agilex 5 HPS peripherals and bridges occupy the low 2GiB. Keep them + * strongly ordered; cached HPS DDR starts at 0x8000_0000 below. */ +.rept 0x0400 /* 0x0000_0000 - 0x7FFF_FFFF */ +.8byte SECT + Device +.set SECT, SECT+0x200000 +.endr +#else #ifdef XPAR_PSU_DDR_0_S_AXI_BASEADDR .set DDR_0_START, XPAR_PSU_DDR_0_S_AXI_BASEADDR .set DDR_0_END, XPAR_PSU_DDR_0_S_AXI_HIGHADDR @@ -697,7 +709,15 @@ MMUTableL2: .8byte SECT + reserved .set SECT, SECT+0x200000 .endr +#endif /* TARGET_agilex5 */ +#ifdef TARGET_agilex5 +/* Agilex 5 GSRD maps the 2GiB HPS DDR window at 0x8000_0000. */ +.rept 0x0400 /* 0x8000_0000 - 0xFFFF_FFFF */ +.8byte SECT + Memory +.set SECT, SECT+0x200000 +.endr +#else .rept 0x0200 /* 0x8000_0000 - 0xBFFF_FFFF */ .8byte SECT + Device /* 1GB lower PL */ .set SECT, SECT+0x200000 @@ -761,6 +781,7 @@ converted to 62MB */ .set SECT, SECT+0x200000 /* 0xFFE0_0000 - 0xFFFF_FFFF*/ .8byte SECT + Memory /* 2MB OCM/TCM */ +#endif /* TARGET_agilex5 */ #else /* TARGET_nxp_ls1028a */ /* ============================================================================ diff --git a/src/sdhci.c b/src/sdhci.c index 60ae4d32cb..e1ea1a70c4 100644 --- a/src/sdhci.c +++ b/src/sdhci.c @@ -469,6 +469,17 @@ static uint32_t sdhci_get_response_type(uint8_t resp_type) #define DEVICE_BUSY 1 +static int sdhci_reset_cmd_line(void) +{ + uint32_t timeout = 0x000FFFFF; + + sdhci_reg_or(SDHCI_SRS11, SDHCI_SRS11_RESET_CMD); + while (((SDHCI_REG(SDHCI_SRS11) & SDHCI_SRS11_RESET_CMD) != 0U) && + (--timeout > 0U)) {} + + return (timeout > 0U) ? 0 : -1; +} + static int sdhci_send_cmd_internal(uint32_t cmd_type, uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type) { @@ -508,10 +519,18 @@ static int sdhci_send_cmd_internal(uint32_t cmd_type, "error SRS12=0x%08X\n", cmd_index, cmd_arg, resp_type, SDHCI_REG(SDHCI_SRS12)); status = -1; /* error */ + if (sdhci_reset_cmd_line() != 0) + wolfBoot_printf("sdhci_send_cmd: command line reset timeout\n"); } SDHCI_REG_SET(SDHCI_SRS12, SDHCI_SRS12_CC); /* clear command complete */ - while ((SDHCI_REG(SDHCI_SRS09) & SDHCI_SRS09_CICMD) != 0); + timeout = 0x000FFFFF; + while (((SDHCI_REG(SDHCI_SRS09) & SDHCI_SRS09_CICMD) != 0U) && + (--timeout > 0U)) {} + if (timeout == 0U) { + wolfBoot_printf("sdhci_send_cmd: command inhibit timeout\n"); + status = -1; + } if (status == 0) { /* check for device busy */ @@ -524,6 +543,10 @@ static int sdhci_send_cmd_internal(uint32_t cmd_type, } } +#if SDHCI_WAIT_AFTER_CMD_US > 0U + udelay(SDHCI_WAIT_AFTER_CMD_US); +#endif + return status; } @@ -661,9 +684,20 @@ static int sdcard_power_init_seq(uint32_t voltage) * SDHCI platforms deliberately: the delay is harmless settle * margin and the SD spec permits it. */ udelay(200); - /* send the operating conditions command */ - status = sdhci_cmd(SD_CMD8_SEND_IF_COND, SD_IF_COND_27V_33V, - SDHCI_RESP_R7); + /* Allow the card time to answer CMD8 after releasing the command line. */ + for (retries = 0; retries < 10; retries++) { + status = sdhci_cmd(SD_CMD8_SEND_IF_COND, SD_IF_COND_27V_33V, + SDHCI_RESP_R7); + if (status == 0) + break; + udelay(10000); + } + if (status != 0) { + wolfBoot_printf("SD: CMD8 failed after %d retries\n", retries); + } + else if (retries > 0) { + wolfBoot_printf("SD: CMD8 succeeded after %d retries\n", retries); + } } return status; } @@ -1518,10 +1552,12 @@ int sdhci_init(void) * not be ready to accept register writes on some platforms. */ udelay(1000); /* 1ms */ - /* Reset the host controller */ +#if SDHCI_SKIP_HOST_RESET == 0 + /* Reset the host controller unless an earlier boot stage initialized it. */ sdhci_reg_or(SDHCI_HRS00, SDHCI_HRS00_SWR); /* Bit will clear when reset is done */ while ((SDHCI_REG(SDHCI_HRS00) & SDHCI_HRS00_SWR) != 0); +#endif /* Set debounce period to ~15ms (platform-specific value may be different) */ SDHCI_REG_SET(SDHCI_HRS01, (0x300000UL << SDHCI_HRS01_DP_SHIFT) & diff --git a/src/update_disk.c b/src/update_disk.c index d30a37f770..8e0e87521f 100644 --- a/src/update_disk.c +++ b/src/update_disk.c @@ -381,7 +381,11 @@ void RAMFUNCTION wolfBoot_start(void) pB_ver_u = pB_ver; wolfBoot_printf("Versions, A:%u B:%u\r\n", pA_ver_u, pB_ver_u); +#if DISK_BLOCK_SIZE < 1024 + wolfBoot_printf("Load block size: %d bytes\r\n", DISK_BLOCK_SIZE); +#else wolfBoot_printf("Load block size: %dKB\r\n", DISK_BLOCK_SIZE / 1024); +#endif max_ver = (pB_ver_u > pA_ver_u) ? pB_ver_u : pA_ver_u; /* Choose partition with higher version */ @@ -398,7 +402,8 @@ void RAMFUNCTION wolfBoot_start(void) load_address = (uint32_t *)((((uintptr_t)_end_wb) + 0xf) & ~0xf); #endif - wolfBoot_printf("Load address 0x%x\r\n", load_address); + wolfBoot_printf("Load address 0x%lx\r\n", + (unsigned long)(uintptr_t)load_address); do { failures++; if (selected) @@ -656,7 +661,8 @@ void RAMFUNCTION wolfBoot_start(void) } #endif - wolfBoot_printf("Booting at %08lx\r\n", load_address); + wolfBoot_printf("Booting at %08lx\r\n", + (unsigned long)(uintptr_t)load_address); #ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT (void)hal_hsm_disconnect(); diff --git a/test-app/app_agilex5.c b/test-app/app_agilex5.c new file mode 100644 index 0000000000..b2324ea748 --- /dev/null +++ b/test-app/app_agilex5.c @@ -0,0 +1,56 @@ +/* app_agilex5.c + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1335, USA + */ + +#include + +#include "hal.h" +#include "hal/agilex5.h" +#include "printf.h" + +/* boot_aarch64.c normally supplies this to the HAL. */ +__attribute__((weak)) unsigned int current_el(void) +{ + unsigned long el; + __asm__ volatile("mrs %0, CurrentEL" : "=r"(el) : : "cc"); + return (unsigned int)((el >> 2) & 0x3U); +} + +void main(void) +{ + uint64_t start; + uint64_t now; + + hal_init(); + wolfBoot_printf("\nAgilex 5 BL33 smoke test\n"); + wolfBoot_printf("Current EL: %d (expected 2)\n", current_el()); + + start = hal_get_timer_us(); + do { + now = hal_get_timer_us(); + } while ((now - start) < 1000U); + wolfBoot_printf("Generic timer advanced by %d us\n", + (uint32_t)(now - start)); + wolfBoot_printf("AGILEX5_BL33_SMOKE_PASS\n"); + + while (1) + __asm__ volatile("wfi"); +} From d67e83405ebdc0d7e93393fffff96f4bf7466f33 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Thu, 6 Aug 2026 16:12:07 -0700 Subject: [PATCH 2/3] Run Agilex 5 build in standard CI triggers --- .github/workflows/test-build-agilex5.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/test-build-agilex5.yml b/.github/workflows/test-build-agilex5.yml index 08e6730448..1e3ac363a3 100644 --- a/.github/workflows/test-build-agilex5.yml +++ b/.github/workflows/test-build-agilex5.yml @@ -1,17 +1,23 @@ name: Agilex 5 wolfBoot build on: + push: + branches: [ 'master', 'main', 'release/**' ] workflow_dispatch: pull_request: + branches: [ '*' ] paths: - 'arch.mk' - 'config/examples/agilex5_013b_sdcard.config' - 'hal/agilex5.*' + - 'hal/board/agilex5/**' - 'include/sdhci.h' - 'src/boot_aarch64*' - 'src/sdhci.c' - 'src/update_disk.c' - 'test-app/app_agilex5.c' + - 'tools/bin-assemble/**' + - 'tools/keytools/**' - '.github/workflows/test-build-agilex5.yml' jobs: From 3f579584b0f4f129f54d1db8fe433b2785d13921 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Fri, 7 Aug 2026 08:53:42 -0700 Subject: [PATCH 3/3] Address Agilex 5 review findings --- docs/Agilex5.md | 2 +- hal/agilex5.c | 4 ++-- src/boot_aarch64_start.S | 7 ++++--- src/sdhci.c | 2 ++ src/update_disk.c | 6 ++++-- test-app/app_agilex5.c | 6 +++--- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/docs/Agilex5.md b/docs/Agilex5.md index 90362a7dcd..51fb94ffec 100644 --- a/docs/Agilex5.md +++ b/docs/Agilex5.md @@ -7,7 +7,7 @@ not replace the platform first stage or TF-A: SDM -> U-Boot SPL -> TF-A BL31/EL3 -> wolfBoot BL33/EL2 -> signed Linux FIT ``` -SPL remains responsible for DDR, clocks, resets, pinmux, the SD6HC PHY and +SPL remains responsible for DDR, clocks, resets, pinmux, the SDHCI PHY and loading the signed U-Boot FIT. BL31 remains responsible for EL3, GICv3, PSCI, secondary CPUs and security-controller setup. The U-Boot-proper payload in the FIT is replaced with `wolfboot.bin` at load/entry address `0x80200000`. diff --git a/hal/agilex5.c b/hal/agilex5.c index de8fccd0a1..cadc5417f4 100644 --- a/hal/agilex5.c +++ b/hal/agilex5.c @@ -315,7 +315,7 @@ void sdhci_platform_dma_prepare(void *buf, uint32_t size, int is_write) if (is_write != 0) __asm__ volatile("dc cvac, %0" : : "r"(addr) : "memory"); else - __asm__ volatile("dc civac, %0" : : "r"(addr) : "memory"); + __asm__ volatile("dc ivac, %0" : : "r"(addr) : "memory"); } __asm__ volatile("dsb sy" : : : "memory"); } @@ -329,7 +329,7 @@ void sdhci_platform_dma_complete(void *buf, uint32_t size, int is_write) if (is_write == 0) { for (addr = start; addr < end; addr += CACHE_LINE_SIZE) - __asm__ volatile("dc civac, %0" : : "r"(addr) : "memory"); + __asm__ volatile("dc ivac, %0" : : "r"(addr) : "memory"); __asm__ volatile("dsb sy" : : : "memory"); } } diff --git a/src/boot_aarch64_start.S b/src/boot_aarch64_start.S index 14b1dc9b4a..f238868fdd 100644 --- a/src/boot_aarch64_start.S +++ b/src/boot_aarch64_start.S @@ -87,10 +87,11 @@ .set L2Table, MMUTableL2 .set vector_base, _vector_table -#if defined(TARGET_versal) || defined(TARGET_agilex5) +#if defined(TARGET_versal) /* Versal: RVBAR is handled by PLM, not accessible from APU in JTAG mode */ -/* BL31 has already programmed CNTFRQ_EL0 on BL33-entry platforms. */ .set counterfreq, 100000000 +#elif defined(TARGET_agilex5) +/* BL31 has already programmed CNTFRQ_EL0 before entering wolfBoot. */ #else .set rvbar_base, 0xFD5C0040 /* Cortex-A53 timestamp clock frequency */ @@ -222,7 +223,7 @@ InitEL3: * sets it to the actual system-counter rate, which our usleep() needs for * accurate psu_init DDR-training delays. Hardcoding 100MHz here is wrong * when the counter runs at the BootROM (undivided) rate. */ -#ifndef WOLFBOOT_ZYNQMP_FSBL +#if !defined(WOLFBOOT_ZYNQMP_FSBL) && !defined(TARGET_agilex5) #ifdef TARGET_nxp_ls1028a /* Read the true base frequency from the system counter (CNTFID0 @ SYSCNT * base+0x20 = SYS_REF_CLK/4); the counterfreq constant is the undivided diff --git a/src/sdhci.c b/src/sdhci.c index e1ea1a70c4..1d1eac4fa2 100644 --- a/src/sdhci.c +++ b/src/sdhci.c @@ -530,6 +530,8 @@ static int sdhci_send_cmd_internal(uint32_t cmd_type, if (timeout == 0U) { wolfBoot_printf("sdhci_send_cmd: command inhibit timeout\n"); status = -1; + if (sdhci_reset_cmd_line() != 0) + wolfBoot_printf("sdhci_send_cmd: command line reset timeout\n"); } if (status == 0) { diff --git a/src/update_disk.c b/src/update_disk.c index 8e0e87521f..77f451e49e 100644 --- a/src/update_disk.c +++ b/src/update_disk.c @@ -382,9 +382,11 @@ void RAMFUNCTION wolfBoot_start(void) wolfBoot_printf("Versions, A:%u B:%u\r\n", pA_ver_u, pB_ver_u); #if DISK_BLOCK_SIZE < 1024 - wolfBoot_printf("Load block size: %d bytes\r\n", DISK_BLOCK_SIZE); + wolfBoot_printf("Load block size: %u bytes\r\n", + (unsigned int)DISK_BLOCK_SIZE); #else - wolfBoot_printf("Load block size: %dKB\r\n", DISK_BLOCK_SIZE / 1024); + wolfBoot_printf("Load block size: %uKB\r\n", + (unsigned int)(DISK_BLOCK_SIZE / 1024U)); #endif max_ver = (pB_ver_u > pA_ver_u) ? pB_ver_u : pA_ver_u; diff --git a/test-app/app_agilex5.c b/test-app/app_agilex5.c index b2324ea748..2271ca6832 100644 --- a/test-app/app_agilex5.c +++ b/test-app/app_agilex5.c @@ -41,14 +41,14 @@ void main(void) hal_init(); wolfBoot_printf("\nAgilex 5 BL33 smoke test\n"); - wolfBoot_printf("Current EL: %d (expected 2)\n", current_el()); + wolfBoot_printf("Current EL: %u (expected 2)\n", current_el()); start = hal_get_timer_us(); do { now = hal_get_timer_us(); } while ((now - start) < 1000U); - wolfBoot_printf("Generic timer advanced by %d us\n", - (uint32_t)(now - start)); + wolfBoot_printf("Generic timer advanced by %u us\n", + (unsigned int)(now - start)); wolfBoot_printf("AGILEX5_BL33_SMOKE_PASS\n"); while (1)