#!/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.
#########################################################################


showhelp()
{
	printf "Usage: $0 [options] [<firmware>.tar.gz] [DEV]\n\n"
	printf "MAC:\t MAC address in hexadecimal seperated by ':' (i.e, AB:CD:EF:01:23:45)\n"
	printf "<firmware>.tar.gz: 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), LX130T (small FPGA), LX240T (big FGPA)\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"
	printf "  -m1|--mac1\t Default MAC address for the ethernet port on board\n"
	printf "  -m2|--mac2\t Default base MAC address for the switch ports\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
}

checkMAC()
{
	X="[0-9a-fA-F][0-9a-fA-F]"
	if echo $1 | grep "^[0-9a-fA-F][02468aceACE]:${X}:${X}:${X}:${X}:${X}\$" > /dev/null; then
		return 0
	fi
	return 1
}

modifyMAC()
{
	origin=$1
	new=$2
	cp $origin $new

	echo "Configure the MAC addresses:"
	echo "  MAC1 $MAC1"
	echo "  MAC2 $MAC2"
	# MAC address doesn't need any modification
	if [ $silent ]; then
	    return 1;
	fi
	# Modify MAC address
	sed -i "s/$MAC1_DEF/$MAC1/" $new
	sed -i "s/$MAC2_DEF/$MAC2/" $new
	return 0
}

# 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

# add /usr/sbin for mkfs.jffs2
export PATH="$PATH:/usr/sbin"

# 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 tar.gz file system
rootfsgz=""
# full path to the cpio image
rootfscpio=""
# full path to the jffs2 image
rootfsjffs2=""
# full path to the file system directory
TMPFS=""

TMPDIR=$(mktemp -d /tmp/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
		rootfsgz=${WRS_OUTPUT_DIR}/images/wrs-image.tar.gz
		shift;;

	*.tar.gz)
		checkExit "tar-file" $1
		tar --directory $TMPDIR -xzf $1
		at91bs=$TMPDIR/at91bootstrap.bin;
		barebox=$TMPDIR/barebox.bin
		kernel=$TMPDIR/zImage
		rootfsgz=$TMPDIR/wrs-image.tar.gz
		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";
		elif [ "$2" = "LX240T" ] || [ "$2" = "LX130T" ]; then
			gateware="*-$2.bin";
		else
			echo "Error: Invalid gateware selection \"$2\""
			showhelp
			exit 1
		fi
		shift; shift;;

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

	-m1|--mac1)
		MAC1="$2"
		checkMAC $MAC1
		if [ $? -eq 1 ];then
			echo "Error: MAC address 1 invalid ($MAC1)"
			exit 1
		fi
		shift; shift;;

	-m2|--mac2)
		MAC2="$2"
		checkMAC $MAC2
		if [ $? -eq 1 ];then
			echo "Error: MAC address 2 invalid ($MAC2)"
			exit 1
		fi
		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$rootfsgz" = "x" ]; then
    showhelp
fi

# Even if not all files are always needed, check all of them immediately
me=$(basename $0)
echo "${me}: Working in $TMPDIR"
checkExit barebox $barebox
checkExit at91bootstrap $at91bs
checkExit kernel $kernel
checkExit root-filesystem $rootfsgz


## 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
if [ "x$memmode" = "xdf" ]; then
	df=1
elif [ "x$memmode" = "xnf" ]; then
	nf=1
elif [ "x$memmode" = "xddr" ]; then
	test=1
else
	df=1
	nf=1
fi

# Check if atmel sam-ba is found by lsusb
if lsusb | grep -q "at91sam"; then
	true;
else
	echo ""
	echo "$me: Waiting for at91sam SAMBA bootloader on usb."
	echo "    Please check the Managment 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
echo "$me: I'm talking with the switch;"
echo -n "   please release the flash button and press Enter to start flashing: "
read unused

# Create a temporary barebox binary with modified MAC addresses
Tbarebox=$TMPDIR/bb.new
modifyMAC ${barebox} ${Tbarebox}


## Flashing DataFlash
if [ $df ]; then
	${FLASHER} -m df $FLAGS $DEV ${at91bs} 0 ${Tbarebox} 33792
fi

## Prepare for the NAND flashing procedure
if [ $nf ]; then

	TMPFS=$TMPDIR/wrsfs-tgz; mkdir $TMPFS
	rootfsjffs2=$TMPDIR/wrs-image.jffs2

	# The TMPCPIO is used for the NAND flashing procedure. It
	# contains the magic string "paperino" (0x61706570 0x69726f6e)
	# in the first 8bytes and in the following byte the whole
	# file system. Barebox use this magic string to identify
	# the flashing procedure.
	TMPCPIO=$TMPDIR/wrsflash.cpio.gz

	# make flashing cpio from the unzipped file system
	TMPSCRIPT=$TMPDIR/wrsrootfs-script
	cat > $TMPSCRIPT << EOF
tar --directory $TMPFS -xzf $rootfsgz
# Remove the unnecessary HDL files, by default we keep 18 ports HDL for both FPGA type
# (There is not enough place in DDR to extract 4 HDLs, be carefull if you add custom files)
find $TMPFS/wr/lib/firmware/ -type f \( ! -name ''${gateware}'' \) -a \( ! -name '*rt_cpu.bin' \) -exec rm -f {} \;

mkfs.jffs2 --little-endian --eraseblock=0x20000 -n --pad -d $TMPFS -o $rootfsjffs2

# Remove heavy and useless stuff to make a light file system to
# load in RAM
rm -rf $TMPFS/etc/init.d/S*
rm -rf $TMPFS/wr
rm -rf $TMPFS/usr/bin
rm -rf $TMPFS/usr/lib
rm -rf $TMPFS/usr/share

mkdir $TMPFS/flashing/
cp -a /dev/kmsg $TMPFS/dev/kmsg
cp ${rootfsjffs2} $TMPFS/flashing/wrs-image.jffs2.img
cp ${kernel} $TMPFS/flashing/zImage
cp ${WRS_BASE_DIR}/usb-loader/S99flash-from-kernel.sh $TMPFS/etc/init.d/
cd ..
echo -n "paperino" > $TMPCPIO
(cd "$TMPFS" && find . | cpio -o -H newc | gzip) >> $TMPCPIO
EOF
	fakeroot bash $TMPSCRIPT
	rm $TMPSCRIPT

	# Erase all nand memory
	$FLASHER -e -m nand
	# Start nand flashing procedure
	$FLASHER -m ddr $FLAGS $DEV ${Tbarebox} 0x0 ${kernel} 0x1000000 ${TMPCPIO} 0x1FFFFF8

	rm -rf $TMPFS
	rm -rf $TMPCPIO
	rm -rf $rootfsjffs2
fi

## Loading in DDR
if [ $test ]; then

	TMPFS=$(mktemp -d /tmp/wrsfs-tgz.XXXXXX)
	rootfsjffs2=/tmp/wrs-image.jffs2.img
	# make cpio and jffs2 image
	TMPSCRIPT=$(mktemp /tmp/wrsrootfs-script.XXXXXX)
	cat > $TMPSCRIPT << EOF
tar --directory $TMPFS -xzf $rootfsgz
mkfs.jffs2 --little-endian --eraseblock=0x20000 -n --pad -d $TMPFS -o $rootfsjffs2
EOF
	fakeroot bash $TMPSCRIPT
	rm $TMPSCRIPT
	rm $TMPFS

	$FLASHER -m ddr $FLAGS $DEV ${Tbarebox} 0x0 ${kernel} 0x1000000 ${rootfsjffs2} 0x2000000
fi

rm $Tbarebox
echo -e "\n\nDone\n"
