#!/bin/sh
#
#    Copyright (c) 2013, 2018 Brocade Communications Systems, Inc.
#    All rights reserved.
#
#    Description:
#		This script is a different flavor of preinstall checking.
#		Essentially it is intended to make easier the
#		Compatibility checking of newly introduced features
#		which are introduced in new releases but also
#		back ported to Older maint/patch release versions as well
#
#		The current preinstall checking design is to always run the 
#		preinstall of the higher of the two versions.
#		This does not lend itself to checking whether
#		the new firmware being downloaded supports a given feature,
#		except through a complex specific version checking.
#
#		This scheme requires such new features to be identified by
#		a tag in preinstall script that helps identify if the new release
#		being downloaded supports the given feature or not.
#
#		Enhancements to this script can then be done to perform
#		feature compatibility checking of such features,
#		and blocking downloads where appropriate.
#
#		If is important that each feature compatibility check
#		- Appends the corresponding error message to BOTH  ERROR/STATUS FILES
#		  STATUS_FILE and BNA_STATUS_FILE
#		- Increments the return code count (or alternately set it to non zero)
#		- return STS_ERR (this is not required but recommended for consistency)
#		This will permit a one pass checking of all features
#		And a cumulative message reflecting all corrective actions.
##############################################################################
# Trap / Ignore SIGINT so user cannot interrupt this script with ^C
trap "" 2
trap "" SIGPIPE

CUR_PREINST_FILE=/sbin/preinst
NEW_PREINST_FILE=$1	# This is the preinst file of the new version being downloaded.
                    # It indicates if it supports these new features:
                    # - ZENTRON 4 CP, 8548 Rev 31 CPU
                    # - nonDFE

###############################################################################
##                            CHECK FEATURE TAGS                             ##
## This section is to define tags for the current running version of code as ##
## opposed to the target version of code. Tags defined in the preinst script ##
## and then checked here will check if the target version of code supports a ##
## given feature. The tags defined here and then checked in the preinstall   ##
## script have the opposite effect where the defined feature is supported on ##
## the current version of code, and then can be used to do conditional check ##
## from the preinst script as needed.                                        ##
##                                                                           ##
## Please do not remove these lines unless a given feature or functionality  ##
## is being removed from the current version of code.                        ##
###############################################################################

EXTN_FWDL_PREP_SUPPORTED="Current version supports extn fwdl-prep feature."

###############################################################################
##  END of CHECK FEATURE TAGS Section.....                                   ##
###############################################################################

##########################################################
#    Begin Common code for Preinst / check_features      #
#    Need to move this to common file shared by the      #
#    2 scripts to prevent finding/fixing same bug twice  #
##########################################################

PATH=/bin:/usr/bin:/sbin:/usr/sbin # adding comment to protect from DOS conversion
#
# Common variables
#
NULL=/dev/null
if [ "$DEBUG" = 1 ]; then
	ECHO='echo -e'
else
	ECHO=:
fi

# This should match the file name in src/lib/upgrade/upgrade.c
STATUS_FILE=/tmp/fwdl_err.txt
BNA_STATUS_FILE=/tmp/bna_fwdl_err.txt
EULA_FILE=/etc/fabos/eula.txt
BNA_WARN_STATUS_FILE=/tmp/bna_fwdl_warn.txt

#
# Error codes - these have to match the error codes
# in fwdl.h.
#

STS_OK=0
STS_ERR=255

RET_CODE=${STS_OK}
RET=${STS_OK}

export CHASSIS_ROLEID=0
if /fabos/bin/fosconfig --show | grep "Virtual Fabric" | grep enabled > /dev/null 2>&1 ; then
	VF_ENABLED=$STS_ERR;
else
	VF_ENABLED=$STS_OK;
fi

# cpid
#
# Retrieve the current Control Processor ID
#
cpid() {
	sed -n -e 's/^Control.\+No: \([[:digit:]]\{1,\}\)$/\1/gp'
}

#
# swbd
#
# Retrieve the current system platform name, of the form "SWBDn", where n
# is cardinal number, assuming a sin/hinv input stream.
#
swbd() {
	sed -n -e 's/^.\+\(SWBD[[:digit:]]\{1,\}\).\+$/\1/gp'
}

# Determine the system platform identifier.
SWBD=`sin | swbd 2> ${NULL}`
CPID=`sin | cpid 2> ${NULL}`

otherhost(){
	case ${SWBD##SWBD} in
	'62')
	    printf 127.1.1.$((8 - CPID % 2))
	    ;;
	'77')
	    printf 127.1.1.$((6 - CPID % 2))
	    ;;
	'141')
		printf 127.1.$((17 - CPID % 2)).$((17 - CPID % 2))
		;;
	'142')
		printf 127.1.$((15 - CPID % 2)).$((15 - CPID % 2))
		;;
	'165' | '166')
	    printf 127.3.1.$((2 - CPID % 2))
	    ;;
	*)
	    printf 10.0.0.$((6 - CPID % 2))
	    ;;
	esac
}

HASHOW="$(/fabos/bin/hashow)"
hashow_cmd=$(ls /fabos/cliexec/hashow)
if [ "$hashow_cmd" != "/fabos/cliexec/hashow" ]; then
       	hashow_cmd="/fabos/bin/hashow"
fi

othercp(){
        that=${HASHOW#*Remote CP \(Slot}
        that="${that%%,*}"
        printf $(($that - 5))
}

ha_role() {
 	case "$($hashow_cmd | ( read a; echo $a ))" in
	    *Local*Active*)
	    printf "ACTIVE"
 	    ;;
	    *Local*Standby*)
	    printf "STANDBY"
 	    ;;
	    *"Not supported"*)
	    printf "ACTIVE"
 	    ;;
	    *)
	    printf "STANDBY"
	    ;;
	esac
}

HA_ROLE=$(ha_role)
if [ $HA_ROLE == "ACTIVE" ]; then
    ACTIVECP=1
fi

ha_state() {
    sync=`/fabos/cliexec/hashow | sed -n -e 's/^.\+\(State sync\).\+$/\1/gp'`

    if [ "$sync" != "State sync" ]; then
	    printf "NOSYNC"
    else
	    printf "SYNC"
    fi
}

HA_STATE=$(ha_state)

correcthost() {
    if [ $ACTIVECP ] ; then
    "$@"
    else
    /usr/bin/rsh -n $(otherhost) ROLE_ID=root LOGIN_ID=root CURRENT_AD=0 "$@"
    fi
}

context_switch()
{
    if [ $VF_ENABLED -ne $STS_OK ]; then
        if [ "$1" != "chassis" ]
        then
            eval $(/fabos/cliexec/lscfg_util --switch $1)
        else
            eval $(/fabos/cliexec/lscfg_util --chassis)
            #export CHASSIS_ROLEID=0
        fi
    fi
    # glb_vf_id="$CURRENT_VF"
    # glb_ls_id="$FABOS_SWITCHNO"
    export ROLE_ID=root
}

#
# both Active and Standby have the information of
# VF and logical switches configured.
#
# VF case: on Standby CP, in order to login to each logical switch, 
# we need to set CHASSIS_ROLEID FABOS_SWITCHNO CURRENT_VF in rsh.
#
correcthost_to_curr_vfid() {
	if [ $ACTIVECP ] ; then
		# for_all_context already did "context_switch --switch vfid"
		"$@"
	else
		if [ $VF_ENABLED -eq $STS_OK ]; then
			# VF disabled
			/usr/bin/rsh -n $(otherhost) ROLE_ID=root LOGIN_ID=root CURRENT_AD=0 "$@"
		else
			# VF enabled, for_all_context changed glb_ls_id and glb_vf_id to each logical switch's
			/usr/bin/rsh -n $(otherhost) ROLE_ID=root LOGIN_ID=root CHASSIS_ROLEID=0 FABOS_SWITCHNO=$glb_ls_id CURRENT_VF=$glb_vf_id CURRENT_AD=0 "$@"
		fi
	fi
}


# executes the provided function in the context of all configured virtual
# fabrics, and logical switches on the active and standby CP's to determine
# if a critera is met
correcthost_all_vfs() {
	if [ $VF_ENABLED -ne $STS_OK ]; then
		# VF is enabled
		if [ $ACTIVECP ] ; then
			for_all_contexts correcthost_to_curr_vfid $@
		else
			# this is the standby cp, examine the configuration of the
			# active cp
			for_all_contexts_standby correcthost_to_curr_vfid $@
		fi
	else
		correcthost_to_curr_vfid $@
	fi
	if [ $? -eq 0 ]; then
		return $STS_OK
	else
		return $STS_ERR
	fi
}

# Helper function. Loop over the valid fabric IDs running the test that is passed as
# a parameter. As soon as one test fails then return $STS_ERR. If all pass then
# return $STS_OK.
# WARNING. This command will change to a random context (The first one that fails
# the test or the last context if all pass). Random terms in case someone is searching
# this file, VF Virtual Fabric AD setcontext FID context and wants to find this warning
for_all_contexts(){
	for FID in ${CONTEXTS} ; do
		context_switch $FID
		glb_vf_id="$CURRENT_VF"
		glb_ls_id="$FABOS_SWITCHNO"
		
		if "$@"
		then	$ECHO -n "$FID-passed "
		else	$ECHO -n "$FID-failed "
			    return $STS_ERR
		fi
	done
	return $STS_OK
}

for_all_contexts_standby(){
	rval=$STS_OK
	/bin/ln -s /fabos/cliexec/lscfg_util /fabos/link_sbin/lscfg_test 2> /dev/null
	local_flag=$?
	export PATH=/fabos/link_bin:/bin:/usr/bin:/sbin:/usr/sbin:/fabos/link_abin:/fabos/link_sbin:/fabos/link_rbin:/fabos/factory:/fabos/xtool
	lscfg_test --all | grep -e "[0-9]" | grep -v "Total" |
	while read glb_ls_id glb_vf_id role
	do
		context_switch $glb_vf_id
		if "$@"
		then	$ECHO -n "$glb_vf_id-passed "
		else	$ECHO -n "$glb_vf_id-failed "
			# note the following return just return from the "|" subshell
			return $STS_ERR
		fi
	done
	if [ $? -ne $STS_OK ]; then rval=$STS_ERR; fi
	if [ $local_flag -eq 0 ];then /bin/rm /fabos/link_sbin/lscfg_test 2> /dev/null; fi
	return $rval
}

is_fwdl_arg() {

    #
    # Reads command line args passed to firmwaredownload
    # and checks if the required argument is specified
    #
    for arg in $(/usr/bin/tr '\0' ' ' < /proc/$PPID/cmdline)
    do
            case $arg in
            (-*$1*)
        return $STS_OK
        ;;
            esac
        done
        return $STS_ERR
}


########################################################
#    End Common code for Preinst / check_features      #
########################################################

