Motorcycle Hacking

In 2017 I got a brand-new motorcycle, and it didn’t take long for me to start fiddling with it. As European laws are quite strict regarding modifications, I wanted to get data out of the ECU to an external embedded system to do fun things with it. This post is a technical description of my spelunking.

Talking to the ECU

First I wanted to be able to communicate with the ECU. This would allow me to log data to study how the bike behaves, and potentially dump the firmware. After some research, I found out my ECU uses a K-line protocol, possibly ISO 9141 or ISO 14230. I quickly found out some other people had already managed to communicate with ECUs like mine by reversing some accessories that are plugged to the diagnostics port. There are many gear indicators that are plug-and-play and can guess which gear is currently engaged by talking to the ECU. There was a person that tapped into the port to look at the messages the gear indicator was exchanging with the ECU. It turns out it may very well be true, that it doesn’t matter which crazy idea you have, somebody else probably already tried to do it. As expected, the interface operated at 10400 bauds (from the standard), but apparently the message content didn’t match the standards:

Initialization:

Pull line low for 70ms
Pull line high for 120ms
> FE 04 FF FF
Wait 200ms
> 72 05 00 F0 99
< 02 04 00 FA

Requests/responses:

> 72 07 72 11 00 14 F0
< 02 1A 72 11 00 00 00 18 00 62 57 EF 10 91 63 FF FF 77 00 00 00 80 63 1A 51 DA

> 72 07 72 D1 00 06 3E
< 02 0C 72 D1 00 03 00 00 00 00 00 AC

I unfortunately don’t have access to the ISO-14230-4 specification, so even if it was compliant, I wouldn’t be able to tell. The decoding would need to start from guesses. The collaborative work on these forums from more experienced people allowed most of the message to be decoded. One of the posters did a great job on building a circuit to communicate with the K-Line interface through a simple USB<->RS232 adapter. The schematics for the circuit seem to come from a russian forum, and had a few limitations, which I figured out only after building an equivalent circuit. The communication initialization requires a cycle of pulling down/up the K-line for specific time intervals, which isn’t simple to do with the RX/TX pins from the RS232 adapter (and not even possible for most RS232 chips). I added a third optocoupler that I can control using the RS232 DTR pin, allowing me to transmit the K-Line initialization sequence without any headaches. With all that, I built a first prototype for the circuit:

It’s just a prototype, I promise.

It’s just a prototype, I promise.

This circuit allowed me to use a simple Python program to communicate with the ECU. With that, I Immediately found a problem: the circuit was too sensitive to EM noise, and the messages would get corrupt all the time, forcing the program to reinitialize the connection. It was not easy for me to find the source of the problem, and required some time with a logic analizer to point out what was wrong. I found out the culprit was the 4N25 optocoupler, which isn’t the best choice when building a circuit that may be exposed to a lot of EM noise. Well, the culprit was me for choosing the wrong component, but you get it. I changed them for H11L1 ICs, as the schmitt-trigger circuit definitely more adapted for that. Circuit changed, problem solved. This is the circuit for the version I’m using:

I know it’s ugly. But it was made with love.

I know it’s ugly. But it was made with love.

Parsing the messages

It’s a guessing game: change it until you get to something that makes sense. Some things are absolutely obvious, like RPM and speed, but others not so much. Some members managed to decode most of the responses sent to the gear indicator:

   SRC,  LEN,  TGT, TABL, STRT,  LEN, CHK
> 0x72, 0x07, 0x72, 0xD1, 0x00, 0x05, 0x3F
   SRC,  LEN,  TGT, TABL, STRT, NEUT, ????, ????, ????,  ENG,  CHK
< 0x02, 0x0B, 0x72, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xAF

   SRC,  LEN,  TGT, TABL, STRT,  LEN, CHK
> 0x72, 0x07, 0x72, 0x11, 0x00, 0x0E, 0xF6
   SRC,  LEN,  TGT, TABL, STRT, RPMH, RPML, TPSV, TPS%, ECTV, ECTC, IATV, IATC, MAPV, MAPP, ????, ????, BATV,  SPD,  CHK
< 0x02, 0x14, 0x72, 0x11, 0x00, 0x05, 0x5D, 0x19, 0x00, 0x2A, 0x7B, 0xAF, 0x36, 0x68, 0x45, 0xFF, 0xFF, 0x8B, 0x14, 0x18

