install-boot.sh (394641cf3d2fd8422a6ee79a73d7eca857bddb2e) | install-boot.sh (db8b56134506840832bec2d1ce07b9e00d4d6d71) |
---|---|
1#!/bin/sh 2 3# $FreeBSD$ 4 5# 6# Installs/updates the necessary boot blocks for the desired boot environment 7# 8# Lightly tested.. Intended to be installed, but until it matures, it will just 9# be a boot tool for regression testing. 10 11# insert code here to guess what you have -- yikes! 12 | 1#!/bin/sh 2 3# $FreeBSD$ 4 5# 6# Installs/updates the necessary boot blocks for the desired boot environment 7# 8# Lightly tested.. Intended to be installed, but until it matures, it will just 9# be a boot tool for regression testing. 10 11# insert code here to guess what you have -- yikes! 12 |
13# Minimum size of FAT filesystems, in KB. 14fat32min=33292 15fat16min=2100 16 |
|
13die() { 14 echo $* 15 exit 1 16} 17 18doit() { 19 echo $* 20 eval $* 21} 22 23find-part() { 24 dev=$1 25 part=$2 26 27 gpart show $dev | tail +2 | awk '$4 == "'$part'" { print $3; }' 28} 29 | 17die() { 18 echo $* 19 exit 1 20} 21 22doit() { 23 echo $* 24 eval $* 25} 26 27find-part() { 28 dev=$1 29 part=$2 30 31 gpart show $dev | tail +2 | awk '$4 == "'$part'" { print $3; }' 32} 33 |
30make_esp() { 31 local dev dst mntpt | 34get_uefi_bootname() { |
32 | 35 |
36 case ${TARGET:-$(uname -m)} in 37 amd64) echo bootx64 ;; 38 arm64) echo bootaa64 ;; 39 i386) echo bootia32 ;; 40 arm) echo bootarm ;; 41 *) die "machine type $(uname -m) doesn't support UEFI" ;; 42 esac 43} 44 45make_esp_file() { 46 local file sizekb loader device mntpt fatbits efibootname 47 48 file=$1 49 sizekb=$2 50 loader=$3 51 52 if [ "$sizekb" -ge "$fat32min" ]; then 53 fatbits=32 54 elif [ "$sizekb" -ge "$fat16min" ]; then 55 fatbits=16 56 else 57 fatbits=12 58 fi 59 60 dd if=/dev/zero of="${file}" bs=1k count="${sizekb}" 61 device=$(mdconfig -a -t vnode -f "${file}") 62 newfs_msdos -F "${fatbits}" -c 1 -L EFISYS "/dev/${device}" > /dev/null 2>&1 63 mntpt=$(mktemp -d /tmp/stand-test.XXXXXX) 64 mount -t msdosfs "/dev/${device}" "${mntpt}" 65 mkdir -p "${mntpt}/EFI/BOOT" 66 efibootname=$(get_uefi_bootname) 67 cp "${loader}" "${mntpt}/EFI/BOOT/${efibootname}.efi" 68 umount "${mntpt}" 69 rmdir "${mntpt}" 70 mdconfig -d -u "${device}" 71} 72 73make_esp_device() { 74 local dev file mntpt fstype efibootname kbfree loadersize efibootfile 75 local isboot1 existingbootentryloaderfile bootorder bootentry 76 77 # ESP device node |
|
33 dev=$1 | 78 dev=$1 |
34 dst=$2 | 79 file=$2 |
35 | 80 |
36 newfs_msdos -a 32 ${dev} | |
37 mntpt=$(mktemp -d /tmp/stand-test.XXXXXX) | 81 mntpt=$(mktemp -d /tmp/stand-test.XXXXXX) |
38 mount -t msdos ${dev} ${mntpt} 39 mkdir -p ${mntpt}/efi/boot 40 cp ${dst}/boot/loader.efi ${mntpt}/efi/boot/bootx64.efi 41 umount ${mntpt} 42 rmdir ${mntpt} | 82 83 # See if we're using an existing (formatted) ESP 84 fstype=$(fstyp "${dev}") 85 86 if [ "${fstype}" != "msdosfs" ]; then 87 newfs_msdos -F 32 -c 1 -L EFISYS "${dev}" > /dev/null 2>&1 88 fi 89 90 mount -t msdosfs "${dev}" "${mntpt}" 91 if [ $? -ne 0 ]; then 92 die "Failed to mount ${dev} as an msdosfs filesystem" 93 fi 94 95 echo "Mounted ESP ${dev} on ${mntpt}" 96 97 efibootname=$(get_uefi_bootname) 98 kbfree=$(df -k "${mntpt}" | tail -1 | cut -w -f 4) 99 loadersize=$(stat -f %z "${file}") 100 loadersize=$((loadersize / 1024)) 101 102 # Check if /EFI/BOOT/BOOTxx.EFI is the FreeBSD boot1.efi 103 # If it is, remove it to avoid leaving stale files around 104 efibootfile="${mntpt}/EFI/BOOT/${efibootname}.efi" 105 if [ -f "${efibootfile}" ]; then 106 isboot1=$(strings "${efibootfile}" | grep "FreeBSD EFI boot block") 107 108 if [ -n "${isboot1}" ] && [ "$kbfree" -lt "${loadersize}" ]; then 109 echo "Only ${kbfree}KB space remaining: removing old FreeBSD boot1.efi file /EFI/BOOT/${efibootname}.efi" 110 rm "${efibootfile}" 111 rmdir "${mntpt}/EFI/BOOT" 112 else 113 echo "${kbfree}KB space remaining on ESP: renaming old boot1.efi file /EFI/BOOT/${efibootname}.efi /EFI/BOOT/${efibootname}-old.efi" 114 mv "${efibootfile}" "${mntpt}/EFI/BOOT/${efibootname}-old.efi" 115 fi 116 fi 117 118 if [ ! -f "${mntpt}/EFI/freebsd/loader.efi" ] && [ "$kbfree" -lt "$loadersize" ]; then 119 umount "${mntpt}" 120 rmdir "${mntpt}" 121 echo "Failed to update the EFI System Partition ${dev}" 122 echo "Insufficient space remaining for ${file}" 123 echo "Run e.g \"mount -t msdosfs ${dev} /mnt\" to inspect it for files that can be removed." 124 die 125 fi 126 127 mkdir -p "${mntpt}/EFI/freebsd" 128 129 # Keep a copy of the existing loader.efi in case there's a problem with the new one 130 if [ -f "${mntpt}/EFI/freebsd/loader.efi" ] && [ "$kbfree" -gt "$((loadersize * 2))" ]; then 131 cp "${mntpt}/EFI/freebsd/loader.efi" "${mntpt}/EFI/freebsd/loader-old.efi" 132 fi 133 134 echo "Copying loader to /EFI/freebsd on ESP" 135 cp "${file}" "${mntpt}/EFI/freebsd/loader.efi" 136 137 existingbootentryloaderfile=$(efibootmgr -v | grep "${mntpt}//EFI/freebsd/loader.efi") 138 139 if [ -z "$existingbootentryloaderfile" ]; then 140 # Try again without the double forward-slash in the path 141 existingbootentryloaderfile=$(efibootmgr -v | grep "${mntpt}/EFI/freebsd/loader.efi") 142 fi 143 144 if [ -z "$existingbootentryloaderfile" ]; then 145 echo "Creating UEFI boot entry for FreeBSD" 146 efibootmgr --create --label FreeBSD --loader "${mntpt}/EFI/freebsd/loader.efi" > /dev/null 147 if [ $? -ne 0 ]; then 148 die "Failed to create new boot entry" 149 fi 150 151 # When creating new entries, efibootmgr doesn't mark them active, so we need to 152 # do so. It doesn't make it easy to find which entry it just added, so rely on 153 # the fact that it places the new entry first in BootOrder. 154 bootorder=$(efivar --name 8be4df61-93ca-11d2-aa0d-00e098032b8c-BootOrder --print --no-name --hex | head -1) 155 bootentry=$(echo "${bootorder}" | cut -w -f 3)$(echo "${bootorder}" | cut -w -f 2) 156 echo "Marking UEFI boot entry ${bootentry} active" 157 efibootmgr --activate "${bootentry}" > /dev/null 158 else 159 echo "Existing UEFI FreeBSD boot entry found: not creating a new one" 160 fi 161 162 umount "${mntpt}" 163 rmdir "${mntpt}" 164 echo "Finished updating ESP" |
43} 44 | 165} 166 |
167make_esp() { 168 local file loaderfile 169 170 file=$1 171 loaderfile=$2 172 173 if [ -f "$file" ]; then 174 make_esp_file ${file} ${fat32min} ${loaderfile} 175 else 176 make_esp_device ${file} ${loaderfile} 177 fi 178} 179 |
|
45make_esp_mbr() { 46 dev=$1 47 dst=$2 48 49 s=$(find-part $dev "!239") 50 if [ -z "$s" ] ; then 51 s=$(find-part $dev "efi") 52 if [ -z "$s" ] ; then 53 die "No ESP slice found" 54 fi 55 fi | 180make_esp_mbr() { 181 dev=$1 182 dst=$2 183 184 s=$(find-part $dev "!239") 185 if [ -z "$s" ] ; then 186 s=$(find-part $dev "efi") 187 if [ -z "$s" ] ; then 188 die "No ESP slice found" 189 fi 190 fi |
56 make_esp /dev/${dev}s${s} ${dst} | 191 make_esp /dev/${dev}s${s} ${dst}/boot/loader.efi |
57} 58 59make_esp_gpt() { 60 dev=$1 61 dst=$2 62 63 idx=$(find-part $dev "efi") 64 if [ -z "$idx" ] ; then 65 die "No ESP partition found" 66 fi | 192} 193 194make_esp_gpt() { 195 dev=$1 196 dst=$2 197 198 idx=$(find-part $dev "efi") 199 if [ -z "$idx" ] ; then 200 die "No ESP partition found" 201 fi |
67 make_esp /dev/${dev}p${idx} ${dst} | 202 make_esp /dev/${dev}p${idx} ${dst}/boot/loader.efi |
68} 69 70boot_nogeli_gpt_ufs_legacy() { 71 dev=$1 72 dst=$2 73 74 idx=$(find-part $dev "freebsd-boot") 75 if [ -z "$idx" ] ; then --- 137 unchanged lines hidden (view full) --- 213 dev=$1 214 dst=$2 215 216 # For non-native builds, ensure that geom_part(4) supports VTOC8. 217 kldload geom_part_vtoc8.ko 218 doit gpart bootcode -p ${vtoc8} ${dev} 219} 220 | 203} 204 205boot_nogeli_gpt_ufs_legacy() { 206 dev=$1 207 dst=$2 208 209 idx=$(find-part $dev "freebsd-boot") 210 if [ -z "$idx" ] ; then --- 137 unchanged lines hidden (view full) --- 348 dev=$1 349 dst=$2 350 351 # For non-native builds, ensure that geom_part(4) supports VTOC8. 352 kldload geom_part_vtoc8.ko 353 doit gpart bootcode -p ${vtoc8} ${dev} 354} 355 |
221DESTDIR=/ | 356usage() { 357 printf 'Usage: %s -b bios [-d destdir] -f fs [-g geli] [-h] [-o optargs] -s scheme <bootdev>\n' "$0" 358 printf 'Options:\n' 359 printf ' bootdev device to install the boot code on\n' 360 printf ' -b bios bios type: legacy, uefi or both\n' 361 printf ' -d destdir destination filesystem root\n' 362 printf ' -f fs filesystem type: ufs or zfs\n' 363 printf ' -g geli yes or no\n' 364 printf ' -h this help/usage text\n' 365 printf ' -o optargs optional arguments\n' 366 printf ' -s scheme mbr or gpt\n' 367 exit 0 368} |
222 | 369 |
370srcroot=/ 371 |
|
223# Note: we really don't support geli boot in this script yet. 224geli=nogeli 225 | 372# Note: we really don't support geli boot in this script yet. 373geli=nogeli 374 |
226while getopts "b:d:f:g:o:s:" opt; do | 375while getopts "b:d:f:g:ho:s:" opt; do |
227 case "$opt" in 228 b) 229 bios=${OPTARG} 230 ;; 231 d) | 376 case "$opt" in 377 b) 378 bios=${OPTARG} 379 ;; 380 d) |
232 DESTDIR=${OPTARG} | 381 srcroot=${OPTARG} |
233 ;; 234 f) 235 fs=${OPTARG} 236 ;; 237 g) 238 case ${OPTARG} in 239 [Yy][Ee][Ss]|geli) geli=geli ;; 240 *) geli=nogeli ;; 241 esac 242 ;; 243 o) 244 opts=${OPTARG} 245 ;; 246 s) 247 scheme=${OPTARG} 248 ;; | 382 ;; 383 f) 384 fs=${OPTARG} 385 ;; 386 g) 387 case ${OPTARG} in 388 [Yy][Ee][Ss]|geli) geli=geli ;; 389 *) geli=nogeli ;; 390 esac 391 ;; 392 o) 393 opts=${OPTARG} 394 ;; 395 s) 396 scheme=${OPTARG} 397 ;; |
398 399 ?|h) 400 usage 401 ;; |
|
249 esac 250done 251 | 402 esac 403done 404 |
252shift $((OPTIND-1)) 253dev=$1 | 405if [ -n "${scheme}" ] && [ -n "${fs}" ] && [ -n "${bios}" ]; then 406 shift $((OPTIND-1)) 407 dev=$1 408fi |
254 255# For gpt, we need to install pmbr as the primary boot loader 256# it knows about | 409 410# For gpt, we need to install pmbr as the primary boot loader 411# it knows about |
257gpt0=${DESTDIR}/boot/pmbr 258gpt2=${DESTDIR}/boot/gptboot 259gptzfs2=${DESTDIR}/boot/gptzfsboot | 412gpt0=${srcroot}/boot/pmbr 413gpt2=${srcroot}/boot/gptboot 414gptzfs2=${srcroot}/boot/gptzfsboot |
260 261# For MBR, we have lots of choices, but select mbr, boot0 has issues with UEFI | 415 416# For MBR, we have lots of choices, but select mbr, boot0 has issues with UEFI |
262mbr0=${DESTDIR}/boot/mbr 263mbr2=${DESTDIR}/boot/boot | 417mbr0=${srcroot}/boot/mbr 418mbr2=${srcroot}/boot/boot |
264 265# VTOC8 | 419 420# VTOC8 |
266vtoc8=${DESTDIR}/boot/boot1 | 421vtoc8=${srcroot}/boot/boot1 |
267 268# sanity check here 269 | 422 423# sanity check here 424 |
270eval boot_${geli}_${scheme}_${fs}_${bios} $dev $DESTDIR $opts || echo "Unsupported boot env: ${geli}-${scheme}-${fs}-${bios}" | 425# Check if we've been given arguments. If not, this script is probably being 426# sourced, so we shouldn't run anything. 427if [ -n "${dev}" ]; then 428 eval boot_${geli}_${scheme}_${fs}_${bios} $dev $srcroot $opts || echo "Unsupported boot env: ${geli}-${scheme}-${fs}-${bios}" 429fi |