#!/bin/bash

source /ciena/scripts/utils.sh

upgrade_version="1.0"

default_image=/ciena/images/bootjumper.img
blacklist=/ciena/images/bootjumper-blacklist
mtddev="/dev/mtd/bootjumper" 
debugswitch="/mnt/sysfs/skip-bootjumper-upgrade"

page_size=512


#--------------------------------------------------------------------

die()
{
    echo "$1"
    exit 1
}

#--------------------------------------------------------------------

now()
{
    date '+%s'
}

#--------------------------------------------------------------------

run_cmd()
{
    # $1: Title
    # $2: Command

    printf '  * %-50.50s ' "$1"  
 
    local _start=$(now)
    eval "$2 &>/dev/null" || die 'FAILED'
    local _diff=$(($(now) - _start))
 
    [ ${_diff} -eq 0 ] && _diff='< 1'
    echo "OK [${_diff}s]"
}

#--------------------------------------------------------------------

erase_part()
{
    # $1: Device Name

    flash_eraseall -q $1
}

#--------------------------------------------------------------------

write_part()
{
    # $1: Device Name
    # $2: Partition input file

    dd bs=$page_size if=$2 of=$1 
}

#--------------------------------------------------------------------

verify_part()
{
    # $1: Device name
    # $2: Partition input file

    local image_size=$(stat -c'%s' "$2" 2> /dev/null) || return 1
    cmp --bytes=$image_size $1 $2
}

#--------------------------------------------------------------------

md5sum_part()
{
    # $1: Device name
    # $2: Size

    dd bs=$2 count=1 if=$1 2>/dev/null | md5sum | cut -f1 -d' '
}

#--------------------------------------------------------------------

upgrade_required()
{
    # Return true if an upgrade is recommended 

    local board=$(get_board_name)

    [ -z "$board" ] && return 1

    [ -e "$blacklist" ] || die "Error: missing $blacklist"

    awk -v board="$board" -v listfile="$blacklist" ' 
        BEGIN { md = 0; rc = "upgrade not required" } 

        /^[[:space:]]*#/ || !NF { next }

        # board <x> length <n> [#.*]
        /^board/ {
            md = 0

            if ($2 == board) {
                c = "/ciena/scripts/update_bootjumper --md5 --size " $4
                c | getline md
                close( c );

                if (md !~ /^[[:xdigit:]]{32}$/) {
                    print "Warning: malformed md5 \"" md "\""
                }

            } 

            next
        }
    
        /^.[[:space:]]*[[:xdigit:]]{32}[[:space:]]*#?/ {
            if (md && $1 == "-" && $2 == md) {
                system("/ciena/bin/evt_log ALERT \"bootjumper update required (" md ")\"");
                rc = "recommend upgrade (" NR ")"; last
            }

            next
        }

        1 { print "Warning: " listfile " line " NR ": malformed input" }

        END {
            print "bootjumper - " rc
            exit rc ~ /^recommend/ ? 0 : 1
        }
    
    ' $blacklist

}


#--------------------------------------------------------------------

usage()
{
    echo
    echo "Usage:"
    echo -e "\t $0    [options] [--] [image filename]"
    echo
    echo "Upgrade or verify the bootjumper image"
    echo
    echo "Options:"
    echo -e "\t-b,--if-blacklisted\tUpdate only if the current image has been blacklisted."
    echo -e "\t-c,--compare \t\tVerify the image against the given image."
    echo -e "\t-m,--md5     \t\tRun md5sum on the image. --size required."
    echo -e "\t-n,--no-prompt\t\tDon't require user input."
    echo -e "\t-s,--size=<size>\tImage size in bytes."
    echo -e "\t-h,--help    \t\tPrint usage."
    echo -e "\t-v,--version \t\tPrint script version."
    echo
    echo -e "\tDefault Image: $default_image"
    echo

    exit $1
}

#--------------------------------------------------------------------

version() {
        echo "version $upgrade_version"
        exit 0
}

#--------------------------------------------------------------------

[ -e $debugswitch ] && echo "$debugswitch exists" && exit 0 


#
# Process options
#

longoptions="if-blacklisted,compare,debug,help,md5,no-prompt,size:,version"
shortoptions="bcdhms:v"

opts=`getopt --name=$0 --options="$shortoptions" --longoptions="$longoptions" -- "$@"`

[ $? -eq 0 ] || usage 1

eval set -- "$opts"

while true; do
    case "$1" in
    -b | --if-blacklisted) option_blacklist=1;  shift ;;
    -c | --compare)        option_compare=1;    shift ;;
    -m | --md5)            option_md5=1;        shift ;;
    -n | --no-prompt)      option_noprompt=1;   shift ;;
    -s | --size)           option_size=$2;      shift; shift ;;
    -h | --help)           usage 0;             shift ;;
    -v | --version)        version;             shift ;;
    --debug)               option_debug=1;      shift ;;
    --)                                         shift; break ;;
    *)  die 4 "Unhandled option $1";            shift ;;
    esac
done

option_image=$1

#
# Ensure running this script make sense 
# 

[ -e $mtddev ] || die "Bootjumper upgrade not supported" 

#
# md5sum on specified bank. --size option is required
#

if [ "$option_md5" ]; then
    [ -n "$option_size" ]       || die "Missing --size"
    [ -z "$option_compare" ]    || die "--compare and --md5 are incompatible"
    [ -z "$option_blacklist" ]  || die "--if-blacklist and --md5 are incompatible"

    md5sum_part $mtddev $option_size
    
    exit $?
fi

#
# Sanitize image file 
#

[ -n "$option_image" ] || option_image=$default_image
[ -f "$option_image" ] || die "Image file $1 does not exist"

#
# Compare/Verify. Image file is required
#

if [ "$option_compare" ]; then 
    [ -z "$option_blacklist" ] || die "--if-blacklist and --compare are incompatible"

    run_cmd "Verifying bootjumper ($mtddev)"  "verify_part $mtddev $option_image"

    exit $?  
fi

#
# Check blacklist 
#

if [ "$option_blacklist" ]; then 
     upgrade_required || exit 0
fi

#
# Write/Update image  
# 

echo "This script will update the bootjumper. Interrupting this operation"
echo "will result in a board that will not boot."

if [ -z "$option_noprompt" ]; then 
    read -p "Type yes to continue.." ans

    [ ${ans}x = "yesx" ] || exit 1
fi

run_cmd "Erase  ($mtddev)"  "erase_part  $mtddev"
run_cmd "Write  ($mtddev)"  "write_part  $mtddev $option_image"
run_cmd "Verify ($mtddev)"  "verify_part $mtddev $option_image"

version=$(/ciena/bin/fw_version $option_image | /usr/bin/tr -dc "[0-9]")

[ ${version}x = "x" ] && version="<unknown>"

/ciena/bin/evt_log ALERT "bootjumper upgraded to version $version"

