#!/bin/sh
# Some parts of this script are inspired by new systemd-boot maintainer scripts from Luca Boccassi
set -e

#
# Variables
#

MOK_DIR="/var/lib/shim-signed/mok"
MOK_KEY="$MOK_DIR/MOK.priv"
MOK_PEM="$MOK_DIR/MOK.pem"

# ESP
if command -v bootctl >/dev/null 2>&1 ; then
  ESP="$(bootctl --quiet --print-esp-path 2>/dev/null)"
fi

# Architecture
case "$(dpkg --print-architecture)" in
  amd64) EFI_ARCH_UPPER="X64" ; EFI_ARCH="x64" ;;
  arm64) EFI_ARCH_UPPER="AA64" ; EFI_ARCH="aa64" ;;
  *) EFI_ARCH="none" ;;
esac

# Vendor name
. /etc/os-release || . /usr/lib/os-release
VENDOR="${ID:-debian}"
VENDOR_UPPER="$(printf %s "$VENDOR" | cut -c1 | tr '[:lower:]' '[:upper:]')$(printf %s "$VENDOR" | cut -c2-)"

# systemd-boot binary
SYSTEMD_BOOT="/usr/lib/systemd/boot/efi/systemd-boot$EFI_ARCH.efi"


#
# Functions
#

# Sign systemd-boot EFI
sign_systemd_boot () {
  # Check if signed systemd-boot belongs to a package
  if [ -z "$(dpkg -S $SYSTEMD_BOOT.signed 2>/dev/null)" ] ; then
    # Check signature
    if ( [ ! -f "$SYSTEMD_BOOT.signed" ] || ! sbverify --cert "$MOK_PEM" $SYSTEMD_BOOT.signed >/dev/null ) ; then
      # Sign EFI binary with MOK
      printf "Signing '%s' with MOK...\n" "$SYSTEMD_BOOT"
      sbsign --key "$MOK_KEY" --cert "$MOK_PEM" "$SYSTEMD_BOOT" --output "$SYSTEMD_BOOT.signed"
    fi
  fi
}

# Compare MD5 sums of two files
compare_md5 () {
  local FILE SRC DST
  for FILE ; do [ -f "$FILE" ] || return 1 ; done
  SRC="$1" ; DST="$2"
  [ "$(md5sum < "$SRC")" = "$(md5sum < "$DST")" ] || return 1
}

# Update file from system to ESP if needed
update_file () {
  local SRC DST
  SRC="$1" ; DST="$2"
  if ( [ -f "$SRC" ] && ! compare_md5 "$SRC" "$DST" ) ; then
    printf "Installing '%s' to '%s'...\n" "$SRC" "$DST"
    install -p -D "$SRC" "$DST"
  fi
}

# Check boot entry
check_boot_entry () {
  # 730079007300740065006d0064002d0062006f006f007400 is 'systemd-boot' encoded in UTF-16-LE"
  EFI_ARCH_DOTS="$(printf %s "$EFI_ARCH" | sed 's/./&./g')"
  efibootmgr -v | grep -E -i "Boot.*$VENDOR_UPPER.*EFI\\\\$VENDOR\\\\shim$EFI_ARCH.efi.*(s.y.s.t.e.m.d.-.b.o.o.t.$EFI_ARCH_DOTS..e.f.i|730079007300740065006d0064002d0062006f006f007400)" | sed -E 's/^Boot(.{4}).*$/\1/'
}

# Install shim files
install_shim () {

  # Check variables
  [ -n "$ESP" ] || return
  [ "$EFI_ARCH" = "none" ] && return

  # Copy files to ESP
  for FILE in shim fb mm ; do
    SRC="/usr/lib/shim/$FILE$EFI_ARCH.efi.signed"
    DST="$ESP/EFI/$VENDOR/$FILE$EFI_ARCH.efi"
    update_file "$SRC" "$DST"

    # Also copy files to the default path
    case "$FILE" in
      shim) DST="$ESP/EFI/BOOT/BOOT$EFI_ARCH_UPPER.efi" ;;
      fb|mm) DST="$ESP/EFI/BOOT/$FILE$EFI_ARCH.efi" ;;
    esac
    update_file "$SRC" "$DST"
  done

  # Copy signed systemd-boot
  SRC="$SYSTEMD_BOOT.signed"
  DST="$ESP/EFI/systemd/${SYSTEMD_BOOT##*/}"
  update_file "$SRC" "$DST"

  # Create CSV file if missing
  FILE="$ESP/EFI/$VENDOR/BOOT$EFI_ARCH_UPPER.CSV"
  if ! ( [ -f "$FILE" ] && iconv -f UCS-2 "$FILE" | grep -q systemd-boot ) ; then
    printf "Creating/updating CSV file for shim fallback\n"
    printf "shim%s.efi,%s,\\\EFI\systemd\systemd-boot%s.efi \\\0,This is the boot entry for %s\n" "$EFI_ARCH" "$VENDOR_UPPER" "$EFI_ARCH" "$VENDOR_UPPER" | iconv -t UCS-2 > "$FILE"
  fi

  # Install boot entry
  if [ -z "$(check_boot_entry)" ] ; then
    PART="$(findmnt -nvo SOURCE "$ESP")" ; PART="/sys/class/block/${PART##*/}"
    [ -h "$PART" ] || return
    DRIVE="$(readlink -f "$PART")" ; DRIVE="${DRIVE%/*}" ; DRIVE="/dev/${DRIVE##*/}"
    PARTNUM="$(cat "$PART/partition")"
    printf "Creating EFI boot entry '%s'...\n" "$VENDOR_UPPER"
    efibootmgr -q --create --disk "$DRIVE" --part "$PARTNUM" --loader "/EFI/$VENDOR/shim$EFI_ARCH.efi" --label "$VENDOR_UPPER" --unicode "\EFI\systemd\systemd-boot$EFI_ARCH.efi \0"
  fi
}


#
# Main
#

case "$1" in
  configure)

    # On first install, create missing kernel files
    if [ -z "$2" ] ; then

      FILE="/etc/kernel/cmdline"
      if [ ! -f "$FILE" ] ; then
        printf "Creating '%s'...\n" "$FILE"
        sed 's/^BOOT_IMAGE=[^ ]* // ; s/ *systemd.machine_id=[^ ]*//' /proc/cmdline > "$FILE"
      fi

      FILE="/etc/kernel/tries"
      if [ ! -f "$FILE" ] ; then
        printf "Creating '%s'...\n" "$FILE"
        printf "2\n" > "$FILE"
      fi

    fi

    # Sign systemd-boot and install shim
    sign_systemd_boot
    install_shim
  ;;

  triggered)
    sign_systemd_boot
    install_shim
  ;;

  abort-upgrade|abort-remove|abort-deconfigure)
  ;;

  *)
    printf "postinst called with unknown argument '%s'\n" "$1" >&2
    exit 1
  ;;
esac

#DEBHELPER#

exit 0
