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 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 30make_esp() { 31 local dev dst mntpt 32 33 dev=$1 34 dst=$2 35 36 newfs_msdos -a 32 ${dev} 37 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} 43} 44 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 56 make_esp /dev/${dev}s${s} ${dst} 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 67 make_esp /dev/${dev}p${idx} ${dst} 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 76 die "No freebsd-boot partition found" 77 fi 78 doit gpart bootcode -b ${gpt0} -p ${gpt2} -i $idx $dev 79} 80 81boot_nogeli_gpt_ufs_uefi() { 82 make_esp_gpt $1 $2 83} 84 85boot_nogeli_gpt_ufs_both() { 86 boot_nogeli_gpt_ufs_legacy $1 $2 $3 87 boot_nogeli_gpt_ufs_uefi $1 $2 $3 88} 89 90boot_nogeli_gpt_zfs_legacy() { 91 dev=$1 92 dst=$2 93 94 idx=$(find-part $dev "freebsd-boot") 95 if [ -z "$idx" ] ; then 96 die "No freebsd-boot partition found" 97 fi 98 doit gpart bootcode -b ${gpt0} -p ${gptzfs2} -i $idx $dev 99} 100 101boot_nogeli_gpt_zfs_uefi() { 102 make_esp_gpt $1 $2 103} 104 105boot_nogeli_gpt_zfs_both() { 106 boot_nogeli_gpt_zfs_legacy $1 $2 $3 107 boot_nogeli_gpt_zfs_uefi $1 $2 $3 108} 109 110boot_nogeli_mbr_ufs_legacy() { 111 dev=$1 112 dst=$2 113 114 doit gpart bootcode -b ${mbr0} ${dev} 115 s=$(find-part $dev "freebsd") 116 if [ -z "$s" ] ; then 117 die "No freebsd slice found" 118 fi 119 doit gpart bootcode -p ${mbr2} ${dev}s${s} 120} 121 122boot_nogeli_mbr_ufs_uefi() { 123 make_esp_mbr $1 $2 124} 125 126boot_nogeli_mbr_ufs_both() { 127 boot_nogeli_mbr_ufs_legacy $1 $2 $3 128 boot_nogeli_mbr_ufs_uefi $1 $2 $3 129} 130 131boot_nogeli_mbr_zfs_legacy() { 132 dev=$1 133 dst=$2 134 135 # search to find the BSD slice 136 s=$(find-part $dev "freebsd") 137 if [ -z "$s" ] ; then 138 die "No BSD slice found" 139 fi 140 idx=$(find-part ${dev}s${s} "freebsd-zfs") 141 if [ -z "$idx" ] ; then 142 die "No freebsd-zfs slice found" 143 fi 144 # search to find the freebsd-zfs partition within the slice 145 # Or just assume it is 'a' because it has to be since it fails otherwise 146 doit gpart bootcode -b ${dst}/boot/mbr ${dev} 147 dd if=${dst}/boot/zfsboot of=/tmp/zfsboot1 count=1 148 doit gpart bootcode -b /tmp/zfsboot1 ${dev}s${s} # Put boot1 into the start of part 149 sysctl kern.geom.debugflags=0x10 # Put boot2 into ZFS boot slot 150 doit dd if=${dst}/boot/zfsboot of=/dev/${dev}s${s}a skip=1 seek=1024 151 sysctl kern.geom.debugflags=0x0 152} 153 154boot_nogeli_mbr_zfs_uefi() { 155 make_esp_mbr $1 $2 156} 157 158boot_nogeli_mbr_zfs_both() { 159 boot_nogeli_mbr_zfs_legacy $1 $2 $3 160 boot_nogeli_mbr_zfs_uefi $1 $2 $3 161} 162 163boot_geli_gpt_ufs_legacy() { 164 boot_nogeli_gpt_ufs_legacy $1 $2 $3 165} 166 167boot_geli_gpt_ufs_uefi() { 168 boot_nogeli_gpt_ufs_uefi $1 $2 $3 169} 170 171boot_geli_gpt_ufs_both() { 172 boot_nogeli_gpt_ufs_both $1 $2 $3 173} 174 175boot_geli_gpt_zfs_legacy() { 176 boot_nogeli_gpt_zfs_legacy $1 $2 $3 177} 178 179boot_geli_gpt_zfs_uefi() { 180 boot_nogeli_gpt_zfs_uefi $1 $2 $3 181} 182 183boot_geli_gpt_zfs_both() { 184 boot_nogeli_gpt_zfs_both $1 $2 $3 185} 186 187# GELI+MBR is not a valid configuration 188boot_geli_mbr_ufs_legacy() { 189 exit 1 190} 191 192boot_geli_mbr_ufs_uefi() { 193 exit 1 194} 195 196boot_geli_mbr_ufs_both() { 197 exit 1 198} 199 200boot_geli_mbr_zfs_legacy() { 201 exit 1 202} 203 204boot_geli_mbr_zfs_uefi() { 205 exit 1 206} 207 208boot_geli_mbr_zfs_both() { 209 exit 1 210} 211 212boot_nogeli_vtoc8_ufs_ofw() { 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 221DESTDIR=/ 222 223# Note: we really don't support geli boot in this script yet. 224geli=nogeli 225 226while getopts "b:d:f:g:o:s:" opt; do 227 case "$opt" in 228 b) 229 bios=${OPTARG} 230 ;; 231 d) 232 DESTDIR=${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 ;; 249 esac 250done 251 252shift $((OPTIND-1)) 253dev=$1 254 255# For gpt, we need to install pmbr as the primary boot loader 256# it knows about 257gpt0=${DESTDIR}/boot/pmbr 258gpt2=${DESTDIR}/boot/gptboot 259gptzfs2=${DESTDIR}/boot/gptzfsboot 260 261# For MBR, we have lots of choices, but select mbr, boot0 has issues with UEFI 262mbr0=${DESTDIR}/boot/mbr 263mbr2=${DESTDIR}/boot/boot 264 265# VTOC8 266vtoc8=${DESTDIR}/boot/boot1 267 268# sanity check here 269 270eval boot_${geli}_${scheme}_${fs}_${bios} $dev $DESTDIR $opts || echo "Unsupported boot env: ${geli}-${scheme}-${fs}-${bios}" 271