libVitaMTP & OpenCMA: Vita content management on Linux (and more)

More than a year ago, I’ve analyzed how the Vita communicates with the computer. I mentioned at the end that I started a project that will be an open source implementation of the protocol that the Vita uses. This protocol is just MTP (media transfer protocol) with some additional commands that I had to figure out. MTP is used by most Windows supported media players and cameras, so I was able to use a lot of existing code from libmtp and gphoto2. After lots of on and off work, I am happy to announce the first (beta) version of libVitaMTP and OpenCMA.

What is libVitaMTP and OpenCMA?

In anticipation of allowing developers to include Vita support in their media management applications, and for allowing developers to create custom applications that use the Vita (for example, it would be possible to write an application that uses the Vita as a general purpose storage device), I’ve placed all the backend code into libVitaMTP. This includes connecting of the Vita through libusb-1.0, processing various XML data sent from the device with libxml2, and supports an interface that allows the developer to send the various custom MTP commands to the device.

OpenCMA is the first user-level software that uses libVitaMTP. It serves two purposes. First, it’s a stripped down, open source implementation of CMA, that allows the user to send and receive games, backups, and media to and from the Vita. It is stripped down because Sony’s official CMA supports reading the metadata from media files, and I chose not to include this feature because it would complicate things.

More information can be found on the Github page.

Testing

If you are a developer and wish to include libVitaMTP in your projects, please give feedback on any bugs or difficulties/bad documentation/inconsistant documentation.

If you are a user and wish to test OpenCMA, I’ve provided some Debian packages (created and tested on Ubuntu 12.04) for you to try. After installing, just invoke “opencma -h” in the terminal to see how to use it.

A sample run of OpenCMA could be

$ opencma -u /path/to/dir/containing/updatelist -p /path/to/photos -v /path/to/videos -m /path/to/music -a /path/to/apps -l 4

the -l 4 means to show more logging information. This is very important for filing bug reports. If you encounter a crash or bug, please make sure to include the output of the OpenCMA session with -l 4. Note that more logging means slower transfers.

Please be careful not to pass in large directories because OpenCMA tries to create an index of all files (recursively) for each path.

Please submit all bug reports and feature requests to the Github issues page. It would make things easier if you include the -l 4 output.

Downloads

As always, the most up to date packages will be uploaded to the project page.

Huawei E587 (T-Mobile 4G Sonic Hotspot): Information and rooting

Earlier this year, I got my hands on the T-Mobile 4G Sonic Hotspot and as always, had to tear it apart as soon as I got it. I never wrote about it because I didn’t find anything overly interesting, but now it’s the end of the year, and I need to clear some inventory from my brain. If anyone remembers my post on the (older) T-Mobile 4G Hotspot (sans “Sonic”), the main limitation of that device was that the processor is an obscure one that required some digging to get information on. Thankfully, the Sonic variety is much easier to break into.

Teardown

I don’t usually do this, but as I couldn’t find any good snapshots of the insides of this device, I took it upon myself to produce some amateur shots. One thing I want to say about the insides is that I loved how the main board is broken into three parts and they’re sandwiched together to make the device small (but thick).

Device with faceplate removed.

Device with faceplate removed.

MCIMX283CVM4B

FreeScale MCIMX283CVM4B

Qualcomm MDM8220 modem

Qualcomm MDM8220 modem

Middle layer, containing various chips

Middle layer, containing various chips

The important information is that the device is ARM based (it even uses the same system-on-chip as older Kindles), and having a well documented SoC is always a plus. There isn’t an obvious debug serial port, but I would bet that there is one knowing how the FreeScale SoCs work. However, we don’t need to explore hardware hacking yet as the software is unexplored.

Rooting

This was literally the easiest device I’ve ever rooted. I can honestly say that from opening the package (knowing nothing about the device) to getting a root shell took me about fifteen minutes. There was only one interface to the device and that’s the management webpage. My plan was to explore every location where I could pass input to the device (settings, HTTP POST requests, MicroSD file browser, etc) and basically just try things until I get a crash or something interesting. The first thing I’ve tried was the settings backup/restore feature. Creating a backup of the settings allows you to download a SQLite database containing the settings. A quick SQL dump of the settings showed me some interesting options that can’t be set directly from the web interface, including:

CREATE TABLE telnet
(
TelnetStatus int
);

Yep, setting TelnetStatus to 1 and restoring the backup database showed me that port 23 was now open from the hotspot’s IP. Well, that was extremely lucky, as always the best hacks are the one which doesn’t require hacking at all. Well that was only half the challenge, the next part is getting access to the root account. I’m thinking everything from brute forcing passwords to looking at privilege escalation exploits but all of that disappeared as soon as I typed “root” and enter because there was no password prompt. That’s right, “root” doesn’t require a password. I did a quick inventory of the filesystem and found the block devices, and using the magic of dd, nc, and the old Unix pipe, quickly dumped all the filesystems.

Software

Here’s the thing though, I spent all this time (almost 45 minutes at this point!) rooting the device and I don’t even have a clear goal. I don’t need to unlock the device because I was a T-Mobile customer at that point, and I didn’t really want to make a pocket ARM computer/server (which would be a thing one can do with this), so I just did a quick scan of how the device works (curiosity is the best excuse) and went my way. Here’s some of the things I’ve discovered, use this information how you will.

First of all, the device runs a stripped down build of Android running “Linux version 2.6.31 (e5@e587) (gcc version 4.4.0 (GCC) ) #1 Sun Aug 28 02:25:47 CST 2011.” On startup, most of the vanilla Android processes (including adbd) are not started, but instead the Qualcomm modem driver, some pppd/networking daemons, and a custom software they call “cms” are started. “cms” makes sure stuff like their custom httpd (which is hard coded to allow the HTML portal site to perform functions on the hotspot) and power management and the OLED display are running and in good status. The Huawi device stores all data on its flash MTD device. From a quick analysis (aka, might be errors), block 0 contains the u-boot bootloader (in what I believe is a format dictated by FreeScale), block 3 contains the kernel (gzipped with a custom header, possible also dictated by FreeScale), block 4 contains the rootfs (also gzipped with a custom header) loaded with boot scripts and busybox, block 5 is Android’s /system which also contains the main binaries (like cms, httpd) and the HTML pages, block 6 is Android’s /data which is empty, block 8 maps to /mnt/backup which I believe is, as the name says, just backups, block 12 maps to /mnt/flash which I believe is where ephemeral data like logs are and also where the settings are stored, and block 13 maps to /mnt/cdrom which has Huewai’s software and drivers for connecting to the computer with (and you see it when you plug the device into your computer).

That’s a quick summary of some of the things I’ve found while poking around this device. Nothing interesting (unless you’re a Huawei E587 fanatic I guess), but I’m sure there’s someone, someday, who got here from Google.

Playstation Vita’s USB MTP Connection Analyzed

This is the first of (hopefully) many posts on the PS Vita. Before I attempt anything drastic with the device, such as getting unsigned code to run, I hope I can try something easy (well, easier) to get used to the device. Ultimately, I want to make a content manager for the PS Vita for Linux. Unlike the PSP, the Vita does not export the memory card as a USB storage device, but instead relies on their custom application to copy content to and from the device. This post will give just a peek into how the communication between the Vita and the PC works.

There are two ways of approaching this. One is to sniff the USB packets to figure out what data gets sent to and from the device, and second is to disassemble the content manager application to find out how it communicates with the device. I tried both methods.

Reverse engineering the Content Manager

The biggest problem here is that the PC version of Sony’s content manager has its symbols removed. This makes everything a hundred times harder as you would have a harder time guessing what each function does. Luckily, the OSX version of the content manager does have the symbols intact. The problem here is that IDA does not work perfectly with Objective-C (it works, but you get a C++ish interpretation of Objective-C). I have a good idea of how the application is laid out, but there isn’t much point giving all the details (not useful). I will give some important points:

  • The Vita uses the Media Transfer Protocol, however I am not sure if it adheres completely to standards or if it uses a custom implementation
  • USB endpoint 0×2 is for input, while 0×81 is for data output, and 0×83 is for MTP event output
  • There is support for passing PSN account information to and from the Vita (password would be in plain text!), but it is unimplemented
  • CMA uses a SQLite database to index media information and licenses
