Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/workflows/test-configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,23 @@ jobs:
config-file: ./config/examples/polarfire_mpfs250_m.config
pre-build: sh tools/ci/gen_mpfs_libero_stub.sh tools/ci/mpfs_libero_stub
make-args: LIBERO_FPGA_CONFIG_DIR=tools/ci/mpfs_libero_stub
# The HSS replacement booting from the other two stores: eMMC (same SDHCI
# driver as SD, different pads) and QSPI into DDR (src/update_ram.c rather
# than src/update_disk.c).
microchip_mpfs250_m_emmc_test:
uses: ./.github/workflows/test-build-riscv.yml
with:
arch: riscv64
config-file: ./config/examples/polarfire_mpfs250_m_emmc.config
pre-build: sh tools/ci/gen_mpfs_libero_stub.sh tools/ci/mpfs_libero_stub
make-args: LIBERO_FPGA_CONFIG_DIR=tools/ci/mpfs_libero_stub
microchip_mpfs250_m_qspi_ddr_test:
uses: ./.github/workflows/test-build-riscv.yml
with:
arch: riscv64
config-file: ./config/examples/polarfire_mpfs250_m_qspi_ddr.config
pre-build: sh tools/ci/gen_mpfs_libero_stub.sh tools/ci/mpfs_libero_stub
make-args: LIBERO_FPGA_CONFIG_DIR=tools/ci/mpfs_libero_stub
microchip_mpfs250_m_mldsa_test:
uses: ./.github/workflows/test-build-riscv.yml
with:
Expand Down
162 changes: 162 additions & 0 deletions config/examples/polarfire_mpfs250_m_emmc.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# PolarFire SoC MPFS250T M-Mode (Machine Mode) with LPDDR4 + eMMC
#
# Identical to polarfire_mpfs250_m.config except for the boot device. One
# SDHCI controller serves both the SD slot and the eMMC through an external
# demux, so the two are mutually exclusive: this build drives the eMMC pads
# and the SD slot is unreachable until a build with DISK_SDCARD=1 runs again.
# On the Video Kit, check the MMC bus voltage jumpers (J16/J35/J36) before
# programming an eMMC build.
#
# Standalone wolfBoot replacing HSS:
# 1. eNVM (0x20220100) -> L2_SCRATCH (0x0A000000) - wolfBoot starts
# 2. M-mode init: PLLs, DDR controller, LPDDR4 training (Video Kit)
# 3. Load signed FIT from eMMC to DDR staging (0x82000000); after verify,
# kernel -> 0x80200000 (FIT "load"), DTB -> 0x8A000000
# 4. Verify ECC384/SHA384 signature
# 5. Drop to S-mode and jump to kernel
#
# Flash via mpfsBootmodeProgrammer (bootmode 1):
# java -jar mpfsBootmodeProgrammer.jar --bootmode 1 --die MPFS250T \
# --package FCG1152 --workdir $PWD wolfboot.elf

ARCH?=RISCV64
TARGET?=mpfs250
SIGN?=ECC384
HASH?=SHA384
IMAGE_HEADER_SIZE=512
WOLFBOOT_VERSION?=1
ARMORED?=0
DEBUG?=0
DEBUG_SYMBOLS?=1
DEBUG_UART?=1
VTOR?=1
EXT_FLASH?=0
SPI_FLASH?=0
NO_XIP?=1
NVM_FLASH_WRITEONCE?=0
UART_FLASH?=0
V?=0
NO_MPU?=1
RAM_CODE?=0
SPMATH?=0
SPMATHALL?=1
DUALBANK_SWAP?=0
PKA?=0
ENCRYPT=0
WOLFTPM?=0
ELF?=1
#DEBUG_ELF?=1

OPTIMIZATION_LEVEL=1

# M-Mode configuration: runs on E51 from L2 SRAM
RISCV_MMODE?=1

# Stack size per hart (L2 SRAM constraints). Single source of truth: this
# Makefile var feeds both the startup asm (-DSTACK_SIZE_PER_HART) and the
# linker script (@STACK_SIZE_PER_HART@ in mpfs250-m.ld).
STACK_SIZE_PER_HART=4096

# E51 core lacks RISC-V crypto extensions (Zknh), use portable C
# RISC-V SHA256/384/512 assembly (wolfcrypt port/riscv) enabled by default.
# Verified on the MPFS250 E51 (rv64imac); requires wolfSSL with the RISC-V
# unaligned-access fix (PR #10530, present in the lib/wolfssl submodule).
# The E51 handles unaligned access so the default (faster) asm path is used;
# add -DWOLFSSL_RISCV_ASM_NO_UNALIGNED for RISC-V cores that trap on it.
NO_ASM?=0

