#!/bin/sh

# default_fw_program.sh - tool to update various devices by using
#                         default firmware images from file system
PATH=$PATH:/usr/local/bin
. sig_catcher

usage()
{
cat << USAGE_HERE
Usage:  default_fw_program.sh <option> <device> [param]
    <option>:
        -p : programming the device
        -v : show the version of the device
    <device>:
        it could be all, smart_battery, eth_switch, pcie_switch, fan, support_fpga, ddr_eeprom, ebod.
    [param]:
        if device pcie_switch, param is PCIE switch ID
            RazorL:  PCIe switch ID: 0
        if device is fan controller, param is fan module number
            fan module numebr: 1~3
        No need to specify param for Other devices

    example: default_fw_program.sh -p all  => Program all devices with default images/configuration files.
        default_fw_program.sh -p support_fpga   =>Program the image into support fpga
        default_fw_program.sh -p fan 1          =>Program the image into fan module 1
        default_fw_program.sh -p eth_switch 0   => Program the file to the ethernet switch on controller.
        default_fw_program.sh -p pcie_switch 0  => Program the file to the pcieswitch0 
        default_fw_program.sh -v all    =>Get the version of all devices
USAGE_HERE
    exit 1
}
disable_interrupt()
{
    #add the signal number which you want to disable it
    trap "" INT
}

enable_interrupt()
{
    trap INT
}

check_slot()
{
    local ret_code=0
    cmd_res=$(gpiotool 10 --get-data)
    case "$cmd_res" in
        *Low*) #Slot A
            ret_code=0;
            ;;
        *High*) #Slot B
            ret_code=1;
            ;;
    esac
    return $ret_code
}

check_update_result()
# $1: return value
# $2: device
{
    result=-1
    case ${2} in
        fan)
            if [ $1 -eq 0 ]; then
                echo "Please reset SP to complete the update process of device"
                result=0
            fi
            ;;
        eth_switch)
            if [ $1 -eq 0 ]; then
                echo "Please reset SP to complete ethernet switch update process"
                result=0
            fi
            ;;

        support_fpga)
            if [ $1 -eq 0 ]; then   
                echo "Please turn off the power supplies to complete the update process"
                result=0
            fi
            ;;
        pcie_switch)
            if [ $1 -eq 0 ]; then
                echo "Please system power cycle to complete the update process"
                result=0
            fi
            ;;  
        *)
            if [ $1 -eq 0 ]; then
                echo "Update request completed"
                result=0
            fi
            ;;
    esac

    if [ $result -lt 0 ]; then
        echo "The update process has failed, please contact support."
        exit 1
    fi
}
check_device_id()
#$1 : device id
#$2 : min device id
#$3 : max device id
{
    local id=${1}
    local min_id=${2}
    local max_id=${3}
    if [ -z ${id} -o -z ${min_id} -o -z ${max_id} ];then
            usage
    fi
    if [ ${id} != "all" ]; then
        if [ ${id} -lt ${min_id} -o ${id} -gt ${max_id} ]; then
                usage
        fi
    fi

}

check_version_result()
# $1: return value
# $2: version
{
    if [ $1 -eq 0 ]; then
        echo "$2"
    else
        echo "not present"
    fi
}

