#!/bin/sh

# Copyright 2017 Cumulus Networks, Inc.
# All rights reserved.

# This script is run *after* the root file system is mounted on
# ${rootmnt}.

PREREQ="cumulus-bottom"

prereqs()
{
	echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
	prereqs
	exit 0
	;;
esac

set -e

. /scripts/functions

stage_dir="${rootmnt}/var/lib/cumulus/installer"
uninstall_file="${stage_dir}/uninstall"

# x86_64 ONIE uninstall helper.  Performs operations that require a
# full chroot environment setup on ${rootmnt}.
x86_64_onie_uninstall_chroot() {
	# Currently there is nothing special to "uninstall" for Cumulus
	# Linux on x86_64.

	# If needed in the future, this would be the place to call
	# some platform specific uninstall functions.

	# Configure ONIE's GRUB to boot into uninstall mode
	chroot ${rootmnt} /usr/lib/cumulus/onie/onie-boot-mode -q -o uninstall

        if [ -d /sys/firmware/efi ] ; then
            # UEFI system
            modprobe efivars || true
            chroot ${rootmnt} /usr/lib/cumulus/uefi-boot-next ONIE
        else
            # Configure GRUB to boot into ONIE's GRUB
            chroot ${rootmnt} /usr/sbin/grub-reboot ONIE
        fi
}

# x86_64 uninstall post helper.  Performs operations on the block
# device after all the file systems are unmounted.  Only the ramdisk
# is in use at this time.
x86_64_onie_uninstall_post() {
	# Currently nothing to do on x86_64 in this stage

	# If needed in the future, this would be the place to call
	# some platform specific uninstall functions.

	true
}

# armel ONIE uninstall helper.  Performs operations that require a
# full chroot environment setup on ${rootmnt}.
armel_onie_uninstall_chroot() {
	# If needed in the future, this would be the place to call
	# some platform specific uninstall functions.

	# set u-boot env arg to run ONIE common uninstall.
	# Hide error messages on first try
	chroot ${rootmnt}  /usr/bin/fw_setenv -f onie_boot_reason uninstall 2>/dev/null
	if [ "$?" != 0  ];then
		# -f is deprecated in nw fw_setenv
		chroot ${rootmnt}  /usr/bin/fw_setenv onie_boot_reason uninstall
		if [ "$?" != 0  ];then
			echo "Error! Failed chroot ${rootmnt}  /usr/bin/fw_setenv onie_boot_reason uninstall"
			exit 1
		fi
	fi


}

# Erase a block device
#
# arg $1 - block device without the "/dev"
erase_block_device()
{
	device=$1

	dev_sz=$(blockdev --getsize64 $device)
	cur_sz=0
	count=0
	n_mb=8
	step=$(( $n_mb * 1024 * 1024 ))
	total=$(( $dev_sz + $step - 1 ))
	total=$(( $total / $step ))
	mb_sz=$(( $dev_sz / ( 1024 * 1024 ) ))
	printf "Erasing storage device: $device (${mb_sz}MB)\n"

	# Scribble random bytes over the partition data
	dd if=/dev/urandom of=/tmp/junk.bin bs=1M count=$n_mb > /dev/null 2>&1
	while [ $cur_sz -lt $dev_sz ] ; do
		dd if=/tmp/junk.bin of=$device bs=$step seek=$count > /dev/null 2>&1
		count=$(( $count + 1 ))
		cur_sz=$(( $step * $count ))
		printf "\r  Percent complete: %02u%%" $(( ($count * 100) / $total ))
	done
	printf "\n"

	printf "Erase complete.\n"
}

# armel uninstall post helper.  Performs operations on the block
# device after all the file systems are unmounted.  Only the ramdisk
# is in use at this time.
armel_onie_uninstall_post() {
	# For armel platforms we need to wipe the CL-BOOT and
	# CL-SYSTEM partitions as ONIE knows nothing about the block
	# storage device.

	for l in CL-BOOT CL-SYSTEM ; do
		dev=$(blkid -o device -t LABEL="$l")
		if [ -b "$dev" ] ; then
			erase_block_device "$dev"
		fi
	done

	# If needed in the future, this would be the place to call
	# some platform specific uninstall functions.
}


# Test for staged uninstall flag
if [ -r "${uninstall_file}" ] ; then

	echo "OS Uninstall Requested.  Configuring for OS uninstall ..."

	if [ "${readonly}" = "y" ]; then
		# remount read/write as we need to modify a few files
		mount -o remount,rw ${ROOT} ${rootmnt}
	fi

	# prevent this logic from possibly repeating
	rm -f ${uninstall_file}

	# Check for supported CPU architectures
	case "$(uname -m)" in
		x86_64|armv7l)
			;;
		*)
			echo "ERROR: unsupported CPU architecture: $(uname -m)"
			exit 1
	esac

	# mount /dev, /sys, /proc and /run into chroot environment as
	# GRUB and fw_setenv need all of these.
	mount -o nodev,noexec,nosuid -t proc proc ${rootmnt}/proc
	mount -o nodev,noexec,nosuid -t sysfs sysfs ${rootmnt}/sys
	mount --bind /dev ${rootmnt}/dev
	mount -o defaults,noatime,size=10M,mode=1777 -t tmpfs tmpfs ${rootmnt}/run
	mkdir -p ${rootmnt}/run/lock

	# Configure system to boot into ONIE, requiring the chroot
	# environment.  Depends on CPU architecture.
	case "$(uname -m)" in
		x86_64)
			x86_64_onie_uninstall_chroot
			;;
		armv7l)
			armel_onie_uninstall_chroot
			;;
		*)
			echo "ERROR: unsupported CPU architecture: $(uname -m)"
			exit 1
	esac

	# clean-up chroot environment and umount ${rootmnt}
	for m in ${rootmnt}/dev ${rootmnt}/sys ${rootmnt}/proc ${rootmnt}/run ${rootmnt} ; do
		umount $m
	done

	# Perform any final operations that require ${rootmnt} to be
	# quiescent.  Only the ramdisk is in use at this time.
	# Depends on CPU architecture.
	case "$(uname -m)" in
		x86_64)
			x86_64_onie_uninstall_post
			;;
		armv7l)
			armel_onie_uninstall_post
			;;
		*)
			echo "ERROR: unsupported CPU architecture: $(uname -m)"
			exit 1
	esac


	echo "Rebooting into ONIE to complete the uninstall ..."
	reboot -f
fi

exit 0
