#!/bin/ksh
#
# Script to initiate Flash update from Soalris
# id: @(#)FWupdate 1.11 04/09/08
# purpose: 
# copyright: Copyright 2003-2004 Sun Microsystems, Inc.  All Rights Reserved
#


#
# Display the banner
#

BANNER="@(#) Flash Update Tool (c) 2002 Sun Microsystems, Inc. v"
VER="0.2"
echo
echo
echo $BANNER$VER
echo


#
# Assign the defaults
#

filename="zzxyz"
device="zzxyz"
fwtype="zzxyz"
force=0

#
# Define the script usage
#

usage()
{
    echo "usage: $0 [-h]"
    echo "usage: $0 [-F] -f <filepath> -d <device> -t <FW type>"
    echo
    echo "\t -h : Help, show usage"
	echo "\t -F : To Force the update when the FW is being downgraded"
    echo "\t -f : Complete filepath & filename specified by following argument"
    echo "\t -t : Type of FW binary. Possible options={sparc, smc, sparc+smc}"
    echo "\t -d : Complete path of device node or device alias specifying"
    echo "\t      the device where file is located"
    echo "\t      If disk is specified, the file must be in the root"
	echo "\t      directory. Also, the file cannot of a Symbolic link"
	echo
	echo "\t      Note: To use this script, you must be super user"
	echo
	echo "#### RUNNING THIS SCRIPT REBOOTS THE CPU BOARD FOR FIRMWARE UPDATE ####"
    echo
}


#
# Look at the arguments and validate them
#

set -A opts
opts[1]=$1
opts[2]=$2
opts[3]=$3
opts[4]=$4
opts[5]=$5
opts[6]=$6
opts[7]=$7
opts[8]=$8

i=1
while [ $i -le $# ]
do
    j=$((i+1))

    case ${opts[$i]} in
    -f) filename=${opts[$j]} ; i=$((i+2)) ;;
    -d) device=${opts[$j]}   ; i=$((i+2)) ;;
    -t) fwtype=${opts[$j]}   ; i=$((i+2)) ;;
    -h) usage ; exit 1 ;;
	-F) force=1              ; i=$((i+1)) ;;
     *) echo "Bad options. Use -h option for help" ; exit 1;;
    esac
done


#
# Check if we are Super User
#

UTYPE1=`id`
UTYPE2=`id | grep root`
if [[ $UTYPE1 != $UTYPE2 ]]
then
	echo "### MUST BE SUPER USER TO EXECUTE THIS SCRIPT ###"
	exit 1
fi

echo
echo
echo "##### THIS SCRIPT WILL REBOOT THE SYSTEM TO PERFORM FIRMWARE UPDATE #####"
echo


#
# Check if all mandatory options are specified
#

if [[ $filename = "zzxyz" ]]
then
	echo "Missing \"filename\". Use -f option to specify the filename"
	echo "Use -h option to get the usage"
	exit 1
fi

if [[ $device = "zzxyz" ]]
then
	echo "Missing \"device\". Use -d option to specify the device"
	echo "Use -h option to get the usage"
	exit 1
fi

if [[ $fwtype = "zzxyz" ]]
then
	echo "Missing \"FW type\". Use -t option to specify the FW type"
	echo "Use -h option to get the usage"
	exit 1
fi


#
# Display the current options selected
#

echo "Using the following settings..."
echo "Filename : " $filename
echo "Device   : " $device
echo "FW type  : " $fwtype


#
# Check the value of <FW type>
#

case $fwtype in
sparc)      cmd=flash-update;;
smc)        cmd=smc-flash-update;;
sparc+smc)  cmd=flash-update;;
*)          echo "Unknown \"<FW Type>\" value : " $fwtype ; exit 1;;
esac

#
# The file specified should not have any relative paths. Must be
#   complete filepaths
#

BASEFILENAME=`basename $filename`
DIRFILENAME=`dirname $filename`

