#!/bin/sh

# bootmenu script for selecting system root partition
# and for configuring some other basic things like network
# Copyright (C) 2004 Nokia
# author: Henrik Saari <henrik.saari@nokia.com>

# defaults

FS_MODULES="mbcache ext2 jbd ext3"
MODULE_PATH=/lib/modules/current
dsm_enable=1

tss_testserver=/usr/bin/testserver

if [ -e /etc/initfs.config ]; then
	. /initfs.config
fi

text2screen -c
text2screen -s 2 -H center -y 20 -T 0 -t "Press and hold MENU key for advanced boot menu"

init_system()
{
	mount -t proc none /proc
	mount -t sysfs none /sys
	mount -t tmpfs none -o size=512K /tmp
	
	mkdir /tmp/dev
	# FIXME check for grep's return value before mknod
	if [ ! -e /tmp/dev/retu ]; then
		mknod /tmp/dev/retu c 10 `grep retu /proc/misc | cut -d " " -f 2`
	fi
	if [ ! -e /tmp/dev/tahvo ]; then
		mknod /tmp/dev/tahvo c 10 `grep tahvo /proc/misc | cut -d " " -f 2`
	fi
}

set_default_root_params() {
	root_dev=mtdblock4
	root_dev_name="Flash"
	root_fstype="jffs2"
	root_fsoptions="rpsize=1024,rpuid=0,rpuid=30000"
}

check_partitions()
{
	grep mtdblock4 /proc/partitions >/dev/null
	if [ $? = 0 ] ; then 
		mtd_found=1
	else
		mtd_found=0
	fi

	grep sda1 /proc/partitions >/dev/null
	if [ $? = 0 ] ; then
		sda_found=1
	else
		sda_found=0
	fi

	grep mmc /proc/partitions >/dev/null
	if [ $? = 0 ] ; then
		mmc_found=1
	else
		mmc_found=0
	fi
}

search_root_onmmc() {
# if user set up mmc booting, try to find the first mmc device
# which contains /sbin/init, it will be used as root
# also fallback to the mtdblock4 (our flash)

	parts=`awk '{print $4}' /proc/partitions | grep 'mmcblk[0-9][0-9]*p[0-9]'`
	[ -z "$parts" ] && return 1

	for i in $parts; do 
		if mount_device "$i"; then
			if [ -x /mnt/new_root/sbin/init ]; then
				root_dev="$i"
				return 0;
			fi
			umount_device "$i"
		fi
	done
        return 1

}

show_roots()
{
	echo "Choose bootup option:"
	if [ $mtd_found -eq 1 ]; then
		echo "	1) Flash"
	fi
	if [ $mmc_found -eq 1 ]; then
		echo "	2) MMC"
	fi
	if [ $sda_found -eq 1 ]; then
		echo "	3) USB Mass Storage Device"
	fi
	echo "	9) Start a shell"
	echo ""
}

enter_local_mode()
{
#    	wlan-fw-update mtum
	testserver
}

start_shell()
{
	echo "Starting shell"
	/bin/sh
}

load_wlan_module()
{
	if [ x"$1" = x"mtum" ]; then
	        umac_name=mtum  
		wlan_driver_name=cx3110x_mt
	else
	        umac_name=umac
		wlan_driver_name=cx3110x
	fi
	echo "Loading WLAN module... "
	insmod $MODULE_PATH/${umac_name}.ko
	insmod $MODULE_PATH/${wlan_driver_name}.ko
	echo "Pushing the WLAN tuned values"
	/usr/bin/wlan-cal
}

show_rd_versions()
{
        text2screen -c
        bg_color=0xffff
        y=0
        x=0
        line_height=20

	text2screen -c -x 0 -y 0 -w 800 -h 160
        text2screen -t "Kernel version:" -s 2 -x $x -y $y -B $bg_color
        y=$(expr $y + $line_height)
        text2screen -t "  `uname -r` " -s 2 -x $x -y $y -B $bg_color
        y=$(expr $y + $line_height)
        text2screen -t "  `uname -v`" -s 2 -x $x -y $y -B $bg_color

        y=$(expr $y + $line_height + $line_height)
        text2screen -t "initfs version:" -s 2 -x $x -y $y -B $bg_color
        y=$(expr $y + $line_height)
        text2screen -t "  `cat /etc/initfs_version`" -x $x -y $y -s 2 -B $bg_color

	y=340
	text2screen -c -y 320 -x 0 -w 320 -h 120
        text2screen -t "Component versions:" -x $x -y $y -s 2 -B $bg_color
        y=$(expr $y + $line_height)
        while read line ; do
                text2screen -t "  $line" -x $x -y $y -s 2 -B $bg_color
                y=$(expr $y + $line_height)
        done < /proc/component_version
}

