This article is part of an extended series on Kobo development and investigation
Any attempt to modify your device is risky. Your device might be permanently destroyed. If you cannot risk the permanent loss of your device, so not attempt to modify it. Something can easily go wrong if you do the wrong thing - or follow out of date instructions. I don't continually maintain and test these instructions, so they might well qualify.
If you can't afford to lose it forever, physically open your Kobo up before doing anything, remove the SD card, and take a disk image of it using a PC with a card reader. I use `dd` with a Linux box to make sure I get a complete image of the entire card.
Note that you could break the case or retaining clips when opening your Kobo. I didn't and I opened mine quite a few times, but who knows if they've changed assembly techniques, plastics, etc since then.
Messing with embedded devices that aren't designed to be hacker-friendly is risky. Deal with it, or don't mess with the device.
Once you've enabled telnet on your Kobo Wifi, you can use it to transfer a disk image of the Kobo's entire firmware image on the internal MicroSD card. This will give you a backup copy of your Kobo's firmware on your computer.
You can't restore the firmware image without physically opening your Kobo if you mess things up badly enough for it not to boot, but hopefully you won't do that. The Kobo seems to be amazingly hard to break unless you corrupt its file systems, overwrite its kernel, etc. Anyway, this way you can avoid opening the Kobo until/unless you ever need a total firmware restore.
Imaging the Kobo's firmware over wifi
To image the disk of a running system, we need all its file systems in read only mode. This turns out to be trivial to achieve with the Kobo, though it requires terminating the main eReader process ("nickel") so you'll want to reboot after you've done it. During the process, the screen will display whatever was on it before you ran the commands to image the system and none of the keys will respond. Just:
pkill nickel
mount -o ro,remount /mnt/onboard
mount -o ro,remount /
nc -l 9984 < /dev/mmcblk0
Now, take note of the IP address printed by the commands above and use it in this command on your main computer:
nc IP_OF_KOBO 9984 > kobo_internal_microsd.img
The disk imaging process will take a while over wifi, and won't show any progress. Mine took about twenty minutes. If you want progress indication, open a second terminal and run:
watch "du -ms kobo_internal_microsd.img"
... to get a count in megabytes of data transferred so far.
Finally, reboot the kobo to bring it back to normal. You can do this by pressing and holding the power button for 6+ seconds, or by typing control-C then "reboot" and enter into the telnet command line on the kobo.
The image saved on your computer should be 1977614336 bytes for a Kobo Wifi with a 2GB internal card (~1.1GB user accessible memory).
If you have any issues, try a different port number with nc.
^C
reboot
Once you have the Kobo's disk image, you can mount the partitions within it to examine them, and you can extract some individual components of the unpartitioned space in the card.
Imaging the Kobo's firmware to an SD card
In principle you can also image the Kobo's firmware to an SD card instead of using wifi. This will be much easier if you don't run Linux. You need a 2GB or larger card.
To image the Kobo's firmware to an SD card you can telnet in to the kobo and make the file systems read-only as above. Make sure you unmount the external sd card /mnt/sd if it is mounted. Then, instead of getting the IP address and running netcat in listen mode, you can just `dd' the internal mmc card to the external sd card, `sync' to force it to flush, and `reboot'.
Alternately, you may prefer to leave the external SD card mounted, remount everything else read only, then run:
dd if=/dev/mmcblk0 | gzip > /mnt/sd/kobo.img.gz
... to make a compressed image (slow!) on the file system on the SD card. This will be easier to work with under Windows, which doesn't work well with raw devices.
Examining the firmware image
gunzip the image if it's compressed. Either back up a copy of the firmware image that you will not touch, or make the firmware image read-only with chattr +i.
You may now mount the three file systems on the image using this little script - or by hand by using "fdisk -l" to dump the partition table, then calculating the offsets to pass to losetup. If you want to use my script, I make no promises that it won't eat your system and your cat, so be careful. Save the following to "kobomount.sh" and mark it executable:
#!/bin/bash
set -e -u
if test $# -ne 1 ; then
echo "Usage: $0 firmware.img"
exit 1
fi
IMG=$1
i=0
sudo -v
for offset in $(sfdisk -d kobo_2gb_microsd_image_v174.img | grep start | cut -d : -f 2 | awk '{print $2}' | sed 's/,//g' |grep -v ^0$); do
sudo losetup --offset $(( $offset * 512 )) /dev/loop$i "$IMG"
sudo mkdir -p /mnt/kobo/$i
sudo mount -o ro /dev/loop$i /mnt/kobo/$i
((i++))||true
done
You may then aim it at your firmware image and it'll mount the contained partitions on /mnt/kobo/0 (the recovery partition), /mnt/kobo/1 (the main OS) and /mnt/kobo/2 (the user flash partition). All will be read-only.
You may also want to extract some blobs from the unpartitioned space at the start of the image. That's where the kernel, boot splash image, etc live. I don't have official documentation on the layout of this space, but reading the upgrade scripts in /etc/init.d suggests that these values should be about right. They are UNVERIFIED except for the boot splash image, which I've been able to edit and replace.
IMG=kobo_2gb_microsd_image_v174.img
dd if=$IMG of=serialnumber.bin bs=512 count=1 skip=1
dd if=$IMG of=hwconfig.bin bs=512 count=1 skip=1024 count=2
# The image that ships with the kobo is < 470 512 byte blocks long. It's not clear
# if something else takes the space between the end of the image and the start of
# the epson display binaries, if it's dead space, or if there's room for bigger
# images.
dd if=$IMG of=bootlogo.bmp bs=512 skip=1026 count=470
dd if=$IMG of=epson_display_setup.bin bs=512 count=1 skip=1920 count=8
dd if=$IMG of=epson_waveform.bin bs=512 count=1 skip=1928 count=$((2048 - 1928))
dd if=$IMG of=kernel.bin bs=512 count=1 skip=2048 count=$((7564-2048))
The Kobo's kernel
We can now examine the existing kernel to learn more about it. This post tells us
how to extract the kernel (but it's more easily done with
scripts/extract-ikconfig from a kernel tree)
The hard way (which lets us extract the image, not just the config) in brief:
od -A d -t x1 kernel.bin | grep '1f 8b 08 00'
# Note the (decimal) offset, correct for offset of deflate header into line
dd if=kernel.bin bs=1 skip=0013076 | zcat > vmlinux
The easy way to dump the config:
scripts/extract-ikconfig $HOME/kobo/kobofirmwaredump/kernel.img
Boot loading is apparently performed by RedBoot (2.0 according to shipped
sources), which should offer tools like `fis list' to report on the structure
of the redboot-managed areas of flash storage. Building redboot is a nightmare,
so I haven't investigated this yet.