#!/bin/sh

backlights_full()
{
    # Turn LCD backlights full on
	echo 0 > /sys/class/pwm/pwmchip2/export
	echo 100000 > /sys/class/pwm/pwmchip2/pwm0/period
	echo 1 > /sys/class/pwm/pwmchip2/pwm0/enable
	echo 100000 > /sys/class/pwm/pwmchip2/pwm0/duty_cycle
}

setup_usb_eject_script()
{
    # Create USB stick unplug script to flash backlights until it is removed 
    echo "#!/bin/sh" > /media/usbremovalwait.sh
    echo "exec 1>/dev/ttymxc0" >> /media/usbremovalwait.sh
    echo "exec 2>/dev/ttymxc0" >> /media/usbremovalwait.sh                           
    echo "while [ -d \"${USBROOTPATH}\" ]; do" >> /media/usbremovalwait.sh
    echo "  echo 100000 > /sys/class/pwm/pwmchip2/pwm0/duty_cycle" >> /media/usbremovalwait.sh  
    echo "  sleep 1" >> /media/usbremovalwait.sh
    echo "  echo 10000 > /sys/class/pwm/pwmchip2/pwm0/duty_cycle" >> /media/usbremovalwait.sh  
    echo "  sleep 1" >> /media/usbremovalwait.sh
    echo "done" >> /media/usbremovalwait.sh
    echo "echo \"Rebooting...\"" >> /media/usbremovalwait.sh 
    echo "reboot" >> /media/usbremovalwait.sh
    # Make it executable and run it
    chmod 775 /media/usbremovalwait.sh
    /media/usbremovalwait.sh &
}

# Successful update
exit_success()
{
    fbv -s 1 ${USBROOTPATH}/recovery/bitmaps/${PRODUCTID}/recoveryupdatesucceeded.png
    echo SUCCESSFUL UPDATE!
    
    setup_usb_eject_script
    
    exit 0
}

# Error during update
exit_error()
{
    fbv -s 1 ${USBROOTPATH}/recovery/bitmaps/${PRODUCTID}/recoveryupdateerror.png
    echo ERROR $1 DURING UPDATE!

    setup_usb_eject_script
    
    exit $1
}

display_updating()
{
    fbv -s 1 ${USBROOTPATH}/recovery/bitmaps/${PRODUCTID}/recoveryupdating.png
}

display_rebooting_to_update()
{
    fbv -s 1 ${USBROOTPATH}/recovery/bitmaps/${PRODUCTID}/recoveryrebooting.png
}

read_settings()
{
    # Set default settings
    APPPARTSIZEMB=${APPPARTSIZEDEFAULTMB}
    KEEPOLDDATA="N"
    RESTOREOLDDATA="N"

    echo "Extracting settings.sh to /tmp..."
    cd /tmp
    tar jxf ${USBROOTPATH}/root/root.tar.bz2 app/bin/settings.sh
    chmod 755 /tmp/app/bin/settings.sh
    # and import the settings (the above defaults may get overriden)
    source /tmp/app/bin/settings.sh
    rm -rf /tmp/app
}

# Display message and reboot to continue update
exit_and_reboot_to_continue_update()
{
    # Tell user we are rebooting to updpate
    display_rebooting_to_update
    
    # Wait for a couple of seconds 
    sleep 2
    
    # and reboot
    reboot
    
    # Get out of script        
    exit 0
}

# Check we have all the firmware we require
firmware_validate()
{
    echo Firmware: Validating...

    # Does the firmware directory for exist?
    if [ ! -d ${USBROOTPATH}/firmware ]; then
        exit_error 100
    fi

    # Check we have all the required files
    FIRMWAREFILES="UBOOTVERSION KERNELVERSION ROOTFSVERSION u-boot.imx rootfs.tar.bz2 uImage ${PRODUCTID}.dtbu"
    for FIRMWAREFILE in ${FIRMWAREFILES}
    do
        if [ ! -f ${USBROOTPATH}/firmware/${FIRMWAREFILE} ]; then
            echo "Firmware: ${USBROOTPATH}/firmware/${FIRMWAREFILE} not found!"
            exit_error 101
        fi
    done
}