# Enable LPDDR4 init in hal_init() by pointing at the Libero/HSS-generated
# fpga_design_config directory for this board. The directory must contain
# fpga_design_config.h and its sub-headers (memory_map/, ddr/, clocks/, ...).
# Typical sources:
# - HSS Video Kit build:
# <hss>/build/boards/mpfs-video-kit/fpga_design_config
# - Libero MSS Configurator export for the design.
# The -I path is added and -DMPFS_DDR_INIT is set automatically when this is
# non-empty (see arch.mk). Override on the command line for one-off builds:
# make LIBERO_FPGA_CONFIG_DIR=/path/to/fpga_design_config
LIBERO_FPGA_CONFIG_DIR?=

# Boot Linux: drop to S-mode after wolfBoot verifies kernel
CFLAGS_EXTRA+=-DWOLFBOOT_MMODE_SMODE_BOOT

# SD card storage for kernel image (no QSPI flash)
DISK_SDCARD?=0
DISK_EMMC?=1

# wolfBoot in L2 SRAM: all 4 scratchpad ways (0x0A000000 - 0x0A07FFFF)
WOLFBOOT_ORIGIN?=0x0A000000
WOLFBOOT_L2SCRATCH_SIZE?=512k

# Boot-hart stack, sized for ML-DSA-87 verify on top of the two
# IMAGE_HEADER_SIZE buffers update_disk.c puts on the stack. ECC384 needs less.
STACK_SIZE?=64k

# 4KB sector size (SD card flow is partition-based, not flash-erase-based)
WOLFBOOT_SECTOR_SIZE?=0x1000

# Scratch address where the signed FIT image is staged before signature
# verification + FIT parse. 0x82000000 is 32 MB into the cached DDR window
# at 0x80000000, which is 1 GB wide - 0xC0000000 up is the non-cached alias
# onto the same DDR, so staging must stay below it. It is clear of the
# kernel destination below and 128 MB below the DTB region, which is the
# headroom the staged-image bound further down depends on.
# After the FIT is parsed:
# kernel is copied to 0x80200000 (FIT-internal "load")
# DTB is copied to WOLFBOOT_LOAD_DTS_ADDRESS (0x8A000000)
# Layout:
# 0x80200000 - 0x814FFFFF : kernel (~19 MB after parse)
# 0x82000000 - 0x832FFFFF : FIT scratch (~19 MB - overwritten on next boot)
# 0x8A000000 - 0x8A004FFF : DTB
WOLFBOOT_LOAD_ADDRESS?=0x82000000

# DTB load address in DDR
WOLFBOOT_LOAD_DTS_ADDRESS?=0x8A000000

# Bound the UNAUTHENTICATED FIT image length before it drives the disk read
# into the DDR staging region (required by src/update_disk.c). The FIT is
# staged at WOLFBOOT_LOAD_ADDRESS (0x82000000); the DTB load region begins
# 128 MB above at 0x8A000000, so cap the staged image at 128 MB so an
# attacker-declared fw_size cannot overrun the DTB region before the
# signature check runs.
WOLFBOOT_RAMBOOT_MAX_SIZE=0x08000000

# Use update_disk loader (partition A/B numbering instead of flash addresses).
# BOOT_PART_A / BOOT_PART_B are 0-indexed GPT entry numbers. GPT partitions
# in the SD card layout of docs/PolarFire.md:
# index 0 (parted "boot" 1 MiB - 33 MiB) -> active boot FIT
# index 1 (parted "update" 33 MiB - 65 MiB) -> inactive/update slot
# index 2 (parted "rootfs" 65 MiB - end) -> Linux rootfs
WOLFBOOT_NO_PARTITIONS=1
CFLAGS_EXTRA+=-DBOOT_PART_A=0
CFLAGS_EXTRA+=-DBOOT_PART_B=1

# Speed up disk partition read (512KB chunks - max DMA size)
CFLAGS_EXTRA+=-DDISK_BLOCK_SIZE=0x80000

# Video Kit routes the SD slot's Card Detect (CD#) signal through the FPGA
# fabric rather than MSSIO, so the SDHCI controller's hardware CI/CDPL
# detection always reads 'no card' in M-mode (no fabric configuration).
# Force the SD bring-up code to assume a card is present.
CFLAGS_EXTRA+=-DSDHCI_FORCE_CARD_DETECT