It was also obvious that by changing the table address and read length, I could read more memory addresses. By trying to read many different bikes, a community table was built with some of the differences. Another member found documentation for an aftermarket display showing that probably the values after the speed were ignition advance and injection time. These two aren’t trivial to make sense of, and some members came up with different theories. I made some experiments myself and chose the method that gave the outputs that seem closer to reality.

It works fine, but it needs validation. With all that in hand, I decided to implement a custom display for my bike, displaying the data I was reading.

Display Box

I decided to attach a screen to the handlebars to display the data I’m interested in. For that, I came up with a few requirements for a first version:

  • Screen should be easily detachable: This way I can remove it to protect it from the elements (sun/rain). If you never had to implement a weatherproof display that looks nice, I can tell you: there’s a painful learning curve (and I didn’t manage yet).
  • Fast initialization: Screen should be available within seconds after turning the key.
  • Non-destructive installation: Having it on the bike must not require the removal/modification of any original part.

With all that in mind, I came up with a project:

  • Raspberry Pi for the graphics rendering power plus any need I may have on peripherals (GPS, IMU, Bluetooth, etc).
  • Hyperpixel 4.0 for the screen (a big cheap screen with good resolution).
  • Custom 3D printed case/support.

In the end, I got to something like this:

This way the display is attached to a Raspberry Pi and both can be removed easily (as a single unit), while the power supply and the K-Line<->RS232 circuit are installed permanently.

I modeled and printed the parts I needed for the installation, and managed to get all to fit properly. I used Fusion 360 for the modeling, but I still want to make some improvements before publishing them.

Software

I decided to separate the display from the ECU communication software. This way I have modular components that I can develop/test independently.

ECU Communication Software

As I was experimenting from the beginning using Python, I ended up writing the whole thing using Python. The amount of processing this application has to do is minimal, and it spends most of the execution time sleeping. I also added logging capabilities to it, so I can play with the data later. It is a very simple application with serial communication code and a few classes to abstract things.

Display Software

To allow fast initialization I decided to write an application that renders directly to the Raspberry’s framebuffer. This way I don’t need to start the whole X11 with a desktop environment before launching the application. I wrote the display software in C++ to make the most of the hardware, and used SDL2 to draw to the framebuffer directly through the videocore4 hardware using OpenGL ES 2.0. It takes around 7 seconds to boot, but that can be improved by creating a custom installation with Yocto or Buildroot.

For development I obviously wanted to validate everything on my computer before trying anything on the Raspberry. To minimize headaches from switching between OpenGL and OpenGL ES, I used ANGLE to have an OpenGL ES 2.0 interface on my desktop. This way my whole code would be compliant with OpenGL ES 2.0 from the very beginning.

The application is very simple, and should work very well as a basic C++ / OpenGL / text rendering / network socket communication template. I made the base for it an open-source project, and called it Rockette.

Completed installation

A funny thing is that the OEM speedometer seems to disagree with the ECU speed value. I compared them to GPS speed measurements and the ECU speed matches almost perfectly with the GPS speed.

The whole system worked very well, but I’m still not sure the parsing of all elements is correct. To be sure, I would need access to the standards or to reverse engineer the ECU firmware, which I have not done yet.

Getting the binaries

I also have the original (unrestricted) ECU, so if I found a way to dump the firmware from both the restricted and understricted ECUs, I’d be able to compare them. But, how could I dump the firmware? I didn’t even need to figure that out, as I could find dumps for both the restricted and unrestricted ECUs on the internet. Thanks internet.

Reverse engineering

With the binaries in hand, I needed to know which instruction set they used, so I could reverse them. My ECUs seem to be plastic-molded and resin-filled (which is quite common for these things), and there doesn’t seem to be a non-destructive way to get them open to peek at the microcontroller. After hours searching the internet, I managed to find a random guy on a random forum that cracked open an ECU just like mine and posted photos of the board to get details on how to flash it. I didn’t have access to the full-resolution images, just the thumbnails, and I felt like this.

Fortunately, on his last post on this thread, he posted what I needed: The MCU had “Freescale 2M27V” written on it. The microcontroller is an MPC5604B! This microcontroller uses the e200z0 PowerPC instruction set with VLE support, but I can’t find a way to get a valid disassembler for it. Ghidra and other tools don’t seem to support this architecture, so please let me know if you know what I’m missing.

