Skip to content

Commit c6d40b1

Browse files
eastmadcclaude
andcommitted
feat(bare-metal): NXP SPC58 chip family — Rule #52 Rule-of-Two
Second chip family, completely orthogonal to the F28066 reference case along every axis the schema is supposed to abstract over: | dim | F28066 (Rule-of-One) | SPC58 (Rule-of-Two) | |--------------|----------------------|----------------------------| | ISA | TI C28x DSP | PowerPC VLE e200z4 | | endianness | little | big | | addressing | 16-bit word | 32-bit byte | | packing | two_bytes_per_word_le| one_byte_per_address | | security | CSM password (CWE-1273) | Lifecycle register (CWE-1234) | | ghidra spec | pending (issue #5259)| PowerPC:BE:32:VLE (mainline) | | use case | UPS / motor control | Automotive ECU | Zero walker code changes — the same bare_metal_walker.py consumes both manifests through the closed POLICY_EVALUATORS dispatch table. Five regions: BAM (boot ROM), flash_boot (signed code), flash_app (application), hsm_sram (Rule #45 no-decrypt analog — semantically inaccessible from main core), lifecycle_register (SSCM_STATUS) with required_value_at_offset policy emitting CWE-1273+1191+1234 when lifecycle != customer-delivery (0x2). Factory state (0x0) leaves JTAG + censorship-password registers open — operator audit MUST catch production firmware shipping with non-customer-delivery lifecycle. Hot-reload tested via MtimeCachedYamlLoader cache_clear() — catalog flipped from 1 family to 2 with zero docker restart, proving the adaptability surface works end-to-end (Scout BB §3 borrowed pattern). Promotes Rule #52 from Rule-of-One to **Rule-of-Two — durable beyond debate**. The next adaptable-extension surface in wairz (file-format registry per Scout EE §5.1, or JTAG TAP families per Scout EE §5.5) inherits this pattern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 0fb58ca commit c6d40b1

1 file changed

Lines changed: 193 additions & 0 deletions

File tree

  • backend/app/services/hardware_firmware/data/chip_families/nxp
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
# ---------------------------------------------------------------------------
2+
# NXP SPC58xx (e200z4, Power Architecture) — chip-family manifest
3+
# ---------------------------------------------------------------------------
4+
# Rule-of-Two reference for Rule #52 (2026-05-19). Proves the schema-driven
5+
# bare-metal pattern works for:
6+
# * Big-endian architecture (vs little-endian F28066)
7+
# * PowerPC VLE ISA (vs C28x DSP)
8+
# * 32-bit byte-addressed memory (vs 16-bit word-addressed)
9+
# * Lifecycle-register security model (vs CSM password)
10+
#
11+
# The SPC58 family powers automotive ECUs (Bosch, Continental, Denso) for
12+
# powertrain / chassis / body / ADAS subsystems. A "factory" lifecycle
13+
# register value = production debug enabled = JTAG accessible — analogous
14+
# (in operator-impact) to F28066 unprogrammed CSM PWL.
15+
#
16+
# Sources:
17+
# - NXP RM0488 (SPC58xx Reference Manual)
18+
# - NXP AN5347 (Lifecycle State Management)
19+
# - NXP AN5365 (HSM Programming Guide)
20+
# - "Reverse-Engineering Automotive ECUs" (hardwear.io 2024)
21+
#
22+
# Architecture quirks:
23+
# * Boot Assist Module (BAM) at 0x00000000-0x00003FFF — factory-programmed
24+
# bootstrap ROM. Reset vector pulls boot configuration from
25+
# XBAR_CROSSBAR_BOOT_BFRn registers and dispatches to flash boot sector.
26+
# * Two-stage flash: boot sector (0x00400000) + application (0x00800000-...)
27+
# — supports A/B field-update without bricking.
28+
# * Hardware Security Module (HSM) — separate Cortex-M0+ core for crypto
29+
# operations; HSM SRAM at 0xF0000000 is not accessible to main core.
30+
# * Lifecycle register at SSCM_STATUS (0xC3FD8000) bits 12-15 encode
31+
# factory|customer_delivery|in_field|failure_analysis state. Factory
32+
# state leaves censorship password registers OPEN; production firmware
33+
# must be in customer_delivery or later.
34+
# ---------------------------------------------------------------------------
35+
36+
schema_version: 1
37+
vendor: nxp
38+
family: spc58
39+
display_name: "NXP SPC58xx (e200z4, Power Architecture automotive MCU)"
40+
description: |
41+
NXP Semiconductors SPC58xx family — multi-core PowerPC e200z4 / e200z7
42+
microcontrollers for automotive applications (powertrain, chassis,
43+
body, ADAS). Big-endian VLE (Variable Length Encoding) ISA, 32-bit
44+
byte-addressed flash, Hardware Security Module on separate core.
45+
46+
Production silicon SHOULD have the lifecycle register set to
47+
customer_delivery (0x2) or later before shipping. Factory state (0x0)
48+
leaves censorship-password registers OPEN — JTAG access to flash +
49+
HSM SRAM is permitted without authentication.
50+
51+
references:
52+
- "NXP RM0488 SPC58xx Family Reference Manual"
53+
- "NXP AN5347 Lifecycle State Management"
54+
- "NXP AN5365 HSM Programming Guide"
55+
- "CWE-1273 Device Unlock Credential Sharing"
56+
- "CWE-1191 On-Chip Debug and Test Interface With Improper Access Control"
57+
- "CWE-1234 Hardware Internal or Debug Modes Allow Override of Locks"
58+
59+
domains:
60+
- name: e200z4_core
61+
arch: powerpc-vle
62+
endianness: big
63+
instruction_word_bits: 16
64+
data_word_bits: 32
65+
address_bus_bits: 32
66+
packing: one_byte_per_address
67+
68+
description: |
69+
Main e200z4 application core. Single-domain manifest — composite
70+
SPC58 SKUs with multiple cores would declare additional Domain
71+
entries (lockstep z4_safety, HSM z0 core, etc.) under the same
72+
family file.
73+
74+
address_regions:
75+
- name: bam
76+
start: 0x00000000
77+
end: 0x00003FFF
78+
access: read-execute
79+
semantic: [boot_assist_module, boot_rom]
80+
description: |
81+
Boot Assist Module — factory-programmed bootstrap ROM (16 KB).
82+
Reads boot configuration from XBAR_CROSSBAR_BOOT_BFRn registers,
83+
loads RCHW (Reset Configuration Half-Word) from flash, and
84+
dispatches to the flash boot sector.
85+
86+
- name: flash_boot
87+
start: 0x00400000
88+
end: 0x0043FFFF
89+
access: read-execute
90+
semantic: [flash_code, signed_code_region]
91+
description: |
92+
Boot sector (256 KB). Contains low-level initialization +
93+
A/B selector logic + secure-boot validator (when HSM is
94+
provisioned).
95+
96+
- name: flash_app
97+
start: 0x00800000
98+
end: 0x01FFFFFF
99+
access: read-execute
100+
semantic: [flash_code, flash_data]
101+
description: |
102+
Application flash (24 MB on SPC58EHx). Operator firmware lives
103+
here. Vendor-stripped production builds typically lack TI/Bosch
104+
compiler-runtime strings, so detection signals rely on RCHW +
105+
BAM dispatch table shape rather than vendor strings.
106+
107+
- name: hsm_sram
108+
start: 0xF0000000
109+
end: 0xF000FFFF
110+
access: read-only
111+
semantic: [hsm_sram, sram]
112+
description: |
113+
Hardware Security Module SRAM (64 KB) — physically present at
114+
this address but accessible only to the HSM core (separate
115+
Cortex-M0+). Main core sees this region as zeros via the
116+
crossbar firewall — Rule #45 no-decrypt analog (HSM key
117+
material is present in memory at runtime but never readable
118+
by wairz). The ``hsm_sram`` semantic tag drives the walker's
119+
policy SKIP; access=read-only is the file-view stance.
120+
121+
- name: lifecycle_register
122+
start: 0xC3FD8000
123+
size: 4
124+
access: read-only
125+
semantic: [security_password]
126+
description: |
127+
SSCM_STATUS register (32-bit). Bits 12-15 encode lifecycle:
128+
0x0 = factory (FAB) ← CWE-1273/1191/1234 finding
129+
0x1 = silicon-test (delivered to NXP)
130+
0x2 = customer-delivery ← Production-ready
131+
0x3 = OEM-production
132+
0x4 = in-field
133+
0x5 = failure-analysis-return
134+
Production firmware MUST NOT ship with lifecycle in {0x0, 0x1}.
135+
policy:
136+
- operator: required_value_at_offset
137+
value_hex: "00000002"
138+
offset: 0
139+
word_size_bits: 32
140+
cwe_ids: [1273, 1191, 1234]
141+
severity: critical
142+
confidence: high
143+
finding_source: c28x_unsecure_csm
144+
description: |
145+
SSCM_STATUS lifecycle != customer-delivery (0x2). Factory
146+
or silicon-test state leaves JTAG + censorship-password
147+
registers open. Operator audit: production silicon MUST
148+
transition to lifecycle ≥ customer-delivery before
149+
shipping.
150+
151+
Note: re-uses the c28x_unsecure_csm finding_source as a
152+
generic "MCU/DSP debug-unlock finding" until Phase 2
153+
adds nxp_spc58_factory_lifecycle to the closed enum.
154+
155+
detection_signals:
156+
# BAM at offset 0 has a known fixed-byte pattern (the e200z4 first
157+
# instruction is always 0x4800 0008 — branch-to-init-vector with
158+
# specific encoding). Operators can extend this list per observed
159+
# dumps without a docker restart.
160+
- kind: silicon_id_byte_match
161+
weight: 0.4
162+
address: 0x00000000
163+
bytes_hex: "48000008"
164+
description: "e200z4 BAM reset-vector branch instruction"
165+
166+
# NXP / Freescale runtime strings — present in vendor-stripped
167+
# builds about 50% of the time; useful additive signal.
168+
- kind: string_present
169+
weight: 0.2
170+
patterns:
171+
- "NXP"
172+
- "Freescale"
173+
- "SPC58"
174+
- "e200z4"
175+
- "PowerPC"
176+
- "HSM_INIT"
177+
- "RCHW_BOOT"
178+
description: "NXP / Freescale compiler-runtime + family identifier strings"
179+
180+
# ELF magic — reject ELF-shaped inputs (defer to ELF parser)
181+
- kind: elf_magic
182+
weight: 1.0
183+
bytes_hex: "7F454C46"
184+
description: "Reject ELF-shaped inputs"
185+
186+
ghidra_import_params:
187+
# Ghidra ships PowerPC:BE:32:VLE — mature SLEIGH spec, full decompiler
188+
# support. Unlike TI C28x where SLEIGH is pending (ghidra#5259),
189+
# SPC58 analysis works out-of-the-box once analyzeHeadless is invoked
190+
# with the right loader hints.
191+
processor: "PowerPC:BE:32:VLE"
192+
loader: BinaryLoader
193+
base_addr: 0x00000000

0 commit comments

Comments
 (0)