#!/bin/sh
set -e

. /usr/share/debconf/confmodule

newline="
"

log() {
	logger -t lilo-installer "$@"
}

error() {
	log "error: $@"
}

info() {
	log "info: $@"
}

findfs () {
	mount | grep "on /target${1%/} " | tail -n1 | cut -d' ' -f1
}

lvm_vg () {
	# Map from /dev/mapper/<vg>-<lv> to /dev/<vg>/<lv>
	vglv=${1#/dev/mapper/}
	if [ "$vglv" != "$1" ]; then
		vglv=`echo "$vglv" | sed -e 's/\([^-]\)-\([^-]\)/\1 \2/' | sed -e 's/--/-/g'`
		vg=`echo "$vglv" | cut -d" " -f1`
		lv=`echo "$vglv" | cut -d" " -f2`
		lvdisplay -c "/dev/$vg/$lv"| sed 's/^[^:]*:\([^:]*\):.*$/\1/'
	else
		lvdisplay -c "$1" 2>/dev/null | cut -d: -f2
	fi
}

first_pv () {
	pvdisplay -c | grep "^[^:]*:$1:" | sed 's/^ *\([^:]*\):.*$/\1/' | head -n 1
}

# Make sure mtab in the chroot reflects the currently mounted partitions.
update_mtab() {
	mtab=/target/etc/mtab
	grep "/target" /proc/mounts | (
	while read devpath mountpoint fstype options n1 n2 ; do
		devpath=`mapdevfs $devpath || echo $devpath`
		mountpoint=`echo $mountpoint | sed "s%^/target%%"`
		# The sed line removes the mount point for root.
		if [ -z "$mountpoint" ] ; then
			mountpoint="/"
		fi
		echo $devpath $mountpoint $fstype $options $n1 $n2
	done ) > $mtab
}

rootfs_devfs=$(findfs /)
bootfs_devfs=$(findfs /boot)
[ -n "$bootfs_devfs" ] || bootfs_devfs="$rootfs_devfs"

rootfs=$(mapdevfs $rootfs_devfs)

bootvg=$(lvm_vg $bootfs_devfs)
if [ -n "$bootvg" ]; then
	bootfs_devfs=$(first_pv $bootvg)
	bootfs_devfs="$(readlink -f "$bootfs_devfs" 2>/dev/null || echo "$bootfs_devfs")"
fi

bootfs=$(mapdevfs $bootfs_devfs)

prefix=$(echo "$bootfs_devfs" | \
  sed 's/\(\/dev\/\(cciss\|ida\)\/c[0-9]d[0-9][0-9]*\|\/dev\/[a-z]\+\).*/\1/')

case $prefix in
	/dev/md)
		disc_offered_devfs="$bootfs_devfs"
		db_register lilo-installer/bootdev_raid lilo-installer/bootdev
	;;
	*)
		disc_offered_devfs="$prefix"
	;;
esac
disc_offered=$(mapdevfs "$disc_offered_devfs")

db_capb backup

db_subst lilo-installer/bootdev disc "$disc_offered"
db_subst lilo-installer/bootdev part "$bootfs"

db_input high lilo-installer/bootdev || [ $? -eq 30 ]
db_go || exit 10 # back up

db_get lilo-installer/bootdev

case "$RET" in
	*Master*|*RAID*) bootdev=$(mapdevfs $disc_offered_devfs)  ;;
	*Debian*)
		bootdev=$(mapdevfs $bootfs_devfs)
		part=$(echo $bootdev | sed 's/.*\([0-9]\)/\1/')
	;;
	*Advanced*)
		not_done=1
		db_set lilo-installer/manual_bootdev "$disc_offered_devfs" || true

		while [ $not_done -eq 1 ]; do
			db_input critical lilo-installer/manual_bootdev || true
			db_go || exit 10
			db_get lilo-installer/manual_bootdev
	
			case "$RET" in
				/dev/[hs]d[a-z]*|/dev/md*)
					bootdev="$(mapdevfs $RET)";
					not_done=0
					part=$(echo $bootdev | sed 's/.*\([0-9]\)/\1/')
				;;
			esac

			if [ $not_done -eq 1 ]; then
				db_subst lilo-installer/manual_bootdev_error path "$RET"
				db_input critical lilo-installer/manual_bootdev_error || true
				db_go || exit 10
			fi
		done
	  ;;
