Skip to main content

Jesse Vincent

Froyo for nookcolor

16 min read




If you've read my blog for a while, you've probably seen my unfortunate interactions with Barnes and Noble trying to buy a nook last Christmas. You've also probably seen some of my Kindle hacking and Android development work.

The big takeaway from last Christmas was "don't by a nook"

The nookcolor is B&N's latest - a 7 inch eReader.

Calling it an eReader is somewhat disingenuous. It's somewhat different from the original nook:

  • No 3G
  • No E Ink screen
  • 50% heavier than the original nook

Like the original nook, it's running Android. It has a microSD slot. And it's been rooted. (Not by me.)

I've been on the road for work a lot lately. That usually means I have rather a lot of time to kill in the evenings. Last Wednesday night, I found myself in a Barnes & Noble store in Northern Virginia. I wanted to check out the new nookcolor, but, well, I wasn't about to give Barnes & Noble any more of my money.

I walked in the front door to find one of the booksellers standing in front of the nook kisok messing around with the nookcolor. I asked if I could play with it for a moment.

As I popped into the Setttings menu, she started to tell me about the device. I'm...not quite sure how it happened, but some of the first words out of her mouth were "It's been rooted, you know."

I guess I look the part.

I played with the device for a while. It felt reasonably solid and was impressively speedy. The bookseller (I've forgotten her name :/) started talking about how much she was looking forward to a community port of Froyo.

My resolve began to weaken, but I knew that I knew nothing about the internals of the device and I wasn't about to buy another Android tablet with an anemic CPU. (I bought a ZT-180 from China and dropped my PixelQi display into it, just to see if it would work. I bought a Viewsonic G Tablet a couple weeks ago with the same intent, but haven't fully disassembled it to get to the display yet.)

I played my get out of jail free card: "So, uh, I suspect that this isn't the typical sort of question you get about the nookcolor, but how fast is the CPU?"

"It's 800MHz."

I bought one. And sat down in the B&N cafe. I used their free wifi to download nooter from nookdevs.

15 minutes later, I had ADW.Launcher, Angry Birds and K-9 Mail installed. Angry Birds was remarkably smooth.

Like everyone else, I spent some time messing around on the device, which identified itself as a "LogicPD zoom2" internally.

"Wow. This is a pretty standard Android device. I wonder how hard a vanilla Android build would be."

Flash forward to Friday.

B&N finally shipped bootloader and kernel source. The source distribution was a zip file containing "Documents and Settings/awu/Desktop/distro.tar"

The content inside the tarball left a bit to be desired. I haven't yet found enough markers to figure out what kernel tree and tag was used as the branchpoint, so I don't know precisely what the local changes are.

I have made reasonable headway on figuring that out, though.

I started reading up on the relevant bits.

Meanwhile, this YouTube video was NOT posted by me:

Over the past couple days, with help from [mbm] on (who did all this before I did ;), I've cobbled together a basic working Froyo userland.

Below is a first pass braindump of what I've done. I'm 100% sure I'm missing steps - and what I have running so far is hardly something I'd want to run full time on my device.

Per usual, what you're doing could turn your device into an expensive paperweight. (It's too flat to make a decent doorstop.)

As nooter (the nookcolor rooting tool) showed us, the nookcolor can boot from SD. In fact, it's set to prefer to boot from SD. This makes development rather less painful than it might otherwise be.

I initially started building a full cleanroom filesystem, but [mbm] convinced me that it's a bit easier to start off with the working nookcolor filesystem image and customize from there. Long term, this is obviously not the right plan.

Root your nookcolor (nc) with nooter.

Download a full filesystem image from the nc. There are a few ways to do this. The fastest is to dd to a local filesystem on the flash card. and mount that on your workstation. The most trivial is:

adb pull /dev/block/mmcblk0 ./nook-8-gig-raw-filesystem

You'll need a MicroSD card of at least 8 gigs to drop this filesystem onto. This will (sort of obviously) obliterate every single bit on that MicroSD.

dd  /dev/sdX

When you pop the MicroSD out and re-insert it, you'll likely see a whole bunch of partitions automount.

Be careful not to distribute this SD image, as the factory partition contains a zip file including a full (proprietary) OS image and the rom partition includes personal device details.