rc=$STS_OK
##############################################################################
#       Zentron 4 compatibility checking
# Zentron 4 CPs (i.e 8548 Rev (SVR) 31 CPU based CPs)
# MUST NOT be permitted to be upgraded or downgraded to firmware versions that
# Do not have the enhancement to support this new CPU.
# Any accidental firmwaredownload (on Z4 CP blade) to such firmware versions
# Will Render the CP Blade into a Brick - that will need to be RMA'd to fix.
#
# Hence the need for this fw compatibility check and blocking of older fw
# on the newer (Z4 CP) platforms.
#
# The enhanced firmware to support the new hardware is identified by the
# "CP31_ZENTRON4_SUPPORTED" string in the preinstall scripti (preinst.sh.in).
#
# This Checks if CP is new - 8548E rev (SVR) 31 CPU
# If so then it block downgrade to prior releases 
# that do not support the new CPU
#
##############################################################################
Z4_CP_ERR_MSG="The new firmware is not compatible with 
            the 8548 Rev 3.1 CPU based CP blade in this system."
check_new_8548_CP_fw_compatibility()
{
	# Do not do Z4 compatibility check for Odin.
	# Odin was always shipped with version 31 cpu.
	if  [ ${SWBD##SWBD} -eq 133 ]; then
		return $STS_OK
	fi

    chipset=`cat /proc/cpuinfo | awk '/chipset/ {print $3}'`
    if [ -z $chipset ] || [ $chipset != 8548E ]; then
        # This is not a 8548E CP return OK
        return $STS_OK
    fi

    revision=`cat /proc/cpuinfo | awk '/SVR/ {print $3}' | awk  -F 'x' '{print $2}'`
    let revision=$revision%100

    #revision=31 #uncomment to test with current 2.0 CP faked to new
    new_cp_supported=`grep -c "CP31_ZENTRON4_SUPPORTED" $NEW_PREINST_FILE`
    result=`expr $revision '>=' "31" 2>/dev/null`
    if [ $result == 1  ]; then
        # Current CP is new - 8548E CP Rev (SVR) 31
        # check if the firmware being downloaded supports new CP 
        if [ $new_cp_supported -eq 0 ]; then
            # New 8548E Rev (SVR) 31 CP But Firmware is older version.
            # Cannot downgrade to fw version that does not support this CP
            let rc=$rc+1
            echo -e $rc:	$Z4_CP_ERR_MSG >> $STATUS_FILE
            echo -e $rc:	$Z4_CP_ERR_MSG >> $BNA_STATUS_FILE
            return $STS_ERR
        else
            # New 8548E Rev (SVR) 31 CP and new firmware is compatible.
            return $STS_OK
        fi
    fi

    #
    # Current CP is Old i.e. 8548E but less than Rev (SVR) 31
    # Next check the redundant CP for the new rev (SVR) 31 CPU
    # if redundant CP is new then block downgrades to 
    # firmware versions that do not support the new CP
    #
    if [ $(ha_state) == "SYNC" ]; then
        revision=`/usr/bin/rsh -n $(otherhost) ROLE_ID=root LOGIN_ID=root CURRENT_AD=0 /bin/cat /proc/cpuinfo | /bin/awk '/SVR/ {print $3}' | awk  -F 'x' '{print $2}'`

        # if revision is not defined then return STS_OK
        if [ -z $revision ]; then
            return $STS_OK
        fi

        let revision=$revision%100
        #revision=31 #uncomment to test with current 2.0 StbyCP faked to new
        result=`expr $revision '>=' "31" 2>/dev/null`
        if [ $result == 0  ]; then
            # Other CP is also old - so no compatibility checking necessary.
            return $STS_OK
        fi
    else
        # This is a single CP system or non-redundant chassis system.
        # And the CP is old -  8548E but not Rev 31
        return $STS_OK
    fi

    # Here Current CP is Old but the Other CP is new 
    # Check if the preinstall of the new firmware being downloaded
    # Supports the new hardware

    if [ $new_cp_supported -eq 0 ]; then
        # Cannot downgrade to fw version that does not support this CP
        let rc=$rc+1
        echo -e $rc:	$Z4_CP_ERR_MSG >> $STATUS_FILE
        echo -e $rc:	$Z4_CP_ERR_MSG >> $BNA_STATUS_FILE
        return $STS_ERR
    fi

    return $STS_OK
}



##############################################################################
#
# Non-DFE (Decision Feedback Equalization) Feature compatibility checks.
# If Non-DFE is enabled on any of the ports and the new firmware does not
# support this feature then firmwaredownload to that version must be blocked
# with appropriate message to disable the feature before moving to that version
#
##############################################################################

NON_DFE_ENABLED_ERR_MSG="Non-DFE is enabled and the new firmware does not support it.
\n   Please run portcfgnondfe --disable [slot/]port for all ports where it is enabled, before downloading the new firmware.
\n   Use porcfgshow to find all ports where Non-DFE is enabled."
BNA_NON_DFE_ENABLED_ERR_MSG="Non-DFE is enabled and the new firmware does not support it.
\n  Please disable Non DFE on the port using WebTools -> Port Admin -> Actions -> Non DFE.
\n  Find the list of Non DFE Enabled Ports in Port Admin table."

check_non_dfe()
{
    #
    # do not use the correcthost primitive here.
    # The preinst file is on this host and not on correcthost
    # correcthost will not work when running fwdl from standby.
    #
    non_dfe_supported=`grep -c "NON_DFE_SUPPORTED" $NEW_PREINST_FILE`
    if [ $non_dfe_supported -ne 0 ]; then
        # The new release supports this feature so ok to proceed.
        return $STS_OK
    fi

    # DFE is not supported by the new firmware.
    # Check if DFE is enabled before permitting download to a version
    # That does not support DFE and block download if enabled

    non_dfe_enabled=`correcthost /fabos/cliexec/portcfgshow | grep Non-DFE | grep -c ON`
    if [ $non_dfe_enabled -ne 0 ]; then
        # Let each failing check
        # Append its own Detailed corrective message to BOTH files:
        # - STATUS_FILE and BNA_STATUS_FILE 
        # increment return code
        let rc=$rc+1
        echo -e $rc:	$NON_DFE_ENABLED_ERR_MSG >> $STATUS_FILE
        echo -e $rc:	$BNA_NON_DFE_ENABLED_ERR_MSG >> $BNA_STATUS_FILE
        return $STS_ERR
    fi

    return $STS_OK
}




##############################################################################
#
# QSFP on ICLs Feature compatibility checks.
# Downgrade to a release that does not support this feature is not allowed
# if some of the ICL ports are connected with new QSFP which support upto 2km. 
#
##############################################################################


glb_ls_id=-1
glb_vf_id=255

ICL_QSFP_FWDL_CHECK="Downgrade is not allowed as some of the ICL ports are connected with new QSFP which support upto 2km. Please remove the QSFP(s) flagged and connect the old QSFP before proceeding with the downgrade."

check_qsfpp_icl()
{
    #
    # do not use the correcthost primitive here.
    # The preinst file is on this host and not on correcthost
    # correcthost will not work when running fwdl from standby.
    #
    qsfpp_icl_supported=`grep -c "QSFPP_ICL_SUPPORTED" $NEW_PREINST_FILE`
    if [ $qsfpp_icl_supported -ne 0 ]; then
        # The new release supports this feature so ok to proceed.
        return $STS_OK
    fi

    # QSFP_ICL is not supported by the new firmware.
    # Check if any QSFPs on ICLs. If so then block the downgrade.

	icl_fwdl_ret=`correcthost_to_curr_vfid /fabos/bin/icl_qsfp_fwdl_check 2>/dev/null | grep -E "2KM QSFP"`
	if [ $? -eq 0 ]; then
		let rc=$rc+1
		echo -e $rc:	$icl_fwdl_ret >> $STATUS_FILE
		echo -e $ICL_QSFP_FWDL_CHECK  >> $STATUS_FILE
		echo -e $rc:	$icl_fwdl_ret >> $BNA_STATUS_FILE
		echo -e $ICL_QSFP_FWDL_CHECK  >> $BNA_STATUS_FILE
		return $STS_ERR;
	fi
    return $STS_OK
}


################################################################################
#
# check for 2KM 32G QSFP ICLs support
#
QSFP_32G_FWDL_BLOCK="Downgrade is not allowed as some of the ICL ports are connected with new 2 KM 32G QSFPs. Please remove the QSFP(s) flagged and connect the old QSFP before proceeding with the downgrade."


check_2km_32G_qsfp_icl()
{
    #
    # do not use the correcthost primitive here.
    # The preinst file is on this host and not on correcthost
    # correcthost will not work when running fwdl from standby.
    #
    qsfp_32G_icl_supported=`grep -c "QSFP_32G_ICL_SUPPORTED" $NEW_PREINST_FILE`
    if [ $qsfp_32G_icl_supported -ne 0 ]; then
        # The new release supports this feature so ok to proceed.
        return $STS_OK
    fi

    # 2KM_32G_QSFP_ICL is not supported by the new firmware.
    # Check if any 2KM 32G QSFPs on ICLs. If so then block the downgrade.
    qsfp_32G_icl_fwdl_ret=`correcthost_to_curr_vfid /fabos/rbin/icl_32G_qsfp_fwdl_check 2>/dev/null | grep -E "2KM 32G QSFP"`
	if [ $? -eq 0 ]; then
		let rc=$rc+1
		echo -e $rc:	$qsfp_32G_icl_fwdl_ret >> $STATUS_FILE
		echo -e $QSFP_32G_FWDL_BLOCK  >> $STATUS_FILE
		echo -e $rc:	$qsfp_32G_icl_fwdl_ret >> $BNA_STATUS_FILE
		echo -e $QSFP_32G_FWDL_BLOCK  >> $BNA_STATUS_FILE
		return $STS_ERR;
	fi
    return $STS_OK
}

QSFP_32G_2KM_FWDL_BLOCK="Downgrade is not allowed as some of the ports are connected with 2KM 32G QSFPs. Please remove the QSFP(s) flagged and connect the supported QSFP before proceeding with the downgrade."

check_2km_32G_qsfp()
{
    #
    # do not use the correcthost primitive here.
    # The preinst file is on this host and not on correcthost
    # correcthost will not work when running fwdl from standby.
    #
    qsfp_32G_2KM_icl_non_icl_supported=`grep -c "QSFP_32G_2KM_ICL_NON_ICL_SUPPORTED" $NEW_PREINST_FILE`
    if [ $qsfp_32G_2KM_icl_non_icl_supported -ne 0 ]; then
        # The new release supports this feature so ok to proceed.
        return $STS_OK
    fi

    # 2KM_32G_QSFP is not supported by the new firmware.
    # Check if any 2KM 32G QSFPs. If so then block the downgrade.
    qsfp_32G_2KM_fwdl_ret=`correcthost_to_curr_vfid /fabos/bin/qsfp_32g_2km_fwdl_check 2>/dev/null | grep -E "2KM 32G QSFP"`
	if [ $? -eq 0 ]; then
		let rc=$rc+1
		echo -e $rc:	$qsfp_32G_2KM_fwdl_ret >> $STATUS_FILE
		echo -e $QSFP_32G_2KM_FWDL_BLOCK  >> $STATUS_FILE
		echo -e $rc:	$qsfp_32G_2KM_fwdl_ret >> $BNA_STATUS_FILE
		echo -e $QSFP_32G_2KM_FWDL_BLOCK  >> $BNA_STATUS_FILE
		return $STS_ERR;
	fi
	# control reaching here means 2KM_32G_QSFP is not supported by the new firmware.
	# And no 2KM_32G_QSFPs plugged in on non-ICL ports
	# Next check if any 2KM_32G_QSFP plugged in on ICL ports
	# if so then block - check_2km_32G_qsfp_icl will take care of that by incrementing rc.
	check_2km_32G_qsfp_icl
    return $STS_OK
}

BUF_OP_MODE_CHECK_FAILED="Downgrade is not allowed because BufOpMode is enabled on CORE blade(s).  Please disable bufopmode using the CLI \"bufopmode --resetall\" \n"
check_buf_op_mode()
{
	if  [ ${SWBD##SWBD} -eq 165 ] || [ ${SWBD##SWBD} -eq 166 ]; then
		buf_op_mode_supported=`grep -c "GEN6_BUF_OP_MODE_SUPPORTED" $NEW_PREINST_FILE`
	else
		buf_op_mode_supported=`grep -c "BUF_OP_MODE_SUPPORTED" $NEW_PREINST_FILE`
	fi
	if [ $buf_op_mode_supported -ne 0 ]; then
		# The new release supports this feature so ok to proceed.
		return $STS_OK
	fi

	# special check for v7.2.1d which also supports BUF_OP_MODE
	# but did not include the BUF_OP_MODE_SUPPORTED tag.
	buf_op_mode_supported=`grep -c "BUFOPMODE_ENABLED" $NEW_PREINST_FILE`
	if [ $buf_op_mode_supported -ne 0 ]; then
		# The new release supports this feature so ok to proceed.
		return $STS_OK
	fi

	# BUF_OP_MODE is not supported by the new firmware.
	# Check if BUF_OP_MODE is enabled on any slots. If so then block the downgrade.
	icl_slots=`correcthost_to_curr_vfid /fabos/bin/slotshow -m | grep "CORE" | awk {'print $1'}`
	if [ "$icl_slots" == "" ]; then
		return $STS_OK
	fi

	for slot in $icl_slots; do
		correcthost_to_curr_vfid /fabos/sbin/bufopmode --show $slot | grep "On" > /dev/null
		if [ $? -eq 0 ]; then
			let rc=$rc+1
			echo -e $rc:    $BUF_OP_MODE_CHECK_FAILED >> $STATUS_FILE
			echo -e $rc:    $BUF_OP_MODE_CHECK_FAILED >> $BNA_STATUS_FILE
			return $STS_ERR
		fi
	done

    return $STS_OK
}


UNSUPPORTEDPLATFORMMSG="Cannot download the requested firmware because the firmware does not support this platform. Please enter another firmware path."
check_q20_supported()
{
	q20_supported=`grep -c "Q20_SWBD134_SUPPORTED" $NEW_PREINST_FILE`
	if [ $q20_supported -ne 0 ]; then
		# The new release supports Q20 platform so ok to proceed.
		return $STS_OK;
	fi

	# Q20 is not supported by the new firmware.
	# Check if the platform is Q20. If so then block the downgrade.
	q20_platform=`correcthost_to_curr_vfid /fabos/cliexec/chassisshow | grep -c "SLKWRM0000391"`
	if [ ${SWBD##SWBD} == '134' ]; then		# Check if Qilin first
		if [ $q20_platform -ne 0 ]; then	# Then check if Qilin-24/Qilin-20 
			# We are downloading to Q20. And the new release does not support it.
			# So return error to block downgrade.
			let rc=$rc+1
			echo -e $rc:    $UNSUPPORTEDPLATFORMMSG >> $STATUS_FILE
			echo -e $rc:    $UNSUPPORTEDPLATFORMMSG >> $BNA_STATUS_FILE
			return $STS_ERR;
		fi
	fi

	# For all other platforms it is good to go.
	return $STS_OK;
}
UNSUPPORTED_DOWNGRADE_MSG="Downgrade is not allowed because root account is permanently disabled in this platform. Requested firmware does not support." 
check_permanet_root_disable_huawei_supported()
{
	huawei_banded=`correcthost_to_curr_vfid /fabos/cliexec/chassisshow | grep -c "BRD0000HU"`

	# Check if the switch is huawei banded.
	if [ $huawei_banded -ne 0 ]; then
		root_disble_supported=`grep -c "ROOT_PERMANET_DISABLE_SUPPORTED" $NEW_PREINST_FILE`
		# Check if root disable feature exist in requested firmware.
		if [ $root_disble_supported -eq 0 ]; then
			let rc=$rc+1
			echo -e $rc:    $UNSUPPORTED_DOWNGRADE_MSG >> $STATUS_FILE
			echo -e $rc:    $UNSUPPORTED_DOWNGRADE_MSG >> $BNA_STATUS_FILE
			return $STS_ERR;
		fi
	fi

	return $STS_OK;
}	




check_Thalassa8G_blade() {
    result=`/fabos/cliexec/slotshow -m | grep "FC8-48E" | wc -l`
    if [ $result -ge 1 ]; then
                return $STS_ERR
    else
       return $STS_OK
    fi
}

check_Quattro_blade() {
    result=`/fabos/cliexec/slotshow -m | grep "FC8-64" | wc -l`
    if [ $result -ge 1 ]; then
                return $STS_ERR
    else
       return $STS_OK
    fi
}
check_Galatea8G_blade() {
    result=`/fabos/cliexec/slotshow -m | grep "FC8-32E" | wc -l`
    if [ $result -ge 1 ]; then
                return $STS_ERR
    else
       return $STS_OK
    fi
}


add_err_status(){
    echo -e $rc:	"$1" >> $STATUS_FILE
    if [ "$#" -eq "1" ]; then
        echo -e $rc:	"$1" >> $BNA_STATUS_FILE
    elif [ "$#" -eq "2" ]; then
        echo -e $rc:	"$2" >> $BNA_STATUS_FILE
    fi
}


TEST() {

    $ECHO  -n "TEST $1 "
    if [ $HA_ROLE == "STANDBY" ] && [ $HA_STATE == "NOSYNC" ]; then
        return $STS_OK
    fi

    $1
    if [ "$?" -ne "$STS_OK" ]; then
        $ECHO "failed"
		let rc=$rc+1
        if [ "$#" -eq "2" ]; then
            add_err_status "$2"
        elif [ "$#" -eq "3" ]; then
            add_err_status "$2" "$3"
        fi
        RET_CODE=$STS_ERR
        return $STS_ERR
    fi

    $ECHO "passed"
    return $STS_OK
}


QUATTRO_BLADE_IS_PRESENT="FC8-64 blade is not supported by the targeted firmware.Please remove the blade and retry."
THALASSA8G_BLADE_IS_PRESENT="FC8-48E blade is not supported by the targeted firmware.Please remove the blade and retry."
GALATEA8G_BLADE_IS_PRESENT="FC8-32E blade is not supported by the targeted firmware.Please remove the blade and retry."

#BNA_QUATTRO_BLADE_IS_PRESENT="Quattro (FC8-64) blade is not supported by the targeted firmware.Please remove the blade and retry."
#BNA_THALASSA8G_BLADE_IS_PRESENT="Thalssa (FC8-48E) blade is not supported by the targeted firmware.Please remove the blade and retry."
#BNA_GALATEA8G_BLADE_IS_PRESENT="Thalssa (FC8-32E) blade is not supported by the targeted firmware.Please remove the blade and retry."

check_enhanced_fc8_blades()
{
	enhanced_fc8_supported=`grep -c "ENHANCED_FC8_BLADES_SUPPORTED" $NEW_PREINST_FILE`
	if [ $enhanced_fc8_supported -ne 0 ]; then
		# The new release supports ENHANCED_FC8_BLADES so ok to proceed.
		return $STS_OK;
	fi

	# Here we know that the new firmware does not support ENHANCED_FC8_BLADES.
	# Make a special check for pattern "check_Thalassa8G_blade" in target preinst file
	# If this pattern is not there then we can safely assume we are going to v7.4.x
	# where these blades are supported - so no need to block
	check_Thalassa=`grep -c "check_Thalassa8G_blade" $NEW_PREINST_FILE`
	if [ $check_Thalassa -eq 0 ]; then
		# The new release supports ENHANCED_FC8_BLADES so ok to proceed.
		return $STS_OK;
	fi

	# Now we are down to the releases that don't support these blades (ie 8.0.1x)
	# Check if Enhanced FC8 Blades are present. If so then block the downgrade.

	#result=`/fabos/cliexec/slotshow -m | grep -E "FC8-48E|FC8-64|FC8-32E" | wc -l
	#TEST check_Thalassa8G_blade "$THALASSA8G_BLADE_IS_PRESENT" "$BNA_THALASSA8G_BLADE_IS_PRESENT"
	#TEST check_Quattro_blade "$QUATTRO_BLADE_IS_PRESENT" "$BNA_QUATTRO_BLADE_IS_PRESENT" 
	#TEST check_Galatea8G_blade "$GALATEA8G_BLADE_IS_PRESENT" "$BNA_GALATEA8G_BLADE_IS_PRESENT" 

	TEST check_Thalassa8G_blade "$THALASSA8G_BLADE_IS_PRESENT"
	TEST check_Quattro_blade "$QUATTRO_BLADE_IS_PRESENT"
	TEST check_Galatea8G_blade "$GALATEA8G_BLADE_IS_PRESENT"

	return $STS_OK;
}

export PATH=/fabos/link_bin:/bin:/usr/bin:/sbin:/usr/sbin:/fabos/link_abin:/fabos/link_sbin:/fabos/link_rbin:/fabos/factory:/fabos/xtool
export VFROLEMAP=-1:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0

cmd_chassis() {

  context_switch chassis

  if [ "$CONFIG" = "TRUE" ]; then
    echo -n . > $TTY
    cliidx=`/usr/bin/expr $cliidx + 1`
    echo "$cliidx $1 $2 $3 $4 $5 $6 $7 $8 $9" >> $cshow
    echo -e "$1 $2 $3 $4 $5 $6 $7 $8 $9:"
      echo "** $1 $2 $3 $4 $5 $6 $7 $8 $9: Command:$rc **" >> $cshow
  else
    echo -e "$1 $2 $3 $4 $5 $6 $7 $8 $9:"
    $1 $2 $3 $4 $5 $6 $7 $8 $9
  fi
}

CHASSISCMD="cmd_chassis"

CONTEXTS=$($CHASSISCMD /fabos/cliexec/configshow -all | sed -n 's/Fabric ID =//p')

# copy all the configuration to tmp files before pre-install script runs.
# this avoids anyone to run RSH

copyAllConfigurationFiles() {
    # checks for active or standby
    if [ $ACTIVECP ] ; then
	#VF enable
	if [ $VF_ENABLED -ne $STS_OK ]; then
	    # iterating through all the FIDs
	    for FID in ${CONTEXTS} ; do
		context_switch $FID
		/fabos/cliexec/configshow -fid $FID > /tmp/chk_config_$FID
	    done
	else
	    # in non FD enviorenment there will be only one configuration - no all, no chassis
	    /fabos/cliexec/configshow > /tmp/chk_config_128
	    
	fi
	/fabos/cliexec/configshow -chassis  > /tmp/chk_config_chassis
	/fabos/cliexec/configshow -all  > /tmp/chk_config_all
    fi    
}

# calling to copy configuration files to /tmp directory
copyAllConfigurationFiles

CONFIGSHOW() {
	if [ $ACTIVECP ] ; then
		if [ "$1" = "-chassis"  ]; then 
			cat /tmp/chk_config_chassis
		elif [ "$1" = "-a" ] || [ "$1" = "-all" ] ; then
			cat /tmp/chk_config_all
		else
			if [ $VF_ENABLED -ne $STS_OK ]; then
				cat /tmp/chk_config_$CURRENT_VF
			else 
				cat /tmp/chk_config_128
			fi
		fi
	else
		if [ "$1" = "-chassis"  ]; then 
			cmd="/fabos/cliexec/configshow -chassis"
			glb_ls_id=-1;
			glb_vf_id=255;
		elif [ "$1" = "-a" ] || [ "$1" = "-all" ] ; then
			glb_ls_id=-1;
			glb_vf_id=255;
			cmd="/fabos/cliexec/configshow -all"
		else
			cmd="/fabos/cliexec/configshow"
		fi
	
		if [ $VF_ENABLED -eq $STS_OK ]; then
			# VF disabled
			/usr/bin/rsh -n $(otherhost) ROLE_ID=root LOGIN_ID=root CURRENT_AD=0 "$cmd"
		else
			# VF enabled, for_all_context changed glb_ls_id and glb_vf_id to each logical switch's
			/usr/bin/rsh -n $(otherhost) ROLE_ID=root LOGIN_ID=root CHASSIS_ROLEID=0 FABOS_SWITCHNO=$glb_ls_id CURRENT_VF=$glb_vf_id CURRENT_AD=0 "$cmd"
		fi
	fi

}




################################################################################
NONDFE_FD_MSG="Cannot download the requested firmware because it does not support portcfgnondfe --force_disable and one or more ports are configured with --force_disable option. Please use portcfgshow to identify these ports and reconfigure them with --enable or --disable option and then retry firmwaredownload."
check_nondfeforcedisable_supported()
{
	nondfe_forcedisable_supported=`grep -c "NONDFE_FORCE_DISABLE_SUPPORTED" $NEW_PREINST_FILE`
	if [ $nondfe_forcedisable_supported -ne 0 ]; then
		# The new release supports portcfgnondfe --forcedisable
		# No need to check further for blocking fwdl due to this feature.
		return $STS_OK;
	fi

	# portcfgnondfe --forcedisable is not supported by the new firmware being downloaded
	# Check if any ports are configured for nondfe force_disable. If so then block the downgrade.
	nondfe_fd=`correcthost_to_curr_vfid /fabos/cliexec/portcfgshow | grep "8G Non-DFE" | grep -c FD`
	if [ $nondfe_fd -ne 0 ]; then
		# one or more ports have nondfe configured with --force_disable option.
		# So return error to block downgrade.
		let rc=$rc+1
		echo -e $rc:    $NONDFE_FD_MSG >> $STATUS_FILE
		echo -e $rc:    $NONDFE_FD_MSG >> $BNA_STATUS_FILE
		return $STS_ERR;
	fi

	# New firmware does not support portcfgnondfe --forcedisable
	# But none of the ports are configured for --forcedisable. so ok to proceed.
	return $STS_OK;
}


UNSUPPORTED_TACACS_ENCRYPTION="Downgrade is not allowed since switch has TACACS+ configurations with encryption enabled. Please remove TACACS+ configurations or set the encryption level to NONE to proceed."

check_tacacs_encryption_enabled()
{
 tacacs_encryption_enabled=$(CONFIGSHOW -all | /bin/grep "tacacs.server" | /bin/grep -c "encryptionlevel:1")
 if [ $tacacs_encryption_enabled -ne 0 ]; then
	return $STS_ERR
 fi
 
 return $STS_OK
}

check_tacacs_encryption()
{
	#
	# Check if new firwmare supports TACACS encryption feature.
	#
	tacacs_encryption_supported=`/bin/grep -c "TACACS_ENCRYPTION_SUPPORTED" $NEW_PREINST_FILE`
	if [ $tacacs_encryption_supported -ne 0 ]; then
        
		# The new release supports this feature so ok to proceed.
		return $STS_OK
 	fi
 
	#
	# New firmware does not support TACACS encryption feature.
	# Now, check if TACACS configurations has encryption enabled
	#
	TEST check_tacacs_encryption_enabled "$UNSUPPORTED_TACACS_ENCRYPTION"
}


UNSUPPORTED_ROLE_NAME_LENGTH="New firmware does not support LDAP rolename length over 31 characters. Please remove/modify the mapping using \"ldapcfg\" command to proceed with firmwaredownload"

check_ldap_support_for_group_length()
{
        #
        # Check if new firmware supports ldap group name length of 64
        #
        ldap_role_length_64_supported=`/bin/grep -c "LDAP_ROLE_NAME_LENGTH_64_SUPPORTED" $NEW_PREINST_FILE`
        if [ $ldap_role_length_64_supported -ne 0 ]; then

                # The new release supports this feature so ok to proceed.
                return $STS_OK
        fi

        #
        # New firmware does not support LDAP group length of 64
        # Now, check if LDAP group name length > 32 is configured on switch including the trailing '\0'
        #
	TEST check_ldap_role_name_length "$UNSUPPORTED_ROLE_NAME_LENGTH"
}


#
# Check if ldap maps role has 32 or less characters including the trailing '\0'
# The changes are specific to customer CVR. May extend to future releases.
#
check_ldap_role_name_length()
{
	if [ -f /etc/fabos/ldap.map ]; then
		input="/etc/fabos/ldap.map"
		while read -r line
		do
                	result=`echo $line | sed -e 's/^.//;s/:.*//' | wc -c`
                        if [ $result -ge 32 ]; then
                                return $STS_ERR
                        fi
        	done <"$input"
        fi
        return $STS_OK
}

UNSUPPORTED_RADIUS_TACACS_ENCRYPION="Downgrade is not allowed since switch has RADIUS or TACACS+ configurations with encryption enabled. Please remove RADIUS or TACACS+ configurations or set the encryption level to NONE to proceed."

check_radius_tacacs_encryption_enabled()
{
 tacacs_encryption=$(CONFIGSHOW -all | /bin/grep "tacacs.server" | /bin/grep -c "encryptionlevel:1")
 radius_encryption=$(CONFIGSHOW -all | /bin/grep "radius.server" | /bin/grep -c "encryptionlevel:1")
 if [ $tacacs_encryption -ne 0 ] || [ $radius_encryption -ne 0 ]; then
 	return $STS_ERR
 fi
  
 return $STS_OK
}

check_radius_tacacs_encryption()
{
	#
	# Check if new firwmare supports storage of only encrypted shared secret for RADIUS and TACACS 
	#
	radius_tacacs_encrypt=`/bin/grep -c "RADIUS_TACACS_ENCRYPTION" $NEW_PREINST_FILE`
	if [ $radius_tacacs_encrypt -ne 0 ]; then
        
		# The new release supports this feature so ok to proceed.
		return $STS_OK
 	fi
 
	#
	# New firmware does not support storage of only encrypted shared secret for RADIUS and TACACS 
	# Now, check if RADIUS or TACACS configurations have encryption enabled
	#
	TEST check_radius_tacacs_encryption_enabled "$UNSUPPORTED_RADIUS_TACACS_ENCRYPION"
}

SERDES_VERSIONS_DIFFER="The Serdes Version of target firmware differs from the current firmware. HCL to FOS version with different Serdes Versions is not permitted.  Please use \"firmwaredownload -s\" for disruptive firmwaredownload so that the new serdes values will take effect. \n"

check_serdes_version_between_cur_n_new_fos()
{
	case ${SWBD##SWBD} in
		'169' | '170')
		;;
	*)
		# Do not bother with Serdes checking for non Chewbacca platforms
		return $STS_OK;
		;;
	esac

	cur_serdes_supported=$(grep CHEW_SERDES_SUPPORTED $CUR_PREINST_FILE)
	new_serdes_supported=$(grep CHEW_SERDES_SUPPORTED $NEW_PREINST_FILE)
	if [ "$cur_serdes_supported" = "$new_serdes_supported" ]; then
		# The cur and new FOS versions support the same SERDES versions
		# So return OK to proceed.
		return $STS_OK;
	fi

	# Current and New (to be downloaded) FOS versions support different versions of serdes. 
	# Check for and block non-disruptive firmwaredownload but permit disruptive firmwaredownload. 

	non_disruptive_fwdl=0

	fwdl_option_s=0;
	fwdl_option_b=0;
	is_fwdl_arg "s"
	if [ $? -eq $STS_OK ]; then
		fwdl_option_s=1;
	fi

	is_fwdl_arg "b"
	if [ $? -eq $STS_OK ]; then
		fwdl_option_b=1;
	fi

	if [ $fwdl_option_s -gt 0 ]; then
		if [ $fwdl_option_b -gt 0 ]; then
			#	-sb is set. this is again non-disruptive (as good as no options set)
			non_disruptive_fwdl=1
		fi
	else
		non_disruptive_fwdl=1
	fi

	if [ $non_disruptive_fwdl -eq 1 ]; then
		let rc=$rc+1
		echo -e $rc:    $SERDES_VERSIONS_DIFFER >> $STATUS_FILE
		echo -e $rc:    $SERDES_VERSIONS_DIFFER >> $BNA_STATUS_FILE
		return $STS_ERR;
	fi

	# Here we have different serdes versions but disruptive firmwaredownload
	return $STS_OK
}

################################################################################
# Extension FWDL-PREP Check
################################################################################

check_extn_fwdl_prep()
{
	#
	# Check if new firwmare supports extn fwdl-prep feature.
	#
	extn_fwdl_prep_supported=`/bin/grep -c "EXTN_FWDL_PREP_SUPPORTED" $NEW_PREINST_FILE`
	if [ $extn_fwdl_prep_supported -eq 0 ]; then
		# The new release does not support this command, so don't attempt to execute
		return $STS_OK
 	fi

	case ${SWBD##SWBD} in
		'62' | '77' | '83' | '148' | '165' | '166')

		correcthost_to_curr_vfid /fabos/link_sbin/extncfg --fwdl-prep --version ${TO_MAJOR}.${TO_MINOR}.${TO_PATCH} --preinst
		;;

	*)
		;;
	esac

	return $STS_OK
}

################################################################################
NEW_128MB_FLASH_BLOCKING_MSG="Cannot download the requested firmware because it does not support the newer Flash used on this Switch. Please retry firmwaredownload using a firmware version that supports this new flash"
check_for_new_128MB_flash()
{
	new_128MB_flash_supported=`grep -c "NEW_128MB_FLASH_SUPPORTED" $NEW_PREINST_FILE`
	if [ $new_128MB_flash_supported -ne 0 ]; then
		# The new release supports the new  128 MB Flash
		# No need to check further for blocking fwdl to this version.
		return $STS_OK;
	fi

	# Control reaching here means we are attempting to
	# download a firmware version that does not support the new 128MB flash
	# Check if this is one of those platforms that has this new part 
	# and block firmwaredownload to this firmware version 
	# that does not support this new part.
	# Otherwise that firmware will brick this switch.

	case ${SWBD##SWBD} in
		'161' | '162' |	'169' | '170' |	'172')
		# Check for New 128MB Flash on these platforms
		# Wedge(161), Wedge_64(162), Chebacca(169), Chewbacca 24 port(170) or Wedge_plus(172)
		;;

		*)
		# Do not bother with New 128MB Flash checking for other Platforms
		# i.e This needs to be checked only for Wedge and Chewbacca platforms
		return $STS_OK;
		;;
	esac

	# Control reaches here for Wedge and Chewbacca platforms
	# And the firmware being downloaded does not support the new 128 MB flash.
	# Check if this switch has the new Flash and if yes then
	# Block firmaredownload to this version.

	prom0_primary=$(cat /proc/mtd | grep  -c "prom0: primary")
	#
	# These platforms should have this line "prom0: primary"
	# But this one does not. Bail out for now.
	#
	if [ $prom0_primary -eq 0 ]; then
		return $STS_OK;
	fi

	erasesize=$(cat /proc/mtd | grep  "prom0: primary" |  awk '/ / {print $3}')

	if [ $erasesize -ne 00010000 ]; then
		# we have a platform with new 128MB flash
		# and we are attempting to download a firmware version which
		# does not have the support for that part.
		# So return error to block downgrade.
		let rc=$rc+1
		echo -e $rc:    $NEW_128MB_FLASH_BLOCKING_MSG >> $STATUS_FILE
		echo -e $rc:    $NEW_128MB_FLASH_BLOCKING_MSG >> $BNA_STATUS_FILE
		return $STS_ERR;
	fi

	# This switch has the old Flash 32MB or 64MB
	# Ok to download the firmware version that does not support the new 128MB flash.
	return $STS_OK;
}

################ Check LCW platform ######################
DDR_2G_NOTBACK4GFOS="Downgrade is not allowed because the target firmware does not support this hardware revision."
check_wedgecr()
{
	case ${SWBD##SWBD} in
		'162')
                if [ -e /proc/system/wedgecr ];then
                        is_lcw="$(cat /proc/system/wedgecr)"
                else
                        is_lcw=0
                fi
                memval=`/fabos/link_bin/memshow | grep "Mem" | awk '{ print $2 }'`
                ddr=$(($memval-2200000000))     # big value, so reduce to smaller number
                if [ $is_lcw -eq 1 ] || [ $ddr -lt 0 ]; then
			newcnt=`grep -c "WEDGE_CR_SUPPORT" $NEW_PREINST_FILE`
			if [ $newcnt -eq 0 ];then
				let rc=$rc+1
				echo -e $rc:    $DDR_2G_NOTBACK4GFOS >> $STATUS_FILE
				echo -e $rc:    $DDR_2G_NOTBACK4GFOS >> $BNA_STATUS_FILE
				return $STS_ERR;
                        fi
                fi
	esac
	return $STS_OK;
}

################ Check for special Huawei switch version 162.7 or 173.4 ..etc  platform ######################
HUAWEI_SWITCH_SPECIAL_NOTSUPPORTED_MSG="Cannot download the requested firmware because it does not support this switch type."
check_special_huawei_disable_enc_support()
{
    # checks for active or standby
    if [ $ACTIVECP ] ; then
    # Check wedge64 for Hauwei special switch with disabled encryption/decryption.
    swtype=`correcthost_to_curr_vfid /fabos/bin/switchshow | awk '/switchType/ {print $2}'`
    if [ $swtype == "162.7" ] || [ $swtype == "173.4" ]; then
        # HW is special Huawei platform, now check supported firmware release tag;
        sp_huawei_supported=`grep -c "HUAWEI_SPECIAL_SWBD_SUPPORTED" $NEW_PREINST_FILE`
        if [ $sp_huawei_supported -ne 0 ]; then
            # this release has or supports the huawei special.
            return $STS_OK;
        else
            # missing the above firmware tag will imply no support;
            # special hauwei switch does NOT support this fos, so display error msg;
            let rc=$rc+1
            echo -e $rc:    $HUAWEI_SWITCH_SPECIAL_NOTSUPPORTED_MSG >> $STATUS_FILE
            echo -e $rc:    $HUAWEI_SWITCH_SPECIAL_NOTSUPPORTED_MSG >> $BNA_STATUS_FILE
            return $STS_ERR;
        fi
    else
        # ignore other platforms;
        return $STS_OK;
    fi
    fi
    return $STS_OK;
}

############ CLEAN ADDRESS BIT ############
LS_ACC_CLEAN_ADDRESS_BIT_BLOCKING_MSG="Cannot download the requested firmware because it does not support Clean Address Bit settings used on this Switch. Please retry firmwaredownload using a firmware version that supports Clean Address Bit, or disable the setting on all ports using the portCfgCleanAddress command."
check_for_clean_address_bit()
{
	# Check for Clean Address Bit support
	clean_address_bit_supported=`grep -c "LS_ACC_CLEAN_ADDRESS_BIT_SUPPORTED" $NEW_PREINST_FILE`
	if [ $clean_address_bit_supported -ne 0 ]; then
		# Clean Address Bit supported, we can proceed
		return $STS_OK;
	fi

	# Check for any configured ports
	clean_address_bit_enabled=`correcthost /fabos/cliexec/portcfgshow | grep "Clean Address" | grep -c ON`
	if [ $clean_address_bit_enabled -ne 0 ]; then
		# One or more ports are configured and new release does not support Clean Address Bit; Block
		let rc=$rc+1
		echo -e $rc:    $LS_ACC_CLEAN_ADDRESS_BIT_BLOCKING_MSG >> $STATUS_FILE
		echo -e $rc:    $LS_ACC_CLEAN_ADDRESS_BIT_BLOCKING_MSG >> $BNA_STATUS_FILE
		return $STS_ERR;
	fi

	# No blocking factors
	return $STS_OK;
}

############ CLEAN BSL ############
BSL_BLOCKING_MSG="Cannot download the requested firmware because it does not support BSN Support Link settings used on this Switch. Please disable the setting using the supportlink --disable command."
check_for_BSL()
{
	# Check for BSL.
	BSL_supported=`grep -c "BSN_SUPPORT_LINK_SUPPORTED" $NEW_PREINST_FILE`
	if [ $BSL_supported -ne 0 ]; then
		# BSL supported, we can proceed
		return $STS_OK;
	fi

	# If on standby CP then before attempting to run supportlink 
	# first check if the Actve CP has supportlink
	# supportlink may not exist on the active CP if it was downgraded in step 1 of the dual step downgrade scenario.
	if [ ! $ACTIVECP ] ; then
		supportlinkDoesNotExist=$(correcthost ls -al /fabos/link_bin/supportlink  2> ${NULL} | grep -c "No such file or directory")
		if [ $supportlinkDoesNotExist ]; then
			return $STS_OK;
		fi
	fi

	# Check for BSL being enabled
	BSL_enabled=`correcthost_to_curr_vfid /fabos/link_bin/supportlink --show | grep "Support Link State" | grep -c Enabled`
	if [ $BSL_enabled -eq 1 ]; then
		# BSL is enabled. block
		let rc=$rc+1
		echo -e $rc:    $BSL_BLOCKING_MSG >> $STATUS_FILE
		echo -e $rc:    $BSL_BLOCKING_MSG >> $BNA_STATUS_FILE
		return $STS_ERR;
	fi

	# No blocking factors
	return $STS_OK;
}

#
# Check for Emulex F-Port trunking configuration before downgrading to lower firmware version
# 8.1.x and 8.2.0 from 8.2.1.
#
EMULEX_FPORT_TRUNNKING_FWDL_CHECK="Downgrade is not allowed because some F-Ports devices are in trunk. Please disable the trunking on these devices and the corresponding switch ports before downgrading firmware."

check_emulex_fport_trunking_configured() {
	slot_based=`correcthost_to_curr_vfid /fabos/bin/slotshow | grep "Not supported on this platform"`
	if [ "$slot_based" == "" ] ; then
		port_list=`correcthost_to_curr_vfid /fabos/bin/switchshow | grep "F-Port" | awk '{print $2"/"$3}'`
	else
		port_list=`correcthost_to_curr_vfid /fabos/bin/switchshow | grep "F-Port" | awk '{print $1}'`
	fi

	role=$ROLE_ID
	ROLE_ID=root
	for port in $port_list
	do
		local_flags=`correcthost_to_curr_vfid /fabos/cliexec/fabportshow $port | grep "Local Flags" | awk '{print $3}'`
		bitmask="0x08000000"
		let ret="$local_flags & $bitmask"
		if [ $ret -ne 0 ]; then
			return $STS_ERR
		fi
	done
	ROLE_ID=$role

	return $STS_OK
}

check_emulex_fport_trunking() {
	emulex_fport_trunking_supported=`grep -c "EMULEX_FPORT_TRUNKING_SUPPORTED" $NEW_PREINST_FILE`
	if [ $emulex_fport_trunking_supported -ne 0 ]; then
		# The new release supports this feature so ok to proceed.
		return $STS_OK
	fi
	
	# Check for Virtual Fabrics
	if [ $VF_ENABLED -ne $STS_OK ]; then
		CHASSISCMD="cmd_chassis"
		if [ $ACTIVECP ] ; then
			for_all_contexts check_emulex_fport_trunking_configured
		else
			for_all_contexts_standby check_emulex_fport_trunking_configured
		fi
	else
		check_emulex_fport_trunking_configured;
	fi
	
	if [ $? -ne $STS_OK ]; then 
		let rc=$rc+1
		echo -e $rc:	$EMULEX_FPORT_TRUNNKING_FWDL_CHECK >> $STATUS_FILE
		echo -e $rc:	$EMULEX_FPORT_TRUNNKING_FWDL_CHECK >> $BNA_STATUS_FILE
		return $STS_ERR
	fi
	return $STS_OK
}




V8X_EULA_FAIL_MSG="This operation requires User acceptance of the terms of the product EULA.\n"\
"Firmwaredownload failed due to non-acceptance of this product's End User License Agreement."

check_v8x_supporting_eula() {
	EULA_ACCEPTANCE_FILE=/etc/config/EULAaccepted
	#cur_fos_supports_eula=`grep -c "V8X_SUPPORTING_EULA" $CUR_PREINST_FILE`
	#if [ $cur_fos_supports_eula -ne 0 ]; then
	#	# The Current v8x  release supports EULA - so  no need to prompt for acceptance
	#	return $STS_OK
	#fi

	if [ -f $EULA_ACCEPTANCE_FILE ]; then
		# User has specified -acceptEULA option
		# Or the request has come from CAL for webtools/BNA/SANNav
		# So no need to prompt to accept EULA
		return $STS_OK
	fi


    #
	# EULA acceptance has not been provided
	# Check next if invoked from APP
	# if so FAIL fwdl wit/hout prompting for EULA
	#
	case "$GEPS_APP_NAME" in
	"WebTools" | "Fabric Manager" | "SANnavMP" | "SANnavGV")
		let rc=$rc+1
		echo -e $rc:	$V8X_EULA_FAIL_MSG >> $STATUS_FILE
		echo -e $rc:	$V8X_EULA_FAIL_MSG >> $BNA_STATUS_FILE
		return $STS_ERR
		;;

		*)
		;;
	esac

	validResponse=0
	while [ $validResponse -eq 0 ]; do
		echo "Do you accept and agree to the terms outlined in the End User License Agreement (EULA) for this product?"
		read -p "Please respond with (Y/y) to accept, (N/n) to Not accept, or (D/d) to Display the EULA):" eulaResponse
		if [ "$eulaResponse" == "y" ] || [ "$eulaResponse" == "Y" ]; then
			#
			# Create EULA_ACCEPTANCE_FILE so the preinstall of the new firwmare
			# will not prompt for EULA acceptance again.
			#
			echo 1 > $EULA_ACCEPTANCE_FILE
	        return $STS_OK
		fi
		if [ "$eulaResponse" == "n" ] || [ "$eulaResponse" == "N" ]; then
			let rc=$rc+1
			echo -e $rc:	$V8X_EULA_FAIL_MSG >> $STATUS_FILE
			echo -e $rc:	$V8X_EULA_FAIL_MSG >> $BNA_STATUS_FILE
	        return $STS_ERR
		fi
		if [ "$eulaResponse" == "d" ] || [ "$eulaResponse" == "D" ]; then
			if [ -f $EULA_FILE ]; then
				/fabos/link_bin/more $EULA_FILE
			else
				echo "End User License Agreement (EULA) not found!"
			fi
		else
			echo
			echo "Invalid response: $eulaResponse"
		fi
	done	
}

##############################################################################
#
# Cypress 16MB bootflash Feature compatibility checks.
# Downgrade to a release that does not support this feature is not allowed
#
##############################################################################
CYPRESS_MANUFACTURER_ID=0x000001
CYPRESS_CHIPID=0x002101
CYPRESS_BOOTFLASH_BLOCKING_MSG="Cannot download the requested firmware because it does not support the Cypress Bootflash. Please retry firmwaredownload using a version that supports Cypress Bootflash"
check_cypress_bootflash()
{
	# Need to check compatibility only on Lando CP
    case ${SWBD##SWBD} in
        '165' | '166')
        ;;
    *)
        # Not a Lando CP in a chassis, ok to download
        return $STS_OK;
        ;;
    esac

	cypress_bootflash_supported=`grep -c "CYPRESS_MID01_BOOTFLASH_SUPPORTED" $NEW_PREINST_FILE`
	if [ $cypress_bootflash_supported -ne 0 ]; then
		# The new release supports the Cpress Bootflash
		# ok to proceed without further compatibility checking.
		return $STS_OK;
	fi

		
	# The version being downloaded does not support the Cypress Bootflash
	# Check if the system has the Cypress BootfFlash and if so block the download
	# Cypress Bootflash: Manufacturer ID 0x000001 Chip ID 0x002101 size 0x1000000 bytes
	manufacturerId=$(cat /proc/mtd_device_info | awk '/Manufacturer ID / {print $3}')
	chipId=$(cat /proc/mtd_device_info | awk '/Chip ID / {print $6}')

	if [ $manufacturerId == $CYPRESS_MANUFACTURER_ID ] && [ $chipId == $CYPRESS_CHIPID ]; then
		let rc=$rc+1
		echo -e $rc:    $CYPRESS_BOOTFLASH_BLOCKING_MSG >> $STATUS_FILE
		echo -e $rc:    $CYPRESS_BOOTFLASH_BLOCKING_MSG >> $BNA_STATUS_FILE
		return $STS_ERR
	fi


    #
    # Current CP does not have Cypress bootflash. check if the other CP has it.
    # if redundant CP has CYPRESS bootflash then block downgrades to 
    # firmware versions that do not support CYPRESS bootflash
    #
    if [ $(ha_state) == "NOSYNC" ]; then
		# No Cypress Bootflash on current CP and CPs not in SYNC, OK to download
		return $STS_OK
	fi

	# CPs are in SYNC.
	# check if the other CP has CYPRESS bootflash and if yes block this firmwaredownlaod.
	manufacturerId=`/usr/bin/rsh -n $(otherhost) ROLE_ID=root LOGIN_ID=root CURRENT_AD=0 /bin/cat /proc/mtd_device_info | awk '/Manufacturer ID / {print $3}'`
	chipId=$(/usr/bin/rsh -n $(otherhost) ROLE_ID=root LOGIN_ID=root CURRENT_AD=0 /bin/cat /proc/mtd_device_info | awk '/Chip ID / {print $6}')

	if [ $manufacturerId == $CYPRESS_MANUFACTURER_ID ] && [ $chipId == $CYPRESS_CHIPID ]; then
		# Other CP has cypress bootflash and the firmware does not support it. Block download
		let rc=$rc+1
		echo -e $rc:    $CYPRESS_BOOTFLASH_BLOCKING_MSG >> $STATUS_FILE
		echo -e $rc:    $CYPRESS_BOOTFLASH_BLOCKING_MSG >> $BNA_STATUS_FILE
		return $STS_ERR
	fi

	# No Cypress Bootflash found, OK to download
	return $STS_OK
}



