Skip to content

Add NXP i.MX95 post-quantum demo for the A55 cluster and Cortex-M7 - #13

Open
dgarske wants to merge 14 commits into
wolfSSL:masterfrom
dgarske:imx95_pqc_demo
Open

dgarske wants to merge 14 commits into
wolfSSL:masterfrom
dgarske:imx95_pqc_demo

Conversation

@dgarske

@dgarske dgarske commented Aug 19, 2026

Copy link
Copy Markdown
Member

A demo running entirely on a Toradex SMARC iMX95: wolfBoot verifies and boots Linux on the Cortex-A55 cluster with ML-DSA-87, a second wolfBoot verifies and boots Zephyr on the Cortex-M7 with the same algorithm, and both cores then run wolfCrypt ML-KEM and ML-DSA benchmarks. Output is a single stream on the board's serial console, tagged by core.

Depends on wolfBoot wolfSSL/wolfBoot#888 for the imx95_a55 target, including the stage 1 that replaces U-Boot SPL. The imx95_m7 target it also uses is already merged.

What it adds

  • demo/ - board-side orchestration, the console stream, and its systemd units
  • m7/ - the Zephyr payload wolfBoot verifies, and its overlay
  • container/ - the wolfCrypt benchmark container for the A55 cluster
  • tools/ - AHAB container packaging, eMMC boot-partition write and select, and memtool for reading the two cores' consoles
  • docs/BUILD.md - building the whole demo from a stock module
  • docs/BOOT-WALKTHROUGH.md - the boot explained stage by stage, and how to switch between the stock and wolfBoot chains

Notes

  • The Zephyr payload deliberately does not use samples/subsys/ipc/openamp_rsc_table. That sample assumes Linux loaded its ELF and resolved its vring addresses, but here Linux loads wolfBoot, so the sample would wait forever for a resource table that is not the one being polled. This payload uses fixed vring addresses matching wolfBoot's table.
  • The Cortex-M7 starts once per Linux boot: echo stop > .../state fails on this BSP while the core is running, so replaying the boot means a power cycle.

Hardware / test status

Validated on a Toradex SMARC iMX95 (LPUART1, 115200 8N1): cold boot to Torizon userspace with both cores verified, over repeated power cycles. The build path in docs/BUILD.md was reproduced end to end from a stock module - both AHAB containers and the kernel FIT it produces come out byte-identical to the ones running on the board.

Scope

The A55 benchmark runs in a container; a native build is not provided. The serial console is the demo; the DisplayPort two-pane renderer is still in demo/ and is opt-in via install-autostart.sh --display.

@dgarske dgarske self-assigned this Aug 19, 2026
Copilot AI lite review requested due to automatic review settings August 19, 2026 21:52

Copilot AI 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.

Pull request overview

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Adds an i.MX95 “post-quantum on both clusters” demo that pairs Linux-side wolfCrypt PQC benchmarks (A55) with wolfBoot ML-DSA-87 verified boot and console relay from the Cortex-M7.

Changes:

  • Add a /dev/mem mmap-based memtool utility for staging payloads and dumping the M7 shared-memory console.
  • Add a Zephyr OpenAMP/RPMsg payload for M7 that relays wolfBoot’s shared-memory console to Linux as an RPMsg TTY.
  • Add board orchestration scripts, a two-pane console renderer, and a benchmark container build/runtime setup.

Reviewed changes