If you stick this into your nc, it should boot to the regular nook image using the boot partition on the MicroSD card.

Right now, the one you REALLY care about is "boot" (On ubuntu, it'll mount as /media/boot). It's a VFAT filesystem on partition 1.

For now, what we care about on that filesystem is uRamdisk, the boot ramdisk. As of this moment, it's set up to mount the nook's internal flash and continue boot from there.

Make a backup of uRamdisk.

uRamdisk is a u-boot filesystem.

You need to unpack it, twiddle some bits and repack it. I have some tools for this, which I'll publish to github as soon as I untangle them from the rest of the nook image in my local repo (Which contains B&N code I can't distribute because it's not obviously under an opensource license).

There's likely a correct way to do this, but the quick-and-dirty way was a bit easier for me to sort out. u-boot ramdisks are gzipped cpio archives with a 64 byte header.

My "unpack" script looks like this:

mkdir work-$$
dd if=$IMAGE of=/tmp/image.cpio.gz bs=64 skip=1
zcat /tmp/image.cpio.gz > work-$$.cpio
cd work-$$
cpio -i -F ../work-$$.cpio
echo "Unpacked ramdisk is in work-$$"

The two files you really care about right now are env.txt and init.rc

Right now, all we care about is twiddling pointers to partitions.

env.txt should look like this:

bootargs=console=ttyS0,115200n8 androidboot.console=ttyS0 root=/dev/mmcblk1p2 rw rootdelay=1 mem=512M init=/init videoout=omap24xxvout omap_vout.video1_numbuffers=6 omap_vout.vid1_static_vrfb_alloc=y omapfb.vram=0:8M
bootcmd=mmc 0 read 0x800 0x81c00000 ${kernel_size}; bootm 81c00000
recovery=echo recovery mode

I've altered the bootcmd's pointer from "mmc 1" to "mmc 0" - this is very much cargo-culting based on the TI docs and not something I've looked at.

Similarly, I've flipped the "root" argument of "bootargs" from mmcblk0p2 to mmcblk1p2. It shouldn't really matter.

EDIT: Turns out this isn't strictly necessary

In init.rc, anywhere the mmcblk0 is mentioned, make it mmcblk1

I also forced adb to always start, just for ease of development.

Now you'll want to repack the ramdisk. My "repack" script looks like this:

DIR="$( basename `pwd`)"
cpio -i -t -F ../${DIR}.cpio | cpio -o -H newc -O ../ramdisk-repacked-${DIR}.cpio
cd ..
gzip ramdisk-repacked-${DIR}.cpio
./mkimage  -A ARM -O Linux -T RAMDisk -C gzip -n Image -d ramdisk-repacked-${DIR}.cpio.gz uRamdisk-${DIR}

mkimage is a standard tool from the u-boot tools directory shipped as part of the B&N nookcolor sourcedrop. I'd assume that the mkimage from any copy of u-boot would be fine.

Once you repack the ramdisk, put it back on the boot partition as uRamdisk.

Umount all the filesystems on the MicroSD, eject the MicroSD and drop it in your nc.

Boot your nc. It should boot normally.

Once it's booted, use adb shell to check that filesystems are mounted from mmcblk1 and not mmcblk0

You can now shutdown your nook.

You have a full OS image on SD.

It's now time for the interesting bit, building Android.

I built from TI's omapzoom branch of Android - They're the folks who make the innermost parts of the nc. should tell you everything you need to know about using repo to clone the repositories, check out froyo and build.

You'll need a crosscompiler. TI recommend:

Follow the instructions for zoom2

Once the build is done, put your MicroSD card back in the nc. This time, you're looking for the system partition (sdX5).

You have two options. You can either wipe out B&N's Android build entirely and install the pristine zoom2 build or you can overlay the zoom2 build on top of B&N's build of Eclair.

I went for the former, though [mbm] had better luck with the latter, as it means you won't have to pick out proprietary libraries and tools and install them one by one.

Obviously, if you use any of the B&N bits, you MUST not distribute your filesystem image. It appears that TI publishes just about every proprietary bit we could possibly want on their GForge instance, though I haven't actually dug in too deep just yet.

You'll want to neuter etc/vold.* on the system partition once you've installed the new image, as it tries to mount an sd card that's now... otherwise occupied.

Once you're done with this, it's time to go back to work on your uRamdisk image, since froyo wants somewhat different startup bits than eclair.

I ended up with something a bit wonky causing mount failures as I was migrating init.rc to froyo. Again, this is courtesy of [mbm]:

	--- ../work-20413/init.rc   2010-12-05 11:22:40.514818375 -0500
+++ init.rc 2010-12-04 21:34:36.209385337 -0500
@@ -1,4 +1,3 @@
-# init.rc used on Encore hardware
on early-init
# Give the kernel time to enumerate the internal and external MMC/SD cards
@@ -16,7 +15,8 @@
export ANDROID_ROOT /system
export ANDROID_ASSETS /system/app
export ANDROID_DATA /data
-    export EXTERNAL_STORAGE /sdcard
+    export EXTERNAL_STORAGE /mnt/sdcard
+    export ASEC_MOUNTPOINT /mnt/asec
export INTERNAL_STORAGE /media
export BOOTCLASSPATH /system/framework/core.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar
export DSP_PATH /system/lib/dsp
@@ -37,16 +37,39 @@
# Backward compatibility
symlink /system/etc /etc
-# create mountpoints and mount tmpfs on sqlite_stmt_journals
+# create mountpoints
+    mkdir /mnt 0775 root system
+    mkdir /mnt/sdcard 0000 system system
+# Create cgroup mount point for cpu accounting
+    mkdir /acct
+    mount cgroup none /acct cpuacct
+    mkdir /acct/uid
+# Backwards Compat - XXX: Going away in G*
+    symlink /mnt/sdcard /sdcard
mkdir /system
-    mkdir /tmp 0777
mkdir /data 0771 system system
mkdir /cache 0770 system cache
mkdir /media 0777 system system
-    mkdir /sdcard 0777 system system
-    mkdir /sqlite_stmt_journals 01777 root root
mkdir /rom 0777 root root
-    mount tmpfs tmpfs /sqlite_stmt_journals size=4m
+    mkdir /config 0500 root root
+    # Directory for putting things only root should see.
+    mkdir /mnt/secure 0700 root root
+    # Directory for staging bindmounts
+    mkdir /mnt/secure/staging 0700 root root
+    # Directory-target for where the secure container
+    # imagefile directory will be bind-mounted
+    mkdir /mnt/secure/asec  0700 root root
+    # Secure container public mount points.
+    mkdir /mnt/asec  0700 root system
+    mount tmpfs tmpfs /mnt/asec mode=0755,gid=1000
mount rootfs rootfs / ro remount
@@ -55,6 +78,46 @@
write /proc/cpu/alignment 4
write /proc/sys/kernel/sched_latency_ns 10000000
write /proc/sys/kernel/sched_wakeup_granularity_ns 2000000
+    write /proc/sys/kernel/sched_compat_yield 1
+    write /proc/sys/kernel/sched_child_runs_first 0
+# Create cgroup mount points for process groups
+    mkdir /dev/cpuctl
+    mount cgroup none /dev/cpuctl cpu
+    chown system system /dev/cpuctl
+    chown system system /dev/cpuctl/tasks
+    chmod 0777 /dev/cpuctl/tasks
+    write /dev/cpuctl/cpu.shares 1024
+    mkdir /dev/cpuctl/fg_boost
+    chown system system /dev/cpuctl/fg_boost/tasks
+    chmod 0777 /dev/cpuctl/fg_boost/tasks
+    write /dev/cpuctl/fg_boost/cpu.shares 1024
+    mkdir /dev/cpuctl/bg_non_interactive
+    chown system system /dev/cpuctl/bg_non_interactive/tasks
+    chmod 0777 /dev/cpuctl/bg_non_interactive/tasks
+    # 5.0 %
+    write /dev/cpuctl/bg_non_interactive/cpu.shares 52
+    # Create dump dir and collect dumps.
+    # Do this before we mount cache so eventually we can use cache for
+    # storing dumps on platforms which do not have a dedicated dump partition.
+    mkdir /data/dontpanic
+    chown root log /data/dontpanic
+    chmod 0750 /data/dontpanic
+    # Collect apanic data, free resources and re-arm trigger
+    copy /proc/apanic_console /data/dontpanic/apanic_console
+    chown root log /data/dontpanic/apanic_console
+    chmod 0640 /data/dontpanic/apanic_console
+    copy /proc/apanic_threads /data/dontpanic/apanic_threads
+    chown root log /data/dontpanic/apanic_threads
+    chmod 0640 /data/dontpanic/apanic_threads
+    write /proc/apanic_console 1
# mount MMC partitions
mount vfat /dev/block/mmcblk1p2 /rom sync noatime nodiratime uid=1000,gid=1000,fmask=117,dmask=007
@@ -382,8 +445,8 @@
service vold /system/bin/vold
socket vold stream 0660 root mount
-#service mountd /system/bin/mountd
-#    socket mountd stream 0660 root mount
+service netd /system/bin/netd
+    socket netd stream 0660 root system
service debuggerd /system/bin/debuggerd
@@ -396,10 +459,13 @@
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
+    onrestart write /sys/power/state on
+    onrestart restart media
service media /system/bin/mediaserver
user media
-    group system audio camera graphics inet net_bt net_bt_admin
+    group system audio camera graphics inet net_bt net_bt_admin net_raw
+    ioprio rt 4
service fw3a /system/bin/fw3a_core
user root
@@ -421,6 +487,37 @@
user bluetooth
group bluetooth net_bt_admin
+service bluetoothd /system/bin/bluetoothd -n
+    socket bluetooth stream 660 bluetooth bluetooth
+    socket dbus_bluetooth stream 660 bluetooth bluetooth
+    # init.rc does not yet support applying capabilities, so run as root and
+    # let bluetoothd drop uid to bluetooth with the right linux capabilities
+    group bluetooth net_bt_admin misc
+    disabled
+service hfag /system/bin/sdptool add --channel=10 HFAG
+    user bluetooth
+    group bluetooth net_bt_admin
+    disabled
+    oneshot
+service hsag /system/bin/sdptool add --channel=11 HSAG
+    user bluetooth
+    group bluetooth net_bt_admin
+    disabled
+    oneshot
+service opush /system/bin/sdptool add --channel=12 OPUSH
+    user bluetooth
+    group bluetooth net_bt_admin
+    disabled
+    oneshot
+service pbap /system/bin/sdptool add --channel=19 PBAP
+    user bluetooth
+    group bluetooth net_bt_admin
+    disabled
+    oneshot
service installd /system/bin/installd
socket installd stream 600 system system
@@ -432,8 +529,6 @@
service ifcfg_ti /system/bin/ifconfig tiwlan0 up
@@ -447,6 +542,19 @@
+service racoon /system/bin/racoon
+    socket racoon stream 600 system system
+    # racoon will setuid to vpn after getting necessary resources.
+    group net_admin
+    disabled
+    oneshot
+service mtpd /system/bin/mtpd
+    socket mtpd stream 600 system system
+    user vpn
+    group vpn net_admin net_raw
+    disabled
+    oneshot
service keystore /system/bin/keystore /data/misc/keystore
user keystore
@@ -463,5 +571,7 @@
service debuglog /system/bin/
user root
+service dumpstate /system/bin/dumpstate -s
+    socket dumpstate stream 0660 shell log
+    disabled
+    oneshot

At this point, (assuming I haven't forgotten anything), you should have a MicroSD that will boot froyo on a nookcolor.

...and then immediately shut down, ostensibly due to power issues. My sneaking suspicion is that this is because the kernel the nc is booting from is B&N's original 2.6.29 image and there's been a bit of skew in how it reads some bit of information out of /proc.

The correct next step is to go and build a proper kernel for the device.

The easy next step is to perform a brutal hackjob on android's batteryservice.


Edit: I have no reason to believe that this is actually likely. But it'd be double-plus irresponsible of me to suggest that turning off a hardware safety feature was a good idea.


	jesse@puppy ~/android-omapzoom/frameworks/base/services ((6c81cb0...) *) $ git diff
diff --git a/services/java/com/android/server/ b/services/java/com/android/server/
index 5cf61bd..bf96479 100644
--- a/services/java/com/android/server/
+++ b/services/java/com/android/server/
@@ -176,8 +176,8 @@ class BatteryService extends Binder {
void systemReady() {
// check our power situation now that it is safe to display the shutdown dialog.
-        shutdownIfNoPower();
-        shutdownIfOverTemp();
+        //shutdownIfNoPower();
+       // shutdownIfOverTemp();
private final void shutdownIfNoPower() {
@@ -210,8 +210,8 @@ class BatteryService extends Binder {
boolean logOutlier = false;
long dischargeDuration = 0;
-        shutdownIfNoPower();
-        shutdownIfOverTemp();
+      //  shutdownIfNoPower();
+        //shutdownIfOverTemp();
mBatteryLevelCritical = mBatteryLevel 

Once you've rebuilt the android core and reinstalled it on your system partition, you should now have something that boots froyo on your nook.

This froyo is VERY MUCH not ready for primetime. Don't expect WIFI, Bluetooth, Google Apps, reasonable performance, sensor access, etc.

TI distributes wifi drivers and all the hardware acceleration you could possibly want:

This all would have taken me a great deal longer without [mbm]'s assistance and advice.

My next steps will (probably) be to try to build a modern kernel from source and see what that does for driver support.

Please note that I don't plan to build a distributable ROM or to port Cyanogenmod, though I'd be thrilled to see someone pick up the torch and do so.

I can't distribute the OS image I have, as it contains a mix of free stuff and proprietary stuff pulled off of my nookcolor's system partitions.

If you're looking to chatter with folks about development for the nookcolor, I'd recommend on

Jesse Vincent

Odds and ends

2 min read

It's been a while since I've blogged about Kindle stuff. I just pushed up the little bit of custom code from my cobbled together Ubuntu/X11 on Kindle hack.  You can find it at

Making use of that is still a bit of work. You need to install a copy of Jaunty Jackalope (or possibly Karmic) for ARM into a QEmu emulator. Then grab that ext2 filesystem image, copy it over to your kindle (2, DX, etc) and mount it somewhere locally and then chroot into it.  From there, you can use the patch at the google code link above to build a copy of that will actually work on the Kindle's display (and doesn't depend on having a tty).  The various support scripts I used for my various demos are all up there as well.  This isn't nearly as polished as Savory, but, well, it's not really an end-user thing at this point ;)

I don't think I'm going to spend a whole lot more time on this, but you never know.

I've been spending a bunch of my time on this "Perl" thing of late. Apparently, I volunteered myself to get Perl 5.12 out. Now I'm responsible for it or something.


Jesse Vincent

Improved PDF rendering for Savory

1 min read

Now with better default fonts (Google's free Droid fonts) and border cropping.

Jesse Vincent

Playing to the crowd

1 min read

From the bits of feedback I've gotten on Savory's initial release on Friday, it seems pretty clear that people want to be able to view rendered PDFs that look "like they're supposed to" 

Savory's initial release used a PDF-to-HTML converter that extracts the text from a PDF and turns it into a reflowable ebook.  If your PDFs are generated from text by modern tools. this is great.  Most PDFs aren't.
Over the weekend, I put together a PDF renderer for Savory build on Poppler and the Kindle's built in Manga support (If you have a .zip or .cbz file full of images, the Kindle will display the images like a book)
For now, every PDF is converted twice. Once to text and once to a set of rendered images. So far, it's working pretty well for me. I'd love some feedback on from anyone who's game.  Just replace your regular savory image with it and reboot the kindle.

Jesse Vincent

What's next for Savory

1 min read

  • Good conversions of image-heavy or image-based PDFs. (I just need to build Ghostscript on the )
  • A revised installer/uninstaller based on some suggestions from the folks at Blog Kindle (Who have a Unicode font mod for the K2 up at
  • Tracking down slightly a few unreliable ebook conversions/installations I've noticed.

Jesse Vincent


16 min read

UPDATED 5 April 2009 - 11:16 EDT: Pointers changed to Savory installer and uninstaller 0.06 which provide minor run-time reliability and book-detection fixes. If you are running 0.05, you should uninstall the old version and install 0.06.

UPDATED 6 April 2009 - 9:41 EDT: I put together beta-quality support for picture-perfect PDF production. You can try it out if you promise to report back

UPDATED 6 April 2009 - 22:44 EDT:Screenshots of savory's improved PDF converter.

Over the past few weeks, I've spent much of my spare time with my new Kindle2...When I bought it, I was excited to have a gorgeous, solidly built ebook reader backed by Amazon's catalog. I figured I'd end up reading a bit more than I already did and spending a bit more money on books than I already did. Both turned out to be true. What I didn't count on was finding a new hobby.

Hi, I'm Jesse and I have a software problem.

When I get a new bit of hardware, I often end up writing software for it. In 2001, when I got one of Canon's first Digital SLRs, I found myself writing code to extract usable images from the "RAW" image files the camera produced. This fall, I picked up a new T-Mobile G1 to replace an iPhone...and found the email client lacking. The Android platform that the G1 runs on is free and open. So I dusted off some long-unused Java experience and created K9, an enhanced version of Android's email client.

I really didn't think this would happen with the Kindle. I was wrong.

What is Savory?

Savory is a native ebook conversion package for the Kindle 2. It lets you download and read PDFs and ePubs on the Kindle without a manual conversion step.

So, you hacked the Kindle?

No. There have actually been a number of other user-generated Kindle updates. igorsk created the toolset which generates Kindle and Kindle2 updates. Other members of the Kindle community have created Kindle2 updates which change the Kindle's fonts to support books in non-western language, let you set your own screensavers and a bunch more. These packages already contain everything a technically savvy user would need to install software on the Kindle. What I did was to port an ebook-conversion package to run reasonably efficiently on a 500mhz ARM with 128 megabytes of system memory and to write a small program which watches for new ebooks in a few chosen formats and run those through the conversion tool.

Does Savory let me decrypt books Amazon has protected with DRM?


So this is like KindlePid?

Nope. Not at all. KindlePid is a tool for reverse-engineering your Kindle's "Mobipocket Pid." KindlePid lets you buy DRM-protected ebooks from providers other than Amazon. Savory converts PDFs and ePubs that you download to your Kindle over WhisperNet or 3G into unprotected .mobi documents. There are web-based and desktop tools which can do everything Savory can do. Savory just brings these features directly to your Kindle 2.

Does Savory let me read DRMed ebooks?

No. Savory does not include support for ebooks protected by DRM. DRM is an incredibly "hot" topic in the ebook world right now. There are varying opinions on its efficacy. My opinions on the matter aren't relevant, except to say that I am not touching the topic with a 10 foot pole. It will not convert DRM-protected ebooks into a format the Kindle will read. It will not add or remove DRM from any ebook.

Does Savory let me do anything Amazon didn't already let me do for free?

No. It just makes some things that are a little cumbersome out of the box simple and transparent. It's already possible to use desktop and web based services to transcode ePub and PDF documents into the Kindle-compatible Mobipocket format. Amazon also provides both free and for-pay email-based conversion services you can use.

Does Savory work with the Kindle 1?


Why did you create Savory?

I'm in love with my Kindle. I've been reading ebooks on screens of various sorts for many years, but the Kindle2 is the first device that I actually enjoy reading as much as I enjoy reading paper books. I've tried other ebook readers, but for a variety of reasons, they just don't work for me. My goal is to make it easier for readers to read more free content on the Kindle.

I got the idea after reading Tim O'Reilly's editorial in Forbes about why the Kindle platform will be more successful if it's more open. My first experiments were actually in server-based transcoders to convert PDFs and epubs to Kindle-compatible Mobipocket books, but I quickly realized that running the converter locally on the Kindle would result in a much better user experience and make the Kindle more useful. And yeah, it seemed like an interesting project.

What document formats does Savory let me read?

Savory allows you to read .epub and .pdf files on your Kindle. It does this by converting these documents to Mobipocket format ebooks using Calibre. You should note that the version of Calibre Savory uses only works with text-based PDFs. If you have image-based or scanned PDFs, conversion will fail. (Images in your PDFS are ok. There just needs to be some text to extract.) Updated: Screenshots of the new and improved PDF converter.

How does Savory work?

Plain-english version

Savory installs a small program which runs on your Kindle and watches for new files in the 'Documents' directory with names ending in '.epub' and '.pdf'. When the system notifies Savory that a document has shown up, it wakes up and runs an open-source file conversion program called Calibre. Savory also updates your Kindle2's browser configuration file to tell it that the Kindle can now handle .pdf and .epub documents.

Technical version

Savory changes the browser configuration file to allow download of pdf and epub documents. It adds a new "init" script which tries to mount savory-image.ext3 on boot. If that succeeds, it runs bin/savory_daemon from within the image mentioned above. savory_daemon is a Python script that watches the documents/ directory and invokes a converter based on Calibre when it sees something that looks right.

Is Savory supported by Amazon?

No. If you have a problem with Savory, DO NOT CONTACT AMAZON. This isn't software they wrote. They're not responsible for it. Please don't bother them about it.

If the nice folks at Amazon contact me (you can find my email address at the bottom of this FAQ) and ask me to stop distributing Savory, I will do so. My goal isn't to "hack" the Kindle, deprive Amazon of revenue or place an increased support burden on Amazon's Kindle team. I just want to make the Kindle2 an even more useful reader than it already is.

Does Savory void my warranty?

I don't know. If you're not comfortable with the possibility, do not install Savory.

Does Savory come with any guarantee or warranty?

I guarantee that Savory will not give you the ability to fly or to see through walls. Past that, no. Savory comes with no warranty or guarantee OF ANY KIND. If it causes your Kindle to burst into flames or gives your pets the ability to read, you are ENTIRELY ON YOUR OWN. By downloading and installing Savory, you accept full responsibility for anything it does.

Savory is distributed under the MIT license:

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.


What do I do if Savory breaks my Kindle?

Head on over to the MobileRead Kindle forums and post your sob story. Hopefully, someone there can help figure out what went wrong and help you get back to a working state. Remember that Savory comes with absolutely no warranty and everybody on MobileRead who might help you out is a volunteer.

How do I install Savory?

Installing Savory or any other third-party update on your Kindle may destroy your Kindle. If that happens, you will have a $360 paper weight. DO NOT INSTALL SAVORY UNLESS YOU'RE WILLING TO END UP WITH A DEAD KINDLE.

You'll need to download three files:

This file contains Savory's file-conversion system and assorted tools.

Download and unzip this file. Then, mount your Kindle2 on your desktop with USB and drag savory-image.ext3 into the "system" folder on your Kindle2.


This file is a Kindle update which will remove an installed copy of Savory from your Kindle. Please keep a copy of this file handy in case you ever need it.


This file is a Kindle update.

You should copy this file to the root directory of your Kindle. After you do that, unmount the kindle and click the "Menu" button, select "Settings", click the "Menu" button and click "Update Your Kindle" This will apply the update.

If "Update Your Kindle" is greyed out, mount the Kindle on your desktop again and DELETE the update file. Then, unmount the Kindle. If you're not already on the Settings page, click "Menu" and select "Settings". Make sure your Kindle is plugged into your computer with the USB cable. Click "Menu" and select "Restart". The Kindle will boot up and immediately enter USB mode. Copy the update file to the Kindle again and follow the instructions above.

I've found that the Kindle is much happier recognizing update files if you reboot the Kindle while it's connected to your computer with USB and copy the update to the Kindle before the Kindle's UI comes up at all

If you copy the file to your kindle and reboot without applying the update, it will end up in a reboot loop - I haven't figured out why yet. If that happens, hold down the "Home" button while booting to get into recovery mode. From there, you can mount the Kindle on your desktop with USB, delete the .bin file and try again.

How do I turn Savory off temporarily?

Mount your Kindle on your computer with USB. Rename the savory-image.ext3 file in the Kindle's "System" folder. Then, unmount your Kindle, click "Menu", select "Settings", click "Menu" and click "Restart your Kindle." When you later want to re-enable Savory, repeat the process, naming the file back to "savory-image.ext3"

How do I remove Savory completely?

If you've decided that Savory isn't for you or you need to remove Savory to perform an Amazon-provided system update, it's a two step process. First, you'll need to follow the instructions above about how to temporarily turn off Savory. Then, download and run the "update_RemoveSavory-0.06.bin" system update and apply it just like you applied the original system update.

Amazon's system updates very carefully check each and every file they're about to update to make sure that they are exactly as Amazon left them. This ensures that a system update doesn't unexpectedly corrupt an "important" file. Savory updates the Kindle's browser configuration to allow download of pdf and epub files, adds an "init script" to start up the savory daemon which watches for new files to convert and modifies the Kindle's "version.txt" file. This way, anyone doing support for your Kindle will know it's not running a stock system image and NOT ELIGIBLE FOR SUPPORT FROM AMAZON.

Savory copies each file it modifies before making changes. All files Savory modifies are saved with the file suffix "-beforesavory". When you uninstall Savory, it restores the pristine versions of these files.

What does Savory do to my battery life?

It makes it shorter. So far, it doesn't feel like it makes it much shorter. Comparisons and benchmarks would be appreciated

What does Savory do with the "originals" of ebooks it converts?

You'll find the originals of any book Savory converts (or fails to convert) in the savory-archive folder on your Kindle when you browse it from your computer.

Where can I get the source code to Savory?

Savory is hosted on Google Code:

What software does Savory use?

Savory wouldn't have been possible without kindle-update-maker, created by Igor Skochinsky.

Savory is about 200 lines of Bourne Shell and Python, built to drive a modified copy of Kovid Goyal's open-source Calibre ebook conversion and management suite.

The disk image containing the Savory daemon and the modified version of Calibre contains a number of dependencies, listed below. You can download all of these source tarballs from

The patches to Calibre are available in the same source repository as the rest of Savory. All other packages are unmodified. Revision 2689 Revision: 370;a=snapshot;h=HEAD;sf=tgz as of 2009-03-30 - pyinotify-0.8.1-py2.6.egg-info

How much code is Savory?

The unique parts of Savory are about 85 lines of shell script and 135 lines of Python.

Why's the Savory disk image nearly 90 megabytes uncompressed?

Savory uses Calibre, a free and open ebook conversion suite. In turn, Calibre uses Python, Qt and some other libraries. While I've slimmed down the requirements by hand, we have a long way to go before Savory fits in 5 or 10 megabytes.

What license is Savory under?

The original code in Savory is available under the terms of the MIT License. The various components bundled with Savory are all free or open software, but they're not all released under the same license.

I want to be able to use my Kindle to read books in some other format. How do I make that happen?

Savory supports a subset of the conversions provided by Calibre. If you contribute to Calibre, Savory should be able to take advantage of those improvements.

Can I run other software on my Kindle?

I don't know. Can you?

Can you help me run other software on my Kindle?


The Kindle has a 3G modem in it. Can I use that to get free internet access for my laptop?

Don't even think about it. The Kindle's 3G internet access is currently provided gratis to all Kindle users for the purpose of browsing the web and downloading ebooks. Amazon could choose to start charging for this "experimental" feature at any time. On top of that, Amazon knows where you live, has your credit card number and, thanks to the Kindle's GPS, knows where you are right now.

Where can I get support for Savory?

The MobileRead forums are probably the right place to start.

So, why is it called Savory?

When I first got a my Kindle2, I experimented with a web-based transcoding proxy which lets you download ePub and PDF files to the Kindle using a tool running on a server. I called the project an "unsavory ePub hack." This new tool is a good deal more elegant and easier to use. It's no longer unsavory. That must mean it's Savory

Savory is awesome! Now I want a Kindle!

Great! That's the kind of thing I like to hear. Savory is (and will always be) 100% free. BUT! Shameless plug warning If you buy a kindle (or anything else) from Amazon, I'll earn a referral fee which goes to feed my ebook habit. Buying a Kindle 2 from Amazon through this site helps us tell Amazon that we want the Kindle to support open formats. If more than a few of you buy a Kindle through this blog, I'll post a running tally.

Who created Savory?

I'm Jesse Vincent. You can reach me at jesse - at - Please don't contact me directly for help with Savory, even if it sets your dog on fire or you're sure that I'll make an exception for you.

If you need help with Savory, I refer you to the forums at (See above)

Jesse Vincent

Jesse Vincent

Jesse Vincent


1 min read

I blame gnat and joshua.

(Image from yog's flickrstream)

Jesse Vincent

Harrier Book

1 min read