#!/bin/sh
# Usage: upgrade.sh [check, execute, rescue]
#
#        check:   Check if an upgrade is actually needed. If so, the result file will
#                 be set to 1, otherwise 0
#        execute: Do all upgrades that is needed
#        rescue:  Upgrade rootfs (and/or other) from rescue
#

# Directory of this script
SCRIPT_DIR=$(dirname $(readlink -f $0))

# Name of this script
SCRIPT_NAME=$(basename $0)

# What to do: check if upgrade is needed, upgrade etc
ACTION=$1

# Name of the result file for this script
SCRIPT_RES_FILE=$SCRIPT_DIR/$SCRIPT_NAME.res

# Where version files are stored in the device
VERSION_FILES="/usr/local/etc/versions"

# The modules to upgrade (And also the order)
#MODULES="wmultra-linux app wmultra-rescue rootfs patches"
MODULES="system app patches mcu"

# Language definitions
LANGUAGE_FILE=lang_upgrade.json
LANGUAGE_PATH="/usr/local/www/default/lang"

PATCH_SCRIPT=$SCRIPT_DIR/patches/patching.sh

# Check if upgrade is needed by checking version files in
# upgrade packet aginst version file stored in the device
#
# arg1: module (uboot, rootfs etc)
#
# returns 1 if upgrade is needed, otherwise 0
checkVersion() {
  if [ -e $VERSION_FILES/version_$1.txt ]; then
    curVer=`head -1 $SCRIPT_DIR/version_$1.txt`
    upgVer=`head -1 $VERSION_FILES/version_$1.txt`

    if [ "$curVer" != "$upgVer" ]; then
      ret=1
    else
      ret=0
    fi
  else
    ret=1
  fi

  return $ret
}

# Check if upgrade of application is needed
#
# returns 1 if upgrade is needed, otherwise 0
checkVersionApp() {
  if [ -e /usr/local/etc/appfs.md5 ]; then
    diff /usr/local/etc/appfs.md5 $SCRIPT_DIR/appfs.md5
    return $?
  else
    return 1
  fi
}

# Check if upgrade of rootfs is needed
#
# returns 1 if upgrade is needed, otherwise 0
checkVersionRootfs() {
  if [ -e /etc/version ] && [ -e $SCRIPT_DIR/version_rootfs.txt ]; then
    curVer=`head -1 /etc/version`
    upgVer=`head -1 $SCRIPT_DIR/version_rootfs.txt`

    if [ "x$curVer" != "x$upgVer" ]; then
      return 1
    else
      return 0
    fi
  else
    return 1
  fi
}

# Check if it needed to apply any patches
#
# returns 1 if a patch needs to be applied, otherwise 0
checkVersionPatches() {
	if [ -e $PATCH_SCRIPT ]; then
		sh $PATCH_SCRIPT check
		return $?
	else
		return 0
	fi
}

# Check if upgrade of kernel is needed
#
# returns 1 if upgrade is needed, otherwise 0
#checkVersionKernel() {
#  if [ -e $SCRIPT_DIR/version_kernel.txt ]; then
#    curVer=`head -1 /proc/version`
#    upgVer=`head -1 $SCRIPT_DIR/version_kernel.txt`
#
#    if [ "x$curVer" != "x$upgVer" ]; then
#      return 1
#    else
#      return 0
#    fi
#  else
#    return 1
#  fi
#}

# Copy version file from upgrade packet to device
#
# arg1: module (uboot, rootfs, etc)
copyVersion() {
  echo " -Updating version numbers for $1"

  # Create directory if it does not exist
  if [ ! -d $VERSION_FILES ]; then
    mkdir $VERSION_FILES
  fi

  cp  $SCRIPT_DIR/version_$1.txt $VERSION_FILES/version_$1.txt
}

# Create a resultfile used by the calling process to determine if
# this script was running smoothly
# First argument is the return code
createResultFile() {
  echo "$1" > $SCRIPT_RES_FILE
}

