FINALLY!!!
After almost a year trying now and then I finally was able to make quite some progress on the Roomba.
The following, lengthy, paragraph will be a description of how I managed to come to the current state. Feel free to skip it if you're not interested in the technical details of dumping the firmware.
Some time after the last post I got a U11 from a Russian guy. It was (basically) identical to mine, so it was not U11 preventing it from booting.
So it was clear that I needed the bootloader code to understand why it was resetting. Unfortunately, the main STM32F1 microcontroller of the roomba is, of course, read-protected. I did not even dare to ask iRobot whether they could help me out with a binary image of it. Thus started the journey to circumvent the read-out protection of the STM32F103ZET6 (U6). After trying some software-only attacks unsuccessfully, I found the paper "Shaping the Glitch: Optimizing Voltage Fault Injection Attacks" that indicated a power glitching attach against the STM32F1 series might be feasible. I tried to implement it using different techniques over the next month, but my CPU-based attempts all failed, even using the signal generator mentioned in the paper.
But finally, last week I had the big breakthrough: I finally decided to dust off my rusty VHDL skills and implement the necessary bootloader communication and glitching logic inside a FPGA, using my old Altera DE1 board. I used a simple hardware approach for the glitch circuit: Just feeding power to the (removed from the Roomba) STM via a 15 Ohm resistor and shorting that to ground when glitching using a IRLR2905 FET. Boy was I happy after the bootloader replied 0x79 instead of 0x1F for the first time, after fiddling around with different glitch positions and lengths using the switches on the DE1 for a while! This showed the glitch was actually working. After implementing the rest of the read command in the FPGA it actually returned the first 256 bytes of the read-protected memory!
A little while later I had extracted the full 512 kB of the firmware and could finally start debugging my boot problem.
To do so I decided not to reflash the orignal STM (to remove the debugging lock), but instead use a new chip, so I would be able to re-read the original one, if necessary. What should I say? After soldering in the new processor and flashing it with the extracted firmware the Roomba just came to life!
No further debugging required, it just booted, charged and would start a cleaning cycle.
Of course I also wanted to use the App to set the robot up. Sadly, this did only work partially. It would see the Robot and try to provision it, but then cancel saying that there's a "bad certificate".
This then led me to the discovery that the firmware actually uses the "Unique device ID" of the STM32 microcontroller to generate the "Bootloader ID". This BLID is also included in the SSL certificates stored in the robot and presented to the app. As I now have a different STM chip inside the Roomba, of course the Unique ID has changed (and is not changeable), which in turn changed the bootloader ID. Because it no longer matches what the certificates say, connecting fails.
So this is where I am currently working on. I could patch the firmware to return the Unique ID of the original controller (which I also read from it), but the firmware image is checksummed on boot, so I would need to understand the algorithm and fix the checksum. Also, this would break with the next firmware update, as it seems the calculation is actually done in the main firmware part and not the bootloader part itself. The other way would be to exchange the certificates sent against new self-signed ones, as I currently think the App is not really checking against the same root cert, but just checks the issuer string and that it is valid against the root cert presented by the robot. I have not yet checked whether the firmware containing the certificates is also checked for changes.
Kind regards,
Stefan