#! /bin/bash

# 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
#


# If the default EFI boot file is signed by SUSE, assume we have to also update it.
#
# This is also the logic shim uses.
#
check_update_default ()
{
  . /etc/os-release

  case "$NAME" in
    SLE*)
      ca_string='SUSE Linux Enterprise Secure Boot CA1';;
    openSUSE*)
      ca_string='openSUSE Secure Boot CA1';;
  esac

  efi_default_file="/boot/efi/EFI/boot/$efi_default"

  update_default=0

  # install/update default location if it is 'our' file
  if [ -n "$ca_string" -a -f $efi_default_file ] ; then
    grep -q "$ca_string" $efi_default_file && update_default=1
  fi
}

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

target=$(uname --hardware-platform)

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

fw_platform_size=$(cat /sys/firmware/efi/fw_platform_size 2>/dev/null)

case "$target" in
  i?86 ) target=i386 efi_default=bootia32.efi ;;
  x86_64 | amd64 )
    target=x86_64 efi_default=bootx64.efi
    if [ "$fw_platform_size" = 32 ] ; then
      target=i386 efi_default=bootia32.efi
      # no 32 bit shim
      SYS__BOOTLOADER__SECURE_BOOT=no
    fi
    ;;
  aarch64 ) target=arm64 efi_default=bootaa64.efi ;;
  arm* ) target=arm efi_default=bootarm.efi ;;
esac

check_update_default

target="$target-efi"

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

# EFI has 2 boot paths. The default is that there is a target file listed in
# the boot list. The boot list is stored in NVRAM and exposed as efivars.
#
# If no entry in the boot list was bootable (or a removable media is in the
# boot list), EFI falls back to removable media booting which loads a default
# file from /efi/boot/boot.efi.
#
# On U-Boot EFI capable systems we do not have NVRAM because we would have to
# store that on the same flash that Linux may be running on, creating device
# ownership conflicts. So on those systems we instead have to rely on the
# removable boot case.
#
# The easiest heuristic is that on "normal" EFI systems with working NVRAM,
# there is at least one efi variable visible. On systems without working NVRAM,
# we either see no efivars at all (booted via non-EFI entry point) or there is
# no efi variable exposed. Install grub in the removable location there.
no_nvram_opts="--no-nvram --removable"
has_nvram=0
append=
if [ ! -d /sys/firmware/efi/efivars -o ! -w /sys/firmware/efi/efivars -o ! "$(ls -A /sys/firmware/efi/efivars)" ] ; then
  append="$no_nvram_opts"
  # no need to *additionally* update default location
  update_default=0
else
  has_nvram=1
  # some arm firmwares need the fallback even though they have nvram vars (bsc#1167015)
  if [ "$target" = "arm64-efi" ] ; then
    update_default=1
  fi
fi

echo "target = $target, update default location = $update_default"

if [ "$SYS__BOOTLOADER__TRUSTED_BOOT" = yes ] && [ -f "/usr/lib/grub2/$target/tpm.mod" -o -f "/usr/share/grub2/$target/tpm.mod" ] ; then
  append="$append --suse-enable-tpm"
fi

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

if [ "$SYS__BOOTLOADER__SECURE_BOOT" = "yes" -a -x /usr/sbin/shim-install ] ; then
  ( set -x ; /usr/sbin/shim-install --config-file=/boot/grub2/grub.cfg $append )
elif [ -x /usr/sbin/grub2-install ] ; then
  if [ "$SYS__BOOTLOADER__SECURE_BOOT" = "yes" ] ; then
    # use '--suse-force-signed' if supported, when shim is not used
    if check_force_signed ; then
      append="$append --suse-force-signed"
    else
      echo "shim-install: command not found"
      exit 1
    fi
  fi
  ( set -x ; /usr/sbin/grub2-install --target="$target" $append )
  if [ "$update_default" = 1 ] ; then
    if [ -x /usr/sbin/shim-install ] ; then
      # update shim to fallback location given it is used most often
      ( set -x ; /usr/sbin/shim-install --config-file=/boot/grub2/grub.cfg --removable )
    else
      # fallback to signed grub so that check_update_default can still work
      # older grub (<= 2.02) uses /usr/lib
      grub_dir="/usr/share/grub2/$target"
      [ -d "$grub_dir" ] || grub_dir="/usr/lib/grub2/$target"
      # directory may not yet exist in some workflows
      mkdir -p "/boot/efi/EFI/boot"
      ( set -x ; cp "$grub_dir/grub.efi" "/boot/efi/EFI/boot/$efi_default" )
    fi
  fi
else
  echo "grub2-install: command not found"
  exit 1
fi
