#!/bin/sh
# A script to ease the use of the usb loader, possibly changing the mac address
#
# Authors:
#	- Benoit Rat (Seven Solutions, www.sevensols.com)
#	- Federico Vaga
# 	- Alessandro Rubini
#
# GNU Lesser General Public License Usage
# This file may be used under the terms of the GNU Lesser
# General Public License version 2.1 as published by the Free Software
# Foundation and appearing in the file LICENSE.LGPL included in the
# packaging of this file.  Please review the following information to
# ensure the GNU Lesser General Public License version 2.1 requirements
# will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
#########################################################################

#hack: allow some environment variables to change behavior, for developing
if [ "x$WRS_FAKE_FLASHER" = "x" ]; then
    fake=false
else
    fake=true
    echo "Using fake flasher (no action on switch is done)"
    sleep 1
fi

if [ "x$WRS_KEEP_TEMPORARIES" = "x" ]; then
    remove_temps=true
else
    remove_temps=false
fi

fake_flasher()
{
    echo "NOT FLASHING with command:"
    echo "   $*"
    echo ""
    sleep 3
}

showhelp()
{
	printf "Usage: $0 [options] [<firmware>.tar] [DEV]\n\n"
	printf "<firmware>.tar: Use the file in the firmware to flash the device\n"
	printf "DEV:\t The usb device (by default it is /dev/ttyACM0)\n"
	printf "Options: \n"
	printf "  -h|--help\t Show this help message\n"
	printf "  -m|--mode\t can be: default (df and nf), df (dataflash),\n\t\t nf (nandflash), ddr (ddr memories).\n"
	printf "  -g|--gateware\t Select the gateware: 18p (18 ports, default), 8p (8 ports)\n"
	printf "  -e \t\t Completely erase the memory (Can erase your configuration)\n"
	printf "  -b|--build\t Use files that you have built in the WRS_OUTPUT_DIR\n"
	exit 0
}


checkExit()
{
	# $1 == what, $2 == filename
	# (assumes $me is the script name)
	if [ -f $2 ]; then
		return 0;
	else
		echo "$me: Can't find file \"$2\" ($1)" >& 2;
		exit 1
	fi
}

# Go to the top directory
dir=$(dirname $0)/..
WRS_BASE_DIR=$(cd $dir && /bin/pwd)

# Sanity checks
if [ -d ${WRS_BASE_DIR}/usb-loader ]; then true; else
    echo "$0: ${WRS_BASE_DIR}/usb-loader: no such directory" >& 2
    exit 1
fi

if [ "x${WRS_OUTPUT_DIR}" = "x" ]; then
    export WRS_OUTPUT_DIR=$(/bin/pwd)
fi

# build flasher itself
FLASHER="${WRS_BASE_DIR}/usb-loader/mch_flasher"
if [ -x $FLASHER ]; then
    true
else
    if CC=cc make -s -C ${WRS_BASE_DIR}/usb-loader; then true; else
	echo "$0: Error compiling in directory ${WRS_BASE_DIR}/usb-loader" >&2;
	exit 1;
    fi
fi

# allow faking operations
if $fake;  then
    FLASHER="fake_flasher $FLASHER"
fi

# Default MAC address for the switch board ethernet
MAC1_DEF="02:34:56:78:9A:BC"
MAC1=$MAC1_DEF
# Default base MAC address for the 18 switch ports
MAC2_DEF="02:34:56:78:9A:00"
MAC2=$MAC2_DEF

# By default we select the gateware only for 18ports because 8ports are
# only used by developper.
gateware="18p*.bin"

DEV=""
FLAGS=""

# full path to the at91boot binary
at91bs=""
# full path to the barebox binary
barebox=""
# full path to the kernel image
kernel=""
# full path to the /usr.gz file system
usrtar=""
# full path to the cpio image
initramfs=""

if [ "x$TMPDIR" = "x" ]; then TMPDIR="/tmp"; fi

WRSTMPDIR=$(mktemp -d $TMPDIR/flash-wrs-XXXXXX)