Also, I’ve compiled a list of MTP operation codes for the Vita that are referenced in CMA (and therefore implemented in the Vita). Note that some of the codes are not in the standards while others are. For events, the second number is for reference with regards to the jump-table inside CMA only.


Events:
0xC104 0: RequestSendNumOfObject
0xC105 1: RequestSendObjectMetadata
0xC107 3: RequestSendObject
0xC108 4: RequestCancelTask
0xC10B 7: RequestSendHttpObjectFromURL
0xC10F 11: RequestSendObjectStatus
0xC110 12: RequestSendObjectThumb
0xC111 13: RequestDeleteObject
0xC112 14: RequestGetSettingInfo
0xC113 15: RequestSendHttpObjectPropFromURL
0xC115 17: RequestSendPartOfObject
0xC117 19: RequestOperateObject
0xC118 20: RequestGetPartOfObject
0xC119 21: RequestSendStorageSize
0xC120 28: RequestCheckExistance
0xC122 30: RequestGetTreatObject
0xC123 31: RequestSendCopyConfirmationInfo
0xC124 32: RequestSendObjectMetadataItems
0xC125 33: RequestSendNPAccountInfo
0xC801 1789: Unimplemented (seen when getting object from Vita)

Commands:
0x1001: GetDeviceInfo
0x1002: OpenSession
0x1007: GetObjectHandles
0x1008: GetObjectInfo
0x1009: GetObject
0x100C: SendObjectInfo
0x100D: SendObject
0x101B: GetPartialObject
0x9511: GetVitaInfo
0x9513: SendNumOfObject
0x9514: GetBrowseInfo
0x9515: SendObjectMetadata
0x9516: SendObjectThumb
0x9518: ReportResult
0x951C: SendInitiatorInfo
0x951F: GetUrl
0x9520: SendHttpObjectFromURL
0x9523: SendNPAccountInfo
0x9524: GetSettingInfo
0x9528: SendObjectStatus
0x9529: SendHttpObjectPropFromUR
0x952A: SendHostStatus
0x952B: SendPartOfObject (?)
0x952C: SendPartOfObject (?)
0x952E: OperateObject
0x952F: GetPartOfObject
0x9533: SendStorageSize
0x9534: GetTreatObject
0x9535: SendCopyConfirmationInfo (?)
0x9536: SendObjectMetadataItems
0x9537: SendCopyConfirmationInfo (?)
0x9538: KeepAlive
0x9802: ?
0x9803: GetObjectPropValue
0x9805: GetObjectPropList

Response:
0x2001: OK
0x2002: GeneralError
0x2006: ParameterNotSupported
0x2007: IncompleteTransfer
0x200C: StoreFull
0x200D: ObjectWriteProtected
0x2013: StoreNotAvailable
0x201D: InvalidParameter
0xA002: ?
0xA003: ?
0xA004: ?
0xA00A: ?
0xA00D: ?
0xA008: ?
0xA010: ?
0xA012: ?
0xA017: ?
0xA018: ?
0xA01B: ?
0xA01C: ?
0xA01F: ?
0xA020: ?
0xA027: ?

Data Types:
0xDC01: StorageID
0xDC02: ObjectFormat
0xDC03: ProtectionStatus
0xDC04: ObjectSize
0xDC05: AssociationType
0xDC07: ObjectFileName
0xDC08: DateCreated
0xDC09: DateModified
0xDC0A: Keywords
0xDC0B: ParentObject
0xDC0C: AllowedFolderContents
0xDC0D: Hidden
0xDC0E: SystemObject
0xDC41: PersistentUniqueObjectIdentifier
0xDC42: SyncID
0xDC43: PropertyBag
0xDC44: Name
0xDC45: CreatedBy
0xDC46: Artist

Object Formats:
0x3000: Undefined
0x3001: Association
0x3008: WAV
0x3009: MP3
0x3801: EXIF/JPEG
0x3804: BMP
0x3806: UndefinedReserved
0x380A: PICT
0x380B: PNG
0xB007: PSPGame
0xB00A: PSPSave
0xB014: VitaGame
0xB400: ?
0xB411: MNV
0xB984: MNV2
0xB982: MP4/MGV/M4V/MNV3

USB packets

