#!/bin/sh
display()
{
	echo $*
}

pnd()
{
	display $*
	$*
}

print_sleep()
{
	i=0
	while [ $i -lt $1 ]
	do
		sleep 1
		display -n "#"
		let i+=1
	done
}

#./script_name dst_block_node src_dir_contained_files update_option
#		1	:only update 3 partitions,when associated "tar" file found
#		2	:update all and "fdisk" even though the target mmc/sd has valid MBR(1.vfat;2.ext3;3.ext3)
#		3	:update nand only
check_arg_valid()
{
	if [ $# -lt 3 ];then
		display "usage:./script_name dst_block_node src_dir_contained_files \
		<1:update fs only;2:update both bare&fs;3:update NAND only>"
		exit 1
	fi
	if [ ! -b $1 ];then
		display "\"$1\" is NOT block!"
		if [ $3 -eq 3 ];then
			echo "uptype $3,go on!"
		else
			exit 1
		fi
	fi
	if [ ! -d $2 ];then
		display "\"$2\" directory does NOT exist!"
		exit 1
	fi
}
#variables can be changed
#
check_arg_valid $*

dst_node=$1
folder=$2
up_type=$3
fs_files="fat.tar root.tar qte.tar"
bare_files="bl2 uImage logo.img"
app_files="root qte ebook"
up_dir=$folder/update_tools
reserved_mega=24
root_mega=50
let qte_mega=128+64
need_fdisk=0
arch=arm
#variables caculated,no need to touch.
#mmcblk0 or sdb
dst_node_block=`echo ${dst_node}|cut -d'/' -f3`
dst_total_blk=`cat /sys/block/${dst_node_block}/size`
fs_files_nr=`echo ${fs_files}|wc -w`
bare_files_nr=`echo ${bare_files}|wc -w`
let dst_mega=${dst_total_blk}/2048
let reserved_blk=$reserved_mega*2048
useable_dst_maga=$((($dst_total_blk-$reserved_blk)/2048))
let fat_mega=$useable_dst_maga-$root_mega-$qte_mega

dst_name=`echo ${dst_node_block}|cut -c1-3`
if [ $dst_name = "mmc" ];then
	part_prefix=p
fi

put2screen()
{
	if [ $arch != "arm" ];then
		return 0
	fi
	cat /sys/class/graphics/fb0/name|grep Eink >/dev/null
	if [ $? -eq 0 ] && [ -f $up_dir/$1.bmp ];then
		$up_dir/epson_main $up_dir/$1.bmp
	else
		echo -e "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n                              update $*" | \
			${up_dir}/triple_display
	fi
}
print_mount()
{
	return 0
	date
	mount
	$1 $2 $3
}

umount_ifany()
{
	if [ $arch != "x86" ];then
		return 0
	fi
	print_mount whoami
	for part in 1 2 3
	do
		display -n "check $dst_node${part_prefix}${part}:"
		mount|grep $dst_node${part_prefix}${part} > /dev/null
		if [ $? -eq 0 ];then
			display -n "CLEAN:"
			pnd umount $dst_node${part_prefix}${part}
		else
			display "OK!"
		fi
	done
	print_mount pwd
	if [ -z $1 ];then
		exit 2
	fi
}
#
dump_info()
{	
	cat /proc/cpuinfo |grep -m 1 ARM>/dev/null
	if [ $? -eq 1 ];then
		arch="x86"
	else
		if [ -f $up_dir/lib.tar ];then
			tar xf $up_dir/lib.tar -C /
		fi
	fi
	uname -a
	display -e "$*\n"\
		"Maybe updated:$fs_files($fs_files_nr); $bare_files($bare_files_nr)\n"\
		"Total:${dst_mega}M($dst_total_blk blocks), Reserved:${reserved_mega}M($reserved_blk blocks),"\
		"Useable ${useable_dst_maga}M\n" \
		"root:${root_mega}M, qte:${qte_mega}M, fat:${fat_mega}M"
}

check_useable()
{
	for part in 1 2 3 4
	do
		print_sleep 1
		sfdisk -R $dst_node 2>&1|grep busy
		if [ $? -eq 0 ];then
			display "${dst_node} is still in use!!!"
			umount ${dst_node}${part_prefix}${part}		
		else
			echo -n "nobody is using $dst_node."
			break
		fi
	done
	#if the dst is still in use,stop! To avoid the dst update itself.
	#Self-update should be done on PC using this shell script!
	print_sleep 3
	sfdisk -R $dst_node 2>&1|grep busy

	if [ $? -eq 0 ];then
		display "$dst_node is still in use,Stop!"
		exit 1
	else
		display "$dst_node can be sfdisk..."
	fi
}
#check partitions
#check_id real_id need_id part_nr
#
check_id()
{
	display -e "${dst_node}${part_prefix}$3 id:$1,need id:$2"
	if [ $1 != $2 ];then
		need_fdisk=1
	fi
}

#Check whether there is need to fdisk the dst block device
#check_part
#
check_part()
{
	display "FOUNDED MBR IDS:"
	for part in 1 2 3 4
	do
		id=`sfdisk --print-id ${dst_node} $part`
		if [ -z $id ];then
			id=0
		fi
		case $part in
		1)
			check_id $id "b" $part
			;;
		2)
			check_id $id "83" $part
			;;
		3)
			check_id $id "83" $part
			;;
		esac
	done
	print_sleep 1
	display -n "After check part,"
	if [ $need_fdisk -eq 1 ];then
		display "need to fdisk"
	else
		display "no need to fdisk..."	
	fi
}

