# bspinst_api.sh
#
# Linux BSP installer drawing API for WonderMedia ARM SoC.
#
# Written by Vincent Chen <vincentchen@wondermedia.com.tw>
#
# Copyright 2008-2009 WonderMedia Corporation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY WONDERMEDIA CORPORATION ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL WONDERMEDIA CORPORATION OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.


source ${src_dir}/bin/bspinst_var.sh

# Quiet - do command in silence
# @command
Quiet ()
{
	$@ 2>/dev/null >/dev/null
#	$@

	return $?
}


# wait_install
#
# Wait a few seconds before installation
wait_install ()
{
	t=$1
	while [ $t -gt 0 ]; do
		msg "Installation will begin in $t seconds"
		sleep 1
		let "t = t - 1"
	done
}

# wait_reboot
#
# Wait a few seconds before reboot
wait_reboot ()
{
	t=$1
	while [ $t -gt 0 ]; do
		msg "System will reboot in $t seconds"
		sleep 1
		let "t = t - 1"
	done
}


# host_arch_detect
#
# Detect ARMv4t or ARMv5t
host_arch_detect ()
{
	echo "armv5t"

	return 0
}

os_type ()
{
	if [ ! -e /proc/binder/state ]; then
		echo "Linux"
	else
		echo "Android"
	fi
}

# rpc_test
#
# Test if RPC service is ready
rpc_test ()
{
	local st=

	st=`rpc timer get_status | cut -d\  -f 3`

	if [ "$st" != "off" ] ; then
		return 127
	fi

	return 0
}

# wait_rpc_ready 
#
# Wait until RPC service is ready
wait_rpc_ready ()
{
	local st=
	while [ "$st" != "off" ] ; do
		st=`rpc timer get_status | cut -d\  -f 3`
	done
}

# regular_name - translate @name to reqular expression.
# @name
regular_name ()
{
	local name=$1
	echo -n $name | sed 's/\//\\\//g' | sed 's/\./\\\./g'
}

# base_name - extract filename from whole path name
# @path_name
# @full_name
base_name ()
{
	local path_name=$1
	local full_name=$2

	local reg_path_name=`regular_name $path_name`
	echo -n $full_name | sed "s/$reg_path_name//g"
}

# fsearch - search a file by pattern match
# @from		the searching directory
# @pattern	the file name pattern
# @result	the matched file name found
fsearch ()
{
	local from=$1
	local pattern=
	local result=

	eval "pattern=\$$2"

	if [ -z "$pattern" ]; then
		return 
	fi

	#printf "> Search for firmware ... "

	for i in `find $from -type f -name "$pattern" -follow | sort -r`
	do
		result=$i
		break
	done
	
	if [ ! -e "$result" ]; then
		#printf "Not found (%s) \n" $pattern
		printf "fsearch: file is not found (%s) \n" $pattern
	else
		#printf "Found \n%s\n" $result
		eval "$2=\"$result\""

		if [ $# == 3 ]; then
			eval "$3=\"$result\""
		fi
	fi
}

# fcheck - terminate program if the file doesn't exist
# @file		the name of the target file
fcheck ()
{
	local file=$1

	if [ ! -e "$file" ]; then
		printf "The required file is missing. ($file)\n"
		exit 0;
	fi
}

# get_var - load environment variables 
# @args
get_var ()
{
	for exp in $@; do
		eval $exp
	done
}

# get_mtd - get mtd device by name
# @name
get_mtd ()
{
	desc=`echo $1 | sed 's/\ /\\\ /g'`
	cat /proc/mtd | grep "$desc" | cut -d: -f1 | sed 's/mtd/\/dev\/mtd/g'
}

# get_mtdblock - get mtdblock device by name
# @name
get_mtdblock ()
{
	get_mtd "$1" | sed 's/mtd/mtdblock/g'
}

# get_mtd_len - get mtd length by name
# @name
get_mtd_len ()
{
	tmp=`cat /proc/mtd |grep "$1"|cut -d\  -f 2`
	len=`printf "0x%x" 0x$tmp`

	echo $len
}

# sf_inst - copy from a file onto SPI flash
# @name
# @file
#
# The default search path is the current folder
# if $src_dir is invalid.
sf_inst ()
{
	local name=$1
	local file=$2
	local _src_dir=
	local mtd=

	mtd=`get_mtd "$name"`

	if [ -z "$mtd" ]; then
		echo "[WMT] *E* No MTD partition called $name."
		return 0
	fi

	if [ -z "$src_dir" ]; then
		_src_dir="."
	else
		_src_dir="$src_dir"
	fi

	Quiet fsearch $_src_dir file

	if [ -e "$file" ]; then
		printf "Update %s to %s ... " $file $mtd
		Quiet flash_eraseall $mtd
		if [ -e /usr/sbin/flashcp ]; then
			Quiet flashcp $file $mtd
		else
			cat $file > $mtd
		fi
		printf "done\n"
	else
		echo "[WMT] *E* not found $file, skip update $name."
		msg "*E* file not found $file - skipping $name."
	fi
}

# nand_inst - copy from a file onto SPI flash
# @name
# @file
#
# The default search path is the current folder
# if $src_dir is invalid.
nand_inst ()
{
	local name=$1
	local file=$2
	local _src_dir=
	local mtd=

	mtd=`get_mtd "$name"`

	if [ -z "$mtd" ]; then
		echo "No MTD partition called $name."
		return 0
	fi

	if [ -z "$src_dir" ]; then
		_src_dir="."
	else
		_src_dir="$src_dir"
	fi

	Quiet fsearch $_src_dir file

	if [ -e "$file" ]; then
		printf "Update %s to %s ... " $file $mtd
		Quiet flash_eraseall $mtd
		if [ -e /usr/sbin/nandwrite ]; then
			Quiet nandwrite -p $mtd $file
		else
			cat $file > $mtd
		fi
		printf "done\n"
	fi
}

# GetVersion_old - get version from U-Boot, U-Load, and Kernel
# @Keyword
GetVersion_old ()
{
	local ver=

	case $1 in
	U-Boot*)
		f=`get_mtd "u-boot-SF"`
		ver=`strsearch $f "U-Boot Version" 3`
		;;
	W-Load*)
		f=`get_mtd "w-load-SF"`
		ver=`strsearch $f "W-Load Version" 2`
		;;
	Kernel*)
		f="/proc/version"
		ver=`strsearch $f "Kernel" 1`
		;;	
	esac

	if [ "$ver" == "" ]; then
		ver="0.00.00.00"
	fi

	echo $1 $ver
}