esac

if echo "${bootdev}" | grep -q '^/dev/md'; then
	raid_boot="yes"
	raid_extra_boot="raid-extra-boot=mbr-only"
else
	raid_boot="no"
	raid_extra_boot="# raid-extra-boot=mbr-only"
fi

db_subst lilo-installer/progress_active bootdev "$bootdev"
db_subst lilo-installer/progress_running bootdev "$bootdev"

db_progress start 0 4 lilo-installer/progress_title

db_progress info lilo-installer/progress_active

# If installing to a partition (not MBR), offer to make it active
# Do not try to make MD device active
if (echo "${bootdev}" | grep -v '/c[0-9]d[0-9]$' | grep -q '[0-9]$') \
  && [ "${raid_boot}" = "no" ]; then
	# Installing to a partition, check if it is already marked active
	if ! fdisk -l ${disc_offered_devfs} | grep "^/dev[a-z0-9/]\+\([hs]d[a-z]\)${part} " | grep -q '\*'; then
		# partition is not marked active, offer to make it so
		db_input high lilo-installer/activate-part || [ $? -eq 30 ]
		if ! db_go; then
			db_progress stop
			exit 10 # back up
		fi
		db_get lilo-installer/activate-part
		if [ "${RET}" = "true" ]; then
			pnum=$(echo ${bootdev} | sed 's/^.*\([0-9]\+\)$/\1/')
			echo -n "I: Setting partition to active..." >&2
			sfdisk -A${pnum} ${disc_offered_devfs}
			echo "done." >&2
		fi
	fi
fi

# Make sure that there's *some* active partition; some BIOSes reportedly
# don't like it otherwise.
if [ "${raid_boot}" = no ] && (! fdisk -l "$disc_offered_devfs" | grep '^/dev/' | grep -q '\*'); then
	# Check whether they already chose not to make their boot partition
	# active. If so, that's their problem ...
	db_get lilo-installer/activate-part
	if [ "$RET" = true ]; then
		# bootdev must be set to a disk rather than a partition,
		# or we'd already have an active partition due to the 
		# previous check. Let's just pick the partition containing
		# /boot.
		pnum="$(echo "$bootfs" | sed 's/^.*\([0-9]\+\)$/\1/')"
		echo -n "I: Setting partition $bootfs to active..." >&2
		sfdisk -A"$pnum" "$disc_offered_devfs"
		echo "done." >&2
	fi
fi

db_progress step 1

# Use a serial console if current default console is a serial port.
# default console is last listed
OLDIFS="$IFS"
IFS=" "
for arg in $(cat /proc/cmdline); do
	case "$arg" in
		console=*)
			defconsole=$arg
		;;
	esac
done
IFS="$OLDIFS"

defconsole=$(sed -e 's/.*console=\([^ ]*\).*/console=\1/' /proc/cmdline)
if echo "$defconsole" | grep -q console=ttyS; then
	PORT=$(echo "$defconsole" | sed -e 's%^console=ttyS%%' -e 's%,.*%%')
	if echo "$defconsole" | grep -q ','; then
		SPEED=$(echo "$defconsole" | sed -e 's%^console=ttyS[0-9]\+,%%' -e 's% .*%%')
		SERIAL="$PORT,$SPEED"
		db_subst lilo-installer/port-speed SPEED "${SPEED}"
		db_metaget lilo-installer/port-speed Description
		PORT_SPEED="$RET"
	else
		SERIAL="$PORT"
	fi

	db_subst lilo-installer/serial-console PORT "ttyS${PORT}"
	db_subst lilo-installer/serial-console PORT_SPEED "${PORT_SPEED}"
	db_input medium lilo-installer/serial-console || [ $? -eq 30 ]
	if ! db_go; then
		db_progress stop
		exit 10 # back up
	fi
