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
This commit is contained in:
Rebecca Cran 2018-12-20 19:39:37 +00:00
parent d5cee48f3e
commit db8b561345
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=342283
14 changed files with 390 additions and 160 deletions

View file

@ -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 ${2}.part ${1}
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

View file

@ -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.org/"
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.

View file

@ -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 ${2}.part ${1}
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

View file

@ -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 ${2}.part ${1}
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

View file

@ -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} \

View file

@ -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 via
.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

View file

@ -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,19 +31,150 @@ find-part() {
gpart show $dev | tail +2 | awk '$4 == "'$part'" { print $3; }'
}
make_esp() {
local dev dst mntpt
get_uefi_bootname() {
dev=$1
dst=$2
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
}
newfs_msdos -a 32 ${dev}
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 msdos ${dev} ${mntpt}
mkdir -p ${mntpt}/efi/boot
cp ${dst}/boot/loader.efi ${mntpt}/efi/boot/bootx64.efi
umount ${mntpt}
rmdir ${mntpt}
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
file=$2
mntpt=$(mktemp -d /tmp/stand-test.XXXXXX)
# 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() {
@ -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 <bootdev>\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

View file

@ -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 <<EOF
/dev/ada0p2 / ufs rw 1 1
EOF
make_esp ${src} ${img}.p1
make_esp_file ${img}.p1 ${espsize} ${src}
makefs -t ffs -B little -s 200m ${img}.p2 ${src}
mkimg -s gpt \
-p efi:=${img}.p1 \
@ -93,7 +71,7 @@ mk_nogeli_gpt_ufs_both() {
cat > ${src}/etc/fstab <<EOF
/dev/ada0p3 / ufs rw 1 1
EOF
make_esp ${src} ${img}.p1
make_esp_file ${img}.p1 ${espsize} ${src}
makefs -t ffs -B little -s 200m ${img}.p3 ${src}
# p1 is boot for uefi, p2 is boot for gpt, p3 is /
mkimg -b ${src}/boot/pmbr -s gpt \
@ -155,7 +133,7 @@ mk_nogeli_gpt_zfs_uefi() {
dd if=/dev/zero of=${img} count=1 seek=$((200 * 1024 * 1024 / 512))
md=$(mdconfig -f ${img})
gpart create -s gpt ${md}
gpart add -t efi -s 800k -a 4k ${md}
gpart add -t efi -s ${espsize}k -a 4k ${md}
gpart add -t freebsd-zfs -l root $md
# install-boot will make this bootable
zpool create -O mountpoint=none -R ${mntpt} ${pool} ${md}p2
@ -193,7 +171,7 @@ mk_nogeli_gpt_zfs_both() {
dd if=/dev/zero of=${img} count=1 seek=$((200 * 1024 * 1024 / 512))
md=$(mdconfig -f ${img})
gpart create -s gpt ${md}
gpart add -t efi -s 800k -a 4k ${md}
gpart add -t efi -s ${espsize}k -a 4k ${md}
gpart add -t freebsd-boot -s 400k -a 4k ${md} # <= ~540k
gpart add -t freebsd-zfs -l root $md
# install-boot will make this bootable
@ -239,7 +217,7 @@ mk_nogeli_mbr_ufs_uefi() {
cat > ${src}/etc/fstab <<EOF
/dev/ada0s2a / ufs rw 1 1
EOF
make_esp ${src} ${img}.s1
make_esp_file ${img}.s1 ${espsize} ${src}
makefs -t ffs -B little -s 200m ${img}.s2a ${src}
mkimg -s bsd -p freebsd-ufs:=${img}.s2a -o ${img}.s2
mkimg -a 1 -s mbr -p efi:=${img}.s1 -p freebsd:=${img}.s2 -o ${img}
@ -253,7 +231,7 @@ mk_nogeli_mbr_ufs_both() {
cat > ${src}/etc/fstab <<EOF
/dev/ada0s2a / ufs rw 1 1
EOF
make_esp ${src} ${img}.s1
make_esp_file ${img}.s1 ${espsize} ${src}
makefs -t ffs -B little -s 200m ${img}.s2a ${src}
mkimg -s bsd -b ${src}/boot/boot -p freebsd-ufs:=${img}.s2a -o ${img}.s2
mkimg -a 2 -s mbr -b ${src}/boot/mbr -p efi:=${img}.s1 -p freebsd:=${img}.s2 -o ${img}
@ -313,7 +291,7 @@ mk_nogeli_mbr_zfs_uefi() {
dd if=/dev/zero of=${img} count=1 seek=$((200 * 1024 * 1024 / 512))
md=$(mdconfig -f ${img})
gpart create -s mbr ${md}
gpart add -t \!239 -s 800k ${md}
gpart add -t efi -s ${espsize}k ${md}
gpart add -t freebsd ${md}
gpart set -a active -i 2 ${md}
gpart create -s bsd ${md}s2
@ -354,7 +332,7 @@ mk_nogeli_mbr_zfs_both() {
dd if=/dev/zero of=${img} count=1 seek=$((200 * 1024 * 1024 / 512))
md=$(mdconfig -f ${img})
gpart create -s mbr ${md}
gpart add -t \!239 -s 800k ${md}
gpart add -t efi -s ${espsize}k ${md}
gpart add -t freebsd ${md}
gpart set -a active -i 2 ${md}
gpart create -s bsd ${md}s2
@ -430,7 +408,7 @@ mk_geli_gpt_ufs_uefi() {
dd if=/dev/zero of=${img} count=1 seek=$(( 200 * 1024 * 1024 / 512 ))
md=$(mdconfig -f ${img})
gpart create -s gpt ${md}
gpart add -t efi -s 800k -a 4k ${md}
gpart add -t efi -s ${espsize}k -a 4k ${md}
gpart add -t freebsd-ufs -l root $md
# install-boot will make this bootable
echo ${passphrase} | geli init -bg -e AES-XTS -i ${iterations} -J - -l 256 -s 4096 ${md}p2
@ -466,7 +444,7 @@ mk_geli_gpt_ufs_both() {
dd if=/dev/zero of=${img} count=1 seek=$(( 200 * 1024 * 1024 / 512 ))
md=$(mdconfig -f ${img})
gpart create -s gpt ${md}
gpart add -t efi -s 800k -a 4k ${md}
gpart add -t efi -s ${espsize}k -a 4k ${md}
gpart add -t freebsd-boot -s 400k -a 4k ${md} # <= ~540k
gpart add -t freebsd-ufs -l root $md
# install-boot will make this bootable
@ -547,7 +525,7 @@ mk_geli_gpt_zfs_uefi() {
dd if=/dev/zero of=${img} count=1 seek=$(( 200 * 1024 * 1024 / 512 ))
md=$(mdconfig -f ${img})
gpart create -s gpt ${md}
gpart add -t efi -s 800k -a 4k ${md}
gpart add -t efi -s ${espsize}k -a 4k ${md}
gpart add -t freebsd-zfs -l root $md
# install-boot will make this bootable
echo ${passphrase} | geli init -bg -e AES-XTS -i ${iterations} -J - -l 256 -s 4096 ${md}p2
@ -590,7 +568,7 @@ mk_geli_gpt_zfs_both() {
dd if=/dev/zero of=${img} count=1 seek=$(( 200 * 1024 * 1024 / 512 ))
md=$(mdconfig -f ${img})
gpart create -s gpt ${md}
gpart add -t efi -s 800k -a 4k ${md}
gpart add -t efi -s ${espsize}k -a 4k ${md}
gpart add -t freebsd-boot -s 400k -a 4k ${md} # <= ~540k
gpart add -t freebsd-zfs -l root $md
# install-boot will make this bootable

View file

@ -301,7 +301,7 @@ create_diskimage_mbr ( ) (
# s1 is boot, s2 is cfg, s3 is /, not sure how to make that
# boot (marked as active) with mkimg yet
mkimg -a 2 ${fmtarg} ${bootmbr} -s mbr \
-p efi:=${NANO_WORLDDIR}/boot/boot1.efifat \
-p efi:=${NANO_WORLDDIR}/boot/efiboot.img \
-p ${s2}:=${NANO_LOG}/_.s2 \
-p ${s3}:=${NANO_LOG}/_.s3 \
-o ${out}
@ -310,7 +310,7 @@ create_diskimage_mbr ( ) (
# p1 is boot for uefi, p2 is boot for gpt, p3 is cfg, p4 is /
# and p5 is alt-root (after resize)
mkimg -a 2 ${fmtarg} ${bootmbr} -s gpt \
-p efi:=${NANO_WORLDDIR}/boot/boot1.efifat \
-p efi:=${NANO_WORLDDIR}/boot/efiboot.img \
-p freebsd-boot:=${NAANO_WORLDDIR}/boot/gptboot \
-p ${p3}:=${NANO_LOG}/_.p3 \
-p ${p4}:=${NANO_LOG}/_.p4 \

View file

@ -31,6 +31,7 @@
#include <sys/param.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <libutil.h>
#include <inttypes.h>
@ -192,7 +193,9 @@ newfs_command(const char *fstype, char *command, int use_default)
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 *scheme,
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;
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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?

View file

@ -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 \
@ -1595,20 +1572,6 @@ arm64)
;;
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
#
# Loop over the main menu until we've accomplished what we came here to do
#