Posts: 145
Joined: Sun Jun 10, 2018 8:32 pm
Location: Brisbane, Australia

Re: Firmware for charger, BMU, CMUs

Sat Dec 22, 2018 5:05 am


Sigh. There is a .csv (basically, ascii readable) file in the RPGDATA folder that I somehow managed to ignore all this time. It tells me a little story about what all the .RPG files are for. In short, I've been largely wasting my time looking at the RPG files, at least the ones I have so far. [ Edit: and at least for the present goal of iMiev firmware. ]

I've still found no relationship whatsoever between .RPG and .CFF files, though I still suspect that a given .RPG "carries" inside it a .CFF, along with a very complex program to upload it via the VCI.

In case it's of interest to anyone, here is the data on what's in the .RPG files that I have from the 2012 distribution.

Code: Select all

VE03071.rpg  Carisma - Countermeasure for smoke & engine hesitation when high speed
VE03072.rpg  Ditto
VE03073.rpg  Ditto
VE03074.rpg  Ditto
VE03076.rpg  Galant - Countermeasure for smoke/fuel consumption display & magnet
VE03077.rpg  Ditto
VE03078.rpg  Space wagon, as above
VE03079.rpg  Ditto
VE0307A.rpg  Ditto
VE0307B.rpg  Ditto
VE0307C.rpg  Space wagon - Countermeasure for output decline/smoke/fuel consumption display & magnet
VE0307D.rpg  Ditto
VE0307E.rpg  Space runner / wagon, as above
VE0307F.rpg  Ditto
VE0307G.rpg  Galant as above
VE0307H.rpg  Ditto
VE0307I.rpg  Space wagon as above
VE0307J.rpg  Ditto
VE0307K.rpg  Space wagon - Countermeasure for smoke/fuel consumption display & magnet
VE0307L.rpg  Ditto
VE0307M.rpg  Ditto
VE0307N.rpg  Ditto
VE0307O.rpg  Space runner, as above
VE0307P.rpg  Ditto
VE0307U.rpg  Colt/Lancer - Countermeasure for cold hesitation
VE03081.rpg  Ditto
VE03082.rpg  Ditto
VE03083.rpg  Ditto
VE03085.rpg  Pajero - Countermeasure for miss MIL light ON/engine hesitation when cold...
VE03086.rpg  Pajero - Addition ETV position gap detection
VE0308A.rpg  PAJERO/MONTERO - Countermeasure for the high boost
VE0308B.rpg  Ditto
VE0308C.rpg  Ditto
VE0308J.rpg  Carisma - Correct fuel consumption display
VE0308K.rpg  Ditto
VE0308L.rpg  Ditto
VE0308M.rpg  Ditto
VE0308N.rpg  Ditto
VE0308O.rpg  Space Star - Countermeasure for error MIL light ON
VE0308P.rpg  Ditto
VE0308Q.rpg  Ditto
VE0308R.rpg  Space Star - Correct fuel consumption display
VE0308S.rpg  Ditto
VE0308T.rpg  Ditto
VE0308U.rpg  Ditto
VE03091.rpg  Ditto
VE03092.rpg  Carisma - as above
VE03093.rpg  Ditto
VE03094.rpg  Space Star - Correct fuel consumption display
VE03095.rpg  Ditto
VE0309C.rpg  L200 - Countermeasure over heat
VE03101.rpg  Space Star - Shock countermeasure of during slow driving with first gear
VE04061.rpg  PAJERO/MONTERO - Countermeasure of hydraulic flywheel
VE04062.rpg  Ditto
VE04063.rpg  Ditto
VE04064.rpg  Ditto
VE04065.rpg  Ditto
VE04066.rpg  Ditto
VE04067.rpg  Ditto
VE04069.rpg  Ditto
VE0406E.rpg  Ditto
VE04091.rpg  Carisma - Countermeasure for engine hard start at extremely cold condition
VE04092.rpg  Ditto
VE04093.rpg  Ditto
VE04094.rpg  Ditto
VE04095.rpg  Ditto
VE04096.rpg  Ditto
VE05021.rpg  Space Star - Countermeasure for engine hunting around 1500RPM on slight down hill
VE05022.rpg  Ditto
VE05051.rpg  L200 - Countermeasure for high idling
VE05052.rpg  Ditto
VE05053.rpg  Ditto
VE05054.rpg  Ditto
VE05055.rpg  Pajero Sport - Countermeasure for high idling
VE06111.rpg  Lancer - Change data related to engine startability at low temperature(for Russian fuel)
VE06112.rpg  Ditto
VE06113.rpg  Ditto
VE06114.rpg  Ditto
VE06115.rpg  Lancer - Delete intermittent control of A/C. Change IG timing for knocking suppression...
VE07041.rpg  Lancer Evolution - Change F/C to prevent over rpm limit resulting in catalyst damage
VE08111.rpg  Pajero - Judgement value of the overboost was changed. Judgement time of the overboost was changed
VE08112.rpg  Ditto
VE08113.rpg  Ditto
VE08114.rpg  Ditto
VE08115.rpg  Ditto
VE09021.rpg  Pajero/Montero - Optimization of fuel control on deceleration. Changed ISC control on engine starting
VE09022.rpg  Ditto

