Skip to content
Manual / Part III / 10 Serial EEPROM & Immo
Chapter 10 · Platform Conversion, EEPROM & Flash Integrity

Serial EEPROM & Immo

The 512-byte immo EEPROM, page by page, with a working checksum fixer.

Calibration symbols
B_STEND RKADD_W DWKRZ_0 DWKRZ_3 FRA_W G186 J220 J285 ASR G28 G40
ECUs covered
06A906032J 06A906032LP
Size
11 symbols · 0 diagrams · ~2,304 words

The 512-byte immo EEPROM, page by page, with a working checksum fixer.

While calibration maps, operating system code, and diagnostic tables reside inside the 1024 KB external parallel flash memory (AM29F800BB), all dynamic vehicle-specific adaptation parameters, anti-theft immobilizer security keys, vehicle identification (VIN), softcoding, and flash programming counters reside in a dedicated 8-pin SPI serial EEPROM located on the ECU PCB adjacent to the C167CR microcontroller.

On standard transverse 06A platforms, this chip is an STMicroelectronics 95040 (512 Bytes / 4 Kbit). On newer longitudinal platforms (such as Audi A4 B6 8E0 909 518 xx), this chip is an STMicroelectronics 95080 (1024 Bytes / 8 Kbit).

BOSCH ME7.5 95040 EEPROM 512-BYTE (32-PAGE) MEMORY LAYOUT

OffsetPage Index & DescriptorFunctional SubsystemData Content & Role
0x000–0x00FPage 0 (Desc: 0xFF18)Header & Hardware SyncStartup state, bus flags
0x010–0x01FPage 1 (Desc: 0x0017)Immobilizer Bank 1Immo Status Byte (0x12)
0x020–0x02FPage 2 (Desc: 0x0117)Immobilizer Bank 2 (Mirror)Immo Status Byte (0x22)
0x030–0x03FPage 3 (Desc: 0x0207)Secret Key Code (SKC/PIN) 14-digit/5-digit Login PIN
0x040–0x04FPage 4 (Desc: 0x0307)Secret Key Code (SKC/PIN) 2Redundant PIN & Key RFID
0x050–0x05FPage 5 (Desc: 0x0437)Immo Status & Lockout TimerLearned key count, lock
0x060–0x06FPage 6 (Desc: 0x0533)VIN Characters 1–14 (Bk 1)Chassis VIN (ASCII)
0x070–0x07FPage 7 (Desc: 0x06B7)VIN 15–17 & Immo ID (Bk 1)VIN tail & 14-char Immo ID
0x080–0x08FPage 8 (Desc: 0x06F7)Immo ID Tail & Crypto SeedImmo ID tail & Seed bytes
0x090–0x09FPage 9 (Desc: 0x07B3)VIN Characters 1–14 (Bk 2)Redundant VIN Bank 2
0x0A0–0x0AFPage 10 (Desc: 0x07F3)VIN 15–17 & Immo ID (Bk 2)Redundant Immo ID Bank 2
0x0B0–0x0BFPage 11 (Desc: 0x08B7)Immo ID Tail (Bk 2)Redundant Immo ID Tail
0x0C0–0x0CFPage 12 (Desc: 0x08F7)Softcoding & WSC (Bank 1)Trans/ABS Coding, WSC
0x0D0–0x0DFPage 13 (Desc: 0x09B3)Softcoding & WSC (Bank 2)Redundant Coding Mirror
0x0E0–0x0EFPage 14 (Desc: 0x09F3)Flash Programming Counter 1Flash attempts & successes
0x0F0–0x0FFPage 15 (Desc: 0x0AB3)Flash Programming Counter 2Redundant Flash Counter
0x100–0x14FPages 16–20 (0x0AF3..0B10)Throttle Body AdaptationMin, Max, Limp endstops
0x150–0x18FPages 21–24 (0x0C37..0F33)Fuel Trim & Knock OffsetsLTFT Add/Mult, Knock dwkrz
0x190–0x1BFPages 25–27 (0x1033..1233)Readiness & DTC FreezeOBD bitmask & fault buffer
0x1C0–0x1CFPage 28 (Desc: 0x1235)VAG Part Number (ASCII)Checksum-Exempt ASCII
0x1D0–0x1DFPage 29 (Desc: 0x1235)Bosch HW/SW Version (ASCII)Checksum-Exempt ASCII
0x1E0–0x1FFPages 30–31 (0x13B7..13F7)End Markers & Trailing CRCFinal factory block sync

