#!/bin/sh /etc/rc.common

START=09
FW=/www/ajax.zip
# recovery flags
MOUNT_FAILED_CONFIG=0
MOUNT_FAILED_CONFIG2=0
R_FLAG_MD5=0

# recovery process detection
RECOVER_FLAG_C1C2=c987217b78dd44056a9da58cf06b8c7a
RECOVER_FLAG_C1=3c0c50c8567663a26a1310bea1f96587
RECOVER_FLAG_C2=e8e31bf603f27c20cbe60814cc74c9e0
RECOVER_FLAG_EMPTY=a54f0041a9e15b050f25c463f1db7449

mount_config_part() {
	UBI_NUM=`ubiattach /dev/ubi_ctrl -m 7`
	RET=$?
	if [ $RET -eq 0 ]
	then
		UBI_NUM=`echo $UBI_NUM | awk '{print $4}'`
		UBI_NUM=${UBI_NUM%,}
		if [ -e /dev/ubi${UBI_NUM} ]
		then
			[ -e /dev/ubi${UBI_NUM}_0 ] || {
				echo "ubi volume not exist, format and make it."
				#ubiformat /dev/mtd3 -s 512 -O 512
				ubimkvol /dev/ubi${UBI_NUM} -N config -m
			}
			mount -t ubifs ubi${UBI_NUM}_0 /etc/persistence
			RET=$?
			if [ $RET -ne 0 ]
			then
				echo "[BOOT][ERROR] Config section mount failed."
				MOUNT_FAILED_CONFIG=1
			else
				MOUNT_FAILED_CONFIG=0
			fi
		else
			echo "[BOOT][ERROR] Ubi attach success but no ubi device."
			MOUNT_FAILED_CONFIG=1
		fi
	else
		echo "[BOOT][ERROR] Config section attach failed."
		MOUNT_FAILED_CONFIG=1
	fi
}

mount_config_part_jffs2() {
	mount -t jffs2 /dev/mtdblock7 /etc/persistence
	RET=$?
	if [ $RET -ne 0 ]
	then
		echo "[BOOT][ERROR] Config section mount failed(jffs2)."
		MOUNT_FAILED_CONFIG=1
	fi
}

mount_config2_part() {
	UBI_NUM=`ubiattach /dev/ubi_ctrl -m 6`
	RET=$?
	if [ $RET -eq 0 ]
	then
		UBI_NUM=`echo $UBI_NUM | awk '{print $4}'`
		UBI_NUM=${UBI_NUM%,}
		if [ -e /dev/ubi${UBI_NUM} ]
		then
			[ -e /dev/ubi${UBI_NUM}_0 ] || {
				echo "ubi volume not exist, format and make it."
				#ubiformat /dev/mtd3 -s 512 -O 512
				ubimkvol /dev/ubi${UBI_NUM} -N config2 -m
			}
			mount -t ubifs ubi${UBI_NUM}_0 /config_backup
			RET=$?
			if [ $RET -ne 0 ]
			then
				echo "[BOOT][ERROR] Config section mount failed."
				MOUNT_FAILED_CONFIG2=1
			else
				MOUNT_FAILED_CONFIG2=0
			fi
		else
			echo "[BOOT][ERROR] Ubi attach success but no ubi device."
			MOUNT_FAILED_CONFIG2=1
		fi
	else
		echo "[BOOT][ERROR] Config section attach failed."
		MOUNT_FAILED_CONFIG2=1
	fi
	
	[ -d /config_backup/config ] || {
		mkdir -p /config_backup/config
	}
	
	[ -d /config_backup/data ] || {
		mkdir -p /config_backup/data
	}
}

RETRY_CNT_FILE="/boot/try_data_ubi_recover"
data_ubi_recovery() {
	skip_unzip_web=1
	retry=0
	[ -e $RETRY_CNT_FILE ] && retry=`cat $RETRY_CNT_FILE`
	if [ "$retry" -lt 3 ]; then
		retry=$(($retry + 1))
		echo "$retry" > $RETRY_CNT_FILE
	else
		return
	fi

	umount /data > /dev/null 2>&1
	rm -rf /data
	ubidetach /dev/ubi_ctrl -m 3 > /dev/null 2>&1
	#ubiformat /dev/mtd3 -y #skip this seems OK
	mtd erase /dev/mtd3 > /dev/null 2>&1
	rs=`ubiattach /dev/ubi_ctrl -m 3`

	echo "$rs" > /dev/console
	echo "[/etc/init.d/draytek_flash_partition] reboot to data_ubi_recovery()" > /dev/console
	sync
	reboot
}

