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