xref: /freebsd/tools/boot/install-boot.sh (revision 190cef3d)
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