Revision as of 02:06, 3 February 2012 by Craig Peacock (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

GoFlex Home Firmware Recovery

The GoFlex Home has a firmware recovery mechanism built into the bootloader.

Firmware can be loaded onto a FAT32 formatted USB stick and inserted into the rear USB host port.

The hard disk should be removed from the dock, otherwise the hard disk may come up as /dev/sda rather than the USB stick and prevent the *.ubi file being found.

Hold the reset pin while power is applied. The yellow light will blink immediately followed by the white LED. At this stage uBoot will have entered the USB firmware installation mode and you can release the reset pin.

USB 0: host mode
PEX 0: interface detected no Link.
Net:   egiga0 [PRIME]
<Explorer> Enter USB firmware instllation by RESET IO.
USB:   scanning bus for devices... 2 USB Device(s) found
1 Storage Device(s) found
reading uImage
...
...
2359296 bytes read
reading initrd
...
...
3385902 bytes read

The bootloader will attempt to load files "uImage" followed by "initrd". Once both have been loaded, it will flash the uImage kernel into NAND memory at 0x100000.

NAND erase: device 0 offset 0x100000, size 0x600000

Erasing at 0x100000 --   2% complete. Cleanmarker written at 0x100000.
Erasing at 0x120000 --   4% complete. Cleanmarker written at 0x120000.
...
Erasing at 0x6c0000 --  97% complete. Cleanmarker written at 0x6c0000.
Erasing at 0x6e0000 -- 100% complete. Cleanmarker written at 0x6e0000.
OK

NAND write: device 0 offset 0x100000, size 0x600000


Writing data at 0x100000 --   0% complete.
Writing data at 0x10f000 --   1% complete.
...
Writing data at 0x6f0800 --  99% complete.
Writing data at 0x6ff800 -- 100% complete.
 6291456 bytes written: OK
Saving Environment to NAND...
Erasing Nand...Writing to Nand... done
## Error: "initializeDev" not defined

And start booting the new kernel with the initial ramdisk.

## Booting image at 00800000 ...
   Image Name:   Linux-2.6.22.18
   Created:      2010-06-17   5:37:59 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2095148 Bytes =  2 MB
   Load Address: 00008000
   Entry Point:  00008000
   Verifying Checksum ... OK
OK
## Loading Ramdisk Image at 01100000 ...
   Image Name:   initrd
   Created:      2010-04-20  15:05:15 UTC
   Image Type:   ARM Linux RAMDisk Image (gzip compressed)
   Data Size:    3385838 Bytes =  3.2 MB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK

Starting kernel ...

Uncompressing Linux...........................................................................
......................................................... done, booting the kernel.

Linux version 2.6.22.18 (ramang@es5x86.axentra.com) (gcc version 4.3.2 (sdk3.2rc1-ct-ng-1.4.1) ) 
#16 Thu Jun 17 01:37:53 EDT 2010
CPU: ARM926EJ-S [56251311] revision 1 (ARMv5TE), cr=00053977
Machine: Feroceon-KW
Using UBoot passing parameters structure
Memory policy: ECC disabled, Data cache writeback
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
CPU0: D cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
Built 1 zonelists.  Total pages: 32512
Kernel command line: console=ttyS0,115200 root=/dev/ram0 rw ramdisk=0x01100000,8M install_type=nand

The inital ramdisk is responsible for loading the new UBIFS image and flashing it.

RAMDISK: Compressed image found at block 0
EXT2-fs warning: checktime reached, running e2fsck is recommended
VFS: Mounted root (ext2 filesystem).
Freeing init memory: 128K



*****************************************************************
 sheevaplug installer version 1.0

**** PRESS ENTER TO STOP THE COUNT DOWN
**** Will flash tarball from USB disk to internal NAND /dev/mtdblock1
**** This will wipe out EVERYTHING on the internal NAND flash
**** Will wait 10 seconds before the flash.




scsi 2:0:0:0: Direct-Access              USB 2.0          1.00 PQ: 0 ANSI: 2
sd 2:0:0:0: [sda] 4108159 512-byte hardware sectors (2103 MB)
sd 2:0:0:0: [sda] Write Protect is off
sd 2:0:0:0: [sda] Assuming drive cache: write through
sd 2:0:0:0: [sda] 4108159 512-byte hardware sectors (2103 MB)
sd 2:0:0:0: [sda] Write Protect is off
sd 2:0:0:0: [sda] Assuming drive cache: write through
 sda: sda1
sd 2:0:0:0: [sda] Attached SCSI removable disk
sd 2:0:0:0: Attached scsi generic sg0 type 0
**** Mounting /dev/sda1
**** Erasing all flash

Erasing 128 Kibyte @ 0 --  0 % complete.
Erasing 128 Kibyte @ 20000 --  0 % complete.
Erasing 128 Kibyte @ 40000 --  0 % complete.
...
Erasing 128 Kibyte @ f8e0000 -- 99 % complete.
Erasing 128 Kibyte @ f900000 -- 100 % complete.
ubiformat: mtd2 (nand), size 261095424 bytes (249.0 MiB), 1992 eraseblocks of 131072 bytes 
(128.0 KiB), min. I/O size 2048 bytes

libscan: scanning eraseblock 0 --  0 % complete  
libscan: scanning eraseblock 1 --  0 % complete  
libscan: scanning eraseblock 2 --  0 % complete 
...
libscan: scanning eraseblock 1989 -- 99 % complete  
libscan: scanning eraseblock 1990 -- 99 % complete  
libscan: scanning eraseblock 1991 -- 100 % complete  
ubiformat: 1992 eraseblocks are supposedly empty

ubiformat: flashing eraseblock 0 --  0 % complete  
ubiformat: flashing eraseblock 1 --  0 % complete  
ubiformat: flashing eraseblock 2 --  0 % complete 
...
ubiformat: flashing eraseblock 1395 -- 99 % complete  
ubiformat: flashing eraseblock 1396 -- 99 % complete  
ubiformat: flashing eraseblock 1397 -- 100 % complete  

ubiformat: formatting eraseblock 1398 --  0 % complete  
ubiformat: formatting eraseblock 1399 --  0 % complete  
ubiformat: formatting eraseblock 1400 --  0 % complete 
...
ubiformat: formatting eraseblock 1989 -- 99 % complete  
ubiformat: formatting eraseblock 1990 -- 99 % complete  
ubiformat: formatting eraseblock 1991 -- 100 % complete  

The system is going down NOW!

Sent SIGTERM to all processes

Sent SIGKILL to all processes

Requesting system reboot
md: stopping all md devices.
sd 2:0:0:0: [sda] Stopping disk
Restarting system.
Reseting !! 

Extracting the initrd

The initial ramdisk is compressed using gzip compression and has a 64 byte headed appended for use with u-boot.

Remove the header and decompress:

dd if=initrd of=initrd.gz bs=1 skip=64
gzip -d initrd.gz

Then mount:

mount initrd ramdisk -o loop

Exploring the initrd

The 8 megabyte inital ramdisk contains busybox as the shell which in turn spawns /etc/init.d/rcS.

It mounts the usb stick as fat32 :

mount -t vfat /dev/sda1 /mnt/usb

looks for a file with the extension *.ubi and proceeds to flash it to mtd2:

echo "**** Erasing all flash"
if [ $UBIFS ]; then
	UBIFILE=`ls /mnt/usb/*.ubi`
	flash_eraseall /dev/mtd2
	ubiformat /dev/mtd2 -f $UBIFILE -s 2048 -O 2048
else
	flash_eraseall -j /dev/mtd1
fi

This makes the initrd quite generic and can be used to flash our own firmware onto the GoFlex Home. All we need to use is add our own kernel (uImage) and/or our own UBIFS with any name provided it has the extension .ubi

RAMDisk Size Issues (attempt to access beyond end of device)

When the recovery/reset button is used to enter recovery mode, uBoot will rewrite the bootargs variable including, among other things, a size limitation of 8Mbytes to:

bootargs=console=ttyS0,115200 root=/dev/ram0 rw ramdisk=0x01100000,8M install_type=nand

With later kernel versions this results in a message similar to:

RAMDISK: gzip image found at block 0
scsi1 : usb-storage 1-1:1.0
RAMDISK: incomplete write (11824 != 13542)
write error
EXT2-fs (ram0): warning: checktime reached, running e2fsck is recommended
VFS: Mounted root (ext2 filesystem) on device 1:0.
Freeing init memory: 148K
attempt to access beyond end of device
ram0: rw=0, want=11282, limit=8192
Buffer I/O error on device ram0, logical block 5640
attempt to access beyond end of device
ram0: rw=0, want=11794, limit=8192
Buffer I/O error on device ram0, logical block 5896
attempt to access beyond end of device
ram0: rw=0, want=11282, limit=8192
Buffer I/O error on device ram0, logical block 5640
attempt to access beyond end of device
ram0: rw=0, want=11794, limit=8192
Buffer I/O error on device ram0, logical block 5896
/bin/sh: can't access tty; job control turned off
# scsi 1:0:0:0: Direct-Access              USB 2.0          1.00 PQ: 0 ANSI: 2
attempt to access beyond end of device
ram0: rw=0, want=11282, limit=8192
Buffer I/O error on device ram0, logical block 5640
attempt to access beyond end of device
ram0: rw=0, want=11794, limit=8192
Buffer I/O error on device ram0, logical block 5896

It appears the zlib compressed RAM disk expands out beyond the 8Mbyte limit specified by uBoot and passed as a kernel parameter.

Changing bootargs has no effect, as once it has been committed to flash, as soon as you initiate a recovery, uBoot resets this variable.

Therefore if we want to update the kernel using the recovery mode, we must hack the kernel.

The RAM backed block device driver lives in the /drivers/block/brd.c. We change the line :

int rd_size = CONFIG_BLK_DEV_RAM_SIZE;

to

int rd_size = 16384;

and comment out the following line in the ramdisk_size function to prevent rd_size being over written by a kernel parameter.

//rd_size = simple_strtol(str, NULL, 0);