load_mmc_modules()
{
	for mod in $FS_MODULES ; do
		if [ -f $MODULE_PATH/$mod.ko ]; then
			insmod $MODULE_PATH/$mod.ko
		fi
	done
}


push_bdaddr()
{
	echo "Pushing the BT address" 
	/usr/bin/bt-cal $dsme_state
}

show_actdead_image()
{
	bootreason=`cat /proc/bootreason`
	if [ x"$bootreason" = x"charger" ]; then
		echo "Showing the 'charger connected' image"
		/usr/bin/fb-chaimage -l /usr/share/images/qgn_indi_charger_connection_detected -c -p ffffff -s 15 &
	fi
}

enter_test_state()
{
    	echo -n "Bringing WLAN interface up... "
        ifconfig wlan0 up
        echo "done."
        echo "Starting test server..."
        $tss_testserver
        # in case of testserver failure, we start shell
        start_shell
        return 1
}

enter_state()
{
	echo "Entering state '$dsme_state'."
	case $dsme_state in 
	    BOOT)
		/usr/bin/show_image -i /usr/share/images/logo-nokia -n
	    	echo "No test state today, waiting for rootfs..."
		return 0
		;;
	    USER)
	    	/usr/bin/show_image -i /usr/share/images/logo-nokia -n
		push_bdaddr
		def_runlevel=2
		return 0
		;;
	    ACTDEAD)
		push_bdaddr
		def_runlevel=5
		show_actdead_image
		return 0
		;;
	    TEST)
		text2screen -t "TEST" -H center -y 360 -s 6 -B 0xffff
		load_wlan_module
		push_bdaddr
		enter_test_state
		#enter_local_mode
		return 1
		;;
	    LOCAL)
		text2screen -t "LOCAL" -H center -y 360 -s 6 -B 0xffff
		load_wlan_module mtum
		push_bdaddr
		enter_test_state
		#enter_local_mode
		return 1
		;;
	    SHUTDOWN)
		echo "Powering off"
		sync
		poweroff
		return 1
		;;
	    *)
		if [ $rd_mode -ne 0 ]; then
                       start_shell
                       return 1
               fi
               echo "Houston, we have a problem, powering off..."
               sync
               poweroff
	       return 1
	       ;;
	esac
}

enable_coredumps()
{
	coredir=/media/mmc1/core-dumps
	echo -n "Enabling core dumps to $coredir/..."
	echo "$coredir/%e-%s-%p.core" > /proc/sys/kernel/core_pattern
	ulimit -c unlimited
	echo "done."
}

enable_powersave()
{
	if [ -f /sys/devices/system/timer/timer0/dyn_tick ]; then
	    echo 1 > /sys/devices/system/timer/timer0/dyn_tick
	fi
	
	if [ -f  /sys/power/sleep_while_idle ]; then
	    echo 1 > /sys/power/sleep_while_idle
	fi
}

start_dsm()
{
    	enable_coredumps

	echo -n "Starting DSME... "
	dsme -d -l syslog -v 4 -p /usr/lib/dsme/libstartup.so
	echo "done."

	/usr/sbin/waitfordsme
	if [ $? -ne 0 ]; then
		dsme_state=MALF
		return
	fi

	/usr/sbin/dsmetool -r "/usr/bin/bme"

	dsme_state=`/usr/sbin/bootstate`
	if [ $? -ne 0 ]; then
		dsme_state=MALF
	fi
}

mount_device() {
	root_dev="$1"

	[ -z "$root_dev" ] && return 1

	if [ -z $root_fstype ]; then
		if [ -z $root_fsoptions ]; then
			time mount /dev/$root_dev /mnt/new_root
		else
			time mount -o $root_fsoptions /dev/$root_dev /mnt/new_root
		fi
	else
		if [ -z $root_fsoptions ]; then
			time mount -t $root_fstype /dev/$root_dev /mnt/new_root
	    	else
			time mount -t $root_fstype -o $root_fsoptions /dev/$root_dev /mnt/new_root
		fi
	fi
	grep -q new_root /proc/mounts
}

