#! /bin/sh
set -e

# grub-mkconfig helper script, installed by sys-kernel/installkernel[grub,uki]
#
# Copyright 2025 Gentoo Authors
# Distributed under the terms of the GNU General Public License v3+
#
# Bug: https://bugs.gentoo.org/942201

prefix="/usr"
exec_prefix="/usr"
datarootdir="/usr/share"

. "$pkgdatadir/grub-mkconfig_lib"

export TEXTDOMAIN=grub
export TEXTDOMAINDIR="${datarootdir}/locale"

# loop-AES arranges things so that /dev/loop/X can be our root device, but
# the initrds that Linux uses don't like that.
case ${GRUB_DEVICE} in
  /dev/loop/*|/dev/loop[0-9])
    GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
  ;;
esac

: ${GRUB_CMDLINE_LINUX_RECOVERY:=single}

# Default to disabling partition uuid support to maintian compatibility with
# older kernels.
: ${GRUB_DISABLE_LINUX_PARTUUID=true}

# btrfs may reside on multiple devices. We cannot pass them as value of root= parameter
# and mounting btrfs requires user space scanning, so force UUID in this case.
if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] && [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] ) \
    || ( [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
	&& [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ] ) \
    || ( ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
	&& ! test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ) \
    || ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then
  LINUX_ROOT_DEVICE=${GRUB_DEVICE}
elif [ "x${GRUB_DEVICE_UUID}" = "x" ] \
    || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ]; then
  LINUX_ROOT_DEVICE=PARTUUID=${GRUB_DEVICE_PARTUUID}
else
  LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
fi

case x"$GRUB_FS" in
    xbtrfs)
	rootsubvol="`make_system_path_relative_to_its_root /`"
	rootsubvol="${rootsubvol#/}"
	if [ "x${rootsubvol}" != x ]; then
	    GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
	fi;;
    xzfs)
	rpool=`${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true`
	bootfs="`make_system_path_relative_to_its_root / | sed -e "s,@$,,"`"
	LINUX_ROOT_DEVICE="ZFS=${rpool}${bootfs%/}"
	;;
esac

title_correction_code=

linux_entry ()
{
  os="$1"
  version="$2"
  type="$3"
  args="$4"

  class="--class ${os} --class gnu-linux --class gnu --class os"

  if [ -z "$boot_device_id" ]; then
      boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
  fi
  if [ x$type != xsimple ] ; then
      case $type in
	  recovery)
	      title="$(gettext_printf "%s, with UKI %s (recovery mode)" "${os}" "${version}")" ;;
	  *)
	      title="$(gettext_printf "%s, with UKI %s" "${os}" "${version}")" ;;
      esac
      if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then
	  replacement_title="$(echo "Advanced options for ${os}" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')"
	  quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"
	  title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
	  grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")"
      fi
      echo "menuentry '$(echo "$title" | grub_quote)' ${class} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
  else
      echo "menuentry '$(echo "$os" | grub_quote)' ${class} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
  fi
  if [ x$type != xrecovery ] ; then
      save_default_entry | grub_add_tab
  fi

  # Use ELILO's generic "efifb" when it's known to be available.
  # FIXME: We need an interface to select vesafb in case efifb can't be used.
  if [ "x$GRUB_GFXPAYLOAD_LINUX" = x ]; then
      echo "	load_video" | sed "s/^/$submenu_indentation/"
      if grep -qx "CONFIG_FB_EFI=y" "${config}" 2> /dev/null \
	  && grep -qx "CONFIG_VT_HW_CONSOLE_BINDING=y" "${config}" 2> /dev/null; then
	  echo '	if [ "x$grub_platform" = xefi ]; then' | sed "s/^/$submenu_indentation/"
	  echo "		set gfxpayload=keep" | sed "s/^/$submenu_indentation/"
	  echo '	fi' | sed "s/^/$submenu_indentation/"
      fi
  else
      if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then
	  echo "	load_video" | sed "s/^/$submenu_indentation/"
      fi
      echo "	set gfxpayload=$GRUB_GFXPAYLOAD_LINUX" | sed "s/^/$submenu_indentation/"
  fi

  echo "	insmod chain" | sed "s/^/$submenu_indentation/"

  if [ x$dirname = x/ ]; then
    if [ -z "${prepare_root_cache}" ]; then
      prepare_root_cache="$(prepare_grub_to_access_device ${esp} | grub_add_tab)"
    fi
    printf '%s\n' "${prepare_root_cache}" | sed "s/^/$submenu_indentation/"
  else
    if [ -z "${prepare_boot_cache}" ]; then
      prepare_boot_cache="$(prepare_grub_to_access_device ${esp} | grub_add_tab)"
    fi
    printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/"
  fi
  message="$(gettext_printf "Loading UKI %s ..." ${version})"
  sed "s/^/$submenu_indentation/" << EOF
	echo	'$(echo "$message" | grub_quote)'
	chainloader	${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
EOF
  sed "s/^/$submenu_indentation/" << EOF
}
EOF
}

machine=`uname -m`
globs="$GRUB_UKI_GLOBS"
[ -z "$globs" ] && globs="/boot/EFI/Linux/*.efi /boot/EFI/EFI/Linux/*.efi /boot/efi/EFI/Linux/*.efi /efi/EFI/Linux/*.efi"

list=
for i in ${globs} ; do
    if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi
done

prepare_boot_cache=
prepare_root_cache=
boot_device_id=
title_correction_code=

# Extra indentation to add to menu entries in a submenu. We're not in a submenu
# yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
submenu_indentation=""

# Perform a reverse version sort on the entire list.
# Temporarily replace the '.old' suffix by ' 1' and append ' 2' for all
# other files to order the '.old' files after their non-old counterpart
# in reverse-sorted order.

entry_id_list=
for uki in ${list}; do
  entry_id_list="$entry_id_list $(basename -s .efi ${uki%%-*})"
done

unique_entry_ids=$(echo $entry_id_list | tr ' ' '\n' | sort -u)

reverse_sorted_list=$(echo $list | tr ' ' '\n' | sed -e 's/\.old$/ 1/; / 1$/! s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/ 2$//')

for entry_id in ${unique_entry_ids}; do
  if [ "x$GRUB_TOP_LEVEL" != x ]; then
    reverse_sorted_list=$(grub_move_to_front "$GRUB_TOP_LEVEL" ${reverse_sorted_list})
  fi

  is_top_level=true
  for linux in ${reverse_sorted_list}; do
    base=$(basename -s .efi ${linux})
    if [ "x${base#${entry_id}}" = "x${base}" ]; then
      # UKI does not start with our entry ID
      continue
    fi
    gettext_printf "Found unified kernel image: %s\n" "$linux" >&2
    basename=`basename $linux`
    dirname=`dirname $linux`
    rel_dirname=`make_system_path_relative_to_its_root $dirname`
    esp=`df -P $linux | tail -1 | cut -d' ' -f 1`
    version=`echo $basename | sed -e "s,^[^0-9]*-,,g"`
    alt_version=`echo $version | sed -e "s,\.old$,,g"`
    linux_root_device_thisversion="${LINUX_ROOT_DEVICE}"

    # The GRUB_DISABLE_SUBMENU option used to be different than others since it was
    # mentioned in the documentation that has to be set to 'y' instead of 'true' to
    # enable it. This caused a lot of confusion to users that set the option to 'y',
    # 'yes' or 'true'. This was fixed but all of these values must be supported now.
    if [ "x${GRUB_DISABLE_SUBMENU}" = xyes ] || [ "x${GRUB_DISABLE_SUBMENU}" = xy ]; then
      GRUB_DISABLE_SUBMENU="true"
    fi

    if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then
      linux_entry "${entry_id}" "${version}" simple \
      "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"

      submenu_indentation="$grub_tab"

      if [ -z "$boot_device_id" ]; then
      boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
      fi
      # TRANSLATORS: %s is replaced with an entry ID
      echo "submenu '$(gettext_printf "Advanced options for %s" "${entry_id}" | grub_quote)' \$menuentry_id_option 'gnulinux-advanced-$boot_device_id' {"
      is_top_level=false
    fi

    linux_entry "${entry_id}" "${version}" advanced \
                "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
    if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
      linux_entry "${entry_id}" "${version}" recovery \
                  "${GRUB_CMDLINE_LINUX_RECOVERY} ${GRUB_CMDLINE_LINUX}"
    fi
  done

  # If at least one kernel was found, then we need to
  # add a closing '}' for the submenu command.
  if [ x"$is_top_level" != xtrue ]; then
    echo '}'
  fi

  echo "$title_correction_code"
done
