#! /usr/bin/sh

# Settings from /etc/sysconfig/filename are available as environment vars
# with the name 'SYS__FILENAME__KEY' (filename converted to upper case).
#
# Not all files are parsed, current list is:
#   bootloader, language
#

# Note: if target is "i386-pc" and /etc/default/grub_installdevice is
# missing or does not contain any valid device entry grub will be installed
# on the disk that contains the /boot directory.
#
# If /boot happens to be on a RAID or similar which is composed of several
# physical disks then grub is installed only on one (the 'first') of them.
#

# include common functions
. "$PBL_INCLUDE/library"

# Usage: prep_partition(disk)
#
# Find a PReP partition on a disk
# Partition and disk name are without leading '/dev/'.
#
# Return empty string is there is no PReP partition.
#
prep_partition ()
{
  prep_part=$(/usr/sbin/fdisk -l -o "Device,Type" "/dev/$1" | grep -m1 PReP | cut -d ' ' -f 1)
  prep_part="${prep_part#/dev/}"

  echo "prep_partition($1) = $prep_part" >&2

  echo "$prep_part"
}


# Usage: partition_to_disk(partition)
#
# Find disk device name for a partition.
# Partition and disk name are without leading '/dev/'.
#
# Return empty string if there is no parent disk device for a partition.
#
partition_to_disk ()
{
  ptd_part=$1
  ptd_dev=$(echo /sys/block/*/"$ptd_part")
  # there should normally be just one entry - but better make sure
  ptd_dev=${ptd_dev%% *}

  if [ -d "$ptd_dev" ] ; then
    ptd_dev=${ptd_dev#/sys/block/}
    ptd_dev=${ptd_dev%/"$ptd_part"}
    [ -e "/dev/$ptd_dev" ] && echo "$ptd_dev"
  fi
}


# Usage: first_slave(disk)
#
# Find first slave device for disk.
#
# Return empty string if there are no slaves.
#
first_slave ()
{
  slave_dev=$(echo /sys/block/"$1"/slaves/*)
  slave_dev=${slave_dev%% *}
  slave_dev=${slave_dev##*/}

  [ "$slave_dev" = "*" ] && slave_dev=

  echo "$slave_dev"
}


# Usage: disk_device(arg)
#
# Find disk device name for arg.
# arg may be a partition name or a directory
# Disk name is without leading '/dev/'.
#
# Return empty string if a disk device could not be found.
#
disk_device ()
{
  echo "disk device($1)" >&2

  if [ "${1#/dev/}" = "$1" ] ; then
    while read dd_part ; do
      # starts with '/'
      [ "${dd_part#/}" != "${dd_part}" ] && break
    done < <(df --local --sync --output=source "$1")
  else
    dd_part="$1"
  fi

  [ -n "$dd_part" ] && dd_part=$(readlink -f "$dd_part")
  [ -n "$dd_part" ] && dd_part=${dd_part#/dev/}
  [ -z "$dd_part" ] && exit

  echo "kernel device = $dd_part" >&2

  dd_dev=$dd_part

  while true ; do
    dd_dev1=$(partition_to_disk "$dd_dev")
    if [ -n "$dd_dev1" ] ; then
      echo "disk($dd_dev) = $dd_dev1" >&2
      dd_dev=$dd_dev1
    fi

    # $dd_dev is a disk but not a partition

    dd_dev1=$(first_slave "$dd_dev")

    if [ -n "$dd_dev1" ] ; then
      echo "slave($dd_dev) = $dd_dev1" >&2
      dd_dev=$dd_dev1
      continue
    fi

    break
  done

  echo "disk = $dd_dev" >&2

  echo "$dd_dev"
}

# Check whether grub2-install supports --suse-force-signed.
#
# Exit code 0: supprted, != 0: not supported.
#
check_force_signed ()
{
  if [ "$target" = powerpc-ieee1275 ] ; then
    /usr/sbin/grub2-install --help 2>& 1 | grep -q -- --suse-force-signed
  else
    false
  fi
}

target=$(uname -m)

if [ -z "$target" ] ; then
  echo "no target platform"
  exit 1
fi

case "$target" in
  i?86 | x86_64 ) target=i386-pc needs_installdevice=1 ;;
  ppc | ppc64* ) target=powerpc-ieee1275 needs_installdevice=1 ;;
  s390x ) target=s390x-emu ;;
esac

echo "target = $target"

# We install grub2 at the end of the installation, not within (bsc#979145)
if [ "$YAST_IS_RUNNING" = instsys ]; then
  echo "Skipping grub2 during installation. Will be done at the end"
  exit 0
fi

if [ "$target" = "powerpc-ieee1275" ] ; then
  grep -q PowerNV /proc/cpuinfo && exit 0
fi

append=
if [ "$SYS__BOOTLOADER__UPDATE_NVRAM" = "no" ] ; then
  append="$append --no-nvram"
fi

if [ "$SYS__BOOTLOADER__TRUSTED_BOOT" = yes -a -d "/usr/lib/trustedgrub2/$target" ] ; then
  trusted="--directory=/usr/lib/trustedgrub2/$target"
fi

if check_force_signed ; then
  if [ "$SYS__BOOTLOADER__SECURE_BOOT" = "yes" ] ; then
    append="$append --suse-force-signed"
  else
    append="$append --suse-inhibit-signed"
  fi
fi

err=0
if [ -x /usr/sbin/grub2-install ] ; then
  if [ "$needs_installdevice" = 1 ] ; then
    has_device=
    if [ -r /etc/default/grub_installdevice ] ; then
      while read device ; do
        # ignore everything that doesn't look like a path
        [ "${device#/}" = "${device}" ] && continue
        if [ -b "$device" -o -f "$device" ] ; then
          has_device=1
          ( set -x ; /usr/sbin/grub2-install $append $trusted --target="$target" --force --skip-fs-probe "$device" ) || err=1
        else
          echo "$device: not a block device"
          err=1
        fi
      done </etc/default/grub_installdevice
    fi
    if [ -z "$has_device" ] ; then
      echo "grub_installdevice missing or invalid"
      if [ "$target" = "i386-pc" -o "$target" = "powerpc-ieee1275" ] ; then
        echo "determining suitable boot device"
        device=$(disk_device /boot)
        if [ -n "$device" -a "$target" = "powerpc-ieee1275" ] ; then
          device=$(prep_partition $device)
        fi
        if [ "$device" ] ; then
          device="/dev/$device"
          has_device=1
          err=0
          ( set -x ; /usr/sbin/grub2-install $append $trusted --target="$target" --force --skip-fs-probe "$device" ) || err=1
        fi
      fi
    fi
    if [ -z "$has_device" ] ; then
      echo "no grub2 install device found"
      err=1
    fi
  else
    ( set -x ; /usr/sbin/grub2-install $append $trusted --target="$target" ) || err=1
  fi
else
  echo "grub2-install: command not found"
  err=1
fi

exit $err
