Skip to content
Manual / Part III / 11 Flash Checksum Hierarchy
Chapter 11 · Platform Conversion, EEPROM & Flash Integrity

Flash Checksum Hierarchy

The three checksum tiers, the block descriptor table, and a standalone fixer.

Calibration symbols
ESKONF KFMIOP KFMIRL KFPED KFZW2 KRKTE LAMFA LDRXN MLHFM KFZW
ECUs covered
06A906032LP
Size
10 symbols · 2 diagrams · ~1,142 words

The three checksum tiers, the block descriptor table, and a standalone fixer.

While Section 10 documents the serial SPI EEPROM (ST 95040 / 95080) memory map and checksum algorithms, the 1024 KB AMD AM29F800BB parallel flash ROM containing the engine executable code and calibration tables enforces an entirely independent, multi-tiered cryptographic and mathematical integrity architecture.

Whenever an engineer modifies a fuel map (KRKTE), ignition table (KFZW), boost ceiling (LDRXN), or DTC table (CLA*), flashing the resulting binary without recalculating the main flash checksums results in an immediate engine no-start condition, accompanied by VCDS Diagnostic Trouble Code P0601 / 16985 (Internal Control Module: Memory Check Sum Error).

BOSCH ME7.5 MAIN FLASH MULTI-TIER CHECKSUM ARCHITECTURE
Tier 1: 16-Bit Additive SumsTier 2: Complement PairsTier 3: Bosch CRC32 / CRC16
• Multipage 16-bit blocks• Paired inverse 16-bit words• Cyclic redundancy polynomials
• Calculated per memory bank• Word_A + Word_B = 0xFFFF• Blocks 0x01FBxx & 0x07FBxx
• Stored in checksum headers• Immediate startup validation• Full flash segmentation sync

11.1. The Three Checksum Tiers Explained#

Bosch Motronic ME7.5 firmware implements three distinct mathematical verification mechanisms distributed across the 1024 KB memory space:

1. Tier 1: 16-Bit Multipage Additive Checksums (Simple Word Sums)#
  • Scope: The flash memory is divided into 14 to 18 discrete logical blocks (varying by project family, e.g. 21D vs 24B).
  • Algorithm: The C167 CPU computes the 16-bit summation of all 16-bit words (u16) across the block: \text{Sum}_{16} = \left( \sum_{i=0}^{N-1} \text{Word}_{16}[i] \right) \pmod{2^{16}}
  • Location: The target sums are stored in a centralized table structure located near offset 0x01FB00–0x01FC00 (Bank 0) and 0x07FB00–0x07FC00 (Bank 1).
  • Execution: Evaluated both during the initial microcontroller cold-boot self-test and periodically during engine idle task loops.
2. Tier 2: 16-Bit Inverse Complement Word Pairs#
  • Scope: Placed at strategic memory boundaries directly before and after major calibration sections.
  • Rule: Two adjacent 16-bit words (\text{Word}_A and \text{Word}_B) must satisfy: \text{Word}_A + \text{Word}_B = \text{0xFFFF} \quad (\text{or } \text{Word}_B = \text{Word}_A \oplus \text{0xFFFF})
  • Function: Serves as a rapid, single-cycle hardware sanity check. If flash write corruption or bit-flipping occurs, the bitwise complement condition fails instantly, triggering emergency shutdown before full arithmetic checks execute.
3. Tier 3: Bosch Proprietary CRC16 / CRC32 Polynomial Blocks#
  • Scope: High-security cyclic redundancy verification covering the core executable microcode segments (0x000000–0x00FFFF and 0x020000–0x07FFFF).
  • Polynomial: Standard IEEE 802.3 CRC32 polynomial: P(x) = x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 Represented in hexadecimal as 0xEDB88320 (reversed) or 0x04C11DB7 (standard).
  • Seed & Final XOR: Standard initial value 0xFFFFFFFF, post-inverted with 0xFFFFFFFF.
  • Validation: When modifying calibration maps, only the calibration CRC block changes; when patching assembly microcode (e.g. adding Launch Control), both the code CRC block and the main flash master CRC must be re-signed.

11.2. Checksum Block Descriptor Table Layout (06A906032LP)#

In 06A906032LP (and all mature 24B binaries), the master checksum configuration table starts at offset 0x01FB80. Each descriptor entry occupies 12 bytes:

Offset in FlashField NameData TypeDescription
Entry + 0x00Start Addressu32 (LE)Physical flash start offset
Entry + 0x04End Addressu32 (LE)Physical flash end offset (inclusive)
Entry + 0x08Stored Checksumu16 (LE)Calculated 16-bit expected sum
Entry + 0x0AChecksum Type / Flagsu16 (LE)0x0001 = Additive, 0x0002 = CRC32
Typical Block Partitioning in a 1024 KB ME7.5 Binary#
  • Block 1 (0x000000–0x003FFF): Interrupt Vector Table & Early Boot Routine.
  • Block 2 (0x004000–0x007FFF): Core OS Kernel & Task Dispatcher (B_10ms, B_20ms).
  • Block 3 (0x008000–0x00FFFF): Communications & KWP2000 Diagnostic Handlers.
  • Block 4 (0x010000–0x013FFF): Primary Ignition & Knock Detection Tables (KFZW, KFZW2).
  • Block 5 (0x014000–0x017FFF): Torque Model & Throttle Translation (KFMIRL, KFMIOP, KFPED).
  • Block 6 (0x018000–0x01BFFF): Fueling, Lambda & MAF Linearization (KRKTE, LAMFA, MLHFM).
  • Block 7 (0x01C000–0x01FFFF): Boost Control PID & Diagnostic Codewords (LDRXN, ESKONF, CD*).
  • Block 8 (0x020000–0x07FFFF): Extended Code Segment (C167 Functions).
  • Block 9 (0x080000–0x0FFFFF): Upper Flash Mirror & Secondary Calibration Data.