# GetVersion - get version from /proc/version
# @Keyword
GetVersion ()
{
	local ret
	if [ -e "$src_dir/version" ]; then
		ret=`cat $src_dir/version | grep $1 | cut -d':' -f 2`
	fi
	if [ "$ret" ]; then
		echo "$ret"
	else
		echo " "
	fi
}

# make_uboot_script
#
# U-boot script autogen. The scripts are used for loadb.
make_uboot_script ()
{
	local _src_dir=

	if [ -z "$src_dir" ]; then
		_src_dir="."
	else
		_src_dir="$src_dir"
	fi

	rm $_src_dir/env/uboot_env_*.bin 2>/dev/null

	src_list=`find $_src_dir -name "uboot_env_*"`

	for i in $src_list; do
		SRC=$i
		DST=${SRC}.img

		$_src_dir/bin/mkimage -A arm -O linux -T script -n "uboot env" -d $SRC $DST
	done
}

mkscriptcmd ()
{
	if [ ! -e "$src_dir/scriptcmd" ] && [ -e "$src_dir/env/scriptcmd.txt" ]; then
		$src_dir/bin/mkimage -A arm -O linux -T script \
			-n "scriptcmd" \
			-d $src_dir/env/scriptcmd.txt $src_dir/scriptcmd
	fi
}

# nand_erase_all
#
# Erase whole NAND partitions
nand_erase_all ()
{
	flash_eraseall `get_mtd "filesystem-NAND"`
}

# add_missing_files
#
# Add required files if necessary
add_missing_files ()
{
	local p01="rpcdemo-*.tgz"
	local p02="directfb-1.4*.tgz"
	local p03="linux-fusion-8*.tgz"
	local p04="libwmtGL-*.tgz"
	local p05="fontconfig*.tgz"
	local p06="freetype2*.tgz"
	local p07="mtd-utils*.tgz"
	local p08="sysfsutils*.tgz"
	local p09="zlib*.tgz"

	# add missing files
	for pkg in $p01 $p02 $p03 $p04 $p05 $p06 $p07 $p08 $p09
	do
		fsearch $src_dir pkg
		echo "Add missing $pkg"
		tar zxf $pkg -C /
	done

	# load linux-fusion-8.1.1
	if [ -e "/etc/rc.d/rc0.d/S48fusion" ]; then
		sh /etc/rc.d/rc0.d/S48fusion
	else
		modprobe fusion
	fi
}

hex_to_dec ()
{
	printf "%u" $1
}

dec_to_hex ()
{
	printf "0x%x" $1
}

# Get offset for kernel-NAND by accumlating partitions
print_kernel_NAND_ofs ()
{
	mtdlist=`cat /proc/mtd|grep NAND|cut -d\  -f2,4|tr \  @|sed 's/"//g'`

	ofs=0
	for i in $mtdlist; do
		size=`hex_to_dec 0x\`echo $i|cut -d@ -f1\``
		mtd=`echo $i|cut -d@ -f2`
		if [ "$mtd" == "kernel-NAND" ]; then
			break;
		fi
		let "ofs = ofs + $size"
	done

	echo `dec_to_hex $ofs`
}

# Get offset for kernel-NAND by skipping 19 eraseblocks
print_kernel_NAND_ofs_abs ()
{
	num=`cat /proc/mtd|grep "NAND"|wc -l`

	tmp=`cat /proc/mtd|grep "kernel-NAND"|cut -d\  -f 3`
	erasesize=`printf "%u" 0x$tmp`

	if [ $num -le 3 ]; then
		ofs="0"	
	else
		tmp=`expr $erasesize \* 19` # 19 eraseblocks
		ofs=`printf "0x%x" $tmp`
	fi
	echo $ofs
}

print_initrd_NAND_ofs ()
{
	tmp=`print_kernel_NAND_ofs`
	kernel_NAND_ofs=`printf "%u" $tmp`
	tmp=`get_mtd_len "kernel-NAND"`
	kernel_NAND_len=`printf "%u" $tmp`

	tmp=`expr $kernel_NAND_ofs + $kernel_NAND_len`
	initrd_NAND_ofs=`printf "0x%x" $tmp`
	echo $initrd_NAND_ofs
}

print_filesystem_NAND_ofs ()
{
	tmp=`print_initrd_NAND_ofs`
	initrd_NAND_ofs=`printf "%u" $tmp`
	tmp=`get_mtd_len "initrd-NAND"`
	initrd_NAND_len=`printf "%u" $tmp`

	tmp=`expr $initrd_NAND_ofs + $initrd_NAND_len`
	filesystem_NAND_ofs=`printf "0x%x" $tmp`
	echo $filesystem_NAND_ofs
}

