#!/bin/sh
# Copyright (C) 2007-2008 PeerTV Inc.
# All rights reserved.
#
# @file scroll.sh
# @brief Shell script which make upgrade from USB DOK. 
#        When HD Format option is selected from TV-Setup/Web Management the
#        HD Format is performed prior to upgrade itself.
#
# @notes The script is also used to fix the following issues if required:
#        * Network EEPROM fix for PeerStation based on EM8622 chip.
#        * WIFI Card Comex fix for PeerStation based on EM8622 chip.
#
# @author Baruch Shapira <baruch@peertv.com>
# @date 23-07-2008

# Turn on debug mode
set -x

. /etc/profile

appsbin_path=$USB_PATH/utils


# Enabling reset button
echo "ready" > /proc/upgrade/pushb

# generating temporary waiting for reboot script to save space - /tmp/upg_wait_reboot.sh set_error_flag
echo "#!/bin/sh" > /tmp/upg_wait_reboot.sh
echo "set -x" >> /tmp/upg_wait_reboot.sh
echo "sleep 2" >> /tmp/upg_wait_reboot.sh
echo "echo \"Remove dok and wait for reboot\"" >> /tmp/upg_wait_reboot.sh
echo "echo \"DONEUSB\" > /tmp/usbd_action" >> /tmp/upg_wait_reboot.sh
echo "while [ 0 = 0 ]; do" >> /tmp/upg_wait_reboot.sh
echo "   grep usb-stor-devices /proc/hardware > /dev/null 2>&1" >> /tmp/upg_wait_reboot.sh
echo "   if [ \$? -ne 0 ]; then" >> /tmp/upg_wait_reboot.sh
echo "      /sbin/reboot" >> /tmp/upg_wait_reboot.sh
echo "   fi" >> /tmp/upg_wait_reboot.sh
echo "   sleep 5" >> /tmp/upg_wait_reboot.sh
echo "done" >> /tmp/upg_wait_reboot.sh
chmod +x /tmp/upg_wait_reboot.sh

if [ -z "$HDD_DEVICE" ]; then
   if [ -e /proc/ide/hda ]; then
      HDD_DEVICE=/dev/hda
   elif  [ -e /proc/ide/hdb ]; then
      HDD_DEVICE=/dev/hdb
   else
      HDD_DEVICE=""
   fi
fi

# detect internal DOK if exists
if [ -x /sbin/sysdok.sh ]; then
   sh /sbin/sysdok.sh
   
   if [ -x /tmp/sysdok ]; then
      . /tmp/sysdok
      t=0; to=10
      while [ ! \( -f /tmp/sysdok.p1 -a -f /tmp/sysdok.p2 -a -f /tmp/sysdok.p3 \) -a $t -lt $to ]; do
         sleep 1
         t=`expr $t + 1`
      done
      mkdir -p $MNT_PATH $USR_PATH $EXT_SYS
   fi
fi

# internal DOK uses differen partition table and block size than HDD
# distinguishing between DOK/HDD to Flash only PeerStation
echo "HDD_DEVICE: $HDD_DEVICE"
if [ -x /tmp/sysdok ]; then
   hd_found=1
   std_partitions=std_partitions_dok
   block_size=4096
   inodes_num=2097152
elif [ ! -z "$HDD_DEVICE" ]; then
   hd_found=1
   std_partitions=std_partitions
   block_size=4096
   inodes_num=0
else
   hd_found=0
fi

# Debug
cat /proc/hardware
mount