# Update u-boot if required
# Returns 1 if u-boot was updated, 0 if it wasnt
uboot_update_if_required()
{
    # Get version of U-Boot and update if we need to
    UBOOTVER=$(fw_printenv -n version)
    NEWUBOOTVER=$(cat ${USBROOTPATH}/firmware/UBOOTVERSION)
    if [ "${UBOOTVER}" != "${NEWUBOOTVER}" ]; then
        # Copy new u-boot to ramdisk (/tmp) and make sure it succeeded
        cp ${USBROOTPATH}/firmware/u-boot.imx /tmp
        if [ $? -eq 0 ]; then
            # We successfully have it in the ramdisk now. Do the update 
            echo "Bootloader: Updating to ${NEWUBOOTVER}..."
            flash_eraseall /dev/mtd0
            flash_eraseall /dev/mtd1
            # NOTE: kobs-ng needs debugfs and also needs to write a temportary file so move to /tmp
            mount -t debugfs debugfs /sys/kernel/debug
            cd /tmp
            kobs-ng init -x -v --chip_0_device_path=/dev/mtd0 /tmp/u-boot.imx
            # The default bootloader environment will check the USB so don't set the recovery flag
            return 1
        else
            echo "Bootloader: Error copying bootloader to ramdisk!"
            exit_error 102            
        fi
    else
        # u-boot was not updated. We need to reset the lcd_backlight_level to max!
        fw_setenv lcd_backlight_level 10000 
    fi

    echo "Bootloader: Already running ${NEWUBOOTVER}"
    return 0
}

# Returns 1 if firmware (Kernel or rootfs) need updating, 0 if they are up to date
# NOTE: This is only used in --arsmode
does_firmware_need_update()
{
    # Check running kernel version is up to date
    KERNELVER=$(uname -r)
    NEWKERNELVER=$(cat ${USBROOTPATH}/firmware/KERNELVERSION)
    if [ "$KERNELVER" != "$NEWKERNELVER" ]; then
        echo "Kernel: Needs updating from ${KERNELVER} to ${NEWKERNELVER}"
        return 1
    else
        echo "Kernel: Already running ${NEWKERNELVER}"
    fi
    
    # Check rootfs is up to date
    ROOTFSVER=$(cat /etc/VERSION)
    NEWROOTFSVER=$(cat $USBROOTPATH/firmware/ROOTFSVERSION)
    if [ "$ROOTFSVER" != "$NEWROOTFSVER" ]; then
        echo "RootFs: Needs updating from ${ROOTFSVER} to ${NEWROOTFSVER}"
        return 1
    else
        echo "RootFs: Already running ${NEWROOTFSVER}"
    fi

    # Update not required    
    return 0
}

# Update the firmware
firmware_update()
{
    echo "Firmware: Updating..."

    uboot_update_if_required
    
    # Update the kernel
    echo "Kernel: Updating..."
    flash_eraseall /dev/mtd2
    nandwrite -p /dev/mtd2 ${USBROOTPATH}/firmware/uImage
    
    # Update the kernel dtb
    echo "Kernel DTB: Updating..."
    flash_eraseall /dev/mtd3
    nandwrite -p /dev/mtd3 ${USBROOTPATH}/firmware/${PRODUCTID}.dtbu
    
    # Format the UBI partition and attach it
    echo "Formatting UBI..."
    ubiformat /dev/mtd5 --yes
    ubiattach /dev/ubi_ctrl -m 5 -d 0

	# Create all the ubi volumes
    echo "Creating UBI volumes..."
    ubimkvol /dev/ubi0 --name=rootfs --size=128MiB
    ubimkvol /dev/ubi0 --name=app --size=${APPPARTSIZEMB}MiB
    ubimkvol /dev/ubi0 --name=data --maxavsize
    
    # Mount and create rootfs volume
    echo "RootFs: Updating..."    
    mkdir -p /tmp/rootfs
    mount -t ubifs ubi0:rootfs /tmp/rootfs
    cd /tmp/rootfs
    tar jxf ${USBROOTPATH}/firmware/rootfs.tar.bz2
    cd /tmp
    sync
    umount /tmp/rootfs
    rm -rf /tmp/rootfs
}

