Skip to content

Commit

Permalink
Improve hybrid bootloader and arm64 UEFI support
Browse files Browse the repository at this point in the history
Previously, it was possible to install both BIOS and UEFI bootloaders
at the same time when creating VM images with grml-debootstrap. In this
setup however, the UEFI bootloader would not be automatically updated,
due to the absence of a grub-efi-ARCH package on the installed system.
It also was not possible to install both bootloaders using
grml-debootstrap on a physical disk, and arm64 VM images could not be
built with full UEFI support as enabled by the --vmefi argument (these
builds would fail).

To rectify these issues:

* Use grub-cloud-amd64 to install both BIOS and UEFI bootloaders and
  manage updates.
* Add support for installing BIOS and UEFI bootloaders simultaneously
  on physical disk installations.
* Get rid of the ARM_EFI_TARGET variable and make ARM64 VM builds use
  VMEFI=1 by default.

Fixes grml#297, grml#257
  • Loading branch information
ArrayBolt3 committed Feb 27, 2025
1 parent 5b43c17 commit 2891f17
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 127 deletions.
103 changes: 83 additions & 20 deletions chroot-script
Original file line number Diff line number Diff line change
Expand Up @@ -623,11 +623,11 @@ efi_setup() {
# then we need to mount efivarfs for efibootmgr usage
if ! ls /sys/firmware/efi/efivars/* &>/dev/null ; then
echo "Mounting efivarfs on /sys/firmware/efi/efivars"
mount -t efivarfs efivarfs /sys/firmware/efi/efivars
mount -t efivarfs efivarfs /sys/firmware/efi/efivars || true
fi

echo "Invoking efibootmgr"
efibootmgr
efibootmgr || true
}

# grub configuration/installation {{{
Expand Down Expand Up @@ -667,21 +667,73 @@ device_to_id() {
return 1
}

is_grub_bios_compatible() {
# Check if the disk uses an MSDOS partition table, these are always compatible
if [[ "$(blkid "$GRUB")" =~ 'PTTYPE="dos"' ]]; then
return 0
# Look for a BIOS boot partition otherwise
else
while read -r line; do
if [[ "$line" =~ ^${GRUB}.*21686148-6449-6e6f-744e-656564454649$ ]]; then
return 0
fi
done < <(lsblk -pnlo NAME,PARTTYPE)
fi
return 1
}

run_grub_install() {
grub_install_cmd=( 'grub-install' "$@" )
if ! "${grub_install_cmd[@]}" ; then
echo "Error: failed to execute '${grub_install_cmd[*]}'." >&2
exit 1
fi
}

grub_install() {

if [ -z "$GRUB" ] ; then
echo "Notice: \$GRUB not defined, will not install grub inside chroot at this stage."
return 0
fi
MAIN_GRUB_PACKAGE=""
GRUB_SECBOOT_PACKAGES=()

efi_setup
case "$ARCH" in
i386)
if [ -n "$EFI" ]; then
MAIN_GRUB_PACKAGE="grub-efi-ia32"
GRUB_SECBOOT_PACKAGES=( "grub-efi-ia32-signed" "shim-signed" )
elif is_grub_bios_compatible; then
MAIN_GRUB_PACKAGE="grub-pc"
fi
;;
amd64)
if is_grub_bios_compatible && [ -n "$EFI" ]; then
MAIN_GRUB_PACKAGE="grub-cloud-amd64"
GRUB_SECBOOT_PACKAGES=( "grub-efi-amd64-signed" "shim-signed" )
elif [ -n "$EFI" ]; then
MAIN_GRUB_PACKAGE="grub-efi-amd64"
GRUB_SECBOOT_PACKAGES=( "grub-efi-amd64-signed" "shim-signed" )
else
MAIN_GRUB_PACKAGE="grub-pc"
fi
;;
arm64)
if [ -n "$EFI" ]; then
MAIN_GRUB_PACKAGE="grub-efi-arm64"
GRUB_SECBOOT_PACKAGES=( "grub-efi-arm64-signed" "shim-signed" )
fi
;;
esac

if [ -n "$EFI" ] ; then
GRUB_PACKAGE=grub-efi-amd64
else
GRUB_PACKAGE=grub-pc
if [ -z "$MAIN_GRUB_PACKAGE" ]; then
echo "Notice: No applicable bootloaders found, will not install grub inside chroot at this stage."
return 0
fi

efi_setup

# make sure this is pre-defined so we have sane settings for automated
# upgrades, see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=711019
local grub_device
Expand All @@ -691,14 +743,13 @@ grub_install() {
grub_device="${GRUB}"
fi

echo "Setting ${GRUB_PACKAGE} debconf configuration for install device to $GRUB"
echo "${GRUB_PACKAGE} ${GRUB_PACKAGE}/install_devices multiselect ${grub_device}" | debconf-set-selections

if ! dpkg --list "${GRUB_PACKAGE}" 2>/dev/null | grep -q '^ii' ; then
echo "Notice: grub option set but no ${GRUB_PACKAGE} package, installing it therefore."
DEBIAN_FRONTEND=$DEBIAN_FRONTEND $APTINSTALL "${GRUB_PACKAGE}"
echo "Setting grub debconf configuration for install device to $GRUB"
if [ -n "$MAIN_GRUB_PACKAGE" ]; then
echo "${MAIN_GRUB_PACKAGE} ${MAIN_GRUB_PACKAGE}/install_devices multiselect ${grub_device}" | debconf-set-selections
fi

DEBIAN_FRONTEND=$DEBIAN_FRONTEND $APTINSTALL "${MAIN_GRUB_PACKAGE}" "${GRUB_SECBOOT_PACKAGES[@]}"

if ! [ -x "$(command -v grub-install)" ] ; then
echo "Error: grub-install not available. (Error while installing grub package?)" >&2
return 1
Expand All @@ -712,19 +763,31 @@ grub_install() {
for device in $SELECTED_PARTITIONS ; do
GRUB="${device%%[0-9]}"
echo "Installing grub on ${GRUB}:"
if ! grub-install --no-floppy "$GRUB" ; then
echo "Error: failed to execute 'grub-install --no-floppy $GRUB'." >&2
exit 1
if [ -n "$EFI" ]; then
case "${ARCH}" in
i386) run_grub_install --no-floppy --target=i386-efi "${GRUB}";;
amd64) run_grub_install --no-floppy --target=x86_64-efi "${GRUB}";;
arm64) run_grub_install --no-floppy --target=arm64-efi "${GRUB}";;
esac
fi
if [ "$MAIN_GRUB_PACKAGE" = 'grub-cloud-amd64' ] || [ -z "$EFI" ]; then
run_grub_install --no-floppy --target=i386-pc "${GRUB}"
fi

done
rm -f /boot/grub/device.map
else
echo "Installing grub on ${GRUB}:"
mkdir -p /boot/grub
echo "(hd0) ${GRUB}" > /boot/grub/device.map
if ! grub-install "(hd0)" ; then
echo "Error: failed to execute 'grub-install (hd0)'." >&2
exit 1
if [ -n "$EFI" ]; then
case "${ARCH}" in
i386) run_grub_install --target=i386-efi "${GRUB}";;
amd64) run_grub_install --target=x86_64-efi "${GRUB}";;
arm64) run_grub_install --target=arm64-efi "${GRUB}";;
esac
fi
if [ "$MAIN_GRUB_PACKAGE" = 'grub-cloud-amd64' ] || [ -z "$EFI" ]; then
run_grub_install --target=i386-pc "${GRUB}"
fi
rm /boot/grub/device.map
fi
Expand Down
Loading

0 comments on commit 2891f17

Please sign in to comment.