if [ "$SIGMA22" = "YES" ]; then
   ### Network eeprom fix - Start
   iobase=`grep 10ec8139 /proc/bus/pci/devices | cut -f 4`

   if [ -n "$iobase" ]; then
      insmod $appsbin_path/8139too-eeprom.o iobase=0x$iobase
   fi
   ### Network eeprom fix - End

   ### Wifi Comex fix - Start
   ath_tool=$appsbin_path/ath_info
   if [ -f /proc/bus/pci/00/03.0 -a -f $ath_tool ]; then
      subvid=`hexdump /proc/bus/pci/00/03.0 | egrep "^0+20 " | cut -d ' ' -f 8`
      subdid=`hexdump /proc/bus/pci/00/03.0 | egrep "^0+20 " | cut -d ' ' -f 9`
      if [ "$subvid" = "168c" ]; then
         modprobe wlan_scan_sta
         modprobe wlan_wep
         modprobe ath_rate_sample
         modprobe ath_pci
         iomem=`cat /proc/iomem | grep ' ath$' | cut -d '-' -f 1`
         if [ -n "$iomem" ]; then
            ifconfig ath0 up
            sleep 3
            regdomain=`$ath_tool $iomem | grep "Regulatory Domain:" | sed -r 's/.*:[ \t]+//g'`
            if [ "$regdomain" != "0x60" ]; then
               $ath_tool -f -w $iomem regdomain 0x60
            else
               echo regdomain is already set
            fi
         fi
         ifconfig ath0 down
         rmmod ath_pci
         rmmod ath_rate_sample
         rmmod wlan_wep
         rmmod wlan_scan_sta
         rmmod ath_hal
         rmmod wlan
      fi
   fi
   ### Wifi Comex fix - End
fi
 
upgrade_package_file_name=upgrade-6.3.59TIus_sig22.tar.gz
upgrade_eng_path=/bin/upgrade
export PATH=$PATH:$upgrade_eng_path
alt_browser=0
fatal_error=0

# check whether all required binary tools are found on USB DOK
# if some executable is missing - exit
MIN_DOK_FILES_LIST="mke2fs e2fsck osdbuf_control sfdisk md5deep $std_partitions"
for item in $MIN_DOK_FILES_LIST ; 
do
   if [ -f $appsbin_path/$item ]; then
      echo "Utility $item found, OK" 
   else
      echo "ERROR: $item binary not found!"
      exit 0
   fi
done

if [ "$SIGMA22" = "YES" ]; then
   insmod llad.o
   insmod em8xxx.o
   insmod mambolfb.o
fi

# must be read before mounting cfgfs !
if [ "$SIGMA34" = "YES" ]; then
   rootfs_mrua_version=`cat /etc/mipsutils_version`
else
   rootfs_mrua_version=`cat /etc/armutils_version`
fi

# userfs integrity test
$upgrade_eng_path/chkufs.sh
ufs_flash_res=$?
ufs_ext_res=1
if [ $ufs_flash_res -ne 0 -a $hd_found -eq 1 ]; then
   tmp_system=/tmp/tmp_system
   mkdir $tmp_system
   mount -t ext3 -o data=journal,commit=1,rw $SYS_BLKDEV $tmp_system
   cp -rf $tmp_system/userfs /tmp
   sync
   umount $tmp_system
   rm $tmp_system
   test -d /tmp/userfs/appsbin
   ufs_ext_res=$?
fi

if [ $ufs_flash_res -eq 0 -o $ufs_ext_res -eq 0 ]; then
   # mounting SYSTEM_PATH
   if [ $ufs_flash_res = 0 ]; then
      mtd_block_num=`cat /proc/upgrade/userfs_num`
      mount -t cramfs -r /dev/mtdblock$mtd_block_num $SYSTEM_PATH
   else
      mount -o nolock /tmp/userfs $SYSTEM_PATH
   fi
   
   # must be read before mounting cfgfs !
   if [ "$SIGMA34" = "YES" ]; then
      userfs_mrua_version=`cat /system/mipsutils_version`
   else
      userfs_mrua_version=`cat /system/armutils_version`
   fi

   # Verifying MRUA version rootfs/userfs compatibility
   if [ "$rootfs_mrua_version" != "$userfs_mrua_version" ]; then
      echo "MRUA ver. of rootfs&userfs differ"
      echo "MRUA ver. of rootfs&userfs differ" > /tmp/usbd_osd
      alt_browser=1
   fi
else
   alt_browser=1
   echo "USERFS is damaged !"
fi

# Initialize the display according to video display mode (/proc/upgrade/vmode)
displaysettings.upg