validate_image()
# $1: path
# $2: filename extention name
# $3: device
#
{
    cd $1
    file_count=$(ls *.$2 | wc -w)
    if [ $3 = "ebod" ] ; then
       limit=2
    else
       limit=1
    fi

    if [  $file_count -gt $limit ] ; then
        echo "$3 device: unexpected $file_count firmware files found!"
        echo "$(ls *.$2)"
        echo ""
        echo "Aborting update!"
        exit 1
    fi
}
get_device_version()
# $1: device
# $2: device ID
{
    echo ""
    echo "${1}:"
    
    case ${1} in
        smart_battery)
            bat_rev=$(batTool hw_rev)
            check_version_result $? "$bat_rev"
            ;;
        eth_switch)
            if [ $platform == "RazorL" ] && [ $brd_rev -lt $razorl_rev_p2i ] ; then
                echo "Command not supported on pre-p2i RazorL motherboards"
                exit 1
            fi

            echo -n "mb: "
            ethswitch_rev=$(switch_config_version.sh 0)
            check_version_result $? "$ethswitch_rev"
            ;;
        pcie_switch)
            case $platform in
            RazorL)
                #valid id is 0 or 1
                check_device_id ${2} 0 1
            ;;
            RazorM|RazorS)
                #valid id is 1
                check_device_id ${2} 1 1
            ;;

            *)
                echo "Command not supported on this platform"
                exit 1
            ;;
            esac

            if [ ${2} != "all" ]; then
                pcieswitch_ids=${2}
            fi

            for id in ${pcieswitch_ids}
            do
                echo -n "id$id: "
                pcieswitch_rev=$(pcieswitch_eeprom.sh version $id)
                check_version_result $? "$pcieswitch_rev"

            done

            ;;
        fan)
            if [ "$platform" = "RazorL" ]; then
                check_device_id ${2} 1 3
            else
                echo "No fans for this platform"    
            fi

            if [ ${2} = "all" ]; then
                if [ "$platform" = "RazorL" ]; then
                    fan_ids="1 2 3"
                fi
            else
                fan_ids=${2};
            fi
            if [[ $? -eq 0 ]]; then
                                check_slot
                                slot=$?
                                for id in ${fan_ids}
                                do
                                       if [ $id -le 3 ] ; then
                                          id1=$id;
                                       else
                                          id1=`expr $id - 3 ` ;
                                       fi
                                       if [ $slot -eq 0 ] ; then #Slot A
                                           if [ $id -le 3 ] ; then
                                              echo " Fan_A$id1:";
                                           else
                                              echo " Fan_B${id1}:";
                                           fi
                                        else #Slot B
                                              echo " Fan_B${id1}:";
                                        fi
                                        echo -n "    Front: "
                                        fanfront_rev=$(fan_controller 0x${id}1 version | grep Version:)
                                        check_version_result $? "$fanfront_rev"


                                        echo -n "    Back: "
                                        fanback_rev=$(fan_controller 0x${id}2 version | grep Version:)
                                        check_version_result $? "$fanback_rev"

                                done
                        fi

            ;;
        support_fpga|ebod)
            cpldfpga_rev=$(cpld_program.sh get_version ${1})
            check_version_result $? "$cpldfpga_rev"
                ;;
        ddr_eeprom)
            ddreeprom_rev=$(ddr_eeprom_version.sh)
            check_version_result $? "$ddreeprom_rev"
            ;;

        *)
            echo "Unknown device: ${1}"
                usage
            exit 1
            ;;
    esac        
}