###########################################################
# This section contains logic for media piracy validation #
#             Media Piracy section - Start                #
###########################################################

# All blank spaces need to be removed from Vendor Name string
VENDOR_BROCADE="BROCADE"

# Since HP branded media have different kinds of Vendor Name string, check for
# only HP* Below are few examples of HP's Vendor Name strings
# HPE-F    BROCADE
# HP-A     BROCADE
# HP-A     BROCAD
VENDOR_HP="HP"

# Below is supported media matrix for pre-Gen7 platforms. This matrix contains
# Brocade branded pre-Gen7 legacy media, HP media & Gen7 media as well as
# non-Brocade branded SmartOptics media. Gen7 media are backward compatible
# pre-Gen7 platforms.
# This matrix is used to block upgrade to 9.0.0 if any ports have pirated media
# plugged into them. Pirated media means whose PN, SN doesn't match with those
# white listed in support matrix.
# In this matrix, 1st column contains Brocade Part Number and subsequent
# columns contain supported Serial Number (first 3 letters) for that Part Number

# Brocade pre-Gen7 media support list for FC ports
brcd_gen6_media_fc_port=( \
"57-1000333-** JAA JAF" \
"57-1000332-** JDA JDF JDP" \
"57-1000335-** JBF" \
"57-0000088-** HAA HAF" \
"57-0000089-** HDA HDF" \
"57-1000262-** HBA HBF" \
"57-1000114-** KAA" \
"57-1000115-** KDA" \
"57-1000351-** ZUA" \
"57-1000480-** ZMA ZMJ" \
"57-1000331-** ZTA ZTF" \
"57-1000267-** HTA" \
"57-1000294-** HUA" \
"57-1000310-** HME" \
)

