Flashing the SheevaPlug Kernel from a USB Drive with U-Boot

If you've ever tried to upgrade the kernel on a SheevaPlug, you know that sometimes flashing from within Linux doesn't work, and will leave the plug in an unbootable state.  Here's how I recovered from a bad flash, using U-Boot to flash a kernel image stored on a USB drive.  In this case I'm flashing a custom-compiled 2.6.33.7 with the realtime patches (2.6.34 and newer seem to have problems with USB audio on the Sheeva).  This guide assumes you know how to get into U-Boot.  Help for most commands is available by typing help command.

First, initialize the USB system.
Marvell>> usb start
(Re)start USB...
USB:   scanning bus for devices... 2 USB Device(s) found
       scanning bus for storage devices... 1 Storage Device(s) found

Next, find out where the kernel lives.  In this case, the kernel has 4MB of space allocated at an offset of 1MB.

 Marvell>> printenv
...
bootargs=rootfstype=jffs2 console=ttyS0,115200 mtdparts=orion_nand:0x400000@0x100000(uImage),0x1fb00000@0x500000(rootfs) rw root=/dev/mtdblock1
...

Identify the kernel uImage to flash.

Marvell>> fatls usb 0
...
  2614696   uimage-2.6.33.7-rt29-nl1
...

Copy the kernel into RAM just after the end of U-Boot's memory area.

Marvell>> fatload usb 0 0x800000 uimage-2.6.33.7-rt29-nl1
reading uimage-2.6.33.7-rt29-nl1
.
................................................................................
................................................................................
...........................

...................................................................

2614696 bytes read

Make sure the kernel loaded correctly.

Marvell>> md 0x800000 0x10
00800000: 56190527 791c42b3 88eaaa4c 68e52700    '..V.B.yL....'.h
00800010: 00800000 00800000 3b1aaa59 00020205    ........Y..;....
00800020: 756e694c 2e322d78 33332e36 722d372e    Linux-2.6.33.7-r
00800030: 2d393274 00316c6e 00000000 00000000    t29-nl1.........

You may want to try booting the new kernel before you flash it (in this case, you'll need to repeat the previous steps after you reboot).

Marvell>> bootm 0x800000
## Booting image at 00800000 ...
   Image Name:   Linux-2.6.33.7-rt29-nl1
   Created:      2010-10-05   9:06:16 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2614632 Bytes =  2.5 MB
   Load Address: 00008000
   Entry Point:  00008000
   Verifying Checksum ... OK
OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.

In my case the kernel failed to boot, so I had to recompile it.  Note that this sometimes fails even with a valid kernel, so if you feel confident, try flashing the kernel anyway and power cycle the device.

$ make clean
$ make -j8 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- uImage
$ make -j8 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- modules
$ make -j8 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- INSTALL_MOD_PATH=../modules modules_install
$ cp arch/arm/boot/uImage ../output/uImage-2.6.33.7-rt29-nl1
$ cd ../modules/ && tar -zcvf ../output/modules-2.6.33.7-nl1.tar.gz . && cd -

Once you've verified the new kernel erase the old kernel (4MB at offset 1MB).

Marvell>> nand erase 0x100000 0x400000

NAND erase: device 0 offset 0x100000, size 0x400000
Erasing at 0x4e0000 -- 100% complete.
OK

If your flash process went really wrong and erroneously marked a bunch of blocks as bad (as mine did), you may need to scrub the kernel area, which will erase all bad blocks in the kernel area.

Marvell>> nand scrub 0x100000 0x400000

Write the new kernel into NAND flash.

Marvell>> nand write 0x800000 0x100000 0x400000

NAND write: device 0 offset 0x100000, size 0x400000
 4194304 bytes written: OK

Test the new kernel.

Marvell>> boot

NAND read: device 0 offset 0x100000, size 0x400000

Reading data from 0x4ff800 -- 100% complete.
 4194304 bytes read: OK
## Booting image at 00800000 ...
   Image Name:   Linux-2.6.33.7-rt29-nl1
   Created:      2010-10-05   9:06:16 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2614632 Bytes =  2.5 MB
   Load Address: 00008000
   Entry Point:  00008000
   Verifying Checksum ... OK
OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.


If all went well, you should see the console output from the booting kernel.  If not, recompile your kernel or use a known-good uImage and try again.  Also, don't forget to extract the kernel modules on the SheevaPlug.