# Gets the Ultra version as a single number ((major * 1000) + minor) or 0 on errors
# Takes the file path as a single argument
getUltraVersion() {
  version_file="$1"

  if [ ! -f "$version_file" ]; then
    # File not found
    echo 0
    return
  fi

  version_data=$(sed -n 's/^\([0-9]\+\)\.\([0-9]\+\).*/\1 \2/p' "$version_file")

  if [ -z "$version_data" ]; then
    # No match found
    echo 0
    return
  fi

  major_version=$(echo "$version_data" | cut -d' ' -f1)
  minor_version=$(echo "$version_data" | cut -d' ' -f2)

  echo $(( (major_version * 1000) + minor_version ))
}

#################################
# Main entry point of this script
#################################

case $ACTION in
  ###############################
  # Check if an upgrade is needed
  check)
    cd $SCRIPT_DIR

    upgradeNeeded=0

    for MODULE in $MODULES
    do
      if [ $MODULE == "app" ]; then
        checkVersionApp
        if [ $? = 1 ]; then
          upgradeNeeded=1
        fi
      elif [ $MODULE == "system" ]; then
        checkVersionRootfs
        if [ $? = 1 ]; then
          upgradeNeeded=1
        fi
		#checkVersionKernel
        #if [ $? = 1 ]; then
        #  upgradeNeeded=1
        #fi
      elif [ $MODULE == "patches" ]; then
        checkVersionPatches
        if [ $? = 1 ]; then
          upgradeNeeded=1
        fi
      elif [ $MODULE == "mcu" ]; then
        checkVersion $MODULE
        if [ $? = 1 ]; then
          upgradeNeeded=1
        fi
      else
        checkVersion $MODULE
        if [ $? = 1 ]; then
          upgradeNeeded=1
        fi
      fi
    done

    createResultFile $upgradeNeeded  # Signal to calling application if an upgrade is needed

    echo "EXIT"

    exit
  ;;

  ############################
  # Perform the actual upgrade
  execute)

	cp $SCRIPT_DIR/$LANGUAGE_FILE $LANGUAGE_PATH/$LANGUAGE_FILE
	chmod 644 $LANGUAGE_PATH/$LANGUAGE_FILE

    cd $SCRIPT_DIR

    for MODULE in $MODULES
    do
      case $MODULE in

        ########
        # System
        system)
          checkVersionRootfs
		  RES=$?
          #checkVersionKernel
		  #let RES=$RES+$?
          if [ $RES -gt 0 ]; then
            echo "MSG UPGRADE_SCRIPT_MSG_SYSTEM"

            echo " -Set RTC-register to signal to rescue to update $MODULE"
            i2cset -f -y 0 0x32 10 0

            # Check which system we are running
			cat /proc/cmdline | grep p2 > /dev/null
			if [ $? = 0 ]; then
				# System 1 (p2)
				NEW_SYSTEM=3
				NEW_PARTITION=3
			else
				# System 2 (p3)
				NEW_SYSTEM=2
				NEW_PARTITION=2
			fi
			# TODO
			#  - kolla kommando status
			#  - kolla monteringar
			#  - installera kärna+dtb
			# unmount both alt mounts, just to be safe
			umount /mnt/rootfs1
			umount /mnt/rootfs2
			gunzip -c $SCRIPT_DIR/rootfs.ext4.gz | dd of=/dev/mmcblk0p$NEW_PARTITION bs=4M
			resize2fs /dev/mmcblk0p$NEW_PARTITION

			#cp $SCRIPT_DIR/zImage /mnt/kernel$NEW_SYSTEM
			#cp $SCRIPT_DIR/ub20.dtb /mnt/kernel$NEW_SYSTEM

			echo "mmcpart=$NEW_SYSTEM" > /mnt/bootcfg/syssel.scr
			echo "mmcroot=/dev/mmcblk0p$NEW_PARTITION rootwait rw" >> /mnt/bootcfg/syssel.scr

          else
            echo " -System up to date"
          fi

          ;;

        #############
        # Application
        app)
          checkVersionApp

          if [ $? = 1 ]; then
            echo "MSG UPGRADE_SCRIPT_MSG_APPL"

            old_ultra_version=$(getUltraVersion /usr/local/etc/versions/ultra_release.txt)
            new_ultra_version=$(getUltraVersion "$SCRIPT_DIR/ultra_release.txt")

            # Application shall be terminated when we get here.
            # If not, copy the file anyway...

            echo " -Copying files, i.e. upgrading application from $old_ultra_version to $new_ultra_version"

            tar xvf $SCRIPT_DIR/appfs.tar -C /

            # Update the old default timezone when upgrading to 1.104 and beyond
            if [ "$old_ultra_version" -lt "1104" ]; then
              rm -f /usr/local/etc/timezone # Will be recreated from timezone.default
              rm -f /usr/local/etc/localtime # Will be recreated below
            fi

            for i in `find /usr/local/ -iname "*.default"` ; do
              file=${i%.default}
              if [ ! -e $file ]; then
                cp $i $file
              fi
            done

            # Remove legacy files to avoid confusion
            rm -f /usr/local/etc/TZ.default /usr/local/etc/TZ

            # Set default timezone
            if [ ! -L /usr/local/etc/localtime ]; then
              ln -s "/usr/share/zoneinfo/$(cat /usr/local/etc/timezone)" /usr/local/etc/localtime
            fi

            if [ -e $SCRIPT_DIR/appfs.md5 ]; then
              cp $SCRIPT_DIR/appfs.md5 /usr/local/etc/appfs.md5
            fi

            echo " -Done!"
          else
            echo " -Application up to date"
          fi

          ;;

        #############
        # Patches
        patches)
          checkVersionPatches

          if [ $? = 1 ]; then
            echo "MSG UPGRADE_SCRIPT_MSG_PATCHES"

            echo " -Applying patches"

            sh $PATCH_SCRIPT execute

            echo " -Done!"
          else
            echo " -Patches up to date"
          fi

          ;;

        #############
        # MCU
        mcu)
          checkVersion $MODULE

          if [ $? = 1 ]; then
            echo "MSG UPGRADE_SCRIPT_MSG_MCU"

            echo " -Flash programming MCU"

			cp $SCRIPT_DIR/UltraBase20_MCU.hex /usr/local/lib/firmware/ultraBase20MCU/
			cp $SCRIPT_DIR/upgradeMCU.sh       /usr/local/bin/

			sh $SCRIPT_DIR/upgradeMCU.sh $SCRIPT_DIR/UltraBase20_MCU.hex

			if [ $? = 0 ]; then
				copyVersion $MODULE
			else
				echo ">> Error while upgrading MCU"
			fi

            echo " -Done!"
          else
            echo " -MCU up to date"
          fi

          ;;

        #############
        # Default...
        *)
          echo ">>Unknown module $MODULE"

      esac

      echo ""
    done

    # All done, copy release file
    cp $SCRIPT_DIR/ultra_release.txt /usr/local/etc/versions/.

    createResultFile 0

    echo "MSG Done"

    # TODO: Kolla om 10 sekunder räcker för att serviceprocessen skall hinna skriva
    #       uppdaterad status till filen som webbsidorna läser
    sleep 10

    echo ">>Rebooting system"

    sync
    reboot

    echo "EXIT"

    exit

  ;;

  ###########################################
  # Called by rescue system to upgrade rootfs
  rescue)
    ubidetach -d 0 /dev/ubi_ctrl
    ubiformat -y /dev/mtd4
    ubiattach -m 4 -d 0 /dev/ubi_ctrl
    ubimkvol /dev/ubi0 -N rootfs -s 55MiB
    ubiupdatevol /dev/ubi0_0 $SCRIPT_DIR/wmultra-rootfs.arm.ubi
    # ubidetach -d $1 /dev/ubi_ctrl

    sync
    reboot
  ;;
esac