fw_device_update()
# $1: device
# $2: device ID
# $3: platform
{
    local cpldfpga_filename
    local res=0
    echo ""
    echo "Updating ${1}:"
    echo ""

    case ${1} in
        smart_battery)
            echo "battery flash /firmware/$platform/battery force"
            ipmi oem battery flash default_image force
            check_update_result $? ${1}
            ;;
        eth_switch)
            if [ $platform == "RazorL" ] && [ $brd_rev -lt $razorl_rev_p2i ] ; then
                echo "Command not supported on pre-p2i RazorL motherboards"
                exit 1
            fi

            echo -n "mb: "
            echo "switch_program.sh"
            switch_program.sh
            check_update_result $? ${1}
            ;;
        pcie_switch)
            if [ ${2} != "all" ]; then
                pcieswitch_ids=${2};
            fi
            for id in ${pcieswitch_ids}
            do
                 echo "pcieswitch_eeprom.sh program_wr $id ${3} -f"
                 pcieswitch_eeprom.sh program_wr $id $3 -f
                 check_update_result $? ${1}
            done
            ;;
        fan)
            if [ ${2} = "all" ]; then
                if [ "$platform" = "RazorL" ]; then
                    fan_ids="1 2 3";
                fi
            else
                fan_ids=${2};
            fi
            thermal_policy_control.sh chk_disable
            res=$?
            if [[ $res -eq 0 || $res -eq 1 ]]; then
                for id in ${fan_ids}
                do
                    #Update firmware images
                    echo "update_fan_firmware.sh -f $id"
                    update_fan_firmware.sh -f $id
                    check_update_result $? ${1}
                done
            fi
            #If we have disabled monitoring, re-enable it
            if [[ $res -eq 1 || $res -eq 2 ]]; then 
                thermal_policy_control.sh chk_enable
            fi
            ;;
        support_fpga)

            if [ "$1" = "support_fpga" ]; then
                subdir_name="fpga"
            else
                subdir_name=$1;
            fi

            fpga_cpld_pwd="/firmware/$platform/$subdir_name"
            cpldfpga_filename_ext="bin"
            validate_image $fpga_cpld_pwd $cpldfpga_filename_ext $1
            FILE_CPLD=$(ls $fpga_cpld_pwd/*.$cpldfpga_filename_ext 2>/dev/null)
            echo "$FPGA_CPLD_PROG_TOOL program_device $1 $FILE_CPLD"
            $FPGA_CPLD_PROG_TOOL program_device $1 $FILE_CPLD
            check_update_result $? ${1}
            ;;
        ddr_eeprom)
            subdir_name=$platform
            ddr_filename_ext="txt"
            ddr_eeprom_pwd="/firmware/$subdir_name/ddr"
            validate_image $ddr_eeprom_pwd $ddr_filename_ext $1
            FILE_DDR=$(ls $ddr_eeprom_pwd/*.$ddr_filename_ext 2>/dev/null)
            echo "$DDR_PROG_TOOL $FILE_DDR"
            $DDR_PROG_TOOL $FILE_DDR
            check_update_result $? ${1}
            ;;

        ebod)
            fpga_cpld_pwd="/firmware/$platform/ebod"
            cpldfpga_filename_ext="jam"
            validate_image $fpga_cpld_pwd $cpldfpga_filename_ext $1
            
            if [ $brd_rev -ge $razorm_rev_p1b ] ; then
                FILE_CPLD=$(ls $fpga_cpld_pwd/*.$cpldfpga_filename_ext | grep -v RazorM_ebod_rev_0.6.jam 2>/dev/null)
             else
                FILE_CPLD=$(ls $fpga_cpld_pwd/*6.$cpldfpga_filename_ext 2>/dev/null)
            fi
            
            echo $VESPA_CPLD_PROG_TOOL $1 $FILE_CPLD
            $FPGA_CPLD_PROG_TOOL program_device $1 $FILE_CPLD
            retval=$?
            ;;

        *)
            echo "Unknown device: ${1}"
            usage
        ;;
    esac
}

#
# main starts here
#
platform=$(cat /var/run/platform)
brd_rev=$(cat /var/run/boardrev)
razorl_rev_p2i=3
razorm_rev_p1b=2
platform_type=1
#The supported devices are smart_battery, eth_switch, fan, pcie_switch and support_fpga
#The device will be added into supported_devices list when it is ready.
case $platform in
    RazorL)
        pcieswitch_ids="0 1"
        platform_type=0
        supported_devices="smart_battery support_fpga pcie_switch ddr_eeprom fan"
        if [ $brd_rev -ge $razorl_rev_p2i ] ; then
            supported_devices="eth_switch $supported_devices"
        fi
    ;;
    RazorM|RazorS)
        pcieswitch_ids="1"
        platform_type=1
        supported_devices="smart_battery eth_switch support_fpga pcie_switch ddr_eeprom fan ebod"
    ;;
    *)
    echo "Command not supported on this platform"
    exit 1
    ;;
esac
if [ $# -lt 2 ]; then
    usage
fi

FPGA_CPLD_PROG_TOOL=/usr/local/bin/cpld_program.sh
DDR_PROG_TOOL=/usr/local/bin/program_ddr_autoload_eeprom.sh
components=0
device_id=0
PROGRAM_OPT=0
VERSION_OPT=0

#$1 argument is option(-p or -v)
while getopts vp fwoption
do
    case $fwoption in
        p)
            PROGRAM_OPT=1

            ;;
        v)
            VERSION_OPT=1
            ;;
        *)
            echo "-p or -v option must be specified."
            usage
            ;;      
    esac
    shift
done


#after run "shift" command
#$1 argument is device
#$2 argument 
#    i. device ID when device is eth_switch, pcie_switch, or fan devices.

if [ ${1} = "all" ]; then
    components=$supported_devices
    device_id="all"
else
    components=${1}
    device_id=${2}
fi

if [ -z $device_id ] && [ $1 == "pcie_switch" ] ; then
    echo "deviceId is not set. Exiting"
    exit 1
fi

if [ $PROGRAM_OPT -eq 1  ]; then
    disable_interrupt
    for device in ${components}
    do
        fw_device_update $device $device_id $platform_type
    done
    if [ "$device_id" = "all" ]; then
        echo "Please turn off the power supplies to complete the update process"
    fi
    enable_interrupt
fi
if [ $VERSION_OPT -eq 1 ]; then
    for device in ${components}
    do
        get_device_version $device $device_id
    done
fi

if [ $VERSION_OPT -eq 0 -a $PROGRAM_OPT -eq 0 ]; then
    echo "Unknown option"
    usage
    exit 1
fi

exit 0