umount_device() {
	 grep -q "$1"  /proc/mounts  && umount /dev/$1
}

boot()
{
        load_wlan_module
	if ! grep -q new_root /proc/mounts; then
		mount_device "$root_dev"
	fi
	if [ $? -ne 0 ]; then
		return 1
	fi
	/usr/sbin/dsmetool --root-mounted
	dsme_state=`/usr/sbin/bootstate`
	if [ $? -ne 0 ]; then
		dsme_state=MALF
	fi
	enter_state
	if [ ! -x /mnt/new_root/sbin/init ]; then
		echo "/sbin/init not found on /dev/$root_dev"
		umount /mnt/new_root
		return 1
	fi
	cd /mnt/new_root
	if [ ! -d mnt/initfs ]; then
		mkdir -p mnt/initfs
	fi
	if [ ! -L /mnt/new_root/var/run ]; then
		rm -rf /mnt/new_root/var/run
		ln -sf /tmp/.run /mnt/new_root/var/run
	fi
	mkdir -p /tmp/.run
	mount -obind /tmp /mnt/new_root/tmp
	pivot_root . mnt/initfs
	# have correct release information inside core dumps
	export OSSO_VERSION=$(cat /etc/osso_software_version)
	echo "Starting init"
	exec /usr/sbin/chroot . /sbin/init $def_runlevel <dev/console >dev/console 2>&1
}

init_system

if [ $dsm_enable -eq 1 ]; then
	start_dsm
	if [ $? -ne 0 ]; then
		return 1
	fi
else
	def_runlevel=
fi

rd_mode=$(cal-tool --get-rd-mode 2> /dev/null)
if [ "$rd_mode" = "enabled" ]; then
	rd_mode=1
	echo "R&D mode enabled"
	show_rd_versions
else
	rd_mode=0
fi

enter_state
enable_powersave

# We are in USER state now
want_menu=0
if [ $rd_mode -ne 0 ]; then
        echo
        echo "Press any key for interactive startup"
        key_pressed 1
        if [ $? -ne 0 ]; then
                want_menu=1
        fi
fi

if [ $want_menu -ne 1 ]; then
	default_root=$(cal-tool --get-root-device 2> /dev/null)
        set_default_root_params
        #now check HW key state
        HWKEYSTATE=$(evkey -s /dev/input/event2)
        # if Escape was not pressed, execute advanced menu script
        if [ "$HWKEYSTATE" != "1" ] ; then
		[ -f /bootmenu.sh ] && . /bootmenu.sh
	fi
	case "$default_root" in
	mmc)
		load_mmc_modules
		if search_root_onmmc; then
			root_dev_name="MMC"
			root_dev_set=1
			root_fstype=""
			root_fsoptions=""
		else
		    	echo "No mmc root found, try default"
			set_default_root_params
		fi
                ;;
        usb)
                root_dev=sda1
                root_dev_name="USB hard drive"
                root_dev_set=1
                root_fstype=""
                root_fsoptions=""
		;;
#        *)
#               set_default_root_params
#                ;;
        esac
#        wait_for_device
        boot
        #in case it fails
        text2screen -c
        text2screen -s 2 -H center -y 20 -T 0 -t "Boot from $default_root failed, booting from flash ..."
        set_default_root_params
        boot
fi

root="invalid"
while [ true ]; do
	check_partitions
	show_roots
	root_dev_set=0
	read root
	case "$root" in
	    1)
		root_dev=mtdblock4
		root_dev_name="Flash"
		root_dev_set=1
		root_fstype="jffs2"
		root_fsoptions=""
		;;
	    2)
		if search_root_onmmc; then
			root_dev_name="MMC"
			root_dev_set=1
			root_fstype=""
			root_fsoptions=""
		else 
			echo "Could not find suitable partition for root on mmc"
		fi
		;;
	    3)
		root_dev=sda1
		root_dev_name="USB hard drive"
		root_dev_set=1
		root_fstype=""
		root_fsoptions=""
		;;
	    9)
		start_shell
		;;
	    *)
		echo "Invalid selection"
		;;
	esac
	if [ $root_dev_set -eq 1 ]; then
		boot
	fi
done