fi

db_progress info lilo-installer/progress_lilo_conf

update_mtab

user_params=$(echo $(user-params | grep -v 'vga=')) || true
if [ -n "$user_params" ]; then
	APPEND="    append=\"$user_params\""
fi

VGA=$(user-params | grep 'vga=') || true
if [ -z "VGA" ]; then
	VGA="vga=normal"
fi

#write out lilo.conf

if [ "${SERIAL}" ]; then
	SERIAL_CONSOLE="serial=${SERIAL}"
else
	SERIAL_CONSOLE="# serial="
fi

if [ "${SERIAL}" ]; then
	if [ -n "$user_params" ]; then
		APPEND="	append=\"$user_params console=ttyS${SERIAL}\""
	else
		APPEND="	append=\"console=ttyS${SERIAL}\""
	fi
fi

if db_get base-installer/kernel/linux/link_in_boot; then
	if [ "$RET" = "true" ]; then
		BOOT="/boot"
	fi
else
	log "warning: Failed to get debconf answer 'base-installer/kernel/linux/link_in_boot'."
fi

if [ -L "/target${BOOT}/initrd.img" ] || [ -e "/target${BOOT}/initrd.img" ] ; then
	INITRD="	initrd=${BOOT}/initrd.img"
	OLD_INITRD="${INITRD}.old"
fi

cat > /target/etc/lilo.conf <<EOF
# /etc/lilo.conf - See: \`lilo(8)' and \`lilo.conf(5)',
# ---------------       \`install-mbr(8)', \`/usr/share/doc/lilo/',
#                       and \`/usr/share/doc/mbr/'.

# +---------------------------------------------------------------+
# |                        !! Reminder !!                         |
# |                                                               |
# | Don't forget to run \`lilo' after you make changes to this     |
# | conffile, \`/boot/bootmess.txt' (if you have created it), or   |
# | install a new kernel.  The computer will most likely fail to  |
# | boot if a kernel-image post-install script or you don't       |
# | remember to run \`lilo'.                                       |
# |                                                               |
# +---------------------------------------------------------------+

# Specifies the boot device.  This is where Lilo installs its boot
# block.  It can be either a partition, or the raw device, in which
# case it installs in the MBR, and will overwrite the current MBR.
#
boot=${bootdev}

# Specifies the device that should be mounted as root. (\`/')
#
root=${rootfs}

# This option may be needed for some software RAID installs.
#
${raid_extra_boot}

# Enable map compaction:
# Tries to merge read requests for adjacent sectors into a single
# read request. This drastically reduces load time and keeps the
# map smaller.  Using \`compact' is especially recommended when
# booting from a floppy disk.  It is disabled here by default
# because it doesn't always work.
#
# compact

# Installs the specified file as the new boot sector
# You have the choice between: text, bmp, and menu
# Look in lilo.conf(5) manpage for details
#
#install=menu

# Specifies the location of the map file
#
map=/boot/map

# You can set a password here, and uncomment the \`restricted' lines
# in the image definitions below to make it so that a password must
# be typed to boot anything but a default configuration.  If a
# command line is given, other than one specified by an \`append'
# statement in \`lilo.conf', the password will be required, but a
# standard default boot will not require one.
#
# This will, for instance, prevent anyone with access to the
# console from booting with something like \`Linux init=/bin/sh',
# and thus becoming \`root' without proper authorization.
#
# Note that if you really need this type of security, you will
# likely also want to use \`install-mbr' to reconfigure the MBR
# program, as well as set up your BIOS to disallow booting from
# removable disk or CD-ROM, then put a password on getting into the
# BIOS configuration as well.  Please RTFM \`install-mbr(8)'.
#
# password=tatercounter2000