if [ $alt_browser -eq 0 ]; then
   # Loading browser
   makesettings.upg
else
   # Loading alt. browser
   $upgrade_eng_path/ascii_browser 0 -X 50 -Y 50 -S 2 -F 255,255,255,255 -B 0,0,255,255 -T 1 $upgrade_eng_path/font.psf " " &
fi

# getting the upgrade code
last_error_code=`cat /proc/upgrade/pending`
echo 0 > /proc/upgrade/pending
echo 0 > /proc/upgrade/flags1
echo 0 > /proc/upgrade/flags2
echo 0 > /tmp/usbd_status_num
echo 0 > /tmp/usbd_status_num_max
echo 0 > /tmp/usbd_pb_total
echo 0 > /tmp/usbd_pb_cur

# calculating overall stages number for different scenarios
if [ "$SIGMA22" = "YES" ]; then
   # Operations - Upgrade flash + Upgrade HD data, system and ufs partitions
   # Flash - Unzip (x1) Untar+Erase+Write+Verify (x5) Done (x1)     = 22
   # Upgrade HD System - Check (x1) Unzip (x1) Untar (x1) Done (x1) = 4
   # Upgrade HD Data   - Check (x1) Untar (x1) Done (x1)            = 3
   # Spare                                                                                                   = 2
   tmp_upgrade_with_hd_stages=31
   # Operations - Upgrade flash
   # Flash - Unzip (x1) Untar+Erase+Write+Verify (x5) Done (x1)     = 22
   tmp_upgrade_without_hd_stages=22
   # Operations - Check all the partitions on the HDD/DOK
   # Check partitions - Check (x4)                                                = 4
   tmp_hd_check_stages=4
   # Operations - Format HDD + Upgrade flash + Upgrade HD data, system and ufs partitions
   # Format HDD - Format (x4)                                                     = 4
   # Flash - Unzip (x1) Untar+Erase+Write+Verify (x5) Done (x1)                   = 22
   # Upgrade HD System - Check (x1) Unzip (x1) Untar (x1) Done (x1)               = 4
   # Upgrade HD Data   - Check (x1) Untar (x1) Done (x1)                          = 3
   # Spare                                                                                                   = 2
   tmp_hd_format_stages=35
else
   # Operations - Upgrade flash + Upgrade HD data, system and ufs partitions
   # Flash - Unzip (x1) Untar+Erase+Write+Verify (x6) Done (x1)                   = 26
   # Upgrade HD System - Check (x1) Unzip (x1) Untar (x1) Done (x1)               = 4
   # Upgrade HD Data   - Check (x1) Untar (x1) Done (x1)                          = 3
   # Spare                                                                                                   = 2
   tmp_upgrade_with_hd_stages=35
   # Operations - Upgrade flash + Upgrade HD data and system partitions
   # Flash - Unzip (x1) Untar+Erase+Write+Verify (x6) Done (x1)                   = 26
   tmp_upgrade_without_hd_stages=26
   # Operations - Check all the partitions on the HDD/DOK
   # Check partitions - Check (x4)                                                = 4
   tmp_hd_check_stages=4
   # Operations - Format HDD  Upgrade flash + Upgrade HD data, system and ufs partitions
   # Format HDD - Format (x4)                                                     = 4
   # Flash - Unzip (x1) Untar+Erase+Write+Verify (x5) Done (x1)                   = 26
   # Upgrade HD System - Check (x1) Unzip (x1) Untar (x1) Done (x1)               = 4
   # Upgrade HD Data   - Check (x1) Untar (x1) Done (x1)                          = 3
   # Spare                                                                                                   = 2
   tmp_hd_format_stages=39
fi

# test whether executables in DOK are runnable by this platform
$appsbin_path/osdbuf_control -i
if [ $? -eq 2 ]; then
    # Requesting reboot
    echo "DOK binaries execution failure" > /tmp/usbd_osd
    echo "ERROR" > /tmp/usbd_action
    
	/tmp/upg_wait_reboot.sh
fi

