MEMS3 Firmware Immobiliser Delete

Download Link:

Using my MEMS3 Mapper you can now easily delete the immobiliser functionality, even with the BMW EWS 3.D secure immobiliser system.

This is something that quite a few people have asked me for. For ECUs that are set up to use the Lucas 5AS or Pektron immobiliser systems, there is a scalar in the map which allows the ECU to run without needing a coded signal from an immobiliser. For ECUs that are set up to use the BMW EWS 3.D immobiliser system, this does not work. These ECUs are found in some Rover 75, MG ZT and Land Rover Freelander models. Once the ECU has been paired with one BME EWS immobiliser, it cannot be paired with another. This makes it very difficult to replace ECUs, either in case of failure or when doing turbo conversions and engine swaps etc. People have been asking me if it was possible to replace the BMW EWS functionality in the ECU with the equivalent Lucas 5AS routines (too complicated at the moment!) or alternatively to delete the immobiliser functionality altogether, leaving the ECU set to “free run”.

By following the instruction below, you will be able disable the immobiliser functionality in any MEMS3 ECU with any immobiliser system.

Basic Instructions

You will need to download the latest version (5.54 or later) of my MEMS3 Tools from here:

Using this version, perform a full read (both Firmware & Map) from the ECU.

Finding the immobiliser code which needs to be modified is a little bit complicated, so I’ve added a wizard to do it for you.

Click Tools, Wizards, Firmware Immobiliser Delete and you should see a dialog like this:

If there are three green tick marks shown, the wizard has been able to trace the immobiliser code (it finds them correctly in every unmodified firmware that I’ve ever seen).

Check Delete Immobiliser Functionality and then click OK.

This deletes the immobiliser functionality in the current project in MEMS3 Mapper – you now need to write the Firmware & Map back to the ECU in the normal way.

Technical Details

All of the ECUs fuelling calculations end up with one single number – the injector pulse width. This is the time for which the injector needs to be open in order to inject an appropriate quantity of fuel. One of the very last things the ECU does is to check a number of flags which control engine immobilisation under different conditions (some of which were related to factory development mode code). If any of these flags result in immobilisation being disabled, it skips over the critical instruction, otherwise it overwrites the calculated injector pulse width with 0, meaning that the injector is open for zero time (doesn’t open at all). You can see the various tests being done here in green in a ksr3p004, NNN000160 VVC 160 ECU. The instruction that effectively immobilises the engine is shown in yellow.



        00130382 08  38  00       btst.b     0x7 ,(BYTE_0000131f ).w

                 07  13  1f

        00130388 66  08           bne.b      LAB_00130392

        0013038a 08  38  00       btst.b     0x7 ,(varBitFlags1323 ).w

                 07  13  23

        00130390 67  14           beq.b      LAB_001303a6


        00130392 08  38  00       btst.b     0x7 ,(BYTE_0000131a ).w

                 07  13  1a

        00130398 66  0c           bne.b      LAB_001303a6

        0013039a 21  bc  00       move.l     #0x0 ,(BYTE_000009b8 ,-,D0w *0x4 )

                 00  00  00

                 05  a0  09  b8

        001303a4 60  06           bra.b      LAB_001303ac



The instruction show in blue is the last chance to skip over the instruction. It’s a “conditional branch” instruction “bne” which means “jump forward by a set number of instructions if the bit tested in the last test was 1”.

Engine immobilisation can be disabled simply by changing this one instruction from a “conditional branch” instruction “bne” (branch if not equal) to an “unconditional branch” instruction “bra” (branch always). This means changing a single byte from $66 to $60 and means that the immobilisation instruction is always skipped, irrespective of the immobilisation flags.

The complicated part is finding this particular instruction, as it will be at a different memory address in every different MEMS3 firmware version (of which there were hundreds), and there will be many very similar instructions throughout the firmware. The good news is that the code was highly conserved right across the MEMS3 product line and therefore we know what we are looking for and know what to do with it when we find it.

In my article on TestBook T4 (Main Dealer) Level Support for MEMS3 I described how I was using Service $21 "Request Data By Local ID" to request live data from the ECU. Inside the firmware there is a table of definitions, listing the fields (mostly RAM variable addresses) for the response record for each local identifier. My code searches for this table by scanning the whole firmware for instructions of the form LEA (NNNNNN).L,AN. Whenever it finds one, it examines the address loaded to see if it looks like it points to the table. It puts some pretty tough conditions on what can and cannot be considered to be the table so it should get it right every time. It tries to walk the whole table from start to end and only accepts it if it finds plausible records all the way through, the expected $FFFF “end of table marker” at the end, no duplicate identifiers and all of the mandatory record identifiers expected.

Once it’s found that, it extracts the Injector 1 Pulse Width variable address from the record definition for identifier $0C and then scans the firmware for a conditional branch followed immediately by the instruction that zeroes that out, as shown above.