#!/bin/sh

# Remove flash drivers on exit
trap "rmmod flash >/dev/null 2>&1; rmmod flashenv >/dev/null 2>&1" 0

flash=/dev/flash0
chgnand=n
chkbut=y
upg=y
force=n
badfiletype=n
useflashenv=n
moddir=/lib/modules/`uname -r`

host=`platform`
case $host in
	PCS100 )
		filen=pcs100.ldr
		flash=/dev/flash_raw
		filek=pcs100.kimg
		chkbut=n
		;;
	PCS200 )
		filen=pcs200.ldr
		filek=pcs200-16M.kimg
		chkbut=n
		;;
	PCS400 )
		filen=pcs400.ldr
		filek=pcs400-16M.kimg
		chkbut=n
		;;
	VCM )
		insmod $moddir/flashenv.ko rwe=1 >/dev/null 2>&1
		useflashenv=y
		filen=vcm.ldr
		filek=vcm-16M.kimg
		;;
	PHONE )
		insmod $moddir/flashenv.ko rwe=1 >/dev/null 2>&1
		useflashenv=y
		filen=phone.ldr
		filek=phone-16M.kimg
		;;
	TRUNK )
		insmod $moddir/flashenv.ko rwe=1 >/dev/null 2>&1
		useflashenv=y
		filen=trunk.ldr
		filek=trunk-16M.kimg
		;;
	CALLSERVER )
		filen=callserver.ldr
		nfile=callserver-16M.nimg
		chgnand=y
		;;
	REMOTECS )
		filen=rcallserver.ldr
		nfile=rcallserver-16M.nimg
		chgnand=y
		;;
	PM5315 | PM5330 )
		insmod flashenv >/dev/null 2>&1
		useflashenv=y
		filen=lx.ldr
		filek=ph53xx-256M.kimg
		;;
	TM5204 )
		insmod flashenv >/dev/null 2>&1
		useflashenv=y
		filen=cs5108.ldr
		filek=tm5204-256M.kimg
		chkbut=n
		;;
	TM5230 )
		insmod flashenv >/dev/null 2>&1
		useflashenv=y
		filen=lx.ldr
		filek=tm52xx-256M.kimg
		;;
	PCS410 )
		insmod flashenv >/dev/null 2>&1
		useflashenv=y
		filen=lx.ldr
		filek=pcs410-256M.kimg
		;;
	* )
		echo Unknown Host $host
		exit
		;;
esac

# get some networking info from all possible sources
if [ -f /var/lib/dhcpcd/dhcpcd-eth0.info ]; then
	eval `awk -F= '{if (substr($2,1,1)=="\"") print $0; else printf "%s=\"%s\"\n", $1,$2}' /var/lib/dhcpcd/dhcpcd-eth0.info`
fi
if [ -f /var/lib/udhcpc/udhcpc-eth0.info ]; then
	eval `awk -F= '{if (substr($2,1,1)=="\"") print $0; else printf "%s=\"%s\"\n", $1,$2}' /var/lib/udhcpc/udhcpc-eth0.info`
fi
if [ -f /tmp/os_env ]; then
	[ -x /usr/bin/get_os_env ] && /usr/bin/get_os_env > /tmp/os_env
	. /tmp/os_env
fi

