Documentary - Motronic 1.7 DIY Reverse Engineering

Collapse
X
 
  • Time
  • Show
Clear All
new posts

  • Rasp
    replied
    If you want play with Motronic datalogging RAM variables by K2 protocol with standart baudrate 9600, you can use KWP71Diag tool https://mega.nz/#!jU8A1ZYA!ajEXKoQy_...hmoGrmZh3r0T54
    with predefined config to M1.7-M1.7.3



    This program will work with simple VAG COM KKL 409.1 adapter, but only with FTDI chip!

    Virtual COM port must be configured:

    Leave a comment:


  • Rasp
    replied
    Lets continue old Motronic digging :)

    Thanks to bmwman91 we have full schematic for M1.7 and can deal with software without "black box" engineering.

    So, we know that CPU is SAB80C515 (datasheet - https://mega.nz/#!iFEViaTR!JPTSSeoff...uffwC7KPd61RZE).
    It has several interrupts which can be executed by software and/or hardware.
    Crankshaft position sensor is connected to P1.0, so IEX3 interrupt hardware execution starts with every tooth on crankshaft wheel. So all crankshaft position-math is doing in this interrupt.

    Also this interrupt caused another, software interrupts - per-segment event (IE0) and knock sensor value measurement (IEX4).

    Another hardware interrupt (IE1) is caused by Vehicle speed sensor.

    Also Motronic has background main cycle loop, here caused sensors lineralization (except VAF, Crankshaft sensor, Camshaft sensor and Vehicle speed sensor), store calculated values to RAM for further use in interrupts (directly in interrupts use only raw values from data area, not from 2D or 3D tables with interpolation due to speed of calculation and there is no need to calculate most values often).

    Leave a comment:


  • Rasp
    replied
    Originally posted by bmwman91
    I assume that the difference between the 276/660 and 277/661 DME's is that one is for the 1.6L and one is for the 1.8L?
    Yes.
    Last edited by Rasp; 01-25-2018, 09:14 PM.

    Leave a comment:


  • bmwman91
    replied
    I am a monster lol. So much for not collecting more junk in my house. I just ordered 2 more DME's on eBay. 0261203282 and 0261200990 which were a couple of variants of the E36 M1.7.2. Just so I can get pictures of the guts and document how this thing changed over time. It will be interesting to see how 0261203277 compares.

    There do not appear to be any 0261203357 units on there, though. Once I dig into the 1.7.2 units a little, I can see about obtaining a M1.7.3 unit. I assume that the difference between the 276/660 and 277/661 DME's is that one is for the 1.6L and one is for the 1.8L?
    Last edited by bmwman91; 01-23-2018, 08:13 AM.

    Leave a comment:


  • bmwman91
    replied
    Originally posted by nando
    Nice thread - this is something that I'm really into now (disassembly). Always wanted to play with the earlier stuff since it's so much simpler, but it's hard because everything is so old and the info is lost - the info Rasp has provided is invaluable!

    I'm pretty comfortable with IDA these days so if you have any questions, maybe I can help - mostly I've been working on MPC5xx and TriCore CPUs though, which is much newer - MPC is actually somewhat easy to disassemble because instructions are fixed length, so if you don't know what something is you can just assume it's 32 bits and move on. :)
    Seriously. As much as the 8051 is regarded as being a venerable platform which was instrumental in the proliferation of microcomputing, screw it. I got my start in embedded systems with 8- & 16-bit PIC/dsPIC controllers using assembly language (I sort of prefer it to C in many cases), and I guess I was spoiled by the ease of using a more modern architecture. The extra-wide program pathways allowing single instruction jumps to any address were nice...the 8051's "true" 8-bit architecture has all sorts of jumps and branches with are constrained to a 2K block, so you end up with branhces-to-jumps and that sort of thing. Gross. Even the PIC/dsPIC aren't as nice as the MPC5xx/TC though since a few instructions are larger than others.

    If you want to take a look at the stuff, the full 40K BIN (with everything in address-correct order) is here:


    Originally posted by Rasp
    Quick answer about M1.7.2 and M1.7.3 DME part number.

    0261203276, 0261203277 - is M1.7.2 for 1.6 and 1.8 engines.
    0261203660, 0261203661 - is M1.7.3 for 1.6 and 1.8 engines.

    Immo can be disabled in 1 bit for M1.7.2 and custom software for M1.7.3, there is not problem, you can buy any.

    Schematic M1.7.2 and M1.7.3 are complitely different, for example M1.7.3 has no dauther board.
    Hmm interesting. I can not find much information on the web regarding M1.7.3, and I got the wrong PN so I bought 0261203277. That might be OK though since I do want to understand the hardware differences across the different M1.7 units.

    Do you know what the difference between the 0261203277 DME and the 0261200990 / 0261203282 / 0261203357 DME units which I believe were all M1.7.2 units used on US E36 M42 cars between 1992 & 1995? Also looking forward to why M1.7.3 is better than M1.7.2! If M1.7.3 is like the M5.2 (M44 DME) that I took apart, I am not sure if I can make a schematic since Bosch seems to have stopped putting part reference markings on the board, probably to make it more difficult for hackers. I would have to invent my own references (R001, R002, etc).





    I can't pull up IDA right now, but I have noticed some issues that I am not sure of. The SAB80515 differs from "classic" 8051 controllers in that it has 256B of internal RAM, with the lower 128B (00h-7Fh) being directly addressable, and the upper 128B (80h-FFh) sharing addresses with the SFR's. The SFR's are accessed directly, and the scratchpad RAM is accessible only by indirect addressing. There are some instructions in the disassembly which try to directly access locations in the 80h-FFh range, but do not correspond to SFR's. An example would be "MOV A, RESERVED_B2" or something like that. I can make a list of these instructions later, and maybe they all fall into data constant regions which I have not correctly identified. Thoughts?

    Leave a comment:


  • Rasp
    replied
    Quick answer about M1.7.2 and M1.7.3 DME part number.

    0261203276, 0261203277 - is M1.7.2 for 1.6 and 1.8 engines.
    0261203660, 0261203661 - is M1.7.3 for 1.6 and 1.8 engines.

    Immo can be disabled in 1 bit for M1.7.2 and custom software for M1.7.3, there is not problem, you can buy any.

    Schematic M1.7.2 and M1.7.3 are complitely different, for example M1.7.3 has no dauther board.

    Leave a comment:


  • nando
    replied
    Nice thread - this is something that I'm really into now (disassembly). Always wanted to play with the earlier stuff since it's so much simpler, but it's hard because everything is so old and the info is lost - the info Rasp has provided is invaluable!

    I'm pretty comfortable with IDA these days so if you have any questions, maybe I can help - mostly I've been working on MPC5xx and TriCore CPUs though, which is much newer - MPC is actually somewhat easy to disassemble because instructions are fixed length, so if you don't know what something is you can just assume it's 32 bits and move on. :)

    Leave a comment:


  • bmwman91
    replied
    Also,
    A long time ago I found a simple EXE on some random website to calculate checksums for a few different DME's. I disassembled the EXE and got the exact algorithm used for the checksum in M1.x. It is pretty simple. Again, addresses are referring to those on the 32K EPROM, not the proper 40K image.

    CSUM = MOD([SUM(0000h:1EFFh) + SUM(2000h:7FFFh) + 46367], 65536)

    This 16 bit value is then stored at address 1F00h:1F01h (MSB:LSB).


    The EXE I found (not mine, I take no credit for making it) is here. It seems to support a number of variants (run through command line):

    Leave a comment:


  • bmwman91
    replied
    Thank you for confirming the ranges of data constants. So 4000h-5BFFh are data, maybe it is all used, maybe not, and the last 288 bytes. Is that all of the constant data that you know of?

    Understood about the sections with no XREF's. There are one or two large ones, and a number of small ones (some I was able to fix because they use "JMP @A+DPTR" which cannot be properly traced without real emulation).

    I can update the schematic to give "unknown" names to the AN6/7 nets since I am only guessing there. Can you take some photos of the top and bottom of the main board so that I can see the layout? The part number etched into the main board is 1268322158-7. My guess is that M1.7.2/3 have the same main board, but maybe different daughter boards in A250 and A200. So, depending on this I might be able to build a complete 1.7.3 schematic for you.

    Let me know your thoughts on why M1.7.3 is superior to M1.7.2. I am happy to learn and consider that for a conversion. There are many on eBay for OK prices, all in Europe since no US-version BMWs had the M43. There seem to be two versions of 0261203277, a silver label one and a gray label one. Do you know the difference between them? One eBay listing says that the gray label one has the EWS/immobilizer, which I would probably want to avoid, but if the firmware is being accessed then it can probably be removed.

    EDIT: I got info from the eBay seller and the gray-label one has no immobilizer. So I purchased one from Italy for $50 with free shipping and should have it next week.

    As for the ROM, the interrupt vector table seems to be exactly the same, so interrupt calls will jump to the correct location in EPROM, but much of the other stuff is different. Some of it looks like code, some looks like data constants, and of course there is a lot of FF!

    Looking forward to your info on the $5 cable to communicate with. I could not find a KW71 interface box that looked like it would work for less than $120, so I just used the Arduino directly on the DME.
    Last edited by bmwman91; 01-22-2018, 11:20 AM.

    Leave a comment:


  • Rasp
    replied
    Originally posted by bmwman91
    There are also some areas with no XREFs, so those are either data constant blocks or the disassembly did not complete properly.
    Not every firmware uses all code, but he is present. Bosch just wrote everything who need at current time of development and place it to firmware.

    Originally posted by bmwman91
    If you have some info on the address ranges which are data constants, that would be helpful (so far it looks like 4000h - 5BFFh is one big block, but I suspect others are there too).
    Main thing that ALL tables in Motronic 1.1-1.7 is between "1 SEGM." and "2 SEGM." (you can see accurate block address with IDA), and of course there is several occurs in the end of binary (last 288 bytes) and inside code, you can find it by search "mov DPTR, " through listing and skip all addresses which point to 4000h - 5BFFh (or another area of MAP segment, if you see another firmware), external RAM and extend chip S702 (A0XXh addresses).

    Originally posted by bmwman91
    I double-checked the PCB images, and the connections that I made in the schematic seem to be correct (AN6 and AN7 are linked to two pins on A250 through two not-present resistors).
    I rechecked asm listing, and found that you correct! Thats what do I call walking around for years, without right schematic. But AN6 is NOT KS1 or KS2, its something else but 100% not knock sensor, because its not readed in crank-syncronised interrupt. In this regard, a huge request will figure out the scheme M1.7.3.
    M1.7.2 not worth paying attention, if you want I can give a detailed answer, why should switch to M1.7.3 and not to M1.7.2.
    I'm already swaped M1.7.2 to M1.7.3 on my car.


    Originally posted by bmwman91
    The internal ROM from my ECU matches exactly to the M1.3 ROM, and it matches partially to the M1.7 ROM that you posted. Which version is yours from?
    Its from M1.7.2 and M1.7.3. I have guess that ROM is not hardly strict to Motronic version, but for DME part number, so most likely it depends on the year of release. I called ROM some time ago because of ignorance this fact. If you try to disassemble M1.7 with 1.7 ROM you will notice that all OK and if you want to recalculate checksum with 1.7 ROM, you notice that all OK too.

    Originally posted by bmwman91
    Also, I found a way to use an Arduino to directly communicate with the MCU, without needing to deal with the K-Line and L-Line. It involves some soldering to connect direct to the 8051 Rx and Tx pins, plus the L-Line endpoint on S550 to send the 5-baud address to initiate communication. I will try to put together some details on that here.
    No need Arduino for communication with old Motronic, just need $5 cable with BMW 20 pin adapter, and soft used all around the world :) I wrote about this later.

    Leave a comment:


  • bmwman91
    replied
    Very good info, thanks! I have been doing some work in IDA as well and am starting to get a rough understanding of the code. There are a number of areas in the code where jump offset values are hard-coded into the firmware, so I can see that great care needs to be taken when changing things. There are also some areas with no XREFs, so those are either data constant blocks or the disassembly did not complete properly. If you have some info on the address ranges which are data constants, that would be helpful (so far it looks like 4000h - 5BFFh is one big block, but I suspect others are there too).

    As for the schematic, this is M1.7 (not 1.7.2 or 1.7.3) so maybe there are other differences that I do not know of. The A250 daughterboard is not actually present in M1.7, but I am guessing that it is the knock processor subsystem based on what is connected to the empty solder connection holes. I double-checked the PCB images, and the connections that I made in the schematic seem to be correct (AN6 and AN7 are linked to two pins on A250 through two not-present resistors). Also I compared the 8K ROM files that you have linked to the 8K ROM that I got out of my ECU. The internal ROM from my ECU matches exactly to the M1.3 ROM, and it matches partially to the M1.7 ROM that you posted. Which version is yours from?

    Thanks again for the info. Looking forward to more!

    Also, I found a way to use an Arduino to directly communicate with the MCU, without needing to deal with the K-Line and L-Line. It involves some soldering to connect direct to the 8051 Rx and Tx pins, plus the L-Line endpoint on S550 to send the 5-baud address to initiate communication. I will try to put together some details on that here.

    Leave a comment:


  • Rasp
    replied
    bmwman91 I guess you have mistake in your schematics.

    AN0 - AFM
    AN1 - VBATT
    AN2 - IAT
    AN3 - CTS
    AN4 - TPS
    AN5 - COPOT
    AN6 - LAM
    AN7 - KS

    AN5 is used for retrieve CO potentiometer voltage, AN6 for retrieve oxygen sensor voltage, AN7 used for retrieve selected knock sensor voltage.

    Select current knock sensor is doing by set logical 1 to P4.0 and 0 to P4.1 and vice versa.

    Leave a comment:


  • Rasp
    replied
    bmwman91 this is awesome info! I have long dreamed for schematics of M1.7.X, because software disassemble without any technical info (or a little with pin calling) is very hard work, mostly wrong, possible for a years.

    I have some software information given by reverse and research several of Motronics versions for few cars and some my expirience about development process. All my info may be right, or something wrong, or totally crap for current time of writing :) Software of such complex thing of Motronic does not right understandable without full description (of course this information can be given only from insiders, many-many years ago, for now its seems hard - all documentation was kept on paper and I'm sure all Motronic 1.X engineers are already retired or died now), all bits of information was given from diagnostic software or XDF and shared info by another enthusiasts of old Motronics and one "digital" DAMOS from M4.4 system, which based on C51.

    At first of all (before any research or software modifications) need some software and hardware instruments.

    Hardware:
    EPROM programmer (I'm use MiniPro TL866CS USB)
    Several W27C512 chips

    Software:
    IDA Pro v6.1 (this version best detect code/data for C51) - https://mega.nz/#!mNtGjTaQ!6m7hpX_2Q...yb33ldRiA0NOQY
    HxD Hex Editor - https://mh-nexus.de/en/hxd/
    as515 (modified as31 assembler, for C515) - https://mega.nz/#!fRc2kSxK!hReKkIqON...qCgG9KeQe_hkBs
    convert (tool for calculate checksum and convert compiled binary to flash binary) - https://mega.nz/#!HctCHZpB!FuNKHd0We...JPh4ymqpd7LH9Q
    ASM editor (I'm use Notepad++) - https://notepad-plus-plus.org/download/
    Set of ROM files for Motronic M1.2, M1.3, M1.7 - https://mega.nz/#!PJF0BIAY!j7aZx5hVm...QW3f2KZU7Waf-U

    Next need to compose full binary if Motronic use 32K bytes flash. Bosch wants to save money (because 64K UV-EPROM is two 32K crystals on one case) and use 8K ROM memory for common functions and 32K flash memory for rest code and data. Only M1.7.3 from BMW 1.X Motronic use 64K flash memory, without ROM, because 40K flash is not enought (but use same first 8K segment with common functions).

    So, for getting full binary ready to disassemble, you need get ROM suitable to Motronic version and place it content from 0x0000 to 0x1FFF, original content from that range must be placed from 0x8000 to 0x9FFF.



    After that, open result file in IDA Pro, and select "Processor type".



    Next screen leave without any changes.



    On next screen select C515 processor.



    Than press "space" button for switch from code overview to code listing, and click on "Unhide all" item menu.



    After all preparations, we can produce ASM file.



    This file is need some modifications for better editing and comatability with as515 assembler. At first need to remove SFR defines.





    Then add STACK define, after last RAM define:

    ".equ STACK,0xD5"

    Stack address (0xD5) is determined from search "mov SP," string, for example search result is "mov SP, #RESERVED00D5"

    and finally replace all occurrences of "RESERVED00D5" with "STACK"





    After that need to rename interrupt labels (set by default interrupt labels conflicted with SFR labels) for prevent assembler errors.

    "RESET:" => "RESET_HANDLER:"
    "IE0:" => "IE0_HANDLER:"
    "TF0:" => "TF0_HANDLER:"
    "IE1:" => "IE1_HANDLER:"
    "TF1:" => "TF1_HANDLER:"
    "RI_TI:" => "RI_TI_HANDLER:"
    "TF2_EXF2:" => "TF2_EXF2_HANDLER:"
    "IADC:" => "IADC_HANDLER:"
    "IEX2:" => "IEX2_HANDLER:"
    "IEX3:" => "IEX3_HANDLER:"
    "IEX4:" => "IEX4_HANDLER:"
    "IEX5:" => "IEX5_HANDLER:"
    "IEX6:" => "IEX6_HANDLER:"

    And of course need to change "ljmp RESET" to "ljmp RESET_HANDLER" throughout listing.


    Now you can compile binary, but for Motronic with used ROM inside CPU if you want to change some logic, you can possible to break internal code structure.
    So we need follow few rules:
    1) Do not edit everything in area from address 0x0000 to 0x1FFF, because this area is placed on ROM and any changes will be ignored.
    2) Do not edit interrupts and common fuctions wrapper area, placed from 0x2000 to first occurence of text "djnz RAM_4A", because code from ROM is call on hard links placed in this area, but if you know what you do, you are welcome.
    For firmwares fully placed on EPROM this rules is not strictly, but necessary.



    3) it is necessary to fix place of the calibration area because links to this area are found all over the code, and of course need remove empty areas without code shift.
    So need place the ORG directives in the right places.

    How find calibration area? Typically, the calibration area is outside the code, in early BMW Motronics it was be. Since Motronic M1.1 firmware strusture looks like this:



    Segments is not hardly restricted by hardware (except using ROM for first 0x2000 bytes), but in some cases must be placed as is, due to math offsets.
    So is best practice place ORG directives before each segment start:









    And put ORG directive to end of code, for prevent exceed 40K size of compiled firmware, also need remove waste 0xFF bytes inserted by IDA for mathing code to 64K size of compiled firmware.



    Also need fix place of firmware last 288 bytes, who store firmware info for daignostics.





    I recommend place ORG directives for whole code, for prevent use of waste 0xFF byte-offset, but is not necessary.





    Of course you can cleanup code from IDA comments with regexp ";(.)*?[\r\n]"

    After all preparations ASM file can be compiled to bin with as515 tool.
    Example of execution:

    as515.exe -Fbin firmware.asm

    Then for fix checksums and prepare compiled firmware to flash you can use convert.exe. This tool detect using ROM by file size (40K is used, 64K is not) and produce result file (32K or 64K) with correct checksum.
    Example of execution:

    convert.exe firmware.bin

    Also you can produce double 32K file for write to 27C512 EPROM, not 27C256, with param "-D".
    Example of execution:

    convert.exe firmware.bin -D

    In next posts I will talk about the internal strusture of the code, defined variables and some algorithms and methodics used in code.

    Leave a comment:


  • bmwman91
    replied
    Originally posted by kyleconstantine
    Wow very cool read....wish i had something to add but this is way above my head. Interested to see future updates. Do you think the motronic 1.72 could be adapted to run the m20?
    In theory, yes. M1.7 was used in Alfa Romeo 6 cylinder engines with wasted spark ignition, and the drivers for the fuel injectors are able to drive at least 3 per output. There are only two injector driver channels, which is why the M42 fires them in pairs. M1.7 has four ignition coil drivers, so you could either stick with the single coil, or convert to wasted spark. I think that later M20 engines had the 60-2 crank position wheel on the crank, which would be needed to use M1.7, and you would need to add a cam position sensor to really get full functionality. It is possible that knock sensing would not really be an option though since the way that the electronics on knock processors work is that they are essentially tuned for the piston diameter (since the frequency spectrum of knock events is strongly related to that). You would have a much easier time running Megasquirt, and it would allow fully sequential injection and COP ignition.

    Originally posted by Mykk540i/6
    Really amazing stuff! I've been working with the Motronic M3.3 system for a couple of years reverse engineering the software code for tuning purposes. This goes beyond anything I can comprehend.
    Got any info on M3.3? Chances are you know a lot more about the software on old Motronics than I do.

    Originally posted by varg
    Wow never thought I'd see someone do this. Are you an EE?
    Not officially an EE, no. But I am an engineer in the electronic hardware industry and I have done a lot of EE-esque work over the years.

    Leave a comment:


  • gath
    replied
    Wow! Very interesting, and beyond me :) Thanks for sharing. True labor of love :bow::bow:

    Leave a comment:

Working...