# Check we have all the app files we require
app_validate()
{
    echo App: Validating...

    # Does the directory for the app exist?
    if [ ! -d ${USBROOTPATH}/root ]; then
        exit_error 200
    fi

    # Check we have all the required files
    APPFILES="root.tar.bz2"
    for APPFILE in ${APPFILES}
    do
        if [ ! -f ${USBROOTPATH}/root/${APPFILE} ]; then
            echo App: ${USBROOTPATH}/root/${APPFILE} not found!
            exit_error 201
        fi
    done
}

# Update the app
app_update()
{
    echo "App: Removing partitions..."
    ubirmvol /dev/ubi0 --name=data
    ubirmvol /dev/ubi0 --name=app
    
    echo "App: Creating partitions..."
    ubimkvol /dev/ubi0 --name=app --size=${APPPARTSIZEMB}MiB
    ubimkvol /dev/ubi0 --name=data --maxavsize
    
    echo "App: Mounting partitions..."
    mkdir -p /tmp/root/app
    mount -t ubifs ubi0:app /tmp/root/app
    mkdir -p /tmp/root/app/data
    mount -t ubifs ubi0:data /tmp/root/app/data

#    restore_data

    echo "App: Updating..."
    cd /tmp/root
    tar jxf ${USBROOTPATH}/root/root.tar.bz2
    
    # Permissions
    chown -R 0:0 /tmp/root/*
    chmod -R 755 /tmp/root/*

    # Copy etc overlay on to /etc
	if [ ${ARSMODE} -eq 1 ]; then
		# Running from NAND so /etc is really /etc (not initramfs!)
		mount -o remount,rw /
		cp -ar /tmp/root/* /


		#cp -ar /tmp/app/etc/* /etc/
		# Adding usr/ for the fonts			
		#cp -a /tmp/app/usr/* /usr/
		mount -o remount,ro /
	else
		# Running from initramfs so need to mount real root in NAND
		mkdir -p /tmp/rootfs
		mount -t ubifs ubi0:rootfs /tmp/rootfs
		
		cp -ar /tmp/root/* /tmp/rootfs/

		#cp -ar /tmp/app/etc/* /tmp/rootfs/etc/
		# Adding usr/ for the fonts
		#cp -ar /tmp/app/usr/* /tmp/rootfs/usr/
		umount /tmp/rootfs
		rm -rf /tmp/rootfs
	fi
    
    sync

    echo "App: Updating splashscreen..."
    if [ -f "${USBROOTPATH}/app/splashscreen${PRODUCTID}.bmp" ]; then
        # Platform dependent splashscreen supplied outside root.tar.bz2
        SPLASHSCREEN=${USBROOTPATH}/app/splashscreen${PRODUCTID}.bmp
    elif [ -f "${USBROOTPATH}/app/splashscreen.bmp" ]; then
        # Generic splashscreen supplied outside app.tar.bz2
        SPLASHSCREEN=${USBROOTPATH}/app/splashscreen.bmp
    elif [ -f "/tmp/root/app/bin/splashscreen${PRODUCTID}.bmp" ]; then
        # Platform dependent splashscreen supplied inside app.tar.bz2
        SPLASHSCREEN=/tmp/root/app/bin/splashscreen${PRODUCTID}.bmp
    else
        # Generic splashscreen supplied inside app.tar.bz2
        SPLASHSCREEN=/tmp/root/app/bin/splashscreen.bmp
    fi
    mkimage -A arm -O linux -T kernel -C none -a 0 -e 0 -n "splashscreen" -d ${SPLASHSCREEN} /tmp/splashscreen.bmpu > /dev/null
    flash_eraseall /dev/mtd4
    nandwrite -p /dev/mtd4 /tmp/splashscreen.bmpu
    rm /tmp/splashscreen.bmpu

    # Dismount and detach UBI
    cd /tmp
    umount /tmp/root/app/data
    umount /tmp/root/app
    rm -rf /tmp/root
}

# Backup the data partition to RAMDISK if KEEPOLDDATA is set to "Y"
backup_data()
{
    # Only backup data if we need to
    if [ "${KEEPOLDDATA}" == "Y" ]; then
        # Do we need to attach UBI?
		if [ ${ARSMODE} -eq 0 ]; then
            # Attach to UBI
            ubiattach /dev/ubi_ctrl -m4 -d0
            if [ $? -ne 0 ]; then
                return
            fi
        fi
            
        # Mount the data partition
        mkdir -p /tmp/datatmp
        mount -t ubifs ubi0:data /tmp/datatmp
        if [ $? -eq 0 ]; then
            echo "Backing up data partition..."
            
            # Backup data to tar.bz2            
            cd /tmp/datatmp
            tar cjf /tmp/databackup.tar.bz2 .
            
            # Set flag to restore the data later on
            RESTOREOLDDATA="Y"
        fi
        
        rm -rf /tmp/datatmp

        # Do we need to dettach UBI?
		if [ ${ARSMODE} -eq 0 ]; then
            # Detach to UBI
            ubidetach -m4
        fi
    fi
}

# Restore the data we previously saved in backup_data
restore_data()
{
    # Only restore data if we need to
    if [ "${RESTOREOLDDATA}" == "Y" ]; then
        echo "Restoring data partition..."
        
        cd /tmp/app/data
        tar jxf /tmp/databackup.tar.bz2
        cd /tmp   
        sync
    fi        
}

#Check is this firmware is compatible with this device
anti_brick_check()
{
    # Get the product id and serial from OTP
    PRODUCTID=$(printf "%d" $(cat /sys/fsl_otp/HW_OCOTP_GP1))

    # Get the software update targetNumber from the info.xml
    targetNumber=-1
    if [ -f ${USBROOTPATH}/info.xml ]; then
    	targetNumber=$(sed -n 's/.*<targetNumber>\(.*\)<\/targetNumber>/\1/p' $USBROOTPATH/info.xml)
    	#targetNumber=$(xmllint --xpath "string(//softwareInfo/targetInfo/targetNumber)" $USBROOTPATH/info.xml)
    fi

    echo "Running on Product ${PRODUCTID}, firmware update target: ${targetNumber}"
    if [ ${PRODUCTID} -ne ${targetNumber} ]; then
	echo ERROR DURING UPDATE, INCOMPATIBLE SOFTWARE!

	fbv -s 1 ${USBROOTPATH}/recovery/bitmaps/recoveryIncompatibleFirmware.png
	setup_usb_eject_script    
	exit 300
    fi
}
###############################################################################

# Redirect output to debug serial
exec 1>/dev/ttymxc0
exec 2>/dev/ttymxc0

echo "Running recovery.sh..."

# Get the root pach of the USB
USBROOTPATH=$(cd "${0%/*}/../" && echo $PWD)

#Check firmware compatibility
anti_brick_check

# Save the parameter to detect if we are in ars mode
if [ "$1" == "--arsmode" ]; then
	# In ARSMODE. We are running on a NAND kernel, not the USB kernel used for updates
	ARSMODE=1
else
	# Not in ARSMODE. We are running on a USB kernel used for updates
	ARSMODE=0
fi

# The default APP partition size
APPPARTSIZEDEFAULTMB=128

backlights_full

display_updating

firmware_validate
app_validate

# Has this script been run from the .ars file (from a unit running from NAND rather than USB)?
if [ ${ARSMODE} -eq 1 ]; then
    echo "Running in --arsmode"
    
    # Update u-boot if required 
    uboot_update_if_required
    if [ $? -eq 1 ]; then
        # u-boot was updated. 
        # NOTE: No need to set usb_recovery flag as default environment already has this set! 
        exit_and_reboot_to_continue_update
    fi
    
    # Does the firmware need updating?
    does_firmware_need_update
    if [ $? -eq 1 ]; then
        # Yes. Make bootloader check USB stick on next reboot by setting the flag
        fw_setenv recovery 1

        exit_and_reboot_to_continue_update
    fi
    
    # Its only the app that needs updating        
    read_settings

    # Dismount UBI partitions and detach
    umount /app/data
    umount /app/event
    umount /app
    
#    backup_data
    
    app_update
    
    exit_success
else
    read_settings

#    backup_data
    
    firmware_update
    
    app_update
    
    exit_success
fi