print_wmt_nfc_mtd_uboot_logo_ofs ()
{
	tmp=`print_filesystem_NAND_ofs`
	initrd_NAND_ofs=`printf "%u" $tmp`
	tmp=`get_mtd_len "filesystem-NAND"`
	initrd_NAND_len=`printf "%u" $tmp`

	tmp=`expr $initrd_NAND_ofs + $initrd_NAND_len`
	filesystem_NAND_ofs=`printf "0x%x" $tmp`
	echo $filesystem_NAND_ofs
}

print_wmt_nfc_mtd_kernel_logo_ofs ()
{
	tmp=`print_wmt_nfc_mtd_uboot_logo_ofs`
	initrd_NAND_ofs=`printf "%u" $tmp`
	tmp=`get_mtd_len "u-boot-logo"`
	initrd_NAND_len=`printf "%u" $tmp`

	tmp=`expr $initrd_NAND_ofs + $initrd_NAND_len`
	filesystem_NAND_ofs=`printf "0x%x" $tmp`
	echo $filesystem_NAND_ofs
}

# do_setenv_nand
# @uboot_env	U-boot script in plain text format
# @mtd		MTD device used by U-Boot env.
#
# Save uboot environment variables from u-boot plain text script
#
# Usage:
#     do_setenv_nand /mnt/mmcblk0p1/env/uboot_env_sf /dev/mtd7
do_setenv_nand ()
{
	local mtd=$2
	local flag=$3

	local crc32=${src_dir}/bin/crc32
	local infile=$1
	local outfile=/tmp/uboot_env.raw
	local tmpfile=/tmp/uboot_env.tmp

	echo "[do_setenv_nand] infile=$infile"
	echo "[do_setenv_nand] outfile=$outfile"
	echo "[do_setenv_nand] tmpfile=$tmpfile"

	dd if=/dev/zero of=${outfile} bs=1k count=64

	cat ${infile} | \
	tr '\n' '~' | sed 's/\\~//g' | tr '~' '\n' | \
	sed 's/\ \+/ /g' | \
	grep setenv | sed 's/setenv //' | sed 's/ /=/' | \
	sed 's/\\;/;/g' | tr "\n" "\0" > ${tmpfile}

	dd if=${tmpfile} of=${outfile} bs=1 seek=4 count=65532 conv=notrunc

	$crc32 -s 4 -x 1 ${outfile}
	$crc32 -s 4 -r ${outfile} > ${tmpfile}
	dd if=${tmpfile} of=${outfile} bs=1 seek=0 count=4 conv=notrunc

	flash_eraseall $mtd
	nandwrite -p -s 0  $mtd ${outfile}

	rm ${tmpfile} ${outfile}
}

# setenv_nand
# @uboot_env	U-boot script in plain text format
#
# Save uboot environment variables from u-boot plain text script
#
# Usage:
#     setenv "uboot_env_nand"
setenv_nand ()
{
	local mtd_name=
	local mtd=
	local uboot_env=$1
	local tmpfile=/tmp/setenv_nand.tmp

	rm -f ${tmpfile}
	if [ -e ${src_dir}/env/uboot_env_head ]; then
		cat ${src_dir}/env/uboot_env_head >> ${tmpfile}
	fi
	if [ -e ${src_dir}/env/${uboot_env} ]; then
		cat ${src_dir}/env/${uboot_env} >> ${tmpfile}
	fi
	if [ -e ${src_dir}/env/uboot_env_tail ]; then
		cat ${src_dir}/env/uboot_env_tail >> ${tmpfile}
	fi

	mtd_name="u-boot env. cfg. 1-NAND"
	mtd=`get_mtd "${mtd_name}"`

	if [ ! -z "${mtd}" ]; then
		do_setenv_nand ${tmpfile} ${mtd}
	else
		echo "No MTD partition called ${mtd_name}."
	fi

	rm -f ${tmpfile}
}

# generate a random MAC address
# random_mac
# @file_name tmp file name
#
# Generate a random MAC address to tmp file
#
# Usage:
#     random_mac /tmp/uboot_env.tmp
random_mac ()
{
	local outfile=$1
	local name=ethaddr
	local random=`head -200 /dev/urandom | cksum | cut -f1 -d" "`

	local a1=`echo $random | cut -c1-2`
	local a2=`echo $random | cut -c3-4`
	local a3=`echo $random | cut -c5-6`
	
	echo "random_mac: 00:40:63:$a1:$a2:$a3"
	
	echo "setenv $name 00:40:63:$a1:$a2:$a3" >> ${outfile}
}

# restore_env
# @env_name	 uboot environment variable name
# @file_name tmp file name
#
# Save current uboot environment variable to tmp file
#
# Usage:
#     restore_env ethaddr /tmp/uboot_env.tmp
restore_env ()
{
	local name=$1
	local outfile=$2
	local invalid_value="getenv $name failed!"
	
	local value=`${src_dir}/bin/getenv $name`
	
	if [ "$value" = "" ] || [ "$value" = "$invalid_value" ]; then
		echo "[WMT] *I* restore: $invalid_value"
	else 
		echo "restore: $name=$value to ${outfile}"
		echo "setenv $name $value" >> ${outfile}
	fi
}