Posts: 145
Joined: Sun Jun 10, 2018 8:32 pm
Location: Brisbane, Australia

Re: Firmware for charger, BMU, CMUs

Wed Dec 26, 2018 5:35 am

Another reverse engineering nerd specific post; feel free to skip if this isn't you.

It's taken me a while to learn the tricks of the CMU's compiler. It loves its register branch instructions, so some functions use the link pointer for the return address (as you'd expect), and others use random other registers. Why not, I suppose, when you have 32 to play with. It makes it very hard to visualise the control flow, and of course Ida Pro's guesses as to where the functions start and end are sometimes wrong, and tedious to fix. Most functions start with a branch to the end of the function, where there is a prepare instruction (a procedure prologue), then another branch back to the real start of the function (just after that first branch). I'm sure that there must be a really good reason to do that, but it eludes me.

In order to call functions from an array, which happens quite often, there is a problem: there is no call instruction that takes a register as the destination; it's always a constant. So they use this complex sequence; in this example, the address of the function to be called is in r16:

Code: Select all

movhi   1, r5, r1
movea   (loc_96DC & 0xFFFF), r1, lp
jmp     [r16]

So the movhi instruction moves 1 to the top half of r1, and adds the contents of r5. What's in r5? It was set waay back before the start of main to be zero. There's a perfectly good always-zero register (r0), but they always use r5. I can only imagine it's good for debugging or some such thing. The movea moves the lower half of the destination (0x96DC), and adds r1, and the result goes to the link pointer. So that's the return address. But wait: there is no one in the upper half of the address! Because the destination (0x96DC) has the sign bit (bit 15) set, the offset is sign extended to be a negative number. Negative offsets are wonderful to this compiler :-) But this negative number added to the 0x10000 already in r1 results in the correct 0x96DC. I finally twigged to this when I got to some code where the destination really was above 0x10000 (64 KiB), and it actually made sense. In many cases, these weird sequences are the only way execution gets to the destination, so of course Ida Pro can't recognise that it's code, and it starts off as unexplored data. That causes a cascade of unexplored code that is called only by that code. At least there isn't much data interspersed between the code, so it's largely a matter of marking big blocks of data as actually code.

99% of references to RAM are via the global pointer register, gp. I've finally figured out how to use enough of Ida Pro's user-defined offset to get what I need, but RAM references end up looking like this:

ld.b (byte_3FFD88C - 0x4005000)[gp], r11

That's just loading the byte at 3FFD88C to r11. The global pointer always contains the strange value 0x4005000, which is 20 KiB past the end of RAM, so all the references to RAM are with negative offsets. But it can't reach all the way to the start of RAM (0x3FF8000), so it seems to me that the first 0x3000 (12 KiB) of RAM are special or different.
There is also some special hardware or external RAM mapped to 0x3FEC000-0x3FFFFFF, which are referenced with negative offsets from r1. Because... negative offsets are beautiful!

The code is also very heavy with its use of arrays. There are arrays in RAM and also plenty in flash memory as well. There are arrays of pointers to functions, pointers to RAM (which point to other parts of RAM, or act as indices into other arrays), or of course to other structures in flash or RAM. There are many "arrays" in flash with one entry, always accessed with index 0, so the value is always a constant. :roll:

While I'm at it, here are the two most useful manuals for CMU work:
R01US0037EJ0100: V850E2S User’s Manual: Architecture (for the instruction set)
R01UH0129ED0701: V850E/Dx3 - DJ3/DL3 32-bit Single-Chip Microcontroller (for the many special function registers). I have Rev. 7.01.
Hopefully useful soon: Linear Technology Multicell Battery Stack Monitor manual; the command codes for the LTC6802 chip start about half way through the manual.

With these breakthroughs, I hope to finally get to the meat of the code. It's been frustrating to date, seeing lots of code, but none of it does much so far.