10.1. Detailed Memory Map: Reverse-Engineering All 32 Pages#

Every page consists of 16 bytes. In all checksummed pages, Bytes 0 through 13 hold data payload, while Bytes 14 and 15 hold the 16-bit little-endian page checksum.

1. Pages 1 & 2: Immobilizer Control Banks (0x010–0x02F)#
  • Memory Offsets: Bank 1 at 0x010–0x01F; Bank 2 (Mirror) at 0x020–0x02F.
  • Key Offset 0x0012 & 0x0022 — The Immobilizer Status Byte:
  • Editing Rule: Both Bank 1 (0x0012) and Bank 2 (0x0022) must be set to identical values. If one is set to 0x02 and the other remains 0x01, the ECU detects a memory corruption, restores the locked state from the backup bank, and sets P1603.
2. Pages 3 & 4: Secret Key Code (SKC / Login PIN) & RFID Key Store (0x030–0x04F)#
  • Memory Offsets: Bank 1 at 0x030–0x03F; Bank 2 at 0x040–0x04F.
    • Holds 32-bit unique IDs of RFID transponders (Megamos Crypto 48 chips) matched to the vehicle.
  • Offsets 0x0032–0x0033 & 0x0042–0x0043 — The 16-Bit Login PIN:
  • Offsets 0x0034–0x003B — Learned Transponder Key Identifiers:
3. Pages 6, 7 & 8: Vehicle Identification Number (VIN) & Immo ID (0x060–0x08F)#
  • Memory Offsets: Bank 1 at 0x060–0x08F; Bank 2 at 0x090–0x0BF.
    • Stored in clear ASCII text (e.g., VWZ7Z0C1234567 or AUX7Z0D9876543).
    • Stamped by the cluster during pairing.
  • Offsets 0x0060–0x006D & 0x0070–0x0072 — 17-Digit Chassis VIN:
  • Offsets 0x0073–0x007D & 0x0080–0x0082 — 14-Digit Immobilizer Serial Number (Immo ID):
4. Pages 12 & 13: ECU Softcoding & Workshop Identification (0x0C0–0x0DF)#
  • Memory Offsets: Bank 1 at 0x0C0–0x0CF; Bank 2 at 0x0D0–0x0DF.
    • Dealership equipment number stamping from the last VAS 5051 tool that coded the module.
  • Offsets 0x00C0–0x00C1 — 5-Digit VAG Softcoding:
  • Offsets 0x00C4–0x00C8 — Workshop Code (WSC) & Importer ID:
5. Pages 14 & 15: Flash Programming Attempt Counters (0x0E0–0x0FF)#
  • Offsets 0x00E0–0x00E1: Number of flash programming attempts (Programmierversuche). Increments by 1 every time an OBD flash session begins (KWP2000 Service 0x34 Request Download).
  • Offsets 0x00E2–0x00E3: Number of successful flash programming completions (Erfolgreiche Programmierungen).
  • Editing Rule: To reset flash history to factory virgin (0 / 0), write 0x00 0x00 to 0x00E0–0x00E3 and mirror into Bank 2 (0x00F0–0x00F3).
6. Pages 16–20: Electronic Throttle (E-Gas) Learned Adaptations (0x100–0x14F)#
  • Stores voltage bounds learned during VCDS Basic Settings Group 060:
    • G187 / G188 minimum lower mechanical stop voltage.
    • G187 / G188 maximum wide-open throttle stop voltage.
    • Emergency limp-home spring rest position (~7.5% plate angle).
    • When adapting a new throttle body, ME7.5 writes updated ADC counts directly into these pages.
7. Pages 21–24: Long-Term Fuel Trims (LTFT) & Cylinder Knock Offsets (0x150–0x18F)#
  • Offsets 0x0150–0x0153: Additive idle fuel trim (rkadd_w / measuring block 032 field 1).
  • Offsets 0x0154–0x0157: Multiplicative load fuel trim (fra_w / measuring block 032 field 2).
  • Offsets 0x0160–0x0167: Learned ignition retard offsets per cylinder (dwkrz_0 through dwkrz_3).
  • Offsets 0x0170–0x0173: Camshaft phase adaptation offset (wngwg_w / correlation between crank G28 and cam G40).
