#!/bin/sh
# use gainroot to become root and relaunch itself
if [ `id -u` != 0 ] ; then
#if not already root, call itself as root
TTY=`tty`
[ "$TTY" = "not a tty" ] && unset TTY
exec sudo gainroot <<EOF
if [ -z "$TTY" ] ; then exec $0 $* ; else exec <$TTY $0 $* ; fi
EOF
exit $?
fi
# real script follows

INITFS_IMAGE_STORAGE=/var/tmp
TOOLS_LOCATION=/usr/sbin
FILES_LOCATION=/usr/lib/bootmenu
BOOTMENU_LOCATION=/etc

OLDDIR=`pwd`
cd `dirname $0`
MYDIR=`pwd`

case $MYDIR in
    /media/mm*)
	echo "Cannot run from FAT formatted card, real UNIX filesystem is needed."
	echo "Please extract archive directly to internal flash and run from there."
	exit 0
	;;
esac

INITFS_IMAGE=$INITFS_IMAGE_STORAGE/initfs.bootmenu.jffs2
INITFS_MAX_SIZE=$((0x0`grep initfs /proc/mtd | cut -d ' ' -f 2`))

ask_no(){
ans=
while [ "$ans" = "" ] ; do
    echo -n "$*"
    read ans
done
case $ans in
    y*|Y*)
	return 1
	;;
    *)
	return 0
	;;
esac
}
ask_yes(){
ask_no "$*" && return 1
return 0
}


initfs_create_backup(){
#echo " *** copying current initfs ..."
##mkdir -p initfs
##rsync -aHx --delete /mnt/initfs/ initfs/
rm -rf $INITFS_IMAGE_STORAGE/initfs
mkdir -p $INITFS_IMAGE_STORAGE/initfs
mount -t jffs2 -o ro /dev/mtdblock3 $INITFS_IMAGE_STORAGE/initfs
echo " *** creating $1 ..."
$TOOLS_LOCATION/mkfs.jffs2 -r $INITFS_IMAGE_STORAGE/initfs -o $1 -e 128 -l -n
umount $INITFS_IMAGE_STORAGE/initfs
rm -rf $INITFS_IMAGE_STORAGE/initfs		
}

