- An old Simos7 ECU, part number 06A906033DM, with a Euro2 modification “with ecology” in the classic “bring me back to 2007” style — lots of P0000 errors, glitches, etc.
- The ECU itself is unavailable at a time, a software-only approach is used initially.
- The closest available references are the Funktionsrahmen for Simos 8.5 and a DAMOS for 3.2 FSI VR6 CALA. Practical overlap is close to zero.
- Known hardware: C167 CPU and 29F400BB flash memory. This combination is relatively straightforward to reverse.
---
Loading the firmware into IDA PROThe firmware is loaded into IDA PRO. The first step is locating the DPP registers:
seg080:0634 E6 00 12 00 mov DPP0, #12h
seg080:0638 E6 01 14 00 mov DPP1, #14h
seg080:063C E6 02 13 00 mov DPP2, #13h
Multiplying these values by 4000h reveals the calibration segments:
0x48000, 0x50000, and 0x4C000.
Unlike Bosch ECUs, the 0x800000 base is not used here.
An existing ME7 script by Andy Whittaker is adapted to these values, resulting in readable code so far
Note on DPP:For details, refer to the CPU documentation. In short, DPP provides compact 16-bit addressing for different memory segments. Since the CPU is 16-bit but memory space is larger, full extended addressing would require additional instructions. DPP windows are therefore used for fast access. Typically, some DPPs point to calibration areas, while others point to RAM.
---
Finding an initial reference pointThe Euro2-modified firmware is used to locate a simple and well-known element, such as the IGA_BAS ignition angle. Parameters of this type usually originate from very early ECU generations, and Simos is no exception.
A simple comparison with WinOLS shows that the modification in the Euro2 file strongly resembles an ignition angle change.
Bosch ECUs are generally easier to reverse because map axes and their sizes are often placed directly before the map data. Uncommon in Siemens.
Additionally, on C167 processors, map addresses are passed as plain immediate values:
This is just a number that is later interpreted as an address. While it is possible to write a script to automatically convert such values into addresses, doing so for a single ECU is not practical.
A simpler approach is visual inspection. A sequence such as `74 74 74` looks like the beginning of a map (e.g. 0x4AFCC). Searching for `FCCh` in IDA typically yields results where usage together with registers r12, r13, or r5 indicates a map or axis reference in the vast majority of cases.
Such a reference is located. So far so good.
---
Map access characteristics in SimosCompared to Bosch ECUs, map access in Simos looks unusual: first one axis is evaluated, then the second axis, and only afterward is the map value fetched.
Since the values originate from DPP0 (12h), Ctrl+R is used to assign the base address 0x48000 (12h × 4000h) to all registers holding addresses (commonly r12, sometimes r13).
If there is uncertainty whether a value represents an address, the called procedure can be inspected. If the register later appears in square brackets (e.g. `[r12]`), it confirms that an address was passed.
After this adjustment, proper references into the calibration area become visible. Axis sizes are found before the axes themselves, and the layout appears consistent.
This yields a valid intermediate result.
---
Map validationIn this case, the map size is identified as 16×12. The values 0Ah and 0Ch preceding the axes confirm this.
An axis size of 16 corresponds to engine speed (RPM), while a size of 12 corresponds to MAF. The variable associated with these axes therefore represents MAF versus RPM. Naming conventions may follow Bosch terminology for convenience.
Map calculation routines typically return the result in register r4. This is verified, and it is assumed that the ignition angle value is written to address 0D22Fh.
This is not considered the final ignition angle. The exact purpose of this particular map is not yet fully known, and multiple ignition-related maps may exist.
The important outcome is that RPM and MAF have been identified and the general mechanism is understood. With known addresses, coefficients can be taken from Simos 8 and applied to this map.
The result appears plausible, confirming the approach.
It is also recommended to review cross-references and identify 8-bit clones of variables. These are commonly used for diagnostics and may be useful later.
---
Limitations and further strategyThis approach alone is insufficient, as firmware variants differ significantly and further understanding is required. A parameter such as `c_tps_max` (maximum throttle angle) may be found, but this alone is not enough.
Reverse engineering typically involves identifying known patterns, educated guessing, and leveraging external reference points. In the case of engine control units, useful external stimuli include:
- CAN bus identifiers and message layouts, which largely match ME7.
- Connector pinout information, allowing signal tracing from pins to internal logic.
- KWP1281 measuring blocks, whose channel descriptions are available in VCDS label files (this is not UDS).
The CAN-based approach appears promising but, in Simos, message IDs are not stored explicitly (or are not easily located). Even their offsets may be absent.
The pinout-based approach involves reviewing ME7 documentation and schematics (e.g. BSF). In practice, these do not match sufficiently.
---
Variable Intake Manifold (VIM) as a candidateA practical candidate is the intake manifold flap, which is known to switch around 5000 RPM. Its control map typically consists of binary values (0/1), and engine speed has already been identified.
Various ME7 reference spreadsheets are examined without success. However, one reference to “swirl diag” stands out. While abbreviations such as PMOEL or TKY are unclear, Bosch refers to the intake flap as SU (SaugrohrUmschaltung), whereas Simos uses VIM (Variable Intake Manifold).
Processor output pins are known and statically mapped in IDA. These ports are binary. In code, their state is usually controlled with instructions such as:
Here, `bclr` enables pull-down, while `bset` leaves the line floating. A quick search for `p2_4` in IDA leads to a simple routine based on RPM and throttle angle.
The resulting map is binary, as expected for an intake flap. After populating the axes, the result appears plausible.
In addition to direct port control, several additional bits are modified, referred to here as `vim_3` and `vim_4`.
Note: Instead of ones, any non-zero value (even arbitrary data) would work, since the logic only checks for zero.
The intake flap is also convenient because it appears in diagnostics.
---
Diagnostic representation (KWP1281)095,0, Variable Intake Manifold (Single Stage Changeover)
095,1, Engine Speed, Specification: 640…900 RPM
095,2, Engine Load
095,3, Coolant Temperature, Specification: 80…115 °C
095,4, Variable Intake Manifold Status, Display Range: ON/OFF
The key observation is that block 095.4 is displayed as ON/OFF.
In KWP1281, diagnostic values are transmitted using a formula number and parameters. The tester interprets the formula number to determine scaling and units. The relevant formula here is 37, which represents textual values.
From the KWP1281 specification (e.g. `text_table_EN.h`):
const char KWP_TEXT_0087[] = "ON";
const char KWP_TEXT_0088[] = "OFF";
Thus, `vim_3` / `vim_4` map directly to diagnostic values 0x87 and 0x88. Cross-references confirm logic that outputs 0x88 when the state is false and 0x87 when true, clearly indicating diagnostic output.
---