|
| 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