That's for the CMU (Cell Management Units). It would be better to reverse engineer the BMU code, or the charger, but I don't have a .CFF file for the charger, and I've made no headway at all with the code for the BMU, other than hopefully finding what looks to be the correct processor series (M32r series). My suspicion is that most CFF files are encrypted, but the CMU code may have fallen to a junior engineer, or the engineer simply forgot, or thought it wasn't worth the effort to encrypt. With that in mind, I've had a few quick passes over the MUT PC software, but I haven't hit on a reference to CFF files as yet.

Edit: I meant to add a paragraph about the PC-relative addressing. For a long time, I had no idea where the start of the code is; it turns out to be about 0x55AE, but perhaps the real start is 0x6000). All branch instructions are PC-relative, so they're no help. Often you can find interrupt vectors, but I still haven't found one that ends in a reti (return from interrupt) instruction. Eventually, I found some absolute addressing code, but it wasn't special enough to be able to find it in 384 KiB of flash memory. Eventually, I found one that had a particular "signature" (like an array of structures containing a pointer to RAM that was always followed by a byte), and was able to match it to such a pattern in flash memory.

Oh, one last whinge. Ida Pro (which goes back to the glory days of 16-bit 8086s) talks about bytes (8-bit), words (16-bit) and longs (32-bit). Modern 32-bit machines such as this one talk about bytes (8-bit), half-words (16-bit), and words (32-bit). The number of times I've seen a load.w instruction and thought that it refers to a 16-bit thing like word_876C is... too many :o

[ Edit: added sentence about flash arrays with one entry. ]
[ Edit: Added link to LTC6802 manual. ]
Last edited by coulomb on Sat Dec 29, 2018 3:11 am, edited 5 times in total.

Posts: 858
Joined: Sun May 03, 2015 7:15 am
Location: The Heart o' Dixie
Contact: Website

Re: Firmware for charger, BMU, CMUs

Wed Dec 26, 2018 8:32 am

Great work as usual, thanks for sharing. i know you have the knowledge, skills and abilities to solve complex codes such as this, and so encourage you to endeavor to persevere.

Makes you wonder who wrote the compiler with all the bizarre and complicated twiddling just to point to a jump address or a memory register.

And then to use different families of processors across various ECUs is a strange strategy. Seems that commonality would lower costs for development and testing, etc., but maybe it was done intentionally to avoid mistakes of loading the wrong code..?
kiev = kenny's innovative electric vehicle

Posts: 145
Joined: Sun Jun 10, 2018 8:32 pm
Location: Brisbane, Australia

Re: Firmware for charger, BMU, CMUs

Sat Dec 29, 2018 3:43 am

More information on the 2012 distribution. This is the starting post:

In the first post of that topic, there is a .rar file. It just contains a .torrent file, which allows you to download a CD-Rom's worth of install data (about 800 MiB). I note that there are passwords mentioned in later posts, but I've not had the opportunity to use them as yet.

There are two main folders: PRE11121-00 and CD3E11121-COPY MASTER. I think you're supposed to install the first one first, then the second folder is a sort of add-on (edit: in fact, an update). Both folders have their own InstallShield executables. When I try to install the former, I get a message box with "The M.U.T.-III system has started. Please suspend a M.U.T.-III system, reboot a personal computer, and start UPDATE."

"UPDATE" probably refers to the other folder, see below.

All the folders in PRE11121-00\INSTALL have encrypted cabinet files; they seem to have customised InstallShield individually for each folder. I see talk of PUBLIC_KEY, and I may have stumbled onto one of the private keys. It could take decades to sort all that out.

But I think that the interesting part for iMiEV users is in the second folder, CD3E11121-COPY MASTER. One subfolder, CAESARCOMPDB, seems to have encrypted cabinet files, and may contain information about the CFF files. So I might make an effort to install that one day. I get "M.U.T.-3 system has started. Please perform after ending M.U.T.-3 system" for the CD3E11121-COPY MASTER update. Maybe it's OK to have the 2018 MUT system, and still use the CD3E11121-COPY MASTER update files.

However, one folder of CD3E11121-COPY MASTER doesn't seem to be part of an encrypted cabinet; it's MUT3\RPGDATA. It contains some 88 .RPG (ReProGram) files, and a similar number of .cff files in CD3E11121-COPY MASTER\RPGDATA\CFF. In my earlier head-slap post, I mentioned how the .RPG files seem to be all for other vehicles. Only four files, all starting with 9499 (this seems to be a product code for iMiEVs), seem to be iMiEV related. I have one other iMiEV file from another source, and it appears to be another version of two of these four. Of these five iMiEV related files, only one, which appears to be the firmware for the CMUs, seems to be unencrypted. Given the paranoia associated with all the other MUT-III files, this seems to be a miracle. Unfortunately, it's looking very much like the CMU processors don't do all that much, despite their quite complex firmware. All they seem to do is to send data to the LTC6802 battery stack monitor chips, copying the commands downstream, and sending the data upstream to the BMU. I don't see any of the commands, since these would come to the first CMU from the BMU. There doesn't seem to be any interpretation of the results; that seems to all happen in the BMU.