# Brocade pre-Gen7 media support list for FCoE ports
brcd_gen6_media_fcoe_port=( \
"57-1000128-** LTA LTF LTJ" \
"57-1000129-** ATA ATJ" \
"57-1000263-** LDF LDJ" \
"57-1000326-** YTA YTF" \
"57-1000339-** LKA" \
"57-1000327-** LFF" \
)

# Brocade pre-Gen7 media support list for GE ports
brcd_gen6_media_ge_port=( \
"57-1000042-** TZA" \
"33210-100 TAA TAF" \
"33211-100 TDA TDF" \
"57-1000311-** TRF" \
"57-1000312-** TRF" \
"57-1000313-** TRF" \
"57-1000314-** TRF" \
"57-1000315-** TRF" \
"57-1000316-** TRF" \
"57-1000317-** TRF" \
"57-1000318-** TRF" \
"57-1000013-** WAA VAF" \
"57-1000014-** WCA VCF" \
"57-1000015-** WDA VDF" \
"57-1000020-** VEF" \
"57-0000075-** AAA AAF" \
"57-0000076-** ADA ADF" \
"57-1000130-** ALA ALF" \
"57-1000266-** AJJ" \
"57-1000128-** LTA LTF LTJ" \
"57-1000263-** LDF LDJ" \
"57-1000327-** LFF" \
"57-1000339-** LKA" \
)