wait_ready()
{
	while (( 1 ))
	do
		print_sleep 1
		sfdisk -R $dst_node 2>&1|grep busy
		if [ $? -ne 0  ];then
			break
		fi
	done
}

mkfs_part()
{
	if [ $1 = "ext2" ];then
		cmd="mkfs.$1"
	elif [ $1 = "vfat" ];then
		cmd="mkfs.$1 -F 32"
	elif [ $1 = "ext3" -a $arch = "arm" ];then
		cmd="mke2fs.static -j"
	elif [ $1 = "ext3" -a $arch != "arm" ];then
		cmd="mke2fs -j"
	fi
	display "--------${cmd} $2"
	$cmd $2
}
#if there is one partition doesn't meet the demand,then fdisk all
#
#do_sfdisk part_nr part_megabytes part_id part_start
part1=0
part2=0
part3=0
do_sfdisk()
{
	echo -e "0,$1,b\n,$2,83\n,$3,83"|sfdisk $dst_node -uM
	if [ $? -ne 0 ];then
		display "sfdisk failed!"
		exit 1
	fi
	for part in 1 2 3 4
	do
		case $part in
		1)
			mkfs_part "vfat" $dst_node${part_prefix}${part}			
			;;
		2)
			mkfs_part "ext3" $dst_node${part_prefix}${part}
			;;
		3)
			mkfs_part "ext3" $dst_node${part_prefix}${part}
			;;
		esac
	done
	part1=1
	part2=1
	part3=1
}

do_fdisk()
{
	if [ $up_type -eq 2 ];then
			need_fdisk=1
			display "But input argument indicates fdisk anyway..."
	fi
	if [ $need_fdisk -eq 1 ];then
		print_sleep 3
		do_sfdisk $fat_mega $root_mega $qte_mega
	fi
}
#extract the specific tar file to associated partition
#	extract_exist_file part_nr fs_type $extracted_file
mnt_dir="/mnt/flash"
extract_exist_file()
{
	case $1 in
	1)
		if [ $part1 -eq 0 ];then
			mkfs_part $2 $dst_node${part_prefix}$1			
		fi
		;;
	2)
		if [ $part2 -eq 0 ];then
			mkfs_part $2 $dst_node${part_prefix}$1
		fi
		;;
	3)
		if [ $part3 -eq 0 ];then
			mkfs_part $2 $dst_node${part_prefix}$1
		fi
		;;
	esac
	pnd mount -t $2 $dst_node${part_prefix}$1 ${mnt_dir}
	if [ $? -eq 0 ];then
		file=`echo $3|cut -d'.' -f1`
		put2screen $file
		pnd tar xf $folder/$3 -C ${mnt_dir}
		pnd umount ${mnt_dir}
	else
		display "fail to mount $dst_node$1($2)"
	fi
}