So at present, I'm stuck. I need to figure out how to decrypt the four encrypted .CFF files (three are for the BMU, one for the EVECU). It also appears that out of all this data, no file contains the charrger firmware, encrypted or otherwise. Hopefully, I'll get some inspiration soon.

[ Edit: added sentence about passwords mentioned in later posts from the first link. ]

Posts: 145
Joined: Sun Jun 10, 2018 8:32 pm
Location: Brisbane, Australia

CAN bus messages on the BMU to CMU private bus

Tue Mar 12, 2019 8:03 pm

CAN bus messages on the BMU to CMU private bus

I'll attempt to give these messages in the format of Decyphering iMiEV and iON CAR-CAN message data . Since these messages are only on the private BMU to CMU CAN bus, and seem to be modified when they reach the BMU and the main vehicle CAN bus, this will only be of interest to those wanting to use the CMUs that come with the iMiEV battery, without using the iMiEV BMU. Since the CMUs are buried inside the battery, it makes sense to make use of them.

I have not used these, or captured data from a real iMiEV; this is all from reverse engineering the CMU firmware. I'm finally making some progress in that direction.

Cell and temperature sensors will be numbered from one as the lowest number. It may be of interest to some to compare these with the 6D1-4 / 6E1-4 messages documented over 6 years ago by garygid in this post.

From CMUs to BMU

6n1, where n is the CMU ID, 1-C, for the 12 CMUs:
6n1:D1 = 0x20 (if boolCan1) + CMU ID. So either 21 to 2C or 01 to 0C.
6n1:D2 = bypass bits. Each bit will be set if the cell was actually bypassing at least sample.
6n1:D3, D4: Temperatures 1 and 2. I believe that these are in whole °C with a -40°C offset. So temperature = value - 40. Limits 20 - 130 representing -20°C to +95°C. I can't be certain about the offset (-40).
6n1:D5 & D6 as ((D5 * 256) + D6) / 200 + 2.1 = cell voltage 1
6n1:D7 & D8 as ((D7 * 256) + D8) / 200 + 2.1 = cell voltage 2

6n2, where n is the CMU ID, 1-C, for the 12 CMUs:
6n2:D1 = 0x20 + CMU ID. So 21 to 2C.
6n2:D2, D3: Temperatures 3 and possibly 4. Same encoding as above. D3 will be zero if n=6 or n=12 (4-cell CMUs).
6n2:D4 = 0.
6n2:D5 & D6 as ((D5 * 256) + D6) / 200 + 2.1 = cell voltage 3
6n2:D7 & D8 as ((D7 * 256) + D8) / 200 + 2.1 = cell voltage 4

6n3, where n is the CMU ID, 1-C, for the 12 CMUs:
6n3:D1 = CMU ID. So 01 to 0C.
6n3:D2, D3: Temperatures 5 and 6. Same encoding as above.
6n3:D4 = 0.
6n3:D5 & D6 as ((D5 * 256) + D6) / 200 + 2.1 = cell voltage 5
6n3:D7 & D8 as ((D7 * 256) + D8) / 200 + 2.1 = cell voltage 6
I believe that CAN IDs 663 and 6C3 (for CMUs 6 and 12) will not appear (unverified at present).

6n4, where n is the CMU ID, 1-C, for the 12 CMUs:
6n4:D1 = CMU ID. So 01 to 0C.
6n4:D2, D3, D4: All 0.
6n4:D5 & D6 as ((D5 * 256) + D6) / 200 + 2.1 = cell voltage 7
6n4:D7 & D8 as ((D7 * 256) + D8) / 200 + 2.1 = cell voltage 8
I believe that CAN IDs 664 and 6C4 (for CMUs 6 and 12) will not appear (unverified at present).

From BMU to CMUs
3C3:D1&D2 as ((D1 * 256) + D2) / 200 + 2.1 = bypass voltage (bypass if cell voltage exceeds this value, and bypassing is enabled)
3C3:D3[0]: bypass enable bit
3C2:D3[1]: some flag associated with bypassing
3C3:D4[0-2]: other flags, use not determined as yet

There appears to be another CAN packet, or possibly serial packet, that mimics the above (i.e. it provides alternative bypass threshold and enable bit). I have yet to determine where this comes from (handler at 0x0E3C0).

To be completed.

Return to “Batteries and Battery Management”