#!/bin/sh
# CTM-ONE firmware upgrade
# Cypress Solutions (c) 2020
VER=1.1.0
REPOSITORY="https://demo.cypress.bc.ca/files/fw"
RSYSLOG_ID="iot"
RSYSLOG_LVL="alert"
RSYSLOG_FACILITY="local0"
DEVICE_SPECIFIC_FW_IMG="cypress-image-ctm-one.tar.xz"
LOCAL_FW_UPGRADE_JOB_ID="LOCAL_FW_UPGRADE"

WGET_ARGS="--tries=3"
IMG_SRC_DIR="/var/data/fw"
FW_IMG_PATTERN="${IMG_SRC_DIR}/*.tar"
TMP_FW_IMG="${IMG_SRC_DIR}/upgradefw_tmp_img.tar"
FW_UPGRADE_RUNNING_FLAG="/tmp/fw_upgrade"

cleanup_install_files()
{
    rm ${FW_IMG_PATTERN} &> /dev/null
    # resume normal led mode
    echo "0" > /sys/kernel/ctm_led/diag
}

err_cleanup_and_exit()
{
    cleanup_install_files
    rm ${FW_UPGRADE_RUNNING_FLAG} &> /dev/null
    /usr/bin/cmd pwr override 0
    if [ -f "/var/volatile/ctm/FW_JOBID" ]; then
       jobId=`cat /var/volatile/ctm/FW_JOBID`
    else
       jobId=${LOCAL_FW_UPGRADE_JOB_ID}
    fi
    payload='{"jobId":"'
    payload+=$jobId
    payload+='","rc":-1}'

    /usr/bin/mosquitto_pub -h 'localhost' -t 'v1/device/job/'$jobId'/update' -m $payload 
    logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} FW upgrade error:$1
    echo $1 > /var/run/FW_ERR_CODE
    exit 1
}

/usr/bin/cmd pwr override 1
touch ${FW_UPGRADE_RUNNING_FLAG}

# for backward compatibility when downgrading to a FW older than 1.2.x generate md5sum of config 
[ -f /var/data/ctm/config.json ] && /usr/bin/md5sum /var/data/ctm/config.json | /usr/bin/cut -c -32 > /var/data/ctm/config.md5

# strip everything until the last slash
fwimg=$(echo $1 | awk -F'/' '{print $NF}')
logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Start (${fwimg})"
if [ -z ${fwimg} ];then
    logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "No firmware image specified"
    echo "No firmware image specified."
    err_cleanup_and_exit 107
fi

url=$2
if [ -z ${url} ];then
    echo "No repository URL specified, using default"
    logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "No repository URL specified, using default"
    url=${REPOSITORY}
fi

dload=1
is_local_upgrade=0
br=""
if [ "${url}" = "local-web" ];then
    echo "Installing firmware from local webif"
    is_local_upgrade=1
    dload=0
elif [ "${url}" = "localhost" ];then
    echo "Installing firmware from local console"
    is_local_upgrade=1
    dload=0
fi

# if only user is given, it's token for iot server
user=$3

# may be provided if target URL is a ftp server
pw=$4

# download the firmware image .tar file
cd ${IMG_SRC_DIR}
if [ "${dload}" = "1" ];then
    echo "downloading firmware image:" ${url}/${fwimg}
    logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "downloading firmware image: ${url}/${fwimg}"
    if [ -n "$user" -a -n "$pw" ]; then
        action=$(/usr/bin/wget ${WGET_ARGS} --ftp-user=$user --ftp-password=$pw -q ${url}/${fwimg} -O ${TMP_FW_IMG})
    elif [ -z ${user} ];then
        action=$(/usr/bin/wget ${WGET_ARGS} -q ${url}/${fwimg} -O ${TMP_FW_IMG})
    else
        action=$(/usr/bin/wget --no-check-certificate ${WGET_ARGS} -q ${url}/${fwimg}?token=${user} -O ${TMP_FW_IMG})
    fi
    if [ $? -ne 0 ]; then
        echo "Error downloading image"
        logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Error downloading image"
        err_cleanup_and_exit 108
    fi
else
    mv ${fwimg} ${TMP_FW_IMG}
fi