Injection Maps

Even without being able to reverse the binary, I was be able to extract the injection maps. I found very instructive tutorials on the internet on how to use a tool called WinOLS, and not only managed to extract many different injection maps, but also to compare the maps from the restricted and non-restricted binaries.

Comparing the ECU maps between the European A2 restricted and unrestricted versions

Matching data with maps

The parsing still needs validation for some values. As I collect logs I’ll compare the logged data with the maps I found.

Similar projects

https://github.com/atoid/Dash https://github.com/atoid/DashBle https://gonzos.net/projects/ctx-obd/ https://bitbucket.org/enly1/hondagearindicator/src/master/

Posted on

The Macbook strikes back - S01E02

After almost succeeding at repairing my mid-2012 Macbook Pro, I was back to square one. Not square zero as now at least I had some non-zero voltages on the board. The magsafe connector doesn’t turn on at all. My second suspect was the ISL6259AHRTZ that should be responsible for controlling the charger circuit and telling the MAX9940 to turn on. I found out the ISL6259 talks to the SMC through an I2C interface, so I plugged my logic analyser to the CLK and SDA pins to try to find out if they were talking. Turns out they were not, and the CLK line didn’t look like CLK at all. Time to replace the ISL.

ISL6259 after replacement, before cleanup. The gunk is just flux that dried out.

The replacement was long and tiring, as it has tiny connections and tiny components all around it. At the first attempt, some lines that should not be shorted were shorted, so I had to start over, and ended up moving a few resistors/capacitors in the process. Took the opportunity to measure the resistors out of the circuit, and there was a resistor that was supposed to be 20Ω but was ~130Ω. Replaced this guy, powered it up and, nothing. Plugged my logic analyser to the I2C lines again and, ohh! Now the CLK line looks like a CLK signal, and I can even see what these guys are chatting about at the SDA line. What if I… tried to unplug and plug the magsafe a few times? Bingo! Sometimes it lights up green, then red after a second, and sometimes it doesn’t light up at all. Progress again, I guess? I also noticed that when I measure the SMC reset line with my multimeter, the magsafe goes green again for a few seconds. So I’d guess it’s the SMC that’s saying there’s something wrong to the magsafe… or the magsafe turns it red as it gets no answer? I don’t know yet… but the next step is to try to peek at the 1-Wire circuit. I’ll also buy some MAX9940 just in case.

Apparently these intermittent problems could be capacitors that are dying, so I’ll also check the capacitors for shorts. I think I’ll even replace the capacitors around these power circuits.

Posted on

My dead Macbook - S01E01

On a sad day, not so long ago, my long time companion stopped working. It’s a mid-2012 Macbook Pro, the first “retina” model. I got it at night to watch Netflix after it spent the whole day charging, and I noticed it wasn’t charging anymore. The charger connector would not light up, and it still worked from the battery, but the battery wasn’t charging, and I knew what this meant: my laptop would stop working as soon as the battery got empty.

I have a degree in CS and have a pretty good understanding of electronics and digital systems, but I’m by no means an electronics engineer. I have been working with embedded systems more and more for the last few years, and as there’s also a lot of material on the internet, I think I’ll give it a shot at repairing my old friend. This will for sure become a series of posts on how I failed, or hopefully succeeded, at bringing my laptop back to life.

Getting it open was the first challenge. I had already opened it before, as I cleaned it a few times and replaced the wireless card to be able to unlock the computer using the Apple Watch (this model isn’t supposed to support that, unless you change this card). At that time, I bought cheap pentalobe screwdrivers in China, and well, they were cheap, but were not the right size and kinda damaged the screws when I used it. I had also tried to buy the “more expensive” pentalobe screwdrivers from China, and had similar results. I think it’s a hit and miss thing and if you are lucky you get good ones, but I was unlucky with my chinese pentalobe screwdrivers more than once, so I didn’t want to play this game again. I wanted to solve this problem once for all and bought the Mako Precision Bit Set from iFixit and totally recommend it, it’s the nicest screwdriver kit I’ve ever had, so it was a breeze to open/disassemble the Macbook, especially with the iFixit teardown guide.