I’ve also captured the USB packets for initializing the device (from device plug-in to Vita displaying the content menu) and gave my best interpretation of it. First line is PC to Vita packet or Vita to PC packet

, followed by packets captured by VMWare running Windows 7, followed by the same action on OSX (dumped from memory using GDB on CMA, not from capturing USB packets), followed by my interpretation of what the packet does (question mark means not sure). EDIT: Some of my comments in the log I know are wrong now.

Next time

I’m hoping to decode these packets and implement them using libusb. I hope Sony is using the MTP standard so I can also make use of libmtp. I also need to be more familiar with how the USB protocol works so I can understand the packet layout better.

EDIT: I’ve begun work on a new project to create an open source content manager for the Vita. As of this post, it can init the device and tell it to show the main menu.

One more thing: custom recovery kernel for Kindle 3

I didn’t plan to do any more Kindle stuff for a while, but when I made a recovery kernel (prevents your Kindle from bricking) for the Kindle 2/DX as part of my 3.X installer, many asked for a similar protective thing on newer Kindles. Well, here it is.

For now it’s just a kernel with recovery features (export entire filesystem without password or serial port and install custom recovery packages), but maybe if I have the time, one day, I will make it a full custom kernel with additional features or something.

Kindle 3.2.1 Jailbreak

UPDATE: Serge A. Levin has kindly modified my “temporary” jailbreak into a more permanent solution. The information below is now considered old and should be disregarded. Link to jailbreak for all devices on all versions.

 

So I never intended to release a jailbreak for Kindle 3.2.1 because 1) people who got a discount for their Kindles should stick by their commitment and keep the ads and 2) this was an update made purely to disable jailbreaks, so there are no new features. However, from what I heard, more and more people are receiving 3.2.1 as stock firmware (not just ad-supported Kindles) and that people who exchanged their broken Kindles also have 3.2.1. I don’t want to reveal the exploit I found yet (I’m saving it for the next big update), but thankfully, after half an hour of digging, I’ve found another glitch that I can use. The bad news is that this isn’t an “easy one click” jailbreak, it will actually take some effort as some precise timing needs to be correct in order to work.

Technical Details

What is this new glitch you ask? It’s pretty simple and pretty stupid and I feel almost embarrassed to use it (that’s why I’m not even using the word exploit). First of all, the last bug I found was fixed by a regex name check that prevent spaces in names. Now, whenever the Kindle gets an update, before doing anything, it looks for the signature of every file in the update (minus the signature files themselves). They do this by using the “find” command to get a file list and piping the output to “read” where “read” feeds each data (separated by a whitespace) into the signature check function where the function proceeds to use OpenSSL to check the signature. Simple enough. Well, what I want to do is make the signature check ignore a file, and to do it, I make a blank file called “\” (literally a backslash). Now it’s hard to explain what happens, so I’ll show you.

Here’s the output of the find command usually:

$ find /tmp/update

/tmp/update/file.ext

/tmp/update/file2.ext

Now, when I insert my slash-file:

$ find /tmp/update

/tmp/update/file.ext

/tmp/update//tmp/update/file2.ext

What happened? The backslash is used in Linux as an escape character. Basically it says to treat the next character as not-special. Remember that “read” splits the data to be read using whitespace (in this case a new line character), so by escaping the whitespace, I can get the system to ignore /tmp/update/file2.ext, and instead get it to read /tmp/update/tmp/update/file2.ext. In that file, I will include an already signed file from an old Amazon update, and when the updater runs, it ignores the extra files and reads the unsigned file. But we’re not done yet. Amazon doesn’t extract the update to a set folder, it extracts it to /tmp/.update-tmp.$$ where $$ means the process id of the script running. This can be any number from 1 to 32768. So what’s the elegant solution to this problem? I don’t know yet. Until someone can come up with a better idea, I’m going to include PIDs 5000-7000. From my tests, if you run it immediately after a reboot, it will be 64xx, so it’s a test of how bad you want to jailbreak ;)

Installation

Since this jailbreak is time and luck based, I’ve included very detailed directions on the exact timing for doing things in the readme. I suggest reading over the directions before starting, because timing is everything. It works only in a certain window of time after startup, so if it doesn’t work you need to restart and try again. If it doesn’t work after three or more tries, it’s mostly my fault as I only tested it with a Kindle 2 so the timing might be different on the Kindle 3. If you have serial port access on your Kindle 3, send me the otaup log and I’ll change the pid set.

