#!/bin/sh
#
# Open Protium Reflash. This script will take a firmware image consisting
# of a compressed linux kernel image, concatentated with a jffs2 root 
# filesystem image. The kernel MTD device is discovered by locating
# the MTD partition with the tag "kernel" and the filesystem MTD device
# is dicovered by locating the MTD partition with the tag "filesystem."
# There is no TOC inside the firmware images so there is no direct way 
# to validate that the sizes of the parts in the firmware match the 
# existing MTD partitions. So there could be a mismatch. However, a
# a mismatch size will be detect as this script mounts the newly laid
# done filesystem, a mismatch guarantees this to fail. That being said
# the script does validate the total size to prevent overwriting 
# uboot. Furthermore the script makes sure the fsdev is not in use and
# that the various images are block aligned.

flimg=$1
if [ -z "$flimg" ]; then
	echo "Usage: reflash <image file>"
	exit 1
fi

if [ \! -f $flimg -o \! -r $flimg ]; then
	#
	# not a file or not readable
	#
	echo "error: Image file [$flimg] not available"
	exit 1
fi

dmesg | grep StorCenter >/dev/null 2>&1
if [ $? -ne 0 ]; then
	exit 0
fi

blksize=512
mtd=/proc/mtd
mtab=/proc/mounts
mntdir=/tmp/fs.$$

ktag=kernel
fstag=filesystem

kdev=` grep  $ktag $mtd | awk -F: '{print $1}' | sed -e 's?mtd?/dev/mtdblock/?g'`
fsdev=`grep $fstag $mtd | awk -F: '{print $1}' | sed -e 's?mtd?/dev/mtdblock/?g'`

flsize=`ls -l $flimg     | awk '{print $5}'`
ksize=`grep   $ktag $mtd | awk '{print "0x" $2}'`
fssize=`grep $fstag $mtd | awk '{print "0x" $2}'`

#
# Size comes out of dc in exp notation and test wont accept a hex number
# so dumo it in hex then use awk to convert to decimal
#
size=0x`dc 16  o $ksize $fssize + p`
size=`echo $size | awk '{printf ("%d",$1)}'`

#
# Make sure we are block aligned
#
kblks=`dc $ksize $blksize / p`
r=`dc $ksize $blksize % p`
if [ $r -ne 0 ]; then 
	echo "error: Kernel partition is not block aligned."
	exit 1
fi

#
# Make sure we are block aligned
#
fsblks=`dc $fssize $blksize / p`
r=`dc $fssize $blksize % p`
if [ $r -ne 0 ]; then 
	echo "error: Filesystem partition is not block aligned."
	exit 1
fi

#
# Check to see that we have enough room
#
if [ $flsize -gt $size ]; then
	echo "error: Image size is bigger then available space."
	exit 1
fi

#
# Is fsdev mounted?
#
grep $fsdev $mtab > /dev/null 2>&1
if [ $? -eq 0 ]; then
	echo "error: $fsdev mounted"
	exit 1
fi

#
# If root is a jffs2 then close enough, im out
#
grep jffs2 $mtab > /dev/null 2>&1
if [ $? -eq 0 ]; then
	echo "error: $fsdev may be mounted"
	exit 1
fi


#
# Mount fsdev and save fsdev/linuxrc
#
mkdir $mntdir /tmp/$$
mount -t jffs2 $fsdev $mntdir
if [ $? -ne 0 ]; then
	echo "error: Unable to mount $fsdev"
	exit 1
fi
echo "Preserving /linuxrc in /tmp/$$"
cp $mntdir/linuxrc* /tmp/$$
umount $mntdir

echo "Image:"
echo "	Name  : $flimg"
echo "	Length: $flsize"
echo
echo "Kernel:"
echo "	Device: $kdev"
echo "	Length: $ksize"
echo "	Blocks: $kblks"
echo 
echo "Filesystem:"
echo "	Device: $fsdev"
echo "	Length: $fssize"
echo "	Blocks: $fsblks"
echo
echo 'Ready to flash, Continue? (yes/no)'
read continue
if [ "z$continue" != "zyes" ]; then
	rm -rf $mntdir /tmp/$$
	exit 0
fi

#
# Lets do the flash
#
echo Preserving existing flash in: $flimg.sav.$$ 
dd of=$flimg.sav.$$ if=$kdev  bs=$blksize count=$kblks
dd of=$flimg.sav.$$ if=$fsdev bs=$blksize count=$fsblks seek=$kblks

echo Flashing new firmware....
dd if=$flimg of=$kdev  bs=$blksize count=$kblks
dd if=$flimg of=$fsdev bs=$blksize count=$fsblks skip=$kblks
sync
sleep 5 

#
# Mount fsdev and restore fsdev/linuxrc
#
mount -t jffs2 $fsdev $mntdir
if [ $? -ne 0 ]; then
	echo "error: Unable to re-mount $fsdev"
	exit 1
fi
echo "Restoring /linuxrc"
cp /tmp/$$/linuxrc* $mntdir
umount $mntdir
rm -rf $mntdir /tmp/$$