Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- set -e
- # Updater for the Shadow.
- #
- # Will flash the mmc partition not in use. Makes some effort not to
- # overwrite your data by mistake:
- #
- # * filesystem must have /etc/build and we must parse it
- # * dmidecode must identify board as one with a downloadable update
- # * /proc/cmdline must have "root=/dev/mmcblk0p[23]"
- # * alternate /dev/mmcblk0p[32] must exist and be a block device
- # * rootfs is squashfs
- # Known problems:
- #
- # * when manually interrupted by ctrl-c or ctrl-\, dd finishes before
- # stopping, and grub config is not updated, and the system won't
- # boot on updated partition [low risk of occurence in the wild, and
- # auto-fixing on next attempt]
- # params
- TIMEOUT=5
- # identify platform
- case $(dmidecode -s baseboard-product-name) in
- UP-CHT01) PLATFORM=up-board ;;
- BP-FP4-LC) PLATFORM=amdfalconx86 ;;
- *) PLATFORM=unknown ;;
- esac
- SERVER=http://update.blade-group.fr/updates
- KEYRING=/usr/share/updater.keyring
- DEFAULTBRANCH="prod"
- if [ -r /etc/blade/branch ]; then
- DEFAULTBRANCH=$(cat /etc/blade/branch)
- fi
- die() {
- echo >&2 "ERROR: $*"
- exit 1
- }
- usage()
- {
- cat <<EOF
- Usage:
- $(basename $0) [options] [branch|version]
- Options:
- --help, -h: This help
- --force, -f: Apply update even if already running same version.
- --fast: Don't rate-limit the download
- --reboot: Reboot if an update was applied
- --graphic Show graphical notification screens
- --imgdir <dir> Show graphical notification screens from <dir>
- Example branches:
- prod Production image for real customers (default)
- preprod prod-candidate, for beta testers
- testing preprod-candidate, for internal testing
- <branch>-test <branch>-candidate for last checks before publication
- EOF
- }
- wrongusage()
- {
- echo >&2 "ERROR: $*"
- usage
- exit 1
- }
- notify()
- {
- [ $GRAPHIC = 1 ] || return 0
- killall -9 feh || true
- feh --fullscreen "$IMGDIR"/"$1".png &
- }
- check_squashfs()
- {
- if command -v unsquashfs >/dev/null; then
- unsquashfs -l "$1" >/dev/null
- else
- echo "WARNING: unsquashfs not found, NOT checking filesystem integrity"
- fi
- }
- FORCE=0
- FEED="$DEFAULTBRANCH"
- REBOOT=0
- GRAPHIC=0
- IMGDIR=/usr/share/shadow/images
- # 100KB/s is below 1Mb/s
- MAYBELIMIT="--limit-rate 100k"
- while [ $# -gt 0 ]; do
- case "$1" in
- -h|--help) usage; exit 0 ;;
- -f|--force) FORCE=$((FORCE+1)) ;;
- --fast) MAYBELIMIT="" ;;
- --reboot) REBOOT=1 ;;
- --graphic) GRAPHIC=1 ;;
- --imgdir) GRAPHIC=1; IMGDIR="$2"; shift ;;
- -*) wrongusage "Unknown option '$1'" ;;
- *) break ;;
- esac
- shift
- done
- if [ $# -gt 0 ]; then
- FEED="$1"
- shift
- fi
- [ $# = 0 ] || wrongusage "Too many non-option arguments"
- # locate this version's root partition
- for opt in $(cat /proc/cmdline); do
- case "$opt" in
- root=*) MYPART=${opt#*=}; break ;;
- esac
- done
- if ! mount | grep -q ' / .* squashfs '; then
- echo "rootfs is not a squashfs, not updating"
- exit 0
- fi
- if [[ "$FEED" =~ ^[0-9]+$ ]]; then
- FEEDVERSION="$FEED"
- else
- FEED="$PLATFORM/$FEED"
- if [ $GRAPHIC = 1 ]; then
- trap "killall -9 feh || true" EXIT
- fi
- notify checking-updates
- FEEDFILE=$(mktemp -t "updater.XXXXXX")
- curl --silent --fail $MAYBELIMIT "$SERVER/$FEED" -o "$FEEDFILE" || die "failed to check for '$FEED' update"
- FEEDVERSION=$(cat $FEEDFILE)
- rm $FEEDFILE
- [ -n "$FEEDVERSION" ] || die "no $FEED version!"
- echo "$FEED version is $FEEDVERSION"
- fi
- # this partition's version
- [ -f /etc/build ] || die "Cannot find /etc/build for Shadow image version"
- CURRENT=$(grep "^DATETIME =" /etc/build | cut -d= -f2 | tr -d ' ')
- expr "$CURRENT" : "[0-9]*$" >/dev/null || die "Cannot understand rev '$CURRENT'"
- [ 14 -eq $(expr "$CURRENT" : "[0-9]*$") ] || die "Revision should have 14 digits: '$CURRENT'"
- echo "Current version is $CURRENT"
- if [ "$FEEDVERSION" -eq "$CURRENT" ]; then
- echo "Shadow is uptodate"
- if [ $FORCE -ge 1 ]; then
- echo " --force given, proceeding anyway"
- else
- exit 0
- fi
- elif [ ! "$FEEDVERSION" -gt "$CURRENT" ]; then
- echo "Version inconsistency: $FEED '$FEEDVERSION' is older than '$CURRENT'"
- if [ $FORCE -ge 1 ]; then
- echo " --force given, proceeding anyway"
- else
- exit 3
- fi
- fi
- # deduce other partition
- case "$MYPART" in
- /dev/mmcblk0p2) MYPARTNUM=2; NEWPARTNUM=3 ;;
- /dev/mmcblk0p3) MYPARTNUM=3; NEWPARTNUM=2 ;;
- *) die "unknown root partition '$MYPART'" ;;
- esac
- NEWPART=/dev/mmcblk0p$NEWPARTNUM
- [ -b $NEWPART ] || die "partition $NEWPART does not exist"
- # other partition's version
- while true; do # this is poor-man's do-while(0)
- # check the filesystem can be completely read
- if ! check_squashfs $NEWPART; then
- echo "Other partition's filesystem is bad, will reflash"
- break;
- fi
- if ! mount -oro $NEWPART /mnt; then
- # this should never happen since we checked it, but old images
- # don't have unsquashfs
- echo "Could not mount other partition, will flash"
- break
- fi
- OTHERVERS=$(grep "^DATETIME =" /mnt/etc/build | cut -d= -f2 | tr -d ' ')
- umount $NEWPART
- if ! [ "$OTHERVERS" -gt 0 ] 2>/dev/null; then
- echo "Cannot understand '$OTHERVERS' as numeric version, will reflash"
- break
- fi
- echo "Other partition had $OTHERVERS"
- break
- done
- IMG=shadow-image-x11-${PLATFORM}-${FEEDVERSION}.rootfs.squashfs
- notify "downloading-update"
- echo "dowloading update..."
- wget -q $SERVER/$PLATFORM/$IMG.sig -O /tmp/$IMG.sig || die "failed to fetch update signature"
- wget $SERVER/$PLATFORM/$IMG -O /tmp/$IMG || die "failed to fetch update"
- notify "applying-update"
- echo "verifying update data..."
- gpgv --keyring $KEYRING /tmp/$IMG.sig /tmp/$IMG ||
- die "failed to verify update"
- echo "flashing update..."
- dd if=/tmp/$IMG of=$NEWPART bs=4M || die "failed to flash update"
- sync
- echo "verifying update..."
- check_squashfs $NEWPART
- echo "updating bootentries..."
- mount /dev/mmcblk0p1 /mnt
- EFIDIR=/mnt/EFI/BOOT
- if [ "$FEED" = "master" ]; then
- QUIET=''
- else
- QUIET='quiet'
- fi
- cat > $EFIDIR/rootpart.cfg <<EOF
- timeout=$TIMEOUT
- timeout_style=countdown
- #set prefix=(\${rootdsk},gpt$NEWPARTNUM)/usr/lib64/grub
- if loadfont (\${rootdsk},gpt$NEWPARTNUM)/usr/share/grub/unicode.pf2
- then
- set gfxmode=1920x1080,2560x1440,1290x1200,1920x1080,1280x1024,1024x768,auto
- set gfxpayload=keep
- terminal_output gfxterm
- fi
- menuentry 'Shadow (image $FEEDVERSION)' {
- linux (\${rootdsk},gpt$NEWPARTNUM)/boot/bzImage root=$NEWPART \${opts}
- }
- menuentry 'Shadow previous (image $CURRENT)' {
- linux (\${rootdsk},gpt$MYPARTNUM)/boot/bzImage root=$MYPART $QUIET \${opts}
- }
- EOF
- sync
- cat > $EFIDIR/oldrootpart.cfg <<EOF
- timeout=$TIMEOUT
- timeout_style=countdown
- #set prefix=(\${rootdsk},gpt$NEWPARTNUM)/usr/lib64/grub
- if loadfont (\${rootdsk},gpt$NEWPARTNUM)/usr/share/grub/unicode.pf2
- then
- set gfxmode=1920x1080,2560x1440,1290x1200,1920x1080,1280x1024,1024x768,auto
- set gfxpayload=keep
- terminal_output gfxterm
- fi
- menuentry 'Shadow recovery (image $CURRENT)' {
- linux (\${rootdsk},gpt$MYPARTNUM)/boot/bzImage root=$MYPART $QUIET \${opts}
- }
- EOF
- umount /dev/mmcblk0p1
- sync
- if [ $REBOOT = 1 ]; then
- notify "reboting"
- echo "Update finished, rebooting..."
- reboot
- else
- echo "Update finished."
- fi
- # signal update to caller
- exit 2
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement