#!/bin/sh

# Copyright 2016 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"
install_file="${stage_dir}/onie-installer"
launch_file="${stage_dir}/launch"

# x86_64 ONIE reboot helper.  Assumes a chroot environment is already
# setup on ${rootmnt}.
x86_64_onie_reboot()
{
	# Depends on legacy BIOS vs UEFI...
	if [ -d "/sys/firmware/efi/efivars" ] ; then
		# nothing to do on UEFI platforms, as onie-select
		# already does the job.
		true
	else
		# Legacy BIOS GRUB.  Install grub in the CL-BOOT
		# partition as we will be trashing the CL-SYSTEM
		# partition.
		local tmp_boot="${rootmnt}/mnt/boot-install"
		mkdir -p $tmp_boot
		mount LABEL=CL-BOOT $tmp_boot
		rm -rf ${tmp_boot}/grub
		cp -a ${rootmnt}/boot/grub $tmp_boot
		# Create a minimal grub.cfg that boots into ONIE.
		# Include serial console configuration if present.
		grep serial ${rootmnt}/boot/grub/grub.cfg > ${tmp_boot}/grub/grub.cfg || true
		cat <<EOF >> ${tmp_boot}/grub/grub.cfg
search --no-floppy --label --set=root ONIE-BOOT
echo    'Loading ONIE ...'
chainloader +1
boot
EOF
		chroot ${rootmnt} grub-install \
		       --force --recheck \
		       --boot-directory=/mnt/boot-install $device
		umount $tmp_boot
	fi

}

# armel ONIE reboot helper.  Assumes a chroot environment is already
# setup on ${rootmnt}.
armel_onie_reboot()
{
	# nothing to do on u-boot based platforms, as onie-select
	# already does the job.
	true
}

# Test for staged cumulus installer image
if [ -r "${launch_file}" -a -r "${install_file}" ] ; then

	echo "Installer found.  Configuring ONIE for image install ..."

	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 ${launch_file}

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

	# copy installer (and perhaps an associated preseed file) out
	# to ramdisk.
	rm -rf /tmp/oi
	mkdir -p /tmp/oi
	cp ${install_file} /tmp/oi
	[ -r "${install_file}.preseed" ] && {
		cp "${install_file}.preseed" /tmp/oi
	}
	[ -r "${install_file}.ztp" ] && {
		cp "${install_file}.ztp" /tmp/oi
	}
	size=$(stat -c '%s' /tmp/oi/onie-installer)
	# Convert size to kibibytes and double it for some margin.
	size=$(( ( ($size / 1024 ) + 1 ) * 2 ))

	# determine CL-SYSROOT block device and partition number.  Be
	# mindful of mmc devices that have a different format,
	# mmcblk0pN.
	device=$(blkid -t LABEL=CL-SYSTEM -o device)
	part=$(echo -n $device | tail -c 1)
	device=$(echo -n $device | sed -e 's/[0-9]$//')
	case "$device" in
		/dev/mmcblk*)
			device=${device%%p}
			blk_suffix="p"
			;;
		*)
			blk_suffix=""
	esac

	# mount /dev, /sys, /proc and /run into chroot environment as
	# GRUB and onie-select 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

	# set ONIE to boot in installer mode
	chroot ${rootmnt} /usr/cumulus/bin/onie-select -fi

	# Configure system to boot into ONIE -- depends on CPU architecture
	case "$(uname -m)" in
		x86_64)
			x86_64_onie_reboot
			;;
		armv7l)
			armel_onie_reboot
			;;
		*)
			echo "ERROR: unsupported CPU architecture: $(uname -m)"
			exit 1
	esac

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

	echo "Configuring disk partitions for image install ..."
	# Clobber CL-SYSROOT partition
	sgdisk -d $part $device
	partprobe $device
	sleep 0.5
	sgdisk -n "${part}:0:+${size}K" $device
	partprobe $device
	sleep 0.5

	onie_dev="${device}${blk_suffix}${part}"

	# Wait for block device to show up
	count=0
	while [ $count -lt 100 ] ; do
		sleep 0.1
		if [ -b "$onie_dev" ] ; then
			sleep 0.5
			if [ -b "$onie_dev" ] ; then
				break
			fi
		fi
		count=$(( $count + 1 ))
	done
	if [ $count -eq 100 ] ; then
		panic "Unable to find block device: $onie_dev"
		exit 1
	fi

	# Put a file system on the partition that ONIE can read
	mkfs.ext2 -L CL-INSTALLER -F "$onie_dev"

	mount -t ext2 "$onie_dev" $rootmnt
	cp /tmp/oi/* $rootmnt
	sync ; sync ; sync
	umount $rootmnt

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

exit 0
