#!/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%/} " | 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
}

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\/[a-z]\+\).*/\1/')

case $prefix in
	/dev/md)
		disc_offered_devfs="$bootfs_devfs"
		db_register lilo-installer/bootdev_raid lilo-installer/bootdev
	;;
	/dev/[hs]d[a-z])
		disc_offered_devfs="$prefix"
	;;
	*)
		disc_offered_devfs=$(find $prefix -follow -name disc | head -n 1)
	;;
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)  ;;
  *Ubuntu*)
    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/ide*|/dev/discs/*|/dev/scsi/*|/dev/md/*)
	   if [ -b "$RET" ]; then
	    bootdev="$(mapdevfs $RET)"
	    not_done=0
	    part=$(echo $bootdev | sed 's/.*\([0-9]\)/\1/')
	   fi
	  ;;
	  /dev/[hs]d[a-z]*|/dev/md*)
	    bootdev=$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 -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/]\+\(part\|[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=/' /proc/cmdline)
if echo "${defconsole}" | grep -q console=ttyS; then
    PORT=$(echo "${defconsole}" | sed -e 's%^console=ttyS%%' -e 's%,.*%%')
    SPEED=$(echo "${defconsole}" | sed -e 's%^console=ttyS[0-9]\+,%%' -e 's% .*%%')
    SERIAL="${PORT},${SPEED}"

    db_subst lilo-installer/serial-console PORT "ttyS${PORT}"
    db_subst lilo-installer/serial-console SPEED "${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

user_params=$(echo $(user-params | grep -v 'vga=')) || true

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}"
  console_params="console=ttyS${SERIAL}"
else
  SERIAL_CONSOLE="# serial="
  console_params=""
fi

# forcing root inside append
APPEND="	append=\"root=${rootfs} $user_params $console_params\""

if [ -e "/target/initrd.img" ]; then
  INITRD="	initrd=/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 Ubuntu, this option should be
# enabled by default.
${SERIAL_CONSOLE}

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

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

image=/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
