#!/bin/sh
# Copyright 2013, 2016, 2017  Patrick Volkerding, Sebeka, Minnesota, USA
# All rights reserved.
#
# Modified by George Vlahavas for Salix, 2016
# Modified by Didier Spaier for gettext support, 2016
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
#  EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
#  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
#  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

# This script installs the elilo boot loader, the kernel, and optionally
# an initrd into the EFI System Partition.  A boot menu entry can also be
# installed using efibootmgr.  The kernel used will be whatever the symlink
# /boot/vmlinuz points to, and if /boot/initrd.gz exists, that will be 
# installed as the initrd.
#
# The EFI System Partition is expected to be mounted on /boot/efi before
# running this script.

TMP=/var/log/setup/tmp

# Set the OS root directory (called T_PX for some unknown reason).
# If an argument is given to this script and it is a directory, it
# is taken to be the root directory.  First though, we check for a
# directory named $T_PX, and that gets the first priority.
if [ ! -d "$T_PX" ]; then
  if [ ! "$1" = "" ]; then
    if [ -d "$1" ]; then
      T_PX="$1"
    fi
  else
    # Are we on the installer image?
    if [ -r /usr/lib/setup/SeTpartitions ]; then
      T_PX=/mnt
    # Or, are we on a running system?
    elif [ -r /etc/slackware-version ]; then
      T_PX=/
    # One more installer-likely thing:
    elif [ -r /usr/lib/setup/setup ]; then
      T_PX=/mnt
    else
      # We will have to assume we're on an installed and running system.
      T_PX=/
    fi
  fi
fi

# Use gettext for translations
export TEXTDOMAIN=eliloconfig
export TEXTDOMAINDIR="$T_PX/usr/share/locale"
. gettext.sh

# Determine the root partition (such as /dev/sda1)
ROOT_DEVICE=$2
if [ "$ROOT_DEVICE" = "" ]; then
 if [ -r $TMP/SeTrootdev ]; then
  ROOT_DEVICE="$(cat $TMP/SeTrootdev)"
 else
  ROOT_DEVICE="$(mount | cut -f 1 -d ' ' | head -n 1)"
 fi
fi

# If the system is not running under EFI, skip running this script:
if [ ! -d /sys/firmware/efi ]; then
  if [ "$T_PX" = "/" ]; then
    gettext "ERROR:  System is not running under UEFI."
    echo
  fi
  exit
fi

# If there's no vfat mounted on /boot/efi or $T_PX/boot/efi, forget it:
if ! mount | grep vfat | grep -wq /boot/efi ; then
  if ! mount | grep vfat | grep -wq $T_PX/boot/efi ; then
    if [ "$T_PX" = "/" ]; then
      gettext "ERROR:  No EFI System Partition mounted on /boot/efi."
      echo
    fi
    exit
  fi
fi

# Figure out the device and partition number of the ESP:
DEVLEN=8
PARTLEN=9
if mount | grep vfat | grep -wq /boot/efi ; then
  mount | grep vfat | grep -w /boot/efi | grep -q -e nvme -e mmcblk && DEVLEN=12 && PARTLEN=14
  EFI_DEVICE=$(mount | grep vfat | grep -w /boot/efi | cut -b 1-${DEVLEN})
  EFI_PARTITION=$(mount | grep vfat | grep -w /boot/efi | cut -f 1 -d ' ' | cut -b ${PARTLEN}- | tr -d [a-z])
else
  mount | grep vfat | grep -w $T_PX/boot/efi | grep -q -e nvme -e mmcblk && DEVLEN=12 && PARTLEN=14
  EFI_DEVICE=$(mount | grep vfat | grep -w $T_PX/boot/efi | cut -b 1-${DEVLEN})
  EFI_PARTITION=$(mount | grep vfat | grep -w $T_PX/boot/efi | cut -f 1 -d ' ' | cut -b ${PARTLEN}- | tr -d [a-z])
fi

# There better be a kernel:
if [ ! -r $T_PX/boot/vmlinuz ]; then
  if [ "$T_PX" = "/" ]; then
    gettext "ERROR:  No kernel found at /boot/vmlinuz."
    echo
  fi
  exit
fi

# Determine full distro name
#
# OK, so this is the main distro name:
DNAME="Salix"
# Let's start with blank edition and version
EDITION=""
VERSION=""
# If an edition file exists, use it.
if [ -f $T_PX/etc/salix-edition ]; then
  EDITION="-`grep -v '^#' $T_PX/etc/salix-edition | head -n 1 | tr ' ' '_'`"
fi
# Now, let's determine the version
# this should always be there in a salix installation
if [ -f $T_PX/usr/share/salixtools/salix-version ]; then
  VERSION="-`cat $T_PX/usr/share/salixtools/salix-version`"
# or maybe it's a slint installation that does not have salixtools. In
# that case, extract the version from the slint-version file.
elif [ -f $T_PX/etc/slint-version ]; then
  DNAME="Slint"
  VERSION="-`head -n 1 $T_PX/etc/slint-version | sed "s/Slint//" | tr -d ' '`"
# or finally, get the version as it appears in the slackware-version
# file
elif [ -f $T_PX/etc/slackware-version ]; then
  DNAME="Slackware"
  VERSION="-`head -n 1 $T_PX /etc/slackware-version | sed "s/Slackware//" | tr -d ' '`"
fi
FULL_DISTRO_NAME="${DNAME}${EDITION}${VERSION}"


