Same Chip, Two Walls: TrustZone-M vs RISC-V PMP on the RP2350

TL;DR

The RP2350 has both an Arm Cortex-M33 pair (TrustZone-M) and a RISC-V Hazard3 pair (PMP) on one die. I built the same minimal isolation demo on both — a guarded secret, a call-in service, and a deliberate illegal read — and verified both on the same Pico 2 over SWD. Findings, all measured rather than read off a spec:

  • Same result, different shape. Both block the illegal read with the secret intact. TrustZone partitions the address map and the toolchain builds the gate for you; PMP filters by privilege and you write the gate yourself.
  • Arm tells you where it broke, Hazard3 doesn’t. SFSR = 0x48 sets SFARVALID, so the faulting address is there for the taking. Hazard3 leaves mtval = 0 on a PMP access fault. mcause = 5 is all you get.
  • The same silicon only fought one of them. The Arm Non-Secure side hit two RP2350 walls that forced a bare-metal, RAM-resident NS image. The RISC-V U-mode side just ran from flash.
  • Hazard3 has a trick TrustZone structurally can’t do: Xh3pmpm lets M-mode sandbox itself, reversibly.
  • Neither of them covers the DMA. That’s a separate MPU, and it’s the RP2350 detail most likely to quietly ruin your day.

Code: rp2350-tz-teeminimal-tz (Arm) and minimal-pmp (RISC-V).

Read more

RK3576 UEFI: Teaching EDK2 to Drive HDMI, USB, and eMMC

TL;DR

  • EDK2 boots a real UEFI environment on the RK3576 — swapping out U-Boot proper for EDK2 after BL31, verified on two boards (Radxa ROCK 4D over SPI, ArmSoM CM5-IO over SD).
  • HDMI’s worst bug was the debugging itself: reading overlay registers back after enable — read-only, no writes — silently perturbed VOP2 and killed the picture; the one real fix underneath all the phantom bugs was a register-write-ordering issue.
  • USB needed two DWC3 xHCI workarounds: skip a structurally-redundant EvaluateContext on SuperSpeed, and mark the hub slot-context flag before the interrupt endpoint arms, or the onboard hub never enumerates.
  • eMMC was simply held in hardware resetEMMC_RST_N defaults to 0, and RK3588 boards never notice because SPL boots from eMMC and clears it in passing; RK3576 booting SD/SPI never touches that bit at all.
  • Ethernet’s PHY part number was copy-pasted wrong everywhere — four independent sources call it an RTL8211F; the schematic says MotorComm YT8531C. It works either way (both are generic Clause-22 PHYs), until you need PHY-specific tuning.
  • Two firmware/OS handoff bugs lived below any single peripheral: a coincidental MZ byte pair in unrelated memory crashed the OS-loader scan, and an unpopulated RAM bank register read as all-zero decoded into a phantom 256 MB.
Read more

Porting OP-TEE to the RK3576

TL;DR

  • It came up secure end-to-end: memory map + DDR firewall, a real hardware TRNG (RK3576’s RKRNG, not RK3588’s TRNG_V1), and an OTP-derived Hardware Unique Key — xtest passes 113/114 on hardware, and the one miss was a build config, not the platform.
  • The silent console was a forced-override bug. TF-A hands RK3576’s BL32 no non-secure DT pointer, so the normal console probe never runs; needs CFG_EARLY_CONSOLE forced on (not just defaulted) and TF-A/OP-TEE agreeing on UART0.
  • The OTP key is a one-way door, and it’s treated like one: ephemeral HUK by default, persistent fuse-burning gated behind an explicit off-by-default flag until the OTP index is confirmed — burn the wrong row and it’s permanent.
  • Base platform support (#7821) is merged into mainline OP-TEE; the OTP key-derivation half (#7841) is still in review, split out deliberately so the irreversible part gets its own scrutiny.
Read more

A One-Line TF-A Fix, and the Review That Came With It

TL;DR

  • The patch deletes one line — a leftover GICV2_G0_FOR_EL3 := 1 override in plat/rockchip/rk3576/platform.mk that was both redundant (the tree-wide default is already 0) and wrong (RK3576 has no reason to route GICv2 Group 0 to EL3).
  • It’s still the first thing I sent to Trusted Firmware-A, and it got read closely by engineers from ST, Google, and Rockchip before it landed.
  • The point isn’t the diff size — it’s what upstream review actually asks of you even when the change is nearly nothing: is this safe for every configuration, not just yours?
Read more