if [ $# -gt 0 ]; then
	case $1 in
		now | soon )
			if [ \( $host = "CALLSERVER" \) -o \( $host = "REMOTECS" \) ]; then
				echo You can\'t upgrade a $host this way
				exit
			fi

			### check for upgrade file ###
			#  decide on server ip address
			if [ $# -eq 2 ]; then
				tftps=$2
			else
				# check from DHCP
				[ "$DHCPSIADDR" ] && tftps=$DHCPSIADDR

				# check static from os_env
				[ "$os_tftpsvr" ] && tftps=$os_tftpsvr
			fi
			# now check we can get file
			if [ "$tftps" ]; then
				echo Using server $tftps
				tftp -g -l /dev/null -r ${filek} $tftps
				if [ $? -ne 0 ]; then
					echo "###### Can\'t find upgrade file on $tftps server"
					[ $useflashenv = "y" ] && rmmod flashenv >/dev/null 2>&1
					exit 1
				fi
			else
				echo Can\'t decide what server will be used - please enter an ip address
				[ $useflashenv = "y" ] && rmmod flashenv >/dev/null 2>&1
				exit 1
			fi

			if [ $host = "PCS100" ]; then
				insmod $moddir/flash.ko >/dev/null 2>&1
				if [ $# -eq 2 ]; then
					echo upgsvr=$2 > /dev/flash_env_single
				fi
				magic=`dd if=$flash bs=4 skip=8192 count=1 2>/dev/null | od -D | awk '{print $2;exit}'`
				prevn=`dd if=$flash bs=4 skip=8194 count=1 2>/dev/null | od -D | awk '{print $2;exit}'`
				if [ \( $magic -eq 1414807885 \) -a \( $prevn -gt 1 \) ]; then
					echo upgnand=y > /dev/flash_env_single
				else
					eraseall -q /dev/mtd0
				fi
				rmmod flash >/dev/null 2>&1
				if [ $1 = "now" ]; then
					echo rebooting for upgrade
					/sbin/reboot
				fi
			else
				if [ \( $host = "PCS400" \) -o \( $host = "PCS200" \) ]; then
					if [ $# -eq 2 ]; then
						echo upgsvr=$2 > /dev/flash_env_single
					fi
					setcmd -1
					if [ $1 = "now" ]; then
						echo rebooting for upgrade ...
						/sbin/poweroff
						sleep 60
					fi
				elif [ \( $host = "PM5315" \) -o \( $host = "PM5330" \) -o \( $host = "TM5230" \) -o \( $host = "PCS410" \) ]; then
					if [ $2 ]; then
						n=""
						[ "$os_ipaddr" ] && n=$os_ipaddr
						g=""
						[ "$os_router" ] && g=$os_router
						s=""
						[ "$os_tftpsvr" ] && s=$os_tftpsvr
						if [ "$n" -a "$g" -a "$s" ]; then
							echo "This unit has a static (non-DHCP) network configuration"
							echo -n "Do you want to over write that configuration [yYnN] ? "
							read a
							case $a in
								y* | Y* )
									;;
								* )
									[ $useflashenv = "y" ] && rmmod flashenv >/dev/null 2>&1
									exit
									;;
							esac
						fi
						if [ $useflashenv = "y" ]; then
							echo "os_ipaddr=" > /dev/flash_env_single
							echo "os_router=" > /dev/flash_env_single
							echo "os_tftpsvr=$2" > /dev/flash_env_single
						fi
					fi

					[ $useflashenv = "y" ] && echo "upgnand=y" > /dev/flash_env_single

					if [ $1 = "soon" ]; then
						echo "upgrade scheduled for next reboot (use poweroff command when ready)"
					else
						echo rebooting for upgrade ...
						/sbin/poweroff
						sleep 60
					fi
				else
					if [ $2 ]; then
						[ "$os_ipaddr" ] && n=$os_ipaddr
						[ "$os_router" ] && g=$os_router
						[ "$os_tftpsvr" ] && s=$os_tftpsvr
						if [ "$n" -a "$g" -a "$s" ]; then
							echo "This unit has a static (non-DHCP) network configuration"
							echo -n "Do you want to over write that configuration [yYnN] ? "
							read a
							case $a in
								y* | Y* )
									;;
								* )
									[ $useflashenv = "y" ] && rmmod flashenv >/dev/null 2>&1
									exit
									;;
							esac
						fi
						if [ $useflashenv = "y" ]; then
							echo "os_ipaddr=" > /dev/flash_env_single
							echo "os_router=" > /dev/flash_env_single
							echo "os_tftpsvr=$2" > /dev/flash_env_single
						fi
					fi

					[ $useflashenv = "y" ] && echo "upgnand=y" > /dev/flash_env_single

					if [ $1 = "soon" ]; then
						echo "upgrade scheduled for next reboot (use poweroff command when ready)"
					else
						echo rebooting for upgrade ...
						/sbin/poweroff
						sleep 60
					fi
				fi
			fi
			;;
		cancel )
			if [ \( $host = "PHONE" \) -o \( $host = "TRUNK" \) -o \( $host = "VCM" \) ]; then
				[ $useflashenv = "y" ] && echo "upgnand=n" > /dev/flash_env_single
				echo upgrade cancelled
			else
				echo option not supported on $host
			fi
			;;
		loader )
			if [ $# -gt 1 ]; then
				if [ $# -gt 2 ]; then
					if [ $3 = "force" ]; then
						force=y
					fi
				fi
				tftp -g -l /tmp/${filen} -r ${filen} $2
				if [ $? -eq 0 ]; then
					if [ -f /tmp/${filen} ]; then
						filen=/tmp/${filen}
						echo Running upgrade for $host

						rmmod flash >/dev/null 2>&1
						if [ $host = PCS100 ]; then
							lsmod | grep -q "^flash"
							if [ $? -ne 0 ]; then
								insmod $moddir/flash.ko >/dev/null 2>&1
								if [ $? -ne 0 ]; then
									echo failed to load flash driver
									exit
								fi
							fi
						elif [ \( $host = PM5315 \) -o \( $host = PM5330 \) -o \( $host = TM5230 \) -o \( $host = PCS410 \) ]; then
							# Hand over to the loader upgrade script
							mv ${filen} /SpliceCom/loader
							exec /etc/init.d/loader $3
						else
							lsmod | grep -q "^flash"
							if [ $? -ne 0 ]; then
								insmod /SpliceCom/loader/flash.ko rwe=1 >/dev/null 2>&1 || \
								insmod $moddir/flash.ko rwe=1 >/dev/null 2>&1 || \
								insmod /SpliceCom/loader/flash.ko >/dev/null 2>&1 || \
								insmod $moddir/flash.ko >/dev/null 2>&1
								if [ $? -ne 0 ]; then
									echo failed to load flash driver
									exit
								fi
							fi
						fi
						if [ ! -r $filen ]; then
							echo can\'t open $filen
							exit
						fi
						if [ ! -w $flash ]; then
							echo can\'t open $flash
							exit
						fi
						if [ $chkbut = "y" ]; then
							if [ `cat /dev/button` -eq 1 ]; then
								echo Loader upgrade aborted due to button push
								exit
							fi
						fi

						echo '#####################################################################################'
						echo Upgrade process will take some time, please be patient and do not power down the unit
						echo '#####################################################################################'

						if [ $host = "PCS100" ]; then
							# Note that od on PCS100 is implemented by busybox and can't take fancy options
							magic=`dd if=$filen bs=1 skip=32768 count=4 2>/dev/null | od -D | awk '{print $2; exit}'`
							ftype=`dd if=$filen bs=1 skip=32772 count=4 2>/dev/null | od -D | awk '{print $2; exit}'`
							frevn=`dd if=$filen bs=1 skip=32776 count=4 2>/dev/null | od -D | awk '{print $2; exit}'`
							fbldn=`dd if=$filen bs=1 skip=32780 count=4 2>/dev/null | od -D | awk '{print $2; exit}'`
							if [ $ftype -ne 1297370946 ]; then
								badfiletype=y
							fi
						elif [ $host = "TM5204" ]; then
							magic=`od -An -j32768 -N4 -td4 $filen`
							ftype=`od -An -j32772 -N4 -td4 $filen`
							frevn=`od -An -j32776 -N4 -td4 $filen`
							fbldn=`od -An -j32780 -N4 -td4 $filen`
							if [ $ftype -ne 1297370946 ]; then
								badfiletype=y
							fi
						else
							magic=`od -An      -N4 -td4 $filen`
							ftype=`od -An -j4  -N4 -td4 $filen`
							frevn=`od -An -j8  -N4 -td4 $filen`
							fbldn=`od -An -j12 -N4 -td4 $filen`
							if [ $ftype -ne 1414483778 ]; then
								badfiletype=y
							fi
						fi

						if [ $magic -ne 1414807885 ]; then
							echo bad file magic for new loader
						else
							if [ $badfiletype = "y" ]; then
								echo file type is not a loader
							else
								echo file: contains loader rev $frevn build $fbldn

								if [ $host = "PCS100" ]; then
									magic=`dd if=$flash bs=1 skip=32768 count=4 2>/dev/null | od -D | awk '{print $2; exit}'`
									prevn=`dd if=$flash bs=1 skip=32776 count=4 2>/dev/null | od -D | awk '{print $2; exit}'`
									pbldn=`dd if=$flash bs=1 skip=32780 count=4 2>/dev/null | od -D | awk '{print $2; exit}'`
								elif [ $host = "TM5204" ]; then
									magic=`od -An -j32768 -N4 -td4 $flash`
									prevn=`od -An -j32776 -N4 -td4 $flash`
									pbldn=`od -An -j32780 -N4 -td4 $flash`
								else
									magic=`od -An      -N4 -td4 $flash`
									prevn=`od -An -j8  -N4 -td4 $flash`
									pbldn=`od -An -j12 -N4 -td4 $flash`
								fi

								if [ $magic -ne 1414807885 ]; then
									echo FLASH contains old style loader
									
									if [ $chgnand = y ]; then
										nflash=/dev/nflash0
										blksz=16896
										maxbad=400
										nandblks=1024
										lsmod | grep -q "^nflash"
										if [ $? -ne 0 ]; then
											insmod $moddir/nflash.ko >/dev/null 2>&1
											if [ $? -ne 0 ]; then
												echo failed to load NAND flash driver
												[ $useflashenv = "y" ] && rmmod flashenv >/dev/null 2>&1
												exit
											fi
										fi
										tftp -g -l /tmp/${nfile} -r ${nfile} $2
										if [ $? -ne 0 ]; then
											echo failed to get $nfile
											[ $useflashenv = "y" ] && rmmod flashenv >/dev/null 2>&1
											exit
										fi
										nfile=/tmp/${nfile}
										if [ ! -r $nfile ]; then
											echo can\'t open $nfile
											[ $useflashenv = "y" ] && rmmod flashenv >/dev/null 2>&1
											exit
										fi
										if [ ! -w $nflash ]; then
											echo can\'t open $nflash
											[ $useflashenv = "y" ] && rmmod flashenv >/dev/null 2>&1
											exit
										fi
										len=`ls -l $nfile | cut -b33-43`
										blks=`expr $len / $blksz`
									fi

									echo Upgrading loader
									if [ $host = "PCS100" ]; then
										# Do it in 2 bits to preserve the config sectors
										dd if=$filen of=$flash bs=1k count=16
										dd if=$filen of=$flash bs=1k count=224 \
											seek=32 skip=32 conv=notrunc
									elif [ $host = "TM5204" ]; then
										# Do it in 2 bits to preserve the config sectors.
										dd if=$filen of=$flash bs=1k count=16
										dd if=$filen of=$flash bs=1k count=224 \
											seek=32 skip=32 conv=notrunc
									else
										# Do it in 2 bits to preserve the MAC address sector
										dd if=$filen of=$flash bs=1k count=128
										dd if=$filen of=$flash bs=1k count=64 \
											seek=192 skip=192 conv=notrunc
									fi

									if [ $chgnand = "y" ]; then
										echo Upgrading NAND Flash \($blks blocks\)
										inblks=0
										outblks=0
										badblks=0
										c1=`dd if=$nfile bs=$blksz count=1 skip=$inblks 2>/dev/null | cksum | cut -f 1 -d " "`
										while [ $inblks -lt $blks ]; do
											echo -n .
											dd if=$nfile of=$nflash bs=$blksz count=1 skip=$inblks seek=$outblks conv=notrunc 2>/dev/null
											c2=`dd if=$nflash bs=$blksz count=1 skip=$outblks 2>/dev/null | cksum | cut -f 1 -d " "`
											if [ $c1 = $c2 ]; then
												inblks=`expr $inblks + 1`
												c1=`dd if=$nfile bs=$blksz count=1 skip=$inblks 2>/dev/null | cksum | cut -f 1 -d " "`
											else
												badblks=`expr $badblks + 1`
												echo bad block encountered - mark bad and skip
												dd if=/dev/zero of=$nflash bs=$blksz count=1 seek=$outblks conv=notrunc 2>/dev/null
												if [ $badblks -gt $maxbad ]; then
													echo Very bad NAND - aborting
													[ $useflashenv = "y" ] && rmmod flashenv >/dev/null 2>&1
													exit
												fi
											fi
											outblks=`expr $outblks + 1`
										done
										echo

										remblks=`expr $nandblks - $outblks`
										if [ $remblks -gt 0 ]; then
											echo clearing out the rest of NAND \($remblks blocks\)
											while [ $outblks -lt $nandblks ]; do
												echo -n .
												echo -n -e '\377' | dd of=$nflash bs=$blksz count=1 seek=$outblks conv=notrunc 2>/dev/null
												outblks=`expr $outblks + 1`
											done
											echo
										fi
									fi
									echo Done
								else
									echo FLASH contains loader rev $prevn build $pbldn
									if [ $frevn -lt $prevn ]; then
										echo FLASH contents are newer than file \(use force to overwrite\)
										upg=n
									else
										if [ $frevn -eq $prevn ]; then
											if [ $fbldn -lt $pbldn ]; then
												echo FLASH contents are newer than file \(use force to overwrite\)
												upg=n
											else
												if [ $fbldn -eq $pbldn ]; then
													echo FLASH contents are the same as the file \(use force to overwrite\)
													upg=n
												fi
											fi
										fi
									fi

									if [ \( $upg = "y" \) -o \( $force = "y" \) ]; then
										echo Changing loader
										if [ $host = "PCS100" ]; then
											# Do it in 2 bits to preserve the config sectors
											dd if=$filen of=$flash bs=1k count=16
											dd if=$filen of=$flash bs=1k count=224 \
												seek=32 skip=32 conv=notrunc
										elif [ $host = "TM5204" ]; then
											# Do it in 2 bits to preserve the config sectors
											dd if=$filen of=$flash bs=1k count=16
											dd if=$filen of=$flash bs=1k count=224 \
												seek=32 skip=32 conv=notrunc
										else
											# Do it in 3 bits to preserve the MAC address sector and config sectors
											# Someday we may no longer need to keep the MAC sector
											dd if=$filen of=$flash bs=1k count=16
											dd if=$filen of=$flash bs=1k count=96 \
												seek=32 skip=32 conv=notrunc
											dd if=$filen of=$flash bs=1k count=64 \
												seek=192 skip=192 conv=notrunc
										fi
										echo Done
									fi
								fi
							fi
						fi
					else
						echo Failed to get loader file $filen
					fi
				else
					echo Failed to get loader file $filen
				fi
			else
				echo Must also specify TFTP server holding loader file $filen
			fi
			rm -f /tmp/${filen} $filen
			;;
		* )
			echo "upgrade [ now | soon | cancel ] [TFTP server IP address]"
			echo "    now - immediate shutdown, upgrade and reboot"
			echo "    soon - upgrade during next reboot"
			echo "    cancel - cancel pending (soon) upgrade"
			echo " Not all options are available on all platforms"
			;;
	esac
else
	echo "upgrade [ now | soon | cancel ] [TFTP server IP address]"
	echo "    now - immediate shutdown, upgrade and reboot"
	echo "    soon - upgrade during next reboot"
	echo "    cancel - cancel pending (soon) upgrade"
	echo " Not all options are available on all platforms"
fi