# Format HD before upgrade if requested
if  [ $last_error_code = 250 ]; then
   echo "Formatting HD"
   if [ $hd_found -eq 0 ]; then
      # Requesting reboot
      echo "Locating HDD" > /tmp/usbd_osd
      echo "-126|HDD not found - Replace the HDD" > /tmp/usbd_error
      echo "ERROR" > /tmp/usbd_action
                 
      /tmp/upg_wait_reboot.sh
   fi

   echo  "DISK_FORMAT" > /tmp/usbd_action
   echo $tmp_hd_format_stages > /tmp/usbd_status_num_max

   sleep 2;
   
   $appsbin_path/sfdisk --force -uM $HDD_DEVICE < $appsbin_path/$std_partitions
   sleep 1;
   mount
   umount $MNT_BLKDEV
   if [ $inodes_num -eq 0 ]; then
      $appsbin_path/mke2fs -z -j -b $block_size $MNT_BLKDEV
   else
      $appsbin_path/mke2fs -z -j -b $block_size -i $inodes_num $MNT_BLKDEV
   fi

   if [ "`cat /tmp/usbd_action`" = "DISK_FORMAT_ERROR" ]; then
      /tmp/upg_wait_reboot.sh
   fi
   
   umount $SYS_BLKDEV
   $appsbin_path/mke2fs -z -j $SYS_BLKDEV
   if [ "`cat /tmp/usbd_action`" = "DISK_FORMAT_ERROR" ]; then
      /tmp/upg_wait_reboot.sh
   fi

   umount $PRV_BLKDEV
   $appsbin_path/mke2fs -z -j $PRV_BLKDEV
   if [ "`cat /tmp/usbd_action`" = "DISK_FORMAT_ERROR" ]; then
      /tmp/upg_wait_reboot.sh
   fi
   
   #rm /tmp/usbd_status_num_max
   echo  "RUNNING" > /tmp/usbd_action
