#!/bin/sh

## Copyright (C) 2006-2012 Daniel Baumann <daniel.baumann@progress-technologies.net>
## Copyright (C) 2016-2017 Riku Voipio    <riku.voipio@linaro.org>
##
## This program comes with ABSOLUTELY NO WARRANTY; for details see COPYING.
## This is free software, and you are welcome to redistribute it
## under certain conditions; see COPYING for details.

set -e

_U_BOOT_DIRECTORY="/boot/extlinux"

Update ()
{
	 # Upate target file using source content
	_TARGET="${1}"
	_SOURCE="${2}"

	_TMPFILE="${_TARGET}.tmp"
	rm -f "${_TMPFILE}"

	echo "${_SOURCE}" > "${_TMPFILE}"

	if [ -e "${_TARGET}" ] && cmp -s "${_TARGET}" "${_TMPFILE}"
	then
		rm -f "${_TMPFILE}"
	else
		# FIXME: should use fsync here
		echo "P: Updating ${_TARGET}..."
		mv -f "${_TMPFILE}" "${_TARGET}"
	fi
}

# FIXME: switch to check extlinux file can be written to
# User is unprivileged
if [ "$(id -u)" -ne 0 ]
then
	echo "E: need root privileges"
	exit 1
fi

# Redirect stdout to stderr due Debconf usage
exec 1>&2

# Reading the default file
if [ -e /etc/default/u-boot ]
then
	. /etc/default/u-boot
fi

# Reading config file fragments if they exist
for file in /usr/share/u-boot-menu/conf.d/*.conf /etc/u-boot-menu/conf.d/*.conf
do
	if [ -e "${file}" ]
	then
		. "${file}"
	fi
done

# Reading the os-release file
if [ -e /etc/os-release ]
then
	. /etc/os-release
elif [ -e /usr/lib/os-release ]
then
	. /usr/lib/os-release
fi


U_BOOT_UPDATE="${U_BOOT_UPDATE:-true}"

if [ "${U_BOOT_UPDATE}" != "true" ]
then
	echo "P: u-boot-update is disabled in /etc/default/u-boot."

	exit 0
fi

# Checking extlinux directory
printf '%s' "P: Checking for EXTLINUX directory..."

# Creating extlinux directory
if [ ! -e "${_U_BOOT_DIRECTORY}" ]
then
	echo " not found."

	printf '%s' "P: Creating EXTLINUX directory..."
	mkdir -p "${_U_BOOT_DIRECTORY}"
	echo " done: ${_U_BOOT_DIRECTORY}"
else
	echo " found."
fi

# Setting defaults if /etc/default/u-boot is missing

U_BOOT_ALTERNATIVES="${U_BOOT_ALTERNATIVES:-default recovery}"
U_BOOT_DEFAULT="${U_BOOT_DEFAULT:-l0}"
U_BOOT_PROMPT="${U_BOOT_PROMPT:-0}"
U_BOOT_ENTRIES="${U_BOOT_ENTRIES:-all}"
U_BOOT_TIMEOUT="${U_BOOT_TIMEOUT:-50}"
U_BOOT_MENU_LABEL="${U_BOOT_MENU_LABEL:-${PRETTY_NAME:-Debian GNU/Linux kernel}}"
U_BOOT_FDT_DIR="${U_BOOT_FDT_DIR:-/usr/lib/linux-image-}"
U_BOOT_FDT_OVERLAYS="${U_BOOT_FDT_OVERLAYS:-}"
U_BOOT_FDT_OVERLAYS_DIR="${U_BOOT_FDT_OVERLAYS_DIR:-/boot/dtbo}"
U_BOOT_INITRD="${U_BOOT_INITRD:-initrd.img}"

if [ -z "${U_BOOT_PARAMETERS}" ] && [ -f /etc/kernel/cmdline ]
then
	U_BOOT_PARAMETERS="$(cat /etc/kernel/cmdline | sed -e 's/root=[^[:space:]]*//' -e 's/^[[:space:]]*//')"
	if [ -z "${U_BOOT_ROOT}" ]
	then
		U_BOOT_ROOT="$(cat /etc/kernel/cmdline | sed -re 's/.*(root=[^[:space:]]*).*/\1/')"
	fi
fi
U_BOOT_PARAMETERS="${U_BOOT_PARAMETERS:-ro quiet}"

# Find parameter for root from fstab
if [ -z "${U_BOOT_ROOT}" ]
then
	# Find root partition
	while read _LINE
	do

read _FS_SPEC _FS_FILE _FS_VFSTYPE _FS_MNTOPS _FS_FREQ _FS_PASSNO << EOF
${_LINE}
EOF

		if [ "${_FS_FILE}" = "/" ]
		then
			case "${_FS_SPEC}" in
				"#"*) ;;
				*) U_BOOT_ROOT="root=${_FS_SPEC}"
				   break ;;
			esac
		fi
	done < /etc/fstab
fi

# if not in fstab, try from current kernel arguments
if [ -z "${U_BOOT_ROOT}" ]
then
	for param in $(cat /proc/cmdline)
	do
		case $param in
		  root=*)
			U_BOOT_ROOT="$param"
			break
			;;
		esac
	done
fi


# Create extlinux.conf
_CONFIG="\
## ${_U_BOOT_DIRECTORY}/extlinux.conf
##
## IMPORTANT WARNING
##
## The configuration of this file is generated automatically.
## Do not edit this file manually, use: u-boot-update

