Update capsule (Lacie V2)

The update capsule consists of a header (in xml) with a tarfile containing the payload glued to it.

Header
Here you see the header of the 1.2.9 update capsule for the Networkspace2  0.2   Kirkwood 2.0 netspace_v2  Network Space 2 networkspace2 </Device> <Main> <File>uImage</File> <SHA1>ec4437e7ea49df71e60dc6f70c8e9dbc8393a292</SHA1> </Main> <Type>update</Type> <Update> <MinimalVersion>1.0.1</MinimalVersion> 1.2.9</Version> <TemporaryStorage>RAM</TemporaryStorage> <Kernel> <File>repository/kernel</File> <SHA1>43c4560aecf05b0ac2dcd95b5a29fbee0b86553e</SHA1> </Kernel> <RootFS> <File>repository/rootfs.tar.lzma</File> <SHA1>529df66910953c70c27ac1f1de54afccac36f9e2</SHA1> </RootFS> </Update> <Exec> <Before> <File>repository/pre_checkLogSize.sh</File> <SHA1>b026bb7a2750d7d7fa4ae4aa5e4ae12e4abdb608</SHA1> </Before> <After> <File>repository/post_updateRemoveFiles.sh</File> <SHA1>644b383e3419840c26e3c04a3045ed9ebe8e44b2</SHA1> </After> </Exec> <ReleaseDate>2010-11-04</ReleaseDate> </Capsule>

Version
I *think* this is about the capsule version.

Device
Descibes the target device. (Mandatory)

Main
Descibes the name an sha1 sum of a uImage which will be flashed in sda10. This kernel does the actual work.

Type
Type of update. Possible are init, upgrade, update, open and uuid-log.

init
Creates a new partition table. Can install a bootloader, kernel, bootfs (sda7) and a rootfs (sda8). Can run Before and After scripts Reboots

upgrade
Can install a bootloader, kernel, bootfs (sda7) and a rootfs (sda8). Can run Before and After scripts Reboots

update
Can install a kernel and install a new snapshot on sda9, resulting in a patched rootfs. Can run Before and After scripts Reboots

open
Can run Before and After scripts A telnet server is started. IP address is obtained by DHCP.

uuid-log
Outputs raid uuids to console

Update
This section could also be called Init, Upgrade, Open or Uuid-log, depending on the Type. Describes needed files with their sha1sum, and possibly defines firmware constraints.

Exec
Defines scripts and the sha1sums of scripts which are run Before and After the actual action. (Type) Several scripts can be defined.

ReleaseData
Yeah, what would that be?

All sha1sums in the header should match, else the capsule is denied.

Payload
The payload is a tarfile, glued directly after the xml header. It contains a file description.xml, which is identical to the header, a file description.sha1, containing the sha1sum of description.xml. Further the tar contains all files defined in description.xml. It may contain more files, the capsule manager doesn't care.

Action
On shutdown Unicorn extracts the capsule file to /capsule. It checks all sha1sums, and when they fit the file defined in <Main></Main> is written to sda10. The bootloader always first checks if a valid uImage is available in sda10, before booting from sda6, so on next boot the update kernel is executed.

Update kernel
The update kernel from the networkspace2 1.2.7 capsule has an embedded initramfs, containing complete rootfs, a (rather curtailed) version of busybox and some dedicated scripts. These scripts are responsible for executing the actual action. sda10 is cleared, so this kernel is used only once.

Using this kernel, when the 'Before' script(s) is executed, only sda9 is mounted, on /mnt/rootfs_rw. When the 'After' scripts are executed sda7 is mounted on /mnt/bootfs, sda8 on /mnt/rootfs_ro and sda9 on /mnt/rootfs_rw. In case of a multi-disk NAS the corresponding raid arrays are mounted.

Usage
A capsule can be autodownloaded from Lacie. Or can be added manually, by putting it in MyShare\Update. (Older firmwares just MyShare), or on boxes without a MyShare, create a share named Share, and put it in Share\Update

Dedicated capsule
For a dedicated capsule (to install some dedicated software package) I think the 'open' type can be used best. A sample