11.3. Standalone Main Flash Checksum Engine Implementation (me7_flash_checksum.py)#

Below is the standalone Python verification engine that parses, verifies, and recalculates ME7.5 1024 KB binary checksums:

#!/usr/bin/env python3
"""
Bosch ME7.5 1024 KB Flash Checksum Verification & Recalculation Engine
Target Platform: AMD AM29F800BB Parallel Flash (1048576 Bytes)
Compatible with: 06A906032LP, PL, SK, HS, CL, DL, JJ, HN
"""

import struct
import sys
import zlib

def verify_and_fix_me7_checksums(bin_path, output_path=None):
    with open(bin_path, 'rb') as f:
        data = bytearray(f.read())

    if len(data) != 1048576:
        print(f"Error: Invalid file size {len(data)} bytes. Must be exactly 1,048,576 bytes.")
        return False

    print(f"Loaded {bin_path} (1024 KB). Scanning for ME7.5 Checksum Descriptors...")

    # Locate master descriptor table in Segment 1 (typically around 0x01FB80)
    # Search for signature start addresses: 0x00000000 followed by valid end address
    descriptor_offset = None
    for candidate in [0x01FB80, 0x01FB00, 0x01FA80, 0x01FC00]:
        start_addr, end_addr = struct.unpack_from('<II', data, candidate)
        if start_addr == 0x00000000 and 0x00001000 <= end_addr <= 0x000FFFFF:
            descriptor_offset = candidate
            break

    if descriptor_offset is None:
        print("Warning: Could not auto-detect descriptor table. Using standard 24B offset 0x01FB80.")
        descriptor_offset = 0x01FB80

    print(f"Checksum table detected at 0x{descriptor_offset:06X}")

    fixed_count = 0
    # Process up to 16 descriptor blocks
    for block_idx in range(16):
        entry_offset = descriptor_offset + (block_idx * 12)
        start_addr, end_addr, stored_sum, flags = struct.unpack_from('<IIHH', data, entry_offset)

        # Terminating condition or invalid entry
        if start_addr >= end_addr or end_addr >= len(data):
            break

        # Calculate 16-bit word summation
        calc_sum = 0
        block_bytes = data[start_addr:end_addr + 1]

        # Unpack as little-endian 16-bit words
        word_count = len(block_bytes) // 2
        words = struct.unpack(f'<{word_count}H', block_bytes[:word_count * 2])
        calc_sum = sum(words) & 0xFFFF

        status = "OK" if calc_sum == stored_sum else "FAIL"
        print(f"Block {block_idx:02d} [0x{start_addr:06X}..0x{end_addr:06X}]: "
              f"Stored=0x{stored_sum:04X}, Calc=0x{calc_sum:04X} -> {status}")

        if calc_sum != stored_sum:
            # Fix checksum in descriptor table
            struct.pack_into('<H', data, entry_offset + 8, calc_sum)
            fixed_count += 1

    # Verify and fix complement pairs in Segment 1
    # Check complement pairs at 0x01FBEE and 0x01FBF0
    comp1, comp2 = struct.unpack_from('<HH', data, 0x01FBEE)
    if (comp1 + comp2) & 0xFFFF != 0xFFFF:
        new_comp2 = (~comp1) & 0xFFFF
        struct.pack_into('<H', data, 0x01FBF0, new_comp2)
        print(f"Fixed Complement Pair at 0x01FBEE: 0x{comp1:04X} + 0x{new_comp2:04X} = 0xFFFF")
        fixed_count += 1

    if fixed_count > 0 and output_path:
        with open(output_path, 'wb') as f:
            f.write(data)
        print(f"Successfully corrected {fixed_count} checksum(s). Written to {output_path}.")
    elif fixed_count == 0:
        print("All flash checksums are 100% valid. No corrections required.")

    return True

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("Usage: python3 me7_flash_checksum.py <input.bin> [output_fixed.bin]")
        sys.exit(1)
    out_file = sys.argv[2] if len(sys.argv) > 2 else sys.argv[1]
    verify_and_fix_me7_checksums(sys.argv[1], out_file)

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.

06 Memory Geometry & Axes
MLHFMKFPEDKFZW2KFMIOPLAMFAKFMIRL
45 Pattern Matching & XDF Porting
KFZW2KFMIOPLAMFAKFMIRLLDRXNKRKTE
03 Benchmark Calibrations
KFPEDKFZW2KFMIOPLAMFAKFMIRLLDRXN
25 Troubleshooting & Failsafes
KFMIOPLAMFAKFMIRLLDRXNKFZW
16 Torque Model & Inversion
KFPEDKFMIOPKFMIRLLDRXN
44 High-Lift Camshafts
KFMIOPKFMIRLESKONFKFZW