# do_setenv
# @uboot_env	U-boot script in plain text format
# @mtd		MTD device used by U-Boot env.
# @flag		active flag
#
# Save uboot environment variables from u-boot plain text script
#
# Usage:
#     do_setenv /mnt/mmcblk0p1/env/uboot_env_sf /dev/mtd3 1
do_setenv ()
{
	local mtd=$2
	local flag=$3

	local crc32=${src_dir}/bin/crc32
	local infile=$1
	local outfile=/tmp/uboot_env.raw
	local tmpfile=/tmp/uboot_env.tmp

	echo "[do_setenv] infile=$infile"
	echo "[do_setenv] outfile=$outfile"
	echo "[do_setenv] tmpfile=$tmpfile"

	dd if=/dev/zero of=${outfile} bs=1k count=64

	cat ${infile} | \
	tr '\n' '~' | sed 's/\\~//g' | tr '~' '\n' | \
	sed 's/\ \+/ /g' | \
	grep setenv | sed 's/setenv //' | sed 's/ /=/' | \
	sed 's/\\;/;/g' | tr "\n" "\0" > ${tmpfile}

	dd if=${tmpfile} of=${outfile} bs=1 seek=5 count=65531 conv=notrunc

	$crc32 -s 5 -x 1 ${outfile}
	$crc32 -s 5 -r ${outfile} > ${tmpfile}
	printf "\x${flag}" >> ${tmpfile}
	dd if=${tmpfile} of=${outfile} bs=1 seek=0 count=5 conv=notrunc

	flash_eraseall $mtd
	cat ${outfile} > $mtd

	#mv ${tmpfile} ${tmpfile}.${flag}
	#cp ${outfile} ${outfile}.${flag}
	rm ${tmpfile} ${outfile}
}



#
# Add additional uboot environment variables to in-file (text script file)
#
# Usage:
#     env_addon outfile
env_addon()
{         
	echo "[WMT] add additionl uboot env..."
	local tmpfile=$1

	echo "setenv kernel-NAND_mtd `get_mtdblock "kernel-NAND"`" >> ${tmpfile}	
	echo "setenv kernel-NAND_ofs `print_kernel_NAND_ofs`" >> ${tmpfile}		
	echo "setenv kernel-NAND_len `get_mtd_len "kernel-NAND"`" >> ${tmpfile}

	echo "setenv initrd-NAND_mtd `get_mtdblock "initrd-NAND"`" >> ${tmpfile}
	echo "setenv initrd-NAND_ofs `print_initrd_NAND_ofs`" >> ${tmpfile}
	echo "setenv initrd-NAND_len `get_mtd_len "initrd-NAND"`" >> ${tmpfile}

	echo "setenv filesystem-NAND_mtd `get_mtdblock "filesystem-NAND"`" >> ${tmpfile}
	echo "setenv filesystem-NAND_ofs `print_filesystem_NAND_ofs`" >> ${tmpfile}
	echo "setenv filesystem-NAND_len `get_mtd_len "filesystem-NAND"`" >> ${tmpfile}

	echo "setenv wmt.nfc.mtd.kernel-logo `print_wmt_nfc_mtd_kernel_logo_ofs`" >> ${tmpfile}
	local uboot_logo_ofs=`print_wmt_nfc_mtd_uboot_logo_ofs`
	local temp=$(( $uboot_logo_ofs + $UBOOT_LOG2_OFFSET )) 
	local uboot_logo2_ofs=`printf "0x%x" $temp`

	echo "setenv wmt.nfc.mtd.u-boot-logo `printf "0x%x" $uboot_logo_ofs`" >> ${tmpfile}
	echo "setenv wmt.nfc.mtd.u-boot-logo2 `printf "0x%x" $uboot_logo2_ofs`" >> ${tmpfile}

	random_mac ${tmpfile}
	
	restore_env serialnum ${tmpfile}
	
	#cat ${tmpfile}
}

# setenv
# @uboot_env	U-boot script in plain text format
#
# Save uboot environment variables from u-boot plain text script
#
# Usage:
#     setenv "uboot_env_sf"
setenv ()
{
	local mtd_name=
	local mtd=
	local uboot_env=$1
	local tmpfile=/tmp/setenv.tmp

	rm -f ${tmpfile}
	if [ -e ${src_dir}/env/uboot_env_head ]; then
		cat ${src_dir}/env/uboot_env_head >> ${tmpfile}
	fi
	if [ -e ${src_dir}/env/${uboot_env} ]; then
		cat ${src_dir}/env/${uboot_env} >> ${tmpfile}
	fi
	if [ -e ${src_dir}/env/uboot_env_tail ]; then
		cat ${src_dir}/env/uboot_env_tail >> ${tmpfile}
	fi
	
	env_addon ${tmpfile}

	mtd_name="u-boot env. cfg. 1-SF"
	mtd=`get_mtd "${mtd_name}"`

	if [ ! -z "${mtd}" ]; then
		do_setenv ${tmpfile} ${mtd} 1
	else
		echo "No MTD partition called ${mtd_name}."
	fi

	mtd_name="u-boot env. cfg. 2-SF"
	mtd=`get_mtd "${mtd_name}"`

	if [ ! -z "${mtd}" ]; then
		do_setenv ${tmpfile} ${mtd} 0
	else
		echo "No MTD partition called ${mtd_name}."
	fi

	#JodyFu: useless for u-boot-env in NAND now
	#setenv_nand ${uboot_env}

	# JodyFu: move next env-var from .config to env/uboot_env_head
	# Use configs from .config or default
	#setenv_if_valid "memtotal" "$MEM_TOTAL"
	#setenv_if_valid "mmcid" "$MMC_ID"
	#setenv_if_valid "lpj" "$LPJ"

	rm -f ${tmpfile}
}