Download

Since this is a temporary fix, I’m not going to add this to my projects list.

Download source and binaries here

EDIT: I’ve heard from some users that you have more chance of succeeding if you don’t have any books to load. So, before doing anything, rename the documents folder to documents.bak and the system folder to system.bak, install the jailbreak, and rename everything back. This should allow more chance of succeeding.

EDIT 2: Some people report turning the wireless off before starting also increases success rates.

Recovering a formatted or corrupt Kindle 2

One day, while playing around with a Kindle 2, I accidentally deleted the /lib folder. Oops. Now, no command beyond “ls” and “rm” work. If this was a computer, I could have simply inserted a installation DVD and copied the files over, but this was an eBook reader, and I was in for a world of pain. This was a month ago, and I’ve finally recovered the Kindle. I’m posting what I did online to save anyone else who’s in the same boat a ton of time. This tutorial is only designed for the Kindle 2, but it MAY work for the DX. It will NOT work for the Kindle 3, but directions should be similar.

 

First

If you’ve think you “bricked” your Kindle, don’t panic yet. There could be a easy solution. Chances are, if you can see the startup progress bar loading, the solution should be easier (although I can’t tell you exactly what your problem is). I would follow Amazon’s troubleshooting directions first. Only proceed if you are absolutely sure nothing else can be done.

Overview

Here’s what you’ll need

  1. TTL to RS232 or USB connector. I used this one. For that, use the jumper on pin 1 and 2 on the side (with the three pins, pin 1 is towards the USB port). Connect Kindle Tx -> Tx, Rx -> Rx, GND -> GND, VDD -> VDD
  2. Windows with HyperTerminal (I tried Kermit on Linux, but it couldn’t send files. HyperTerminal is the only program I’ve tested that works sending files to the Kindle)
  3. Linux or Unix-based computer with “dd” and “ssh”
  4. My custom recovery kernel which allows jailbreak signed recovery packages and exporting MMC0 without a password. If you want to know how I’ve made it in technical details, see the appendix.

Here’s what we’ll be doing:

  1. Attaching the recovery port
  2. Flashing the custom patched recovery kernel
  3. Obtaining a backup of Kindle system files
  4. Restoring your Kindle

Attaching the recovery port

First open up the Kindle 2 to reveal the PCB board. You should remove both the metal casing and the white plastic with all the screws. On the top, to the left of the headphone jack, you should see four pads labeled J4. Either solder (recommended) or tape (make sure it isn’t lose!) four wires to these pads. The order of these ports (left to right, where left is towards the volume switch) are: VDD, Rx, Tx, GND. Connect these lines to your TTL adapter and connect the adapter to your computer.

Flashing the custom patched recovery kernel

Open up HyperTerminal, and connect to your adapter. Make sure to click “Configure” and fill in the settings. The settings are: BPS: 115200, Data bits: 8, Parity: none, Stop bits: 1, Flow control: none. Then, restart your Kindle either by removing & reconnecting the battery, holding the sleep switch for 30 seconds, or tapping the reset switch on the PCB. Press Enter when text pops up in HyperTerminal. You only have one second, so be quick. In uBook, type in “run prg_kernel_serial” (make sure to type fast or uBoot will timeout). Then right click on the text, and choose “Send File”. Under protocol, choose Ymodem-G and for the file, select my custom kernel. Wait a few minutes for it to upload and install, then type in “bootm 0xa0060000″ to boot the kernel. The Kindle has two kernels that it alternates on each boot, so if you want to use my recovery kernel, you need to either flash the other kernel also or type in “bootm 0xa0060000″ into uboot on startup. Hold down Enter either on your computer or on the Kindle to enter the recovery menu. The recovery menu times out in 10 seconds, so you need to be quick. First type “I” to recreate all the partitions, then type “3″ to export the MMC. Again, these can be typed from either your keyboard in HyperTerminal, or the Kindle keypad. If you do not have access to HyperTerminal because you are in Linux restoring, you can get back here by holding Enter on the Kindle keypad and pressing 3 on the recovery menu.

Obtaining a backup of Kindle system files

