#!/bin/bash
# 
# This Netwalker PC-Z1 recovery boot image download ustility is
# for console with root privilege on any modern Linux system.
# URL data etc. are based on version: 1.020 by Sharp recovery.sh 
#
# (c) Osamu Aoki osamu@debian.org, GPL 2.0+
#
# Usages:
#
# * Internal microSD card reader of Netwalker
# $ sudo ./spider-recovery
# 
# * USB microSD card reader on normal PC at /dev/sdc:
# $ sudo DEV=/dev/sdc ./spider-recovery
# 
# * USB microSD card reader on normal PC at /dev/sdc with local copies of 
#   image files at $(cwd):
# $ sudo DEV=/dev/sdc URL=local ./spider-recovery
# 
#
# You can use last part of "dmesg" to identify device location for DEV.

#set -x
set -e

# Data taken from version: 1.020 by Sharp recovery.sh source

# minimum size needed to store the recovery system data
# This can be overriden by environment variables.
# Actual usage is just below 1.6GB
MSIZE=${MSIZE:-1921024}

# /dev/mmcblk0p1 is normally mounted to /media/disk on netwalker system
# if microSD card is inserted after boot.
# This can be overriden by environment variables.
MEDIADISK=${MEDIADISK:-/media/disk}

# directory to keep firmware
FIRMWARE="firmware"
# Binary kernel image in zImage format
ZIMAGE="zImage"
# Name of /boot
BOOT="boot"
# Name of /etc
ETC="etc"
# Local directory as this is started
LOCAL=$(pwd)

# Default URL to get binary images
# If set to null-string, use local copies
URL=${URL:-http://mit.sharp.co.jp/}

# About 80 MB of small filesystem for filesystem
URL1=$URL
FILE1="os.tar.bz2"

# About 2.1MB for kernel image
URL2=$URL
FILE2="zImage"

# About 975MB for ubi image (flash initialization?)
URL3=$URL
FILE3="ubi.img"

#######################################################################
# This is start of subroutin programs
#######################################################################

function confirm() {
	printf "%s" "$1"
	read x
	case "x$x" in
	x)
		return 0
		;;
	xy|xyes|xY|xYES|xYes)
		return 0
		;;
	xn|xno|xN|xNO|xNo)
		return 1
		;;
	esac
	return 1
}

# standard routines
function xecho() {
	case $1 in
	YN|yn|Yn)
		# print and confirm and exit
		if confirm    "$2 (Y/n):" >&2 ; then
			return 0
		else
			return 1
		fi
		;;
	confirm|prompt)
		# print and confirm
		confirm    "$2 (RETURN to continue):" >&2 || true
		return 0
		;;
	info)
		# print and go on ...
		printf "%s\n" "$2" >&2 || true
		return 0
		;;
	warn)
		# print and confirm
		confirm    ">WARN:   $2 (RETURN to continue):" >&2 || true
		return 0
		;;
	error)
		# print and confirm and exit
		printf "%s\n"    ">>ERROR: $2" >&2
		exit 1
		;;
	*)
		echo "BUGGY: xecho $1 $2" >&2
		exit 1
		;;
	esac
}

function xunmount(){
	# Some automounter might have mounted it.  unmount now.
	if mount -l | fgrep -q --color=never $1 ; then
		umount -l $1
	fi
}

function webget(){
	# this could be curl
	if [ "x$1" -ne "xlocal" ]; then
		wget --no-cache ${1}${2}
	else
		cp ${LOCAL}/${2} ${2}
	fi
	if [ $? -ne 0 ] ;then
		xecho error "failed to download from $1"
	fi
}

function xsfdisk(){
	# partition microSD <start>=0 <size>=all  <id>=(LINUX_NATIVE  (83))
	sfdisk -q $DEV -uM << EOF
0,,L
EOF

}

#######################################################################
#  Format microSD card
#######################################################################
function format_microsd(){
# Report device situation to user
xecho info "You will wipe out all $DEV (containing ${PART})."
xecho info "==========================================================================="
xecho info "Following devices are in use:"
mount -l | fgrep --color=never "/dev/" >&2 || true
if mount -l | fgrep -q --color=never $DEV ; then
	xecho error "Removable media $DEV should not be mounted."
fi
xecho info "==========================================================================="

# User confirmation
# Get last minutes confirmation to fdisk/mkfs $DEV
if ! xecho confirm "Formatting microSD.  All data in ${PART} on $DEV will be lost ..." ; then
	xecho error "We stop here. We are not maiking recovery microSD."
fi

# Some automounter might have mounted it.  unmount now.
sync
xunmount $PART

xecho info "Make only $PART partition on $DEV for Linux ext2."
xsfdisk

# Some automounter might have mounted it.  unmount now.
sync
xunmount $PART

xecho info "Make ext2 filesystem on $PART."
mke2fs $PART

# Some automounter might have mounted it.  unmount now.
sync
xunmount $PART

}