# setenv_if_valid
# @name
# @value
setenv_if_valid ()
{
	if [ $# -lt 2 ]; then
		return
	fi

	if [ ! -z "$2" ] && [ "$2" != "AUTO" ]; then
		setenv.sh "$1" "$2"
	fi
}

# strsearch
# @file
# @string
# @offset
#
# Search a word at the offset of the specific string.
strsearch ()
{
	if [ $# -lt 3 ]; then
		return
	fi

	local match=0
	local ofs=$3
	local uniq_word=`echo $2 | sed 's/ /_/g'`
	local tokens=`strings $1 | sed "s/$2/$uniq_word/g" | tr -d ![]`
	local keyword=`strings $1 | grep "$2"`

	if [ "$keyword" == "" ]; then
		return
	fi

	for i in $tokens ; do
		if [ "$i" == "$uniq_word" ]; then
			match=1
		fi
		if [ $match == 1 ]; then
			if [ $ofs == 0 ]; then
				echo $i
				return
			else
				let "ofs = ofs - 1"
			fi
		fi
	done
}

#
# PLEASE DON'T MODIFY FUNCTIONS ABOVE THIS LINE.
# THOSE FUNCTIONS ARE THE HEART OF BSPINST2.
#
print_recommend_wload_version()
{
 	local mtd_wload=`get_mtd "w-load-SF"`
	local wload_updateid=`strings ${mtd_wload}  | grep "UPDATEID_"` 
  if [ -z "$wload_updateid" ]; then
      echo "[WMT] old w-load(before V1.1.1) in board, need to update."
      if [ ! -e ${src_dir}/bin/mu ]; then
        echo "[WMT] *E* not found mu command, skip w-load update"
        return 0;
      fi

      local addr1_val=`${src_dir}/bin/mu  d 0xD8000434 1`
      local addr2_val=`${src_dir}/bin/mu  d 0xD813020C 1`
      echo "[WMT] addr1_val= $addr1_val"
      echo "[WMT] addr2_val= $addr2_val"
      local reg1=`echo $addr1_val | cut -d\  -f3`
      local reg2=`echo $addr2_val | cut -d\  -f5`
      echo "[WMT] reg1= $reg1, reg2= $reg2"
      local try_wload=
      if [ 2 == `echo $(( ($reg1 & 3 ) ))` ]; then
          try_wload="w-load_DDR3_700M_1066M_8bit_2_*.bin"
      else
          if [ 1 == `echo $(( ($reg1 & 3 ) ))` ] && [ 0x00000c28 == `echo $reg2` ]; then
            try_wload="w-load_DDR2_600M_667M_8bit_2_*.bin"
          else
            try_wload="w-load_DDR2_700M_800M_8bit_2_*.bin"
          fi
      fi
      
      p_wload_topatch="$try_wload"

  else

    local buildno_board=`echo $wload_updateid | awk -F _ '{print $(NF)}'`
    
    local wild_wload_name=`echo $wload_updateid | sed 's/[0-9]\{6,\}/*/g' | sed 's/UPDATEID/*/g'`
    local wload_full_path=`find $src_dir -name $wild_wload_name`

    if [ -z "$wload_full_path" ]; then
      p_wload_topatch="Installed: $wload_updateid"
      return 0
    fi
    
    local file_wload=`basename "${wload_full_path}"`
    local buildno_file=`echo $file_wload | awk -F _ '{print $(NF)}' | sed 's/.bin//g'`
    
    ##echo "[WMT] buildno_file = $buildno_file,  buildno_board = $buildno_board"
    if [ $buildno_file -gt $buildno_board ]; then
      ##echo "[WMT] updating $wload_full_path..."

      p_wload_topatch = "$file_wload"
    else
    ##  echo "[WMT] no newer w-load file, skip"
      p_wload_topatch="Installed: $wload_updateid"
    fi 
    
  fi

  msg "Recommended W-Load Version:"
  msg "$p_wload_topatch"
  
}


inst_wload_sf ()
{
	local mtd_wload=`get_mtd "w-load-SF"`
	local wload_updateid=`strings ${mtd_wload}  | grep "UPDATEID_"` 
	#local wload_updateid=`strings $src_dir/w-load_DDR2_700M_800M_8bit_2_0090001.bin  | grep "UPDATEID_"` 
	
	if [ -z "$wload_updateid" ]; then
		echo "[WMT] old w-load(before V1.1.1) in board, need to update."
		if [ ! -e ${src_dir}/bin/mu ]; then
			echo "[WMT] *E* not found mu command, skip w-load update"
			return 0;
		fi

		local addr1_val=`${src_dir}/bin/mu  d 0xD8000434 1`
		local addr2_val=`${src_dir}/bin/mu  d 0xD813020C 1`
		echo "[WMT] addr1_val= $addr1_val"
		echo "[WMT] addr2_val= $addr2_val"
		local reg1=`echo $addr1_val | cut -d\  -f3`
		local reg2=`echo $addr2_val | cut -d\  -f5`
		echo "[WMT] reg1= $reg1, reg2= $reg2"
		local try_wload=
		if [ 2 == `echo $(( ($reg1 & 3 ) ))` ]; then
				try_wload="w-load_DDR3_700M_1066M_8bit_2_*.bin"
		else
				if [ 1 == `echo $(( ($reg1 & 3 ) ))` ] && [ 0x00000c28 == `echo $reg2` ]; then
					try_wload="w-load_DDR2_600M_667M_8bit_2_*.bin"
				else
					try_wload="w-load_DDR2_700M_800M_8bit_2_*.bin"
				fi
		fi

		echo "[WMT] use ${src_dir}/$try_wload"

		sf_inst "w-load-SF" "$try_wload"
    
   
    
		return 0
	fi

  
	echo "[WMT] wload_updateid: $wload_updateid"
	local buildno_board=`echo $wload_updateid | awk -F _ '{print $(NF)}'`
	
	local wild_wload_name=`echo $wload_updateid | sed 's/[0-9]\{6,\}/*/g' | sed 's/UPDATEID/*/g'`
	echo "[WMT] wild_wload_name: $wild_wload_name"
	local wload_full_path=`find $src_dir -name $wild_wload_name`

	if [ -z "$wload_full_path" ]; then
		echo "[WMT] *W* no w-load updated file "
		return 0
	fi
	
	local file_wload=`basename "${wload_full_path}"`
	local buildno_file=`echo $file_wload | awk -F _ '{print $(NF)}' | sed 's/.bin//g'`
	
	echo "[WMT] buildno_file = $buildno_file,  buildno_board = $buildno_board"
	if [ $buildno_file -gt $buildno_board ]; then
		echo "[WMT] updating $wload_full_path..."
		sf_inst "w-load-SF" "$file_wload"
	else
		echo "[WMT] no newer w-load file, skip"
	fi
}


inst_wload_from_settings()
{
#    wload_full_path = "${src_dir}/$WLOAD_IMAGE" 
    sf_inst "w-load-SF" "$WLOAD_IMAGE"
}


inst_uboot_sf ()
{
	local file_uboot="u-boot.bin"
	if [ ! -e "$src_dir/$file_uboot" ]; then
		echo "[WMT] *W* not found uboot file, skip u-boot update!"
		return 0;
	fi
	
	local uboot_updateid_file=`strings $src_dir/$file_uboot  | grep "UPDATEID_"` 
	if [ -z "$uboot_updateid_file" ] ; then
		echo "[WMT] *I* no new u-boot, skip u-boot update!"
		return 0
	fi

	local mtd_uboot=`get_mtd "u-boot-SF"`
	local uboot_updateid_board=`strings ${mtd_uboot}  | grep "UPDATEID_"` 

	echo "[WMT] uboot_updateid_board: $uboot_updateid_board"
	echo "[WMT] uboot_updateid_file: $uboot_updateid_file"

	if [ -z "$uboot_updateid_board" ] ; then
		echo "[WMT] *I* old uboot(before V1.1.1) in board, update..."
		sf_inst "u-boot-SF" "$file_uboot"
		return 0
	fi
	
	if [ "$uboot_updateid_file" \> "$uboot_updateid_board" ]; then
		echo "[WMT] updating $file_uboot..."
		sf_inst "u-boot-SF" "$file_uboot"
	else
		echo "[WMT] no newer u-boot file, skip."
	fi
}

inst_kernel_sf ()
{
	sf_inst "kernel-SF" "uzImage.bin"
}

inst_initrd_sf ()
{
	sf_inst "filesystem-SF" "initrd.gz"
}

inst_filesystem_sf ()
{
	sf_inst "filesystem-SF" "ramdisk*.gz"
}

inst_filesystem_cramfs ()
{
       sf_inst "filesystem-SF" "rootfs*.cramfs"
}

inst_wload_nand ()
{
	nand_inst "w-load-NAND" "w-load.bin"
}

inst_uboot_nand ()
{
	nand_inst "u-boot-NAND" "u-boot-nand.bin"
}

inst_kernel_nand ()
{
	nand_inst "kernel-NAND" "uzImage.bin"
}

inst_kernel_nand_from_config()
{
  nand_inst "kernel-NAND" "$KERNEL_IMAGE"
}

inst_initrd_nand ()
{
	nand_inst "initrd-NAND" "initrd.gz"
}

isblack ()
{
	local blacklist=
	local res=
	local p=$1

	if [ ! -e $src_dir/blacklist.txt ]; then
		return 0
	fi

	blacklist=`cat $src_dir/blacklist.txt | grep -v \#`
	for b in $blacklist; do
		res=`find $p -name "$b"`
		if [ "$res" != "" ]; then
			return 1
		fi
	done
	return 0
}

isListed ()
{
	local list=
	local res=
	local f=$1
	local p=$2

	if [ -z "$f" ]; then
		return 0
	fi

	if [ ! -e "$src_dir/packages/$f" ]; then
		return 0
	fi

	list=`cat $src_dir/packages/$f | grep -v \#`
	for b in $list; do
		res=`find $p -name "$b"`
		if [ "$res" != "" ]; then
			return 1
		fi
	done
	return 0
}

# inst_filesystem_nand
#
# Install software packages into NAND rootfs
#
# The default search path is the current folder
# if $src_dir is invalid.
inst_filesystem_nand ()
{
	local nand2=
	local nandblock2=
	local mount_point=/tmp/mtd
	local ret=
	local prev_ratio=$CompleteRatio
	local _ratio=

	nand2=`get_mtd "filesystem-NAND"`
	nandblock2=`get_mtdblock "filesystem-NAND"`

	if [ ! -e "${mount_point}" ]; then
		mkdir -p ${mount_point}
	fi

	sync

	umount ${mount_point} 2>/dev/null
	echo
	printf "Erasing MTD device (%s)... Please wait." $nand2
	flash_eraseall $nand2 > /dev/null
	printf "\b\b\b\b\b\b\b\b\b\b\b\b done.        \n"

	printf "Writing MTD device (%s)... Please wait.\n" $nandblock2
	mount -t yaffs2 -o rw $nandblock2 ${mount_point}

	local_cwd="$src_dir/packages"
	if [ -e "$local_cwd" ]; then
		packages=`find $local_cwd -name "*.tgz" | sort`
		pkglist=
		pkgtotal=0
		pkgcount=0
		echo
		for f in $packages ; do
			if [ $INSTALL_BASIC -eq 1 ]; then
				isListed basic.txt $f
				ret=$?
			elif [ $INSTALL_RECOMMENDED -eq 1 ]; then
				isListed recommended.txt $f
				ret=$?
			elif [ $INSTALL_FULL -eq 1 ]; then
				isListed full.txt $f
				ret=$?
			else
				ret=1
			fi
			if [ $ret -eq 1 ]; then
				isblack $f
				if [ $? == 0 ]; then
					pkglist="$pkglist $f"
					let 'pkgtotal = pkgtotal + 1'
				fi
			fi
		done
		for f in $pkglist ; do
			let 'pkgcount = pkgcount + 1'
			_ratio=`expr $prev_ratio + \( 70 - $prev_ratio \) \* $pkgcount / $pkgtotal`
			ratio $_ratio
			msg "`base_name $local_cwd/ $f`"
			echo "Install $f ($pkgcount / $pkgtotal)"
			tar zxf $f -C ${mount_point} >/dev/null 
			sleep 1
		done
	fi

#   copy single patch to root-fs, including restore packages
	msg "copy rootfs patch&restore files..."
	echo "[WMT] copy rootfs patch to FileSystem-Nand"
	/bin/cp -aR $src_dir/packages/fs_patch/root_patch/. ${mount_point}
	echo "[WMT] copy all data patch to FileSystem-Nand for foctroy-recovery"
	/bin/cp -aR $src_dir/packages/fs_patch/data_patch ${mount_point}/.restore/
#   remove customer key information
	/bin/rm -rf ${mount_point}/.restore/wmtpref

	sync
	umount ${mount_point}
	printf "\b\b\b\b\b\b\b\b\b\b\b\bdone.        \n"
}

reboot_countdown ()
{
	for t in 3 2 1 0 ; do
		msg "Don't remove installation disk! ($t)"
		sleep 1
	done
	msg "Rebooting for installation stage 2"

	sleep 5
	reboot -f -n
}

# Install senarios
# 0. SF 16MiB              (ramdisk)"
# 1. SF 16MiB  + NAND      (yaffs2)"
# 2. SF/NAND 512KiB + NAND (yaffs2)"
# 3. SD/MMC                (ramdisk)"
# 4. SF 8MiB               (ramdisk)"
# 5. SF 8,16MiB            (cramfs)"

# pre_install
#
# Installation phase 1
#
pre_install ()
{
	echo "Executing pre_install($1)"

	case $1 in
	0)
		msg "Upgrading W-Load to SF."
		inst_wload_sf
		ratio 10

		msg "Upgrading U-Boot to SF."
		inst_uboot_sf
		ratio 20

		msg "Upgrading U-Boot env. cfg. to SF."
		setenv "uboot_env_sf"
		ratio 30

		msg "Upgrading Kernel to SF."
		inst_kernel_sf
		ratio 40

		msg "Upgrading Ramdisk to SF."
		inst_filesystem_sf
		ratio 100
		;;
	1)
		msg "Upgrading W-Load to SF."
		inst_wload_sf
		ratio 10

		msg "Upgrading U-Boot to SF."
		inst_uboot_sf
		ratio 20

		msg "Upgrading U-Boot env. cfg. to SF."
		setenv "uboot_env_sf"
		ratio 30

		msg "Upgrading Kernel to SF."
		inst_kernel_sf
		ratio 40

		msg "Upgrading Ramdisk to SF."
		inst_initrd_sf
		ratio 50

		reboot_countdown
		;;
	2)
		msg "Upgrading W-Load to SF."
		inst_wload_sf
		ratio 5

		msg "Upgrading W-Load to NAND."
		inst_wload_nand
		ratio 10

		msg "Upgrading U-Boot to SF."
		inst_uboot_sf
		ratio 15

		msg "Upgrading U-Boot to SF."
		inst_uboot_nand
		ratio 20

		local initrd=`get_mtd "initrd-NAND"`

		if [ "$initrd" != "" ] ; then
			msg "Upgrading U-Boot env. cfg. to SF."
			setenv uboot_env_nand_r
			ratio 30

			msg "Upgrading Kernel to NAND."
			inst_kernel_nand
			ratio 40

			msg "Upgrading Ramdisk to NAND."
			inst_initrd_nand
			ratio 50

			reboot_countdown
		else
			msg "Cannot upgrade initrd-NAND!!!"
			sleep 10

			#msg "Upgrading U-Boot env. cfg. to SF."
			#setenv uboot_env_mmc
			#ratio 30
		fi
		;;
	3)
		msg "Upgrading U-Boot env. cfg. to SF."
		setenv uboot_env_mmc
		ratio 100
		;;
	4)
		msg "Upgrading W-Load to SF."
		inst_wload_sf
		ratio 10

		msg "Upgrading U-Boot to SF."
		inst_uboot_sf
		ratio 20

		msg "Upgrading U-Boot env. cfg. to SF."
		setenv "uboot_env_sf_8mb"
		ratio 30

		msg "Upgrading Kernel to SF."
		inst_kernel_sf
		ratio 40

		msg "Upgrading Ramdisk to SF."
		inst_filesystem_sf
		ratio 100
		;;
	5)
		msg "Upgrading W-Load to SF."
		inst_wload_sf
		ratio 10

		msg "Upgrading U-Boot to SF."
		inst_uboot_sf
		ratio 20

		msg "Upgrading U-Boot env. cfg. to SF."
		setenv "uboot_env_sf_cramfs"
		ratio 30

		msg "Upgrading Kernel to SF."
		inst_kernel_sf
		ratio 40

		msg "Upgrading Cramfs to SF."
		inst_filesystem_cramfs
		ratio 100
		;;
	esac
}

