This project modernized the entire firmware stack for the SolidRun HoneyComb LX2K (LX2160A CEx7) from a stale 2021-era codebase to current upstream releases, bringing the existing OP-TEE/StandaloneMm Secure Boot support forward from OP-TEE 3.14.0 to 4.9.0.
Result: A fully modern, Secure Boot-enabled firmware booting Ubuntu 24.04 via shim → GRUB → signed kernel.
| Component | Before | After |
|---|---|---|
| ATF (TF-A) | NXP lf_v2.4 (2021) | NXP lf_v2.12 (2025) |
| RCW | SolidRun LSDK-20.04-sr (2020) | NXP lf-6.6.52-2.2.0 + SolidRun CEX7 configs |
| EDK2 | edk2-stable202105 | edk2-stable202602 |
| edk2-platforms | SolidRun fork (2021) | upstream master + SolidRun overlay |
| Secure Boot stack | OP-TEE 3.14.0 + edk2-stable202105 | OP-TEE 4.9.0 + edk2-stable202602 |
┌─────────────────────────────────────────────────┐
│ Ubuntu 24.04 │
├─────────────────────────────────────────────────┤
│ GRUB (signed by Canonical, verified by shim) │
├─────────────────────────────────────────────────┤
│ shim (signed by Microsoft UEFI CA 2011) │
├─────────────────────────────────────────────────┤
│ UEFI (EDK2 edk2-stable202602) │
│ ├─ VariableSmmRuntimeDxe (NS proxy) │
│ ├─ MmCommunicationOpteeDxe (NS↔S bridge) │
│ └─ SecurityStubDxe + DxeImageVerificationLib │
├─────────────────────────────────────────────────┤
│ OP-TEE 4.9.0 (Secure World) │
│ └─ StandaloneMm (EFI variable services) │
│ ├─ VariableStandaloneMm (auth variables) │
│ ├─ FaultTolerantWriteStandaloneMm │
│ └─ EepromFvb (I2C EEPROM NV storage) │
├─────────────────────────────────────────────────┤
│ ATF v2.12 (BL1/BL2/BL31) │
│ └─ DDR init, SerDes, PSCI, SPD=opteed │
├─────────────────────────────────────────────────┤
│ RCW + PBI (NXP lf-6.6.52 + SolidRun CEX7) │
│ └─ PLL ratios, pin mux, errata workarounds │
└─────────────────────────────────────────────────┘
Cherry-picked SolidRun's 16 board-support patches from their lx2160a_build repo onto NXP's lf_v2.4 ATF branch. Verified the platform boots to GRUB.
Updated EDK2 from edk2-stable202105 to edk2-stable202602 (5 years of upstream development). Key source-level fixes required across SolidRun's platform code:
AsmMacroIoLibV8.h→AsmMacroLib.h(header rename)ARM_CORE_INFOstruct: droppedClusterIdfield- IORT ACPI:
RMR_DESC→MEM_RANGE_DESC, field renames NET_RANDOM/NetRandomInitSeed→PseudoRandomU32SMBIOS_CACHE_SIZEbitfield struct changePROCESSOR_ID_DATAnew 4-field struct on AARCH64
Critical fix: NULL|LzmaCustomDecompressLib must be linked into the PeilessSec module's DSC entry for the LZMA decompression handler to register. Without it, DecompressFirstFv() fails and UEFI hangs after the SEC banner.
Rebased SolidRun's 16 patches from NXP lf_v2.4 to NXP lf_v2.10. Clean cherry-picks, no conflicts.
Strategy: Start from upstream tianocore/edk2-platforms master (already edk2-stable202602 compatible) and port SolidRun's hardware support forward. This means future EDK2 updates are nearly free for infrastructure code.
| Category | Files | Action |
|---|---|---|
| SolidRun-only | 640 | Copied onto upstream base |
| Overlapping | 18 | Upstream-first, minimal SolidRun additions |
| Upstream-only | 40+ | Kept as-is |
Key merge decisions:
- IoAccessLib: Took upstream's
GetMmioOperations()API, updated 17 SolidRun files that used the oldSwapMmioXxx()functions - PciHostBridgeLib: Kept SolidRun's version (1756 lines with SMMU/IORT/FDT integration vs upstream's 430-line version)
- NxpQoriqLs.dec: Added SolidRun's ~260 additional PCDs/GUIDs to upstream's DEC
- I2cDxe: Reverted to Phase 2's self-contained driver (upstream's NonDiscoverable Device model requires a platform registration driver that doesn't exist for LX2160aCex7)
- SocGetClock: Fixed signature mismatch (upstream changed from variadic to enum-based API)
This was the most complex phase. The existing OP-TEE 3.14.0 + edk2-stable202105 Secure Boot support needed porting forward to OP-TEE 4.9.0 + edk2-stable202602, which required significant changes to both the OP-TEE SP hosting and the EDK2 StandaloneMm configuration.
Only 2 of SolidRun's original patches were needed on 4.9.0. API changes:
vm_map_pad()→vm_map()(padding parameter removed)TEE_MATTR_CACHE_NONCACHE→TEE_MATTR_MEM_TYPE_DEV(memory attribute rename)CORE_MEM_TA_RAM→CORE_MEM_NON_SEC(memory region type rename)
New patches added during bring-up:
- FFA_FEATURES handler: StandaloneMm issues
FFA_FEATURESqueries that OP-TEE 4.9.0 didn't handle, causing immediate SP termination - StMM heap increase: 402→800 pages. With OpenSSL + AuthVariableLib + VarCheckPolicyLib loaded, 1.57 MiB of heap was insufficient
The StandaloneMm build required extensive library path updates for edk2-stable202602:
ArmSvcLib,FvLib,CompilerIntrinsicsLibmoved to MdePkgStandaloneMmCoreEntryPointmoved to ArmPkg (ARM-specific version)DevicePathLibfor MM_STANDALONE: must useUefiDevicePathLibBase.inf(MODULE_TYPE=BASE)PcdFfaEnableremoved from upstream; library selection determines FFA behaviorPcdFfaLibConduitSmc=FALSE— SP runs at S-EL0 under OP-TEE, must use SVC not SMCPcdShadowBfv=FALSE— BFV is loaded into RAM by OP-TEE, no shadow copy needed
The most challenging debugging involved understanding the ARM StandaloneMm communication flow, which differs significantly from x86:
NS DXE side: Secure World (StMM):
VariableSmmRuntimeDxe VariableStandaloneMm
→ MmCommunicate() ← MmiManage(&GUID, ...)
→ OpteeInvokeFunction() ← PiMmCpuTpFwRootMmiHandler
→ OP-TEE (stmm_sp.c) ← DelegatedEventLoop
→ FFA_MSG_SEND_DIRECT_REQ ← ParseFfaSvcRequest
Bug 1: Variable Arch Protocol never installed
VariableSmmRuntimeDxe (NS side) registers a callback on gEfiSmmVariableProtocolGuid, but nobody installs that signal protocol on the NS DXE side. On x86, PiSmmIpl bridges this from SMM to DXE. On ARM with OP-TEE, no bridge exists — VariableStandaloneMm.c:VariableNotifySmmReady() is an empty no-op.
Fix: Link VariableMmDependency NULL library into MmCommunicationOpteeDxe. This DXE library constructor installs the signal protocols. Used by upstream VExpress-FVP, Juno, and OVMF — but not documented anywhere as a requirement.
Bug 2: ASSERT in MmiManage — VarCheckPolicyLib handler missing
VariablePolicySmmDxe.c (NS side) sends variable policy commands to StMM using gVarCheckPolicyLibMmiHandlerGuid. No MMI handler was registered in StMM because VarCheckPolicyLibStandaloneMm wasn't linked into VariableStandaloneMm.
Fix: Added NULL|VarCheckPolicyLibStandaloneMm.inf to VariableStandaloneMm in StandaloneMm.dsc. Only OVMF's StandaloneMm path had this — none of the upstream ARM DSCs did.
Bug 3: StMM heap exhaustion (EFI_OUT_OF_RESOURCES)
After hundreds of successful MM communications, MmAllocatePool in PiMmStandaloneMmCpuDriverEntry fails. The OpenSSL crypto library + AuthVariableLib + VarCheckPolicyLib consume too much of the 402-page (1.57 MiB) heap.
Fix: Increased stmm_heap_size from 402 to 800 pages (3.2 MiB) in OP-TEE's stmm_sp.c.
EepromFvb registers a SetVirtualAddressMap event handler that converts physical addresses to virtual. But VariableRuntimeDxe also has a handler that calls through the FVB protocol. If the events fire in the wrong order, the FVB protocol pointers get double-converted, causing a crash.
Fix (applied to edk2 core): Shadow copy approach in VariableDxe.c — saves a pre-conversion copy of the FVB protocol so the variable driver always has valid pointers regardless of event ordering.
Cherry-picked the same 16 SolidRun patches from lf_v2.10 to NXP's latest lf_v2.12. Only 1 conflict (the DISABLE_S5 build flag, trivially resolved alongside new upstream build options).
Replaced the old SolidRun/rcw submodule (LSDK-20.04-sr, 2020-era) with a fork based on NXP's lf-6.6.52-2.2.0 tag plus 6 SolidRun patches (0002–0007 from lx2160a_build).
Old approach: envsubst templates generating a single rcw_lx2160acex7.bin at build time, with PLL ratios computed by shell arithmetic in runme.sh.
New approach: ~150 pre-generated .rcw source files covering all speed/SerDes/boot-source combinations, compiled by rcw.py at build time. No envsubst dependency.
Key improvements:
- Correct PLL ratios:
CGB_PLL2_RAT=7,HWA_CGB_M1_CLK_SEL=6(old values were 9 and 7, incorrect for 2200/750 MHz) - Correct bus speed: 750 MHz auto-selected for 2200 MHz overclock (old code always used 700 MHz)
- Pin mux: ~20 explicit pin mux settings (IIC4, IIC6, SDHC1_DIR, USB_EXT, etc.) that were previously left at silicon defaults
- PBI errata workarounds: a050426 (internal RAM), a050479 (PCIe link training), a010554 (SATA), a009531/a008851 (per-lane PCIe) — baked into the RCW binary, applied before ATF runs
- Fan GPIO: PBI command drives fan full speed at reset (
write 0x2320000,0x20000000) - Auto-boot:
bootlocptrscript for automatic boot source selection
The runme.sh changes:
- Removed
envsubstdependency, addedpython3(forrcw.py) - Auto-corrects
BUS_SPEEDto 750 whenSOC_SPEED=2200 - Maps
BOOT_MODEto RCW naming (sd→sdhc,flexspi_nor→xspi,auto→auto) - Validates RCW binary exists before ATF build
- Uses
make BOARDS="lx2160acex7_rev2"at the top-level RCW directory
Result: Eliminated the ERROR: erratum_a050426: Invalid RCW ATF boot message. Boots to Ubuntu with Secure Boot enabled.
All work lives on the lizf.uefi-modernize branch of lizthegrey/lx2160a_uefi.
| Repo | Branch | Base | Patches (compare) |
|---|---|---|---|
| lx2160a_uefi (parent) | lizf.uefi-modernize |
SolidRun master |
34 commits (submodule pointer updates; could be squashed) |
| ATF | lizf.nxp-v2.12-cex7 |
NXP lf_v2.12 |
16 patches |
| RCW | lizf.nxp-lf6.6.52-cex7 |
NXP lf-6.6.52-2.2.0 |
6 patches |
| EDK2 | lizf.edk2-stable202602 |
edk2-stable202602 |
2 patches |
| edk2-platforms | lizf.upstream-rebase |
upstream/master |
17 patches |
| edk2-non-osi | lizf.upstream-rebase |
upstream/master |
4 patches |
| OP-TEE | lizf.4.9.0-cex7 |
4.9.0 |
5 patches |
All originally authored by Josua Mayer, Rabeeh Khoury, and Jon Nettleton (@linux4kix) at SolidRun. Cherry-picked across v2.4 → v2.10 (clean) → v2.12 (one conflict on DISABLE_S5 build flag, resolved by keeping both the new upstream build options and SolidRun's DISABLE_S5 addition in Makefile and make_helpers/defaults.mk).
| Commit | Description | Author | Upstreamable? |
|---|---|---|---|
1c50a1a |
fiptool: disable pedantic flag for older libc | Josua Mayer | Maybe (workaround) |
e643180 |
lx2160a auto boot | Rabeeh Khoury | Yes (platform) |
883e939 |
dcfg: MEM_PLL_CFG_SHIFT for DDR frequency | Jon Nettleton | Yes (bug fix) |
a0a1e36 |
lx2160a: optional S5 GPIO from Makefile | Rabeeh Khoury | Yes (platform) |
fa452b0 |
lx2160a: flexible CONFIG_DDR_NODIMM | Josua Mayer | Yes (platform) |
c1a7dd9 |
layerscape: mmap dynamic config region in BL2 | Josua Mayer | Yes (bug fix) |
eef680a |
lx2160a: flush I2C bus before DDR init | Josua Mayer | Yes (platform) |
b3f7b21 |
DDR: dump SPD EEPROM on debug builds | Josua Mayer | Yes (debug) |
ec9a59a |
DDR: disarm error for non-identical DIMMs | Josua Mayer | Yes (improvement) |
fc1a3ce |
DDR: debug output for parsed DIMM params | Josua Mayer | Yes (debug) |
bf7fc9f |
lx2160a: fix build without NV_SW_MAINT | Josua Mayer | Yes (bug fix) |
7d298be |
lx2160a: fix boot without SPI flash | Josua Mayer | Yes (bug fix) |
726c768 |
Add SolidRun CEX7 platform | Josua Mayer | Yes (new platform) |
976d615 |
Add SolidRun LX2162A SOM platform | Josua Mayer | Yes (new platform) |
4145d77 |
Add SolidRun CEX6 platform | Josua Mayer | Yes (new platform) |
d97591f |
PSCI: build-time flag to disable SYSTEM_OFF | Josua Mayer | Yes (feature) |
| Commit | Description | Upstreamable? |
|---|---|---|
ac53afd |
OP-TEE MM communication driver + OpteeLib | Partially (NXP-originated, needs cleanup) |
4e75ff7 |
VariableRuntimeDxe: avoid double VA conversion of FVB | Yes — bug fix applicable to all ARM StMM platforms |
The FVB double-VA-conversion fix (4e75ff7) is a genuine upstream bug. When SetVirtualAddressMap events fire in arbitrary order, the FVB protocol pointers can be double-converted, crashing any ARM platform using EepromFvb or similar non-flash FVB backends with StandaloneMm.
| Commit | Description | Category |
|---|---|---|
fff9746 |
Add 640 SolidRun/NXP hardware support files | Platform support |
dc6cfe4 |
Merge SolidRun HW support into 18 overlapping files | Platform support |
d0b30e4 |
Fix FeatureFlag PCDs, DTB rule, IoAccessLib, clock PPI | API compat |
266ec3a |
OP-TEE MM communication driver for Secure Boot | Secure Boot |
02be32a |
Remove SwapMmio compat macros → GetMmioOperations | API cleanup |
d11b663 |
Fix NxpPlatformGetClock for upstream SocGetClock API | API compat |
4deae84 |
Revert I2cDxe to self-contained driver | Platform workaround |
60593b8 |
Increase FD size to 3MB for Secure Boot | Build config |
adf81d0 |
Update StandaloneMm MMIO VAs for OP-TEE 4.9.0 | Platform config |
ac2fdc5 |
StandaloneMm: PcdFfaLibConduitSmc=FALSE | Platform config |
e21a324 |
StandaloneMm: enable serial debug output | Debug |
8db1d1f |
StandaloneMm: fix ExtractGuidedSectionLib for MM Core | Bug fix |
2e67b4c |
StandaloneMm: disable BFV shadowing | Platform config |
83209ed |
Link VariableMmDependency into MmCommunicationOpteeDxe | Bug fix (affects all ARM StMM) |
3c93275 |
Link VarCheckPolicyLibStandaloneMm into VariableStandaloneMm | Bug fix (affects all ARM StMM) |
a40b39a |
StandaloneMm: use BaseDebugLibNull for RELEASE | Build fix |
ec46a99 |
SmbiosPlatformDxe: report actual CPU frequency in SMBIOS Type 4 | Bug fix |
| Commit | Description | Upstreamable? |
|---|---|---|
66988ca |
ls: lx2160ardb: Add MMIO device mapping for StMM SP | Yes (platform) |
c34fd89 |
Fix mobj_phys_alloc for StMM IO mapping | Yes — bug fix |
0cf3685 |
ls: fix StMM MMIO VA assignment | Yes (platform) |
a7a4ebd |
stmm_sp: handle FFA_FEATURES syscall from SP | Yes — bug fix for all StMM users |
57cc281 |
stmm_sp: increase StMM heap from 402→800 pages | Debatable (might need per-platform config) |
All originally authored by Rabeeh Khoury and Josua Mayer at SolidRun. Applied via git am from lx2160a_build/patches/rcw/ (patches 0002–0007; 0001 and 0008–0014 are for other boards/SoMs).
| Commit | Description | Author |
|---|---|---|
03d5ca0 |
rcw.py: add loadc, jumpc, jump PBI instructions | Rabeeh Khoury |
328f3a8 |
lx2160asi: bootlocptr auto-boot script | Josua Mayer |
93ee51f |
lx2160asi: split SD1 lanes A-D 40GE into 4x10G | Josua Mayer |
c51d17b |
lx2160asi: convert SD1 lanes G&H from 10G to 25G | Josua Mayer |
f2b5286 |
Config generator script for SolidRun boards | Josua Mayer |
a723a86 |
LX2160A CEX7 rev2 ClearFog-CX board configs | Josua Mayer |
| Commit | Description |
|---|---|
b2db5ae |
SolidRun/LX2160aCex7: DPC and DPL firmware images (DPAA2 network config) |
170e534 |
NXP Qoriq Management Complex binary |
4b87eb9 |
AMD GOP driver (AARCH64 graphics output) |
28aed83 |
NXP Qoriq binary update to 10.28.1 |
These are vendor-provided binaries required for DPAA2 Ethernet and graphics output. Not candidates for upstream contribution (already from vendor sources).
- EDK2
4e75ff7— FVB double VA conversion fix inMdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c. Affects any ARM platform using a non-flash FVB backend with StandaloneMm. Originally written by Ard Biesheuvel for SolidRun's edk2 fork. Upstream PR: tianocore/edk2#12259.
-
OP-TEE
a7a4ebd— FFA_FEATURES handler in stmm_sp.c. Fixed upstream ined89aa36c(August 2025) by Yeoreum Yun at ARM, with a broader fix that returnsFFA_NOT_SUPPORTEDfor all undefined FFA functions (not justFFA_FEATURES). -
edk2-platforms
83209ed+3c93275— VariableMmDependency and VarCheckPolicyLib linkage for ARM StandaloneMm. Both are already present in the upstream ARM reference DSCs (PlatformStandaloneMm.dsc.incfor VExpress-FVP and Juno). Our SolidRun DSC was missing them because it was written independently rather than including the upstream.dsc.inc.
- OP-TEE
c34fd89—mobj_phys_allocfix forCORE_MEM_NON_SECIO mapping. Thealloc_and_map_io()function that uses this code path only exists in SolidRun's fork; upstreamstmm_sp.cdoesn't map platform MMIO into StMM this way.
-
ATF platform patches — The CEX7/CEX6/LX2162A SOM platform definitions and DDR fixes could be submitted to NXP's
nxp-qoriq/atffork, making SolidRun a first-class NXP Layerscape platform. Interest issue: nxp-qoriq/atf#3. -
edk2-platforms SolidRun overlay — The 640 SolidRun-only files (DPAA2 Ethernet, SPI, MMC, SMBIOS, ACPI tables) represent a complete board package that could be submitted to
tianocore/edk2-platforms. Interest issue: tianocore/edk2-platforms#951.
- OP-TEE StMM heap size — 402 pages is too small for any StMM build with OpenSSL crypto. This should either be increased upstream or made configurable via a
CFG_STMM_HEAP_SIZEbuild option. Issue: OP-TEE/optee_os#7728.
git clone --recursive https://github.com/lizthegrey/lx2160a_uefi.git -b lizf.uefi-modernize
cd lx2160a_uefi
# Standard build (2000 MHz, no Secure Boot, RELEASE)
bash ./runme.sh
# Overclock + Secure Boot
SOC_SPEED=2200 DDR_SPEED=3200 SECURE_BOOT=true bash ./runme.sh
# Debug build
UEFI_RELEASE=DEBUG SECURE_BOOT=true bash ./runme.sh
# Clean build
CLEAN=1 SOC_SPEED=2200 DDR_SPEED=3200 SECURE_BOOT=true bash ./runme.shFlash to SD card (no seek — offset is baked into the image):
dd if=images/lx2160acex7_*.img of=/dev/sdX bs=512 conv=notruncAfter first boot with a Secure Boot-enabled image, the platform is in Setup Mode. Enroll a self-generated PK and Microsoft's standard db/KEK certificates using efitools (efi-updatevar, cert-to-efi-sig-list, sign-efi-sig-list). Note: cert-to-efi-sig-list requires PEM format — convert Microsoft's DER .crt files with openssl x509 -inform DER first. Enroll db and KEK before PK, as setting PK exits Setup Mode.
ERROR: SPD different between DIMMs— pre-existing with mixed DIMM configs, uses first DIMM timingsFailed to find MM Communication Buffer HOB— non-fatal on ARM (x86-style HOB not used; ARM usesmNsCommBufferfrom OP-TEE)- DKMS modules (e.g.,
v4l2loopback) need MOK signing for Secure Boot
- SolidRun engineers (Jon Nettleton @linux4kix, Josua Mayer, Rabeeh Khoury) — original platform support patches for ATF, EDK2, and OP-TEE
- NXP — LX2160A platform code in ATF and edk2-platforms
- Ard Biesheuvel — FVB virtual address conversion pattern used in the double-VA fix
- Liz Fong-Jones (@lizthegrey) — project lead, testing, hardware access
- Claude (Anthropic) — code analysis, debugging, implementation assistance
All patches follow the licensing of their respective upstream projects (BSD-2-Clause-Patent for EDK2/edk2-platforms, BSD-2-Clause for OP-TEE/ATF).