karosium / smbusb

USB SMBus Interface
GNU Lesser General Public License v2.1
146 stars 43 forks source link

adding support for /dev/i2c on linux? #19

Open 5ch4um1 opened 4 years ago

5ch4um1 commented 4 years ago

First of all: thank you so much for all that useful information! :)

I was wondering if somebody has already adapted the tools to work with /dev/i2c on linux? This is probably not a good idea, but messing with batteries is not a good idea in the first place i guess?

And apart from that, somewhere in a forum i saw a post suggesting that one could use a modified video cable to talk to i2c devices, and i was able to replicate some of the functionality of smbusb with i2c-tools and the vga port, including entering boot rom mode, checking the boot rom version (also 3.1 on my chip) and reading blocks with i2ctransfer. But before i try to write and brick the chip i thought it would be a good moment to ask some dumb questions... would it e.g. be possible to just edit/rewrite single blocks? (or actually 2 blocks if i understood that right?) or in other words, is it necessary to dump, erase and rewrite everything? the erase part is necessary as far as i understood? I tried to understand the code of the flashing process without too much success so far. if i get that right, a word write of 0x83DE to 0x12 would erase everything? and then it does block writes? and then, what does the SMBSendByte(0x16,CMD_EXECUTE_FLASH); do? is that just to exit the boot rom mode? sorry for all the stupid questions...

5ch4um1 commented 3 years ago

Well, i recently got one of those cheap 8 channel logic analyzers...turns out, they are based on the fx2...the i2c pins are not broken out, but that eeprom is a nice place to solder wires to: image so thanks to smbusb_bootstrap i finally managed to get dumps of the firmware and the eeprom and could compare them to the results of some scripts i had written some time ago, and i could fix some errors. I think i managed to dump both firmware and eeprom now via /dev/i2c `#!/bin/bash

max=18416 for ((i=16384;i<=max;))

do y=$(printf "%#.4x\n" $i) let "i+=32"

sudo i2cset -y 1 0x0b 0x09 $y w sleep 0.01 r=$(sudo i2ctransfer -y 1 w1@0x0b 0x0c r33) echo $r | cut -c6- sleep 0.01 done`

(edit: not sure what i smoked yesterday, but it took me way to long to realize that 20 actually means 0x20, aka 32...worked anyway, but i fixed this now and it reads the 32 bytes it should)

this for example should dump the content of the eeprom. The output format is obviously different from what your tools produce, but i guess when doing the writes with i2ctransfer we'll need the data like that anyway.
I think i'll try these days if i first can finally fix my battery using your tools and then maybe try to write to the chip with /dev/i2c. By the way, has anybody tried single block writes instead of writing the whole thing? iirc, the datasheet suggests that this should be possible? Oh, and for those who don't want to use the display data channel, but own a raspberry pi, this should work on a pi too.

karosium commented 3 years ago

Your description of the erase->write->exit process is correct. https://www.ti.com/lit/ug/sluu187/sluu187.pdf might help with commands.

Someone wrote tools for /dev/i2c here: https://github.com/noolex/lenovo_battery_repair

Multi interface support would be good to have but I won't be able to work on it any time soon unfortunately.

5ch4um1 commented 3 years ago

Ah, that's nice, that bat_hack script even does the math. :) I guess we can call this issue resolved then. Unfortunately my battery stopped talking to me, so i can't test right now. (thought about buying a chip on aliexpress to keep playing, this broken battery has had a huge educational value for me so far...) Another interesting project i stumbled upon these days was this: https://github.com/iam4722202468/ThinkpadBattery which is basically a smart battery emulator for arduino platforms. He simply uses an attiny85 to tell the laptop what it wants to hear. Tried this with an arduino nano clone, works like a charm, and also might be pretty practical for testing real batteries i guess. And last but not least, for those of you who are interested in the firmware, there is this guy from australia who wrote a ghidra plugin: https://github.com/pelrun/ghidra-cr816 which is still way above my capabilities, but i hope to make use of it one day. Anyway, thank you very much for you work, i have learned a thing or two from reading your code, and finally got a backup of both firmware and eeprom data.

mefistotelis commented 3 years ago

Responding more to the title of the issue than the actual discussion - it so happens that I made a tool which uses /dev/i2c. It actually uses 'smbus2' Python module, and that Python module opens the device and does ioctl calls on it.

The tool: https://github.com/o-gs/dji-firmware-tools#comm_sbs_bqctrlpy Usage example: https://www.youtube.com/watch?v=P5PNOO2GebY

5ch4um1 commented 3 years ago

that looks like a lot of work, really nice! i like that sbs_read_firmware_version_bq_sealed function! :)