8. Pages 28 & 29: VAG Hardware & Software Part Number Strings (0x1C0–0x1DF)#
  • Page 28 (0x1C0–0x1CF): VAG Part Number string in ASCII (e.g., 06A906032LP ).
  • Page 29 (0x1D0–0x1DF): Bosch Software Version in ASCII (e.g., 0005 0261207955).
  • CRITICAL CHECKSUM EXEMPTION: Although the internal firmware descriptor word for Pages 28 and 29 (0x1235) has the checksum present bit set, Bosch ME7.5 operating systems exempt these two pages from mathematical checksum verification. They store ASCII strings and must never have their last two bytes altered to formula values.

10.2. The Master Bosch ME7.5 EEPROM Checksum Algorithm#

Whenever any byte in Pages 0–27 or 30–31 is edited, the 16-bit complement checksum in Bytes 14 and 15 of that specific page must be recalculated. Failing to update the checksum causes the ECU to flag P1603 / 18011 (Internal Control Module: EEPROM Defective) on the next key cycle and lock adaptation storage.

1. Per-Page Firmware Descriptor Table#

Inside the C167 firmware ROM, Bosch maintains a lookup table containing a 16-bit descriptor word for each of the 32 pages:

  Page 00: 0xFF18   Page 08: 0x06F7   Page 16: 0x0AF3   Page 24: 0x0F33
  Page 01: 0x0017   Page 09: 0x07B3   Page 17: 0x0B32   Page 25: 0x1033
  Page 02: 0x0117   Page 10: 0x07F3   Page 18: 0x0B10   Page 26: 0x1133
  Page 03: 0x0207   Page 11: 0x08B7   Page 19: 0x0B10   Page 27: 0x1233
  Page 04: 0x0307   Page 12: 0x08F7   Page 20: 0x0B10   Page 28: 0x1235 (EXEMPT)
  Page 05: 0x0437   Page 13: 0x09B3   Page 21: 0x0C37   Page 29: 0x1235 (EXEMPT)
  Page 06: 0x0533   Page 14: 0x09F3   Page 22: 0x0D33   Page 30: 0x13B7
  Page 07: 0x06B7   Page 15: 0x0AB3   Page 23: 0x0E33   Page 31: 0x13F7
2. Bitmask Flags#
  • ChecksumPresentMask = 0x0001: If (descriptor & 0x0001) != 0, this page is protected by a checksum.
  • ChecksumBitMask = 0x0040: If (descriptor & 0x0040) != 0, subtract 1 from the running sum before complementation.
3. Mathematical Checksum Formulation#

For page P \in [0, 31] starting at byte offset \text{offset} = P \times 16:

  1. Sum the 14 data payload bytes (Bytes 0 through 13): \text{Sum} = \sum_{i=0}^{13} \text{EEPROM}[\text{offset} + i]
  2. Add the page index number: \text{Sum} = \text{Sum} + P
  3. If bit 6 of the page descriptor is active: $$\text{If } (\text{Descriptor}[P] \land \text{0x0040})

eq 0 \implies \text{Sum} = \text{Sum} - 1$$

  1. Compute the 16-bit two's complement negation: \text{Checksum} = (-\text{Sum}) \pmod{2^{16}}
  2. Store the 16-bit word in little-endian format at Bytes 14 and 15: \text{EEPROM}[\text{offset} + 14] = \text{Checksum} \land \text{0xFF} \text{EEPROM}[\text{offset} + 15] = (\text{Checksum} \gg 8) \land \text{0xFF}

10.3. Standalone Python Checksum Fixer & Immo Defeater (me7_eeprom_fixer.py)#

The following self-contained Python script automatically defeats the immobilizer, validates all 32 pages, and recalculates all Bosch page checksums for any 512-byte (95040) or 1024-byte (95080) EEPROM image:

#!/usr/bin/env python3
import sys

PAGE_DESCRIPTORS = [
    0xFF18, 0x0017, 0x0117, 0x0207, 0x0307, 0x0437, 0x0533, 0x06B7,
    0x06F7, 0x07B3, 0x07F3, 0x08B7, 0x08F7, 0x09B3, 0x09F3, 0x0AB3,
    0x0AF3, 0x0B32, 0x0B10, 0x0B10, 0x0B10, 0x0C37, 0x0D33, 0x0E33,
    0x0F33, 0x1033, 0x1133, 0x1233, 0x1235, 0x1235, 0x13B7, 0x13F7,
]
EXEMPT_PAGES = {28, 29}

