Skip to content

Add M-mode wolfBoot for PolarFire SoC MPFS250TS as an HSS replacement - #916

Open
dgarske wants to merge 25 commits into
wolfSSL:masterfrom
dgarske:mpfs250_hss_replace
Open

dgarske wants to merge 25 commits into
wolfSSL:masterfrom
dgarske:mpfs250_hss_replace

Conversation

@dgarske

@dgarske dgarske commented Sep 29, 2026 •

Copy link
Copy Markdown
Member

Description

wolfBoot as a complete replacement for the Hart Software Services on PolarFire SoC: the M-mode loader in eNVM brings up LPDDR4, loads and verifies a signed FIT from SD, stays resident as the SBI for Linux, and anchors its keys in the device.

  • DDR: Cadence controller core split from the PolarFire PHY/PLL/training platform; the read-first fix for cold-boot CPU writes; a retraining budget.
  • Athena F5200 offload driven by the wolfCrypt port in wolfcrypt/src/port/microchip (the lib/wolfssl submodule is bumped to pick it up), with a mandatory self-check, the hash path selectable with MPFS_ATHENA_SHA because it is slower than software over a whole image; the System Controller mailbox fenced from S-mode.
  • Keys in secure NVM: verification keystore served from sNVM, PUF-derived KEK, RFC 3394-wrapped image key, ROM-flag enforcement, and a read-only page survey behind MPFS_SNVM_DUMP (docs/PolarFire.md).
  • Hand-off hardening: SRST halts every hart, bounded console, page-wide trailer zeroization, PMP guard, zeroed key provider.
  • fit: FIT_RAMDISK_REQUIRED makes a FIT ramdisk that fails to load stop the boot, for an image whose initramfs is its only root filesystem.
  • SBI vendor extension on the HSS EID: version, serial, PUF-derived keys by purpose, bitstream services when fenced; Linux module (docs/PolarFire.md).
  • disk: failover before the golden boot (image key and slot-head erase via hal_disk_failover).
  • Boot mode 2: mpfs250_ubl, a User Boot Loader stub verifying a detached manifest over the eNVM wolfBoot and refusing anything below MPFS_UBL_MIN_VERSION; mpfs_bootmode2.sh for the secure dies, including the sNVM Master Key generation the vendor programmer never requests.
  • QSPI: the full CoreQSPI divider table with a compile-time range check, MPFS_QSPI_CLK_DIV defaulting to the divider where measured read throughput stops improving, and word-mode FIFO reads where the data phase is a whole number of words.
  • Watchdog and reset cause: the MSS watchdog policy corrected to what the hardware allows - there is no enable bit, the first refresh locks the window registers, and a refresh above MVRP is answered with a chip reset, so every refresh tests the forbidden-window bit rather than assuming it is clear - and the reset-cause register cleared by zeroing rather than write-one-to-clear; MPFS_WDT_NODES_KEEP for an OS that owns the watchdogs.
  • L2 scratchpad residency: the scratchpad range is flushed before the startup pin loop, so each line is allocated into a scratchpad way instead of updating a copy an earlier wide-masked access left in a normal way; the secondary harts zero their hart-local block only after the boot hart has pinned the scratchpad. Without this, wolfBoot's own .text, stack and trap vector could be evicted during a bulk image load and the hart faulted into a silent trap loop.
  • sdhci: the watchdog is serviced during the SDMA data phase, each buffer-boundary segment gets its own timeout budget, and the DMA Select field is cleared before SDMA is selected rather than OR-ed into whatever was left set.
  • riscv_sbi: the M-mode trap stack re-armed from the frame address; the remote-fence wait bounded by time.
  • System Controller SPI flash erase, write, read and directory update for a fenced OS (MPFS_SBI_SC_FLASH), so a bitstream can be staged where neither the mailbox nor the flash controller is reachable from S-mode.
  • docs/PolarFire.md: one document for the target - a quick start taking build, card and eNVM program end to end for the three ways in, with the console output each step must produce, then the configurations, QSPI and DDR notes, boot mode 2, the sNVM/PUF root of trust and the SBI extension. docs/Targets.md keeps the summary tables and links to it.

Testing

MPFS250TS Video Kit, cold and warm boots to a Yocto login with the root filesystem in the FIT initramfs, in both boot mode 1 and boot mode 2; a DDR soak; encrypted images under the PUF-wrapped key; the Athena offload confirmed serving calls on silicon; sNVM keystore with ROM-flag enforcement; the SBI extension from Linux, unfenced and fenced, including erase, program and read-back of the System Controller flash through the fence; failover zeroize and re-provisioning; the QSPI divider swept across the controller's whole range on silicon, with the data checked at every setting; the boot mode 2 stub run as the System Controller runs it, over JTAG, including its refusal of an eNVM image below the version floor; and ML-DSA-87 booting to a login in both boot modes, with the stub's manifest still ECC384 because the stub has no room for a PQC verifier.