while [ $# -ge 1 ]; do
	case $1 in
	-b|--build)
		at91bs=${WRS_OUTPUT_DIR}/images/at91bootstrap.bin;
		barebox=${WRS_OUTPUT_DIR}/images/barebox.bin
		kernel=${WRS_OUTPUT_DIR}/images/zImage
		initramfs=${WRS_OUTPUT_DIR}/images/wrs-initramfs.gz
		usrtar=${WRS_OUTPUT_DIR}/images/wrs-usr.tar.gz
		tarball=${WRS_OUTPUT_DIR}/images/wrs-firmware.tar
		shift;;

	*.tar)
		checkExit "tar-file" $1
		tar --directory $WRSTMPDIR -xf $1
		at91bs=$WRSTMPDIR/at91bootstrap.bin;
		barebox=$WRSTMPDIR/barebox.bin
		kernel=$WRSTMPDIR/zImage
		initramfs=$WRSTMPDIR/wrs-initramfs.gz
		usrtar=$WRSTMPDIR/wrs-usr.tar.gz
		tarball=$1
		shift;;

	-h|--help) 	showhelp; shift;;

	-m|--memmode)
		# verify memory mode
		if [ "$2" != "nf" ] && [ "$2" != "df" ] && [ "$2" != "ddr" ] && [ "$2" != "default" ]; then
			echo "Error: Invalid memory mode \"$2\""
			showhelp
			exit 1
		fi
		memmode="$2"
		shift; shift;;
		
	-g|--gateware)
		# Obtain which gateware type we want to keep for flash
		if [ "$2" = "18p" ] || [ "$2" = "8p" ]; then
			gateware="$2*.bin";
		else
			echo "Error: Invalid gateware selection \"$2\""
			showhelp
			exit 1
		fi
		shift; shift;;

	/* ) DEV="-s $1"; shift ;;

	-m1|--mac1|-m2|--mac2)
		echo "Error: can't change mac1 and mac2 any more. See docs" >& 2
		shift; shift;;

	-[ecs])
		# e == erase, c == check, s == scrub
		FLAGS="${FLAGS} $1"; shift;;

	* ) echo "$0: Invalid argument \"$1\"" >&2; exit 1;;
    esac
done

if [ "x$usrtar" = "x" ]; then
    showhelp
fi


# Check that there is a tftpboot place with the right thing...
tartftp=wrs-firmware.tar
tarsum=$(md5sum < $tarball)
for n in /tftpboot /home/tftpboot $HOME/tftpboot $HOME/[wW][rR]/tftpboot; do
    if [ ! -d $n ]; then continue; fi
    if [ ! -f $n/$tartftp ]; then continue; fi
    sum2=$(md5sum < $n/$tartftp)
    if [ "$tarsum" != "$sum2" ]; then
	echo "Warning: File $n/$tartftp not up to date";
	echo "Maybe you want to run the following command:"
	echo ""
	echo "  cp $tarball $n/$tartftp"
	echo ""
	echo "Press enter to continue"
	read a
    fi
done

# Even if not all files are always needed, check all of them immediately
me=$(basename $0)
echo "${me}: Working in $WRSTMPDIR"
checkExit "AT91Bootstrap IPL"           $at91bs
checkExit "BareBox boot loader"         $barebox
checkExit "Linux kernel"                $kernel
checkExit "initial RAM disk"            $rootfsgz
checkExit "archive for /usr filesystem" $usrtar


## MAC1 and MAC2 are really recommended
if [ "x$MAC1" = "x$MAC1_DEF" ]; then
    echo "Warning: you did not set the MAC1 value; using \"$MAC1_DEF\""
fi
if [ "x$MAC2" = "x$MAC2_DEF" ]; then
    echo "Warning: you did not set the MAC2 value; using \"$MAC2_DEF\""
fi

## Selecting the running memmode
df=false; nf=false; ddr=false
if [ "x$memmode" = "xdf" ]; then
	df=true
elif [ "x$memmode" = "xnf" ]; then
	nf=true
elif [ "x$memmode" = "xddr" ]; then
	ddr=true
else
	df=true
	nf=true
fi

# Check if atmel sam-ba is found by lsusb
if lsusb | grep -q "at91sam" || $fake; then
	true;
else
	echo ""
	echo "$me: Waiting for at91sam SAMBA bootloader on usb."
	echo "    Please check the Management USB cable is connected "
	echo "    and keep pressed the Flash button while" 
	echo "    resetting/powering the switch."
	while true; do
		if lsusb | grep -q "at91sam"; then
			break
		fi
		sleep 1
		echo -n "."
	done
	echo " Ok"
fi

# Remove the jumper now, before proceeding
if $fake; then
    echo "$me: fake operations, let's continue withouth a WR switch;"
else
    echo "$me: I'm talking with the switch;"
fi
echo -n "   please release the flash button and press Enter to start flashing: "
read unused

## Flashing DataFlash: at91bootstrap at 0, then barebox at 0x8400 (33792)
if $df; then
	${FLASHER} -m df $FLAGS $DEV ${at91bs} 0 ${barebox} 33792
fi

## Prepare for the NAND flashing procedure (kernel, initramfs, /usr)
if $nf; then

	# A this poinit, we used to create a special filesystem but that
	# step is not needed any more: the standard initramfs works for
	# installation too.

	# So, the only things that remains is setting up the magic string
	# before the initramfs itself:
	MAGICSTR=$WRSTMPDIR/magicstr
	echo -n paperino > $MAGICSTR

	# Also, we don't erase nand: the initramfs does it at install time
	#$FLASHER -e -m nand

	# Start nand flashing procedure
	$FLASHER -m ddr $FLAGS $DEV \
	    ${barebox}   0x0000000 \
	    ${kernel}    0x1000000 \
	    ${MAGICSTR}  0x17FFFF8 \
	    ${initramfs} 0x1800000

	if $remove_temps; then
	    rm -rf $WRSTMPDIR
	else
	    echo "Keeping temporary directory: ${WRSTMPDIR}"
	fi

	# Now, flashing proceeds by booting a kernel, get its messages

	# Wait for the device to disappear
	while [ -e /dev/ttyACM0 ]; do sleep 0.1; done
	# Wait for the device to appear again
	while [ ! -e /dev/ttyACM0 ]; do sleep 0.1; done
	# Report install messages until the device disappears again
	cat /dev/ttyACM0

fi

## Loading in DDR. This is used to boot without booting (i.e. no at91boot)
if $ddr; then

	# barebox would be enough, but place kernel and initramfs too. it costs nothing
	$FLASHER -m ddr $FLAGS $DEV \
	    ${barebox}   0x0000000 \
	    ${kernel}    0x1000000 \
	    ${initramfs} 0x1800000

	# It looks like this does it all. We are done

	if $remove_temps; then
	    rm -rf $WRSTMPDIR
	else
	    echo "Keeping temporary directory: ${WRSTMPDIR}"
	fi



fi

echo -e "\n\nDone\n"
