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