For your information, changes were last made on: 30 December 2004 08:47 -0500
General
What to fix checksums yourself? - ECUFix - NEW!
My MY1999 Audi S4 uses a Bosch Motronic ME 7.1 ECU.
My ECU is labelled up as follows:
| VAG # |
8D0 907 551 C |
| Bosch # |
0 261 206 108 |
| Component |
2.7l V6/5VT 0002 |
| Soft Coding |
05611 |
I am starting to disassemble the code in the ECU but it's currently almost impossible to do so. Do you want to get involved?
Audi/ecu/S4TT-108.bin - this is the standard, stock binary code out of the ECU. The ECU uses a Siemens C16x based CPU.
I need any information you may have on the Bosch ME 7.1. If you know of memory maps, or anything.... please let me know!
I'm using the undisputed leader in disassemblers, IDA Pro to work on this. You can get details of IDA Pro here: http://www.datarescue.com/idabase/
Please purchase IDA and support it.
Why Disassemble?
Interesting question.... When I first bought my Lotus Esprit, there was not a lot of real information available on its ECU. The desire to find out what was in the Engine Management System really whetted my appetite. Some considerable time later, some 12 months of work, I had cracked the ECU and understood a good 80% of it.
When I bought my Audi S4, I researched what was available in the market place for ECU upgrades. Looking at very informative sites such as the excellent Audi World http://www.audiworld.com/tech/ they tended to recommend the GIAC chip upgrade http://www.giacusa.com/
However, imagine what went through my mind when I enquired via several Emails to AWE-Tuning as to the availability of a chip upgrade for my Audi S4 and the following appeared in my Inbox:
Sent: Thursday, June 06, 2002 6:49 PM
Subject: Re: GIAC Chip for UK Spec 1999 Audi S4
> I realize that, and I also see that you enjoy cracking performance chip
> encryptions and posting the files on the web!
>
> Sorry we could not help.
>
Obviously a man who thinks some knowledge shared is somehow linked to the piracy of someone else's hard work. I wonder how much this man truly knows about performance tuning and doesn't solely rely on the expertise of GIAC and profit from it?
GIAC on the other hand didn't even have the courtesy to reply to my complaint I sent them from this disgusting reply from one of their agents... oops, re-sellers.
As a side, if you see any pirated files on any of my web-sites... please let me know!
Anyway, enough said on that subject....
Memory Map
The ME 7.1 has a whopping 512K Byte of code resident on its FLASH ROM! This is one complicated ECU.... After extracting the code, I've managed to figure out the following memory map:

Cracking the Puzzle - Checksums
The poor guy who wants to alter his ECU maps has a nightmare of a job. Even if he finds out what Map needs to be changed, he is restricted on what he can do until he knows how to correct the on-chip checksums.
Why Checksums?
Well, the computer controlling your engine is situated slap-bang in the middle of a very hostile environment, especially when you know that there's 42,000 volts zapping around it. Image how your PC would feel if its input supply varied as much as a car battery's could. I can't imagine what jump starting a flat battery on a cold day would do to an electrical system!
If the ECU were to find a couple of bits out of millions were changed, the results could be very serious for your engine. Even if the engine survived, the probable result would be an engine that wouldn't run. Very annoying.
Quality ECU manufactures such as Bosch need to ensure that the ECU is executing its code correctly and without error. If an error occurs, rather than try and correct it, the ECU will always restart itself and try and continue to run. The result would probably be an engine stall but at least no rouge code would be allowed to execute.
What Data Integrity Schemes do Bosch Use?
From what I have unearthed so far, I can see that Bosch uses 3 different types of scheme to guard against data corruption.
All important data bytes are mirrored with their 1s complimented counter parts and then checked before execution.
A multipoint checksum regime is employed.
A complete ROM checksum is performed.
A special XOR checksum.
Twos Complimented Data
All important data is mirrored and then checked every time it's used.
Here's some actual code:
| mov |
r4, loc_380946 |
; Move Word |
| cpl |
r4 |
; Integer One's Complement |
| cmp |
r4, unkinv_3827FE |
; Integer Compare |
| jmpr |
cc_NZ, loc_824562 |
; Complimented word is OK, so JUMP |
| mov |
r4, loc_38094C |
; Move Word |
| cpl |
r4 |
; Integer One's Complement |
| cmp |
r4, unkinv_3827FA |
; Integer Compare |
| jmpr |
cc_NZ, loc_824562 |
;Complimented word is OK, so JUMP |
| movb |
rl4, loc_380908 |
; Move Byte |
| cplb |
rl4 |
; Integer One's Complement Byte |
| cmpb |
rl4, unkinv_3827F8 |
; Integer Compare Byte |
| jmpr |
cc_Z, loc_824576 |
; Complimented word is OK, so JUMP |
| |
Executing here means that a byte has been corrupted. |
When an important word is written, the word's compliment is written in another memory location too. If this word is then read, the code similar to above is executed and both copies of the word are read in and checked before they are used.
Multipoint Checksum
Within the calibration space, there are a number of checksum blocks defined:
dw 4000h ; StartAddr
dw 0 ; StartSeg
dw 7FFFh ; EndAddr
dw 0 ; EndSeg
dw 16B3h ; ChksumLo
dw 0F47h ; ChksumHi
dw 0E94Ch ; InvChksumLo
dw 0F0B8h ; InvChksumHi
Remember that the C167 is little endian, so you have to read the addresses Lo Word first and Hi Word second. This is just a structure that looks like this in C notation:
typedef struct SegChksum
{
unsigned __int32 nStartaddr;//start address
unsigned __int32 nEndaddr;//end address
unsigned __int32 nChksum; //checksum
unsigned __int32 nInvChksum; //complemented checksum
} SegChksum;
From the above example, you can see that this checksum block starts at 0x04000 and carries onto 0x07ffff. If all's ok, the resultant checksum code should give 0x0f4716b3 as an answer. Invert this (1s compliment) and you get 0x0f0b8e94c.
Now.... the Crown Jewels of tuning.... how are the mutipoint checksums calculated? Well, here's the disassembled code:
| ; Calculate 32 bit checksum |
| ChkSumCalc: |
|
; |
| |
mov |
r1, ChksumResultLo_382866 ; 32 bit chksum Lo result |
| |
mov |
r2, ChksumResultHi_382868 ; 32 bit chksum Hi result |
| |
mov |
r3, ChksumStartAddr_38286C ; Address of chksum start range |
| |
mov |
r4, ChksumSeg_38286E ; Segment number of chksum start range |
| |
mov |
r5, ChksumLength_382870 ; Length in double words of chksum range |
| |
jmpr |
cc_UC, calc_86DA00 ; Relative Conditional Jump |
| loop_86D9F4: |
|
|
| |
exts |
r4, #2 ; Begin Extended Segment Sequence |
| |
add |
r1, [r3+] ; Integer Addition |
| |
addc |
r2, #0 ; Integer Addition with Carry |
| |
exts |
r4, #2 ; Begin Extended Segment Sequence |
| |
add |
r1, [r3+] ; Integer Addition |
| |
addc |
r2, #0 ; Integer Addition with Carry |
| calc_86DA00: |
|
; |
| |
cmpd1 |
r5, #0 ; Integer Compare and Decrement by 1 |
| |
jmpr |
cc_NZ, loop_86D9F4 ; Relative Conditional Jump |
| |
mov |
ChksumResultLo_382866, r1 ; 32 bit chksum Lo result |
| |
mov |
ChksumResultHi_382868, r2 ; 32 bit chksum Hi result |
| |
mov |
ChksumStartAddr_38286C, r3 ; Address of chksum start range |
| |
jmpr |
cc_NZ, loc_86DA14 ; Relative Conditional Jump |
| |
add |
r4, #1 ; Integer Addition |
| loc_86DA14: |
|
; |
| |
mov |
ChksumSeg_38286E, r4 ; Segment number of chksum start range |
| |
rets |
; Return from Inter-Segment Subroutine |
| ; End of function ChkSumCalc |
From this code you can see that the checksum only consists of adding all of the program words up and storing them into a 32 bit result..... fairly straight forward!
Complete ROM Checksum
The ROM checksum is calculated from two structures:
typedef struct ROMChksum
{
unsigned __int32 nStartaddr;//start address
unsigned __int32 nEndaddr;//end address
unsigned __int32 nChksum; //checksum
unsigned __int32 nInvChksum; //complemented checksum
} ROMChksum;
The structures in ROM tell us the following:
StartAddr_81BFE6:dw ROMSTART_800000 - ROMSTART_800000
seg206:3FE8 StartSeg_81BFE8:dw 80h ; DATA XREF: ResetROMChksum_86B972+14r
seg206:3FEA EndAddr_81BFEA: dw ROMEND_80FBFF - ROMSTART_800000
seg206:3FEC EndSeg_81BFEC: dw 80h ; DATA XREF: ResetROMChksum_86B972+2Er
seg206:3FEE ; Checksum Block 2
seg206:3FEE ;
seg206:3FEE dw ROMSTART_820000
seg206:3FF0 dw 82h
seg206:3FF2 dw ROMEND_87FFFF
seg206:3FF4 dw 87h
This is a bit difficult to read but it's saying that the ROM checksum is calculated from two address ranges:
0x800000 - 0x80fbff
0x820000 - 0x87ffff
This result is then stored on the ROM.
It's interesting to note that this particular range does not cover the maps, i.e. 0x810000 - 0x81ffff.
CRC32 Checksum
The ME7.1 also contains a 3 stage CRC32 based checksum.
For each address range, the ME7.1 uses the following algorithm:
Create a 32bit rolling checksum variable and initalise it with 0xffffffff
FOR(STARTADDRESS TO ENDADDRESS)
1 read byte at current address
2 XOR the value in (1) with the LSB of the rolling checksum
3 shift left by two bits the value (2)
4 use (3) as an offset to the address of XOR Seed table within the ECU
5 read the 32bit value referenced by this address
6 shift right the rolling checksum by 8 bits
7 XOR the value from (5) with that from (6)
8 store this value (7) as the rolling checksum
ENDFOR
After the address range is calculated, invert the rolling checksum to give you the final XOR checksum.
No wonder it took me 6 months to work it out!
Checksum Source Code Example
One of my articles wouldn't be complete without some source-code would it?! Here's a simple application I wrote that demonstrates the checksum algorithms (except XOR):


The checksum tool will:
read in the Audi ME7.1 binary for the Audi S4,
extract the application strings,
systematically run through all the checksum blocks,
calculate the checksum
and then compare the calculated checksum with that stored on the ROM.
The tool can be downloaded here:
Executable only:
ftp://ftp.andywhittaker.com/pub/motronic71/ME71ChkSumv10.exe
C++ Source-code
ftp://ftp.andywhittaker.com/pub/motronic71/ME71ChkSumv10.zip
ENJOY!
You can download a fully functional program here ECUFix - NEW!
Reading/Writing the ROM via OBD
This is one of my next projects. I have already found the code that reads and writes to the FLASH ROM.
I need to find out how the OBD port parses its data and passes it to the code.....
.... watch this space! ....