HSS-only services (IHC, remoteproc, Athena AES over SBI), an eNVM update from Linux under boot mode 2, and the MRAM part on the customer board are follow-on work.

@dgarske dgarske self-assigned this Sep 29, 2026
Copilot AI balanced review requested due to automatic review settings September 29, 2026 23:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Default sNVM ranges overlap, some option combinations fail to build, and diagnostics expose PUF-derived secret bytes.

Review effort: Balanced
Findings: 4 High severity · 3 Medium severity · 5 Low severity

Open (12)
What changed in this PR

Adds PolarFire SoC hardware crypto acceleration, PUF-backed key protection, and sNVM trust-anchor storage, alongside M-mode boot fixes.

Changes:

  • Adds Athena SHA-384/AES-CTR offload and System Controller services.
  • Adds sNVM keystore and PUF-wrapped encryption-key support.
  • Fixes scratchpad initialization, DDR ordering, partition selection, and RISC-V ABI settings.
File Description
Makefile Wires new sNVM objects and linker parameters.
arch.mk Updates MPFS DDR validation and ABI flags.
options.mk Adds sNVM, KEK, and Athena options.
include/​user_settings.h Enables AES for KEK support.
include/​snvm_keystore.h Defines the sNVM keystore layout.
include/​snvm_kek.h Defines KEK and wrapped-key APIs.
hal/​mpfs250.h Adds mailbox, sNVM, PUF, and Athena interfaces.
hal/​mpfs250.c Implements services and crypto callbacks.
hal/​mpfs250_athena.c Adapts the external CAL library.
hal/​mpfs250_ddr.c Reorders DDR controller programming.
hal/​mpfs250-m.ld Expands configurable scratchpad and stack sizing.
src/​boot_riscv_start.S Pins all scratchpad cache ways.
src/​snvm_keystore.c Implements the sNVM trust-anchor backend.
src/​snvm_kek.c Implements PUF KEK derivation and key wrap.
src/​encrypt_key_snvm_puf.c Supplies wrapped disk-encryption keys.
src/​update_disk.c Adds staged DDR decryption.
src/​libwolfboot.c Supports custom keys without partitions.
tools/​unit-tests/​unit-snvm-keystore.c Tests keystore bounds and paging.
tools/​unit-tests/​Makefile Registers the new unit test.
config/​examples/​polarfire_mpfs250.config Corrects stock GPT slot selection.
config/​examples/​polarfire_mpfs250_m.config Expands M-mode scratchpad and stack.
docs/​Targets.md Links hardware-root-of-trust documentation.
docs/​polarfire_snvm_puf.md Documents provisioning and validation.
docs/​keystore.md Documents the sNVM backend.
docs/​encrypted_partitions.md Documents PUF-wrapped custom keys.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread hal/mpfs250.c Outdated
Comment thread include/snvm_kek.h
Comment thread options.mk Outdated
Comment thread src/snvm_kek.c Outdated
Comment thread src/snvm_kek.c Outdated
Comment thread docs/polarfire_snvm_puf.md Outdated
Comment thread docs/polarfire_snvm_puf.md Outdated
Comment thread hal/mpfs250.c Outdated
Comment thread include/snvm_kek.h Outdated
Comment thread include/snvm_kek.h Outdated
@dgarske
dgarske force-pushed the mpfs250_hss_replace branch 4 times, most recently from de33a73 to 76f5e5f Compare September 30, 2026 21:19
@dgarske
dgarske requested a balanced review from Copilot September 30, 2026 23:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Comment thread include/snvm_kek.h
Comment thread include/snvm_keystore.h Outdated
Comment thread options.mk
Comment thread options.mk
Comment thread src/encrypt_key_snvm_puf.c Outdated
Comment thread include/snvm_keystore.h Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread docs/polarfire_snvm_puf.md Outdated
Comment thread options.mk Outdated
Comment thread options.mk
Comment thread src/encrypt_key_snvm_puf.c Outdated
Comment thread hal/mpfs250.c Outdated
Comment thread hal/mpfs250.c Outdated
Comment thread options.mk Outdated
@dgarske
dgarske force-pushed the mpfs250_hss_replace branch 4 times, most recently from c1156a4 to 9961f39 Compare October 3, 2026 01:35
@dgarske
dgarske requested a balanced review from Copilot October 6, 2026 21:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Comment thread hal/mpfs250_ddr.c
Comment thread hal/mpfs250_snvm.c
Comment thread src/riscv_sbi.c
Comment thread src/riscv_sbi.c Outdated
Comment thread hal/mpfs250-m.ld
Comment thread hal/mpfs250.c Outdated
Comment thread hal/mpfs250.c Outdated
Comment thread hal/mpfs250_snvm.c
Comment thread src/riscv_sbi.c Outdated
Comment thread docs/polarfire_snvm_puf.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread hal/mpfs250_ddr.c Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The security option can silently provide no PMP isolation, and zeroization detection checks only the header rather than the complete page.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