# Optional encryption (kernel signed+encrypted with AES-256)
#CUSTOM_ENCRYPT_KEY=1
#ENCRYPT=1
#ENCRYPT_WITH_AES256=1
#OBJS_EXTRA=src/my_custom_encrypt_key.o

# Used by test-application/ELF wrapper
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80200000
WOLFBOOT_PARTITION_SIZE=0x4000000

# Debug options (useful for initial M-mode + DDR bring-up)
CFLAGS_EXTRA+=-DDEBUG_BOOT
#CFLAGS_EXTRA+=-DDEBUG_SDHCI
#CFLAGS_EXTRA+=-DDEBUG_DISK
#CFLAGS_EXTRA+=-DDISK_TEST
# Verbose register-level DDR tracing (development aid). Historically the
# DBG_DDR printf delays appeared load-bearing for TIP training; that was
# resolved by the auto-init-disable training reorder and the WRCALIB
# all-4-lane accept gate with retry, so this is safe to leave disabled.
#CFLAGS_EXTRA+=-DDEBUG_DDR
80 changes: 80 additions & 0 deletions config/examples/polarfire_mpfs250_m_qspi_ddr.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# PolarFire SoC MPFS250T M-Mode (Machine Mode) with LPDDR4 + SC QSPI
#
# Standalone wolfBoot replacing HSS, booting Linux from QSPI instead of a
# disk. polarfire_mpfs250_m_qspi.config is the other QSPI M-mode build: it
# runs an application out of the L2 scratchpad and never brings up DDR. This
# one is the HSS-replacement configuration with QSPI as the image store, so it
# uses src/update_ram.c rather than src/update_disk.c and keeps the A/B update
# slots the disk configuration does not have.
#
# Standalone wolfBoot replacing HSS:
# 1. eNVM (0x20220100) -> L2_SCRATCH (0x0A000000) - wolfBoot starts
# 2. M-mode init: PLLs, DDR controller, LPDDR4 training (Video Kit)
# 3. Load signed FIT from QSPI to DDR staging (0x82000000); after verify,
# kernel -> 0x80200000 (FIT "load"), DTB -> 0x8A000000
# 4. Verify ECC384/SHA384 signature
# 5. Drop to S-mode and jump to kernel
#
# The slots are sized for a Linux FIT: 48 MB each in the Video Kit's 128 MB
# MT25QL01G, which the 32 MB slots of the application configuration cannot
# hold. Writing a slot that size over the UART programmer is impractical, so
# UART_QSPI_PROGRAM is off here; write QSPI from a running Linux (the SBI
# vendor extension flash services, MPFS_SBI_VENDOR=1) or from a programmer.
#
# Flash via mpfsBootmodeProgrammer (bootmode 1):
# java -jar mpfsBootmodeProgrammer.jar --bootmode 1 --die MPFS250T \
# --package FCG1152 --workdir $PWD wolfboot.elf

ARCH?=RISCV64
TARGET?=mpfs250
SIGN?=ECC384
HASH?=SHA384
IMAGE_HEADER_SIZE=512
WOLFBOOT_VERSION?=1
ARMORED?=0
DEBUG?=0
DEBUG_SYMBOLS?=1
DEBUG_UART?=1
VTOR?=1
EXT_FLASH?=1
SPI_FLASH?=0
NO_XIP?=1
NVM_FLASH_WRITEONCE?=0
UART_FLASH?=0
UART_QSPI_PROGRAM?=0
V?=0
NO_MPU?=1
RAM_CODE?=0
SPMATH?=0
SPMATHALL?=1
DUALBANK_SWAP?=0
PKA?=0
ENCRYPT=0
WOLFTPM?=0
ELF?=1
OPTIMIZATION_LEVEL=1
RISCV_MMODE?=1
STACK_SIZE_PER_HART=4096
NO_ASM?=0
LIBERO_FPGA_CONFIG_DIR?=
CFLAGS_EXTRA+=-DWOLFBOOT_MMODE_SMODE_BOOT
CFLAGS_EXTRA+=-DMPFS_SC_SPI
DISK_SDCARD?=0
DISK_EMMC?=0
WOLFBOOT_ORIGIN?=0x0A000000
WOLFBOOT_L2SCRATCH_SIZE?=512k
STACK_SIZE?=64k
WOLFBOOT_SECTOR_SIZE?=0x10000
WOLFBOOT_LOAD_ADDRESS?=0x82000000
WOLFBOOT_LOAD_DTS_ADDRESS?=0x8A000000
WOLFBOOT_RAMBOOT_MAX_SIZE=0x08000000
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x100000
WOLFBOOT_PARTITION_SIZE=0x3000000
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x3100000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x6100000
# Standalone DTB regions after the swap, as polarfire_mpfs250_qspi.config has
# them. A FIT carries its own fdt sub-image and never reaches these; they are
# the fallback for booting a plain kernel image out of QSPI.
WOLFBOOT_DTS_BOOT_ADDRESS=0x6110000
WOLFBOOT_DTS_UPDATE_ADDRESS=0x6120000
CFLAGS_EXTRA+=-DDEBUG_BOOT
14 changes: 13 additions & 1 deletion docs/PolarFire.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ The programmer's `--die` list covers `MPFS025T` through `MPFS460T` and their `_E

