Skip to content

Commit

Permalink
installkernel.ebuild: install grub-mkconfig hook for ukis
Browse files Browse the repository at this point in the history
TODO: multi-profile UKI support

Also need a fix for the secureboot/shim situation in the chainloader
command.

Co-authored-by: Peter Levine <plevine457@gmail.com>
See-also: gentoo/gentoo#39113
Signed-off-by: Nowa Ammerlaan <nowa@gentoo.org>
  • Loading branch information
Nowa-Ammerlaan and Peter-Levine committed Feb 21, 2025
1 parent f60ca6b commit 7e71056
Show file tree
Hide file tree
Showing 2 changed files with 234 additions and 9 deletions.
229 changes: 229 additions & 0 deletions grub/05_uki
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
#! /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
14 changes: 5 additions & 9 deletions installkernel-9999.ebuild
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,10 @@ SLOT="0"
KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~loong ~m68k ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86 ~amd64-linux ~x86-linux"
IUSE="dracut efistub grub refind systemd systemd-boot ugrd uki ukify"
REQUIRED_USE="
?? ( efistub grub systemd-boot )
refind? ( !systemd-boot !grub )
systemd-boot? ( systemd )
ukify? ( uki )
?? ( dracut ugrd )
"
# Only select one flag that sets "layout=", except for uki since grub,
# systemd-boot, and efistub booting are all compatible with UKIs and
# the uki layout.
#
# Refind does not set a layout=, it is compatible with the compat, uki
# and efistub layout. So block against only grub and systemd-boot.
#
# systemd-boot could be made to work without the systemd flag, but this
# makes no sense since in systemd(-utils) the boot flag already
# requires the kernel-install flag.
Expand Down Expand Up @@ -123,6 +114,11 @@ src_install() {
use efistub && doexe hooks/systemd/95-efistub-kernel-bootcfg.install
use refind && doexe hooks/systemd/95-refind-copy-icon.install

if use grub && use uki; then
exeinto /etc/grub.d
doexe grub/05_uki
fi

if use systemd; then
sed -e 's/${SYSTEMD_KERNEL_INSTALL:=0}/${SYSTEMD_KERNEL_INSTALL:=1}/g' -i installkernel ||
die "enabling systemd's kernel-install failed"
Expand Down

0 comments on commit 7e71056

Please sign in to comment.