File shim-install of Package shim
399
1
#! /bin/bash -e
2
3
arch=`uname -m`
4
rootdir=
5
bootdir=
6
efidir=
7
install_device=
8
efibootdir=
9
ca_string=
10
no_nvram=no
11
removable=no
12
clean=no
13
sysconfdir="/etc"
14
libdir="/usr/lib64" # Beware, this is arch dependent!
15
datadir="/usr/share"
16
source_dir="${datadir}/efi/${arch}"
17
efibootmgr="/usr/sbin/efibootmgr"
18
grub_probe="/usr/sbin/grub2-probe"
19
grub_mkrelpath="/usr/bin/grub2-mkrelpath"
20
grub_install="/usr/sbin/grub2-install"
21
grub_install_target=
22
self="`basename $0`"
23
grub_cfg="/boot/grub2/grub.cfg"
24
update_boot=no
25
def_grub_efi="${source_dir}/grub.efi"
26
def_boot_efi=
27
28
[ ! -r /usr/etc/default/shim ] || . /usr/etc/default/shim
29
[ ! -r /etc/default/shim ] || . /etc/default/shim
30
31
if [ -z "$def_shim_efi" ] ; then
32
def_shim_efi="shim.efi"
33
fi
34
35
source_shim_efi="${source_dir}/${def_shim_efi}"
36
37
if [ x${arch} = xx86_64 ] ; then
38
grub_install_target="x86_64-efi"
39
def_boot_efi="bootx64.efi"
40
elif [ x${arch} = xaarch64 ] ; then
41
grub_install_target="arm64-efi"
42
def_boot_efi="bootaa64.efi"
43
else
44
echo "Unsupported architecture: ${arch}"
45
exit 1
46
fi
47
48
if [ ! -d "${source_dir}" -o ! -e "${def_grub_efi}" ] ; then
49
# for outdated packages fall back to previous behavior
50
source_dir="$libdir/efi"
51
def_grub_efi="${source_dir}/grub.efi"
52
fi
53
54
# Get GRUB_DISTRIBUTOR.
55
if test -f "${sysconfdir}/default/grub" ; then
56
. "${sysconfdir}/default/grub"
57
fi
58
59
if [ x"${GRUB_DISTRIBUTOR}" = x ] && [ -f "${sysconfdir}/os-release" ] ; then
60
. "${sysconfdir}/os-release"
61
GRUB_DISTRIBUTOR="${NAME} ${VERSION}"
62
fi
63
64
bootloader_id="$(echo "$GRUB_DISTRIBUTOR" | tr 'A-Z' 'a-z' | cut -d' ' -f1)"
65
if test -z "$bootloader_id"; then
66
bootloader_id=grub
67
fi
68
69
efi_distributor="$bootloader_id"
70
bootloader_id="${bootloader_id}-secureboot"
71
72
case "$bootloader_id" in
73
"sle"*)
74
ca_string='SUSE Linux Enterprise Secure Boot CA1';;
75
"opensuse"*)
76
ca_string='openSUSE Secure Boot CA1';;
77
*) ca_string="";;
78
esac
79
80
usage () {
81
echo "Usage: $self [OPTION] [INSTALL_DEVICE]"
82
echo
83
echo "Install Secure Boot Loaders on your drive."
84
echo
85
echo "--directory=DIR use images from DIR."
86
echo "--grub-probe=FILE use FILE as grub-probe."
87
echo "--removable the installation device is removable."
88
echo "--no-nvram don't update the NVRAM variable."
89
echo "--bootloader-id=ID the ID of bootloader."
90
echo "--efi-directory=DIR use DIR as the EFI System Partition root."
91
echo "--config-file=FILE use FILE as config file, default is $grub_cfg."
92
echo "--clean remove all installed files and configs."
93
echo "--suse-enable-tpm install grub.efi with TPM support."
94
echo
95
echo "INSTALL_DEVICE must be system device filename."
96
}
97
98
argument () {
99
opt="$1"
100
shift
101
102
if test $# -eq 0; then
103
echo "$0: option requires an argument -- \`$opt'" 1>&2
104
exit 1
105
fi
106
echo "$1"
107
}
108
109
# Check the arguments.
110
while test $# -gt 0
111
do
112
option=$1
113
shift
114
115
case "$option" in
116
-h | --help)
117
usage
118
exit 0 ;;
119
120
--root-directory)
121
rootdir="`argument $option "$@"`"; shift;;
122
--root-directory=*)
123
rootdir="`echo "$option" | sed 's/--root-directory=//'`" ;;
124
125
--efi-directory)
126
efidir="`argument $option "$@"`"; shift;;
127
--efi-directory=*)
128
efidir="`echo "$option" | sed 's/--efi-directory=//'`" ;;
129
130
--directory | -d)
131
source_dir="`argument $option "$@"`"; shift;;
132
--directory=*)
133
source_dir="`echo "$option" | sed 's/--directory=//'`" ;;
134
135
--bootloader-id)
136
bootloader_id="`argument $option "$@"`"; shift;;
137
--bootloader-id=*)
138
bootloader_id="`echo "$option" | sed 's/--bootloader-id=//'`" ;;
139
140
--grub-probe)
141
grub_probe="`argument "$option" "$@"`"; shift;;
142
--grub-probe=*)
143
grub_probe="`echo "$option" | sed 's/--grub-probe=//'`" ;;
144
145
--config-file)
146
grub_cfg="`argument "$option" "$@"`"; shift;;
147
--config-file=*)
148
grub_cfg="`echo "$option" | sed 's/--config-file=//'`" ;;
149
150
--removable)
151
no_nvram=yes
152
removable=yes ;;
153
154
--no-nvram)
155
no_nvram=yes ;;
156
157
--suse-enable-tpm)
158
# bsc#1174320 shim-install uses wrong paths for EFI files
159
# There are 3 possible locations of grub-tpm.efi and we will check them
160
# one by one.
161
if [ -e "${source_dir}/grub-tpm.efi" ]; then
162
source_grub_efi="${source_dir}/grub-tpm.efi"
163
elif [ -e "${datadir}/grub2/${grub_install_target}/grub-tpm.efi" ] ; then
164
source_grub_efi="${datadir}/grub2/${grub_install_target}/grub-tpm.efi"
165
else
166
source_grub_efi="/usr/lib/grub2/${grub_install_target}/grub-tpm.efi"
167
fi
168
;;
169
170
--clean)
171
clean=yes ;;
172
173
-*)
174
echo "Unrecognized option \`$option'" 1>&2
175
usage
176
exit 1
177
;;
178
*)
179
if test "x$install_device" != x; then
180
echo "More than one install device?" 1>&2
181
usage
182
exit 1
183
fi
184
install_device="${option}" ;;
185
esac
186
done
187
188
if test -n "$efidir"; then
189
efi_fs=`"$grub_probe" --target=fs "${efidir}"`
190
if test "x$efi_fs" = xfat; then :; else
191
echo "$efidir doesn't look like an EFI partition." 1>&2
192
efidir=
193
fi
194
fi
195
196
197
if [ -z "$bootdir" ]; then
198
bootdir="/boot"
199
if [ -n "$rootdir" ] ; then
200
# Initialize bootdir if rootdir was initialized.
201
bootdir="${rootdir}/boot"
202
fi
203
fi
204
205
# Find the EFI System Partition.
206
if test -n "$efidir"; then
207
install_device="`"$grub_probe" --target=device --device-map= "${efidir}"`"
208
else
209
if test -d "${bootdir}/efi"; then
210
install_device="`"$grub_probe" --target=device --device-map= "${bootdir}/efi"`"
211
# Is it a mount point?
212
if test "x$install_device" != "x`"$grub_probe" --target=device --device-map= "${bootdir}"`"; then
213
efidir="${bootdir}/efi"
214
fi
215
elif test -d "${bootdir}/EFI"; then
216
install_device="`"$grub_probe" --target=device --device-map= "${bootdir}/EFI"`"
217
# Is it a mount point?
218
if test "x$install_device" != "x`"$grub_probe" --target=device --device-map= "${bootdir}"`"; then
219
efidir="${bootdir}/EFI"
220
fi
221
elif test -n "$rootdir" && test "x$rootdir" != "x/"; then
222
# The EFI System Partition may have been given directly using
223
# --root-directory.
224
install_device="`"$grub_probe" --target=device --device-map= "${rootdir}"`"
225
# Is it a mount point?
226
if test "x$install_device" != "x`"$grub_probe" --target=device --device-map= "${rootdir}/.."`"; then
227
efidir="${rootdir}"
228
fi
229
fi
230
231
if test -n "$efidir"; then
232
efi_fs=`"$grub_probe" --target=fs "${efidir}"`
233
if test "x$efi_fs" = xfat; then :; else
234
echo "$efidir doesn't look like an EFI partition." 1>&2
235
efidir=
236
fi
237
fi
238
fi
239
240
if test -n "$efidir"; then
241
efi_file=shim.efi
242
efibootdir="$efidir/EFI/boot"
243
mkdir -p "$efibootdir" || exit 1
244
if test "$removable" = "yes" ; then
245
efidir="$efibootdir"
246
else
247
efidir="$efidir/EFI/$efi_distributor"
248
mkdir -p "$efidir" || exit 1
249
fi
250
else
251
echo "No valid EFI partition" 1>&2
252
exit 1;
253
fi
254
255
if test "$removable" = "no" -a -f "$efibootdir/$def_boot_efi"; then
256
if test -n "$ca_string" && (grep -q "$ca_string" "$efibootdir/$def_boot_efi"); then
257
update_boot=yes
258
fi
259
else
260
update_boot=yes
261
fi
262
263
if test "$clean" = "yes"; then
264
rm -f "${efidir}/shim.efi"
265
rm -f "${efidir}/MokManager.efi"
266
rm -f "${efidir}/grub.efi"
267
rm -f "${efidir}/grub.cfg"
268
rm -f "${efidir}/boot.csv"
269
if test "$update_boot" = "yes"; then
270
rm -f "${efibootdir}/${def_boot_efi}"
271
rm -f "${efibootdir}/fallback.efi"
272
# bsc#1175626, bsc#1175656 also clean up MokManager
273
rm -f "${efibootdir}/MokManager.efi"
274
fi
275
if test "$no_nvram" = no && test -n "$bootloader_id"; then
276
# Delete old entries from the same distributor.
277
for bootnum in `$efibootmgr | grep '^Boot[0-9]' | \
278
fgrep -i " $bootloader_id" | cut -b5-8`; do
279
$efibootmgr -b "$bootnum" -B
280
done
281
fi
282
exit 0
283
fi
284
285
cp "${source_dir}/MokManager.efi" "${efidir}"
286
287
if test -n "$source_grub_efi" && ! test -f "$source_grub_efi"; then
288
echo "File $source_grub_efi doesn't exist, fallback to default one" 1>&2
289
source_grub_efi=""
290
fi
291
292
if test -z "$source_grub_efi"; then
293
source_grub_efi="$def_grub_efi"
294
fi
295
296
echo "copying $source_grub_efi to ${efidir}/grub.efi"
297
cp "$source_grub_efi" "${efidir}/grub.efi"
298
299
if test "$efidir" != "$efibootdir" ; then
300
cp "${source_shim_efi}" "${efidir}/shim.efi"
301
if test -n "$bootloader_id"; then
302
echo "shim.efi,${bootloader_id}" | iconv -f ascii -t ucs2 > "${efidir}/boot.csv"
303
fi
304
fi
305
306
if test "$update_boot" = "yes"; then
307
cp "$source_shim_efi" "${efibootdir}/${def_boot_efi}"
308
if test "$removable" = "no"; then
309
cp "${source_dir}/fallback.efi" "${efibootdir}"
310
# bsc#1175626, bsc#1175656 Since shim 15, loading MokManager becomes
311
# mandatory if a MOK request exists. Copy MokManager to \EFI\boot so
312
# that boot*.efi can load MokManager to process the request instead
313
# of shutting down the system immediately.
314
cp "${source_dir}/MokManager.efi" "${efibootdir}"
315
fi
316
fi
317
318
319
make_grubcfg () {
320
321
grub_cfg_dirname=`dirname $grub_cfg`
322
grub_cfg_basename=`basename $grub_cfg`
323
cfg_fs_uuid=`"$grub_probe" --target=fs_uuid "$grub_cfg_dirname"`
324
# bsc#1153953 - Leap 42.3 boot error snapshot missing
325
# We have to check btrfs is used as root file system to enable relative path
326
# lookup for file to be on par with other utility which also accounts for it.
327
GRUB_FS="$(stat -f --printf=%T / || echo unknown)"
328
329
if test "x$SUSE_BTRFS_SNAPSHOT_BOOTING" = "xtrue" &&
330
[ "x${GRUB_FS}" = "xbtrfs" ] ; then
331
cat <<EOF
332
set btrfs_relative_path="yes"
333
EOF
334
if ${grub_mkrelpath} --usage | grep -q -e '--relative'; then
335
grub_mkrelpath="${grub_mkrelpath} -r"
336
fi
337
fi
338
339
if [ x$GRUB_ENABLE_CRYPTODISK = xy ]; then
340
for uuid in `"${grub_probe}" --target=cryptodisk_uuid --device-map= "${grub_cfg_dirname}"`; do
341
echo "cryptomount -u $uuid"
342
done
343
fi
344
345
cat <<EOF
346
search --fs-uuid --set=root ${cfg_fs_uuid}
347
set prefix=(\${root})`${grub_mkrelpath} ${grub_cfg_dirname}`
348
source "\${prefix}/${grub_cfg_basename}"
349
EOF
350
351
}
352
353
make_grubcfg > "${efidir}/grub.cfg"
354
# bnc#889765 GRUB shows broken letters at boot
355
# invoke grub_install to initialize /boot/grub2 directory with files needed by grub.cfg
356
# bsc#1118363 shim-install didn't specify the target for grub2-install
357
# set the target explicitly for some special cases
358
${grub_install} --target=${grub_install_target} --no-nvram
359
360
if test "$no_nvram" = no && test -n "$bootloader_id"; then
361
362
modprobe -q efivars 2>/dev/null || true
363
364
# Delete old entries from the same distributor.
365
for bootnum in `$efibootmgr | grep '^Boot[0-9]' | \
366
fgrep -i " $bootloader_id" | cut -b5-8`; do
367
$efibootmgr -b "$bootnum" -B
368
done
369
370
efidir_drive="$("$grub_probe" --target=drive --device-map= "$efidir")"
371
efidir_disk="$("$grub_probe" --target=disk --device-map= "$efidir")"
372
if test -z "$efidir_drive" || test -z "$efidir_disk"; then
373
echo "Can't find GRUB drive for $efidir; unable to create EFI Boot Manager entry." >&2
374
# bsc#1119762 If the MD device is partitioned, we just need to create one
375
# boot entry since the partitions are nested partitions and the mirrored
376
# partitions share the same UUID.
377
elif [[ "$efidir_drive" == \(mduuid/* && "$efidir_drive" != \(mduuid/*,* ]]; then
378
eval $(mdadm --detail --export "$efidir_disk" |
379
perl -ne 'print if m{^MD_LEVEL=}; push( @D, $1) if (m{^MD_DEVICE_\S+_DEV=(\S+)$});
380
sub END() {print "MD_DEVS=\"", join( " ", @D), "\"\n";};')
381
if [ "$MD_LEVEL" != "raid1" ]; then
382
echo "GRUB drive for $efidir not on RAID1; unable to create EFI Boot Manager entry." >&2
383
fi
384
for mddev in $MD_DEVS; do
385
efidir_drive="$("$grub_probe" --target=drive --device-map= -d "$mddev")"
386
efidir_disk="$("$grub_probe" --target=disk --device-map= -d "$mddev")"
387
efidir_part="$(echo "$efidir_drive" | sed 's/^([^,]*,[^0-9]*//; s/[^0-9].*//')"
388
efidir_d=${mddev#/dev/}
389
$efibootmgr -c -d "$efidir_disk" -p "$efidir_part" -w \
390
-L "$bootloader_id ($efidir_d)" -l "\\EFI\\$efi_distributor\\$efi_file"
391
done
392
else
393
efidir_part="$(echo "$efidir_drive" | sed 's/^([^,]*,[^0-9]*//; s/[^0-9].*//')"
394
$efibootmgr -c -d "$efidir_disk" -p "$efidir_part" -w \
395
-L "$bootloader_id" -l "\\EFI\\$efi_distributor\\$efi_file"
396
fi
397
fi
398
399