git: 599273f942b8 - main - Copy the new ia32 loader

From: Warner Losh <imp_at_FreeBSD.org>
Date: Fri, 20 Sep 2024 14:59:23 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=599273f942b8dc6f957487bb28f36694dab9dad2

commit 599273f942b8dc6f957487bb28f36694dab9dad2
Author:     Ahmad Khalifa <ahmadkhalifa570@gmail.com>
AuthorDate: 2024-06-03 01:53:44 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2024-09-20 14:45:10 +0000

    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
---
 release/amd64/make-memstick.sh         |  7 ++++-
 release/amd64/mkisoimages.sh           |  7 ++++-
 tools/boot/install-boot.sh             | 52 +++++++++++++++++++++++++---------
 usr.sbin/bsdinstall/scripts/bootconfig | 36 ++++++++++++++---------
 4 files changed, 72 insertions(+), 30 deletions(-)

diff --git a/release/amd64/make-memstick.sh b/release/amd64/make-memstick.sh
index 4c51d7d65af4..cbb80e971343 100755
--- a/release/amd64/make-memstick.sh
+++ b/release/amd64/make-memstick.sh
@@ -60,7 +60,12 @@ fi
 
 # Make an ESP in a file.
 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 \
     -b ${BASEBITSDIR}/boot/mbr \
diff --git a/release/amd64/mkisoimages.sh b/release/amd64/mkisoimages.sh
index 3cc7a6cc919e..245beb660c3f 100644
--- a/release/amd64/mkisoimages.sh
+++ b/release/amd64/mkisoimages.sh
@@ -64,7 +64,12 @@ if [ "$1" = "-b" ]; then
 	espfilename=$(mktemp /tmp/efiboot.XXXXXX)
 	# ESP file size in KB.
 	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"
 
 	shift
diff --git a/tools/boot/install-boot.sh b/tools/boot/install-boot.sh
index 332756582137..217bf0ff1457 100755
--- a/tools/boot/install-boot.sh
+++ b/tools/boot/install-boot.sh
@@ -42,11 +42,10 @@ get_uefi_bootname() {
 }
 
 make_esp_file() {
-    local file sizekb loader device stagedir fatbits efibootname
+    local file sizekb device stagedir fatbits efibootname
 
     file=$1
     sizekb=$2
-    loader=$3
 
     if [ "$sizekb" -ge "$fat32min" ]; then
         fatbits=32
@@ -58,8 +57,25 @@ make_esp_file() {
 
     stagedir=$(mktemp -d /tmp/stand-test.XXXXXX)
     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 \
 	-o fat_type=${fatbits} \
 	-o sectors_per_cluster=1 \
@@ -70,13 +86,20 @@ make_esp_file() {
 }
 
 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
 
     # ESP device node
     dev=$1
     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)
 
     # See if we're using an existing (formatted) ESP
@@ -93,7 +116,6 @@ make_esp_device() {
 
     echo "Mounted ESP ${dev} on ${mntpt}"
 
-    efibootname=$(get_uefi_bootname)
     kbfree=$(df -k "${mntpt}" | tail -1 | cut -w -f 4)
     loadersize=$(stat -f %z "${file}")
     loadersize=$((loadersize / 1024))
@@ -114,7 +136,7 @@ make_esp_device() {
         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}"
 	rmdir "${mntpt}"
         echo "Failed to update the EFI System Partition ${dev}"
@@ -126,24 +148,26 @@ make_esp_device() {
     mkdir -p "${mntpt}/EFI/freebsd"
 
     # 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
-        cp "${mntpt}/EFI/freebsd/loader.efi" "${mntpt}/EFI/freebsd/loader-old.efi"
+    if [ -f "${mntpt}/EFI/freebsd/${dst}.efi" ] && [ "$kbfree" -gt "$((loadersize * 2))" ]; then
+        cp "${mntpt}/EFI/freebsd/${dst}.efi" "${mntpt}/EFI/freebsd/${dst}-old.efi"
     fi
 
     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
-        existingbootentryloaderfile=$(efibootmgr -v | grep "${mntpt}//EFI/freebsd/loader.efi")
+    # efibootmgr won't work on systems with ia32 UEFI firmware
+    # 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
             # 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
 
         if [ -z "$existingbootentryloaderfile" ]; then
             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
                 die "Failed to create new boot entry"
             fi
diff --git a/usr.sbin/bsdinstall/scripts/bootconfig b/usr.sbin/bsdinstall/scripts/bootconfig
index bd69195f76ff..618a1966095e 100755
--- a/usr.sbin/bsdinstall/scripts/bootconfig
+++ b/usr.sbin/bsdinstall/scripts/bootconfig
@@ -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
 	    *)		die "Unsupported arch $(uname -m) for UEFI install"
 	esac
+
+	if [ `sysctl -n machdep.efi_arch` == i386 ]; then
+		ARCHBOOTNAME=ia32
+		file=loader_ia32.efi
+	else
+		file=loader.efi
+	fi
+
 	BOOTDIR="/efi/boot"
 	BOOTNAME="${BOOTDIR}/boot${ARCHBOOTNAME}.efi"
 	FREEBSD_BOOTDIR="/efi/freebsd"
-	FREEBSD_BOOTNAME="${FREEBSD_BOOTDIR}/loader.efi"
+	FREEBSD_BOOTNAME="${FREEBSD_BOOTDIR}/${file}"
 	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}"
-	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
-	# specifically select what to boot (which we do via
-	# efibootmgr). However, virtual environments often times lack
-	# support for the NV variables efibootmgr sets. In addition,
-	# some UEFI implementations have features that interfere with
-	# the setting of these variables. To combat that, we install the
-	# default removable media boot file as a fallback if it doesn't
-	# exist. We don't install it all the time since that can
-	# interfere with other installations on the drive (like rEFInd).
+	# UEFI defines a way to specifically select what to boot
+	# (which we do via efibootmgr). However, if we booted from an ia32
+	# UEFI environment, we wouldn't have access to efirt. In addition,
+	# virtual environments often times lack support for the NV variables
+	# efibootmgr sets, and some UEFI implementations have features that
+	# interfere with the setting of these variables. To combat that, we
+	# install the default removable media boot file if it doesn't exist.
+	# We don't install it all the time since that can interfere with other
+	# installations on the drive (like rEFInd).
 	#
 	if [ ! -f "${mntpt}/${BOOTNAME}" ]; then
-		cp "$BSDINSTALL_CHROOT/boot/loader.efi" "${mntpt}/${BOOTNAME}"
+		cp "$BSDINSTALL_CHROOT/boot/${file}" "${mntpt}/${BOOTNAME}"
 	fi
 
-	if [ "$BSDINSTALL_CONFIGCURRENT" ]; then
+	if [ "$BSDINSTALL_CONFIGCURRENT" ] && [ "$ARCHBOOTNAME" != ia32 ]; then
 		update_uefi_bootentry
 	fi