# do_install
#
# Installation phase 2
do_install ()
{
	echo "Executing do_install($1)"

		msg "Upgrading W-Load to SF."
		inst_wload_from_settings
		ratio 20

		#JodyFu: useless for w-load in NAND now
		#msg "Upgrading W-Load to NAND."
		#inst_wload_nand
		#ratio 10

		msg "Upgrading U-Boot to SF."
		inst_uboot_sf
		ratio 40

		#JodyFu: useless for u-boot in NAND now
		#msg "Upgrading U-Boot to NAND."
		#inst_uboot_nand
		#ratio 20

		local mtd=`get_mtd "kernel-NAND"`

		if [ "$mtd" != "" ] ; then
			msg "Upgrading U-Boot env. cfg. to SF."
			setenv "uboot_env_nand"
			ratio 60

			#JodyFu: just for factory recovery
			msg "Upgrading Ramdisk to NAND."
			inst_initrd_nand
			ratio 80

			msg "Upgrading Kernel to NAND."
			inst_kernel_nand_from_config
			ratio 90

			#msg "Upgrading filesystem to NAND."
			#inst_filesystem_nand
			#ratio 75
		else
			msg "Cannot upgrade kernel-NAND!!!"
			sleep 10
		fi


    msg "Upgrading U-Boot LOGO to NAND"
    update_logo "u-boot-logo"
    ratio 94

    msg "Upgrading Kernel LOGO to NAND"
    update_logo "kernel-logo"
    ratio 98
        
	
		msg "Finished (u-Boot, w-load, kernel, logos)"

}

