Skip to content

SMEG+ Patches

Reverse-engineering notes and tooling for PSA / Stellantis SMEG+ head units — the Magneti Marelli infotainment fitted to Peugeot, Citroën and DS vehicles around 2012–2017.

The project started with one concrete problem: an aftermarket CarPlay / Android-Auto piggyback injects its audio into the head unit's AUX input, and the unit kept starting on the radio. It now boots straight to AUX (builds/aux-boot.json, confirmed on the car). The work underneath it — the signed media contract, the checksum cascade, the settings partitions — applies to any patch you want to make to one of these units.

No vendor firmware here

This site documents our own reverse-engineering and tooling. It contains no Peugeot / Citroën / DS / Stellantis / Magneti Marelli firmware, upgrade packages, symbol maps, or other copyrighted binaries. You supply your own legally obtained package. The licence key material needed to re-seal a package is recovered from that package at runtime and is never stored here.

Start here

Find your way in

The site is organised by the part of the firmware you are touching. Start with whichever card matches what you are trying to do.

Target

Developed against SMEG5.43.A.R2 (CD 26482, 19-09-17) on a NAV unit in a 2015 Peugeot 208. The AUDIO_BT and AUDIO_BT_256 builds are supported too; each is a separate image with its own symbol map and patch addresses.

Status

  • Boot to AUX. aux-autoswitch + aux-boot-default + aux-boot-restore boot the unit to AUX. The minimal build is builds/aux-boot.json. See How the boot source is chosen.
  • The re-seal works. A modified, re-sealed package is accepted; string 2099 ("the update file is protected and cannot be copied") does not appear.
  • AUX is always available (IsAUXSRCAvailable()): it no longer greys out without a signal, and it is in the SRC cycle.
  • No idle mute on AUX. The unit mutes the AUX input while it sees no signal there, so the piggyback's audio is gated until something plays. aux-no-idle-mute removes that one mute decision — one nop, verified under emulation on all three builds, no car has run it. See Patch reference.
  • Custom ring tone audio.
  • Custom ring tone names. The names are literals in the application image, and media.names patches them in place; built and verified offline, not yet confirmed on a car. See Ring tones.
  • SPYSTORE backs up /USER_DATA (spy-dump-userdata).

Switching to AUX when a signal appears is not being pursued. aux-signal-switch exists as an emulated candidate only; see The AUX signal path.

Every patch set, by status

Generated from the status field of each patches/*.json by tools/patch_status.py, so it cannot disagree with the patch reference.

  • Confirmed on hardware: aux-always-available, aux-autoswitch, aux-boot-default, aux-boot-restore, spy-dump-userdata
  • Candidates awaiting a car test: aux-no-idle-mute, aux-signal-switch, aux-sticky
  • Falsified on hardware: spy-dump-userdata-partition
  • Diagnostic builds, not for driving: diagnostic-logging, diagnostic-logmask, diagnostic-logsink

Per-patch detail: Patch reference.

The car tests behind each status are in Hardware verification; open work is in the repository issues.

Lessons worth knowing first

  • The unit keeps its own state. Settings live on a separate /USER_DATA partition, not in the package. Editing the copy inside system.bin can appear to do nothing.
  • Payloads are version- and value-checked. A source value the unit does not recognise is ignored silently, and it falls back — so validate against the real enum rather than guessing.
  • Build, then check, then flash. tools/preflight.py runs as part of the build and fails it; it catches the mistakes that otherwise cost a trip to the car.