]> git.pld-linux.org Git - packages/efi-boot-update.git/blob - efi-boot-update
'kernel' and 'kernel-old' modules added
[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 -E "efi-boot-update: $*" >&2
23 }
24
25 verbose () {
26     if is_yes "$VERBOSE" ; then 
27         echo -E "efi-boot-update: $*" >&2
28     fi
29 }
30
31 verbose_cmd () {
32     if is_yes "$VERBOSE" ; then
33         echo -E "+$*" >&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 -nE "$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="$1"; shift
70     if [ -n "$*" ] ; then
71         msg "update_file: unexpected arguments: $*"
72         return 1
73     fi
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
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
94 get_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
110 find_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         
123 remove_bootmgr_entry () {
124     local bootnum
125     bootnum=$(find_bootmgr_entry "$1")
126     [ -n "$bootnum" ] || return 0
127     verbose_cmd $EFIBOOTMGR $EFIBOOTMGR_OPTS --quiet --delete-bootnum -b "$bootnum"
128     echo -n "$bootnum"
129 }
130
131 add_bootmgr_entry () {
132     local label="$1"
133     local binary="$2"
134     local args="$3"
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}"
143     binary="$(echo -nE "$binary"|sed -e's;/;\\;g')"
144
145     if [ -n "$bootnum" ] ; then
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"
149     fi
150     verbose_cmd $EFIBOOTMGR $EFIBOOTMGR_OPTS --create \
151                         --quiet --label "$label" --loader "$binary" -u "$args"
152     bootnum="$(find_bootmgr_entry "$label")"
153     echo -n "$bootnum"
154 }
155
156 safe_string () {
157     echo -n "$*" | tr -c '[a-zA-Z0-9_]' '_'
158 }
159
160 ALLOW_AUTO="no"
161 FORCE_UPDATES="no"
162 MOUNT_EFI_PARTITION="no"
163 LABEL_PREFIX=""
164 VERBOSE="no"
165
166 [ -e /etc/efi-boot/update.conf ] && . /etc/efi-boot/update.conf
167
168 AUTO_RUN=no
169
170 while [ -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             ;;
192         --auto)
193             is_yes "$ALLOW_AUTO" || exit 0
194             AUTO_RUN=yes
195             ;;
196         *)
197             usage >&2
198             exit 2
199             ;;
200     esac
201 done
202
203 if ! 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
221 fi
222
223 if [ -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
233 else
234     msg "efibootmgr missing, won't update the boot manager configuration"
235     EFIBOOTMGR=/bin/true
236 fi
237
238 for 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=""
248     install_files() {
249         /bin/true
250     }
251
252     . "$bootloader_conf" || continue
253
254     LABEL="$LABEL_PREFIX$LABEL"
255
256     if ! is_yes "$ENABLED" ; then
257         remove_bootmgr_entry "$LABEL" >/dev/null
258         continue
259     fi
260
261     local efi_arch
262     if [[ "$ARCH" = i?86 || "$ARCH" = pentium[45] || "$ARCH" = "athlon" ]] ; then
263         # %ix86
264         efi_arch=ia32
265     elif [[ "$ARCH" = "x86_64" || "$ARCH" = "amd64" || "$ARCH" = "ia32e" ]] ; then
266         # %x8664
267         efi_arch=x64
268     else
269         efi_arch="$ARCH"
270     fi
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
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")"
285             eval "_$(safe_string ${CONFIG_NAME})_bootnum=\"$bootnum\""
286     fi
287 done
288
289 if [ -n "$ORDER" -a "$EFIBOOTMGR" != "/bin/true" ] ; then
290     # set up the configured boot order, not removing any existing entries
291     tail="$($EFIBOOTMGR | awk '/^BootOrder:/ {gsub(/,/," ",$2); print $2}')"
292     head=""
293     for config_name in $ORDER ; do
294         eval "bootnum=\$_$(safe_string ${config_name})_bootnum"
295         if [ -z "$bootnum" ] ; then
296             verbose "Cannot find '$config_name' config - won't add to boot order."
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
306 fi
307
308 if ! 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."
311 fi
312
313 # vi: ft=sh sw=4 sts=4 et
This page took 0.113425 seconds and 3 git commands to generate.