Let’s put your broken Kindle aside. You need a working copy of Kindle’s system files. I cannot provide this for legal reasons, but if you obtain another Kindle 2 (preferably the same model and version as your broken one, but others MAY work [not Kindle 3 though... yet]), jailbreak it and install the usbNetwork hack for SSH access. Make sure that Kindle has at least 500MB of free space on the FAT partition to store the backup image. Once you SSH’d into the working Kindle (there are tons of tutorials around on this), issue the following command:

dd if=/dev/mmcblk0p1 of=/mnt/us/rootfs.img bs=1024

Note that this will only make a copy of the OS files. All personal information, passwords, books, etc are not copied. You can tell your friend that. This may take five to fifteen minutes to run, but when the command returns with the blocks written, you can disable usbNetwork and enable USB storage again. Copy the rootfs.img file over to your recovery computer and prepare to restore.

Restoring your Kindle

Back to your broken Kindle. You need to reformat the root and copy over the backup files. I moved the Kindle over to a Linux computer because it is easier. You can also use OSX or maybe even cygwin, but I haven’t tested. In shell, type in the following commands:

sudo su # Become root, so you don’t need to sudo everything

fdisk -l # Look for your Kindle’s identifier, it should be something like /dev/sdc, it should be a 2GB drive with 4 partitions. I will use /dev/sdX to represent this drive

mkfs.ext3 /dev/sdX2 # Make a ext3 partition for /var/local

dd if=/path/to/rootfs.img of=/dev/sdX1 bs=1MiB # This will take a long time to finish

Note that an alternative method is to gzip rootfs.img and place it into a recovery package created using kindle_update_tool.py, but I’ll leave that as an exercise for the reader.

Appendix

So, what is in the magical Kindle recovery kernel? It’s actually just a regular Kindle kernel recompiled with a modified initramfs with a patched recovery script. Using the regular kernel, you’ll run into two difficulties when trying to recover. First, if you press 3 to export MMC0, you’ll get a password prompt. Good luck brute forcing it. Second, if you build a custom recovery package using kindle_update_tool.py m –k2 –sign –fb, it will not work because of signature checks. What I did was patch the two checks.

First, I extracted the recovery-utils file by gunzipping uImage (with the extra stuff stripped out), and gunzipped initramfs.cpio from that. Then I extracted initramfs.cpio and found recovery-utils under /bin.

Next, the easy part is patching the updater package signature checks. What I did is extract the updater RSA public key file from the Kindle, found under /etc/uks and used OpenSSL to extract the public key from it (n and e). Then I opened recovery-utils with a hex editor, searched for the public key, and replaced it with the jailbreak key (found in kindle_update_tool.py).

Finally, the challenging part was to patch the password check from export MMC0. First I opened recovery-utils with IDA Pro. Then I located the check_pass function. I worked backwards from that and saw it was called from loc_94A8. Here’s a snippet of the check along with my interpretation of what it does:

BL check_pass # Call the check_pass function

CMP R0, #0 # check_pass sets register R0 with the return value, we will check if R0 equals 0×0

BEQ loc_9604 # If the previous instruction is true, then password check has failed

LDR R0, =aDevMmcblk0 ; “/dev/mmcblk0″ # We did not jump out, so CMP R0, #0 is false

BL storage_export # Call this function

It’s always easy to patch the least amount of instructions with the least amount of changes, so this is what I did. (Note that IDA Pro doesn’t allow editing instructions directly, so I have to find the machine code in hex to know what to replace. Luckily, I have tons to instructions to look at and see what their corresponding machine codes are).

NOP # Instead of calling check_pass, I did MOV R0, R0 which is the same as NOP

CMN R0, R0 # Negative compare R0 with itself. Basically, always return false.

… rest is the same

Now, I saved the file and luckily, it was the same size. So I didn’t have to recreate the initramfs.cpio, I just replaced the file inside with my hex editor (note that cpio files do not have checksum checks unlike tar files). I copied this to the kernel source folder and compiled the kernel. Lucky for you, I have already done all of this so you don’t have to.

Compiling the Linux kernel for Amazon Kindle

So, I recently bought a Kindle 2. As usual, the minute it arrived, I ripped it apart, poked every chip, and then started to reverse engineer the damn thing. Wait. I didn’t have to! I found this out days late, after messing with IDA Pro. Amazon has generously released most of the back end code for the Kindle as open source. (The front end, aka the stuff you see, is written in Java and we might get to that another day). So I decided to compile my own Kindle kernel. Why? Why not. Here’s how:

Part 1: Prerequisites

  • Get a root shell of your Kindle. If you don’t know, Google “usbNetworking”
  • A Linux computer for compiling code
  • Amazon’s sources for your version of the Kindle: http://www.amazon.com/gp/help/customer/display.html?nodeId=200203720
  • An ARM cross-compiler. You can compile Amazon’s code, or if you’re lazy, use CodeSourcery’s precompiled toolchain: http://www.codesourcery.com/sgpp/lite/arm
  • The following packages, get them from your distro’s repo: libncurses-dev (for menuconfig), uboot-mkimage (for making the kernel image), and module-init-tools (depmod)

Part 2: Compiling the kernel

  1. Extract the source to anywhere. If you can’t decide, use “~/src/kernel/” and “cd” to the source files.
  2. Now, you need to configure for the Kindle, type “make mario_mx_defconfig
  3. Edit the “.config” file and look for the line that starts with “CONFIG_INITRAMFS_SOURCE“. We don’t need that, delete that line or comment (#) it out.
  4. Here’s the part were you make all your modifications to the kernel. You might want to do “make menuconfig” and add extra drivers/modules. I’ll wait while you do that.
  5. Back? Let’s do the actual compiling. Type the following: “make ARCH=arm CROSS_COMPILE=~/CodeSourcery/Sourcery_G++_Lite/bin/arm-none-linux-gnueabi- uImage”. This will make the kernel image. I assume you installed CodeSourcery’s cross compiler to your home folder (default). If your cross compiler is elsewhere, change the command to match it.
  6. Compile the modules into a compressed TAR archive (for easy moving to the kindle): “make ARCH=arm CROSS_COMPILE=~/CodeSourcery/Sourcery_G++_Lite/bin/arm-none-linux-gnueabi- targz-pkg” (again, if your cross compiler is installed to a different location, change it).
  7. For some reason, depmod refuses to run with the compile script, so we’re going to do it manually. Do the following “depmod -ae -F System.map -b tar-install -r 2.6.22.19-lab126 -n > modules.dep” Change 2.6.22.19-lab126 to your compiled kernel version.
  8. Open modules.dep up with a text editor and do a search & replace. Replace all instances of “kernel/” with “/lib/modules/2.6.22.19-lab126/kernel/” (again, use your version string). I’m not sure this is needed, but better safe then brick.
  9. Now copy arch/arm/boot/uImage, linux-2.6.22.19-lab126.tar.gz (or whatever your version is), and modules.dep to an easy to access location.

Part 3: Installing on Kindle

  1. Connect the Kindle to your computer, and open up the storage device. Copy the three files you moved from the previous part to your Kindle via USB.
  2. This part is mostly commands, so get a root shell to your Kindle, and do the following commands line by line. Again, anywhere the version string “2.6.22.19-lab126” is used, change it to your kernel’s version. Explanation follows.

mv /mnt/us/linux-2.6.22.19-lab126.tar.gz /mnt/us/modules.dep /mnt/us/uImage /tmp

mv /lib/modules /lib/modules.old

cd /tmp & tar xvzf /tmp/linux-2.6.22.19-lab126.tar.gz

mv lib/modules /lib/

chmod 644 modules.dep

mv modules.dep /lib/modules/2.6.22.19-lab126/

/test/flashtools/update-kernel-both uImage

sync

shutdown -r now

Wow, that’s a lot of commands. What did that do? Well, line by line:

  1. Move the files we compiled to the temp folder. That way, we don’t have to clean up.
  2. Back up the old kernel modules
  3. Go to the temp folder and untar the modules
  4. Install the modules
  5. Correct the permissions for the modules.dep file (in case something happened after copying from your computer)
  6. Move the module dependencies list to it’s correct folder.
  7. Flash the kernel (I don’t know why it has to be flashed twice to two different partitions, but if you don’t, it won’t load, maybe sig checks?)
  8. Make sure everything is finished writing
  9. Reboot