## Boot configurations

Seven ready-to-use config templates cover all supported boot mode / storage / memory combinations:
Nine ready-to-use config templates cover all supported boot mode / storage / memory combinations:

| Configuration | Config File | Boot Mode | Storage | Memory | HSS |
|---------------|-------------|-----------|---------|--------|-----|
Expand All @@ -229,6 +229,8 @@ Seven ready-to-use config templates cover all supported boot mode / storage / me
| **QSPI + L2-LIM** | `polarfire_mpfs250_hss_l2lim.config` | S-mode (U54 via HSS) | SC QSPI | L2-LIM (no DDR) | Yes |
| **M-Mode (no HSS)** | `polarfire_mpfs250_m_qspi.config` | M-mode (E51, no HSS) | SC QSPI | L2 Scratchpad | No |
| **M-Mode + DDR** | `polarfire_mpfs250_m.config` | M-mode (E51, no HSS) | SD Card | LPDDR4 (DDR) | No |
| **M-Mode + DDR, eMMC** | `polarfire_mpfs250_m_emmc.config` | M-mode (E51, no HSS) | eMMC | LPDDR4 (DDR) | No |
| **M-Mode + DDR, QSPI** | `polarfire_mpfs250_m_qspi_ddr.config` | M-mode (E51, no HSS) | SC QSPI | LPDDR4 (DDR) | No |
| **Boot mode 2 UBL** | `polarfire_mpfs250_ubl.config` | System Controller -> sNVM stub | eNVM (verifies it) | L2-LIM | No |

The **M-Mode + DDR** configuration brings up the LPDDR4 controller from
Expand All @@ -250,6 +252,16 @@ still produces a working M-mode wolfBoot without DDR. Add
`-DDEBUG_DDR` to `CFLAGS_EXTRA` for verbose register-level traces
during bring-up.

The eMMC and QSPI variants are the same configuration with a different
image store. One SDHCI controller reaches both the SD slot and the eMMC
through an external demux, so the SD and eMMC builds are mutually exclusive:
`DISK_EMMC=1` drives the eMMC pads (the Libero `ALT_` IOMUX set on a design
that configures both) and the SD slot is then unreachable until an SD build
runs again. The QSPI variant drops the disk driver entirely and loads the
signed FIT from flash with `src/update_ram.c`, which keeps the A/B update
slots the disk configuration does not have; its slots are 48 MB because a
Linux FIT does not fit the 32 MB slots of the application QSPI build.

For GitHub Actions, `tools/ci/gen_mpfs_libero_stub.sh` generates a
compile-only stub (every `LIBERO_SETTING_*` symbol referenced by the
HAL, defined to `0`; loop-bound settings to `1U`) so the M-Mode + DDR
Expand Down
8 changes: 5 additions & 3 deletions hal/hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,14 +284,16 @@ int hal_flash_test_dualbank(void)

#endif /* TEST_FLASH */

#ifdef MMU
#if defined(MMU) || defined(WOLFBOOT_FDT)
/* Weak default for targets with no configured device tree; some HALs also
* compile their own out under WOLFBOOT_NO_PARTITIONS. */
* compile their own out under WOLFBOOT_NO_PARTITIONS. Guarded to match the
* callers in src/update_ram.c and the declaration in include/hal.h: a target
* that parses a device tree without a full MMU configuration needs it too. */
WEAKFUNCTION void* hal_get_dts_address(void)
{
return NULL;
}
#endif /* MMU */
#endif /* MMU || WOLFBOOT_FDT */

WEAKFUNCTION int RAMFUNCTION hal_flash_protect(haladdr_t address, int len)
{
Expand Down
Loading
Loading