while true
do
	if [[ $BASEFILENAME = "." ]] || [[ $BASEFILENAME = ".." ]]
	then
		echo "Relative File Paths are not allowed"
		echo "Please Specify the Complete Filepath without the use of \"..\" & \".\""
		exit 1
	fi
	if [[ $BASEFILENAME = "/" ]]
	then
		break
	fi
	BASEFILENAME=`basename $DIRFILENAME`
	DIRFILENAME=`dirname $DIRFILENAME`
done

# Device name maybe just an devalias or complete path to device node
# When device is disk:
#	Filename cannot be a Symbolic Link
#	Filename must be in root directory

DEVICENAME=`basename $device`
DEVICEBASENAME=`echo $DEVICENAME | awk -F@ '{ print $1 }'`
DIRFILENAME=`dirname $filename`

if [[ $DEVICEBASENAME = "disk" ]] || [[ $DEVICEBASENAME = "sd" ]]
then
	if [ -L $filename ]
	then
		echo "File $filename is a Symbolic Link"
		echo "Update from disk cannot work with a Sym Link"
		exit 1
	fi

	if [[ $DIRFILENAME != "/" ]]
	then
		echo "Update from disk needs the file to be in Root directory"
		exit 1
	fi
fi

#
# Check if specified file exists
#

if [ -d $filename ]
then
	echo "$filename is a directory!"
	exit 1
fi

if [ ! -f $filename ]
then
	echo "Specified file : " $filename " Not Found"
	exit 1
fi


#
# Lets check the contents of the binary
#

echo
echo "Checking the input file format..."

MAGIC=`od -X -N 4 $filename | awk '{print $2}'`
case $MAGIC in
"4f424d44") echo "\tFile is OBP/Combined image"   ; INP=flash-update ;;
"43450000") echo "\tFile is SMC Boot Code image"  ; INP=smc-flash-update ;;
"43452000") echo "\tFile is SMC Boot Code image"  ; INP=smc-flash-update ;;
"43460000") echo "\tFile is SMC Flash Code image" ; INP=smc-flash-update ;;
*)          echo "\tFile is of Unknown Format. Cannot Proceed!" ; exit 1 ;;
esac

if [[ $cmd != $INP ]]
then
	echo "Specified \"FW Type\" DOES NOT matches the Input File Format"
	echo "Use -t option to specify right \"FW type\". Cannot proceed!"
	exit 1
fi


#
# Lets get the new binary info
#

echo
SCRPTPATH=`dirname $0`
echo "FW Info file : " $SCRPTPATH/.FWupdate.info
. $SCRPTPATH/.FWupdate.info

V_MAJOR=`echo $FWVER | sed "s/\./ /g" | awk '{ print $1 }'`
V_MIN=`echo $FWVER | sed "s/\./ /g" | awk '{ print $2 }'`
V_BUILD=`echo $FWVER | sed "s/\./ /g" | awk '{ print $3 }'`

echo
echo "NEW FIRMWARE INFO :"
echo "SPARC Version  : " $FWVER
echo "SMCFW Version  : " $SMCFWVER
echo "Board          : " $BOARDNAME
echo "Model          : " $BOARDMODEL

if [[ $BOARDNAME1 != NULL ]]
then
	echo "Alternate Board: " $BOARDNAME1
	echo "Altername Model: " $BOARDMODEL1
fi
if [[ $BOARDNAME2 != NULL ]]
then
	echo "Alternate Board: " $BOARDNAME2
	echo "Altername Model: " $BOARDMODEL2
fi
if [[ $BOARDNAME3 != NULL ]]
then
	echo "Alternate Board: " $BOARDNAME3
	echo "Altername Model: " $BOARDMODEL3
fi
echo


#
# Lets get the existing binary info
#

PRTDIAG=/usr/platform/`uname -i`/sbin/prtdiag
PRTCONF=/usr/sbin/prtconf

echo "CURRENT FIRMWARE INFO :"

CURRFWVER=`$PRTCONF -V | awk '{print $18}'`
CV_MAJOR=`$PRTCONF -V | awk '{print $18}' |sed "s/\./ /g" | awk '{ print $1 }'`
CV_MIN=`$PRTCONF -V | awk '{print $18}' |sed "s/\./ /g" | awk '{ print $2 }'`
CV_BUILD=`$PRTCONF -V | awk '{print $18}' |sed "s/\./ /g" | awk '{ print $3 }'`


