Skip to content

Instantly share code, notes, and snippets.

@jacky9813
Created April 20, 2024 09:49
Show Gist options
  • Save jacky9813/6dbf8f0f80892f9b60c023298a536ee3 to your computer and use it in GitHub Desktop.
Save jacky9813/6dbf8f0f80892f9b60c023298a536ee3 to your computer and use it in GitHub Desktop.
[Linux] Convert boot mode to UEFI
#!/bin/bash
#
# Convert to EFI
#
# IMPORTANT NOTES:
# * This script CAN ONLY BE running in a chrooted environment.
# * This script will install shim, but still secure boot may fail.
#
# Tested for CentOS 7, but should have a similar process for all other
# Linux distros, at least for RHEL for its derivatives.
#
# This script can be run on a BIOS booted environment as well, such as most of
# AWS EC2 x86_64 AMI. (Guess why I'm testing on BIOS environment.)
#
# This script assumes you've done the following things:
# 1. Creates GPT table on the destination disk, which contains:
# * (Optional) BIOS Boot volulme (usually around 4M)
# * EFI System volume (usually around 1G)
# * Primary Linux volume (takes the rest of the space)
# The layout should like this:
# First Sector Last Sector
# | BIOS | EFI | Linux |
# 2. Mounted the disks as follow:
# * <Old BIOS boot Linux volume> => /mnt/src
# * <Primary Linux volume> => /mnt/dst
# * <EFI System volume> => /mnt/dst/boot/efi (create this directory
# if not exists)
# 3. Copy everything from source to destination with preserving
# all attributes:
# cp -R --preserve=all /mnt/src/* /mnt/dst/
# 4. Mount additional volumes before chroot:
# * mount --type proc /proc /mnt/dst/proc
# * mount --rbind /dev /mnt/dst/dev
# * mount --rbind /sys /mnt/dst/sys
# * mount --make-rslave /mnt/dst/dev
# * mount --make-rslave /mnt/dst/sys
# 5. Chrooted into /mnt/dst:
# sudo chroot /mnt/dst /bin/bash
#
SYSTEM_DISK=/dev/vdc
EFI_SYSTEM_VOLUME=${SYSTEM_DISK}2
MAIN_SYSTEM_VOLUME=${SYSTEM_DISK}3
# Install required packages for EFI boot
yum install shim grub2-efi grub2-efi-modules efibootmgr
# Install BIOS-compatible bootloader
grub2-install $SYSTEM_DISK
# Install EFI bootloader
grub2-install --target x86_64-efi --efi-directory /boot/efi $SYSTEM_DISK
# Setup GRUB config
echo "GRUB_DISABLE_OS_PROBER=true" >> /etc/sysconfig/grub
grub2-mkconfig -o /boot/grub2/grub.cfg
# EFI cannot use 16-bit boot mode, forcefully change it to linuxefi and
# initrdefi.
sed -i -E 's/(linux|initrd)16/\1efi/' /boot/grub2/grub.cfg
pushd /etc
rm grub2-efi.cfg
ln -s ../boot/grub2/grub.cfg grub2-efi.cfg
popd
# Let GRUB find configuration file from main system volume
cat << EOF > /boot/efi/EFI/centos/grub.cfg
search --no-floppy --fs-uuid --set=root $(blkid -s UUID -o value $MAIN_SYSTEM_VOLUME)
set prefix=(\$root)/boot/grub2
export \$prefix
configfile \$prefix/grub.cfg
EOF
cp /etc/fstab /etc/fstab.backup
rm /etc/fstab
add_fstab_entry(){
if [ -z "$1" ] || [ -z "$2" ]; then
cat << EOF > &2
Usage: $0 DEVICE MOUNT_PATH [MOUNT_OPTION]
Add mount profile into /etc/fstab, where DEVICE will automatically
converted into UUID format.
EOF
return 1
fi
MOUNT_OPTION=${3:-defaults}
printf 'UUID=%-36s %-30s %-10s %-15s 0 0\n' \
"$(blkid -s UUID -o value $1)" \
"$2" \
"$(blkid -s TYPE -o value $1)" \
"$MOUNT_OPTION" | tee -a /etc/fstab
}
add_fstab_entry "$MAIN_SYSTEM_VOLUME" /
add_fstab_entry "$EFI_SYSTEM_VOLUME" /boot/efi
# Restore SELinux context
restorecon -R /
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment