tag:blogger.com,1999:blog-38153115364580727702024-03-14T07:07:54.974+01:00Reversing EverythingYet another reverse engineering blogIgor Skochinskyhttp://www.blogger.com/profile/17257295611554526824noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-3815311536458072770.post-817475665413819512009-03-10T02:30:00.001+01:002009-03-10T02:30:38.497+01:00Kindle 2 tidbits<p>I’ve been a bit busy recently and couldn’t follow my favorite ebook forum <a href="www.mobileread.com">Mobileread.com</a> as closely as I wanted. Also, it seems to have exploded with the release of Kindle 2. I don’t have the device myself and don’t plan to buy it, but I did notice a few things when skimming the forums.</p> <p>1) Firmware updates <br />Apparently Amazon didn’t change the obfuscation for the firmware updates and an enterprising person <a href="http://www.mobileread.com/forums/showpost.php?p=380345&postcount=53">patched</a> my update maker for K2 to make an “update” which sets up a custom screensaver (apparently the K1 shortcut have been disabled).</p> <p>2) USB network <br />Apparently K2 includes a USBnet module which <a href="http://blog.fsck.com/2009/03/tethering-your-kindle.html">can be enabled</a> with a debug command. This allows, for example, to use a PC internet connection instead of Whispernet, or to connect to services running on the Kindle. <a href="http://blog.fsck.com/2009/03/a-productive-evening-so-far.html">Telnet</a> is possible, but it needs to be installed on the device first.</p> <p>3) Kindle for iPhone <br />Amazon released an iPhone application, and it is now possible use an iPhone or iPod touch instead of Kindle to buy and read ebooks from Amazon. Someone was quick to discover that <a href="http://www.mobileread.com/forums/showpost.php?p=379552&postcount=127">a small change</a> in kindlepid.py allows one to produce a PID for the iPhone and read library books (or remove DRM from purchased books) the same way as with Kindle. A few days later Amazon <a href="http://www.mobileread.com/forums/showthread.php?t=41278">removed serial numbers</a> from the “Manage my Kindle” page, probably to try closing this “hole”. It worked for <a href="http://www.mobileread.com/forums/showpost.php?p=382204&postcount=14">about two hours</a>.</p> <p>P.S. I did find some time to work on my scripts. <br />1) Updated kindlepid.py and kindledfix.py to support iPhone serials and fix the metadata corruption problem. <a href="http://skochinsky.googlepages.com/azw-0.2.zip">Download</a>. <br />2) Made a combined Kindle firmware update tool. It can extract a firmware update or make a new one, for Kindle 1 or Kindle 2 (K2 untested). <a href="http://skochinsky.googlepages.com/k_tool-0.1.zip">Download</a>.</p> Igor Skochinskyhttp://www.blogger.com/profile/17257295611554526824noreply@blogger.com34tag:blogger.com,1999:blog-3815311536458072770.post-61285210310462577952008-12-21T00:30:00.007+01:002008-12-21T00:47:29.436+01:00PRS-700 internals and disassemblyI already <a href="http://www.mobileread.com/forums/showthread.php?t=31661">knew a bit</a> about PRS-700 internals from the sources published by Sony, but looking inside allowed me to confirm guesses and find out some new things. So what's new in PRS-700?<br /><br />The main change is the CPU - Sony switched from iMXL to iMX31L. It is much faster (up to 532MHz instead of 200MHz) and has an ARM11 core (with ARMv6 instruction set) versus ARM9 in iMXL. It also includes USB2.0 OTG controller and SDHC/MS controllers, which allowed Sony to get rid of separate USB and flash card controller chips, though they did have to add an NXP ISP1504 USB tranciever.<br />Another chip they dumped is the 2MB NOR flash which housed the bootloader and some other rarely updated info. Now everything is stored on the NAND flash, which doubled in size (512MB instead of 256MB). RAM size was also doubled to 128MB.<br />The E-Ink controller is now Epson/E-Ink's "Broadsheet" S1D13521 (was E-Ink's Metronome), which has its own separate 8MB of RAM for extra display speed. Asahi Kasei DAC got replaced by Wolfson's WM8350 codec, which also includes power management, battery control and real-time clock. The sub-CPU which handles keys and touch screen is now a 16-bit Renesas R8C/2A, replacing the 8-bit H8/38004.<br />On software side, Linux kernel was upgraded to 2.6.23 (compiled with gcc 4.2) from 2.4.17 (gcc 2.95.3), and glibc got replaced by uClibc.<br /><br />See my <a href="http://www.flickr.com/photos/21729510@N03/sets/72157611324679087/">Flickr gallery</a> for step-by-step PRS-700 disassembly guide. It was a bit trickier than PRS-505, so take care. When assembling, make sure there is nothing between E-Ink and touch screen, any foreign particles stand out really good when you turn on the built-in light.Igor Skochinskyhttp://www.blogger.com/profile/17257295611554526824noreply@blogger.com5tag:blogger.com,1999:blog-3815311536458072770.post-76260641619507654522007-12-21T16:54:00.000+01:002007-12-21T17:15:01.398+01:00Hacking the Kindle part 3: root shell and runtime system<H2>Root Shell</H2><br /><br />After I downloaded and extracted the root fs image, I quickly ran the /etc/shadow file though John the Ripper. In a moment it displayed the root password: "fiona" (which is the codename for the Kindle, by the way). Alas, it didn't work when I tried entering into console. Also, adding "init=/bin/sh" or "single" to the kernel boot arguments didn't work either.<br />So I started to poke around with the firmware update and after some time was able to run a script which mounted the read-write part of root filesystem and dumped the /etc/shadow from it. Unsurprisingly, it had a different password hash. Apparently the root password is changed somewhere before shipping to the end user. So I quickly adapted the script to replace the shadow file on the device with the original one.<br />You can find that implementation in this update maker zip.<br /><a href="http://skochinsky.googlepages.com/kindle_update_maker-0.1.zip">kindle_update_maker-0.1.zip</a><br /><br />After replacing the shadow file and a reboot, I was able to get in.<br /><br />Output of some commands.<br /><pre class="terminal" style="border: 1px solid rgb(164, 185, 127); overflow: auto; width: 600px; height: 250px;" onclick=""><br />[root@kindle root]#ls -la /<br />drwxr-xr-x 2 root root 592 Oct 30 2007 bin<br />drwxr-xr-x 1 root root 0 Jan 1 00:00 dev<br />lrwxrwxrwx 1 root root 7 Oct 30 2007 etc -> opt/etc<br />drwxr-xr-x 2 root root 3 Oct 30 2007 home<br />drwxr-xr-x 2 root root 3 Oct 30 2007 initrd<br />drwxr-xr-x 2 root root 586 Oct 30 2007 lib<br />lrwxrwxrwx 1 root root 11 Oct 30 2007 linuxrc -> bin/busybox<br />drwxr-xr-x 5 root root 34 Oct 30 2007 mnt<br />drwxr-xr-x 10 root root 1024 Nov 5 2007 opt<br />dr-xr-xr-x 101 root root 0 Jan 1 15:42 proc<br />drwxr-xr-x 2 root root 506 Oct 30 2007 sbin<br />drwxr-xr-x 10 root root 0 Jan 1 15:42 sys<br />drwxrwxrwx 5 root root 0 Jan 1 15:44 tmp<br />drwxr-xr-x 10 root root 95 Oct 30 2007 usr<br />drwxr-xr-x 2 root root 55 Oct 30 2007 var<br /><br />[root@kindle root]# mount<br />devfs on /dev type devfs (rw)<br />/dev/bml0/6 on / type squashfs (ro)<br />/dev/stl0/8 on /opt type ext3 (rw,sync,noatime,nodiratime)<br />/proc on /proc type proc (rw,nodiratime)<br />sysfs on /sys type sysfs (rw)<br />devfs on /dev type devfs (rw)<br />usbdevfs on /proc/bus/usb type usbdevfs (rw)<br />devpts on /dev/pts type devpts (rw)<br />tmpfs on /tmp type tmpfs (rw)<br />/dev/bml0/7 on /mnt/dc type squashfs (ro)<br /><br />[root@kindle root]# ps -A f<br /> PID TTY STAT TIME COMMAND<br /> 1 ? S 0:01 [swapper]<br /> 2 ? SN 0:00 [ksoftirqd/0]<br /> 3 ? S< 0:00 [events/0]<br /> 4 ? S< 0:00 \_ [khelper]<br /> 20 ? S< 0:10 \_ [kblockd/0]<br /> 87 ? S 0:02 \_ [pdflush]<br /> 89 ? S< 0:00 \_ [aio/0]<br /> 86 ? S 0:00 \_ [pdflush]<br /> 10 ? S 0:00 [sleepd]<br /> 33 ? S 0:00 [khubd]<br /> 88 ? S 0:00 [kswapd0]<br /> 676 ? S 0:12 [voltd]<br /> 678 ? S 0:02 [pnlcd_animate]<br /> 681 ? S 0:00 [kseriod]<br /> 710 ? S 0:00 [wantph]<br /> 709 ? S 0:00 [wanend]<br /> 721 ? S 0:00 [mmcdd]<br /> 727 ? S 0:00 [hpdetd]<br /> 740 ? Ss 0:00 init <br /> 1116 tts/2 Ss 0:00 \_ -sh<br /> 2344 tts/2 R+ 0:00 \_ ps -A f<br /> 831 ? S 0:00 [kjournald]<br /> 884 ? S 0:03 /sbin/syslogd -m 0 -b 1 -S -s 250<br /> 887 ? S 0:01 /sbin/klogd<br /> 976 ? S 0:00 [eink_fb_apt]<br /> 974 ? S 0:04 [eink_fb_udt]<br /> 975 ? S 0:00 [eink_fb_sst]<br /> 1023 ? S 0:07 [f-s-gadget]<br /> 1024 ? S 0:00 [f-s-activity]<br /> 1063 ? S 0:00 [wdtpmd]<br /> 1071 ? S 0:00 /usr/sbin/watchdogd -k 9 -t 30<br /> 1079 ? S 0:00 /usr/sbin/netwatchd -d 20 -t 5 -p www.amazon.com<br /> 1086 ? S 0:03 /usr/sbin/nomkd -v 80 -r 44 -d 23 cvm<br /> 1092 ? S 0:00 crond -l 9 -c /etc/crontab <br /> 1097 ? S 0:00 /bin/sh /usr/sbin/tphmonitor<br /> 1101 ? S 0:00 \_ /usr/sbin/tphserver -f<br /> 1119 ? S 0:00 /bin/sh /usr/sbin/execmonitor<br /> 1128 ? S 0:00 \_ /usr/sbin/execserver<br /> 1123 ? S 0:00 /bin/sh /opt/amazon/ebook/bin/run_framework<br /> 1169 ? S 0:00 \_ /bin/sh /opt/amazon/ebook/bin/start.sh<br /> 1173 ? SL 0:18 \_ /usr/java/bin/cvm -Xmx16m -Dsun.boot.library.path=/opt/usr/java/lib:/usr/java/lib -cp :/opt/amazon/ebook/lib/MobiCore-impl.jar:/opt/amazon/ebook/lib/MobipocketCoreReader.jar:/opt/amazon/ebook/lib/ReaderSDK.jar:/opt/amazon/ebook/lib/SearchSDK.jar:/opt/amazon/ebook/lib/framework-api.jar:/opt/amazon/ebook/lib/framework-impl.jar:/opt/amazon/ebook/lib/jdbm.jar:/opt/amazon/ebook/lib/json.jar:/opt/amazon/ebook/lib/kxml2.jar:/opt/amazon/ebook/lib/xyml.jar:/opt/amazon/ebook/booklet/AudiblePlayer.jar:/opt/amazon/ebook/booklet/AudioPlayer.jar:/opt/amazon/ebook/booklet/Browser.jar:/opt/amazon/ebook/booklet/ContentManager.jar:/opt/amazon/ebook/booklet/Demo.jar:/opt/amazon/ebook/booklet/Experimental.jar:/opt/amazon/ebook/booklet/Home.jar:/opt/amazon/ebook/booklet/MobiReader.jar:/opt/amazon/ebook/booklet/PictureViewer.jar:/opt/amazon/ebook/booklet/PrefBooklet.jar:/opt/amazon/ebook/booklet/Search.jar:/opt/amazon/ebook/booklet/XymlBooklet.jar:/opt/amazon/ebook/booklet/msp.jar:/opt/usr/java/lib/libjnisystem.jar -Ddebug=1 -Dcheck_comm_stack=true -Dhttp.keepalive.timeout=60000 -Dhttp.maxConnections=16 -Dallow_demo=false -Dawt_fb_enable=0 -Dextkeyboard=false -Dconfig=/opt/amazon/ebook/config/framework-unix.conf -DENABLE_SEARCH_INDEXING_THREAD=true -Dprintdebugtime=false com.amazon.ebook.framework.Main<br /> (around 30 cvm copies skipped)<br /> 2298 ? S 0:00 [mmcqd]<br /></pre><br />As you can see, /opt is writable and so is /etc which points to it. On factory reset, the writable partition is populated from /usr/default/opt.tar.gz file.<br /><br />Here's the full listing of the filesystem: <a href="http://skochinsky.googlepages.com/list.zip">list.zip</a>.<br /><br /><H2>Bonus content</H2><br />The main GUI and most of the back-end code is written in Java. The framework is quite elaborate and can be extended with extra "booklets".<br />After spending some time investigating it with <a href="http://www.kpdus.com/jad.html">JAD</a>, I found some undocumented shortcuts, features and easter eggs. Here's a more or less complete list.<br /><br /><H3>Picture viewer</H3><br />I'm not sure why Amazon didn't make it public (maybe because paging is kinda slow), but there is a basic picture viewer in Kindle.<br />To activate it:<br />1) make a folder called "pictures" in the root of Kindle drive or SD card. Kindle also checks for "dcim" made by cameras.<br />2) put your pictures for a single "book" into a folder inside that. The subfolder name will be used as the "book" name. Supported formats are jpg, png, gif.<br />3) in Home screen press Alt-Z. A new "book" should appear. Open it to view your pictures.<br />4) In the local menu you can toggle dithering, resize to fit and full screen mode.<br /><br /><H3>Keyboard shortcuts</H3><br />Various undocumented/underdocumented keyboard shortcuts. I italicized most interesting ones.<br /><br /><H4>Global keys</H4><br /> <b>Alt-Shift-R</b> reboot Kindle<br /> <b>Alt-Shift-.</b> restart GUI<br /> <b>Alt-Shift-G</b> <i>make screenshot</i><br /> due to an implementation bug, screenshots can only be stored on SD card, not the main storage. A gif file is saved in the card root.<br /> <b>Shift-Sym</b> start demo<br /> Enabled only if allow_demo=true is passed on the Java commandline. Needs a special demo script present on the SD card.<br /><br /><H4>Home</H4><br /> <b>Alt-Shift-M</b> <i>Minesweeper</i><br /> <b>Alt-Z</b> rescan picture directories<br /> <b>Alt-T</b> show time<br /><br /><H4>Reader</H4><br /> <b>Alt-B</b> toggle bookmark<br /> <b>Alt-T</b> spell out time<br /> <b>Alt-0</b> enable/disable slideshow<br /> <b>Alt-1</b> <i>start slideshow</i> (if enabled)<br /> <b>Alt-2</b> stop slidehow<br /> <b>Alt-PageForward/PageBackward</b> go to next/prev annotation or one "chunk" (1/20th of a book) forward or backward<br /><br /><H4>Settings</H4> <br /> <b>411</b> show diagnostics data<br /> <b>511</b> run loopback call test<br /> <b>611</b> diagnostic data service call<br /> c/e/s<br /> <b>126</b> <i>Lab126 team members</i><br /><br /><H4>Font List</H4><br /> <b>J</b> <i>show/hide justification options</i><br /><br /><H4>Picture viewer</H4><br /> <b>Alt-Shift-0</b> <i>set current picture as screensaver</i><br /> <b>F</b> toggle fullscreen mode<br /><br /><H4>Minesweeper</H4><br /> <b>I,J,K,L</b> up,left,down,right<br /> <b>M</b> mark mine<br /> <b>R</b> restart<br /> <b>Space</b> open cell<br /> <b>Scroll</b> move cursor up/down<br /> <b>Alt-Scroll</b> move cursor left/right<br /> <b>H</b> return to Home screen<br /><br /><H4>Text input</H4><br /> <b>Alt-Backspace</b> clear all<br /> <b>Alt-H/Alt-J</b> move cursor<br /> (the following don't work in search field for some reason)<br /> <b>Alt-6</b> ?<br /> <b>Alt-7</b> ,<br /> <b>Alt-8</b> :<br /> <b>Alt-9</b> "<br /> <b>Alt-0</b> '<br /><br /><H4>Browser</H4><br /> It seems there is a location capability (GPS?) in the CDMA module. I cannot check it as I'm not in USA but the following shortcuts are programmed inside the browser.<br /> <b>Alt-1</b> show current location in google maps<br /> <b>Alt-2</b> find gas station nearby<br /> <b>Alt-3</b> find restaurants nearby<br /> <b>Alt-4</b> <reserved><br /> <b>Alt-5</b> find custom keyword nearby<br /> <b>Alt-D</b> dump debug info to the log and toggle highlight default item<br /> <b>Alt-Z</b> toggle zone drawing and show log<br /><br /><H4>Audio Player</H4><br /> <b>Alt-F</b> next<br /> <b>Alt-P</b> play/stop<br /><br /><H3>Search commands</H3><br />These command work in the search field. You can enter only beginning of the command if that's enough for it to be unique.<br /><br />Public commands (always available)<br /><blockquote><br />@help<br />@web<br />@wiki/@wikipedia<br />@store<br />@time<br /></blockquote><br />Semiprivate (available but not mentioned in @help)<br /><blockquote><br />;dumpMessages dump current debug log into the "documents" directory<br />;debugOn set log level=2 and enable private commands<br />;debugOff set log level=1 and disable private commands<br /></blockquote><br />Private commands<br /><b>Note</b>: following commands are clearly not intended for end users. Some of them may damage your Kindle and void your warranty. Enter at your own risk.<br /><blockquote><br />`help list private commands<br />`7777 set version to TOPmk-xyz-77770 (to disable OTA updates?)<br />`voltLog <1|0> enable/disable voltage table debug<br />`batteryLoggingDelay <delay> set battery logging delay (in seconds)<br />`pppStop close WAN PPP connection<br />`disableIndexing<br />`logOpenFiles<br />`startIndexing<br />`dumpBattery<br />`indexStatus<br />`compliance<br />`einkAdjustments <param><br />`allocate [MB]<br />`log611<br />`reloadContentRoster<br />`indexForever<br />`downloadIndex<br />`consumeMemory<br />`terminal<br />`checkForUpdate<br />`applyUpdate<br />`stopIndexing<br />`processNowNow<br />`processTodo<br />`countUnmergedDownloadedIndexes<br />`dumpIndexStats<br />`memInfo<br /></blockquote>Igor Skochinskyhttp://www.blogger.com/profile/17257295611554526824noreply@blogger.com79tag:blogger.com,1999:blog-3815311536458072770.post-64120379480556543432007-12-20T13:44:00.000+01:002007-12-20T15:41:27.243+01:00Hacking the Kindle part 2: bootloader and firmware updates<H2>Bootloader</H2><br /><br />The Kindle uses <a href="http://www.denx.de/wiki/UBoot">Das U-Boot</a> bootloader. To break into the interactive shell, just press any key right afer reset.<br />"help" gives a list of available commands<br /><pre class="terminal" style="border: 1px solid rgb(164, 185, 127); overflow: auto; width: 600px; height: 250px;" onclick=""><br />KINDLE> help<br />? - alias for 'help'<br />badblocks - print OneNAND bad block info<br />base - print or set address offset<br />bbm - BBM sub-system<br />bdinfo - print Board Info structure<br />boot - boot default, i.e., run 'bootcmd'<br />bootd - boot default, i.e., run 'bootcmd'<br />bootf - boot from various options<br />bootm - boot application image from memory<br />cmp - memory compare<br />coninfo - print console devices and information<br />cp - memory copy<br />crc32 - checksum calculation<br />dcache - enable or disable data cache<br />diags - execute the User Diagnostics from OneNAND<br />dsleep - sleep USB device controller<br />dwake - wake USB device controller<br />echo - echo args to console<br />erase - erase FLASH memory<br />exit - exit script<br />factory - string [lock] [LLL_RR_PP]<br />fatinfo - print information about filesystem<br />fatload - load binary file from a dos filesystem<br />fatls - list files in a directory (default /)<br />fb - framebuffer subsystem<br />flinfo - print FLASH memory information<br />gain - displays/sets the gain value<br />go - start application at address 'addr'<br />help - print online help<br />hsuspend - suspend the 1761 USB host controller<br />hwake - wake USB host controller<br />icache - enable or disable instruction cache<br />iminfo - print header information for application image<br />itest - return true/false on integer compare<br />keys - prints out hex values from device keyboard until console key is pressed<br />kindle - print info about Kindle's revision<br />load - load OneNAND page into DataRAM<br />loadb - load binary file over serial line (kermit mode)<br />loads - load S-Record file over serial line<br />loop - infinite loop on address range<br />loopw - infinite write loop on address range<br />mbboot - boot bootloader from MMC/SC card<br />md - memory display<br />mdc - memory display cyclic<br />mkboot - boot kernel & initrd from MMC/SD card<br />mm - memory modify (auto-incrementing)<br />mmcinit - init mmc card<br />mtest - simple RAM test<br />mw - memory write (fill)<br />mwc - memory write cyclic<br />nand - NAND sub-system<br />nboot - boot from NAND device<br />nm - memory modify (constant address)<br />ohms - calculates board resistance<br />onenand - print OneNAND register info<br />opamp - displays/sets the op-amp offset value<br />otp - dump/read/write OneNAND OTP<br />printenv- print environment variables<br />protect - enable or disable FLASH write protection<br />reboot - alias of reset to match kernel<br />reset - perform RESET of the CPU<br />run - run commands in an environment variable<br />rve - displays/sets the rve (reference voltage error) value<br />saveenv - save environment variables to persistent storage<br />serial - set/display board serial number in OTP<br />setenv - set environment variables<br />sleep - delay execution for some time<br />snuz - put PXA to sleep<br />test - minimal test like /bin/sh<br />update - update sub-system (updates images from MMC/SD card to flash)<br />usb_init - init USB host controller<br />version - print monitor version<br />write - write DataRAM buffer to OneNAND page<br /></pre><br />Let's see what we can do with bbm command<br /><pre class="terminal" style="border: 1px solid rgb(164, 185, 127); overflow: auto; width: 600px; height: 250px;" onclick=""><br />KINDLE> ? bbm<br />bbm format<br /> - format device<br />bbm open<br /> - open device<br />bbm eraseall<br /> - erase all blocks<br />bbm erase 'start' 'end'<br /> - erase blocks from 'start' to 'end'<br />bbm load image 'id' ['start']<br /> - load image from partition 'id' into RAM;<br /> image is loaded into RAM at location 0xA2000000<br /> or into 'start' if 'start' is specified (in hex)<br />bbm save image 'id' ['start'] 'size'<br /> - save image of 'size' to partition 'id';<br /> image should be loaded into RAM at 0xA2000000<br /> or into 'start' if 'start' is specified (in hex)<br /><br />- Partition Info -<br />bbm show partition<br /> - show partition information<br />bbm save partition<br /> - save partition information<br />bbm del partition<br /> - delete last partition<br />bbm add partition 'id 'attr' 'blocks'<br /> - add partition 'id' of type 'attr' and of size 'blocks'<br />KINDLE> bbm show partition<br /><< PARTITION INFORMATION >><br /> id : Bootloaders, Diagnostics (3)<br /> attr : RW (1)<br /> first_blk : 0 (0x00000000)<br /> no_blks : 12 (1.5 MB)<br /> ---------------------<br /> id : Standard Kernel (17)<br /> attr : RW (1)<br /> first_blk : 12 (0x00180000)<br /> no_blks : 12 (1.5 MB)<br /> ---------------------<br /> id : Recovery Kernel (16)<br /> attr : RW (1)<br /> first_blk : 24 (0x00300000)<br /> no_blks : 12 (1.5 MB)<br /> ---------------------<br /> id : Standard Initrd (15)<br /> attr : RW (1)<br /> first_blk : 36 (0x00480000)<br /> no_blks : 10 (1.3 MB)<br /> ---------------------<br /> id : Recovery Initrd (14)<br /> attr : RW (1)<br /> first_blk : 46 (0x005C0000)<br /> no_blks : 10 (1.3 MB)<br /> ---------------------<br /> id : Read-only Root Filesystem (8)<br /> attr : RW (1)<br /> first_blk : 56 (0x00700000)<br /> no_blks : 96 (12 MB)<br /> ---------------------<br /> id : Default Content (9)<br /> attr : RW (1)<br /> first_blk : 152 (0x01300000)<br /> no_blks : 120 (15 MB)<br /> ---------------------<br /> id : Read/Write Root Filesystem (10)<br /> attr : RW (1)<br /> first_blk : 272 (0x02200000)<br /> no_blks : 144 (18 MB)<br /> ---------------------<br /> id : Userstore (11)<br /> attr : RW (1)<br /> first_blk : 416 (0x03400000)<br /> no_blks : 1584 (198 MB)<br /> ---------------------<br /> id : Environment Variables (4)<br /> attr : RW (1)<br /> first_blk : 2000 (0x0FA00000)<br /> no_blks : 2 (256 KB)<br /> ---------------------<br /></pre><br /><br />The diagnostics U-Boot image is stored in the first partition.<br />There are two kernels, standard and recovery with corresponding ramdisks. Recovery kernel is used for firmware update.<br />There is a read-only root filesystem and read-write part. There is a partition with default content used for factory reset.<br />Then there is a userstore partition, which is visible as mass storage drive over USB.<br /><br />There were no commands to copy data from flash to SD/MMC, but I could load flash partitions into memory and dump that. <br /><pre class="terminal" style="border: 1px solid rgb(164, 185, 127); overflow: auto; width: 600px; height: 250px;" onclick=""><br />KINDLE> bbm load image 3<br />Loading partition "Bootloaders, Diagnostics" into 0xA2000000... Success<br />KINDLE> base a2000000<br />KINDLE> md.b 0 100<br />a2000000: 4e 69 63 6b ff ff ff ff ff ff ff ff ff ff ff ff Nick............<br />a2000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................<br />a2000020: 0e 00 00 ea 18 f0 9f e5 2c f0 9f e5 18 f0 9f e5 ........,.......<br />a2000030: 18 f0 9f e5 18 f0 9f e5 18 f0 9f e5 18 f0 9f e5 ................<br />a2000040: 60 00 00 a2 20 01 00 a2 80 01 00 a2 e0 01 00 a2 `... ...........<br />a2000050: 40 02 00 a2 a0 02 00 a2 00 03 00 a2 40 03 00 a2 @...........@...<br />a2000060: 00 00 0f e1 80 00 c0 e3 00 f0 29 e1 7c 00 9f e5 ..........).|...<br />a2000070: 21 0a 40 e2 02 0c 40 e2 02 0a 40 e2 0c d0 40 e2 !.@...@...@...@.<br />a2000080: 70 00 9f e5 70 10 9f e5 00 20 a0 e3 00 20 80 e5 p...p.... ... ..<br />a2000090: 04 00 80 e2 01 00 50 e1 fb ff ff 1a e6 80 00 ea ......P.........<br />a20000a0: 00 00 a0 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............<br />a20000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />a20000c0: 28 00 1f e5 18 10 90 e5 01 10 81 e3 18 10 80 e5 (...............<br />a20000d0: 10 10 90 e5 02 1b 81 e2 02 1b 81 e2 0c 10 80 e5 ................<br />a20000e0: fe ff ff ea ef be ad de ef be ad de ef be ad de ................<br />a20000f0: 00 00 00 a2 20 00 00 a2 1c 56 06 a2 98 52 4a a3 .... ....V...RJ.<br /></pre><br />(Nick probaly refers to Nick Vaccaro of Lab126, who apparently was one of the main Kindle software developers. Hi Nick!)<br /><br />Due to either my cable or inconsistent terminal settings, any dump of over 256 bytes was returning only some bytes in the beginning and some in the end. So I had to conjure up a little Python script to send dump commands in chunks of 256 bytes, parse the output and write it to a file. It took a few hours per partition, but in the end I was able to dump what I needed. In the initrd image of the recovery kernel I found scripts that performed firmware update and so I could reverse the update file format.<br /><br /><H2>Firmware updates</H2><br /><br />Firmware update can be performed both over-the-air and from the SD card or mass storage partition. <br /><br />The firmware update file should match the mask "update*.bin" and reside in the root of the userstore partition (Kindle's USB drive) or SD/MMC card. There should be only one such file present. The file consists of a header and scrambled .tar.gz file with update files.<br /><br /><pre>offset size value<br />0 4 signature (OTA: "FC02", manual: "FB01")<br />4 4 fromVersion (minimal version to update)<br />8 4 toVersion (maximal version to update)<br />0C 2 deviceCode (number in 3rd and 4th characters of the serial, i.e. 01)<br />0E 1 updateOptional (seems unused)<br />0F 1 <padding><br />10 32 scrambled md5 hash string of the tgz<br />20000 ? scrambled tgz with update files<br /></pre><br />Version value is made from the kindle version string. In my unit, it's 292-Kindle-012138 and the version value is 121380292 (12138*10000 + 292).<br /><br />The manual update doesn't check any fields except signature and md5.<br /><br />Scramble algorithm:<br /><pre>byte = rol(byte,4)^0x7A;</pre><br />Descramble:<br /><pre>byte = rol(byte^0x7A,4);</pre><br /><br />The tgz should contain a text file matching the mask "update*.dat". Its lines have the following format:<br /><pre>id md5 filename block_count display_name</pre><br /><span style="font-weight:bold;">id</span> is the ID of the flash partition to write to. I know the following numbers:<br />6 base RO fs (squashfs image)<br />7 default content (squashfs)<br /><br /><span style="font-weight:bold;">block_count</span> is the number of 128K blocks to flash (see bbm show partition output above). <br /><br />If <span style="font-weight:bold;">id</span> is 129, the file is considered a shell script and is executed.<br />If <span style="font-weight:bold;">id</span> is 128, the md5 is checked but nothing is done with the file.<br /><br />I made a small Python script to assemble an update file with all checksums calculated automagically. It will be included in the next post.<br /><br />To do a manual update, first put the update bin in the root of Kindle's flash drive or SD card. Then hold Home button while resetting the Kindle. In a while you will see the following menu:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_KFKbB1o0M_8/R2p-9u4SMZI/AAAAAAAAAA4/fEnsRr2Azos/s1600-h/image_picture_service_menu_all.GIF"><img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_KFKbB1o0M_8/R2p-9u4SMZI/AAAAAAAAAA4/fEnsRr2Azos/s400/image_picture_service_menu_all.GIF" border="0" alt="Service menu" id="BLOGGER_PHOTO_ID_5146065123245437330" /></a><br />2 "Firmware Reset" clears all user-specific data and settings and returns the Kindle to factory state. I'm not sure if it will be usable without extra initialization by Amazon technicians.<br />3 "Exit" starts normal boot process.<br />0 (not shown) starts the diagnostics bootloader. Interaction is done mostly over the console, you won't see much on the Kindle screen.<br />1 "Firmware update" starts the manual update process.Igor Skochinskyhttp://www.blogger.com/profile/17257295611554526824noreply@blogger.com9tag:blogger.com,1999:blog-3815311536458072770.post-13019865084706678582007-12-20T02:38:00.000+01:002007-12-20T03:37:41.820+01:00Hacking the Kindle part 1: getting the consoleFrom reading the <a href="http://www.amazon.com/gp/help/customer/display.html?ie=UTF8&nodeId=200203720">sources</a> published by Amazon, it was clear that Kindle has a console running at least during boot. And there was an unconnected port available from outside.<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_KFKbB1o0M_8/R2nNje4SMVI/AAAAAAAAAAY/QcwLulwLKWE/s1600-h/debug_port.png"><img style="float:none; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_KFKbB1o0M_8/R2nNje4SMVI/AAAAAAAAAAY/QcwLulwLKWE/s320/debug_port.png" border="0" alt="Debug Port" id="BLOGGER_PHOTO_ID_5145870058715754834" /></a><br />Logically, the console would be accessible there. I salvaged a flat cable with a connector from my Rio Karma dock and stripped extra conductors to bring the pin count down to 20. Next I needed a TTL-RS232 converter. I almost bought one from EBay, but then realized that I already have one in the form of a data cable for my Samsung GSM phone. I stripped the phone connector, spent some time to discover the pinout of the cable, and was ready to search for the console. With a multimeter I found grounded pins of the debug connector so I knew which ones I can skip. I then started PuTTY, set port parameters to 115200/8n1 (gleaned from source code), connected ground of the cable to the shield, and started connecting RX of the cable to every pin in order, resetting the Kindle each time. Eventually I was able to see the output of the bootloader.<br /><pre class="terminal"><br />check_recovery: shift-<r>ecover, shift-<u>pdate, shift-</> reset...<br /> normal boot...<br /><br />U-Boot 1.1.2 (Oct 29 2007 - 16:35:25)<br /><br />*** Welcome to Kindle ***<br /></pre><br />With a bit of solder I fixed it, and then did the same with the TX wire while pressing some keys on the keyboard. As I was at the login prompt at this point, once I had the correct pin I could see the echo in the terminal. Unsurprisingly, the RX pin was right next to the TX.<br />I wasn't able to solder cable to the connector without shorting (the pins are 0.5mm apart!), so in the end I removed most of the pins, soldered short wires to the removed pins and inserted those I needed back into the connector.<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_KFKbB1o0M_8/R2nQSu4SMXI/AAAAAAAAAAo/5z32UsdHc4s/s1600-h/Img0005.jpg"><img style="float:none; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_KFKbB1o0M_8/R2nQSu4SMXI/AAAAAAAAAAo/5z32UsdHc4s/s320/Img0005.jpg" border="0" alt="Connected" id="BLOGGER_PHOTO_ID_5145873069487829362" /></a><br />The final pinout:<br />12 TX (connect PC's RX here)<br />11 RX (connect PC's TX here)<br />10 GND (also 7 and 3)<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_KFKbB1o0M_8/R2nPA-4SMWI/AAAAAAAAAAg/rfsj11_c1xY/s1600-h/cable_closeup.png"><img style="float:none; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_KFKbB1o0M_8/R2nPA-4SMWI/AAAAAAAAAAg/rfsj11_c1xY/s320/cable_closeup.png" border="0" alt="Pinout" id="BLOGGER_PHOTO_ID_5145871665033523554" /></a><br /><br />There are probably JTAG pins too, but those are a bit harder to find by trial and error. Also, I don't have a JTAG cable.<br /><br />In case you want to make your own connector, you'll need:<br />1) a 20-pin 0.5mm pitch flat flex cable with a connector. Digikey seems to have <a href="http://parts.digikey.com/1/parts/35672-cable-flat-flex-4-50mm-20-pos-210200211.html">some</a>.<br />2) a TTL-RS232 or TTL-USB converter. For the former, make sure you get one that can handle 3.3V levels (i.e. MAX232 analog won't do, you'll need MAX3232 or similar). For the latter, probably any will do.Igor Skochinskyhttp://www.blogger.com/profile/17257295611554526824noreply@blogger.com14tag:blogger.com,1999:blog-3815311536458072770.post-6072381596912888772007-12-14T18:33:00.001+01:002007-12-14T18:37:14.519+01:00Sony Reader PRS-505 disassemblyI liked looking into the Reader much more than the Kindle.<br /><br /><a href="http://www.flickr.com/photos/21729510@N03/sets/72157603454047408/">Sony Reader PRS-505 disassembly</a>Igor Skochinskyhttp://www.blogger.com/profile/17257295611554526824noreply@blogger.com4tag:blogger.com,1999:blog-3815311536458072770.post-8123402535412478002007-12-14T13:27:00.000+01:002007-12-14T13:37:06.352+01:00Kindle disassembly and internalsI know that RapidRepair published <a href="http://www.rapidrepair.com/guides/amazonkindleguide/amazon-kindle-Take-Apart-Guide.htm">their guide</a> recently but I found it not detailed enough, so I tried to take many pictures when disassembling my own Kindle. I hope this will be interesting.<br /><br /><a href="http://www.flickr.com/photos/21729510@N03/sets/72157603433447881/">Disassembly with step-by-step photos</a><br /><br /><a href="http://www.flickr.com/photos/21729510@N03/sets/72157603452368174/">Detailed internals with close-ups of various chips</a><br /><br />Check photo notes for chip details.<br /><br />P.S. After I uploaded my photos, I found <a href="http://www.pcdoctor-community.com/pcdblog/2007/12/02/inside-the-amazon-kindle/">this post</a> in PC-Doctor blog. He has some notes about the chips used.Igor Skochinskyhttp://www.blogger.com/profile/17257295611554526824noreply@blogger.com1tag:blogger.com,1999:blog-3815311536458072770.post-36174406092954272632007-12-12T14:05:00.001+01:002009-03-13T04:03:07.025+01:00Mobipocket books on KindleWe've <a href="http://www.mobileread.com/forums/showthread.php?t=16244">known</a> for some time already that Amazon's AZW files are actually Mobi files, but Amazon didn't share Kindle's Mobi PID which would allow one to buy encrypted Mobi books for Kindle.<br />Well, I've discovered the algorithm used to generate the PID and was able to use it on Fictionwise, but there was another catch. AZW files have a flag set in the DRM info which is not present in books bought from other vendors. After fixing that, I could read the book on Kindle.<br /><br />Linked archive includes two Python scripts.<br /><br /><b>kindlepid.py</b> generates Mobi PID from Kindle serial number. You can then add this PID at a Mobipocket vendor site and redownload books with Kindle's PID enabled. It's possible that some vendors will refuse this PID, as it has an asterisk in place of the traditional dollar sign (Fictionwise works fine).<br /><b>kindlefix.py</b> "fixes" a Mobi book so that it can be read on Kindle. It should already include Kindle's PID (which you need to specify too). The script will output the fixed book with .azw extension.<br /><br /><a href="http://skochinsky.googlepages.com/azw-0.2.zip">Kindle Mobipocket tools <strike>0.1</strike> 0.2</a> <br /><a href="http://rapidshare.com/files/208588168/azw-0.2.zip.html">Mirror</a>Igor Skochinskyhttp://www.blogger.com/profile/17257295611554526824noreply@blogger.com141tag:blogger.com,1999:blog-3815311536458072770.post-30326180748504514452007-12-06T05:11:00.000+01:002007-12-14T13:44:15.629+01:00Kindle boot logSo the Kindle has a console running. Lots of interesting info here...<br /><pre><br />U-Boot 1.1.2 (Oct 29 2007 - 16:35:25)<br /><br />*** Welcome to Kindle ***<br /><br />U-Boot code: A3F00000 -> A3F3FA6C BSS: -> A3F77850<br /><br />REV2 Bootloader: Kindle 400 MHz REV2 Board, Revision #9<br /> Boot block version: 20070525<br /> Checksum: 0x9F132881<br /> Buildrev: 292-Kindle-012138<br /> IOC Firmware Version #63<br /><br />RAM Configuration:<br /> Bank #0: 0xA0000000 64 MB<br />Flash Configuration:<br /> Bank #0: 0x00000000 128 MB<br /> Bank #1: 0x04000000 128 MB<br />NAND Configuration:<br /> 256 MB<br />BML_Init success<br />BML_Open success<br />**************** device info *******************<br />nPgsPerBlk = 64<br />nSctsPerPg = 4<br />nNumOfUsBlks = 2002<br />*************************************************<br />bml open success<br />pi->nNumOfPartEntry: 10Success loading partition<br />load env done<br />op_amp#=65535<br />gain#=0<br />rve#=1015<br />panel#=010_01_23<br />panel#=010_01_23<br />serial#=B001BAB074999999<br />usb_force_sleep: hw_flags.disable_pdc_suspend = 0<br />waiting for CLKREADY<br />Mode reg = 0x00000000<br />soft resetting device controller<br />power switch is on<br />Update battery level: >3720mV<br />Boot battery level: >3680mV<br />Alert battery level: >3600mV<br />Current battery level: 3911mV (bootable)<br /><br />Loading partition "Standard Kernel" into 0xA2000000... Success<br />Loading partition "Standard Initrd" into 0xA2E20000... Success<br /><br />iminfo a2000000 a2e20000<br /><br />## Checking Image at a2000000 ...<br /> Image Name: Linux-2.6.10-lab126<br /> Image Type: ARM Linux Kernel Image (uncompressed)<br /> Data Size: 1236608 Bytes = 1.2 MB<br /> Load Address: a0008000<br /> Entry Point: a0008000<br /> Verifying Checksum ... OK<br /><br />## Checking Image at a2e20000 ...<br /> Image Name: initrd_fs.gz<br /> Image Type: ARM Linux RAMDisk Image (gzip compressed)<br /> Data Size: 689536 Bytes = 673.4 KB<br /> Load Address: 00000000<br /> Entry Point: 00000000<br /> Verifying Checksum ... OK<br /><br />bootm a2000000 a2e20000<br />## Booting image at a2000000 ...<br /> Image Name: Linux-2.6.10-lab126<br /> Image Type: ARM Linux Kernel Image (uncompressed)<br /> Data Size: 1236608 Bytes = 1.2 MB<br /> Load Address: a0008000<br /> Entry Point: a0008000<br /> Verifying Checksum ... OK<br />OK<br />## Loading Ramdisk Image at a2e20000 ...<br /> Image Name: initrd_fs.gz<br /> Image Type: ARM Linux RAMDisk Image (gzip compressed)<br /> Data Size: 689536 Bytes = 673.4 KB<br /> Load Address: 00000000<br /> Entry Point: 00000000<br /> Verifying Checksum ... OK<br /><br />Starting kernel ...<br /><br />Uncompressing Linux................................................................................ done, booting the kernel.<br />Linux version 2.6.10-lab126 (build@lab126-build) (gcc version 3.4.2) #1 Mon Oct 29 16:38:09 PST 2007<br />CPU: XScale-PXA255 [69052d06] revision 6 (ARMv5TE)<br />CPU: D VIVT undefined 5 cache<br />CPU: I cache: 32768 bytes, associativity 32, 32 byte lines, 32 sets<br />CPU: D cache: 32768 bytes, associativity 32, 32 byte lines, 32 sets<br />Machine: Fiona Platform<br />Fiona Board Resistance : 150 mOhms<br />Memory policy: ECC disabled, Data cache writeback<br />Memory clock: 99.53MHz (*27)<br />Run Mode clock: 398.13MHz (*4)<br />Turbo Mode clock: 398.13MHz (*1.0, inactive)<br />Built 1 zonelists<br />Kernel command line: console=ttyS2,115200n8 root=/dev/rd/0 initrd=/linuxrc rw reboot=hard<br />reserved 4096 bytes at a3fff000 for boot globals<br />reserved 122880 bytes at a3fe1000 for framebuffer<br />PID hash table entries: 512 (order: 9, 8192 bytes)<br />Console: colour dummy device 80x30<br />Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)<br />Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)<br />Memory: 64MB = 64MB total<br />Memory: 61456KB available (2070K code, 357K data, 100K init)<br />Mount-cache hash table entries: 512 (order: 0, 4096 bytes)<br />CPU: Testing write buffer coherency: ok<br />checking if image is initramfs...it isn't (no cpio magic); looks like an initrd<br />Freeing initrd memory: 673K<br />NET: Registered protocol family 16<br />Recalculated watermarks:<br /> wan: 3603 (was 3603)<br /> low: 3586 (was 3586)<br /> critical: 3536 (was 3536)<br />REV2 board detected<br />Power transition failed err=-5 for pnlcd video display class<br />SCSI subsystem initialized<br />usbcore: registered new driver usbfs<br />usbcore: registered new driver hub<br />PXA CPU frequency change support initialized<br />NetWinder Floating Point Emulator V0.97 (extended precision)<br />FPOW: Fiona Power Management Driver v0.54<br />squashfs: version 3.0 (2006/03/15) Phillip Lougher<br />devfs: 2004-01-31 Richard Gooch (rgooch@atnf.csiro.au)<br />devfs: boot_options: 0x1<br />Initializing Cryptographic API<br />WATER: Disabling IOC voltage reporting, initing our own timer...<br />Battery Voltage: 3881 mVolts (raw: 3854 mVolts)<br />V[1] : ~3881~<br />A[1] : ~181~<br />T[1] : ~26~<br />OP Amp Offset : Uninitialized<br />Op Amp Gain Correction : Uninitialized<br />Voltage Reference Correction Factor : 1015 / 1000<br />IOC: Fiona IOC Driver v1.0, IOC FW version #63<br />Battery: 3.911 Volts, 26 Degrees C, 164 mA Draw, DISCHARGING, 72%<br />PNLCD: Fiona PNLCD Driver v0.94<br />KEYBOARD: Fiona Keyboard Driver v1.0<br />ppoke driver: Major: 207 Rev. 4 Kernel v.2.6.10-lab126<br />/proc/peek initialized.<br />/proc/poke initialized.<br />ttyS0 at MMIO 0x40100000 (irq = 15) is a FFUART<br />ttyS1 at MMIO 0x41600000 (irq = 0) is a HWUART<br />ttyS2 at MMIO 0x40700000 (irq = 13) is a STUART<br />io scheduler noop registered<br />RAMDISK driver initialized: 8 RAM disks of 4096K size 1024 blocksize<br />loop: loaded (max 8 devices)<br />PPP generic driver version 2.4.2<br />wan: AnyDATA DTEV WAN module driver 0.8.4<br />i2c /dev entries driver<br />i2c_adapter i2c-0: found device 0x1a<br />Advanced Linux Sound Architecture Driver Version 1.0.6 (Sun Aug 15 07:17:53 2004 UTC).<br />soc: version 0.7 liam.girdwood@wolfsonmicro.com<br />wm8971: WM8971 audio codec 0.2.3<br />soc: WM8971 <-> pxa2xx-i2s mapping ok<br />ALSA device list:<br /> #0: WM8971 Portable Codec (SoC)<br />NET: Registered protocol family 2<br />IP: routing cache hash table of 512 buckets, 4Kbytes<br />TCP: Hash tables configured (established 4096 bind 8192)<br />NET: Registered protocol family 1<br />NET: Registered protocol family 17<br />RAMDISK: Compressed image found at block 0<br />VFS: Mounted root (ext2 filesystem).<br />Mounted devfs on /dev<br />starting initrd...<br />eink_fb: /dev/fb/0 frame buffer device, using 471K for video memory<br />eink_fb: Apollo Display Driver 1.00<br />xsr: module license 'Samsung Proprietary' taints kernel.<br />Samsung XSR Core 1.2.1-lab126-2<br />elevator: using noop as default io scheduler<br />Samsung STL 1.2.1-lab126-2<br />Samsung RFS 1.2.1-lab126-2<br />kjournald starting. Commit interval 5 seconds<br />EXT3 FS on stl8, internal journal<br />EXT3-fs: recovery complete.<br />EXT3-fs: mounted filesystem with ordered data mode.<br />starting init...<br />dosfsck 2.11-lab126 (7 Dec 2006)<br />dosfsck 2.11-lab126, 7 Dec 2006, FAT32, LFN<br />Checking we can access the last sector of the filesystem<br />Boot sector contents:<br />System ID "mkdosfs"<br />Media byte 0xf8 (hard disk)<br /> 512 bytes per logical sector<br /> 2048 bytes per cluster<br /> 32 reserved sectors<br />First FAT starts at byte 16384 (sector 32)<br /> 2 FATs, 32 bit entries<br /> 386048 bytes per FAT (= 754 sectors)<br />Root directory start at cluster 2 (arbitrary size)<br />Data area starts at byte 788480 (sector 1540)<br /> 96416 data clusters (197459968 bytes)<br />8 sectors/track, 1 heads<br /> 0 hidden sectors<br /> 387204 sectors total<br />Checking for unused clusters.<br />Checking free cluster summary.<br />/dev/stl0/9: 293 files, 7117/96416 clusters<br />mount: Mounting /dev/mmc/blk0/part1 on /mnt/mmc failed: No such file or directory<br />system: processing module dependencies<br />system: loading module pdc<br />pdc: version 1.0<br />pdc: IRQ 26<br />system: loading module usbserial<br />drivers/usb/serial/usb-serial.c: USB Serial support registered for Generic<br />usbcore: registered new driver usbserial_generic<br />usbcore: registered new driver usbserial<br />drivers/usb/serial/usb-serial.c: USB Serial Driver core v2.0<br />system: initializing eInk driver for rootfs use<br />eink_fb: /dev/fb/0 frame buffer device, using 588K for video memory<br />eink_fb: Apollo Display Driver 1.00<br />eink_fb: write_eink_which, size=50327<br />eink_fb: curr_count=0 write_size=50327<br />eink_fb: done, status=1<br />1+0 records in<br />1+0 records out<br />system: initializing random number generator<br />system: initializing USB gadget driver<br />g_file_storage gadget: controller 'pdc' not recognized<br />g_file_storage gadget: File-backed Storage Gadget, version: 28 July 2004<br />g_file_storage gadget: Number of LUNs=2<br />system: initializing audio configuration for REV2 or higher<br />system: initializing audio driver defaults<br />system: initializing network configuration<br />system: setting "conservative" processor power mode<br />system: starting processor watchdog<br />SA1100/PXA2xx Watchdog Timer: timer margin 60 sec<br />watchdogd 0.1 Copyright (C) 2007 Lab126, Inc. All rights reserved.<br />system: starting network connection watchdog<br />netwatchd 0.5 Copyright (C) 2007 Lab126, Inc. All rights reserved.<br />system: starting CVM memory watchdog<br />nomkd 0.7 Copyright (C) 2006-2007 Lab126, Inc. All rights reserved.<br />system: starting TPH monitor<br />system: starting tphserver<br />tphserver 0.2 Copyright (C) 2007 Lab126, Inc. All rights reserved.<br />system: starting booklet framework<br /><br /><br /><br />Welcome to Kindle!<br /><br />kindle login:<br /></pre>Igor Skochinskyhttp://www.blogger.com/profile/17257295611554526824noreply@blogger.com4tag:blogger.com,1999:blog-3815311536458072770.post-39115607612634835252007-11-23T00:28:00.002+01:002008-08-27T11:11:55.483+02:00Embiid PublishingShort History<br /><br />Embiid Publishing was an early e-pub company which started back in 2000. They published some midlist SF and Romance titles, most famous probably being Liaden series by Sharon Lee and Steve Miller. They offered nice prices ($5 in average), and free sampler bundles. At first their books were Windows-only, later they started to offer Rocket format and a book reader for Palm OS. In 2006 the company <a href="http://www.mobileread.com/forums/showthread.php?t=6598">closed doors</a>, leaving customers with books they could not convert.<br /><br />The Reader<br /><br />The Windows reader program could read two formats: UBK and EBK. The former was slightly scrambled but could be read by any reader. The latter was encrypted with a personalized key and could only be read by the personalized reader executable downloadable with the first purchase.<br />The Reader was written in Delphi and had pretty basic functionality: changeable font, bookmarks, navigation.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_KFKbB1o0M_8/R0YjK7_LiKI/AAAAAAAAAAM/G8rXQMVq-DM/s1600-h/embiid.png"><img id="BLOGGER_PHOTO_ID_5135831095870982306" alt="" src="http://3.bp.blogspot.com/_KFKbB1o0M_8/R0YjK7_LiKI/AAAAAAAAAAM/G8rXQMVq-DM/s320/embiid.png" border="0" /></a><br /><br />File format details<br /><br />A pseudo-C description of the file header looks like following:<br /><pre>struct EmbiidFile {<br /> /* 00 */ int32 file_seed; //the seed for decrypting header fields<br /> /* 04 */ char type[5]; //file type (encrypted w/ file_seed)<br /><br />#define FTYPE_UBK "Valid" //non-personalized (text encrypted with file_seed)<br />#define FTYPE_EBK "EBook" //personalized (text encrypted with user_seed)<br /> <br /> /* 09 */ uint32 cover_off; //offset of the cover image (jpeg image)<br /> /* 0D */ uint32 cover_len; //length of the cover image data<br /> /* 11 */ byte version; //format version (encrypted w/ file_seed)<br /><br />#define CURRENT_VERSION 1<br /><br /> /* 12 */ char title[50]; //book title (encrypted w/ file_seed), space-padded<br /> /* 44 */ char author[954]; //book author (encrypted w/ file_seed), space-padded<br /> /* 3FE */ uint16 nchapters; //number of chapters<br /> /* 400 */ uint32 chap_lens[256]; //chapter lengths<br /> /* 800 */ char book_text[]; //text of the book. UBK: encrypted with file_seed, EBK: encrypted with user_seed<br />}<br /></pre><br /><br />The encryption uses a 1024-byte array to xor the data with. The array is initialized from the seed using a pseudo-random number generator. Here's pseudocode for its generation:<br /><pre>float a = seed/1000.0<br />for(int i=1;i<0x400;i++)<br />{<br /> float b = int(a/127773);<br /> float c = a - b*127773;<br /> a = c*16807 - b*2836;<br /> if (a<0) a+=2147483647;<br /> xor_buf[i] = int(a/2147483647*256)&0xFF;<br />}<br /></pre><br /><br />The decryption uses the file offset of the data to index the array, and it skips bytes that would decrypt to 0x1A (the EOF symbol):<br /><br /><pre>xor_val = xor_buf[file_offset%0x400];<br />val_out = val_in^xor_val;<br />if (val_out==0x1A)<br /> val_out = val_in;<br /></pre><br /><br />While the <span style="font-family:monospace"><b>file_seed</b></span> is stored directly in the file, <span style="font-family:monospace"><b>user_seed</b></span> is calculated as Adler32 checksum of a 128-byte user ID, which is stored directly in the personalized EmbiidReader.exe.<br /><br /><pre>t1 = 1;<br />sum = 0;<br />i = 0;<br />do{<br /> t1 = (t1 + user_id[i++]) % 0xFFF1;<br /> sum = (t1 + sum) % 0xFFF1;<br />}<br />while ( i <0x80 );<br />user_seed = (sum<<16) | t1;<br /></pre><br /><br />The text of the book uses a small subset of HTML tags for formatting, but the paragraphs are delimited by newlines, not <br> or <p> tags.<br /><br />Here's a small Python script to convert an Embiid book to HTML. A valid EmbiidReader.exe is necessary to decrypt personalized books.<br /><a href="http://skochinsky.googlepages.com/embiid-0.3.zip">Google Pages</a><br />You will need <a href="http://python.org/download/">Python</a> to run it.<br />Place your books, EmbiidReader.exe and embiid.py into the same directory and execute from command prompt:<br />embiid.py <book.ebk><br />You should get a <book.html> file with decoded text.Igor Skochinskyhttp://www.blogger.com/profile/17257295611554526824noreply@blogger.com8tag:blogger.com,1999:blog-3815311536458072770.post-56330866892070377892007-11-22T18:41:00.000+01:002007-12-14T13:45:12.702+01:00WelcomeHello, visitor.<br />I am a long-time reverse engineering hobbyist. Most of that time I've been "working for myself" but now I've decided to share some of my findings. My reverse engineering interests include decompilation, file formats and interoperability (and more). I've written a two-part article on Visual C++ reversing for OpenRCE.org: <a href="https://www.openrce.org/articles/full_view/21">1</a>, <a href="https://www.openrce.org/articles/full_view/23">2</a>.<br />Right now I'm "into" eBook readers, so the next few posts will probably be on eBook formats.Igor Skochinskyhttp://www.blogger.com/profile/17257295611554526824noreply@blogger.com3