Hacking the Kindle

Published: 2017 October 13

Index

I've just bought a Kindle 3. It's a lovely device, light, nicely shaped, a superb screen, and I think I had it two hours before I jailbroke it so I could run my own software on it.

This page is a collection of some of the stuff I've done with it, and the things I've learned while doing it, and some of the crude but useful tools I made to do it with.

A Javascript shell for the Kindle

This here is a basic Javascript interactive shell that I knocked up in a week or so. It allows you to enter Javascript commands using the Kindle's keypad and screen via a crude but serviceable terminal emulator.

The interpreter used is Rhino, which is written in Java. Unfortunately the Kindle's security model means we don't get any nice stuff like the Rhino Javascript-to-Java JIT, but do still get Rhino's excellent Java integration: it's possible to directly access any Java class from Rhino as if it were Javascript. As such this makes KJS a great way to explore the Kindle's APIs.

There's also a very basic shell which allows external commands to be loaded and run (all in Javascript, of course). This doesn't do much but might be useful in the feature. (Got any handy scripts you think should be distributed with KJS? Let me know!)

Warning: The Kindle's not actually robust enough to run arbitrary code, and it's very easy to crash your device by doing the wrong thing --- e.g. while (true); will do it. (Can't break out of infinite loops.) So be careful, and when you device crashes and loses all your data, don't say I didn't warn you.

If you want to hack it, get the source code. Some things you might want to pull out of it include:

  • Retroweaver integration, allowing Java 1.5 language features (generics! autoboxing! foreach loops!) on the Kindle's 1.4 JVM.
  • com.cowlark.eventbus, a port of GWT's excellent event bus system, and a wrapper around the Kindle lifecycle APIs so that we don't need to worry about what thread they're calling into our application from.
  • com.cowlark.kterm, a slightly-complete VT52 terminal emulator with crude but serviceable custom inputmethods allowing actual code to be written in it... although with four shift keys it does feel a bit like a ZX Spectrum.

Getting started with Kindle development

Jailbreaking the Kindle

The first port of call should be here:

This is the only jailbreak you need to run applications.

Important notes:

  • This will not let you decrypt AZW ebooks. The DRM Amazon use on their ebooks has got absolutely nothing to do with jailbreaking your device.
  • This will not let you access the 3G network. There's a completely different mechanism that authorises applications to use Whispernet, and this is not it. If you were hoping to be able to use this to get free 3G internet access to you PC via your Kindle, forget it.

The only thing the jailbreak will let you do is to run your own programs on the device (including ones that completely trash it and turn it into a paperweight; You Have Been Warned).

Development tools

Kindle applications are written in Java. It's Personal Basis Profile 1.1 and Java 1.4, both of which are ancient and horrible. It's been heavily customised and there's a set of extra proprietary libraries that give access to things like the e-ink screen and the Kindle's native user interface.

Of course, in order to be able to compile code against the Kindle libraries, you need to get a copy: the easiest way to do that is to pull it off the Kindle. To do this, use the following update. When installed, it will copy the entire contents of the Kindle's library directory into /lib where you can get at it. The only jar you need is Kindlet-1.2.jar but we copy the rest anyway in case something interesting is there.

Once you have this, add it to your build classpath.

Signing applications

The Kindle will only run signed applications, and wants to be able to verify the signatures before it will run anything. This means that:

  • You must have a set of private developer keys to sign your applications with.
  • Anyone who wants to run your applications must install your public developer keys before your applications will run.

So, you now need to generate a set of developer keys.

Once you have a developer.keystore, put it somewhere safe and don't lost it. Then install the appropriate public key update package on your Kindle.

Skipping ahead

Right now you should be in a position to be able to build, install, and run applications. However, to save time here's something I prepared earlier:

The above rather meaty package contains everything you need to get started. Unzip, run the ./makekindlet script, and you should end up with a HelloWorld.azw2 ready to deploy onto your Kindle. There might even be some working Eclipse project files.

(The script does assume that your developer private keys and Kindlet-1.2.jar are both in the $HOME/.kindle directory.)

You also get the following extremely handy features:

  • Java 1.4 is horrible, so I've bolted on the totally excellent RetroWeaver. This tool allows you to use Java 1.5 code on a older version of the JVM. This means we get to use things like generics, autoboxing, foreach loops, better reflection, and in general all the stuff that makes Java an actually usable language.
  • I've wrapped the Kindlet lifecycle API in the excellent event bus mechanism ported from GWT. The reason for this is to insulate you from the fact that said API is multithreaded. This isn't Amazon's fault, as they're just copying what Midlets did, but it's an excruciatingly horrible thing to have to work with. (You cannot, for example, make UI calls from one of the lifecycle callbacks, because you're not running in the UI thread.) Now they're just event sources. Plus, the event bus mechanism is extremely useful to have around anyway.

It might also be possible to bolt on ProGuard. This would shrink the resulting .azw2 file by detecting unused code --- the Retroweaver support libraries in particular are pretty large. However, I don't reckon it's really worth the hassle.

Gotchas

And now some warnings.

There's a reason Amazon don't officially allow homebrew on the Kindle, and I don't think it's business related. The Kindle is a very fragile device. It's incredibly easy to crash; there's no isolation between user applications and the system user interface.

This means:

  • Whenever you load a class containing static members, the memory used for those members will never be freed. Ever.
  • There is no way to forcibly terminate an application. Accidentally get an infinite loop? That thread will run forever.
  • If you leave a thread running on exit, your Kindle will crash.

This means that if you're writing code and testing it on your Kindle, you will see it crash and reboot a lot. So far I haven't lost any data. You may not be so lucky.

In particular, if you run a lot of third party applications, I think you're very likely to see slow bit rot, where the device will slowly destabilise over time until it crashes and reboots, at which point it goes back to normal and then starts to slowly destabilise over time, etc. Remember that the Kindle's normal lifecycle is never to reboot, ever. This means that slow memory leaks over time that you would never notice on a desktop will slowly build up.

So, to summarise: I think the reason Amazon don't officially allow homebrew on the Kindle is because they don't want the blame when people start complaining that their Kindles are unreliable. By requiring all third-party applications to be vetted by them does at least allow them to run some basic checks to see whether the applications are fit for purpose or not.

Thanks

Most of this work's not mine; I'm merely collating and glueing together functionality other people have done. In particular, the hard work in producing the jailbreaks, signing tools etc came from the folks on the excellent Kindle Developer's Corner forum on mobileread.com.

Another surprisingly good source for technical information is the official Amazon development forum... although I'd recommend against posting there.