#!/bin/sh

## Copyright (C) 2006-2012 Daniel Baumann <daniel.baumann@progress-technologies.net>
##
## 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

_EXTLINUX_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
}

# 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/extlinux ]
then
	. /etc/default/extlinux
fi

EXTLINUX_UPDATE="${EXTLINUX_UPDATE:-true}"

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

	exit 0
fi

# Checking extlinux directory
echo -n "P: Checking for EXTLINUX directory..."

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

	echo -n "P: Creating EXTLINUX directory..."
	mkdir -p "${_EXTLINUX_DIRECTORY}"
	echo " done: ${_EXTLINUX_DIRECTORY}"
else
	echo " found."
fi

# Setting defaults
EXTLINUX_ALTERNATIVES="${EXTLINUX_ALTERNATIVES:-default recovery}"
EXTLINUX_DEFAULT="${EXTLINUX_DEFAULT:-l0}"
EXTLINUX_ENTRIES="${EXTLINUX_ENTRIES:-all}"
EXTLINUX_MEMDISK="${EXTLINUX_MEMDISK:-true}"
EXTLINUX_MEMDISK_DIRECTORY="${EXTLINXU_MEMDISK_DIRECTORY:-/boot}"

if [ -z "${EXTLINUX_MENU_LABEL}" ]
then
	if [ -x "$(which lsb_release 2>/dev/null)" ]
	then
		EXTLINUX_MENU_LABEL="$(lsb_release -i -s) GNU/Linux, kernel"
	else
		EXTLINUX_MENU_LABEL="Debian GNU/Linux, kernel"
	fi
fi

EXTLINUX_OS_PROBER="${EXTLINUX_OS_PROBER:-true}"
EXTLINUX_PARAMETERS="${EXTLINUX_PARAMETERS:-ro quiet}"

if [ -z "${EXTLINUX_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_SPEC}" != "#" ] && [ "${_FS_FILE}" = "/" ]
		then
			EXTLINUX_ROOT="root=${_FS_SPEC}"
			break
		fi
	done < /etc/fstab
fi

if [ -z "${EXTLINUX_THEME}" ]
then
	# Using default menu if available
	if [ -e /usr/share/syslinux/themes/debian/extlinux ]
	then
		EXTLINUX_THEME="debian"
	else
		EXTLINUX_THEME="none"
	fi
fi

EXTLINUX_TIMEOUT="${EXTLINUX_TIMEOUT:-50}"

# Writing new default file
cat > "/etc/default/extlinux" << EOF
## /etc/default/extlinux - configuration file for extlinux-update(8)

EXTLINUX_UPDATE="${EXTLINUX_UPDATE}"

EXTLINUX_ALTERNATIVES="${EXTLINUX_ALTERNATIVES}"
EXTLINUX_DEFAULT="${EXTLINUX_DEFAULT}"
EXTLINUX_ENTRIES="${EXTLINUX_ENTRIES}"
EXTLINUX_MEMDISK="${EXTLINUX_MEMDISK}"
EXTLINUX_MEMDISK_DIRECTORY="${EXTLINUX_MEMDISK_DIRECTORY}"
EXTLINUX_MENU_LABEL="${EXTLINUX_MENU_LABEL}"
EXTLINUX_OS_PROBER="${EXTLINUX_OS_PROBER}"
EXTLINUX_PARAMETERS="${EXTLINUX_PARAMETERS}"
EXTLINUX_ROOT="${EXTLINUX_ROOT}"
EXTLINUX_THEME="${EXTLINUX_THEME}"
EXTLINUX_TIMEOUT="${EXTLINUX_TIMEOUT}"
EOF

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


"

# Find linux versions
_VERSIONS="$(cd /boot && ls vmlinuz-* | grep -v .dpkg-tmp | sed -e 's|vmlinuz-||g' | sort -nr)"

if [ "$(stat --printf %d /)" = "$(stat --printf %d /boot)" ]
then
	# / and /boot are on the same filesystem
	_BOOT_DIRECTORY="/boot"
else
	# / and /boot are not on the same filesystem
	_BOOT_DIRECTORY=""
fi


