Monday, August 29, 2016

Hacking the R2J240 with LGC firmware


The second battery controller I looked at was the Renesas R2J240-10F020. It's a complete black box with very little information available except for some outtakes from the datasheet on Chinese developer forums. There is very little resemblance to the M37512, an older Mitsubishi/Renesas microcontroller used in earlier battery packs that's fairly well documented.


The first thing you notice is that this chip has the analog frontend integrated (unlike the M37512 or the bq8030) because there's no separate chip for measuring voltages and such. Cells are connected directly to this chip so it's a one-chip solution for building smart batteries.

SBS Report

$ smbusb_sbsreport
SMBusb Firmware Version: 1.0.1
-------------------------------------------------
Manufacturer Name:          LGC
Device Name:                LNV-42T4911
Device Chemistry:           LION
Serial Number:              41291
Manufacture Date:           2010.01.25

Manufacturer Access:        6001
Battery Mode:               e000
*snip*


Probing around



I started out by measuring voltages on all the pins. Just going by logic I was expecting some sort of differentiation on the various sides of the chip.

To summarize my findings after the first pass:
  • 1-12 is the "main microcontroller side" has the SMBus pins, VCC (and probably RESET and others)
  • 25-36  is connected to current sensing and exposes various built-in voltage regulators
  • 37-48  appears to be mainly unused with a couple of pins at 3.3v, GPIO side?
  • 13-24  has many pins connected directly to "high voltage" from the cells.
I took a 1k resistor connected to ground and started poking the pins with it to find reset. It should be possible to pull reset low through 1k resistor but unlikely on VCC and it shouldn't lead to a complete reset on an unrelated pin. It's also possible to rule out most pins through visual inspection and measurement. So long story short: Pin #12 is Reset.

Next I wanted to see if there's something like a Boot pin that's going to get me a different mode when pulled either low or high during reset so I started up a continuous command scan and started poking at the pins again.

Pulling Pin #4 (also connected to Test Point 1 on the other side of the PCB) low during reset gave me this:

$ smbusb_scan -w 0x16
------------------------------------
             smbusb_scan
------------------------------------
SMBusb Firmware Version: 1.0.1
Scanning for command writability..
Scan range: 00 - ff
Skipping: None
------------------------------------
*snip*
[f0] ACK, Byte writable
[f1] ACK
[f2] ACK
[f3] ACK
[f4] ACK
[f5] ACK
[f6] ACK
[f7] ACK
[f8] ACK
[f9] ACK
[fa] ACK, Byte writable, Word writable, Block writable
[fb] ACK, Byte writable, Word writable, Block writable
[fc] ACK, Byte writable, Word writable, Block writable, >Block writable
[fd] ACK, Byte writable, Word writable, Block writable, >Block writable
[fe] ACK
[ff] ACK

The chip was ACKing on every command. A deliberate attempt at confusing any would-be attacker perhaps? The write scan however reveals that the chip is actually exposing some real functionality on some of the commands and that a couple of them violate SMBus protocol.

Pin #4 appears to be BOOT (active-low).



Mapping

Mapping out the protocol took a while especially because it doesn't correspond to standard SMBus protocol but I was eventually able to figure out how to read and write to RAM and erase blocks of memory-mapped flash.
Just writing to the appropriate address in ram (after the flash blocks have been erased) writes the flash memory which is convenient.

There are several partitions of flash mapped into RAM and I'm sure I haven't found all of them. The ones I did are included as address&length presets in the flasher tool.



$ smbusb_r2j240flasher -d eep2.bin -p df2
------------------------------------
        smbusb_r2j240flasher
------------------------------------
SMBusb Firmware Version: 1.0.1
------------------------------------
Dumping memory 0x3400-0x37ff ...
Done!
$ xxd eep2.bin
0000000: 0000 0000 0000 0000 0000 ffff ffff ffff  ................
0000010: 4c4e 562d 3432 5434 3739 3700 0000 0000  LNV-42T4797.....
*snip*

$ smbusb_r2j240flasher -d eep3.bin -p df3
------------------------------------
        smbusb_r2j240flasher
------------------------------------
SMBusb Firmware Version: 1.0.1
------------------------------------
Dumping memory 0xc000-0xdfff ...
Done!
$ xxd eep3.bin
0000000: 0100 0700 b801 b801 1100 0203 0201 01e3  ................
0000010: e6fe e3ae 7000 e0e4 0cc8 0038 3150 14f0  ....p......81P..
0000020: 1530 2a4c 4743 0031 3100 0000 0000 0000  .0*LGC.11.......
0000030: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000040: 0000 004c 4e56 2d34 3254 3439 3131 0000  ...LNV-42T4911..
0000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000060: 0000 004c 494f 4e01 2d01 2d30 07fa 1031  ...LION
*snip*


In this particular battery pack the static information was stored in df3 and the dynamic in df2, df1 was empty.
Another battery stored dynamic info in df1 so this is going to differ between firmwares/packs.

Just like the bq8030 the static area is protected by a checksum on this controller/firmware as well. I took a shot at it just for kicks and it was pretty simple so I included it in the flasher tool.