def calc_page_checksum(data, page_offset, page_num, desc):
    s = sum(data[page_offset + i] for i in range(14)) + page_num
    if desc & 0x0040:
        s -= 1
    return (-s) & 0xFFFF

def fix_eeprom_bank(data, bank_offset=0):
    updated = 0
    for page in range(32):
        if page in EXEMPT_PAGES:
            continue
        desc = PAGE_DESCRIPTORS[page]
        if not (desc & 0x0001):
            continue
        p_off = bank_offset + (page * 16)
        expected = calc_page_checksum(data, p_off, page, desc)
        stored = data[p_off + 14] | (data[p_off + 15] << 8)
        if stored != expected:
            data[p_off + 14] = expected & 0xFF
            data[p_off + 15] = (expected >> 8) & 0xFF
            updated += 1
    return updated

def process_eeprom(in_path, out_path, immo_off=True):
    with open(in_path, "rb") as f:
        buf = bytearray(f.read())

    if len(buf) not in (512, 1024):
        raise ValueError(f"Invalid EEPROM size: {len(buf)} bytes (expected 512 or 1024)")

    if immo_off:
        # Patch Bank 1 and Bank 2 Immobilizer bytes
        buf[0x0012] = 0x02
        buf[0x0022] = 0x02
        if len(buf) == 1024:
            buf[0x0212] = 0x02
            buf[0x0222] = 0x02
        print("[+] Immobilizer flags patched to 0x02 (Immo Defeated)")

    fixes = fix_eeprom_bank(buf, 0)
    if len(buf) == 1024:
        fixes += fix_eeprom_bank(buf, 512)

    with open(out_path, "wb") as f:
        f.write(buf)
    print(f"[+] Corrected {fixes} page checksums. Output saved to: {out_path}")

if __name__ == "__main__":
    if len(sys.argv) < 3:
        print("Usage: python3 me7_eeprom_fixer.py <input.bin> <output.bin> [--immo-off]")
        sys.exit(1)
    process_eeprom(sys.argv[1], sys.argv[2], "--immo-off" in sys.argv)

10.4. Step-by-Step Hex Editing Instructions: Performing Common Tasks#

Task 1: Complete Immobilizer Defeat (Immo Off)#
  1. Open your 512-byte EEPROM dump in a hex editor (e.g. HxD, Hex Fiend, or 010 Editor).
  2. Go to byte 0x0012: Change value from 0x01 to 0x02.
  3. Go to byte 0x0022: Change value from 0x01 to 0x02.
  4. Run me7_eeprom_fixer.py (or me7eeprom --fixchecksums) to recalculate the row checksums at 0x001E–0x001F and 0x002E–0x002F.
Task 2: Extracting the 5-Digit Login PIN / SKC#
  1. Locate bytes 0x0032 and 0x0033.
  2. Read the values as a little-endian 16-bit unsigned integer:
  3. Verify against backup bank at 0x0042 and 0x0043 (must match).
Task 3: Changing the Chassis VIN#
  1. Go to address 0x0060.
  2. Type the first 14 characters of the new VIN in ASCII (e.g. WVWZZZ1JZ3W1234).
  3. Go to address 0x0070.
  4. Type the remaining 3 characters of the VIN in ASCII (e.g. 567).
  5. Mirror the exact same string to Bank 2: characters 1–14 at 0x0090, characters 15–17 at 0x00A0.
  6. Recalculate checksums for Pages 6, 7, 9, and 10.
Task 4: Converting a 512-Byte Dump to Run on an 8E0 95080 Chip#
  1. Take your 512-byte transverse 06A EEPROM dump (512_bytes.bin).
  2. Create a duplicate 1024-byte file by appending the 512-byte image to itself:
   cat 512_bytes.bin 512_bytes.bin > 1024_padded_8e0.bin
  1. Run the checksum fixer on both 512-byte banks:
   python3 me7_eeprom_fixer.py 1024_padded_8e0.bin 1024_padded_8e0_fixed.bin --immo-off
  1. Flash 1024_padded_8e0_fixed.bin into the 8E0 95080 chip using an external programmer or bench tool.

10.5. VCDS Diagnostic Adaptation Channels & Direct EEPROM Physical Mapping#