for _VERSION in ${_VERSIONS}
do
	echo "P: Writing config for /boot/vmlinuz-${_VERSION}..."

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

	if [ -e /boot/initrd.img-${_VERSION} ]
	then
		_INITRD="initrd=${_BOOT_DIRECTORY}/initrd.img-${_VERSION}"
	else
		_INITRD=""
	fi

	if echo ${EXTLINUX_ALTERNATIVES} | grep -q default
	then

	# Writing default entry
	_CONFIG="${_CONFIG}

label l${_NUMBER}
	menu label ${EXTLINUX_MENU_LABEL} ${_VERSION}
	linux ${_BOOT_DIRECTORY}/vmlinuz-${_VERSION}
	append ${_INITRD} ${EXTLINUX_ROOT} ${EXTLINUX_PARAMETERS}"

	fi

	if echo ${EXTLINUX_ALTERNATIVES} | grep -q live
	then

	# Writing live entry
	_CONFIG="${_CONFIG}

label l${_NUMBER}l
	menu label ${EXTLINUX_MENU_LABEL} ${_VERSION} (live mode)
	linux ${_BOOT_DIRECTORY}/vmlinuz-${_VERSION}
	append ${_INITRD} ${EXTLINUX_ROOT} ${EXTLINUX_PARAMETERS} boot=live plainroot
	text help
   This option boots the system into live mode (non-persistent)
	endtext"

	fi

	if echo ${EXTLINUX_ALTERNATIVES} | grep -q recovery
	then

	# Writing recovery entry
	_CONFIG="${_CONFIG}

label l${_NUMBER}r
	menu label ${EXTLINUX_MENU_LABEL} ${_VERSION} (recovery mode)
	linux ${_BOOT_DIRECTORY}/vmlinuz-${_VERSION}
	append ${_INITRD} ${EXTLINUX_ROOT} $(echo ${EXTLINUX_PARAMETERS} | sed -e 's| quiet||') single
	text help
   This option boots the system into recovery mode (single-user)
	endtext"

	fi

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

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

_NUMBER=""

Update "${_EXTLINUX_DIRECTORY}/linux.cfg" "${_CONFIG}"


if [ "${EXTLINUX_MEMDISK}" = "true" ]
then
	if [ ! -e /usr/lib/extlinux/memdisk ]
	then
		echo "E: /usr/lib/extlinux/memdisk: No such file"
		exit 1
	fi

	cp -f /usr/lib/extlinux/memdisk "${_EXTLINUX_DIRECTORY}"

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


