It seems I'm bound to hacking various ARM-based devices these days. I've been using a kindly donated Kindle 3 with a broken screen for a few months now as kind of sandbox machine. It's always nice to have a few systems on-line one can log into from various unfashionable corners of the Internet for bouncing connections or for running a service on a whim. A Debian-running Kindle is especially nice for an always-on machine, since it consumes very little power.
So far I've been running the Kindle with a stock system, only jailbroken and with the usbnet hack installed. I installed a basic, 1.5 GB Debian chroot into the FAT partition on Kindle's flash and had a ssh daemon running on the wireless LAN interface. While it's still quite useful, that's only a part of the 4 GB of built-in storage and the daemons running in the stock system consume a lot of RAM. Plus, they sometimes mess with the hardware in ways I don't like. For instance, the wireless LAN connection usually drops when USB power goes away. Obviously the way to go was to run Debian natively.
Before I could install Debian onto the flash drive directly, I had to find out how the Kindle actually boots and what facilities are there to recover in case something goes wrong.
As seems to be the standard on Linux-running ARMs, the first visible thing that happens is U-boot. It's stored in boot flash memory that is mapped into CPU's address space (this flash is different from the built-in MMC drive that the operating system uses).
If you press a key on the serial console at the Hit any key to stop autoboot prompt, you get a simple command line. It allows you to inspect memory, load code or data via the serial port into RAM or flash and boot a kernel that is present somewhere in the address space. There seem to also be some facility for tftp network booting, but without a wired Ethernet adapter on board it appears useless. Although U-boot can also include functionality for accessing the MMC drive, version on my Kindle has that disabled.
If you don't want to mess with the boot flash (I don't want to for now), the only thing that you can do from U-boot is to boot the Linux kernel. Kernel and an initrd image are also stored in the boot flash and hence directly accessible in the ARM address space.
The initrd image contains some recovery utilities that can be accessed by pressing Enter at the Press [ENTER] for recovery menu... prompt. Since these run directly from the initrd, they work even if the MMC drive is completely corrupted. The most useful is option 3 from the recovery menu. It exports the MMC drive as an USB mass storage device, which can then be used to setup the root filesystem from another computer (with friendly still alive... messages periodically being sent to the serial line).
Menu ==== 3. Load MMC0 over USB storage 4. Erase MMC0 I. Initialize Partition Table (fdisk) and format FAT O. Format and overwrite FAT partition E. Export FAT partition U. Update using update*.bin file on FAT partition M. Update using update*.bin file on FAT partition of second MMC port D. dmesg / kernel printk ring buffer. Q. quit
Oh, and option 3 requires a password, which is the well-known fiona + four (not three as for the root password) hex digits of the MD5 digest of the serial number.
If you don't enter the recovery menu, the code in initrd mounts the root filesystem and executes /sbin/init. From there on things proceed as usual in a normal Linux system. Kernel parameters stored in U-boot set the root filesystem as the first partition on the built-in MMC drive.
This boot process seems to be completely compatible with an armel Debian Squeeze install. One snag I did encounter is that the root partition needs to have at least /dev/console and /dev/null special files. Other device files are created at boot time by udev, but without these two, I get a tried-to-kill-init kernel panic at boot. Also, it helps to double-check /etc/fstab and /etc/inittab, since debootstrap doesn't set these up for you. Root filesystem is /dev/mmcblk0p1. If you want to be able to log-in from the serial console, a line like this works in the inittab:
mxc0:2345:respawn:/sbin/getty -L 115200 ttymxc0
The original Kindle comes with a MBR-style partition table on the MMC drive (here it's called /dev/sdd since I was inspecting it from another computer - on Kindle it's /dev/mmcblk0):
Disk /dev/sdd: 4001 MB, 4001366016 bytes 4 heads, 16 sectors/track, 122112 cylinders, total 7815168 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Device Boot Start End Blocks Id System /dev/sdd1 * 7688 1338943 665628 83 Linux /dev/sdd2 1338944 1388095 24576 83 Linux /dev/sdd3 1388096 1404479 8192 83 Linux /dev/sdd4 1404480 7815167 3205344 b W95 FAT32
sdd1 is the root partition for the stock Kindle OS with an ext3 filesystem. sdd2 contains another ext3 filesystem with some kind of configuration and log storage. sdd3 is empty and was all zeros on this Kindle. sdd4 contains the storage that is visible when you attach an un-modified Kindle to a computer. It contains another MBR partition table with a single, FAT32-formatted partition.
I removed all of these and just created a single ext3 partition over the complete drive. At boot this causes some scary messages from the initrd code which seems to attempt some sanity checks on the partition table and checks for possible system updates in the FAT32 partition. Apparently it tries to correct the situation, but luckily gives up without modifying the partition table before starting Debian's init process.
While I now have a basic Debian installation running directly on the Kindle, there are still things missing. For instance, I still have to get wireless LAN to work again and there are some oddities with power management which I hope to cover in another one of these posts. All in all, Kindle turned out to be much more hacker-friendly than the Chromebook, which is surprising considering that in contrast to the evil Kindle the former has been advertised as being developer friendly.