#######################################################################
#  Download recovery image to microSD
#######################################################################
function download_recovery_image(){
# make unused mount point for microSD card
MOUNTPOINT=$MEDIADISK
for COUNT in 0 1 2 3 4 5 6 7 8 9 "END"; do
	if  [ $COUNT = "END" ]; then
		xecho info "You may need to clean files $MEDIADISK-*."
		xecho error "failed to make mount point starting: $MEDIADISK"
	fi
	MOUNTPOINT=${MEDIADISK}-${COUNT}
	if [ ! -d $MOUNTPOINT ]; then
		break
	fi
done
mkdir -p $MOUNTPOINT

xecho info "mounting $PART at $MOUNTPOINT"
mount $PART $MOUNTPOINT

if [ $? -ne 0 ] ; then
	umount -l $PART
	xecho error "Can not mount $PART on $MOUNTPOINT."
fi

# cd into mount point of microSD device
cd $MOUNTPOINT
xecho info "change directory from $LOCAL to $MOUNTPOINT"

# download os.tar.bz2
webget $URL1 $FILE1

# expand os.tar.bz2 at root of microSD partition1 (ext2)
tar xvfj $FILE1
	
if [ ! -d $FIRMWARE ] ; then
	mkdir -p $FIRMWARE
fi

cd $FIRMWARE
xecho info "change directory to $(pwd)"
if [ -e $FILE2 ] ; then
	rm -f $FILE2
fi
# download to zImage to /firmware/
webget $URL2 $FILE2

if [ -e $FILE3 ] ; then
	rm -f $FILE3
fi
# download ubi.img to /firmware/ 
webget $URL3 $FILE3
xecho info "download completed"

# back from $FIRMWARE to mount point of microSD
cd ..
xecho info "change directory to $(pwd)"

xecho info "copy $FILE2 in $FIRMWARE to $ZIMAGE in /$BOOT"
cp -fv $FIRMWARE/$FILE2 $MOUNTPOINT/$BOOT/$ZIMAGE
xecho info "$ZIMAGE copied to /$BOOT/$ZIMAGE."

xecho info "==========================================================================="
if [ $MACHINE != "netwalker" ] && xecho yn "Will you skip /etc/rcS.d/S30checkfs.sh to avoid mount issue?" ;then
	rm -f $MOUNTPOINT/etc/rcS.d/S30checkfs.sh
	xecho info "\"/etc/rcS.d/S30checkfs.sh\" removed from rescue image."
fi
xecho info "==========================================================================="
if ! xecho yn "Will you keep recover script." ;then
	rm -f $MOUNTPOINT/etc/rc2.d/S01upfirm
	xecho info "\"/etc/rc2.d/S01upfirm\" removed from rescue image."
fi
xecho info "==========================================================================="

cd $LOCAL
xecho info "change directory to $(pwd)"

xecho info "sync devices before unmounting."
sync

xecho info "umounting microSD card partition: $PART"
umount -l $PART

xecho info "removing mount point: $MOUNTPOINT"
rm -rf $MOUNTPOINT

# Complete
xecho info "Recovery microSD has been created."
}

#######################################################################
# This is start of main program
#######################################################################

# Sanity check: being root
if [ "$(id -u)" != 0 ]; then
	xecho error "You have to have root privilege."
fi

# quick guess for machine architecture
if [ `uname -m` = "armv7l" ] ; then
	xecho info "You are on armv7l and we assume you are running this under netwalker."
	MACHINE="netwalker"
else
	xecho info "You are not on armv7l and we assume you are running this not under netwalker."
	MACHINE=`uname -m`
fi

xecho prompt "Please insert microSD card now if it has not done so."
# Some automounter might have mounted it.  unmount now.
sleep 1

if [ $MACHINE = "netwalker" ]; then
	# /dev/mmcblk0 for netwalker internal micro SD"
	# This can be overriden by environment variables.
	DEV=${DEV:-/dev/mmcblk0}
	PART=${PART:-/dev/mmcblk0p1}
else
	# This is used if this microSD card is attached via USB card reader
	# your main system HDD is on /dev/sda
	# The first USB connected drive will be wiped.
	# This can be overriden by environment variables
	# search first sd? device except sda
	for COUNT in b c d e f g h i j k l "END"; do
		if  [ $COUNT = "END" ]; then
			xecho error "failed to find formattable device."
		fi
		DEV0=/dev/sd${COUNT}
		if fdisk -l /dev/sd${COUNT} | fgrep  --color=never cylinders >/dev/null ; then
			DEV0=/dev/sd${COUNT}
			break
		fi
	done
	DEV=${DEV:-$DEV0}
	PART=${PART:-${DEV}1}
fi

sync
xunmount $PART
if xecho yn "Will you format mocroSD card on ${DEV}?" ;then
	format_microsd
fi

if xecho yn "Will you download recovery image onto mocroSD card on ${DEV}?" ;then
	download_recovery_image
fi

if xecho yn "Will you check filesystem state of recovery image?" ;then
	tune2fs -l $PART
fi

# Instruction
xecho info "You need to do the following from NetWalker."
xecho info "==========================================================================="
xecho info "1. Insert this microSD to NetWalker."
xecho info "2. Restart NetWalker while pressing 2 buttons even after you see Sharp logo."
xecho info "==========================================================================="