# Mounting HD if any
elif [ $hd_found -eq 1 ]; then
   hd_dev_1=`$appsbin_path/sfdisk "$HDD_DEVICE"1 -s`
   if [ $? = 0 ]; then 
      hd_dev_1=`expr $hd_dev_1 '/' 1024`
   else
      hd_dev_1=0
   fi
   hd_dev_2=`$appsbin_path/sfdisk "$HDD_DEVICE"2 -s`
   if [ $? = 0 ]; then
      hd_dev_2=`expr $hd_dev_2 '/' 1024`
   else
      hd_dev_2=0
   fi
   hd_dev_3=`$appsbin_path/sfdisk "$HDD_DEVICE"3 -s`
   if [ $? = 0 ]; then 
      hd_dev_3=`expr $hd_dev_3 '/' 1024`
   else
      hd_dev_3=0
   fi
   hd_dev_4=`$appsbin_path/sfdisk "$HDD_DEVICE"4 -s`
   if [ $? = 0 ]; then
      hd_dev_4=`expr $hd_dev_4 '/' 1024`
   else
      hd_dev_4=0
   fi

   size_offset_mb=100

   # HD exists - checking partitioning
   par_num=1
   par_ok=1
   for x in `cat $appsbin_path/$std_partitions | cut -f 2 -d ','`
   do
	check=0
	if [ "$x" != ";" -a "$x" != "EOF" ]; then
		case $par_num in
			1)	par_size=$hd_dev_1;;
			2)	par_size=$hd_dev_2;;
			3)	par_size=$hd_dev_3;;
			4)	par_size=$hd_dev_4;;
			*)	check=1;;
		esac 
		
		# Checking whether partition size is within rang
		if [ "$par_size" -le "`expr $x + $size_offset_mb`" -a  "$par_size" -ge "`expr $x - $size_offset_mb`" ]; then
			check=1
		fi
		
		if [ $check -eq 1 ]; then
		   echo "Partition $par_num geometry is correct"
		else
		   echo "Partition $par_num geometry is wrong"
		   par_ok=0
		fi 
	fi

        # Checking whether it's Linux Partition
        par_id=`$appsbin_path/sfdisk $HDD_DEVICE -d | grep "$HDD_DEVICE"$par_num | cut -d '=' -f 4`
        if [ "$par_id" != "83" ]; then
           echo "Partition $par_num geometry is wrong"
           par_ok=0
        fi

	par_num=`expr $par_num + 1`
   done

   # If bad partitioning was found
   if [ $par_ok = 0 ]; then
      echo "Bad partitioning"

      echo  "DISK_FORMAT" > /tmp/usbd_action
      echo $tmp_hd_format_stages > /tmp/usbd_status_num_max

      sleep 1;
      $appsbin_path/sfdisk --force -uM $HDD_DEVICE < $appsbin_path/$std_partitions
      sleep 1;
      mount
      umount $MNT_BLKDEV
      if [ $inodes_num -eq 0 ]; then
         $appsbin_path/mke2fs -z -j -b $block_size $MNT_BLKDEV
      else
         $appsbin_path/mke2fs -z -j -b $block_size -i $inodes_num $MNT_BLKDEV
      fi
	
      if [ "`cat /tmp/usbd_action`" = "DISK_FORMAT_ERROR" ]; then
         /tmp/upg_wait_reboot.sh
	  fi

         umount $SYS_BLKDEV 
         $appsbin_path/mke2fs -z -j $SYS_BLKDEV
         if [ "`cat /tmp/usbd_action`" = "DISK_FORMAT_ERROR" ]; then
            /tmp/upg_wait_reboot.sh
	     fi
                
         umount $PRV_BLKDEV 
         $appsbin_path/mke2fs -z -j $PRV_BLKDEV
	 if [ "`cat /tmp/usbd_action`" = "DISK_FORMAT_ERROR" ]; then
        /tmp/upg_wait_reboot.sh
	 fi
	 #rm /tmp/usbd_status_num_max
   else
	#simple upgrade with valid Hard Disk
	echo $tmp_upgrade_with_hd_stages > /tmp/usbd_status_num_max
   fi

   if [ -z "$SYS_BLKDEV" -o -z "$MNT_BLKDEV" ]; then 
   	SYS_BLKDEV=$HDD_DEVICE3
	MNT_BLKDEV=$HDD_DEVICE1
   fi
else
	# simple upgrade is initiated without Hard Disk
	echo $tmp_upgrade_without_hd_stages > /tmp/usbd_status_num_max
fi

sleep 2

# Finding last error code
last_error_code=`cat /proc/upgrade/pending`
if [ $last_error_code -ge 250 -o $last_error_code = 0 ]; then
   echo "Upgrade started !"
else
   # Recovery
   echo "Upgrade was interrupted - restoring !"
   echo "Last upgrade aborted with ($last_error_code)" > /tmp/usbd_error
fi

# Initiating upgrade
$upgrade_eng_path/store_settings.sh store

$upgrade_eng_path/upgrade_eng -s $USB_PATH/$upgrade_package_file_name -v 5
if [ $? = 0 ] ; then
   if [ ! -e back_to_defaults ]; then
      if [ ! -e back_to_defaults ]; then 
		$upgrade_eng_path/store_settings.sh ret; 
	fi
   else
      # Reset Video Display Mode control in EEPROM
      echo 0 > /proc/upgrade/vmode
   fi
else
   echo "Upgrade HD FAILED!"
   echo "ERROR" > /tmp/usbd_action
   /tmp/upg_wait_reboot.sh
fi

if [ $hd_found -eq 1 ]; then
   $upgrade_eng_path/upgrade_hd.sh $USB_PATH/$upgrade_package_file_name $upgrade_eng_path 
   if [ $? != 0 ] ; then
      echo "Upgrade HD FAILED!"
      echo "ERROR" > /tmp/usbd_action
      /tmp/upg_wait_reboot.sh
   fi
fi

# Requesting reboot
echo 100 > /tmp/usbd_pb_total
echo 100 > /tmp/usbd_pb_cur

cat /proc/hardware
/tmp/upg_wait_reboot.sh