#!/bin/sh

# lh_binary_syslinux(1) - installs syslinux into binary
# Copyright (C) 2006-2008 Daniel Baumann <daniel@debian.org>
#
# live-helper 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

# Including common functions
LH_BASE="${LH_BASE:-/usr/share/live-helper}"

for FUNCTION in "${LH_BASE}"/functions/*.sh
do
	. "${FUNCTION}"
done

# Setting static variables
DESCRIPTION="installs syslinux into binary"
HELP=""
USAGE="${PROGRAM} [--force]"

Arguments "${@}"

# Reading configuration files
Read_conffiles config/all config/common config/bootstrap config/chroot config/binary config/source
Set_defaults

if [ "${LH_BOOTLOADER}" != "syslinux" ]
then
	exit 0
fi

Echo_message "Begin installing syslinux..."

# Requiring stage file
Require_stagefile .stage/config .stage/bootstrap

# Checking stage file
Check_stagefile .stage/binary_syslinux

# Checking syslinux templates
Check_templates syslinux

# Checking lock file
Check_lockfile .lock

# Creating lock file
Create_lockfile .lock

# Check architecture
Check_architecture amd64 i386
Check_crossarchitecture

# Checking depends
Check_package chroot/usr/bin/syslinux syslinux

# Restoring cache
Restore_cache cache/packages_binary

# Installing depends
Install_package

# Local functions
Utf8_to_latin1 ()
{
	VALUE="${1}"

	echo "${VALUE}" | iconv -f utf-8 -t latin1
}

Syslinux_memtest_entry ()
{
	LABEL="${1}"
	MENULABEL="$(Utf8_to_latin1 "${2}")"
	KERNEL="${3}"

	MEMTEST="${MEMTEST}\nLABEL ${LABEL}\n"

	# Write the menu label if the syslinux menu is being use
	MEMTEST="${MEMTEST}\tMENU LABEL ${MENULABEL}\n"
	MEMTEST="${MEMTEST}\tkernel ${LIVE_KERNEL_PATH}/${KERNEL}\n"
	MEMTEST="$(/bin/echo ${MEMTEST} | sed -e 's|//|/|g')"
}

Syslinux_live_entry ()
{
	LABEL="${1}"
	MENULABEL="$(Utf8_to_latin1 "${2}")"
	MENULABEL="${2}"
	KERNEL="${3}"
	INITRD="${4}"
	APPEND="${5}"

	case "${LH_BINARY_IMAGES}" in
		iso|usb-hdd)
			NUMBER="$(ls -1 ${KERNEL_PATH} | grep 'vmlinuz[0-9]\+$' | wc -l)"
			NUMBER="$((${NUMBER} +1))"

			# Note: ISOLINUX will not find the kernel if the name ends in ".img".
			mv ${KERNEL_PATH}/${KERNEL} ${KERNEL_PATH}/vmlinuz${NUMBER}
			mv ${KERNEL_PATH}/${INITRD} ${KERNEL_PATH}/initrd${NUMBER}.img

			KERNEL=vmlinuz${NUMBER}
			INITRD=initrd${NUMBER}.img
		;;
	esac

	# Regular kernel
	LINUX_LIVE="${LINUX_LIVE}\nLABEL ${LABEL}\n"

	# Write the menu label if the syslinux menu is being use
	LINUX_LIVE="${LINUX_LIVE}\tMENU LABEL ${MENULABEL}\n"
	LINUX_LIVE="${LINUX_LIVE}\tkernel ${LIVE_KERNEL_PATH}/${KERNEL}\n"
	LINUX_LIVE="${LINUX_LIVE}\tappend initrd=${LIVE_KERNEL_PATH}/${INITRD} boot=${INITFS} ${LH_BOOTAPPEND_LIVE} ${APPEND}\n"

	# Failsafe kernel
	LINUX_LIVE="${LINUX_LIVE}\nLABEL ${LABEL}failsafe\n"

	# Write the menu label if the syslinux menu is being use
	LINUX_LIVE="${LINUX_LIVE}\tMENU LABEL ${MENULABEL} (fail-safe mode)\n"
	LINUX_LIVE="${LINUX_LIVE}\tkernel ${LIVE_KERNEL_PATH}/${KERNEL}\n"
	LINUX_LIVE="${LINUX_LIVE}\tappend initrd=${LIVE_KERNEL_PATH}/${INITRD} boot=${INITFS} ${LH_BOOTAPPEND_LIVE} ${APPEND} ${FAILSAFE}\n"
}

Syslinux_install_entry ()
{
	LABEL="${1}"
	KERNEL="${2}"
	INITRD="${3}"
	APPEND="${4}"

	# Boot in quiet mode where appropriate
	if [ "${LH_DISTRIBUTION}" != "etch" ]
	then
		QAPPEND="quiet"
	fi

	for TYPE in Install Expert Rescue Auto
	do
		case "${TYPE}" in
			Install)
				TAPPEND="${APPEND} ${QAPPEND}"
				;;

			Expert)
				TAPPEND="priority=low ${APPEND}"
				;;

			Rescue)
				TAPPEND="rescue/enable=true ${APPEND} ${QAPPEND}"
				;;

			Auto)
				TAPPEND="auto=true priority=critical ${APPEND} ${QAPPEND}"
				;;
		esac

		case "${LABEL}" in
			Text)
				TYPE_SUFFIX=""
				;;
			GUI)
				TYPE_SUFFIX="gui"
				;;
		esac

		LINUX_INSTALL="${LINUX_INSTALL}\nLABEL $(echo "${TYPE}" | tr A-Z a-z)${TYPE_SUFFIX}\n"
		LINUX_INSTALL="${LINUX_INSTALL}\tMENU LABEL Start ${LABEL} ${TYPE}\n"
		LINUX_INSTALL="${LINUX_INSTALL}\tkernel ${LIVE_INSTALL_KERNEL_PATH}/${KERNEL}\n"
		LINUX_INSTALL="${LINUX_INSTALL}\tappend initrd=${LIVE_INSTALL_KERNEL_PATH}/${INITRD} ${TAPPEND} ${LH_BOOTAPPEND_INSTALL}\n"
	done
}

Copy_syslinux_templates ()
{
	cp -r "${TEMPLATES}"/common/* ${SCREEN_PATH}

	if [ "${LH_SYSLINUX_MENU}" = "disabled" ]
	then
		cp "${TEMPLATES}"/normal/*.cfg ${SCREEN_PATH}
		cp "${TEMPLATES}"/normal/data/* ${DATA_PATH}
	else
		cp "${TEMPLATES}"/menu/*.cfg ${SCREEN_PATH}
		cp "${TEMPLATES}"/menu/data/* ${DATA_PATH}

		# Grab menu binary
		MENUMODULE=$(grep 'menu.c32' ${TEMPLATES}/menu/header.cfg | sed 's|default\s*.*/\(.*menu.c32\)$|\1|g')
		case "${LH_CHROOT_BUILD}" in
			enabled)
				cp chroot/usr/lib/syslinux/"${MENUMODULE}" ${DATA_PATH}
				;;
			disabled)
				cp /usr/lib/syslinux/"${MENUMODULE}" ${DATA_PATH}
				;;
		esac
	fi

	if [ -d "${TEMPLATES}"/"${LH_LANGUAGE}" ]
	then
		cp -r "${TEMPLATES}"/"${LH_LANGUAGE}"/* ${SCREEN_PATH}
	else
		cp -r "${TEMPLATES}"/en/* ${SCREEN_PATH}
	fi

	for FILE in ${SCREEN_PATH}/*.live
	do
		mv ${FILE} $(dirname ${FILE})/$(basename ${FILE} .live)
	done

	if [ "${LH_DEBIAN_INSTALLER}" != "disabled" ]
	then
		for FILE in ${SCREEN_PATH}/*.install
		do
			mv ${FILE} $(dirname ${FILE})/$(basename ${FILE} .install)
		done

		case "${LH_ARCHITECTURE}" in
			amd64|i386|powerpc)
				for FILE in ${SCREEN_PATH}/*.install.g-i
				do
					mv ${FILE} $(dirname ${FILE})/$(basename ${FILE} .install.g-i)
				done
				;;

			*)
				rm -f ${SCREEN_PATH}/*.install.g-i
				;;
		esac
	else
		rm -f ${SCREEN_PATH}/*.install*
	fi

	# Copying custom splash screen
	if [ "${LH_SYSLINUX_SPLASH}" = "none" ]
	then
		# no splash screen
		SPLASH=""
		rm -f ${SCREEN_PATH}/splash.rle
		rm -f ${DATA_PATH}/splash.png
	else
		if [ "${LH_SYSLINUX_MENU}" = "disabled" ]
		then
			SPLASH="${LIVE_DATA_PATH}/splash.rle"
		else
			SPLASH="${LIVE_DATA_PATH}/splash.png"
		fi

		if [ -n "${LH_SYSLINUX_SPLASH}" ]
		then
			if [ ! -e "${LH_SYSLINUX_SPLASH}" ]
			then
				Echo_error "%s doen't exist" "${LH_SYSLINUX_SPLASH}"
				exit 1
			else
				rm -f ${SCREEN_PATH}/splash.rle
				rm -f ${DATA_PATH}/splash.png
				cp -f "${LH_SYSLINUX_SPLASH}" ${DATA_PATH}/$(basename ${SPLASH})
			fi
		fi
	fi
}

Configure_syslinux_templates ()
{
	templates="$(find ${SYSLINUX_PATH} -type f -name '*.cfg' -o -name '*.txt')"

	for template_file in ${templates}
	do
		sed -i -e "s|{\$LINUX_LIVE}|${LINUX_LIVE}|" \
		       -e "s|{\$LINUX_INSTALL}|${LINUX_INSTALL}|" \
		       -e "s|{\$MEMTEST}|${MEMTEST}|" \
		       -e "s|{\$LIVE_SCREEN_PATH}|${LIVE_SCREEN_PATH}|" \
		       -e "s|{\$LIVE_DATA_PATH}|${LIVE_DATA_PATH}|" \
		       -e "s|{\$LIVE_KERNEL_PATH}|${LIVE_KERNEL_PATH}|" \
		       -e "s|{\$SPLASH}|${SPLASH}|" \
		       -e "s|{\$LH_DISTRIBUTION}|${LH_DISTRIBUTION}|" \
		       -e "s|{\$LH_DATE}|$(date +%Y%m%d)|" \
		       -e "s|{\$LH_MEDIA}|${MEDIA}|" \
		       -e "s|{\$LH_VERSION}|${VERSION}|" \
		       -e "s|{\$LH_SYSLINUX_TIMEOUT}|${LH_SYSLINUX_TIMEOUT}0|" \
		$template_file
	done

	# Syslinux v3.31 in etch does not support include statements
	if [ "${LH_DISTRIBUTION}" = "etch" ]
	then
		while grep -qs ^include ${SCREEN_PATH}/syslinux.cfg
		do
			INCLUDES=$(grep ^include ${SCREEN_PATH}/syslinux.cfg |awk '{print $2}')

			for FILE_PATH in ${INCLUDES}
			do
				FILE_NAME=$(basename ${FILE_PATH})

				sed -i -e '\@include '${FILE_PATH}'@ {
					r '${SCREEN_PATH}/${FILE_NAME}'
					d
				}' ${SCREEN_PATH}/syslinux.cfg

				# remove the files, which were included
				if [ -e ${SCREEN_PATH}/${FILE_NAME} ]
				then
					rm -f ${SCREEN_PATH}/${FILE_NAME}
				fi
			done
		done

		# Syslinux v3.31 in etch does not support sub directories, /path/kernel,
		# when using FAT hard drive images, remove leading /'s
		if [ "${LH_BINARY_IMAGES}" = "usb-hdd" ]
		then
			for FILE in ${SCREEN_PATH}/syslinux.cfg ${SCREEN_PATH}/boot.txt
			do
				sed -i -e 's|/||' ${FILE}
			done
		fi
	fi
}

# Setting up common variables
case "${LH_INITRAMFS}" in
	casper)
		INITFS="casper"
		;;

	live-initramfs)
		INITFS="live"
		;;
esac

# Setting boot method specific variables
case "${LH_BINARY_IMAGES}" in
	iso)
		SYSLINUX_PATH="binary/isolinux"
		KERNEL_PATH="binary/${INITFS}"
		SCREEN_PATH="${SYSLINUX_PATH}"
		DATA_PATH="${SCREEN_PATH}/data"
		LIVE_KERNEL_PATH="/${INITFS}"
		LIVE_INSTALL_KERNEL_PATH="/install"
		LIVE_SCREEN_PATH="/isolinux"
		LIVE_DATA_PATH="${LIVE_SCREEN_PATH}/data"
		MEDIA="CD-ROM"
		;;

	net)
		SYSLINUX_PATH="tftpboot"
		KERNEL_PATH="${SYSLINUX_PATH}/debian-live/${LH_ARCHITECTURE}"
		SCREEN_PATH="${SYSLINUX_PATH}/debian-live/${LH_ARCHITECTURE}/boot-screens"
		DATA_PATH="${SCREEN_PATH}/data"
		LIVE_KERNEL_PATH="debian-live/${LH_ARCHITECTURE}"
		LIVE_INSTALL_KERNEL_PATH="debian-install/${LH_ARCHITECTURE}"
		LIVE_SCREEN_PATH="debian-live/${LH_ARCHITECTURE}/boot-screens"
		LIVE_DATA_PATH="${LIVE_SCREEN_PATH}/data"
		MEDIA="netboot"
		;;

	tar|usb-hdd)
		SYSLINUX_PATH="binary/syslinux"
		KERNEL_PATH="binary/${INITFS}"
		SCREEN_PATH="${SYSLINUX_PATH}"
		DATA_PATH="${SCREEN_PATH}/data"
		LIVE_KERNEL_PATH="/${INITFS}"
		LIVE_INSTALL_KERNEL_PATH="/install"
		LIVE_SCREEN_PATH="/syslinux"
		LIVE_DATA_PATH="${LIVE_SCREEN_PATH}/data"

		# Syslinux v3.31 in etch does not support sub directories, /path/kernel,
		# when using FAT hard drive images
		if [ "${LH_DISTRIBUTION}" = "etch" ] && [ "${LH_BINARY_IMAGES}" = "usb-hdd" ]
		then
			SYSLINUX_PATH="binary"
			KERNEL_PATH="binary"
			SCREEN_PATH="binary"
			DATA_PATH="binary"
			LIVE_KERNEL_PATH=""
			LIVE_INSTALL_KERNEL_PATH=""
			LIVE_SCREEN_PATH=""
			LIVE_DATA_PATH=""
		fi

		MEDIA="hd-media"
		;;
esac

Check_multiarchitecture

# Creating directories
mkdir -p "${KERNEL_PATH}"
mkdir -p "${SCREEN_PATH}"
mkdir -p "${DATA_PATH}"

# Setting boot parameters
case "${LH_ENCRYPTION}" in
	""|disabled)
		;;
	*)
		LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} encryption=${LH_ENCRYPTION}"
		;;
esac

if [ -n "${LH_USERNAME}" ]
then
	case "${LH_INITRAMFS}" in
		casper)
			LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} username=${LH_USERNAME}"
			;;

		live-initramfs)
			if [ "${LH_USERNAME}" != "user" ]
			then
				LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} username=${LH_USERNAME}"
			fi
			;;
	esac
fi

if [ -n "${LH_HOSTNAME}" ]
then
	case "${LH_INITRAMFS}" in
		casper)
			LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} hostname=${LH_HOSTNAME}"
			;;

		live-initramfs)
			if [ "${LH_HOSTNAME}" != "debian" ]
			then
				LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} hostname=${LH_HOSTNAME}"
			fi
			;;
	esac
fi

if [ "${LH_UNION_FILESYSTEM}" != "unionfs" ]
then
	LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} union=${LH_UNION_FILESYSTEM}"
fi

if [ "${LH_EXPOSED_ROOT}" != "disabled" ]
then
	LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} exposedroot"
fi

if [ "${LH_BINARY_IMAGES}" = "net" ]
then
	case "${LH_NET_ROOT_FILESYSTEM}" in
		nfs)
			LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} netboot=nfs nfsroot=${LH_NET_ROOT_SERVER}:${LH_NET_ROOT_PATH}"
			;;

		cifs)
			LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} netboot=cifs nfsroot=//${LH_NET_ROOT_SERVER}${LH_NET_ROOT_PATH}"
			;;

		*)
			Echo_error "Unsupported net filesystem"
			exit 1
			;;
	esac

	if [ -n "${LH_NET_ROOT_MOUNTOPTIONS}" ]
	then
		LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} nfsopts=${LH_NET_ROOT_MOUNTOPTIONS}"
	fi
fi

if [ -n "${LH_NET_COW_PATH}" ]
then
	case "${LH_NET_COW_FILESYSTEM}" in
		nfs)
			if [ -n "${LH_NET_COW_MOUNTOPTIONS}" ]
			then
				LH_NET_COW_MOUNTOPTIONS=",${LH_NET_COW_MOUNTOPTIONS}"
			fi

			LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} nfscow=${LH_NET_COW_SERVER}:${LH_NET_COW_PATH}${LH_NET_COW_MOUNTOPTIONS}"
			;;

		*)
			Echo_error "Unsupported net filesystem"
			exit 1
			;;
	esac
fi

LH_BOOTAPPEND_LIVE="$(echo ${LH_BOOTAPPEND_LIVE} | sed -e 's|  ||')"

# Parameters are listed at: linux/Documentation/kernel-parameters.txt
FAILSAFE="noapic noapm nodma nomce nolapic nosmp vga=normal"

# Moving kernels into place
if [ "binary/${INITFS}" != "${KERNEL_PATH}" ]
then
	mv binary/${INITFS}/vmlinuz* ${KERNEL_PATH}
	mv binary/${INITFS}/initrd* ${KERNEL_PATH}

	if [ "${LH_MEMTEST}" != "disabled" ] && [ "${LH_MEMTEST}" != "none" ]
	then
		mv binary/${INITFS}/memtest ${KERNEL_PATH}
	fi
fi

# Default entries
DEFAULT_FLAVOUR="$(echo ${LH_LINUX_FLAVOURS} | awk '{ print $1 }')"
DEFAULT_KERNEL="$(basename chroot/boot/vmlinuz-*${DEFAULT_FLAVOUR})"
DEFAULT_INITRD="initrd.img-$(echo ${DEFAULT_KERNEL} | sed -e 's|vmlinuz-||')"

Syslinux_live_entry "live" "${LH_SYSLINUX_MENU_LIVE_ENTRY}" "${DEFAULT_KERNEL}" "${DEFAULT_INITRD}"

if [ "$(echo ${LH_LINUX_FLAVOURS} | wc -w)" -gt "1" ]
then
	for FLAVOUR in ${LH_LINUX_FLAVOURS}
	do
		if [ "${FLAVOUR}" != "${DEFAULT_FLAVOUR}" ]
		then
			FLAVOUR_KERNEL="$(basename chroot/boot/vmlinuz-*${FLAVOUR})"
			FLAVOUR_INITRD="initrd.img-$(echo ${FLAVOUR_KERNEL} | sed -e 's|vmlinuz-||')"
			Syslinux_live_entry "live-${FLAVOUR}" "${LH_SYSLINUX_MENU_LIVE_ENTRY} ${FLAVOUR}" "${FLAVOUR_KERNEL}" "${FLAVOUR_INITRD}"
		fi
	done
fi

# Assembling debian-installer configuration
if [ "${LH_DEBIAN_INSTALLER}" != "disabled" ]
then
	VMLINUZ_DI="vmlinuz"
	INITRD_DI="initrd.gz"
	APPEND_DI="vga=normal"

	VMLINUZ_GI="gtk/vmlinuz"
	INITRD_GI="gtk/initrd.gz"
	APPEND_GI="video=vesa:ywrap,mtrr vga=788"

	Syslinux_install_entry "Text" "${VMLINUZ_DI}" "${INITRD_DI}" "${APPEND_DI}"
	Syslinux_install_entry "GUI" "${VMLINUZ_GI}" "${INITRD_GI}" "${APPEND_GI}"
fi

# Assembling memtest configuration
if [ -f "${KERNEL_PATH}"/memtest ]
then
	Syslinux_memtest_entry "memtest" "${LH_SYSLINUX_MENU_MEMTEST_ENTRY}" "memtest"
fi

# Copy templates to base syslinux directory
Copy_syslinux_templates

# Fill in templates with created values
Configure_syslinux_templates

# Configure syslinux setup per boot method
case "${LH_BINARY_IMAGES}" in
	iso)
		case "${LH_CHROOT_BUILD}" in
			enabled)
				cp chroot/usr/lib/syslinux/isolinux.bin ${SCREEN_PATH}
				;;
			disabled)
				cp /usr/lib/syslinux/isolinux.bin ${SCREEN_PATH}
				;;
		esac

		mv ${SCREEN_PATH}/syslinux.cfg ${SCREEN_PATH}/isolinux.cfg

		# Copying configuration file
		if [ -n "${LH_SYSLINUX_CFG}" ]
		then
			cp "${LH_SYSLINUX_CFG}" ${SCREEN_PATH}/isolinux.cfg
		fi
		;;

	net)
		case "${LH_CHROOT_BUILD}" in
			enabled)
				cp chroot/usr/lib/syslinux/pxelinux.0 ${KERNEL_PATH}
				;;
			disabled)
				cp /usr/lib/syslinux/pxelinux.0 ${KERNEL_PATH}
				;;
		esac

		mkdir -p ${KERNEL_PATH}/pxelinux.cfg
		ln -s ${LIVE_KERNEL_PATH}/pxelinux.cfg ${SYSLINUX_PATH}/pxelinux.cfg
		ln -s ${LIVE_KERNEL_PATH}/pxelinux.0 ${SYSLINUX_PATH}/pxelinux.0

		mv ${SCREEN_PATH}/syslinux.cfg ${KERNEL_PATH}/pxelinux.cfg/default

		# Copying configuration file
		if [ -n "${LH_SYSLINUX_CFG}" ]
		then
			cp "${LH_SYSLINUX_CFG}" ${KERNEL_PATH}/pxelinux.cfg/default
		fi
		;;

	tar|usb-hdd)
		case "${LH_CHROOT_BUILD}" in
			enabled)
				cp chroot/usr/lib/syslinux/isolinux.bin ${SCREEN_PATH}/syslinux.bin
				;;
			disabled)
				cp /usr/lib/syslinux/isolinux.bin ${SCREEN_PATH}/syslinux.bin
				;;
		esac

		# Copying configuration file
		if [ -n "${LH_SYSLINUX_CFG}" ]
		then
			cp "${LH_SYSLINUX_CFG}" ${SCREEN_PATH}/syslinux.cfg
		fi
		;;
esac

# Saving cache
Save_cache cache/packages_binary

# Removing depends
Remove_package

# Creating stage file
Create_stagefile .stage/binary_syslinux