do_mount_data_part() {
	UBI_NUM=`ubiattach /dev/ubi_ctrl -m 3`
	RET=$?
	if [ $RET -eq 0 ]
	then
		UBI_NUM=`echo $UBI_NUM | awk '{print $4}'`
		UBI_NUM=${UBI_NUM%,}

		i=0
		while [ $i -lt 10 ]; do #wait 10 sec to attach ubi device
			[ -e /dev/ubi${UBI_NUM} ] && break
			i=$(($i + 1))
			echo "[BOOT][WARNING] no ubi device, wait $i sec." > /dev/console
			sleep 1
		done

		if [ -e /dev/ubi${UBI_NUM} ]
		then
			[ -e /dev/ubi${UBI_NUM}_0 ] || {
				echo "ubi volume not exist, format and make it."
				#ubiformat /dev/mtd3 -s 512 -O 512
				ubimkvol /dev/ubi${UBI_NUM} -N data -m
			}
			mount -t ubifs ubi${UBI_NUM}_0 /data
			RET=$?
			if [ $RET -ne 0 ]
			then
				echo "[BOOT][ERROR] Data section mount failed."
				data_ubi_recovery
			elif [ -e $RETRY_CNT_FILE ]; then
				#ubi status OK
				retry=`cat $RETRY_CNT_FILE`
				[ "$retry" -ne 0 ] && echo "0" > $RETRY_CNT_FILE
			fi
		else
			echo "[BOOT][ERROR] Data section ubi attach success but no ubi device."
			data_ubi_recovery
		fi
	else
		echo "[BOOT][ERROR] Data section attach failed."
		data_ubi_recovery
	fi
}

mount_data_part() {
	do_mount_data_part
	
	# check for old board, G33894
	df | grep data > /dev/null 2>&1
	RET_DF=$?
	if [ $RET_DF -eq 0 ]
	then
		DATA_SIZE_NUM=`df | head -n 6 | tail -n 1 | awk '{print $2}'`
		if [ $DATA_SIZE_NUM -lt 32768 ]
		then
			echo "[DFP] Upgrade data partition for early-released devices ..."
			umount /data
			ubidetach /dev/ubi_ctrl -m 3
			ubiformat /dev/mtd3 -y
			mtd erase /dev/mtd3
			reboot
			echo "[DFP] Reboot now"
		fi
	fi
	
	[ -d /data/config_backup ] || {
		mkdir -p /data/config_backup
	}

	[ -d /data/log ] || {
		mkdir -p /data/log
	}
	
	# apply change to flash
	sync
}

erase_recover_flag() {
	# erase recover flag
	nandwrite -s 131072 -p /dev/mtd1 /etc/mtd-recover-empty.bin
}

recovery_c1_and_c2() {
	# set erase flag
	if [ $R_FLAG_MD5 = $RECOVER_FLAG_EMPTY ]
	then
		nandwrite -s 131072 -p /dev/mtd1 /etc/mtd-recover-c1c2.bin
	fi
	
	# erase mtd6 and mtd7
	mtd erase config
	mtd erase config2
	
	# mount them
	mount_config_part
	if [ $MOUNT_FAILED_CONFIG -eq 1 ]
	then
		echo "[BOOT][ERROR] recovery_c1_and_c2: Config section mount failed."
		return 1
	fi
	
	mount_config2_part
	if [ $MOUNT_FAILED_CONFIG2 -eq 1 ]
	then
		echo "[BOOT][ERROR] recovery_c1_and_c2: Backup section mount failed."
		#return 1
		# do not return because it is still workable without backup configutation
	fi
	
	# copy default
	# don't have to copy, it will be done later in boot_post
	
	erase_recover_flag
}