CURRBOARDNAME=`$PRTDIAG | grep SPARC | awk '{print $6}'`
if [[ $CURRBOARDNAME == "Netra" ]] || [[ $CURRBOARDNAME == "Netra(tm)" ]]
then
    CURRBOARDMODEL=`$PRTDIAG | grep SPARC | awk '{print $7}'`
else
    CURRBOARDNAME=`$PRTDIAG | grep SPARC | awk '{print $7}'`
    CURRBOARDMODEL=`$PRTDIAG | grep SPARC | awk '{print $9}'`
fi


echo "SPARC Version  : " $CURRFWVER
echo "Board          : " $CURRBOARDNAME
echo "Model          : " $CURRBOARDMODEL


#
# Lets check the validity  : board type, model, fw version etc.
#

if [[ $CURRBOARDNAME != $BOARDNAME ]] && [[ $CURRBOARDNAME != $BOARDNAME1 ]] && [[ $CURRBOARDNAME != $BOARDNAME2 ]] && [[ $CURRBOARDNAME != $BOARDNAME3 ]]
then
	echo "The New Firmware Binary does not belongs to this platform"
	echo "Board Name do not match. Cannot proceed!"
	exit 1
fi

if [[ $CURRBOARDMODEL != $BOARDMODEL ]] && [[ $CURRBOARDMODEL != $BOARDMODEL1 ]] && [[ $CURRBOARDMODEL != $BOARDMODEL2 ]] && [[ $CURRBOARDMODEL != $BOARDMODEL3 ]]
then
	echo "The New Firmware Binary does not belongs to this platform"
	echo "Board Model do not match. Cannot Proceed!"
	exit 1
fi

MESSAGE0="Start to update the firmware ..."
MESSAGE1="WARNING: The New FW Version is Older than the Current FW!"
MESSAGE2="Use -F option to Force the Update of this Firmware"
MESSAGE3="WARNING: The New FW Version is Equal to the Current FW!"
echo

typeset -i v_major
typeset -i v_min
typeset -i v_build
typeset -i cv_major
typeset -i cv_min
typeset -i cv_build

typeset -i tmp_data

v_major=$V_MAJOR
v_min=$V_MIN
v_build=$V_BUILD
cv_major=$CV_MAJOR
cv_min=$CV_MIN
cv_build=$CV_BUILD


if [ $v_major -gt $cv_major ]
then
	echo "$MESSAGE0.."
else
	if [ $v_major -lt $cv_major ]
	then
		echo "$MESSAGE1!!"
		if [ $force -eq 0 ]
		then
			echo "$MESSAGE2"
			exit 1
		fi
	else
		if [ $v_min -gt $cv_min ]
		then
			echo "$MESSAGE0."
		else
			if [ $v_min -lt $cv_min ]
			then	
				echo "$MESSAGE1!"
 				if [ $force -eq 0 ]
 				then
					echo "$MESSAGE2"
 					exit 1
 				fi
			else
				if [ $v_build -gt $cv_build ]
				then
					echo "$MESSAGE0"
				else
					if [ $v_build -lt $cv_build ]
					then
						echo "$MESSAGE1"
						if [ $force -eq 0 ]
						then
							echo "$MESSAGE2"
							exit 1
						fi
					else
						echo "$MESSAGE3"
						if [ $force -eq 0 ]
						then
							echo "$MESSAGE2"
							exit 1
						fi
					fi
				fi
			fi
		fi
	fi
fi

#
# All the validation has been done. Lets initiate the update.
#

echo
echo "Updating $fwtype image with file :"
echo "\t\t$filename"
echo "\t\ton device \"$device\" using \"$cmd\""

rebootpar="obp:$cmd $device:,$filename"

echo
echo "Reboot parameter:"
echo "\t\t" $rebootpar
echo

sync;sync;sync
/usr/sbin/reboot -- "$rebootpar"


#
# Control should not get here...
#

echo
echo Reboot Failed!!!
echo
