diff options
| author | Rebecca Cran <bcran@FreeBSD.org> | 2018-12-20 19:39:37 +0000 |
|---|---|---|
| committer | Rebecca Cran <bcran@FreeBSD.org> | 2018-12-20 19:39:37 +0000 |
| commit | db8b56134506840832bec2d1ce07b9e00d4d6d71 (patch) | |
| tree | 242e3d5aea577a1691fc784b6b35da9690e23d5c /tools/boot | |
| parent | d5cee48f3e65662051e15c85e4fc1841d72977fe (diff) | |
Notes
Diffstat (limited to 'tools/boot')
| -rwxr-xr-x | tools/boot/install-boot.sh | 205 | ||||
| -rwxr-xr-x | tools/boot/rootgen.sh | 54 |
2 files changed, 198 insertions, 61 deletions
diff --git a/tools/boot/install-boot.sh b/tools/boot/install-boot.sh index 54eb6bec97603..cf82ff056fe2f 100755 --- a/tools/boot/install-boot.sh +++ b/tools/boot/install-boot.sh @@ -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() { + + 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() { @@ -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 diff --git a/tools/boot/rootgen.sh b/tools/boot/rootgen.sh index 87b541bdf4b09..4faf9335ca717 100755 --- a/tools/boot/rootgen.sh +++ b/tools/boot/rootgen.sh @@ -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 |
