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 !!
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
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
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);