default ${U_BOOT_DEFAULT}
menu title U-Boot menu
prompt ${U_BOOT_PROMPT}
timeout ${U_BOOT_TIMEOUT}
"

# Find linux versions
_KERNELS=$(linux-version list --paths | linux-version sort --reverse | sed -e 's,.*/boot/,,g')

# Find boot directory as seen in u-boot, and path prefix while in linux
if [ "$(stat --printf %d /)" = "$(stat --printf %d /boot)" ]
then
	# / and /boot are on the same filesystem
	_BOOT_DIRECTORY="/boot"
	_BOOT_PATH=""
else
	# / and /boot are not on the same filesystem
	_BOOT_DIRECTORY=""
	_BOOT_PATH="/boot"
fi


for _KERNEL in ${_KERNELS}
do
	# Strip kernel prefix to derive version.
	_VERSION=${_KERNEL#*-}
	echo "P: Writing config for ${_KERNEL}..."

	_NUMBER="${_NUMBER:-0}"
	_ENTRY="${_ENTRY:-1}"

	if [ -e "/boot/${U_BOOT_INITRD}-${_VERSION}" ]
	then
		_INITRD="initrd ${_BOOT_DIRECTORY}/${U_BOOT_INITRD}-${_VERSION}"
	elif [ -e "/boot/${U_BOOT_INITRD}" ]
	then
		_INITRD="initrd ${_BOOT_DIRECTORY}/${U_BOOT_INITRD}"
	else
		_INITRD=""
	fi
	if [ -e "${U_BOOT_FDT}" ] && [ -n "${U_BOOT_FDT}" ] && [ "/" = $(echo "${U_BOOT_FDT}" | head -c1) ]
	then
		_FDT="fdt ${U_BOOT_FDT}"
	elif [ -e "${_BOOT_PATH}${U_BOOT_FDT_DIR}${_VERSION}/${U_BOOT_FDT}" ] && [ -n "${U_BOOT_FDT}" ]
	then
		_FDT="fdt ${U_BOOT_FDT_DIR}${_VERSION}/${U_BOOT_FDT}"
	elif [ -d "${_BOOT_PATH}${U_BOOT_FDT_DIR}${_VERSION}/" ]
	then
		_FDT="fdtdir ${U_BOOT_FDT_DIR}${_VERSION}/"
	elif [ -f "${_BOOT_PATH}/${U_BOOT_FDT:-dtb-${_VERSION}}" ] && [ /usr/lib/linux-image- = "${U_BOOT_FDT_DIR}" ]
	then
		_FDT="fdt /${U_BOOT_FDT:-dtb-${_VERSION}}"
	else
		_FDT=""
	fi

	if [ -d "${_BOOT_PATH}/${U_BOOT_FDT_OVERLAYS_DIR}" ]
	then
		_DTBO_LIST=""
		if [ -n "${U_BOOT_FDT_OVERLAYS}" ]
		then
			for _DTBO in ${U_BOOT_FDT_OVERLAYS}
			do
				if [ -f "${_BOOT_PATH}/${U_BOOT_FDT_OVERLAYS_DIR}/${_DTBO}" ]
				then
					_DTBO_LIST="${_DTBO_LIST} ${U_BOOT_FDT_OVERLAYS_DIR}/${_DTBO}"
				fi
			done
		else
			for _DTBO_PATH in "${_BOOT_PATH}/${U_BOOT_FDT_OVERLAYS_DIR}/"*.dtbo
			do
				if [ -f "${_DTBO_PATH}" ]
				then
					_DTBO=$(basename "${_DTBO_PATH}")
					_DTBO_LIST="${_DTBO_LIST} ${U_BOOT_FDT_OVERLAYS_DIR}/${_DTBO}"
				fi
			done
		fi
		if [ -n "${_DTBO_LIST}" ]
		then
			_FDTOVERLAYS="fdtoverlays ${_DTBO_LIST}"
		fi
	fi

	if echo "${U_BOOT_ALTERNATIVES}" | grep -q default
	then

	# Writing default entry
	_CONFIG="${_CONFIG}

label l${_NUMBER}
	menu label ${U_BOOT_MENU_LABEL} ${_VERSION}
	linux ${_BOOT_DIRECTORY}/${_KERNEL}
	${_INITRD}
	${_FDT}
	${_FDTOVERLAYS}
	append ${U_BOOT_ROOT} ${U_BOOT_PARAMETERS}"

	fi

	if echo "${U_BOOT_ALTERNATIVES}" | grep -q recovery
	then

	# Writing recovery entry
	_CONFIG="${_CONFIG}

label l${_NUMBER}r
	menu label ${U_BOOT_MENU_LABEL} ${_VERSION} (rescue target)
	linux ${_BOOT_DIRECTORY}/${_KERNEL}
	${_INITRD}
	${_FDT}
	append ${U_BOOT_ROOT} $(echo "${U_BOOT_PARAMETERS}" | sed -e 's| quiet||') single
	"

	fi

	_NUMBER="$((_NUMBER + 1))"

	if [ "${U_BOOT_ENTRIES}" = "${_ENTRY}" ]
	then
		break
	fi
done

_NUMBER=""

Update "${_U_BOOT_DIRECTORY}/extlinux.conf" "${_CONFIG}"