initfs_create(){
echo -n " *** copying current initfs ..."
#mkdir -p initfs
#rsync -aHx --delete /mnt/initfs/ initfs/
mkdir -p $INITFS_IMAGE_STORAGE/mnt
mount -t jffs2 -o ro /dev/mtdblock3 $INITFS_IMAGE_STORAGE/mnt
cp -a $INITFS_IMAGE_STORAGE/mnt $INITFS_IMAGE_STORAGE/initfs
umount $INITFS_IMAGE_STORAGE/mnt
rmdir $INITFS_IMAGE_STORAGE/mnt
echo " done."

echo "If you remove extra stuff you may write to initfs and customize bootmenu."
if ask_yes "Remove unneeded extra (and factory testing) stuff? (yes/no) : " ; then
	echo " *** removing extra stuff ..."
	for i in `cat $FILES_LOCATION/to_remove.lst` ; do rm -rf $INITFS_IMAGE_STORAGE/initfs/$i ; done
fi

INITFSVERSION=`cut -d ' ' -f 1,2 $INITFS_IMAGE_STORAGE/initfs/etc/initfs_version  | tr ' ' '.'`
if [ -f $FILES_LOCATION/initfs.${INITFSVERSION}.tgz ] ; then
    echo " *** extracting boot menu files for initfs version ${INITFSVERSION} ..."
    tar zxvf $FILES_LOCATION/initfs.${INITFSVERSION}.tgz -C $INITFS_IMAGE_STORAGE/initfs
    mknod -m660 $INITFS_IMAGE_STORAGE/initfs/dev/loop0 b 7 0
    mknod -m660 $INITFS_IMAGE_STORAGE/initfs/dev/loop b 7 0
            
    if [ -f $FILES_LOCATION/bootmenu.sh ] ; then
    	echo " *** copying bootmenu.sh"
	cp $FILES_LOCATION/bootmenu.sh $INITFS_IMAGE_STORAGE/initfs/
	chown root:root $INITFS_IMAGE_STORAGE/initfs/bootmenu.sh
    fi
    #telnetd
    if [ -f $FILES_LOCATION/utelnetd.${INITFSVERSION}.tgz ] ; then
	if ask_yes "install telnet server for network recovery? (yes/no) " ; then
		tar zxvf $FILES_LOCATION/utelnetd.${INITFSVERSION}.tgz -C $INITFS_IMAGE_STORAGE/initfs
		echo " *** OK, utelnetd added"
	else
		echo " *** OK, utelnetd skipped"
	fi	   
	
    fi
    #dropbear
    if [ -f $FILES_LOCATION/dropbear.${INITFSVERSION}.tgz ] ; then
	if ask_yes "install dropbear ssh server for advanced network recovery? (yes/no) " ; then
		tar zxvf $FILES_LOCATION/dropbear.${INITFSVERSION}.tgz -C $INITFS_IMAGE_STORAGE/initfs
		echo " *** OK, dropbear added"
		if [ -f /etc/dropbear/dropbear_rsa_host_key ] ; then
		echo " *** dropbear found in rootfs, copying server keys to initfs"
		mkdir -p $INITFS_IMAGE_STORAGE/initfs/etc/dropbear
		cp -a /etc/dropbear/dropbear_*_key $INITFS_IMAGE_STORAGE/initfs/etc/dropbear/
		else
		echo " *** no dropbear in rootfs, server keys will be generated on each boot"
		fi
	else
		echo " *** OK, dropbear skipped"
	fi	   
	
    fi
	# remove previous bootmenu.conf
	[ -f $INITFS_IMAGE_STORAGE/initfs/etc/bootmenu.conf ] && rm $INITFS_IMAGE_STORAGE/initfs/etc/bootmenu.conf
    echo " *** searching for optional bootmenu.conf in /etc ..."
    if [ -f $BOOTMENU_LOCATION/bootmenu.conf ] ; then
	if ask_yes "$BOOTMENU_LOCATION/bootmenu.conf found, do you want to add it to initfs? (yes/no) " ; then
	    	mkdir -p $INITFS_IMAGE_STORAGE/initfs/etc
		cp $BOOTMENU_LOCATION/bootmenu.conf $INITFS_IMAGE_STORAGE/initfs/etc/
		echo " *** OK, bootmenu.conf added"
		echo " *** updating /etc/bootmenu.d .."
    		rm -rf $INITFS_IMAGE_STORAGE/initfs/etc/bootmenu.d
	    	mkdir -p $INITFS_IMAGE_STORAGE/initfs/etc/bootmenu.d
    		cp -r /etc/bootmenu.d/*.item $INITFS_IMAGE_STORAGE/initfs/etc/bootmenu.d
	else
		echo " *** OK, bootmenu.conf ignored"
	fi	   
    else
    	echo " *** not found, no problem"
    fi
    echo " *** creating $1 ..."
    $TOOLS_LOCATION/mkfs.jffs2 -r $INITFS_IMAGE_STORAGE/initfs -o $1 -e 128 -l -n
else
    echo " !!! unknown initfs version ${INITFSVERSION}, cannot install bootmenu"
fi
rm -rf $INITFS_IMAGE_STORAGE/initfs		
}

initfs_flash(){
sync
echo -n " *** remounting initfs read only ... "
#mount -o remount,ro /dev/mtdblock3 /mnt/initfs || return 1
#workaround buggy bysybox mount in N800, the line above fails
#we can also use mount inside initfs
chroot /mnt/initfs mount -t jffs2 -o remount,ro /dev/mtdblock3 /
#ignore mount return code and check if initfs is now mounted ro
INITFSMODE=`grep '/mnt/initfs jffs2' /proc/mounts | cut -d ' ' -f 4`
if [ ! "$INITFSMODE" = "ro" ] ; then
	echo "failed, flashing skipped"
	return 1
else
	echo "OK"
fi
sync
echo " *** caching old initfs to memory (for crash prevention)"
# block level, probably useless
dd if=/dev/mtdblock3 of=/dev/null bs=65536 2>/dev/null
# file level, read all interesting stuff (should be enough to cache dsme and bme)
tar cf - /mnt/initfs/usr /mnt/initfs/lib /mnt/initfs/bin /mnt/initfs/sbin >/dev/null 2>/dev/null
echo " *** erasing initfs partition (/dev/mtd3) ..."
$TOOLS_LOCATION/flash_eraseall -j /dev/mtd3
echo " *** flashing $1 image ..."
$TOOLS_LOCATION/nandwrite -a -p /dev/mtd3 $1
echo " *** done"
return 0
}

renameprevious(){
FROM=$1
if [ -f $FROM ] ; then
    TO=${FROM}.`ls -l $FROM | awk ' { print $6$7$8 }' | tr -d '.:-'`
    echo "Previous $FROM detected, renamed to $TO"
    mv $FROM $TO
fi
}

wizard(){

echo ""
echo " === Flasher for initfs with onscreen bootmenu ==="
echo ""
echo "For safe flashing please do the following:"
echo ""
echo "- close all aplications (to free available RAM and prevent system crash)"
echo "- disconnect from wi-fi network (to prevent random system crash with N770)"
echo "- make sure you have at least 5MB free disk space in flasher directory"
echo "- make sure you know how to reflash device in usual way if this fails"
echo ""

if ask_no "Are you sure to continue? (yes/no) : " ; then
    echo "OK, see you later :-)"
    exit 0
fi

if ask_yes "Create backup of current initfs (yes/no) : " ; then
    renameprevious /var/backups/initfs/initfs.orig.jffs2
    initfs_create_backup /var/backups/initfs/initfs.orig.jffs2
    ls -l /var/backups/initfs/initfs.orig.jffs2
    echo "Press enter to continue"
    read ans
fi

echo "Part 1 - Preparing ${INITFS_IMAGE} image"
renameprevious $INITFS_IMAGE
initfs_create ${INITFS_IMAGE}
if [ -f ${INITFS_IMAGE} ] ; then

ls -l ${INITFS_IMAGE}
imgsize=`ls -l ${INITFS_IMAGE} | awk '{ print $5 }'`
if [ $imgsize -gt ${INITFS_MAX_SIZE} ] ; then
    echo "Oversized image, max size is $INITFS_MAX_SIZE actual is $imgsize"
    echo "Please select different options next time." 
    exit 0
fi
echo ""
if ask_no "Part 2 - Ready for flashing this image? (yes/no) : " ; then
    echo "OK, see you later :-)"
    exit 0
fi

initfs_flash ${INITFS_IMAGE}
echo "Press enter to reboot device (or ctrl+c to quit, not recommended)"
read ans
echo "Rebooting ..."
shutdown -r now
else
echo "Cannot find ${INITFS_IMAGE}, something failed, nothing flashed."
fi
}

#this flashes initfs image directly, usable for backup or prepared image
flasher(){
if ask_no "Ready to flash initfs jffs2 image $1? (yes/no) : " ; then
    echo "OK, see you later :-)"
    exit 0
fi
initfs_flash $OLDDIR/$1
echo "Press enter to reboot device (or ctrl+c to quit, not recommended)"
read ans
shutdown -r now
}


if [ "$#" = "1" -a -f "$OLDDIR/$1" ] ; then
	if [ "`basename $1 .jffs2`.jffs2" != "`basename $1`" ] ; then
	    echo "$1 has no .jffs2 suffix !"
	    echo "Cowardly refusing to brick your device :-)"
	    exit 0
	fi
	flasher "$1"
else
	wizard
fi