#clean up prev files if they exist
mv ${TMP_FW_IMG} ${TMP_FW_IMG}.tmp
rm ${IMG_SRC_DIR}/*.tar
mv ${TMP_FW_IMG}.tmp ${TMP_FW_IMG}

# extract tar
# var/data dir for payload
rm -rf ${IMG_SRC_DIR}/.upgrade >/dev/null
mkdir ${IMG_SRC_DIR}/.upgrade
echo "Extracting image files" 
logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Extracting image files"
action=$(tar xvf ${TMP_FW_IMG} -C ${IMG_SRC_DIR}/.upgrade)

# calculate md5 of downloaded img file
cd ${IMG_SRC_DIR}/.upgrade
echo "Verifying firmware image"
logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Verifying firmware image"
retval=$(md5sum -c md5sum.txt)
if [ $? -eq 0 ];then
    echo "Checksum OK"
    logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Checksum OK"
else
    echo "Checksum FAIL"
    logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Checksum FAIL"
    err_cleanup_and_exit 109
fi

# verify image is for ctm-one series
if [ ! -f "${DEVICE_SPECIFIC_FW_IMG}" ]; then
    echo "Firmware incompatible with device"
    logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Firmware incompatible with device"
    err_cleanup_and_exit 110
fi

# verify the signatures
if [[ $fwimg == *"fs-1.3."* ]]; then
    echo "Skip signature check for 1.3.x versions of FW"
    logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Skip signature check for 1.3.x versions of FW"
else
    # verify the FW signature
    cmd signature fw_image.sha256.base64 ${DEVICE_SPECIFIC_FW_IMG}
    if [ $? -eq 0 ];then
        echo "Firmware Signature OK"
        logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Firmware Signature OK"
    else
        echo "Firmware Signature FAIL"
        logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Firmware Signature FAIL"
        err_cleanup_and_exit 111
    fi

    # verify the install script signature
    cmd signature install.sha256.base64 install.sh
    if [ $? -eq 0 ];then
        echo "Install Script Signature OK"
        logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Install Script Signature OK"
    else
        echo "Install Script Signature FAIL"
        logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Install Script Signature FAIL"
        err_cleanup_and_exit 113
    fi

    # verify the app platform signature
    if [ -f "app_platform.ipk" ]; then
        cmd signature app_platform.sha256.base64 app_platform.ipk
        if [ $? -eq 0 ];then
            echo "App Platform Script Signature OK"
            logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "App Platform Signature OK"
        else
            echo "App Platform Signature FAIL"
            logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "App Platform Signature FAIL"
            err_cleanup_and_exit 114
        fi
    fi

    # verify the python package
    if [ -f "ctm_one_python_packages.tar" ]; then
        cmd signature ctm_one_python_packages.sha256.base64 ctm_one_python_packages.tar
        if [ $? -eq 0 ];then
            echo "Python3 Package Signature OK"
            logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Python3 Package Signature OK"
        else
            echo "Python3 Package Signature FAIL"
            logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Python3 Package Signature FAIL"
            err_cleanup_and_exit 115
        fi
    fi
fi


# determine current rootfs
crootnum=$(cat /proc/cmdline|awk -Fmmcblk1p '{print $2}'|awk '{print $1}')
if [ "$crootnum" -eq "1" ];then
    croot=/dev/mmcblk1p1
    broot=/dev/mmcblk1p2
elif [ "$crootnum" -eq "2" ];then
    croot=/dev/mmcblk1p2
    broot=/dev/mmcblk1p1
else
    echo "can't determine current rootfs partition"
    logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "can't determine current rootfs partition"
    err_cleanup_and_exit 116
fi

# trigger sweeping red
echo "7" > /sys/kernel/ctm_led/diag

# enter img src dir, source and execute the install script
cd ${IMG_SRC_DIR}
source ${IMG_SRC_DIR}/.upgrade/install.sh
ctm_one_upgrade_fw $croot $broot
ret=$?

cleanup_install_files

if [ "$ret" = "0" ]; then
    /bin/cp -f /etc/version  /var/data/ctm/FIRMWARE_UPDATED
    echo "Firmware update completed successfully - rebooting now!"
    logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} Success
    /usr/bin/cmd pwr override 0
    while :
    do
        /usr/bin/cmd pwr mode 3
        sleep 5
    done
fi

echo "Firmware installation failed with return code "$ret
logger -p ${RSYSLOG_FACILITY}.${RSYSLOG_LVL} -t ${RSYSLOG_ID} "Firmware installation failed with return code: $ret"
err_cleanup_and_exit 117
