From owner-svn-src-all@freebsd.org Thu Dec 20 19:39:41 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id BE6161351A99; Thu, 20 Dec 2018 19:39:40 +0000 (UTC) (envelope-from bcran@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 7017468339; Thu, 20 Dec 2018 19:39:40 +0000 (UTC) (envelope-from bcran@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 34D04234F; Thu, 20 Dec 2018 19:39:40 +0000 (UTC) (envelope-from bcran@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id wBKJdeFb015224; Thu, 20 Dec 2018 19:39:40 GMT (envelope-from bcran@FreeBSD.org) Received: (from bcran@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id wBKJdbhB015092; Thu, 20 Dec 2018 19:39:37 GMT (envelope-from bcran@FreeBSD.org) Message-Id: <201812201939.wBKJdbhB015092@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: bcran set sender to bcran@FreeBSD.org using -f From: Rebecca Cran Date: Thu, 20 Dec 2018 19:39:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r342283 - in head: release/amd64 release/arm64 release/i386 release/tools share/man/man8 tools/boot tools/tools/nanobsd/embedded usr.sbin/bsdinstall/partedit usr.sbin/bsdinstall/scripts X-SVN-Group: head X-SVN-Commit-Author: bcran X-SVN-Commit-Paths: in head: release/amd64 release/arm64 release/i386 release/tools share/man/man8 tools/boot tools/tools/nanobsd/embedded usr.sbin/bsdinstall/partedit usr.sbin/bsdinstall/scripts X-SVN-Commit-Revision: 342283 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 7017468339 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.98 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_SHORT(-0.98)[-0.978,0]; NEURAL_HAM_LONG(-1.00)[-0.999,0] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 20 Dec 2018 19:39:41 -0000 Author: bcran Date: Thu Dec 20 19:39:37 2018 New Revision: 342283 URL: https://svnweb.freebsd.org/changeset/base/342283 Log: Rework UEFI ESP generation Currently, the installer uses pre-created 800KB FAT12 filesystems that it dd's onto the ESP partition. This changeset improves that by having the installer generate a FAT32 filesystem directly onto the ESP using newfs_msdos and then copying loader.efi into /EFI/freebsd. For live installs it then runs efibootmgr to add a FreeBSD boot entry in the BIOS. Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D17947 Modified: head/release/amd64/make-memstick.sh head/release/amd64/mkisoimages.sh head/release/arm64/make-memstick.sh head/release/i386/make-memstick.sh head/release/tools/vmimage.subr head/share/man/man8/uefi.8 head/tools/boot/install-boot.sh head/tools/boot/rootgen.sh head/tools/tools/nanobsd/embedded/common head/usr.sbin/bsdinstall/partedit/gpart_ops.c head/usr.sbin/bsdinstall/partedit/partedit_arm64.c head/usr.sbin/bsdinstall/partedit/partedit_x86.c head/usr.sbin/bsdinstall/scripts/bootconfig head/usr.sbin/bsdinstall/scripts/zfsboot Modified: head/release/amd64/make-memstick.sh ============================================================================== --- head/release/amd64/make-memstick.sh Thu Dec 20 19:27:46 2018 (r342282) +++ head/release/amd64/make-memstick.sh Thu Dec 20 19:39:37 2018 (r342283) @@ -12,6 +12,9 @@ set -e +scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../../tools/boot/install-boot.sh + PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH @@ -36,11 +39,16 @@ makefs -B little -o label=FreeBSD_Install -o version=2 rm ${1}/etc/fstab rm ${1}/etc/rc.conf.local +# Make an ESP in a file. +espfilename=$(mktemp /tmp/efiboot.XXXXXX) +make_esp_file ${espfilename} ${fat32min} ${1}/boot/loader.efi + mkimg -s mbr \ -b ${1}/boot/mbr \ - -p efi:=${1}/boot/boot1.efifat \ + -p efi:=${espfilename} \ -p freebsd:-"mkimg -s bsd -b ${1}/boot/boot -p freebsd-ufs:=${2}.part" \ -a 2 \ -o ${2} +rm ${espfilename} rm ${2}.part Modified: head/release/amd64/mkisoimages.sh ============================================================================== --- head/release/amd64/mkisoimages.sh Thu Dec 20 19:27:46 2018 (r342282) +++ head/release/amd64/mkisoimages.sh Thu Dec 20 19:39:37 2018 (r342283) @@ -25,6 +25,9 @@ set -e +scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../../tools/boot/install-boot.sh + if [ -z $ETDUMP ]; then ETDUMP=etdump fi @@ -43,18 +46,12 @@ if [ "$1" = "-b" ]; then bootable="-o bootimage=i386;$BASEBITSDIR/boot/cdboot -o no-emul-boot" # Make EFI system partition (should be done with makefs in the future) - dd if=/dev/zero of=efiboot.img bs=4k count=200 - device=`mdconfig -a -t vnode -f efiboot.img` - newfs_msdos -F 12 -m 0xf8 /dev/$device - mkdir efi - mount -t msdosfs /dev/$device efi - mkdir -p efi/efi/boot - cp "$BASEBITSDIR/boot/loader.efi" efi/efi/boot/bootx64.efi - umount efi - rmdir efi - mdconfig -d -u $device - bootable="$bootable -o bootimage=i386;efiboot.img -o no-emul-boot -o platformid=efi" - + # The ISO file is a special case, in that it only has a maximum of + # 800 KB available for the boot code. So make an 800 KB ESP + espfilename=$(mktemp /tmp/efiboot.XXXXXX) + make_esp_file ${espfilename} 800 ${BASEBITSDIR}/boot/loader.efi + bootable="$bootable -o bootimage=i386;${espfilename} -o no-emul-boot -o platformid=efi" + shift else BASEBITSDIR="$3" @@ -73,7 +70,7 @@ publisher="The FreeBSD Project. https://www.FreeBSD.o echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > "$BASEBITSDIR/etc/fstab" $MAKEFS -t cd9660 $bootable -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME" "$@" rm -f "$BASEBITSDIR/etc/fstab" -rm -f efiboot.img +rm -f ${espfilename} if [ "$bootable" != "" ]; then # Look for the EFI System Partition image we dropped in the ISO image. Modified: head/release/arm64/make-memstick.sh ============================================================================== --- head/release/arm64/make-memstick.sh Thu Dec 20 19:27:46 2018 (r342282) +++ head/release/arm64/make-memstick.sh Thu Dec 20 19:39:37 2018 (r342283) @@ -15,6 +15,9 @@ set -e PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH +scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../../tools/boot/install-boot.sh + if [ $# -ne 2 ]; then echo "make-memstick.sh /path/to/directory /path/to/image/file" exit 1 @@ -36,9 +39,14 @@ makefs -B little -o label=FreeBSD_Install -o version=2 rm ${1}/etc/fstab rm ${1}/etc/rc.conf.local +# Make an ESP in a file. +espfilename=$(mktemp /tmp/efiboot.XXXXXX) +make_esp_file ${espfilename} ${fat32min} ${1}/boot/loader.efi + mkimg -s gpt \ - -p efi:=${1}/boot/boot1.efifat \ + -p efi:=${espfilename} \ -p freebsd:=${2}.part \ -o ${2} +rm ${espfilename} rm ${2}.part Modified: head/release/i386/make-memstick.sh ============================================================================== --- head/release/i386/make-memstick.sh Thu Dec 20 19:27:46 2018 (r342282) +++ head/release/i386/make-memstick.sh Thu Dec 20 19:39:37 2018 (r342283) @@ -12,6 +12,9 @@ set -e +scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../../tools/boot/install-boot.sh + PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH @@ -36,9 +39,15 @@ makefs -B little -o label=FreeBSD_Install -o version=2 rm ${1}/etc/fstab rm ${1}/etc/rc.conf.local +# Make an ESP in a file. +espfilename=$(mktemp /tmp/efiboot.XXXXXX) +make_esp_file ${espfilename} ${fat32min} ${1}/boot/loader.efi + mkimg -s mbr \ -b ${1}/boot/mbr \ + -p efi:=${espfilename} -p freebsd:-"mkimg -s bsd -b ${1}/boot/boot -p freebsd-ufs:=${2}.part" \ -o ${2} +rm ${espfilename} rm ${2}.part Modified: head/release/tools/vmimage.subr ============================================================================== --- head/release/tools/vmimage.subr Thu Dec 20 19:27:46 2018 (r342282) +++ head/release/tools/vmimage.subr Thu Dec 20 19:39:37 2018 (r342283) @@ -6,6 +6,9 @@ # Common functions for virtual machine image build scripts. # +scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../../tools/boot/install-boot.sh + export PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin" trap "cleanup" INT QUIT TRAP ABRT TERM @@ -29,10 +32,14 @@ write_partition_layout() { -o ${VMIMAGE} ;; arm64:aarch64) + # Create an ESP + espfilename=$(mktemp /tmp/efiboot.XXXXXX) + make_esp_file ${espfilename} ${fat32min} ${BOOTFILES}/efi/loader_lua/loader_lua.efi mkimg -s mbr -f ${VMFORMAT} \ - -p efi:=${BOOTFILES}/efi/boot1/boot1.efifat \ + -p efi:=${espfilename} \ -p freebsd:=${VMBASE} \ -o ${VMIMAGE} + rm ${espfilename} ;; powerpc:powerpc*) mkimg -s apm -f ${VMFORMAT} \ Modified: head/share/man/man8/uefi.8 ============================================================================== --- head/share/man/man8/uefi.8 Thu Dec 20 19:27:46 2018 (r342282) +++ head/share/man/man8/uefi.8 Thu Dec 20 19:39:37 2018 (r342283) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 25, 2018 +.Dd December 14, 2018 .Dt UEFI 8 .Os .Sh NAME @@ -77,20 +77,16 @@ The default boot configuration for .Fx installs -.Pa boot1.efi +.Pa loader.efi in the default path. .It -.Pa boot1.efi +.Pa loader.efi reads boot configuration from .Pa /boot.config or .Pa /boot/config . -Unlike other first-stage boot loaders, -.Pa boot1.efi -passes the configuration to the next stage boot loader and does not -itself act on the contents of the file. .It -.Pa boot1.efi +.Pa loader.efi searches partitions of type .Li freebsd-ufs and @@ -98,7 +94,7 @@ and for .Pa loader.efi . The search begins with partitions on the device from which -.Pa boot1.efi +.Pa loader.efi was loaded, and continues with other available partitions. If both .Li freebsd-ufs @@ -107,9 +103,6 @@ and partitions exist on the same device the .Li freebsd-zfs partition is preferred. -.Pa boot1.efi -then loads and executes -.Pa loader.efi . .It .Pa loader.efi loads and boots the kernel, as described in @@ -122,20 +115,8 @@ system console is automatically selected when booting .Nm . .Sh FILES .Bl -tag -width /boot/loader -compact -.It Pa /boot/boot1.efi -First stage .Nm bootstrap -.It Pa /boot/boot1.efifat -.Xr msdosfs 5 -FAT file system image containing -.Pa boot1.efi -for use by -.Xr bsdinstall 8 -and the -.Ar bootcode -argument to -.Xr gpart 8 . .It Pa /boot/loader.efi Final stage bootstrap .It Pa /boot/kernel/kernel Modified: head/tools/boot/install-boot.sh ============================================================================== --- head/tools/boot/install-boot.sh Thu Dec 20 19:27:46 2018 (r342282) +++ head/tools/boot/install-boot.sh Thu Dec 20 19:39:37 2018 (r342283) @@ -10,6 +10,10 @@ # insert code here to guess what you have -- yikes! +# Minimum size of FAT filesystems, in KB. +fat32min=33292 +fat16min=2100 + die() { echo $* exit 1 @@ -27,21 +31,152 @@ find-part() { gpart show $dev | tail +2 | awk '$4 == "'$part'" { print $3; }' } -make_esp() { - local dev dst mntpt +get_uefi_bootname() { + case ${TARGET:-$(uname -m)} in + amd64) echo bootx64 ;; + arm64) echo bootaa64 ;; + i386) echo bootia32 ;; + arm) echo bootarm ;; + *) die "machine type $(uname -m) doesn't support UEFI" ;; + esac +} + +make_esp_file() { + local file sizekb loader device mntpt fatbits efibootname + + file=$1 + sizekb=$2 + loader=$3 + + if [ "$sizekb" -ge "$fat32min" ]; then + fatbits=32 + elif [ "$sizekb" -ge "$fat16min" ]; then + fatbits=16 + else + fatbits=12 + fi + + dd if=/dev/zero of="${file}" bs=1k count="${sizekb}" + device=$(mdconfig -a -t vnode -f "${file}") + newfs_msdos -F "${fatbits}" -c 1 -L EFISYS "/dev/${device}" > /dev/null 2>&1 + mntpt=$(mktemp -d /tmp/stand-test.XXXXXX) + mount -t msdosfs "/dev/${device}" "${mntpt}" + mkdir -p "${mntpt}/EFI/BOOT" + efibootname=$(get_uefi_bootname) + cp "${loader}" "${mntpt}/EFI/BOOT/${efibootname}.efi" + umount "${mntpt}" + rmdir "${mntpt}" + mdconfig -d -u "${device}" +} + +make_esp_device() { + local dev file mntpt fstype efibootname kbfree loadersize efibootfile + local isboot1 existingbootentryloaderfile bootorder bootentry + + # ESP device node dev=$1 - dst=$2 + file=$2 - newfs_msdos -a 32 ${dev} mntpt=$(mktemp -d /tmp/stand-test.XXXXXX) - mount -t msdos ${dev} ${mntpt} - mkdir -p ${mntpt}/efi/boot - cp ${dst}/boot/loader.efi ${mntpt}/efi/boot/bootx64.efi - umount ${mntpt} - rmdir ${mntpt} + + # See if we're using an existing (formatted) ESP + fstype=$(fstyp "${dev}") + + if [ "${fstype}" != "msdosfs" ]; then + newfs_msdos -F 32 -c 1 -L EFISYS "${dev}" > /dev/null 2>&1 + fi + + mount -t msdosfs "${dev}" "${mntpt}" + if [ $? -ne 0 ]; then + die "Failed to mount ${dev} as an msdosfs filesystem" + fi + + 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)) + + # Check if /EFI/BOOT/BOOTxx.EFI is the FreeBSD boot1.efi + # If it is, remove it to avoid leaving stale files around + efibootfile="${mntpt}/EFI/BOOT/${efibootname}.efi" + if [ -f "${efibootfile}" ]; then + isboot1=$(strings "${efibootfile}" | grep "FreeBSD EFI boot block") + + if [ -n "${isboot1}" ] && [ "$kbfree" -lt "${loadersize}" ]; then + echo "Only ${kbfree}KB space remaining: removing old FreeBSD boot1.efi file /EFI/BOOT/${efibootname}.efi" + rm "${efibootfile}" + rmdir "${mntpt}/EFI/BOOT" + else + echo "${kbfree}KB space remaining on ESP: renaming old boot1.efi file /EFI/BOOT/${efibootname}.efi /EFI/BOOT/${efibootname}-old.efi" + mv "${efibootfile}" "${mntpt}/EFI/BOOT/${efibootname}-old.efi" + fi + fi + + if [ ! -f "${mntpt}/EFI/freebsd/loader.efi" ] && [ "$kbfree" -lt "$loadersize" ]; then + umount "${mntpt}" + rmdir "${mntpt}" + echo "Failed to update the EFI System Partition ${dev}" + echo "Insufficient space remaining for ${file}" + echo "Run e.g \"mount -t msdosfs ${dev} /mnt\" to inspect it for files that can be removed." + die + fi + + 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" + fi + + echo "Copying loader to /EFI/freebsd on ESP" + cp "${file}" "${mntpt}/EFI/freebsd/loader.efi" + + existingbootentryloaderfile=$(efibootmgr -v | grep "${mntpt}//EFI/freebsd/loader.efi") + + if [ -z "$existingbootentryloaderfile" ]; then + # Try again without the double forward-slash in the path + existingbootentryloaderfile=$(efibootmgr -v | grep "${mntpt}/EFI/freebsd/loader.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 + if [ $? -ne 0 ]; then + die "Failed to create new boot entry" + fi + + # When creating new entries, efibootmgr doesn't mark them active, so we need to + # do so. It doesn't make it easy to find which entry it just added, so rely on + # the fact that it places the new entry first in BootOrder. + bootorder=$(efivar --name 8be4df61-93ca-11d2-aa0d-00e098032b8c-BootOrder --print --no-name --hex | head -1) + bootentry=$(echo "${bootorder}" | cut -w -f 3)$(echo "${bootorder}" | cut -w -f 2) + echo "Marking UEFI boot entry ${bootentry} active" + efibootmgr --activate "${bootentry}" > /dev/null + else + echo "Existing UEFI FreeBSD boot entry found: not creating a new one" + fi + + umount "${mntpt}" + rmdir "${mntpt}" + echo "Finished updating ESP" } +make_esp() { + local file loaderfile + + file=$1 + loaderfile=$2 + + if [ -f "$file" ]; then + make_esp_file ${file} ${fat32min} ${loaderfile} + else + make_esp_device ${file} ${loaderfile} + fi +} + make_esp_mbr() { dev=$1 dst=$2 @@ -53,7 +188,7 @@ make_esp_mbr() { die "No ESP slice found" fi fi - make_esp /dev/${dev}s${s} ${dst} + make_esp /dev/${dev}s${s} ${dst}/boot/loader.efi } make_esp_gpt() { @@ -64,7 +199,7 @@ make_esp_gpt() { if [ -z "$idx" ] ; then die "No ESP partition found" fi - make_esp /dev/${dev}p${idx} ${dst} + make_esp /dev/${dev}p${idx} ${dst}/boot/loader.efi } boot_nogeli_gpt_ufs_legacy() { @@ -218,18 +353,32 @@ boot_nogeli_vtoc8_ufs_ofw() { doit gpart bootcode -p ${vtoc8} ${dev} } -DESTDIR=/ +usage() { + printf 'Usage: %s -b bios [-d destdir] -f fs [-g geli] [-h] [-o optargs] -s scheme \n' "$0" + printf 'Options:\n' + printf ' bootdev device to install the boot code on\n' + printf ' -b bios bios type: legacy, uefi or both\n' + printf ' -d destdir destination filesystem root\n' + printf ' -f fs filesystem type: ufs or zfs\n' + printf ' -g geli yes or no\n' + printf ' -h this help/usage text\n' + printf ' -o optargs optional arguments\n' + printf ' -s scheme mbr or gpt\n' + exit 0 +} +srcroot=/ + # Note: we really don't support geli boot in this script yet. geli=nogeli -while getopts "b:d:f:g:o:s:" opt; do +while getopts "b:d:f:g:ho:s:" opt; do case "$opt" in b) bios=${OPTARG} ;; d) - DESTDIR=${OPTARG} + srcroot=${OPTARG} ;; f) fs=${OPTARG} @@ -246,25 +395,35 @@ while getopts "b:d:f:g:o:s:" opt; do s) scheme=${OPTARG} ;; + + ?|h) + usage + ;; esac done -shift $((OPTIND-1)) -dev=$1 +if [ -n "${scheme}" ] && [ -n "${fs}" ] && [ -n "${bios}" ]; then + shift $((OPTIND-1)) + dev=$1 +fi # For gpt, we need to install pmbr as the primary boot loader # it knows about -gpt0=${DESTDIR}/boot/pmbr -gpt2=${DESTDIR}/boot/gptboot -gptzfs2=${DESTDIR}/boot/gptzfsboot +gpt0=${srcroot}/boot/pmbr +gpt2=${srcroot}/boot/gptboot +gptzfs2=${srcroot}/boot/gptzfsboot # For MBR, we have lots of choices, but select mbr, boot0 has issues with UEFI -mbr0=${DESTDIR}/boot/mbr -mbr2=${DESTDIR}/boot/boot +mbr0=${srcroot}/boot/mbr +mbr2=${srcroot}/boot/boot # VTOC8 -vtoc8=${DESTDIR}/boot/boot1 +vtoc8=${srcroot}/boot/boot1 # sanity check here -eval boot_${geli}_${scheme}_${fs}_${bios} $dev $DESTDIR $opts || echo "Unsupported boot env: ${geli}-${scheme}-${fs}-${bios}" +# Check if we've been given arguments. If not, this script is probably being +# sourced, so we shouldn't run anything. +if [ -n "${dev}" ]; then + eval boot_${geli}_${scheme}_${fs}_${bios} $dev $srcroot $opts || echo "Unsupported boot env: ${geli}-${scheme}-${fs}-${bios}" +fi Modified: head/tools/boot/rootgen.sh ============================================================================== --- head/tools/boot/rootgen.sh Thu Dec 20 19:27:46 2018 (r342282) +++ head/tools/boot/rootgen.sh Thu Dec 20 19:39:37 2018 (r342283) @@ -5,7 +5,8 @@ passphrase=passphrase iterations=50000 -do_boot1_efi=0 +# The smallest FAT32 filesystem is 33292 KB +espsize=33292 # # Builds all the bat-shit crazy combinations we support booting from, @@ -16,13 +17,13 @@ do_boot1_efi=0 # Sad panda sez: this runs as root, but could be userland if someone # creates userland geli and zfs tools. # -# This assumes an external prograam install-boot.sh which will install +# This assumes an external program install-boot.sh which will install # the appropriate boot files in the appropriate locations. # # These images assume ada0 will be the root image. We should likely # use labels, but we don't. # -# ASsumes you've already rebuilt... maybe bad? Also maybe bad: the env +# Assumes you've already rebuilt... maybe bad? Also maybe bad: the env # vars should likely be conditionally set to allow better automation. # @@ -34,29 +35,6 @@ cpsys() { (cd $src ; tar cf - .) | (cd $dst; tar xf -) } -make_esp() -{ - local src dst md mntpt - src=$1 - dst=$2 - - if [ "${do_boot1_efi}" -eq 1 ]; then - cp ${src}/boot/boot1.efifat ${dst} - else - dd if=/dev/zero of=${dst} count=1 seek=$((100 * 1024 * 1024 / 512)) - md=$(mdconfig -f ${dst}) - newfs_msdos -a 32 /dev/${md} - mntpt=$(mktemp -d /tmp/stand-test.XXXXXX) - mount -t msdos /dev/${md} ${mntpt} -# mkdir -p ${mntpt}/efi/freebsd # not yet - mkdir -p ${mntpt}/efi/boot - cp ${src}/boot/loader.efi ${mntpt}/efi/boot/bootx64.efi - umount ${mntpt} - rmdir ${mntpt} - mdconfig -d -u ${md} - fi -} - mk_nogeli_gpt_ufs_legacy() { src=$1 img=$2 @@ -78,7 +56,7 @@ mk_nogeli_gpt_ufs_uefi() { cat > ${src}/etc/fstab < ${src}/etc/fstab < ${src}/etc/fstab < ${src}/etc/fstab < #include #include +#include #include #include @@ -192,7 +193,9 @@ newfs_command(const char *fstype, char *command, int u for (i = 0; i < (int)nitems(items); i++) { if (items[i].state == 0) continue; - if (strcmp(items[i].name, "FAT16") == 0) + if (strcmp(items[i].name, "FAT32") == 0) + strcat(command, "-F 32 -c 1"); + else if (strcmp(items[i].name, "FAT16") == 0) strcat(command, "-F 16 "); else if (strcmp(items[i].name, "FAT12") == 0) strcat(command, "-F 12 "); @@ -400,7 +403,7 @@ gpart_bootcode(struct ggeom *gp) TRUE); return; } - + bootsize = lseek(bootfd, 0, SEEK_END); boot = malloc(bootsize); lseek(bootfd, 0, SEEK_SET); @@ -706,8 +709,17 @@ set_default_part_metadata(const char *name, const char if (strcmp(type, "freebsd-swap") == 0) mountpoint = "none"; if (strcmp(type, bootpart_type(scheme, &default_bootmount)) == 0) { - if (default_bootmount == NULL) + if (default_bootmount == NULL) { + + int fd = open("/tmp/bsdinstall-esps", O_CREAT | O_WRONLY | O_APPEND, + 0600); + if (fd > 0) { + write(fd, md->name, strlen(md->name)); + close(fd); + } + md->bootcode = 1; + } else if (mountpoint == NULL || strlen(mountpoint) == 0) mountpoint = default_bootmount; } Modified: head/usr.sbin/bsdinstall/partedit/partedit_arm64.c ============================================================================== --- head/usr.sbin/bsdinstall/partedit/partedit_arm64.c Thu Dec 20 19:27:46 2018 (r342282) +++ head/usr.sbin/bsdinstall/partedit/partedit_arm64.c Thu Dec 20 19:39:37 2018 (r342283) @@ -35,8 +35,7 @@ #include "partedit.h" /* EFI partition size in bytes */ -#define EFI_BOOTPART_SIZE (200 * 1024 * 1024) -#define EFI_BOOTPART_PATH "/boot/boot1.efifat" +#define EFI_BOOTPART_SIZE (260 * 1024 * 1024) const char * default_scheme(void) @@ -95,10 +94,7 @@ const char * partcode_path(const char *part_type, const char *fs_type) { - if (strcmp(part_type, "GPT") == 0) - return (EFI_BOOTPART_PATH); - - /* No boot partition data for non-GPT */ + /* No boot partition data for ARM64 */ return (NULL); } Modified: head/usr.sbin/bsdinstall/partedit/partedit_x86.c ============================================================================== --- head/usr.sbin/bsdinstall/partedit/partedit_x86.c Thu Dec 20 19:27:46 2018 (r342282) +++ head/usr.sbin/bsdinstall/partedit/partedit_x86.c Thu Dec 20 19:39:37 2018 (r342283) @@ -35,8 +35,7 @@ #include "partedit.h" /* EFI partition size in bytes */ -#define EFI_BOOTPART_SIZE (200 * 1024 * 1024) -#define EFI_BOOTPART_PATH "/boot/boot1.efifat" +#define EFI_BOOTPART_SIZE (260 * 1024 * 1024) static const char * x86_bootmethod(void) @@ -141,16 +140,14 @@ const char * partcode_path(const char *part_type, const char *fs_type) { - if (strcmp(part_type, "GPT") == 0) { - if (strcmp(x86_bootmethod(), "UEFI") == 0) - return (EFI_BOOTPART_PATH); - else if (strcmp(fs_type, "zfs") == 0) + if (strcmp(part_type, "GPT") == 0 && strcmp(x86_bootmethod(), "UEFI") != 0) { + if (strcmp(fs_type, "zfs") == 0) return ("/boot/gptzfsboot"); else return ("/boot/gptboot"); } - /* No partcode except for GPT */ + /* No partcode except for non-UEFI GPT */ return (NULL); } Modified: head/usr.sbin/bsdinstall/scripts/bootconfig ============================================================================== --- head/usr.sbin/bsdinstall/scripts/bootconfig Thu Dec 20 19:27:46 2018 (r342282) +++ head/usr.sbin/bsdinstall/scripts/bootconfig Thu Dec 20 19:39:37 2018 (r342283) @@ -1,5 +1,6 @@ #!/bin/sh #- +# Copyright (c) 2018 Rebecca Cran # Copyright (c) 2017 Nathan Whitehorn # All rights reserved. # @@ -26,6 +27,11 @@ # # $FreeBSD$ +die() { + echo $* + exit 1 +} + if [ `uname -m` == powerpc ]; then platform=`sysctl -n hw.platform` if [ "$platform" == ps3 -o "$platform" == powernv ]; then @@ -35,6 +41,115 @@ if [ `uname -m` == powerpc ]; then fi fi -# For new-style EFI booting, add code here -# Add boot0cfg for MBR BIOS booting? +# Update the ESP (EFI System Partition) with the new bootloader +if [ "$(uname -m)" = "amd64" ] || [ "$(uname -m)" = "i386" ]; then + X86_BOOTMETHOD=$(sysctl -n machdep.bootmethod) +fi +if [ "$(uname -m)" = "arm64" ] || [ "$X86_BOOTMETHOD" = "UEFI" ]; then + UFSBOOT_ESPS=$(cat /tmp/bsdinstall-esps) + num_esps=0 + + if [ -n "$ZFSBOOT_DISKS" ]; then + # We're in a ZFS install environment + for disk in $ZFSBOOT_DISKS; do + index=$(gpart show "$disk" | cut -w -f 4,5 | grep "efi" | cut -w -f 1) + # Check that $index is an integer + [ -n "$index" ] && [ "$index" -eq "$index" ] && [ "$index" -ge 0 ] 2> /dev/null + if [ $? -ne 0 ]; then + continue + fi + + if [ -e "/dev/${disk}p${index}" ]; then + ESPS="$ESPS ${disk}p${index}" + elif [ -e "/dev/${disk}s${index}" ]; then + ESPS="$ESPS ${disk}s${index}" + else + continue + fi + + num_esps=$((num_esps + 1)) + done + fi + + if [ -n "$UFSBOOT_ESPS" ]; then + # We're in a UFS install environment + for partition in $UFSBOOT_ESPS; do + ESPS="$ESPS $partition" + num_esps=$((num_esps + 1)) + done + fi + + if [ -z "$ESPS" ]; then + # The installer hasn't given us any ESPs to use. + # Try and figure out which to use by looking for an + # unformatted efi partition + for disk in $(sysctl -n kern.disks); do + hasfreebsd=$(gpart show "$disk" | cut -w -f 4,5 | grep "freebsd") + if [ -n "$hasfreebsd" ]; then + index=$(gpart show "$disk" | cut -w -f 4,5 | grep "efi" | cut -w -f 1) + # Check that $index is a valid integer + [ -n "$index" ] && [ "$index" -eq "$index" ] && [ "$index" -ge 0 ] 2> /dev/null + if [ $? -ne 0 ]; then + continue + fi + + mntpt=$(mktemp -d /tmp/stand-test.XXXXXX) + if [ -e "/dev/${disk}p${index}" ]; then + dev=${disk}p${index} + elif [ -e "/dev/${disk}s${index}" ]; then + dev=/${disk}s${index} + else + continue + fi + + # Try and mount it. If it fails, assume it's + # unformatted and should be used. + mount -t msdosfs "/dev/${dev}" "${mntpt}" + if [ $? -ne 0 ]; then + ESPS="$ESPS ${dev}" + num_esps=$((num_esps + 1)) + else + umount "${mntpt}" + fi + rmdir "${mntpt}" + fi + done + fi + + for esp in $ESPS; do + newfs_msdos -F 32 -c 1 -L EFISYS "/dev/$esp" > /dev/null 2>&1 + if [ $? -ne 0 ]; then + die "Failed to format ESP $esp as FAT32" + fi + + mntpt=$(mktemp -d /tmp/stand-test.XXXXXX) + mount -t msdosfs "/dev/${esp}" "${mntpt}" + if [ $? -ne 0 ]; then + die "Failed to mount ESP ${dev} on ${mntpt}" + fi + + mkdir -p "$mntpt/EFI/freebsd" + cp "$BSDINSTALL_CHROOT/boot/loader.efi" "${mntpt}/EFI/freebsd/loader.efi" + + if [ "$num_esps" -gt 1 ]; then + bootlabel="FreeBSD (${esp})" + else + bootlabel="FreeBSD" + fi + + efibootmgr --create --label "$bootlabel" --loader "${mntpt}/EFI/freebsd/loader.efi" > /dev/null + + umount "${mntpt}" + rmdir "${mntpt}" + + # When creating new entries, efibootmgr doesn't mark them active, so we need to + # do so. It doesn't make it easy to find which entry it just added, so rely on + # the fact that it places the new entry first in BootOrder. + bootorder=$(efivar --name 8be4df61-93ca-11d2-aa0d-00e098032b8c-BootOrder --print --no-name --hex | head -1) + bootentry=$(echo "$bootorder" | cut -w -f 3)$(echo "$bootorder" | cut -w -f 2) + efibootmgr --activate "$bootentry" > /dev/null + done +fi + +# Add boot0cfg for MBR BIOS booting? Modified: head/usr.sbin/bsdinstall/scripts/zfsboot ============================================================================== --- head/usr.sbin/bsdinstall/scripts/zfsboot Thu Dec 20 19:27:46 2018 (r342282) +++ head/usr.sbin/bsdinstall/scripts/zfsboot Thu Dec 20 19:39:37 2018 (r342283) @@ -213,7 +213,6 @@ KLDLOAD='kldload %s' LN_SF='ln -sf "%s" "%s"' MKDIR_P='mkdir -p "%s"' MOUNT_TYPE='mount -t %s "%s" "%s"' -NEWFS_ESP='newfs_msdos -F %s -L "%s" "%s"' PRINTF_CONF="printf '%s=\"%%s\"\\\n' %s >> \"%s\"" PRINTF_FSTAB='printf "$FSTAB_FMT" "%s" "%s" "%s" "%s" "%s" "%s" >> "%s"' SHELL_TRUNCATE=':> "%s"' @@ -851,29 +850,7 @@ zfs_create_diskpart() "$align_small" efiboot$index efi 200M \ $disk || return $FAILURE - f_eval_catch $funcname mkdir "$MKDIR_P" \ - "$BSDINSTALL_TMPETC/esp" || - return $FAILURE - f_eval_catch $funcname newfs_msdos "$NEWFS_ESP" "16" \ - "EFISYS" "/dev/${disk}p1" || - return $FAILURE - f_eval_catch $funcname mount "$MOUNT_TYPE" "msdosfs" \ - "/dev/${disk}p1" \ - "$BSDINSTALL_TMPETC/esp" || - return $FAILURE - f_eval_catch $funcname mkdir "$MKDIR_P" \ - "$BSDINSTALL_TMPETC/esp/efi/boot" || - return $FAILURE - f_eval_catch $funcname cp "$COPY" "/boot/loader.efi" \ - "$BSDINSTALL_TMPETC/esp/efi/boot/$ZFSBOOT_ESP_NAME" || - return $FAILURE - f_eval_catch $funcname echo "$ECHO_OVERWRITE" \ - "$ZFSBOOT_ESP_NAME" \ - "$BSDINSTALL_TMPETC/esp/efi/boot/startup.nsh" || - return $FAILURE - f_eval_catch $funcname umount "$UMOUNT" \ - "$BSDINSTALL_TMPETC/esp" || - return $FAILURE + # We'll configure the ESP in bootconfig fi if [ "$ZFSBOOT_BOOT_TYPE" = "BIOS" -o \ @@ -1593,20 +1570,6 @@ arm64) : ${ZFSBOOT_PARTITION_SCHEME:=GPT} fi ;; -esac - -# -# The EFI loader installed in the ESP (EFI System Partition) must -# have the expected name in order to load correctly. -# -[ "$ZFSBOOT_ESP_NAME" ] || case "${UNAME_m:-$( uname -m )}" in - arm64) ZFSBOOT_ESP_NAME=BOOTaa64.efi ;; - arm) ZFSBOOT_ESP_NAME=BOOTarm.efi ;; - i386) ZFSBOOT_ESP_NAME=BOOTia32.efi ;; - amd64) ZFSBOOT_ESP_NAME=BOOTx64.efi ;; - *) - f_dprintf "Unsupported architecture: %s" $UNAME_m - f_die esac *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***