description.xml
<Capsule> 0.2</Version> <Device>  Kirkwood</Family> 2.0</Id> netspace_v2</Revision> </Hardware> Network Space 2</Product> networkspace2</ProductId> </Device> <Main> <File>uImage</File> <SHA1>ec4437e7ea49df71e60dc6f70c8e9dbc8393a292</SHA1> </Main> <Type>open</Type> <Open> <MinimalVersion>1.0.1</MinimalVersion> 9.9.9</Version> <TemporaryStorage>RAM</TemporaryStorage> </Open> <Exec> <After> <File>repository/post_exec.sh</File> <SHA1>bf43b4ca4eb743b773f3a788754ab7c02ce1b078</SHA1> </After> </Exec> <ReleaseDate>2012-07-09</ReleaseDate> </Capsule> A sample repository/post_exec.sh

'After' script
SDA9MOUNT=/mnt/root_rw SDA8MOUNT=/mnt/root_ro SNAPSHOTDIR="" CURRENTSNAPSHOT="" FindCurrentSnapshot {    local IFSbackup=${IFS}; IFS=/ local chunk for chunk in $1 do        [ -z $chunk ] && continue CURRENTSNAPSHOT="${CURRENTSNAPSHOT}/${chunk}" if ! [ -z "${SNAPSHOTDIR}" ] ; then IFS=$IFSbackup return 0 fi        if [ "${chunk}" = "snaps" ] ; then SNAPSHOTDIR=${CURRENTSNAPSHOT} fi    done IFS=$IFSbackup } DetectPaths {     echo this=$0 LOCALDIR=` dirname $0 ` [ "" = "$LOCALDIR" ] && echo "localdir not found" && exit 0 echo localdir=$LOCALDIR FindCurrentSnapshot $LOCALDIR [ "" = "$SNAPSHOTDIR" ] && echo "snapshotdir not found" && exit 0 echo snapshotdir=$SNAPSHOTDIR [ "" = "$CURRENTSNAPSHOT" ] && echo "current snapshot not found" && exit 0 echo currentsnapshot=$CURRENTSNAPSHOT } DetectPaths mkdir -p ${CURRENTSNAPSHOT}/etc/initng/ mv -f ${LOCALDIR}/dedicated.i ${CURRENTSNAPSHOT}/etc/initng/ to_find=/etc/initng/runlevel/default.runlevel most_recent=` find $SNAPSHOTDIR | grep $to_find | sort -r | head -n 1 ` [ "" = "$most_recent" ] && most_recent=${SDA8MOUNT}${to_find} cp $most_recent /tmp/mr grep ^dedicated /tmp/mr || echo dedicated >>/tmp/mr mkdir -p ` dirname ${CURRENTSNAPSHOT}${to_find} ` mv -f /tmp/mr ${CURRENTSNAPSHOT}${to_find} uImage=` find $SNAPSHOTDIR | grep boot/uImage | sort -r | head -n 1 ` if [ "" != "$uImage" ] ; then # Found a uImage. Now we have to decide where to put it. In a multidisk # Lacie this could be any of the disks. Fortunately the cmdline contains # a root= statement, pointing to a partition on that drive rootdev="" for arg in ` cat /proc/cmdline ` do       case $arg in           boot=*)                rootdev=` echo $arg | cut -d '=' -f 2 `                ;;            *) ;;       esac done # In case this failed, just assume sda: [ -z $rootdev ] && rootdev=/dev/sda7 # strip the number on the end rootdev=` echo ${rootdev} | sed 's/[0-9]*//g' ` # and write the uImage dd if=$uImage of=${rootdev}10 fi reboot
 * 1) !/bin/sh
 * 1) First find out where we live.
 * 1) Do your custom action
 * 1) If you need to edit a file, you'll have to search for the most recent,
 * 2) because the current snapshot doesn't necessarily contain it
 * 1) It might even not be in the snapshots at all, in that case get it from sda8
 * 1) edit the file
 * 1) add your line, if it isn't already there
 * 1) move it to it's destination. Make sure the directory already exists
 * 1) === VERY IMPORTANT ===
 * 2) Have a look if a uImage is in one of the snapshots. In that case the most
 * 3) recent one has to be written to sda10, as sda6 might contain an older one,
 * 4) to be able to factory reset the box.
 * 1) An 'open' capsule won't reboot automagically. (But has a telnetd daemon running.
 * 2) So if you skip next line you could login a look around)

Generating capsulefile
cp description.xml dedicated.capsule sha1sum description.xml | awk '{ print $1 }' >description.sha1 tar c description.xml description.sha1 uImage repository/ >>dedicated.capsule