update_fs()
{
	part=0
	if [ ! -d $mnt_dir ];then
		mkdir -p $mnt_dir
	fi
	for file in ${fs_files}
	do
		let part+=1
		if [ ! -f ${folder}/$file ];then
			display "NO ${folder}/${file}"
			continue
		else
			display "up ${folder}/${file}"		
		fi	
		case $file in
		fat*)
			extract_exist_file $part vfat $file
			;;
		root*)
			extract_exist_file $part ext3 $file
			;;
		qte*)
			extract_exist_file $part ext3 $file
			;;
		esac
	done
}
#"const" variable
blk_size=512
total_blk=${dst_total_blk}
stuff_bytes=1024
bl1_bytes=8192
env_bytes=$((16*1024))
bl2_bytes=$((1*1024*1024-${env_bytes}-${bl1_bytes}-${stuff_bytes}))
kernel_bytes=$((4*1024*1024))
logo_bytes=$((2*1024*1024))

#calculated automatically
offset_bytes=$(($stuff_bytes+$bl1_bytes))
bl1_blk=$(($total_blk-$offset_bytes/$blk_size))

let "offset_bytes+=$env_bytes"
env_blk=$(($total_blk-$offset_bytes/$blk_size))

let "offset_bytes+=$bl2_bytes"
bl2_blk=$(($total_blk-$offset_bytes/$blk_size))

let "offset_bytes+=$kernel_bytes"
kernel_blk=$(($total_blk-$offset_bytes/$blk_size))

let "offset_bytes+=$logo_bytes"
logo_blk=$(($total_blk-$offset_bytes/$blk_size))

update_bare()
{
	if [ $up_type -ne 2 ];then
		display "skip bare files..."
		return 0
	fi
	display -e "$stuff_bytes $bl1_bytes $env_bytes $bl2_bytes $kernel_bytes $logo_bytes\n"\
				"$bl1_blk $env_blk $bl2_blk $kernel_blk $logo_blk"
	for file in ${bare_files}
	do
		up_file=${folder}/$file
		if [ -f $up_file ];then
			case $file in
			bl2)
				pnd dd if=$up_file of=$dst_node bs=$blk_size count=$(($bl1_bytes/$blk_size)) seek=${bl1_blk} conv=notrunc
				pnd dd if=$up_file of=$dst_node bs=$blk_size count=$(($bl2_bytes/$blk_size)) seek=${bl2_blk} conv=notrunc
				;;
			uImage)
				pnd dd if=$up_file of=$dst_node bs=$blk_size count=$(($kernel_bytes/$blk_size)) \
					seek=${kernel_blk} conv=notrunc
				;;
			logo*)
				pnd dd if=$up_file of=$dst_node bs=$blk_size count=$(($logo_bytes/$blk_size)) \
					seek=${logo_blk} conv=notrunc
				;;
			esac
		else
			display "NO $file..."
		fi
	done
}

update_nand()
{
	if [ $up_type -ne 3 ];then
		return 0
	fi
	for file in $app_files
	do
		cmtd=`cat /proc/mtd |grep $file`
		app_file=$folder/${file}.tar
		if [ ! -z "$cmtd" ] && [ -f $app_file ];then
				mtdnr=`echo ${cmtd}|cut -d' ' -f1|cut -c4`
				pnd $up_dir/flash_eraseall /dev/mtd$mtdnr
				pnd mount -t yaffs2 /dev/mtdblock$mtdnr $mnt_dir
				if [ $? -eq 0 ];then
					display "Up $app_file,maybe a long time,please wait..."
					put2screen ${file}
					pnd tar xf $app_file -C $mnt_dir
					pnd umount /dev/mtdblock$mtdnr
				fi
		fi
	done
	put2screen "finish"	
	display "-------------------Finish update-------------------"
	exit 1
}
#main
trap 'display "catch a signal!!!";umount_ifany' INT TERM QUIT
dump_info $0 $*
umount_ifany $arch
update_nand
check_useable
check_part
do_fdisk
update_fs
update_bare

sync;sync;sync
put2screen "finish" 
print_mount
display "-------------------Finish update-------------------"