# Brocade Gen7 media support list for FC ports
brcd_gen7_media_fc_port=( \
"57-1000481-** BAR" \
"57-1000485-** JAA JAF" \
"57-1000486-** JDA JDF" \
"57-1000487-** HAA HAF" \
"57-1000488-** HDA HDF" \
"57-1000489-** HBA HBF" \
"57-1000490-** ZUA" \
"57-1000491-** ZMA" \
"57-1000492-** KAA" \
"57-1000493-** KDA" \
"57-1000494-** JBF" \
)

# HP branded media support list for FC ports
hp_media_fc_port=( \
"P9H32A JAA JAF" \
"P9H29A JDA JDF" \
"QK724A HAA HAF" \
"QK725A HDA HDF" \
"H6Z29A HBA HBF" \
"QK726A KAA" \
"QK727A KDA" \
)

# HP branded media support list for GE ports
hp_media_ge_port=( \
"AP823A AAA AAF" \
"AP824A ADA ADF" \
"AW537A CZA TZA TZH" \
)

# Media from Smartoptics vendor are not Brocade branded. Also one 16G DWDM optic
# from Finisar is not Brocade branded. So threat them as exception.
# Add supported serial numbers for Smartoptics & Finisar media here.
non_brcd_media=( \
"32G-IR-D***-BR JFC HFC" \
"16G-ER-D***-BR1 JFC HFC" \
"16G-ER-D***-BR2 JFC HFC" \
"16G-ER-BR2 JFC HFC" \
"FTLX3670SCC**B16 \*" \
)


