Copy the new ia32 loader

This handles copying in install-boot.sh and bsdinstall's bootconfig.

install-boot.sh:
make_esp_file now optionally takes extra arguments so it can copy
multiple files. This is used by the amd64 release scripts.
make_esp_device also takes an extra optional argument for efibootname.
This is currently unused, but it can be used in the future to do
something like:
make_esp_device loader.efi bootx64
make_esp_device loader_ia32.efi bootia32

Reviewed by: imp
Pull Request: https://github.com/freebsd/freebsd-src/pull/1098
This commit is contained in:
Ahmad Khalifa 2024-06-03 04:53:44 +03:00 committed by Warner Losh
parent b538d49110
commit 599273f942
4 changed files with 72 additions and 30 deletions

View File

@ -60,7 +60,12 @@ fi
# Make an ESP in a file. # Make an ESP in a file.
espfilename=$(mktemp /tmp/efiboot.XXXXXX) espfilename=$(mktemp /tmp/efiboot.XXXXXX)
make_esp_file ${espfilename} ${fat32min} ${BASEBITSDIR}/boot/loader.efi if [ -f "${BASEBITSDIR}/boot/loader_ia32.efi" ]; then
make_esp_file ${espfilename} ${fat32min} ${BASEBITSDIR}/boot/loader.efi bootx64 \
${BASEBITSDIR}/boot/loader_ia32.efi bootia32
else
make_esp_file ${espfilename} ${fat32min} ${BASEBITSDIR}/boot/loader.efi
fi
mkimg -s mbr \ mkimg -s mbr \
-b ${BASEBITSDIR}/boot/mbr \ -b ${BASEBITSDIR}/boot/mbr \

View File

@ -64,7 +64,12 @@ if [ "$1" = "-b" ]; then
espfilename=$(mktemp /tmp/efiboot.XXXXXX) espfilename=$(mktemp /tmp/efiboot.XXXXXX)
# ESP file size in KB. # ESP file size in KB.
espsize="2048" espsize="2048"
make_esp_file ${espfilename} ${espsize} ${BASEBITSDIR}/boot/loader.efi if [ -f "${BASEBITSDIR}/boot/loader_ia32.efi" ]; then
make_esp_file ${espfilename} ${espsize} ${BASEBITSDIR}/boot/loader.efi bootx64 \
${BASEBITSDIR}/boot/loader_ia32.efi bootia32
else
make_esp_file ${espfilename} ${espsize} ${BASEBITSDIR}/boot/loader.efi
fi
bootable="$bootable -o bootimage=i386;${espfilename} -o no-emul-boot -o platformid=efi" bootable="$bootable -o bootimage=i386;${espfilename} -o no-emul-boot -o platformid=efi"
shift shift

View File