"

	for _IMAGE in "${EXTLINUX_MEMDISK_DIRECTORY}"/*.iso "${EXTLINUX_MEMDISK_DIRECTORY}"/*.img
	do
		# Skip non-existing files and files matching '^initrd.*'
		if [ ! -e "${_IMAGE}" ] || [ "$(basename ${_IMAGE} | cut -b 1-6)" = "initrd" ]
		then
			continue
		fi

		_NUMBER="${_NUMBER:-0}"

		echo "P: Writing config for ${_IMAGE}..."

		case "${_IMAGE}" in
			*.iso)
				_IMAGE_APPEND="iso"
				;;

			*.img)
				_IMAGE_APPEND="raw"
				;;
		esac

		if [ -n "${_BOOT_DIRECTORY}" ]
		then
			# / and /boot are on the same filesystem
			_MEMDISK_DIRECTORY="${_EXTLINUX_DIRECTORY}"
		else
			# / and /boot are not on the same filesystem
			_MEMDISK_DIRECTORY="$(echo ${_EXTLINUX_DIRECTORY} | sed -e 's|^/boot||')"
			_IMAGE="$(echo ${_IMAGE} | sed -e 's|^/boot||')"
		fi

		# Writing image entry
		_CONFIG="${_CONFIG}

label m${_NUMBER}
	menu label Memdisk, image $(basename ${_IMAGE})
	linux ${_MEMDISK_DIRECTORY}/memdisk
	initrd ${_IMAGE}
	append ${_IMAGE_APPEND}"

		_NUMBER="$((${_NUMBER} + 1))"
	done

	_NUMBER=""

	Update "${_EXTLINUX_DIRECTORY}/memdisk.cfg" "${_CONFIG}"
fi

if [ "${EXTLINUX_OS_PROBER}" = "true" ] && [ -x "$(which os-prober 2>/dev/null)" ]
then
	if [ ! -e /usr/lib/extlinux/chain.c32 ]
	then
		echo "E: /usr/lib/extlinux/chain.c32: No such file"
		exit 1
	fi

	cp -f /usr/lib/extlinux/chain.c32 "${_EXTLINUX_DIRECTORY}"

# Create os-prober.cfg
_CONFIG="\
## ${_EXTLINUX_DIRECTORY}/os-prober.cfg
##
## IMPORTANT WARNING
##
## The configuration of this file is generated automatically.
## Do not edit this file manually, use: extlinux-update


"

	for _OS in $(os-prober | tr ' ' '^' | paste -s -d ' ')
	do
		_DEVICE="$(echo ${_OS} | cut -d ':' -f 1)"
		_LONGNAME="$(echo ${_OS} | cut -d ':' -f 2 | tr '^' ' ')"
		_LABEL="$(echo ${_OS} | cut -d ':' -f 3 | tr '^' ' ')"
		_BOOT="$(echo ${_OS} | cut -d ':' -f 4)"

		if [ "${_BOOT}" != "chain" ]
		then
			continue
		fi

		if [ -z "${_LONGNAME}" ]
		then
			_LONGNAME="${_LABEL}"
		fi

		_NUMBER="${_NUMBER:-0}"

		echo "P: Writing config for ${_LONGNAME} on ${_DEVICE}..."

		_DEVICENAME="$(echo ${_DEVICE} | sed -e 's/^\/dev\/[sh]d//' -e 'y/abcdefghij/0123456789/' -e 's/./& /')"

		# Writing other os entry
		_CONFIG="${_CONFIG}

label o${_NUMBER}
	menu label Other OS, ${_LONGNAME} (on ${_DEVICE})
	kernel chain.c32
	append hd${_DEVICENAME}"

		_NUMBER="$((${_NUMBER} + 1))"
	done

	_NUMBER=""

	Update "${_EXTLINUX_DIRECTORY}/os-prober.cfg" "${_CONFIG}"
fi


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


default ${EXTLINUX_DEFAULT}
prompt 1
timeout ${EXTLINUX_TIMEOUT}
"

if [ -n "${EXTLINUX_THEME}" ] && [ "${EXTLINUX_THEME}" != "none" ]
then
	if [ ! -e "/usr/share/syslinux/themes/${EXTLINUX_THEME}/extlinux" ]
	then
		echo "E: /usr/share/syslinux/themes/${EXTLINUX_THEME}/extlinux: No such file or directory"
		exit 1
	else
		echo -n "P: Installing ${EXTLINUX_THEME} theme..."
		rm -rf "${_EXTLINUX_DIRECTORY}/themes/${EXTLINUX_THEME}"

		mkdir -p "${_EXTLINUX_DIRECTORY}/themes"

		EXTLINUX_THEME_ORIG="$(readlink /usr/share/syslinux/themes/${EXTLINUX_THEME})" || true

		if [ -n "${EXTLINUX_THEME_ORIG}" ]
		then
			cp -aL "/usr/share/syslinux/themes/${EXTLINUX_THEME_ORIG}/extlinux" "${_EXTLINUX_DIRECTORY}/themes/${EXTLINUX_THEME_ORIG}"
			ln -sf "${EXTLINUX_THEME_ORIG}" "${_EXTLINUX_DIRECTORY}/themes/${EXTLINUX_THEME}"
		else
			cp -aL "/usr/share/syslinux/themes/${EXTLINUX_THEME}/extlinux" "${_EXTLINUX_DIRECTORY}/themes/${EXTLINUX_THEME}"
		fi

		echo " done."
	fi

	_CONFIG="${_CONFIG}
include themes/${EXTLINUX_THEME}/theme.cfg"

else

	_CONFIG="${_CONFIG}
display boot.txt
include linux.cfg"

	if [ "${EXTLINUX_MEMDISK}" = "true" ] && [ -e "${_EXTLINUX_DIRECTORY}/memdisk.cfg" ]
	then

		_CONFIG="${_CONFIG}
include memdisk.cfg"

	fi

	if [ "${EXTLINUX_OS_PROBER}" = "true" ] && [ -e "${_EXTLINUX_DIRECTORY}/os-prober.cfg" ]
	then

		_CONFIG="${_CONFIG}
include os-prober.cfg"

	fi

	if [ ! -e "${_EXTLINUX_DIRECTORY}/boot.txt" ]
	then
		echo "Wait 5 seconds or press ENTER to " > "${_EXTLINUX_DIRECTORY}/boot.txt"
	fi
fi

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