@EFI_PLATFORM_PATH@ macro for us in $ARGS
[packages/efi-boot-update.git] / efi-boot-update
CommitLineData
7a63766a
JK
1#!/bin/sh
2
3_SCRIPT_NAME=efi-boot-update
7d8cd73a 4_SCRIPT_VERSION=0.1
7a63766a
JK
5
6. /etc/rc.d/init.d/functions
7
8usage () {
9
10 echo "Usage: $0 OPTIONS"
11 echo "Update EFI boot loaders"
12 echo
13 echo " --version Show version number"
14 echo " --help, -h This help message"
15 echo " --mount, -m Try to mount /boot/efi first"
16 echo " --verbose, -v Verbose output"
17 echo " --force Force file updates"
fe76538b 18 echo " --auto Automatic run from packages %post"
7a63766a
JK
19}
20
21msg () {
7a5c96c9 22 echo -E "efi-boot-update: $*" >&2
7a63766a
JK
23}
24
25verbose () {
26 if is_yes "$VERBOSE" ; then
7a5c96c9 27 echo -E "efi-boot-update: $*" >&2
7a63766a
JK
28 fi
29}
30
31verbose_cmd () {
32 if is_yes "$VERBOSE" ; then
7a5c96c9 33 echo -E "+$*" >&2
7a63766a
JK
34 fi
35 "$@"
36}
37
38
39list_remove () {
40
41 for item in $1 ; do
42 if [ "$item" = "$2" ] ; then
43 continue
44 fi
7a5c96c9 45 echo -nE "$item "
7a63766a
JK
46 done
47}
48
49update_file () {
50 local cmd
51 local src
52 local dest
53 while [ -n "$1" ] ; do
54 case $1 in
55 --missingok)
56 shift
57 [ -e "$1" ] || return 0
58 ;;
59 --*)
60 msg "update_file: ignoring unknown option: $1"
61 shift
62 ;;
63 *)
64 break
65 ;;
66 esac
67 done
68 src="$1"; shift
560a4357 69 dst="$1"; shift
7a63766a
JK
70 if [ -n "$*" ] ; then
71 msg "update_file: unexpected arguments: $*"
72 return 1
73 fi
560a4357
JK
74 if [ -z "$src" ] ; then
75 msg "update_file: no source file"
76 return 1
77 fi
78 if [ -z "$dst" ] ; then
79 dst=`basename "$src"`
80 fi
7a63766a
JK
81 if [ "${dst#/}" = "${dst}" ] ; then
82 # relative path
83 dst="$DESTDIR/$dst"
84 fi
85 if is_yes "$FORCE_UPDATES" ; then
86 is_yes "$VERBOSE" && echo +cp --force --preserve=timestamps "$src" "$dst"
87 cp --force --preserve=timestamps "$src" "$dst"
88 else
89 is_yes "$VERBOSE" && echo +cp --update --preserve=timestamps "$src" "$dst"
90 cp --update --preserve=timestamps "$src" "$dst"
91 fi
92}
93
94get_efibootmgr_opts() {
95 local efi_disk
96 local efi_partnum
97 efi_disk=$(mount | awk '$3=="/boot/efi" {print $1}' 2>/dev/null)
98 EFIBOOTMGR_OPTS="--gpt"
99 if [ -n "$efi_disk" ] ; then
100 efi_partnum="$(echo $efi_disk|sed -e's;^.*[^0-9]\([0-9]\+\)$;\1;')"
101 efi_disk="$(echo $efi_disk|sed -e's;^\(.*\)[0-9]\+$;\1;')"
102 if [ -b "$efi_disk" -a -n "$efi_partnum" ] ; then
103 EFIBOOTMGR_OPTS="$EFIBOOTMGR_OPTS --disk $efi_disk"
104 EFIBOOTMGR_OPTS="$EFIBOOTMGR_OPTS --part $efi_partnum"
105 fi
106 fi
107 echo -n $EFIBOOTMGR_OPTS
108}
109
110find_bootmgr_entry () {
111
112 $EFIBOOTMGR | awk -v find="$1" '
113/^Boot[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\*?/ {
114 sub(/^Boot/,"");
115 sub(/\*/,"");
116 num=$1;
117 $1="";
118 gsub(/^[ \t]+|[ \t]+$/,"");
119 if ($0 == find) print num
120 }'
121}
122
123remove_bootmgr_entry () {
124 local bootnum
125 bootnum=$(find_bootmgr_entry "$1")
126 [ -n "$bootnum" ] || return 0
c1469194 127 verbose_cmd $EFIBOOTMGR $EFIBOOTMGR_OPTS --quiet --delete-bootnum -b "$bootnum"
7a63766a
JK
128 echo -n "$bootnum"
129}
130
131add_bootmgr_entry () {
6451bc22
JK
132 local label="$1"
133 local binary="$2"
134 local args="$3"
7a63766a
JK
135 local bootnum
136 bootnum=$(find_bootmgr_entry "$label")
137
138 if [ "${binary#/}" = "${binary}" ] ; then
139 # relative path
140 binary="$DESTDIR/$binary"
141 fi
142 binary="${binary#/boot/efi}"
7a5c96c9 143 binary="$(echo -nE "$binary"|sed -e's;/;\\;g')"
7a63766a
JK
144
145 if [ -n "$bootnum" ] ; then
cd8795e2
JK
146 # efibootmgr doesn't seem to update the arguments
147 # we need to remove old entry and create a new one
148 verbose_cmd $EFIBOOTMGR $EFIBOOTMGR_OPTS --quiet --delete-bootnum -b "$bootnum"
7a63766a 149 fi
cd8795e2
JK
150 verbose_cmd $EFIBOOTMGR $EFIBOOTMGR_OPTS --create \
151 --quiet --label "$label" --loader "$binary" -u "$args"
152 bootnum="$(find_bootmgr_entry "$label")"
7a63766a
JK
153 echo -n "$bootnum"
154}
155
fff9d424
JK
156safe_string () {
157 echo -n "$*" | tr -c '[a-zA-Z0-9_]' '_'
158}
159
fe76538b 160ALLOW_AUTO="no"
7a63766a
JK
161FORCE_UPDATES="no"
162MOUNT_EFI_PARTITION="no"
163LABEL_PREFIX=""
7a63766a
JK
164VERBOSE="no"
165
166[ -e /etc/efi-boot/update.conf ] && . /etc/efi-boot/update.conf
167
fe76538b
JK
168AUTO_RUN=no
169
7a63766a
JK
170while [ -n "$*" ] ; do
171 local arg
172 arg="$1"
173 shift
174 case $arg in
175 --help|-h)
176 usage
177 exit 0
178 ;;
179 --version)
180 echo "$_SCRIPT_NAME $_SCRIPT_VERSION"
181 exit 0
182 ;;
183 --mount|-m)
184 MOUNT_EFI_PARTITION=yes
185 ;;
186 --verbose|-v)
187 VERBOSE=yes
188 ;;
189 --force)
190 FORCE_UPDATES="yes"
191 ;;
fe76538b
JK
192 --auto)
193 is_yes "$ALLOW_AUTO" || exit 0
194 AUTO_RUN=yes
195 ;;
7a63766a
JK
196 *)
197 usage >&2
198 exit 2
199 ;;
200 esac
201done
202
203if ! mountpoint -q /boot/efi ; then
204 mkdir -p /boot/efi
205 if is_yes "$MOUNT_EFI_PARTITION" ; then
206 # first try via fstab
207 if ! mount /boot/efi 2>/dev/null ; then
208 local efi_device
209 efi_device="$(/sbin/blkid -o device -l -t PARTUUID="54f69bcc-954d-4f97-8fef-80b359f9e4aa")"
210 if [ -z "$efi_device" ] ; then
211 msg "EFI system partition not found."
212 exit 1
213 fi
214 mount -t vfat "$efi_device" /boot/efi
215 fi
216 fi
217 if ! mountpoint -q /boot/efi ; then
218 msg "EFI system partition not mounted."
219 exit 1
220 fi
221fi
222
223if [ -x /usr/sbin/efibootmgr ] ; then
224 modprobe -q efivars
225 EFIBOOTMGR=/usr/sbin/efibootmgr
226 if ! $EFIBOOTMGR >/dev/null 2>&1 ; then
227 msg "efibootmgr does not work (efivars interface not available?)"
228 msg "won't update boot manager configuration"
229 EFIBOOTMGR=/bin/true
230 else
231 EFIBOOTMGR_OPTS="$(get_efibootmgr_opts)"
232 fi
233else
234 msg "efibootmgr missing, won't update the boot manager configuration"
235 EFIBOOTMGR=/bin/true
236fi
237
7a63766a
JK
238for bootloader_conf in /etc/efi-boot/update.d/*.conf ; do
239 if [ ! -e "$bootloader_conf" ] ; then
240 continue
241 fi
242 ENABLED=yes
243 CONFIG_NAME="$(basename "$bootloader_conf" .conf)"
244 LABEL="$CONFIG_NAME"
245 ARCH="$(uname -m)"
246 BINARY=""
247 ARGS=""
27eab27d
JK
248 install_files() {
249 /bin/true
250 }
7a63766a
JK
251
252 . "$bootloader_conf" || continue
253
254 LABEL="$LABEL_PREFIX$LABEL"
255
256 if ! is_yes "$ENABLED" ; then
07ca222f 257 remove_bootmgr_entry "$LABEL" >/dev/null
7a63766a
JK
258 continue
259 fi
260
5b02c492
JK
261 local efi_arch
262 if [[ "$ARCH" = i?86 || "$ARCH" = pentium[45] || "$ARCH" = "athlon" ]] ; then
263 # %ix86
f8b86fe2 264 efi_arch=ia32
5b02c492
JK
265 elif [[ "$ARCH" = "x86_64" || "$ARCH" = "amd64" || "$ARCH" = "ia32e" ]] ; then
266 # %x8664
267 efi_arch=x64
268 else
269 efi_arch="$ARCH"
270 fi
3c17787a
JK
271
272 PLATFORM_PATH="EFI/$(echo -nE "$PLATFORM_DIR"|sed -e's/@ARCH@/'"$efi_arch"'/')"
273 local escaped_EFI_PLATFORM_PATH="$(echo -nE "$PLATFORM_PATH"|sed -e's;/;\\\\;g')"
274 DESTDIR="/boot/efi/$PLATFORM_PATH"
275 ARGS="$(echo -nE "$ARGS"|sed -e's/@ARCH@/'"$efi_arch"'/;s/@EFI_PLATFORM_PATH@/'"$escaped_EFI_PLATFORM_PATH"'/g')"
276
277 verbose "ARGS: '$ARGS'"
278
7a63766a
JK
279 mkdir -p "$DESTDIR"
280
281 verbose "Updating $LABEL..."
282 install_files
283 if [ -n "$BINARY" ] ; then
284 bootnum="$(add_bootmgr_entry "$LABEL" "$BINARY" "$ARGS")"
fff9d424 285 eval "_$(safe_string ${CONFIG_NAME})_bootnum=\"$bootnum\""
7a63766a
JK
286 fi
287done
288
da8a0db5 289if [ -n "$ORDER" -a "$EFIBOOTMGR" != "/bin/true" ] ; then
7a63766a 290 # set up the configured boot order, not removing any existing entries
da8a0db5 291 tail="$($EFIBOOTMGR | awk '/^BootOrder:/ {gsub(/,/," ",$2); print $2}')"
7a63766a
JK
292 head=""
293 for config_name in $ORDER ; do
fff9d424 294 eval "bootnum=\$_$(safe_string ${config_name})_bootnum"
7a63766a 295 if [ -z "$bootnum" ] ; then
fff9d424 296 verbose "Cannot find '$config_name' config - won't add to boot order."
7a63766a
JK
297 continue
298 fi
299 tail="$(list_remove "$tail" "$bootnum")"
300 head="$head $bootnum"
301 done
302 bootorder="$(echo -n $head $tail | sed -e's/ /,/g')"
303 if [ -n "$bootorder" ] ; then
304 verbose_cmd $EFIBOOTMGR $EFIBOOTMGR_OPTS --quiet --bootorder "$bootorder"
305 fi
306fi
307
fe76538b
JK
308if ! is_yes "$ALLOW_AUTO" && ! is_yes "$AUTO_RUN"; then
309 msg "ALLOW_AUTO is not enabled in /etc/efi-boot/update.conf,"
310 msg "files will not be automatically updated on upgrades."
311fi
312
7a63766a 313# vi: ft=sh sw=4 sts=4 et
This page took 0.3627 seconds and 4 git commands to generate.