# Get key from IR
GetKeyCode ()
{
	local f=/usr/bin/input.sh
	local k=/tmp/keycode
	if [ ! -e $f ]; then
		echo "#!/bin/sh" > $f
		echo "echo \$1 > $k" >> $f
		chmod 755 $f
		sync
	fi

	if [ -e $k ]; then
		cat $k
		> $k
	fi
}

show_next_mac ()
{
	let "s = 0"
	for i in 1 2 3 4 5 6; do
		let "u$i = `echo $1|cut -d: -f$i|xargs printf "0x%s"|\
			xargs printf "%u"`"
		let "s = s * 256 + u$i"
	done

	let "s = s + 1"

	for i in 6 5 4 3 2 1; do
		let "u$i = `expr $s % 256`"
		let "s = s / 256 "
	done
	
	printf "%02x:%02x:%02x:%02x:%02x:%02x\n" $u1 $u2 $u3 $u4 $u5 $u6 |\
		tr [a-z] [A-Z]
}

edit_config ()
{
	if [ $# -lt 2 ]; then
		echo "Usage: edit_config config name [value]"
		return
	fi

	local config=$1
	local name=$2
	local value=$3
	local old_value=

	if [ -e "$config" ]; then
		old_value=`cat $config | grep $name | cut -d= -f2`
	fi

	if [ -z "$old_value" ]; then
		if [ ! -z "$value" ]; then
			# add
			echo "$name=$value" >> $config
			return
		fi
	else
		if [ ! -z "$value" ]; then
			# modify
			sed "s/$name=$old_value/$name=$value/g" -i $config
		else
			# delete
			sed "s/$name=$old_value//g" -i $config
		fi
	fi
	sed "/^$/d" -i $config
}

save_config ()
{
	local f="$src_dir/.config"
	edit_config $f DEFAULT_SCENARIO $DEFAULT_SCENARIO
	edit_config $f INSTALL_BASIC $INSTALL_BASIC
	edit_config $f INSTALL_RECOMMENDED $INSTALL_RECOMMENDED
	edit_config $f INSTALL_FULL $INSTALL_FULL
	edit_config $f TIMEOUT_MENU $TIMEOUT_MENU
	edit_config $f TIMEOUT_STARTUP $TIMEOUT_STARTUP
	edit_config $f TIMEOUT_EXIT $TIMEOUT_EXIT
	edit_config $f MAC_0 $MAC_0
	edit_config $f MAC_INCREMENT $MAC_INCREMENT
	edit_config $f MEM_TOTAL $MEM_TOTAL
	sync
	cat $f
}

load_config ()
{
	local f="$src_dir/.config"
	if [ -e "$f" ]; then
		source $f
		cat $f
	else
		save_config
	fi
}

load_version_config()
{
  local verconf="$src_dir/VERSION_CONFIG.txt"
 	if [ -e "$verconf" ]; then
    source $verconf
 	fi
}

netconfig ()
{
	# do nothing, because using random_mac
	return
	
	local f="$src_dir/.config"

	if [ "$MAC_0" == "AUTO" ]; then
		HWADDR_0=`ifconfig|grep eth0|sed 's/HWaddr /@/'|cut -d@ -f2`
	else
		HWADDR_0=$MAC_0
	fi
	SetMessage `FM 4` `FM 11` "MAC_0 = $HWADDR_0"
	setenv.sh "ethaddr" "$HWADDR_0"

	if [ "$MAC_INCREMENT" != "0" ] && [ "$MAC_0" != "AUTO" ]; then
		MAC_0=`show_next_mac $MAC_0`
		edit_config $f MAC_0 "$MAC_0"
		echo "Next MAC_0 will be $MAC_0"
	fi
}

