#!/bin/sh -euf

# Copyright 2013-2014 Intel Corporation
# Author: Artem Bityutskiy
# License: GPLv2

PROG="setup-scripts-boot"
VER="1.0"

srcdir="$(readlink -ev -- ${0%/*})"
PATH="/usr/share/setup-scripts:$srcdir:$PATH"

if [ -f "$srcdir/setup-scripts-sh-functions" ]; then
	. "$srcdir/setup-scripts-sh-functions"
	. "$srcdir/installerfw-sh-functions"
else
	.  /usr/share/setup-scripts/setup-scripts-sh-functions
	.  /usr/share/setup-scripts/installerfw-sh-functions
fi

# This is a small trick which I use to make sure my scripts are portable -
# check if 'dash' is present, and if yes - use it.
if can_switch_to_dash; then
	exec dash -euf -- "$srcdir/$PROG" "$@"
	exit $?
fi

install_gummiboot()
{
	verbose "installing gummiboot to $bootdir"

	local installdir="$bootdir/EFI/boot"
	local gummiboot_path="$(installerfw_mnt_prefix "/usr/lib/gummiboot")"
	local src32="$gummiboot_path/gummibootia32.efi"
	local src64="$gummiboot_path/gummibootx64.efi"
	local src=""
	local dst=""

	# Autoboot from fs0 by default
	local efi_bootdir="fs0:"

	# Make sure gummiboot is installed in the system
	if ! ([ -f "$src32" ] || [ -f "$src64" ]); then
		fatal "\"$gummiboot_path/gummiboot*.efi\" files not found!"
	fi

	# Install gummiboot
	mkdir -p $verbose -- "$installdir" >&2

	if [ -f "$src64" ] ; then
	    src="$src64"
	    dst="$installdir/bootx64.efi"
	elif [ -f "$src32" ] ; then
	    src="$src32"
	    dst="$installdir/bootia32.efi"
	fi

	if [ -f "$src" ] ; then
	    local basename=$(basename -- "$dst")
	    cp $verbose "$src" "$dst" 2>&2
	    echo "${efi_bootdir}\\EFI\\boot\\$basename" > "${bootdir}/startup.nsh"
	fi

	verbose "installed gummiboot to $bootdir"
}

install_extlinux()
{
	local installdir="$bootdir/extlinux"
	local extlinux="extlinux"
	local output

	# Check if extlinux is available
        if ! command -v "extlinux" >/dev/null 2>&1; then
		extlinux="$(installerfw_mnt_prefix "/sbin/extlinux")"
		[ -f "$extlinux" ] ||
			fatal "cannot find \"$extlinux\""
	fi

	# Get device node name for the boot partition
	local boot_devnode
	installerfw_get_part_info "/boot" "DEVNODE_NOW" "boot_devnode"
	if [ ! -n "$boot_devnode" ] ; then
	    verbose "No /boot part, fallback to /"
		installerfw_get_part_info "/" "DEVNODE_NOW" "boot_devnode"
	fi
	[ -n "$boot_devnode" ] || \
		fatal "cannot find device node of the boot disk, probably" \
		      "INSTALLERFW_PARTx_DEVNODE_NOW environment" \
		      "variable is not defined"

	# Install extlinux
	verbose "installing extlinux to $bootdir, boot device node is" \
	        "\"$boot_devnode\""
	mkdir -p $verbose -- "$installdir" >&2
	output="$("$extlinux" --device "$boot_devnode" -i "$installdir" 2>&1)" \
		|| fatal "cannot install extlinux to \"$installdir\" (note," \
		         "extlinux version 5 or greater is required)" \
		         "${br}${output}"

	# Get device node name for the boot disk
	local mbr_devnode
	installerfw_get_part_info "/boot" "DISK_DEVNODE_NOW" "mbr_devnode"
	if [ !  -n "$mbr_devnode" ] ; then
	    verbose "No /boot disk, fallback to /"
	    installerfw_get_part_info "/" "DISK_DEVNODE_NOW" "mbr_devnode"
	fi
	[ -n "$mbr_devnode" ] || \
		fatal "cannot find device node of the boot disk, probably" \
		      "INSTALLERFW_PARTx_DISK_DEVNODE_NOW environment" \
		      "variable is not defined"

	# Install the MBR part of extlinux
	local mbr_bin="$(installerfw_mnt_prefix \
			 "/usr/share/syslinux/gptmbr.bin")"
	verbose "setting up MBR, writing \"$mbr_bin\" to \"$mbr_devnode\""
	output="$(dd if="$mbr_bin" of="$mbr_devnode" count=1 2>&1)" || \
		fatal "cannot install MBR, dd if=$mbr_bin of=$mbr_devnode" \
		      "failed${br}${output}"

	verbose "installed extlinux to $bootdir"
}

show_usage()
{
	cat <<-EOF
Usage: $PROG [options]

Install the EFI bootloader (gummiboot) and create the initial configuration
for all the currently installed kernels. This program depends on various
"installer framework" variables.

Options:
  -v, --verbose  be verbose
  --version      show the program version and exit
  -h, --help     show this text and exit
EOF
}

show_usage_fail()
{
	IFS= printf "%s\n\n" "$PROG: error: $*" >&2
	show_usage >&2
	exit 1
}

# Parse the options
tmp=`getopt -n $PROG -o v,h --long verbose,version,help -- "$@"` ||
	show_usage_fail "cannot parse command-line options"
eval set -- "$tmp"

verbose=
while true; do
	case "$1" in
	-v|--verbose)
		verbose="-v"
		;;
	--version)
		printf "%s\n" "$VER"
		exit 0
		;;
	-h|--help)
		show_usage
		exit 0
		;;
	--) shift; break
		;;
	*) show_usage_fail "unrecognized option \"$1\""
		;;
	esac
	shift
done

bootdir="$(installerfw_mnt_prefix "/boot")"

if installerfw_available; then
	installerfw_save_env
else
	installerfw_restore_env
fi

# Get OS name
get_os_name "os_name"

if installerfw_is_efi_boot_system; then
	install_gummiboot
else
	install_extlinux
fi

# Create bootloader entries for each kernel
kernels="$(ls -1 "$bootdir" | LC_ALL=C grep -- "^vmlinuz-" | sort -r)"

[ -n "$kernels" ] || \
	fatal "no kernels (vmlinuz-*) found in \"$bootdir\""

printf "%s\n" "$kernels" | while IFS= read -r kernel; do
	setup-scripts-bootloader-conf $verbose add --force "$kernel"
done

# Set the default kernel to the kernel with highest version
newest_kernel="$(get_newest_kernel "$bootdir")"
setup-scripts-bootloader-conf $verbose default "$newest_kernel"

# And finally, create the /etc/fstab file
setup-scripts-fstab $verbose --force