@ -42,11 +42,10 @@ get_uefi_bootname() {
} }
make_esp_file() { make_esp_file() {
local file sizekb loader device stagedir fatbits efibootname local file sizekb device stagedir fatbits efibootname
file=$1 file=$1
sizekb=$2 sizekb=$2
loader=$3
if [ "$sizekb" -ge "$fat32min" ]; then if [ "$sizekb" -ge "$fat32min" ]; then
fatbits=32 fatbits=32
@ -58,8 +57,25 @@ make_esp_file() {
stagedir=$(mktemp -d /tmp/stand-test.XXXXXX) stagedir=$(mktemp -d /tmp/stand-test.XXXXXX)
mkdir -p "${stagedir}/EFI/BOOT" mkdir -p "${stagedir}/EFI/BOOT"
efibootname=$(get_uefi_bootname)
cp "${loader}" "${stagedir}/EFI/BOOT/${efibootname}.efi" # Allow multiple files to be copied.
# We do this in pairs, e.g:
# make_esp_file ... loader1.efi bootx64 loader2.efi bootia32
#
# If the second argument is left out,
# determine it automatically.
shift; shift # Skip $file and $sizekb
while [ ! -z $1 ]; do
if [ ! -z $2 ]; then
efibootname=$2
else
efibootname=$(get_uefi_bootname)
fi
cp "$1" "${stagedir}/EFI/BOOT/${efibootname}.efi"
shift; shift || : # Ignore failure to shift
done
makefs -t msdos \ makefs -t msdos \
-o fat_type=${fatbits} \ -o fat_type=${fatbits} \
-o sectors_per_cluster=1 \ -o sectors_per_cluster=1 \
@ -70,13 +86,20 @@ make_esp_file() {
} }
make_esp_device() { make_esp_device() {
local dev file mntpt fstype efibootname kbfree loadersize efibootfile local dev file dst mntpt fstype efibootname kbfree loadersize efibootfile
local isboot1 existingbootentryloaderfile bootorder bootentry local isboot1 existingbootentryloaderfile bootorder bootentry
# ESP device node # ESP device node
dev=$1 dev=$1
file=$2 file=$2
# Allow caller to override the default
if [ ! -z $3 ]; then
efibootname=$3
else
efibootname=$(get_uefi_bootname)
fi
dst=$(basename ${file%.efi})
mntpt=$(mktemp -d /tmp/stand-test.XXXXXX) mntpt=$(mktemp -d /tmp/stand-test.XXXXXX)
# See if we're using an existing (formatted) ESP # See if we're using an existing (formatted) ESP
@ -93,7 +116,6 @@ make_esp_device() {
echo "Mounted ESP ${dev} on ${mntpt}" echo "Mounted ESP ${dev} on ${mntpt}"
efibootname=$(get_uefi_bootname)
kbfree=$(df -k "${mntpt}" | tail -1 | cut -w -f 4) kbfree=$(df -k "${mntpt}" | tail -1 | cut -w -f 4)
loadersize=$(stat -f %z "${file}") loadersize=$(stat -f %z "${file}")
loadersize=$((loadersize / 1024)) loadersize=$((loadersize / 1024))
@ -114,7 +136,7 @@ make_esp_device() {
fi fi
fi fi
if [ ! -f "${mntpt}/EFI/freebsd/loader.efi" ] && [ "$kbfree" -lt "$loadersize" ]; then if [ ! -f "${mntpt}/EFI/freebsd/${dst}.efi" ] && [ "$kbfree" -lt "$loadersize" ]; then
umount "${mntpt}" umount "${mntpt}"
rmdir "${mntpt}" rmdir "${mntpt}"
echo "Failed to update the EFI System Partition ${dev}" echo "Failed to update the EFI System Partition ${dev}"
@ -126,24 +148,26 @@ make_esp_device() {
mkdir -p "${mntpt}/EFI/freebsd" mkdir -p "${mntpt}/EFI/freebsd"
# Keep a copy of the existing loader.efi in case there's a problem with the new one # Keep a copy of the existing loader.efi in case there's a problem with the new one
if [ -f "${mntpt}/EFI/freebsd/loader.efi" ] && [ "$kbfree" -gt "$((loadersize * 2))" ]; then if [ -f "${mntpt}/EFI/freebsd/${dst}.efi" ] && [ "$kbfree" -gt "$((loadersize * 2))" ]; then
cp "${mntpt}/EFI/freebsd/loader.efi" "${mntpt}/EFI/freebsd/loader-old.efi" cp "${mntpt}/EFI/freebsd/${dst}.efi" "${mntpt}/EFI/freebsd/${dst}-old.efi"
fi fi
echo "Copying loader to /EFI/freebsd on ESP" echo "Copying loader to /EFI/freebsd on ESP"
cp "${file}" "${mntpt}/EFI/freebsd/loader.efi" cp "${file}" "${mntpt}/EFI/freebsd/${dst}.efi"
if [ -n "${updatesystem}" ]; then # efibootmgr won't work on systems with ia32 UEFI firmware
existingbootentryloaderfile=$(efibootmgr -v | grep "${mntpt}//EFI/freebsd/loader.efi") # since we only use it to boot the 64-bit kernel
if [ -n "${updatesystem}" ] && [ ${efibootname} != "bootia32" ]; then
existingbootentryloaderfile=$(efibootmgr -v | grep "${mntpt}//EFI/freebsd/${dst}.efi")
if [ -z "$existingbootentryloaderfile" ]; then if [ -z "$existingbootentryloaderfile" ]; then
# Try again without the double forward-slash in the path # Try again without the double forward-slash in the path
existingbootentryloaderfile=$(efibootmgr -v | grep "${mntpt}/EFI/freebsd/loader.efi") existingbootentryloaderfile=$(efibootmgr -v | grep "${mntpt}/EFI/freebsd/${dst}.efi")
fi fi
if [ -z "$existingbootentryloaderfile" ]; then if [ -z "$existingbootentryloaderfile" ]; then
echo "Creating UEFI boot entry for FreeBSD" echo "Creating UEFI boot entry for FreeBSD"
efibootmgr --create --label FreeBSD --loader "${mntpt}/EFI/freebsd/loader.efi" > /dev/null efibootmgr --create --label FreeBSD --loader "${mntpt}/EFI/freebsd/${dst}.efi" > /dev/null
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
die "Failed to create new boot entry" die "Failed to create new boot entry"
fi fi

View File

@ -109,32 +109,40 @@ if [ -n "$(awk '{if ($2=="/boot/efi") printf("%s\n",$1);}' $PATH_FSTAB)" ]; then
# i386) ARCHBOOTNAME=ia32 ;; # no support for this in i386 kernels, rare machines # i386) ARCHBOOTNAME=ia32 ;; # no support for this in i386 kernels, rare machines
*) die "Unsupported arch $(uname -m) for UEFI install" *) die "Unsupported arch $(uname -m) for UEFI install"
esac esac
if [ `sysctl -n machdep.efi_arch` == i386 ]; then
ARCHBOOTNAME=ia32
file=loader_ia32.efi
else
file=loader.efi
fi
BOOTDIR="/efi/boot" BOOTDIR="/efi/boot"
BOOTNAME="${BOOTDIR}/boot${ARCHBOOTNAME}.efi" BOOTNAME="${BOOTDIR}/boot${ARCHBOOTNAME}.efi"
FREEBSD_BOOTDIR="/efi/freebsd" FREEBSD_BOOTDIR="/efi/freebsd"
FREEBSD_BOOTNAME="${FREEBSD_BOOTDIR}/loader.efi" FREEBSD_BOOTNAME="${FREEBSD_BOOTDIR}/${file}"
mntpt="$BSDINSTALL_CHROOT/boot/efi" mntpt="$BSDINSTALL_CHROOT/boot/efi"
f_dprintf "Installing loader.efi onto ESP" f_dprintf "Installing ${file} onto ESP"
mkdir -p "${mntpt}/${FREEBSD_BOOTDIR}" "${mntpt}/${BOOTDIR}" mkdir -p "${mntpt}/${FREEBSD_BOOTDIR}" "${mntpt}/${BOOTDIR}"
cp "$BSDINSTALL_CHROOT/boot/loader.efi" "${mntpt}/${FREEBSD_BOOTNAME}" cp "$BSDINSTALL_CHROOT/boot/${file}" "${mntpt}/${FREEBSD_BOOTNAME}"
# #
# The following shouldn't be necessary. UEFI defines a way to # UEFI defines a way to specifically select what to boot
# specifically select what to boot (which we do via # (which we do via efibootmgr). However, if we booted from an ia32
# efibootmgr). However, virtual environments often times lack # UEFI environment, we wouldn't have access to efirt. In addition,
# support for the NV variables efibootmgr sets. In addition, # virtual environments often times lack support for the NV variables
# some UEFI implementations have features that interfere with # efibootmgr sets, and some UEFI implementations have features that
# the setting of these variables. To combat that, we install the # interfere with the setting of these variables. To combat that, we
# default removable media boot file as a fallback if it doesn't # install the default removable media boot file if it doesn't exist.
# exist. We don't install it all the time since that can # We don't install it all the time since that can interfere with other
# interfere with other installations on the drive (like rEFInd). # installations on the drive (like rEFInd).
# #
if [ ! -f "${mntpt}/${BOOTNAME}" ]; then if [ ! -f "${mntpt}/${BOOTNAME}" ]; then
cp "$BSDINSTALL_CHROOT/boot/loader.efi" "${mntpt}/${BOOTNAME}" cp "$BSDINSTALL_CHROOT/boot/${file}" "${mntpt}/${BOOTNAME}"
fi fi
if [ "$BSDINSTALL_CONFIGCURRENT" ]; then if [ "$BSDINSTALL_CONFIGCURRENT" ] && [ "$ARCHBOOTNAME" != ia32 ]; then
update_uefi_bootentry update_uefi_bootentry
fi fi