In my previous post, I described running Arch on an OpenWRT router. Today, I’ll be taking it a step further and running Arch and a full LXDE installation natively on an Amazon Kindle, which can be interacted with directly using the touch screen. This is possible thanks to the Kindle’s operating system being Linux!

You can see the end result in action here. Apologies for the shaky video - it was shot using my phone and no tripod.

If you’re wanting to follow along, make sure you’ve rooted your Kindle beforehand. This is essential – without it, it’s impossible to run custom scripts or binaries.

I’m testing this on an 8th generation Kindle (KT3) – it should, however, work for all recent Kindles given you’ve enough storage and are rooted. You also need to set up USBnetwork for SSH access and optionally KUAL if you want a simple way of launching the chroot.

First things first: We need to set up a filesystem and extract an Arch installation into it, which we can later chroot into. The filesystem will be a file which will be mounted as a loop device. The reason why we’re not extracting the Arch installation directly into a directory on the Kindle is because the Kindle’s storage filesystem is FAT32. FAT32 doesn’t support required features such as symbolic links, which would break the Arch installation. Please note that this also means that your chroot filesystem can be 4 gigabytes large, at maximum. This can be worked around by mounting the real root inside the chroot filesystem, which it’s still a hacky way to go about it. But I digress.

First, figure out how large your filesystem actually can be. SSH into your Kindle and see how much free space you have:

$ ssh root@192.168.15.244 kindle# df -k /mnt/base-us Filesystem 1K-blocks Used Available Use% Mounted on /dev/loop/0 3188640 361856 2826784 11% /mnt/base-us

Seems like we have around 2800000K (around 2.8G) of space available. Let’s make our filesystem 2.6G – it’s enough to host our root filesystem and some extra applications, such as LXDE. Note that I’ll be running the following commands on my PC and transferring the filesystem over later. You can also do all of this on the Kindle, but it’s simply easier and faster this way.

Let’s create a blank file of the wanted size. I’m using dd , but you can also use fallocate for this:

$ dd if = /dev/zero of = arch.img bs = 1024 count = 2600000 2600000+0 records in 2600000+0 records out 2662400000 bytes (2.7 GB, 2.5 GiB) copied, 6.92058 s, 385 MB/s

Let’s create our filesystem on it. Since we’re doing this on the PC, we need make it 32bit and disable the metadata_csum and huge_file options on the filesystem, as the Kindle’s ext4 kernel doesn’t support them.

$ mkfs.ext4 -O ^64bit,^metadata_csum,^huge_file arch.img mke2fs 1.45.0 (6-Mar-2019) Discarding device blocks: done Creating filesystem with 650000 4k blocks and 162560 inodes Filesystem UUID: a4e72620-368a-44b4-81bb-9e66b2903523 Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912 Allocating group tables: done Writing inode tables: done Creating journal (16384 blocks): done Writing superblocks and filesystem accounting information: done

This is optional, but I’ll also disable periodic filesystem checks on it:

$ tune2fs -c 0 -i 0 arch.img tune2fs 1.45.0 (6-Mar-2019) Setting maximal mount count to -1 Setting interval between checks to 0 seconds

Next it’s time to mount the filesystem:

$ mkdir rootfs $ sudo mount -o loop arch.img rootfs/

The Kindle I’m using has a Cortex-A9-based processor, so let’s download the ARMv7 version of Arch Linux ARM from here. You can download it and extract then, or simply download and extract at the same time:

$ curl -L http://os.archlinuxarm.org/os/ArchLinuxARM-armv7-latest.tar.gz | sudo tar xz -C rootfs/

sudo is required to extract as it sets up a lot of files with root permissions. You can ignore the errors about SCHILY.fflags . Verify that the files extracted successfully with ls -l rootfs/ .

Let’s prepare our Kindle for the filesystem. I opted for hosting the filesystem in extensions/karch as I want to use KUAL for easy launching:

$ ssh root@192.168.15.244 kindle# mkdir -p /mnt/base-us/extensions/karch

While we’re here, it’s also a good idea to stop the power daemon to prevent the Kindle from going into sleep mode while transferring the filesystem and interrupting our transfer:

kindle# stop powerd powerd stop/waiting

Let’s transfer our filesystem:

kindle# exit Connection to 192.168.15.244 closed. $ scp arch.img root@192.168.15.244:/mnt/base-us/extensions/karch/

This might take quite a bit of time, depending on your connection.

Once it’s done, let’s SSH in once again and set up our mountpoint:

$ ssh root@192.168.15.244 kindle# cd /mnt/base-us/extensions/karch/ kindle# mkdir system

I decided to set up my own loop device, so I can have it named, but you can ignore this and opt to use /dev/loop/12 or similar instead. Just make sure it’s already not in use with mount .

Setting up a loop point and mounting the filesystem:

kindle# mknod -m0660 /dev/loop/karch b 7 250 kindle# mount -o loop = /dev/loop/karch -t ext4 arch.img system/

We should also mount some system directories into it:

kindle# mount -o bind /dev system/dev kindle# mount -o bind /dev/pts system/dev/pts kindle# mount -o bind /proc system/proc kindle# mount -o bind /sys system/sys kindle# mount -o bind /tmp system/tmp kindle# cp /etc/hosts system/etc/

It’s time to chroot into our new system and set it up for LXDE. You can also use this opportunity to set up whatever applications you need, such as an onscreen keyboard:

kindle# chroot system/ /bin/bash chroot# echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen chroot# locale-gen chroot# rm /etc/resolv.conf chroot# echo 'nameserver 8.8.8.8' > /etc/resolv.conf chroot# pacman-key --init # this will take a while chroot# pacman-key --populate chroot# pacman -Syu --noconfirm chroot# pacman -S lxde xorg-server-xephyr --noconfirm

We use Xephyr because it’s the easiest way to get our LXDE session up and running. Since the Kindle uses X11 natively, we can try using that. It’s possible to stop the native window manager using stop lab126_gui outside the chroot, but then the Kindle will stop updating the screen with new data, leaving it blank – forcing you to use something like eips to refresh the screen. The X server still works, however, and you can confirm this by using something like x11vnc after running your own WM in it. Xephyr spawns a new X server inside the preexisting X server, which is not as efficient but a lot easier.

We can however stop everything else related to the native GUI, as we need the extra memory and we can’t use it while LXDE is running anyways:

chroot# exit kindle# SERVICES = "framework pillow webreader kb contentpackd" kindle# for service in ${ SERVICES } ; do stop ${ service } ; done

While we’re here, we need to get the screen size for later:

kindle# eips -i | grep 'xres:' | awk '{print $2"x"$4}' 600x800

Let’s chroot back into the system and see if we can get LXDE to run. Be sure to replace the screen size parameter if needed:

kindle# chroot system/ /bin/bash chroot# export DISPLAY = :0 chroot# Xephyr :1 -title "L:A_N:application_ID:xephyr" -screen 600x800 -cc 4 -nocursor & chroot# export DISPLAY = :1 chroot# lxsession & chroot# xrandr -o right

If everything goes well, you should have LXDE visible on your Kindle’s screen. Ta-da! Feel free to play around with it. I’ve found that the touch screen is suprisingly accurate, even though it is using an IR LED system to detect touches instead of a normal digitizer.

Once done in the chroot, Ctrl-C + Ctrl-D can be issued to exit the chroot. We can then restore the Kindle UI by doing:

kindle# for service in ${ SERVICES } ; do start ${ service } ; done

It might take a while for anything to display again.