Copilot reviewed 18 out of 20 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
imx95-pqc-demo/tools/memtool.c Adds /dev/mem mmap read/write/load/fill and M7 console ring dump tooling.
imx95-pqc-demo/m7/zephyr-app/src/main.c Implements the M7-side OpenAMP/RPMsg endpoint and wolfBoot console relay logic.
imx95-pqc-demo/m7/zephyr-app/prj.conf Configures Zephyr for OpenAMP + minimal logging and documents MPU constraints.
imx95-pqc-demo/m7/zephyr-app/CMakeLists.txt Defines the Zephyr application build.
imx95-pqc-demo/m7/imx95_wolfboot.overlay Relocates the Zephyr image, enables MU, and declares MPU-accessible console/status region.
imx95-pqc-demo/m7/build.sh Provides a reproducible Zephyr build producing a raw binary payload.
imx95-pqc-demo/demo/twopane.py Renders the two-pane demo view on a console without tmux/screen dependencies.
imx95-pqc-demo/demo/stage.sh Stages demo artifacts to the board and builds/stages memtool.
imx95-pqc-demo/demo/m7-start.sh Starts remoteproc and stages the signed payload into the M7 boot partition region.
imx95-pqc-demo/demo/m7-console-tail.sh Provides a console-ring tailer for the M7 pane (alternative to RPMsg TTY).
imx95-pqc-demo/demo/demo-run.sh Orchestrates container start, M7 start, and launches the renderer to a target TTY.
imx95-pqc-demo/container/entrypoint.sh Runs benchmark cycles and selects baseline vs sha3-crypto build at runtime.
imx95-pqc-demo/container/docker-compose.yml Defines the benchmark container service for on-board execution/logging.
imx95-pqc-demo/container/build-image.sh Builds (and optionally pushes) the arm64 demo container image.
imx95-pqc-demo/container/build-aarch64.sh Cross-builds wolfSSL for aarch64 in baseline and sha3-crypto configs.
imx95-pqc-demo/container/Dockerfile Multi-stage image build that cross-compiles wolfSSL and ships benchmarks.
imx95-pqc-demo/README.md Documents the demo purpose, measurements, build steps, and key gotchas.
README.md Adds the new i.MX95 PQC demo to the repository’s example list.

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

Comment thread imx95-pqc-demo/tools/memtool.c
Comment thread imx95-pqc-demo/tools/memtool.c
Comment thread imx95-pqc-demo/tools/memtool.c
Comment thread imx95-pqc-demo/tools/memtool.c
Comment thread imx95-pqc-demo/tools/memtool.c
Comment thread imx95-pqc-demo/tools/memtool.c
Comment thread imx95-pqc-demo/m7/zephyr-app/src/main.c
Comment thread imx95-pqc-demo/m7/zephyr-app/src/main.c
Comment thread imx95-pqc-demo/demo/twopane.py
Comment thread imx95-pqc-demo/demo/twopane.py Outdated
@dgarske
dgarske force-pushed the imx95_pqc_demo branch 3 times, most recently from 486acd5 to 68e60a7 Compare August 21, 2026 03:56
@dgarske
dgarske marked this pull request as ready for review September 16, 2026 21:52
@dgarske

dgarske commented Sep 20, 2026

Copy link
Copy Markdown
Member Author

Follow-ups from taking the demo through a full bench cycle and then walking
docs/BUILD.md from a clean clone.

The Cortex-M7 benchmark was faulting intermittently, then on every boot once
the display renderer was enabled. It was not a demo bug: wolfcrypt's
bench_mlkem() hands bench_mlkem_keygen() a key object straight from XMALLOC,
and that function calls wc_MlKemKey_Free() at the top of its loop, so the first
iteration frees whatever pointers the uninitialized memory held.
bench_frodokem() and the SLH-DSA benchmark already zero their keys for the same
reason. Fixed in wolfssl; BUILD.md records the dependency, since rebuilding the
payload without it walks straight back into the fault.

The DisplayPort path is now in the repo rather than living only on the board:
demo-display-fg.sh, wolfssl-display.service, and a font lookup in drmfb.py.
install-autostart.sh --display enables the renderer alongside the serial unit
instead of replacing it, so the screen is a second view of the same run, and it
disables the older combined wolfssl-demo.service that fought it for the panel.
No font is committed; Torizon ships none and has no package manager, so
BUILD.md says how to stage one.

Walking the build guide from a clean clone turned up ten defects, all fixed
here. The two worth calling out: the guide told you to import an existing
signing key with keytools/keygen -i, which leaves the tree with a keystore and
no private key, so the next plain make offers to overwrite the keystore your
signed images match - it now uses USER_PRIVATE_KEY/USER_PUBLIC_KEY, which never
invokes the generator. And emmc-write-boot.sh verified its readback over the
whole 31.5 MiB boot partition rather than the image length, so any image
smaller than the partition reported MD5 MISMATCH on a good write.

Also: the A55 verified-boot lines are replayed from the DDR log ring after the
kernel messages, where an audience can read them; two starters can no longer
load the M7 payload at once; and the eMMC helpers give sudo a terminal.

Verified on hardware. The M7 benchmark now completes on ten of ten power
cycles, against zero of three before the fix. Rebuilding the FIT from the
guide's steps reproduces it byte-for-byte with SOURCE_DATE_EPOCH pinned, and
the board boots and verifies the result.

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.

2 participants