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