$ smbusb_r2j240flasher -w eep3_f.bin -p df3 --fix-lgc-static-checksum --execute
------------------------------------
        smbusb_r2j240flasher
------------------------------------
SMBusb Firmware Version: 1.0.1
------------------------------------
Erasing flash block starting at 0xc000 ...
Done!
Fixing LGC static checksum..
Done!
Writing memory 0xc000-0xdfff ...
Done!
Verifying 0xc000-0xdfff ...
Verified OK!
Exiting Boot ROM and starting firmware.

$ smbusb_sbsreport
SMBusb Firmware Version: 1.0.1
-------------------------------------------------
Manufacturer Name:          LGC
Device Name:                Karosium000
Device Chemistry:           LION
Serial Number:              41291
Manufacture Date:           2010.01.25
*snip*


Reset

Pretty much the same procedure as with the bq8030. Map and modify the dynamic area. Eventually you'll find the error flag. As with the bq8030 the dynamic area isn't checksummed in this controller/firmware either.

Helpful tips:
  • Again, multiple log entries. The number of 0x00 bytes at the beginning of the section determine the number. Patch the duplicated data in all of them.
  • You can decrease the number of log entries to 1 for the time of mapping which will make the job a lot easier.
  • The real cycle count is stored encoded. No idea how. With this particular firmware it was at 0x78-79. Zeroing out the bytes still decreases the cycle count to 5 but the precise algorithm/obfuscation? No clue.
  • Please don't ask me to fix flash dumps :-)
  • Good luck!
Notes

No disassembly/ler for this chip. I don't really know what architecture it's based on. If I had to guess I'd say an extended version of the MELPS 7700, an old Mitsubishi architecture that Renesas inherited because trying to load it up in IDA with that core seems to produce something that starts to make sense but fails on invalid instructions. I could be completely wrong though.

If anyone wants to tackle this they could probably find a nice, easy way of getting into the Boot ROM using just SMBus commands.

10 comments:

  1. Hi! Do you know anything about 51F51 controller? It is single-chip solution for smart batteries. I found it in my Thinkpad T530 9-cell (94WH) battery. Google provide links to the AliExpress but there is no any Datasheets.

    ReplyDelete
    Replies
    1. No clue, sorry. It might be a later revision of this Renesas one but that's just a guess.

      Delete
    2. Thank for answer. Until wating for my FX2LP board: seems (http://ubrt.com.ua/main/built-in-program-modules/lgc-tools, in Russian, sorry) that 51F51 is a R2J240_51F51. So, R2J240 in another package (TSSOP38). Also, fiwmware LGC too.

      Viktor, could you please add info: where is pins 4 and 12 connected in your case? PCB elemetns and so on...

      Delete
    3. Good to know, thanks!
      Unfortunately I can't help you there either. The R2J240 pack I have is already back in service so I don't want to break it apart again and I haven't taken any detailed pictures of the controller board. The procedure I've mentioned in the post (though time consuming) could work. Step 1, measure all voltages Step 2, deduce different sides Step 3, try to find reset Step 4, keep resetting while pulling logic-level pins either high or low while running "watch -n 1 smbusb_sbsreport" and wait until all you get is ERROR scans, then do a scan to confirm that you're in boot rom (or that you've hung/fried the chip, if you're unlucky).

      Delete
  2. Hello,
    I have Thinkpad x201 and i bought a 6 cell battery from AliExpress.
    I left it for charge the battery, it charges but when it reaches 100% charge with ac connected for a while, gauge suddenly drops %0 and the battery light charges from solid green to flashing orange, battery voltage stays (12,5v~) what it should be at %100. I could use the full capacity of the battery while the orange battery light flashing.
    The seller will send a new one but i want to repair the defective battery. Do you have an idea?

    ReplyDelete
    Replies
    1. No clue, sorry. The cheap aftermarket packs are unlikely to use any of these chips.

      Delete
  3. Hello,
    Does shorting the pin12 to ground reset the circuit? I recharged my battery pack from dead to 11.5V(exernally), but it is not working. It says plugged in 0%, not charging. Before I recharged, the battery was not even showing up. But I am still not able to charge it. What is your advice? does flashing it after fixing crc reset it?

    ReplyDelete
    Replies
    1. It resets the microcontroller (ie. restarts the firmware). There's no simple way to "reset" as in clear the failure flag if it's been set which is why this project came to be.

      Reading the battery related posts from 2016 aug-sep could help get you started. Some experience with electronics and reverse engineering binary blobs is necessary.

      CRC fix is only necessary for modifying the static area. Failure flag is in the dynamic area. I can't offer any assistance beyond that. Good luck!

      Delete
  4. Thank you victor.
    I understand I have to setup a hardware to do this. Is there a way to access the battery using system smbus without using external hardware, with windows or linux? I am unable to setup the hardware on my own. I have a TI stellaris launchpad with me, but porting the code to it seems intimidating to me.

    ReplyDelete
    Replies
    1. Answered here: https://goo.gl/yLL1Dt
      FWIW there isn't really any hardware setup involved. It should just be plug and play if you have the required board. Though note that the windows binary release may not work with certain boards since it doesn't include this fix https://goo.gl/GJLNWC yet

      Delete