Open (2)
Resolved since last review (1)

Comment thread options.mk
Comment thread hal/mpfs250_snvm.c Outdated
@dgarske
dgarske force-pushed the mpfs250_hss_replace branch from b8062fa to 20df3d5 Compare October 26, 2026 18:15

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Fenrir Automated Review — PR #916

Scan targets checked: wolfboot-src, wolfboot-bugs
Not reviewed (no scan target covers them): .github/workflows/test-configs.yml, .gitignore, Makefile, arch.mk, config/examples/polarfire_mpfs250.config, config/examples/polarfire_mpfs250_m.config, config/examples/polarfire_mpfs250_m_qspi.config, config/examples/polarfire_mpfs250_ubl.config, docs/PolarFire.md, docs/README.md, docs/Targets.md, docs/compile.md, docs/encrypted_partitions.md, docs/keystore.md, hal/mpfs250-m.ld, hal/mpfs250.h, hal/mpfs250_snvm.h, hal/mpfs250_ubl.h, hal/mpfs250_ubl.ld, lib/wolfssl and 8 more
Coverage: 12 of 20 in-scope changed file(s) opened by the reviewer; not opened: include/riscv_sbi.h, include/sdhci.h, src/update_ram.c, tools/linux/wolfboot-sbi/wolfboot_sbi.c, tools/unit-tests/unit-mpfs-wdt.c, tools/unit-tests/unit-snvm-kek.c, tools/unit-tests/unit-snvm-keystore.c, tools/unit-tests/unit-update-disk-failover.c

Findings: 2
2 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Review tier: Lite

Comment thread hal/mpfs250.c
static long sbi_vendor_sc_run(uint8_t opcode, uint32_t index,
unsigned long *val)
{
long err = sbi_vendor_sc_start(opcode, index, NULL, 0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

sbi_vendor_sc_run publishes sbi_scb_started, letting a concurrent SC_STATUS release the lock it still holds · Race conditions

sbi_vendor_sc_run goes through sbi_vendor_sc_start, which sets sbi_scb_started=1, even though it waits and unlocks itself. Once the mailbox goes idle, another hart's SBI_WOLF_FID_SC_STATUS can clear the flag and call sbi_scb_unlock() while this call still runs. The later second unlock can then drop a third hart's lock, so two harts can drive the mailbox at once (e.g. corrupting a one-shot GET_KEY PUF response).

Suggested fix: In sbi_vendor_sc_run, take sbi_scb_trylock() and call mpfs_scb_start() directly, without setting sbi_scb_started, which only asynchronous starts should set.

Related known findings (similar but distinct; listed for context, not part of this finding)

  • Earlier finding on this pull request: 1) File/function: both are in hal/mpfs250.c, but the candidate is in sbi_vendor_sc_run and -3 is in the SBI_WOLF_FID_SC_STATUS handler in sbi_hal_vendor_ecall. 2) Faulting operation: the candidate has the synchronous sc_run path set the async-only sbi_scb_started flag via sbi_vendor_sc_start. -3 has SC_STATUS call sbi_scb_unlock() whenever the mailbox is idle, without checking the lock owner. 3) Root cause: both end in the same SC_STATUS early unlock racing a lock held by another hart. The candi

rc = -EINVAL;
break;
}
rc = 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SC flash erase loop never yields the CPU during long blocking SBI erases · Logic errors

Each loop pass makes a blocking M-mode call that erases one 64 KB SPI sector. A multi-MB range therefore runs in kernel context for tens of seconds while holding the mutex, with no cond_resched() and no signal check, which triggers soft-lockup/RCU-stall reports and cannot be interrupted.

Suggested fix: In each erase iteration, call cond_resched() and stop with -EINTR when fatal_signal_pending(current) is set.
Basis: Linux Documentation/admin-guide/lockup-watchdogs.rst: a soft lockup is a bug that makes the kernel loop in kernel mode for more than 20 seconds without letting other tasks run.

@dgarske
dgarske force-pushed the mpfs250_hss_replace branch from 9964ae8 to 1df0123 Compare October 26, 2026 23:47
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.

4 participants