dialog --title "`gettext "INSTALL ELILO"`" \
--backtitle "`gettext "ELILO (EFI Linux Loader) installation"`" \
--menu "`gettext "ELILO is a Linux boot loader for \
EFI based systems.  Installing ELILO will allow you to boot your Linux \
system from the hard drive after selecting it from the UEFI boot menu.  \
Since an EFI System Partition was detected on this machine, it is \
recommended that you install ELILO now.  Please select an option:"`" \
0 0 0 \
"install" "`gettext "Install ELILO on the EFI System Partition"`" \
"skip" "`gettext "Do not install ELILO"`" 2> $TMP/reply
if [ $? = 1 -o $? = 255 ]; then
  exit
fi
REPLY="`cat $TMP/reply`"
rm -f $TMP/reply
if [ "$REPLY" = "skip" ]; then
  exit
fi

mkdir -p $T_PX/boot/efi/EFI/${FULL_DISTRO_NAME} 1> /dev/null 2> /dev/null
cat << EOF > $T_PX/boot/efi/EFI/${FULL_DISTRO_NAME}/elilo.conf
chooser=simple
delay=1
timeout=1
#
EOF
cp -a $T_PX/boot/elilo-x86_64.efi $T_PX/boot/efi/EFI/${FULL_DISTRO_NAME}/elilo.efi 1> /dev/null 2> /dev/null
cp $T_PX/boot/vmlinuz $T_PX/boot/efi/EFI/${FULL_DISTRO_NAME} 1> /dev/null 2> /dev/null
cat << EOF >> $T_PX/boot/efi/EFI/${FULL_DISTRO_NAME}/elilo.conf
image=vmlinuz
        label=vmlinuz
EOF
touch -r $T_PX/boot/vmlinuz $T_PX/boot/efi/EFI/${FULL_DISTRO_NAME}/vmlinuz
if [ -r $T_PX/boot/initrd.gz ]; then
  cp $T_PX/boot/initrd.gz $T_PX/boot/efi/EFI/${FULL_DISTRO_NAME} 1> /dev/null 2> /dev/null
  touch -r $T_PX/boot/initrd.gz $T_PX/boot/efi/EFI/${FULL_DISTRO_NAME}/initrd.gz
  cat << EOF >> $T_PX/boot/efi/EFI/${FULL_DISTRO_NAME}/elilo.conf
        initrd=initrd.gz
EOF
fi
cat << EOF >> $T_PX/boot/efi/EFI/${FULL_DISTRO_NAME}/elilo.conf
        read-only
        append="root=$ROOT_DEVICE vga=normal ro"
EOF

dialog --title "`gettext "INSTALL BOOT MENU ENTRY?"`" \
--backtitle "`gettext "ELILO (EFI Linux Loader) installation"`" \
--menu "`gettext "Would you like to install \
a boot menu entry so that you can easily select Salix when you boot your \
machine?  WARNING:  DO NOT install a boot menu entry on Apple hardware.  \
Apple computers use a different type of EFI firmware, and efibootmgr has \
been known to damage them.  On all other computers, it is recommended to add \
a boot menu entry.  Please select an option:"`" \
0 0 0 \
"install" "`gettext "Install a boot menu entry"`" \
"skip" "`gettext "Do not install a boot menu entry"`" 2> $TMP/reply
if [ $? = 1 -o $? = 255 ]; then
  exit
fi
REPLY="`cat $TMP/reply`"
rm -f $TMP/reply
if [ "$REPLY" = "skip" ]; then
  exit
fi

if [ ! -d /sys/firmware/efi/vars ]; then
  modprobe efivars 1> /dev/null 2> /dev/null
  sleep 1 # Probably not needed, but playing it safe
fi
# If it's still gone, we fail silently:
if [ ! -d /sys/firmware/efi/vars ]; then
  exit
fi

efibootmgr -v | rev | cut -f 2- | rev | grep Boot0 | grep "${FULL_DISTRO_NAME}" | while read line ; do
  # Reject entries that don't exactly match as not our business
  if [ ! "$(echo $line | cut -f 2- -d ' ')" = "${FULL_DISTRO_NAME}" ]; then
    continue
  fi
  ENTRY="$(efibootmgr -v | grep "^$(echo $line | cut -b1-8)")"
  dialog --title "`gettext "REMOVE OLD \"Salix\" EFI BOOT ENTRY?"`" \
  --backtitle "`gettext "ELILO (EFI Linux Loader) installation"`" \
  --yesno "`gettext "An old Salix boot entry has been found in your EFI boot menu. \
Would you like to remove this before installing the new Salix boot \
entry?  This is recommended.

Old EFI boot menu entry:"`
$ENTRY" 0 0
  if [ ! $? = 0 ]; then
    continue
  fi
  # Remove the boot entry:
  efibootmgr -q -B -b $(echo $line | cut -b5-8)
done

efibootmgr -q -c -d $EFI_DEVICE -p $EFI_PARTITION -l "\\EFI\\${FULL_DISTRO_NAME}\\elilo.efi" -L "${FULL_DISTRO_NAME}"

efibootmgr -v | rev | cut -f 2- | rev | grep Boot0 | grep "${FULL_DISTRO_NAME}" | while read line ; do
  # Reject entries that don't exactly match as not our business
  if [ ! "$(echo $line | cut -f 2- -d ' ')" = "${FULL_DISTRO_NAME}" ]; then
    continue
  fi
  ENTRY="$(efibootmgr -v | grep "^$(echo $line | cut -b1-8)")"
  if echo $ENTRY | grep -q -F "\EFI\${FULL_DISTRO_NAME}\elilo.efi" ; then
  dialog --title "`gettext "EFI BOOT ENTRY INSTALLED"`" \
  --backtitle "`gettext "ELILO (EFI Linux Loader) installation"`" \
  --msgbox "`gettext "A Salix boot entry has been installed to your EFI boot
menu.

EFI boot menu entry:"`
$ENTRY" 0 0
  fi
done

# Done.