#!/bin/sh
#
# Experimental kernel flasher for Nokia 770, N800 and N810
#
# Copyright (c) 2006, 2007, 2008 Frantisek Dufka
#

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

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


if [ $# -lt 1 ] ; then
    echo "usage: $0 zImage"
    exit 0
fi

if [ ! -f $1 ] ; then
    echo "file $1 not found"
    exit 0
fi

hexdump(){
# file offset size
    $BASEDIR/xxd -u -ps -s $2 -l $3 $1
}

hexlong(){
#byteswap little-endian long value
    val=$(hexdump $1 $2 $3)
    for i in 7 5 3 1 ; do 
	echo -n $(expr substr $val $i 2)
    done
}

dec2hex(){
    printf "%08X" $1
}

hex2dec(){
    val=0x$1
    echo -n $((val))
}

check_file_value(){
[ "$(hexlong $1 $2 $3)" = "$4" ]
}

BASEDIR=`dirname $0`
kernel=$1
TMPFILE=kernel-$$

echo "Checking kernel image $kernel ..."
#compute image size
ok=1
check_file_value $kernel 0 4 E1A00000 || ok=0
[ $ok = 1 ] && check_file_value $kernel 28 4 E1A00000 || ok=0
if [ $ok = 0 ] ; then
	echo "This is not a valid kernel image, cowardly exiting."
	exit 0
fi
origsize=`cat $kernel | wc -c`
isizehex=$(hexlong $kernel 44 4) #real kernel size stored inside kernel image
isize=$(hex2dec $isizehex)
#pad kernel image size up to multiple of 128 (Nokia flasher does this, why ?)
ksize=$isize
[ $((ksize%128)) -gt 0 ] && ksize=$((ksize-ksize%128+128))
#we need this in hex for NOLO header
ksizehex=$(dec2hex $ksize)

echo "File size $origsize (0x`dec2hex $origsize`)"
echo "Expected kernel size $isize (0x$isizehex), padded to $ksize (0x$ksizehex)"

if [ "$origsize" != "$isize" ]  ; then
#	echo "Expected kernel size does not match real file size !!"
	if [ "$origsize" -lt "$isize" ] ; then
	    echo "Incomplete file, cowardly exiting."
	    exit 0
	else
	    #complain only if not already padded (extracted from FIASCO image?)
	    if [ "$origsize" != "$ksize" ] ; then
		echo "Extra trailing garbage ignored."
	    else
		echo "Image already padded (probably extracted from firmware)."
	    fi
	fi
fi

#prepare NOLO header
echo -n "NOLO img" >$TMPFILE
for i in 7 5 3 1 ; do
printf >>$TMPFILE "\x$(expr substr $ksizehex $i 2)"
done
dd 2>/dev/null >>$TMPFILE if=/dev/zero bs=1 count=2036

if [ `cat $TMPFILE | wc -c` != 2048 ] ; then
    echo "failed to write NOLO header, exiting"
    rm $TMPFILE
    exit 0
fi
cat >>$TMPFILE $kernel
if [ `cat $TMPFILE | wc -c` != $((2048+origsize)) ] ; then
    echo "failed to create NOLO kernel image, exiting"
    rm $TMPFILE
    exit 0
fi

# OK, NOLO kernel image ready 
if ask_yes "Are you ready to flash? (yes/no) " ; then
case `grep product /proc/component_version` in
	*SU-18)
	# N770, use kernel hack
	KERNELVERSION=`cut -d ' ' -f 3 /proc/version`
	if [ -f ${BASEDIR}/nand_rw_enable.ko.${KERNELVERSION} ] ; then
	    insmod ${BASEDIR}/nand_rw_enable.ko.${KERNELVERSION}
	    ${BASEDIR}/flash_eraseall /dev/mtd2
	    ${BASEDIR}/nandwrite -a -p /dev/mtd2 $TMPFILE
	    rmmod nand_rw_enable
	    echo "Kernel flashed, reboot to make it active."
	else
	    echo "Sorry currently running kernel unsupported. Catch-22 situation :-)"
	fi
	;;
	*RX-34|*RX-44)
	    ${BASEDIR}/flash_eraseall /dev/mtd2
	    ${BASEDIR}/nandwrite -a -p /dev/mtd2 $TMPFILE
	    echo "Kernel flashed, reboot to make it active."
	;;
	*)
	echo "Unknown device, nothing flashed."
	;;
esac
fi
echo -n "Cleaning up..."
rm $TMPFILE
echo " done."