# Specifies the number of deciseconds (0.1 seconds) LILO should
# wait before booting the first image.
#
delay=20

# You can put a customized boot message up if you like.  If you use
# \`prompt', and this computer may need to reboot unattended, you
# must specify a \`timeout', or it will sit there forever waiting
# for a keypress.  \`single-key' goes with the \`alias' lines in the
# \`image' configurations below.  eg: You can press \`1' to boot
# \`Linux', \`2' to boot \`LinuxOLD', if you uncomment the \`alias'.
#
# message=/boot/bootmess.txt
#	prompt
#	delay=100
#	timeout=100

# Specifies the VGA text mode at boot time. (normal, extended, ask, <mode>)
#
# vga=ask
# vga=9
#
${VGA}

# Kernel command line options that apply to all installed images go
# here.  See: The \`boot-prompt-HOWTO' and \`kernel-parameters.txt' in
# the Linux kernel \`Documentation' directory.
#
# append=""
 
# If you used a serial console to install Debian, this option should be
# enabled by default.
${SERIAL_CONSOLE}

#
# Boot up Linux by default.
#
default=Linux

image=${BOOT}/vmlinuz
	label=Linux
	read-only
#	restricted
#	alias=1
${APPEND}
${INITRD}

image=${BOOT}/vmlinuz.old
	label=LinuxOLD
	read-only
	optional
#	restricted
#	alias=2
${APPEND}
${OLD_INITRD}


# If you have another OS on this machine to boot, you can uncomment the
# following lines, changing the device name on the \`other' line to
# where your other OS' partition is.
#
# other=/dev/hda4
#	label=HURD
#	restricted
#	alias=3
EOF

# Add other OSes.
probed="$(os-prober)" || true
count=2

OLDIFS="$IFS"
IFS="$newline"

if [ -n "$probed" ]; then
	for os in $probed; do
		IFS="$OLDIFS"
		partition=$(echo "$os" | cut -d: -f1)
		mappedpartition=$(mapdevfs $partition)
		label=$(echo "$os" | cut -d: -f3)
		type=$(echo "$os" | cut -d: -f4)
		case "$type" in
			chain)
				cat >> /target/etc/lilo.conf <<EOF
other=$mappedpartition
	label=$label
#	restricted
#	alias=$count
EOF
			;;
			*)
				info "unhandled: $os"
			;;
		esac
		IFS="$newline"
	done
	IFS="$OLDIFS"
fi

db_progress step 1

db_progress info lilo-installer/progress_installing

mount -t proc none /target/proc || true

if ! apt-install lilo ; then
	info "Calling 'apt-install lilo' failed"
	# Hm, unable to install lilo into /target/, what should we do?
	db_input critical lilo-installer/apt-install-failed || [ $? -eq 30 ]
	if ! db_go; then
		db_progress stop
		exit 10 # back up to menu
	fi
	db_get lilo-installer/apt-install-failed
	if [ true != "$RET" ] ; then
		db_progress stop
		exit 1
	fi
fi

db_progress step 1

db_progress info lilo-installer/progress_running

ERRCODE=0
log-output -t lilo-installer chroot /target /sbin/lilo || ERRCODE=$?
if [ "$ERRCODE" != 0 ]; then
	db_subst lilo-installer/failed ERRCODE "$ERRCODE"
	db_input critical lilo-installer/failed || [ $? -eq 30 ]
	db_progress stop
	db_go || exit 10 # back up
	exit 1
fi

umount /target/proc || true

db_progress step 1

db_progress stop

sed -e 's/do_bootloader = no/do_bootloader = yes/' -e 's/postinst_hook = \(\/sbin\/\|\)update-grub//' -e 's/postrm_hook   = \(\/sbin\/\|\)update-grub//' < /target/etc/kernel-img.conf > /target/etc/kernel-img.conf.$$
mv /target/etc/kernel-img.conf.$$ /target/etc/kernel-img.conf