When an automotive technician alters operating parameters via Ross-Tech VCDS / VAS-5054A diagnostic software, the ECU writes the newly calibrated scalar offsets directly into non-volatile SPI EEPROM cells. Understanding this mapping enables an engineer to inspect, preset, or clone adaptation values directly in a hex editor:

VCDS ADAPTATION CHANNELS TO 95040 EEPROM PHYSICAL OFFSET MAPPING

ChannelFunctional ParameterEEPROM PagePhysical ByteFormat & Resolution
Ch 00Factory Adaptations ResetPages 16–270x100–0x1BFBulk wipe to 0x00/FF
Ch 01Idle Speed Adjustment (NMIN)Page 12 & 130x0C2 / 0x0D2u8: 10 rpm / step
Ch 02Fuel Enrichment / TransientPage 12 & 130x0C3 / 0x0D3u8: 0.78% / step
Ch 03Ignition Angle Global OffsetPage 12 & 130x0C6 / 0x0D6s8: 0.75 deg / step
Ch 50Immobilizer Learning RoutinePages 3,4,7,80x030–0x08FVIN, PIN, Crypto Key
Ch 60Throttle Body Basic SettingsPages 16–200x100–0x14FG187/G188 ADC Limits
Ch 99VVT Exhaust/Intake DiagnosticsPage 250x1921-byte status bitmask
Detailed Subsystem Mechanics#
  1. Channel 00 (Clear All Learned Values): Executing Save [0] on Channel 00 triggers the C167 CPU to zero out the learned throttle body ADC endpoints (Pages 16–20), wipe the short-term and long-term fuel trim corrections rkadd and fra (Pages 21–24), and clear cylinder-selective knock adaptation tables.
    • Completely closed mechanical lower stop.
    • Emergency limp-home spring rest position.
    • Wide-open throttle mechanical upper stop. The resulting potentiometer voltages from G187 and G188 are stored across Pages 16 through 20. If these values are corrupted, the ECU flags DTC P1559 or P1545 and refuses throttle input.
  2. Channel 01 (Idle Speed Trimming): Allows the idle RPM to be raised or lowered by up to \pm 150\text{ rpm}. Modifies byte 0x00C2 in Bank 1 and byte 0x00D2 in Bank 2. Value 128 represents factory baseline (800\text{ rpm}). Setting 138 raises idle to 900\text{ rpm} (vital for smoothing high-lift aftermarket camshafts or solid engine mounts).
  3. Channel 60 (Electronic Throttle Body Adaptation — Basic Settings 060): The ECU commands the throttle motor (G186) through its mechanical range:

10.6. Immobilizer Generation 2 (WFS2) vs. Generation 3 (WFS3) Cryptographic Architecture#

Between 1999 and 2005, VAG phased out early Immobilizer II (WFS2) in favor of the much more sophisticated Immobilizer III (WFS3) system:

1. Immobilizer II (WFS2 — Early Transverse ME7.5, e.g. 06A906032J / 21D)#
  • Structure: 17-digit VIN only. Does not utilize a separate 14-character cluster serial number.
  • Transponder: Megamos Crypto ID48 with fixed pre-programmed transponder serials.
  • Handshake: Unidirectional. The cluster verifies the transponder key and sends an authorization telegram to the ECU over K-Line (Pin 43).
  • Immo Defeat: Setting byte 0x0012 to 0x02 is sufficient; no secondary cluster pairing or rolling crypto seed is maintained in EEPROM.
2. Immobilizer III (WFS3 — Mature Transverse ME7.5, e.g. 06A906032LP / JJ / SK / 24B)#
  • Structure: Dual identification:
  • Mutual Authentication Handshake: At power-on, the instrument cluster (J285) and ECU (J220) engage in a mutual 128-bit challenge-response authentication over the 500 kbps Drivetrain CAN bus (CAN IDs 0x280 and 0x480):
  • Immo Defeat Mechanics in WFS3: Setting byte 0x0012 = 0x02 and 0x0022 = 0x02 forces the C167 operating system to bypass the CAN authentication listener entirely, asserting B_stend = 1 unconditionally upon hardware reset.

Cross-referenced on shared calibration symbols, not on subject matter — these are the chapters that touch the same maps.

← Previous chapter · Contents · Next chapter →

Related

Cross-referenced on shared calibration symbols, not on subject matter — these are the chapters that touch the same maps.