# is_gen6_extn_platform()
#
# Return true if this is an extension platform
is_gen6_extn_platform()
{
	case ${SWBD##SWBD} in

	'165' | '166')
	harpoon_present=$(/fabos/cliexec/slotshow -m | grep -c "186.*SX6")
	if [ $harpoon_present -eq 0 ]
	then
		# If Harpoon blade is not present then not an extension platform.
		return 0
	fi
	return 1
		;;
	'178')
	return 1
		;;
	esac

	return 0
}

mediatrc()
{
	message="$@"
	if [ "$MEDIA_TRC" = 1 ]; then
		$ECHO $message
	fi
}

medialog()
{
	message="$@"
	echo $message
}

skip_ge_port_media=1	# Do Not validate media on GE ports of Extn platforms
skip_fcoe_port_media=1	# Do Not validate media on ALL ports of FCoE blade
fcoe_blade_id=204
fcoe_blade_slots=""
extn_blade_id=186
extn_blade_slots=""

validate_media_bpn_serial()
{
	bpn=$1
	serial=$2
	vendor=$3
	port=$4
	extn_gen7med_chk=$5
	valid=0
	mediatrc "Validating $bpn $serial $vendor plugged into $port ..."

	# Check if ge_port media validation needs to be skipped
	if [ $skip_ge_port_media -eq 1 ]
	then
		# If port is GE-port, then skip validation
		echo $port | grep ge 1> ${NULL} 2>&1
		if [ $? -eq 0 ]
		then
			mediatrc "Skipping media validation on GE port $port"
			valid=1
			return $valid
		fi
	fi

	# Check if fcoe_port media validation needs to be skipped
	if [ $skip_fcoe_port_media -eq 1 ]
	then
		# Check if fcoe blade is present in the system
		if [ "$fcoe_blade_slots" != "" ]
		then
			# Get slot number
			slot=`echo $port | sed '/\/.*/s///g'`
			# Check if this slot# corresponds to that of fcoe blade
			echo $fcoe_blade_slots | grep -w $slot 1> ${NULL} 2>&1
			if [ $? -eq 0 ]
			then
				mediatrc "Skipping media validation on FCoE port $port"
				valid=1
				return $valid
			fi
		fi
	fi

	# Validate Brocade branded media
	if [[ "$vendor" == "$VENDOR_BROCADE"* ]]
	then
		# Validate Brocade pre-Gen7 branded media
		for (( i = 0; i < ${#brcd_gen6_media_fc_port[@]}; i++ ))
		do
			itr=(${brcd_gen6_media_fc_port[$i]})

			# Remove ** from PN
			pn=`echo ${itr[0]} | sed '/\**/s///g'`
			if [[ "$bpn" == "$pn"* ]]
			then
				mediatrc "Got media details ${itr[@]} - ${#itr[@]}"
				for (( j = 1; j <  ${#itr[@]}; j++ ))
				do
					if [ "${itr[$j]}" = "$serial" ]
					then
						mediatrc "Valid media ${itr[0]} ${itr[$j]}"
						valid=1
						return $valid
					fi
				done
			fi
		done

		if [ $skip_fcoe_port_media -eq 0 ]
		then
			for (( i = 0; i < ${#brcd_gen6_media_fcoe_port[@]}; i++ ))
			do
				itr=(${brcd_gen6_media_fcoe_port[$i]})
	
				# Remove ** from PN
				pn=`echo ${itr[0]} | sed '/\**/s///g'`
				if [[ "$bpn" == "$pn"* ]]
				then
					mediatrc "Got media details ${itr[@]} - ${#itr[@]}"
					for (( j = 1; j <  ${#itr[@]}; j++ ))
					do
						if [ "${itr[$j]}" = "$serial" ]
						then
							mediatrc "Valid media ${itr[0]} ${itr[$j]}"
							valid=1
							return $valid
						fi
					done
				fi
			done
		fi

		if [ $skip_ge_port_media -eq 0 ]
		then
			for (( i = 0; i < ${#brcd_gen6_media_ge_port[@]}; i++ ))
			do
				itr=(${brcd_gen6_media_ge_port[$i]})

				# Remove ** from PN
				pn=`echo ${itr[0]} | sed '/\**/s///g'`
				if [[ "$bpn" == "$pn"* ]]
				then
					mediatrc "Got media details ${itr[@]} - ${#itr[@]}"
					for (( j = 1; j <  ${#itr[@]}; j++ ))
					do
						if [ "${itr[$j]}" = "$serial" ]
						then
							mediatrc "Valid media ${itr[0]} ${itr[$j]}"
							valid=1
							return $valid
						fi
					done
				fi
			done
		fi

		# Validate Brocade Gen7 branded media
		for (( i = 0; i < ${#brcd_gen7_media_fc_port[@]}; i++ ))
		do
			itr=(${brcd_gen7_media_fc_port[$i]})

			# Remove ** from PN
			pn=`echo ${itr[0]} | sed '/\**/s///g'`
			if [[ "$bpn" == "$pn"* ]]
			then
				mediatrc "Got media details ${itr[@]} - ${#itr[@]}"
				for (( j = 1; j <  ${#itr[@]}; j++ ))
				do
					if [ "${itr[$j]}" = "$serial" ]
					then
						# If the flag to check Gen7 media on extn platform, then
						# inverse the return value. i.e. in such a case treat
						# Gen7 media as invalid media.
						if [ "$extn_gen7med_chk" = "EXTN_GEN7MED_CHK" ]
						then
							mediatrc "Invalid media ${itr[0]} ${itr[$j]}"
							valid=0
						else
							mediatrc "Valid media ${itr[0]} ${itr[$j]}"
							valid=1
						fi
						return $valid
					fi
				done
			fi
		done
	fi

	# Validate HP branded media
	# Since HP branded media have different kinds of Vendor Name string, check
	# for only HP* which will cover all those Vendor Name strings
	if [[ "$vendor" == "$VENDOR_HP"* ]]
	then
		for (( i = 0; i < ${#hp_media_fc_port[@]}; i++ ))
		do
			itr=(${hp_media_fc_port[$i]})
			if [ "${itr[0]}" = "$bpn" ]
			then
				mediatrc "Got media details ${itr[@]} - ${#itr[@]}"
				for (( j = 1; j <  ${#itr[@]}; j++ ))
				do
					if [ "${itr[$j]}" = "$serial" ]
					then
						mediatrc "Valid media ${itr[0]} ${itr[$j]}"
						valid=1
						return $valid
					fi
				done
			fi
		done

		if [ $skip_ge_port_media -eq 0 ]
		then
			for (( i = 0; i < ${#hp_media_ge_port[@]}; i++ ))
			do
				itr=(${hp_media_ge_port[$i]})
				if [ "${itr[0]}" = "$bpn" ]
				then
					mediatrc "Got media details ${itr[@]} - ${#itr[@]}"
					for (( j = 1; j <  ${#itr[@]}; j++ ))
					do
						if [ "${itr[$j]}" = "$serial" ]
						then
							mediatrc "Valid media ${itr[0]} ${itr[$j]}"
							valid=1
							return $valid
						fi
					done
				fi
			done
		fi
	fi

	# Validate non-Brocade branded media - from exception list
	for (( i = 0; i < ${#non_brcd_media[@]}; i++ ))
	do
		itr=(${non_brcd_media[$i]})

		# Remove any * from PN and break PN into 2 parts
		# i.e. 1st part before * and 2nd part after * (if any)
		pn1=`echo ${itr[0]} | awk -F"**" '{print $1}'`
		pn2=`echo ${itr[0]} | awk -F"**" '{print $2}'`
		if [[ "$bpn" == "$pn1"*"$pn2" ]]
		then
			mediatrc "Got media details ${itr[@]} - ${#itr[@]}"
			for (( j = 1; j <  ${#itr[@]}; j++ ))
			do
				# If SN prefix contains wild char "\*", then remove it before
				# doing comparision with Serial Number
				if [[ "$serial" == "$(echo ${itr[$j]} | sed '/\\\*/s///g')"* ]]
				then
					mediatrc "Valid media ${itr[0]} ${itr[$j]}"
					valid=1
					return $valid
				fi
			done
		fi
	done

	mediatrc "Invalid media $bpn $serial"
	return $valid
}

validate_media()
{
	extn_gen7med_chk=$1

	# Gather media info across all VFs on this system. Collect Brocade Part
	# Number, Serial Number & Vendor Name corresponding to all media plugged
	# into this system. Also get port number where media has been plugged into.
	#
	# Note - This script may fail to get media info if media or port or blade or
	#        switch is in Faulted state or blade is in powered Off state.
	#

	# If extn_gen7med_chk is set to EXTN_GEN7MED_CHK, then this function is
	# intended to check if any Gen7 media has been plugged into extn platforms
	# such as Awing, Harpoon etc. This is set, when downgrade from 9.x to 8.x
	# is attempted and hence downgrade may need to be blocked since 8.x may
	# not have support for Gen7 secured media.
	#
	# If extn_gen7med_chk is not set, then this function is invoked for media
	# validation on all platforms as part of upgrade from 8.x to 9.x
	#
	if [ "$extn_gen7med_chk" = "EXTN_GEN7MED_CHK" ]
	then
		# Check if this chassis has any extension blade or
		# if this is an extension pizzabox
		extn_blade_slots=$(correcthost /fabos/cliexec/slotshow -m 2>${NULL} | grep -w $extn_blade_id | awk '{print $1}')

		# If neither extn pizza box nor extn blade present then return success
		if [ "$SWBD" != "SWBD178" -a "$extn_blade_slots" = "" ]
		then
			mediatrc "Not an extension platform"
			return $STS_OK
		fi
	fi

	medialog "Gathering info of all media plugged into this system ..."
	media_info=(`correcthost_all_vfs /fabos/cliexec/sfpshow -all 2>${NULL} | grep -e Port -e Name -e PN -e Serial | grep -B1 -A2 Name | grep -v "^--" | sed '/Slot[ ]*/s///g' | sed '/GE/s/Port[ ]*/ge/g' | sed '/ GE: /s///g' | sed '/Port[ ]*/s///g' | sed '/ id/s///g' | awk '{for (i=3; i<NF; i++) printf $i; print $NF}' | sed '/:/s///g'`)

	media_info_sz=${#media_info[@]}
	per_port_media_info=4
	num_media=`expr $media_info_sz \/ $per_port_media_info`

	# Cross check num_media calculated above by re-issuing sfpshow
	num_valid_media=`correcthost_all_vfs /fabos/cliexec/sfpshow 2>${NULL} | grep Vendor | wc -l`
	if [ $num_media -ne $num_valid_media ]
	then
		mediatrc "Warning: Some issue encountered while gathering media info"
		mediatrc "Warning: num_media=$num_media and num_valid_media=$num_valid_media"
	fi

	# If no media plugged in, then return
	if [ $num_media -eq 0 ]
	then
		medialog "No media found"
		return $STS_OK
	fi

	# If media validation for fcoe port needs to be skipped, then check if
	# system has any fcoe blades
	fcoe_blade_slots=$(correcthost /fabos/cliexec/slotshow -m 2>${NULL} | grep -w $fcoe_blade_id | awk '{print $1}')

	# Now parse media info corresponding to each port and validate the same
	# against media support matrix
	# Each port's media info is in following order
	#    port-number
	#    media-vendor-name - All blank space are removed in vendor name
	#    media-part-number
	#    media-serial-number - We are interested in first 3 letters

	medialog "Validating $num_media ports which have media plugged in "
	bad_media=0

	for (( m_itr = 0; m_itr < $media_info_sz; ))
	do
		pt=${media_info[$m_itr+0]}
		pt_bpn=${media_info[$m_itr+2]}
		pt_serial=(${media_info[$m_itr+3]})
		pt_serial=`echo ${pt_serial:0:3}`
		pt_vendor=${media_info[$m_itr+1]}

		# Skip Gen7 media validation for non-extn blades
		if [ "$extn_gen7med_chk" = "EXTN_GEN7MED_CHK" -a "$SWBD" != "SWBD178" ]
		then
			# Get slot number
			slot=`echo $pt | sed '/\/.*/s///g'`
			# Check if this slot# corresponds to that of extn blade
			echo $extn_blade_slots | grep -w $slot 1> ${NULL} 2>&1
			if [ $? -eq 1 ]
			then
				mediatrc "Skipping port $pt media validation on non-extn blade"
				m_itr=`expr $m_itr + $per_port_media_info`
				continue
			fi
		fi

		validate_media_bpn_serial $pt_bpn $pt_serial $pt_vendor $pt $extn_gen7med_chk
		if [ $? -eq 0 ]
		then
			mediatrc "Port $pt does not contain valid Brocade media"
			mediatrc "Port $pt, BPN $pt_bpn, Serial Prefix $pt_serial, Vendor $pt_vendor"
			if [ -z "$BAD_MEDIA_PORTS" ]
			then
				BAD_MEDIA_PORTS=$pt
			else
				BAD_MEDIA_PORTS=$BAD_MEDIA_PORTS,$pt
			fi
			bad_media=`expr $bad_media + 1`
		fi

		m_itr=`expr $m_itr + $per_port_media_info`
	done

	if [ $bad_media -ne 0 -a ! -z "$BAD_MEDIA_PORTS" ]
	then
		# Error string is different for generic media validation than that for
		# gen7 media validation on extnesion platform.
		if [ "$extn_gen7med_chk" != "EXTN_GEN7MED_CHK" ]
		then
			medialog "WARNING: Total $bad_media ports do not have valid Brocade Media."
			MEDIA_PIRACY_VALIDATION_FAILED=$(eval echo "$MEDIA_PIRACY_VALIDATION_FAILED")
			BNA_MEDIA_PIRACY_VALIDATION_FAILED=$(eval echo "$BNA_MEDIA_PIRACY_VALIDATION_FAILED")
			# Explicit call to add_err_status since error strings were changed
			add_err_status "$MEDIA_PIRACY_VALIDATION_FAILED" "$BNA_MEDIA_PIRACY_VALIDATION_FAILED"
		else
			medialog "WARNING: Total $bad_media ports have Gen7 Brocade Media."
			EXTN_GEN7_MEDIA_VALIDATION_FAILED=$(eval echo "$EXTN_GEN7_MEDIA_VALIDATION_FAILED")
			BNA_EXTN_GEN7_MEDIA_VALIDATION_FAILED=$(eval echo "$BNA_EXTN_GEN7_MEDIA_VALIDATION_FAILED")
			# Explicit call to add_err_status since error strings were changed
			add_err_status "$EXTN_GEN7_MEDIA_VALIDATION_FAILED" "$BNA_EXTN_GEN7_MEDIA_VALIDATION_FAILED"
		fi
		return $STS_ERR
	fi

	return $STS_OK
}


###########################################################
#             Media Piracy section - End                  #
###########################################################



#
# Block downgrade ON Gen 6 Extension Platforms:
# To 8.2.x or 8.1.x FOS version that do not support Secure Media
# (ie These will not have tag EXTN_PRE90_GEN7_MEDIA_SUPPORTED)
# from FOS Versions >=8.2.2d or >= 8.2.1e on extension platforms
# if Gen7 media is plugged.

# This function is not intended to validate Skybolt (Gen5 extension platform),
# since Skybolt will not block Gen7/Secured media when running with any version of 8.x firmware.
#

EXTN_GEN7_MEDIA_VALIDATION_FAILED="Firmware downgrade is not allowed as port\(s\) \$BAD_MEDIA_PORTS have Gen7 Media plugged into them. Please replace those media and validate media using \"sfpshow\" CLI. Then proceed with firmware downgrade"

BNA_EXTN_GEN7_MEDIA_VALIDATION_FAILED=$EXTN_GEN7_MEDIA_VALIDATION_FAILED

check_gen7secure_media_on_extn_platforms()
{
	# Check if Extension Platform.
	# If Not then no further gen7 secure media checking is needed
	is_gen6_extn_platform
	if [ $? -eq 0 ]
	then
		return $STS_OK
	fi
	# Check if target firmware has support for Gen7 media on extension platform
	extn_gen7med_supported=`grep -c "EXTN_PRE90_GEN7_MEDIA_SUPPORTED" $NEW_PREINST_FILE`
	if [ $extn_gen7med_supported -ne 0 ]
	then
		return $STS_OK
	fi

	# Check if target firmware is either 8.2.2c or 8.2.1e or v9.x
	# or their respective CVR, CCE derivatives. These are from the exception list.
	# These target firmwares have support for Gen7 media on extension platform;
	# but they do not have corresponding TAG in their preinstall script.
	# Hence explicitly check those firmwares from exception list and allow downgrade to the same.
	# Also accommodate for CVR, CCE etc of 8.2.2c or 8.2.1e or 9.x.
	#
	# IMP Note - Do not add any more versions to this exception list; instead
	# whenever Gen7 optics support on extn platform gets back ported to any more
	# 8.x version, at that time add corresponding TAG to their preinstall script
	FWNAME=$(od --strings /tmp/release.plist | grep "Fabric OS" | awk '{print $4}')
	if [[ "$FWNAME" == "8.2.2c"* || "$FWNAME" == "8.2.1e"* || "$FWNAME" == "9."* ]]
	then
		return $STS_OK
	fi

	# Since target 8.x firmware does not support Gen7 media, validate if any
	# Gen7 media plugged in to extension platform
	# Use "" so that single argument goes to TEST function
	TEST "validate_media EXTN_GEN7MED_CHK"

	return $STS_OK
}

ADMIN_ACCT_DISABLED="WARNING: Default \"admin\" account is disabled currently and it cannot be enabled back with user-defined account(s) in the target version."

check_admin_acct()
{
    FILE="/etc/shadow"
	def_acct_check=`grep -c "DEFAULT_ADMIN_ACCOUNT_CHECK" $NEW_PREINST_FILE`
	FWNAME=$(od --strings /tmp/release.plist | grep "Fabric OS" | awk '{print $4}')

	if [[ "$FWNAME" == "9."* ]]
	then
		return $STS_OK
	fi
	if [ "$def_acct_check" != 0 ]; then
		return $STS_OK
	fi	
    if [ ! -f $FILE ]; then
        return $STS_OK
    fi
    while read line
    do
        acctname=`echo $line | cut -d ':' -f1`
        if [ $acctname == 'admin' ]; then
            inactive=`echo $line | cut -d ':' -f8`
            if [ $inactive ] ; then
                if [ $inactive -eq 0 ]; then
                    echo -e "$ADMIN_ACCT_DISABLED"
					echo -e "$ADMIN_ACCT_DISABLED" >> $BNA_WARN_STATUS_FILE
                fi
            fi
        fi
    done < $FILE
    return $STS_OK
}





################ Check for special WWN Failure Mitigation compatibility ######################
WWN_FAILURE_MITIGATION_SUPPORT_MSG="Cannot download the requested firmware because it does not support the WWN failure mitigation feature."
WWN_CF_NFLT_MSG="Both WWN cards are not accessible. Firmwaredownload is not possible until access to WWN cards is restored"
WWN_CF_CFLT_MSG="Firmwaredownload is not possible because both WWN cards are not accessible and the Use of CF copy is not Authorized
\n\tPlease contact your service provider to obtain and add the license to authorize the use of CF copy
\n\tAnd then retry Firmwaredownload"
WWN_CF_ACTV_MSG="Firmwaredownload is not possible because both WWN cards are not accessible and the Target FOS Version does not support CF copy of WWN card data.
\n\tPlease retry firmaredownload to a FOS Version that supports the CF copy of WWN Cards."


CF_ACTIVE=8
CF_FAULTY=9
CF_NFAULTY=10
check_wfm_support()
{

	# WFM check is only applicable to the DCX platform
	# For any other platform return $STS_OK to proceed
	if  [ ${SWBD##SWBD} -ne 62 ]; then
		return $STS_OK
	fi

	# First Read WFM State;
	state=$(od -x /var/config/wwn/wfm_ctrl  | awk '{print $3}')
	state=$(expr $state + 0)

    # checks if in Faulty without CF copy of wwn data 
	# This State is merged with CF_FAULTY - with use of cached data
	# So this is not expected to be exercised
	# if [ -f /var/config/wwn/CF_NFLT ]; then
	if [ $state -eq 10 ]; then				# State = 10 = Faulty without WWN data copy
		let rc=$rc+1
		echo -e $rc:    $WWN_CF_NFLT_MSG >> $STATUS_FILE
		echo -e $rc:    $WWN_CF_NFLT_MSG >> $BNA_STATUS_FILE
		return $STS_ERR;
	fi
	
    # checks if in Faulty with CF copy of wwn data 
	# Either straight from CF (if one of the WWN cards was accessible)
	# Or recreated from the Cache when both WWN cards are not accessible.
	# if [ -f /var/config/wwn/CF_CFLT ]; then
	if [ $state -eq $CF_FAULTY ]; then		# State = 9 = Faulty with WWN data copy
		let rc=$rc+1
		echo -e $rc:    $WWN_CF_CFLT_MSG >> $STATUS_FILE
		echo -e $rc:    $WWN_CF_CFLT_MSG >> $BNA_STATUS_FILE
		return $STS_ERR;
	fi
	
        
	wwn_failure_mitigation_supported=`grep -c "WWN_FAILURE_MITIGATION_SUPPORTED" $NEW_PREINST_FILE`

    # checks if in Active State
	#if [ -f /var/config/wwn/CF_ACTV ]; then
	if [ $state -eq $CF_ACTIVE ]; then		# State = 8 = Active (ie Licensed to use CF copy with both cards faulted) 
		# Check if target FOS supports WFM if so allow the upgrade
		if [ $wwn_failure_mitigation_supported -ne 0 ]; then
            # System is in CF_ACTIVE state && Target FOS supports WFM - OK to proceed:
			# i.e Both WWN cards are inaccessible AND Use of WWN CF copy is authorized with special licence
			# And target FOS supports WWN failure mitigation
			# Hence OK to proceed with firmwaredownload to target FOS
            return $STS_OK;
		else
			let rc=$rc+1
			echo -e $rc:    $WWN_CF_ACTV_MSG >> $STATUS_FILE
			echo -e $rc:    $WWN_CF_ACTV_MSG >> $BNA_STATUS_FILE
			return $STS_ERR;
		fi
	fi
 
	return $STS_OK;
}

<< 'TEMP-HACK-FOR-CUT-PASTE-UNIT_TEST'
#if [ -f /var/config/wwn/CF_ACTV ]; then 	
if [ $state -eq $CF_ACTIVE ]; then
	if [ $wwn_failure_mitigation_supported -ne 0 ]; 
	then
		echo "cf_actv and target supports wfm"; 
	else 
		echo "cf_actv but target does not support wfm"; 
		echo "abort fwdl"; 
	fi; 
else
	echo "Not in cf_actv"
fi
TEMP-HACK-FOR-CUT-PASTE-UNIT_TEST

# main()
#
echo > $STATUS_FILE      # Clear the error file
echo > $BNA_STATUS_FILE  # Clear the BNA error file
echo "Please address the following before downloading the specified firmware:" >> $STATUS_FILE

check_new_8548_CP_fw_compatibility
check_non_dfe
check_qsfpp_icl
check_2km_32G_qsfp
check_buf_op_mode
check_q20_supported
check_permanet_root_disable_huawei_supported
check_enhanced_fc8_blades
check_nondfeforcedisable_supported
check_tacacs_encryption
check_radius_tacacs_encryption
check_serdes_version_between_cur_n_new_fos
check_for_new_128MB_flash
check_wedgecr
check_special_huawei_disable_enc_support
check_for_clean_address_bit
check_for_BSL
check_emulex_fport_trunking
check_ldap_support_for_group_length
check_v8x_supporting_eula
check_cypress_bootflash
check_gen7secure_media_on_extn_platforms
check_admin_acct
check_wfm_support
exit $rc

