You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 5df9e95
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: docs/Targets.md
+25-1Lines changed: 25 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9859,7 +9859,14 @@ Both caches are enabled by `hal_init()`, which matters because verifying an imag
9859
9859
9860
9860
## NXP i.MX95 Cortex-A55 (BL33)
9861
9861
9862
-
wolfBoot replaces U-Boot proper on the i.MX95's Cortex-A55 cluster: it is the third image in AHAB container 2 (after BL31 and OP-TEE), entered by BL31 at `0x90200000` in NS-EL2, where it verifies a Linux FIT (kernel + DTB + initramfs) with ML-DSA-87 and boots it at EL2. SPL/ELE authenticate the container itself (AHAB), so the chain is ROM -> ELE -> SPL -> BL31 -> wolfBoot -> Linux once SRK fuses are programmed. NXP also documents an OEM PQC SRK hybrid (ML-DSA) AHAB flow, so the container half of the chain can be post-quantum as well.
9862
+
wolfBoot replaces U-Boot proper on the i.MX95's Cortex-A55 cluster: it is the third image in AHAB container 2 (after BL31 and OP-TEE), entered by BL31 at `0x90200000` in NS-EL2, where it verifies a Linux FIT (kernel + DTB + initramfs) with ML-DSA-87 and boots it at EL2. NXP also documents an OEM PQC SRK hybrid (ML-DSA) AHAB flow, so the container half of the chain can be post-quantum as well.
9863
+
9864
+
Which component authenticates the containers depends on which slot wolfBoot occupies, and the two cases are not the same:
9865
+
9866
+
-**wolfBoot as BL33 only** (this section). U-Boot SPL is still in container 0 and still calls the ELE to authenticate container 2 before BL31 runs, so the chain is ROM -> ELE -> SPL -> BL31 -> wolfBoot -> Linux once SRK fuses are programmed.
9867
+
-**wolfBoot as stage 1 as well** (next section). SPL is gone, so wolfBoot performs that ELE call itself. `IMX95_AHAB_AUTH` is what does it, and it is on by default; the chain becomes ROM -> ELE -> wolfBoot stage 1 -> BL31 -> wolfBoot BL33 -> Linux.
9868
+
9869
+
In both cases the ROM and the ELE authenticate container 0 before any A55 code runs, so whichever image sits in the SPL slot is itself verified.
9863
9870
9864
9871
Validated on a Toradex SMARC iMX95 with `TARGET=imx95_a55` (`config/examples/imx95-a55.config`): full boot to Linux userspace with the FIT on the carrier SD (uSDHC2, `hal/imx95_usdhc.c` - i.MX uSDHC, not SDHCI-compatible).
9865
9872
@@ -9884,6 +9891,23 @@ DDR is up before stage 1 runs, because the OEI did it, so stage 1 only needs the
9884
9891
9885
9892
Two things differ from the BL33 build. The console is programmed rather than inherited, since nothing has configured LPUART1 yet. And on eMMC the containers live in a boot partition, not the user area: `imx95_emmc_boot_partition()` reads back the same `PARTITION_CONFIG` field that told the ROM which one to load from, and reads follow it.
9886
9893
9894
+
#### What stage 1 authenticates
9895
+
9896
+
Taking SPL's slot means taking over the step SPL performed. The boot ROM and the ELE authenticate container 0, so stage 1 is verified code, but the container it goes on to load BL31, OP-TEE and BL33 out of is a separate one that nothing has checked yet. `IMX95_AHAB_AUTH=1` (the default) makes stage 1 ask the ELE to check it, the same three calls U-Boot's SPL makes:
9897
+
9898
+
1. The container's header, image table and signature block are staged into DDR at `0x90000000` - NXP's own `IMG_CONTAINER_BASE` for this SoC - because the ELE reads the address it is given over its own master port and requires DDR. Every value stage 1 then acts on comes from those staged bytes; the medium is not consulted for the table again.
9899
+
2.`ELE_OEM_CNTN_AUTH_REQ` authenticates the header.
9900
+
3. Each image is loaded to its destination and then checked in place with `ELE_VERIFY_IMAGE_REQ`, one at a time so a failure names the image. `ELE_RELEASE_CONTAINER_REQ` follows, before the jump.
9901
+
9902
+
Any failure stops the boot. `IMX95_AHAB_AUTH=0` builds without it, for bring-up on a part whose containers are not signed; it cannot be combined with `IMX95_STAGE1_PASSTHROUGH` or `IMX95_STAGE1_ALLOW_SELF_OVERLAP`, both of which would carry on past a refusal, and the build fails if you try.
9903
+
9904
+
Separately, and regardless of that flag, stage 1 bounds every destination *before* writing any of them. An image is streamed straight from the boot device into the address the container names, so a check made afterwards would come too late to matter: by then the bytes have landed. Destinations must lie inside DDR, must not overlap the staging window, this loader, the M7 carveout, the ELE shared-memory region or the VPU boot area, must not overlap each other once rounded up to the block size, and image 0 must be an A55 executable whose entry point lies inside its own bytes.
9905
+
9906
+
Two limits are worth stating plainly:
9907
+
9908
+
-**On an open part AHAB reports success without enforcing a signature.** That is why an unsigned container boots at all. What authentication buys there is an ELE-checked hash of each image against a table nobody signed - integrity, not authenticity. Stage 1 prints the lifecycle on every boot so the difference is visible rather than implied. Enforcement begins when the SRK hash is fused; see the i.MX8QuadMax AHAB section above for what that costs and why it is irreversible.
9909
+
-**Authenticating the container does not prevent rollback.** The offset of the next container is derived by walking container 0, which stage 1 reads off the medium and nothing re-authenticates, so a different but validly signed older container set would authenticate happily. That needs `sw_version`/`fuse_version` policy or the AHAB monotonic counter, neither of which is implemented here.
9910
+
9887
9911
## TI C2000 C28x (LAUNCHXL-F28P55X)
9888
9912
9889
9913
wolfBoot runs on the Texas Instruments C2000 C28x DSP (TMS320F28P550SJ, 150 MHz) as a secure execute-in-place (XIP) bootloader. The C28x is word-addressed with `CHAR_BIT == 16` (no 8-bit type -- each octet occupies one 16-bit cell), built with the TI `cl2000` toolchain against wolfSSL's wide-byte (`CHAR_BIT != 8`) support.
0 commit comments