I found out my board model is 820-3332A and managed to find the electrical schematics for the motherboard without much problem (as it’s old I guess?), and even found out there’s a fantastic tool called OpenBoardView to open .brd schematics and help navigating through components and lines. That, and a multimeter, was all I needed to get started with the troubleshooting. So I tried to find out how the charging system works and what could have gone wrong. A few Louis Rossmann videos later and I started measuring the tensions at multiple points in the circuit, and they were all zero. Deady Mc Deadface. Looked for short-circuited lines everywhere, and couldn’t find any.

After some research, I found out that Apple’s Magsafe charger is much more clever than I anticipated, and the Macbook talks to it through a 1-Wire interface, and has even some clever sensing features that shut it completely off in a safe way if things go weird, and they were weird. There is a chip that protects the 1-Wire interface from frying important things (MAX9940) but it was not even being powered, so I discarded it for now. The charging/battery management is done by an ISL6259AHRTZ chip, so I ordered some as it could very well be the problem. There is also an inrush limiter circuit, that uses two P-channel mosfet in one die (IRF9395TRPBF) and could be causing the problem. Ordered some of these too. Got pretty confident that this guy was faulty, as it would explain why I was getting the 0V. As these guys are SMD components, I needed tools. I got a TS-80 soldering iron because I found it super nice, and there’s even an open-source firmware for it! Also got a generic 858D hot air station. Also bought kits of SMD resistors and capacitors in different sizes (402 and 603), just in case I needed some. Ah and some nice no-clean soldering flux, as flux is absolutely necessary when working with SMDs. Was hesitant and didn’t buy any soldering paste.

IRF9395TRPBF is the big rectangular greyish thing in the center.

Tools and components in hand, I started heating things. The IRF9395TRPBF was replaced, powered the magsafe and… nothing. But wait! plugged again… nothing. Sigh. Oh… plugged again, and… green light! Connected the fans and… fans spinning! Good news! Things seem to be working again… I guess? Not sure why it didn’t turn green the first time I plugged… oh well, it works! Put everything back together and voila, laptop back to life!

It’s alive!

Some keyboard keys were not responding properly, but that shouldn’t be hard to address. Success! Oh, no no no. Of course it could not be that easy. It started behaving badly. Fans spinning fast out of the blue, can’t read the battery percentage… I think it is the SMC misbehaving. And then suddenly, it turns off and the magsafe connector won’t turn on again. Sigh.

The SMC (system management controller) is a chip responsible for an unknown amount of important things in some computers. I know that for Macbooks it’s responsible for things like keyboard backlight, ambient light sensing, thermal management, some hard drive encryption tasks, power management, so, yeah, pretty important things. It’s a very special kind of chip as well, as it has software inside it. And it’s Apple software. So you guessed right, it’s not easy to find a replacement for this guy. Not only it’s a very hard to solder 157 contact BGA chip, but there are no public datasheets for this chip in specific (LM4FSXAH5BB), and even if you got one, you need to be sure it has the right firmware for your specific laptop flashed into it. Most repair shops take them off “donor boards” (dead boards which this chip is still functional), which have to be precisely the same model, and as they are dead boards you never know if the SMC is bad, so you replace and hope for the best. There’s a very nice presentation from Alex Ionescu on how important this chip is, how to flash it (if your computer still works), and some nice anecdotes. Tricky… now I really hope my SMC didn’t go bad. Also very interesting, I’d really enjoy to make some SMC tools to help other people.

Took the board out again, checked the voltages… yep! Now I have voltages different than zero. Well, that’s an adventure for another day, but, progress… I guess?

Posted on

Blogging like it's 2004

Finally, after many years, got a blog for myself again. For real, it’s a few. I’ve decided to create four different blogs, for different topics:

  • Development: As a software developer, I believe I have many things to share. If they are good or not, well, you tell me!
  • Making things: I love making things. This is a special space to me where I’ll write about electronics, 3D modeling, 3D printing and some development, but mostly linked to stuff I’m making.
  • Hacking: I also love breaking things. Initially I thought about putting “Hacking” and “Making” together, but it felt weird to write about “PowerPC VLE instructions” and “3D Modeling” in the same blog, so here we are.
  • Thoughts: Here I’ll share anything that doesn’t fit in the other categories. It’s more of an unstructured space where I can write about anything I feel like without worrying about mixing up topics.

These will probably grow slowly, but I’m excited about the journey.

Posted on