recovery_c1() {
	# set erase flag
	if [ $R_FLAG_MD5 = $RECOVER_FLAG_EMPTY ]
	then
		nandwrite -s 131072 -p /dev/mtd1 /etc/mtd-recover-c1.bin
	fi
	
	# erase mtd7
	mtd erase config
	
	# mount
	mount_config_part
	if [ $MOUNT_FAILED_CONFIG -eq 1 ]
	then
		echo "[BOOT][ERROR] recovery_c1: Config section mount failed."
		return 1
	fi
	
	# recover primary configuration with backup
	rsync -a --delete /config_backup/* /etc/persistence/;sync
	
	erase_recover_flag
}

recovery_c2() {
	# set erase flag
	if [ $R_FLAG_MD5 = $RECOVER_FLAG_EMPTY ]
	then
		nandwrite -s 131072 -p /dev/mtd1 /etc/mtd-recover-c2.bin
	fi
	
	# erase mtd6
	mtd erase config2
	
	# mount
	mount_config2_part
	if [ $MOUNT_FAILED_CONFIG2 -eq 1 ]
	then
		echo "[BOOT][ERROR] recovery_c2: Backup section mount failed."
		#return 1
		# do not return because it is still workable without backup configutation
	fi
	
	# recover backup partition
	rsync -a --delete /etc/persistence/* /config_backup/;sync
	
	erase_recover_flag
}

do_cmp_and_rcvry() {
	FILE1=$1
	FILE2=$2
	#FILE_DEFAULT=$3
	
	if [ -f $FILE1 ]
	then
		if [ -f $FILE2 ]
		then
			# files both exist, diff them
			cmp $FILE1 $FILE2
			RET=$?
			if [ $RET -ne 0 ]
			then
				# something's wrong, which file is bad?
				#echo "checking different file $file"
				eval `ls -al $FILE1 | awk '{print "C1_LAST_CHAR_OFFSET="$5}'`
				C1_LAST_CHAR_OFFSET=`expr $C1_LAST_CHAR_OFFSET - 1`
				#echo "file size is $C1_LAST_CHAR_OFFSET"
				eval `hexdump -s $C1_LAST_CHAR_OFFSET -n 1 $FILE1 | head -n 1 | awk '{print "C1_LAST_CHAR=" $1}'`
				#echo "last char1 is $C1_LAST_CHAR"
				
				eval `ls -al $FILE2 | awk '{print "C2_LAST_CHAR_OFFSET="$5}'`
				C2_LAST_CHAR_OFFSET=`expr $C2_LAST_CHAR_OFFSET - 1`
				#echo "file size is $C2_LAST_CHAR_OFFSET"
				eval `hexdump -s $C2_LAST_CHAR_OFFSET -n 1 $FILE2 | head -n 1 | awk '{print "C2_LAST_CHAR=" $1}'`
				#echo "last char2 is $C2_LAST_CHAR"
				
				ZERO_HOLE=*
				if [ "$C1_LAST_CHAR" = "$ZERO_HOLE" ]
				then
					if [ "$C2_LAST_CHAR" = "$ZERO_HOLE" ]
					then
						echo "[BOOT][DFP] file $file is corrupt, and can not be recovered."
					else
						#echo "file $file recovered"
						rsync $FILE2 $FILE1
					fi
				else
					# whatever condition we sould do this
					rsync $FILE1 $FILE2
					#if [ "$C2_LAST_CHAR" = "$ZERO_HOLE" ]
					#then
					#	echo "c1 to c2"
					#	rsync $FILE1 $FILE2
					#else
					#	# both files are good, assume that power cut happened between 
					#	rsync $FILE1 $FILE2
					#fi
				fi
			fi
		else
			# backup lost, copy it
			rsync $FILE1 $FILE2
		fi
	else
		if [ -f $FILE2 ]
		then
			# primary config lost, copy it
			rsync $FILE2 $FILE1
		#else
			# both lost, use default
		#	rsync /etc/config-default/$file $FILE1
		#	rsync /etc/config-default/$file $FILE2
		fi
	fi
}

file_comparation_and_recovery() {
	for file in $(ls /etc/config-default); do
		do_cmp_and_rcvry /etc/persistence/config/$file /config_backup/config/$file
	done
	
	for file in $(ls /etc/data-default); do
		do_cmp_and_rcvry /etc/persistence/data/$file /config_backup/data/$file
	done
	
	# write data to flash media
	sync
}

check_different() {
	diff -r -q /config_backup/config/ /etc/persistence/config/ >/dev/null 2>&1
	RET=$?
	if [ $RET -ne 0 ]
	then
		echo "[BOOT][DFP] primary and backup configuration are different, try to recover."
		file_comparation_and_recovery
	fi
}

configuration_recovery() {
	# configuration recovery
	if [ $MOUNT_FAILED_CONFIG -eq 1 ]
	then
		if [ $MOUNT_FAILED_CONFIG2 -eq 1 ]
		then
			# both config and config2 are broken
			echo "[DFP] Both primary configuration and backup configuration are broken, try to recover with default settings"
			recovery_c1_and_c2
		else
			# config broken, use backup to recover it
			echo "[DFP] Primary configuration is broken, try to recover with backup configuration"
			recovery_c1
		fi
	else
		if [ $MOUNT_FAILED_CONFIG2 -eq 1 ]
		then
			# backup broken, use config to recover it
			echo "[DFP] Backup configuration is broken, try to recover with primary configuration"
			recovery_c2
		else
			# both partitions are good, check if they have something different
			check_different
		fi
	fi
}

test_and_mount_config() {
	# fs type detection
	#UBIFS_MD5=9d02262ac7b9cb33f0c3a8c2f9cf6edc
	JFFS2_MD5=5b268d227ff3b2c8cc5150096274bd64
	dd if=/dev/mtdblock7 of=/tmp/mtd-hdr.bin bs=2 count=1 >/dev/null 2>&1
	MTD_HDR_MD5=
		eval `md5sum /tmp/mtd-hdr.bin |
		awk '{
		print "MTD_HDR_MD5=" $1}'`

	# mount config partition
	if [ "$MTD_HDR_MD5" = "$JFFS2_MD5" ]
	then
		mount_config_part_jffs2
	else
		mount_config_part
	fi
}

WEB_CHECK_FILE="/boot/unzip_web_check"
mount_ajax(){
	web_check=0
	if [ -e $WEB_CHECK_FILE ]; then
		if [ -d /data/www ] ;then
			for f in $(ls /data/www/); do
				[ -e /www/$f ] || {
					web_check=1
					echo "[WEB ajax BOOT CHECK]: Link:$f in /www/ is gone, do recovery" >/dev/console
					break
				}
			done
		else
			web_check=1
		fi
	else
		echo "1" > $WEB_CHECK_FILE
		web_check=1
	fi

	[ $web_check -eq 1 ] && {
		rm -rf /data/www
		mkdir /data/www
		[ -e $FW ] && unzip -q -o $FW -d /data/www || echo "[WEB ajax BOOT CHECK]:FATAL ERROR: $FW is gone, can not unzip" >/dev/console
		for f in $(ls /data/www/); do
			[ -e /www/$f ] || ln -s /data/www/$f /www
			[ -e /data/www/$f/sc/skins/Enterprise/ ] && {
				ln -s /data/www/$f/sc/skins/Enterprise/ /data/www/$f/sc/skins/standard
			}
		done
	    #rm $FW #reserve this file for web recovery
	}
}
user_based_auth()
{
	ln -s  /www/cgi-bin /www/auth/cgi-bin 2>/dev/null
	ln -s  /www/images /www/auth/images 2>/dev/null
}

start() {
	# read recovery flag
#	dd if=/dev/mtdblock1 of=/tmp/mtd1-recover-flag.bin bs=4 count=1 skip=32768 >/dev/null 2>&1
#	R_FLAG_MD5=
#		eval `md5sum /tmp/mtd1-recover-flag.bin |
#		awk '{
#		print "R_FLAG_MD5=" $1}'`
	
	# continue recovery if flag is on	
#	case "$R_FLAG_MD5" in
#		"$RECOVER_FLAG_C1C2" )
#			recovery_c1_and_c2
#			;;
#		"$RECOVER_FLAG_C1" )
#			mount_config2_part
#			recovery_c1
#			;;
#		"$RECOVER_FLAG_C2" )
#			test_and_mount_config
#			recovery_c2
#			;;
#		* )
#			# test fs type and mount primary config partition
#			test_and_mount_config
#	
#			# mount backup config partition
#			mount_config2_part
#			;;
#	esac
	
	# recover config and backup if needed
#	configuration_recovery
	
	mount_config_part_jffs2
	
	# mount data partition
	skip_unzip_web=0
	mount_data_part #if error => set skip_unzip_web flag
	
	#Backup /www/ajax.zip to /data/ to support a restore mechanism when /www/ajax.zip is missed once
	if [ -e "/data/md5_ajax" ] ;then
		backup_md5sum=`cat /data/md5_ajax |cut -d' ' -f 1`
		if [ -e "/www/ajax.zip" ] ;then
			new_md5sum=`md5sum /www/ajax.zip |cut -d' ' -f 1`
		else
			new_md5sum=""
		fi
		#Update backup of ajax.zip to /data/
		if [ -n "$new_md5sum" ] ;then
			[ "$new_md5sum" != "$backup_md5sum" ] && {
				echo "[WEB ajax BOOT CHECK]:ajax (checksum diff), overwrite /www/ajax.zip to /data/www/ajax.zip" >/dev/console
				rm -f /data/ajax.zip /data/md5_ajax 2>/dev/null
				cp /www/ajax.zip /data/ >/dev/null 2>/dev/null
				md5sum /data/ajax.zip > /data/md5_ajax 2>/dev/null
			}
		else
			if [ -e "/data/ajax.zip" ] ;then
				echo "[WEB ajax BOOT CHECK]:WARNING: /www/ajax.zip is NOT FOUND! Restore old ajax from /data/ajax.zip to /www/" >/dev/console
				cp /data/ajax.zip /www/
			else
				echo "[WEB ajax BOOT CHECK]:FATAL ERROR: /www/ajax.zip and /data/ajax.zip are both missed... No method to recover, try upload firmware again" >/dev/console
			fi
		fi
	else
		#Create backup of ajax.zip to /data/
		echo "[WEB ajax BOOT CHECK]:Init backup of /www/ajax.zip to /data/" >/dev/console
		rm -f /data/ajax.zip 2>/dev/null
		cp /www/ajax.zip /data/ >/dev/null 2>/dev/null
		md5sum /data/ajax.zip > /data/md5_ajax 2>/dev/null
	fi
	
	[ $skip_unzip_web -eq 0 ] && mount_ajax
	
	user_based_auth
}
