=============== Cyph's Flashkit =============== GOAL This package is the result of my research into flashing individual partitions on the 32MB Intel L18 Strataflash on the E680 without using the Windows PST tools, but instead using Linux's own MTD layer. ADVANTAGES - much faster than using PST - you can still retain your settings and data - you don't need Windows BACKGROUND For onboard persistent storage the E680 has an Intel StrataFlash L18 chip (http://www.intel.com/design/flcomp/prodbref/251890.htm) and a DiskOnChip. The DiskOnChip is already writable in Linux with the tffs.o proprietary driver and therefore shall not be elaborated on any further here. The L18 chip is the most interesting. It contains, amongst other things, the bootloader, kernel and root filesystem. Interface with this chip is provided through Linux's MTD layer using the cfi_cmdset_0001_mp.c, which is Motorola's modification of the cfi_cmdset_0001.c driver. During normal operation, only the VFM filesystem (mounted at /ezxlocal) is written to. So, with this chip's interfaces going through the standard MTD layer, writing to it should be a piece of cake. Just cross-compile mtd-utils and we're good to go, right? Unfortunately, not. These are the hurdles that are in the path: 1. Device nodes in /dev are incomplete and wrong. Easily fixable with mknod. 2. There is no mtd partition for the root filesystem! The root filesystem is accessed through Motorola's own roflash driver. Why did Motorola do this? I realized its because they want to be able to mount root as Linear (which lets cramfs mount off a range of physical memory, instead of a block device) and other cramfs partitions (like /usr/language on the DiskOnChip) as block devices at the same time. The DiskOnChip can only be accessed as a block device. Linux was not able to do this at the time of development, so they came up with their own solution. Pretty neat actually. The rootfs roflash device (/dev/roflash) is marked as Linear, so cramfs(which they modified) will use the flash's physical address to mount instead of going through the block subsystem. This is why you can't read from /dev/roflash. The segfault is due to shoddy coding on their part, they should have checked and returned an error instead. BTW, it looks like they were trying to get XIP to work, but I guess the files just got too big for that. So, we just create some mtd_partition structs and insert them using a kernel module, right? A little tough, but still possible. Wrong! Writing to the chip gives a "Read-only filesystem" error. 3. According to the L18 data sheet, individual erase blocks on the chip can be unlocked (writable), locked (set as read-only, but can still be unlocked) and locked down(read-only until the chip is power cycled or the voltage on some pin is changed). cfi_cmdset_0001_mp.c locks down all erase blocks except the VFM filesystem when the system boots. Damn!! Most of the chip is read-only until the chip is power-cycled. However looking at the driver in cfi_cmdset_0001_mp.c closely, it turns out like the chip is powered down at some point in time when the system is running: when the power management brings the phone to a low power state. Interesting. Solution is to write a kernel module (rwflash.o) that hijacks the power management callbacks and unlock the entire chip when the system returns from low-power mode. Navigating through some data structures and copy-and-paste of code should do the trick. However, we don't unlock the bootloader, because its a really really really bad idea to screw that one up. 4. So now we have a writable chip, and mtd partition mappings. Now to write to the root filesystem. But we can't expect the system to stay alive while its root filesystem is being overwritten. So, we need an alternate root, and some pivot_root magic to change root on the fly. Alternate root can be built by taking Motorola's own cramfs filesystem (25mb) and stripping it down to just inetd, telnet and some console utilities (2.9mb). USAGE Things you need: 1. SD/MMC Card 2. Linloader 3. Prepared cramfs image for rootfs or setup on your SD/MMC. (You can start by experimenting with flashing /usr/setup, much faster and less risk) 4. Telnet access to phone 5. Lots of pluck Procedures: telnet 169.254.142.2 10000 flashcp –v /mmc/mmca1/cg33.smg /dev/mtd5 flashcp -v R52_G_0D.76_cg33_2.0.bin /dev/mtd5 1. Unzip flashkit.zip and copy flashkit/ into the root of your MMC/SD card. 2. Unplug phone from USB or charger 3. Run rwflash.lin. This will load rwflash.o 4. Leave the phone alone and wait. When the screen blanks out wait 30secs longer, there's a good chance the phone entered low power mode. 5. Telnet to the phone and cat /proc/rwflash_status. If it shows "unlocked", your flash is writable!! If not, unplug phone and go to step 4 6. cd /mmc/mmca1/flashkit 7. ./start.sh 8. The script will start killing the phone's apps and mount the miniroot. After which, your telnet connection will be terminated. 9. Telnet back to the phone at port 10000 and login as root. You are now in the miniroot. All phone applications should be killed by now (Except for mmcsdapp, for some reason, it is stuck in an uninterruptible sleep. This means we can't unmount the original root. Well, too bad.) 10. cat /proc/mtd to see what partitions you have. You should be able to flash the "R/W" partitions: mtd4: 000e0000 00020000 "R/W Kernel" mtd5: 018e0000 00020000 "R/W RootFS" mtd6: 00020000 00020000 "R/W Setup" mtd7: 00020000 00020000 "R/W Logo" 11. Now, there are a few ways you can do this: flashcp -v modified_root.cramfs /dev/mtd5 OR flash_erase /dev/mtd5 0 199 dd if=modified_root.cramfs of=/dev/mtd5 bs=4096 OR dd if=modified_root.cramfs of=/dev/mtdblock5 bs=4096 12. sync 13. Pull out battery. Reboot. Note: - flashcp will verify the image after writing, but for some reason it fails to verify when you are flashing the rootfs. Its a bug in the verification code I think. dd back from /dev/mtd5 and use md5sum to verify. - do not access files in /oldroot when flashing the rootfs. - using this miniroot, you can also backup/restore /diska and /ezxlocal as they are unmounted while miniroot is active. CREDITS pascal -- for his heroic effort to get the kernel sources, giving me hours of code reading pleasure :) leprechaun -- for his cross-compiler instructions silvio -- for his utilities and initial work on modifying rootfs