]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/kernel-install/kernel-install
login: shorten code a bit
[thirdparty/systemd.git] / src / kernel-install / kernel-install
1 #!/bin/sh
2 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
3 # ex: ts=8 sw=4 sts=4 et filetype=sh
4 # SPDX-License-Identifier: LGPL-2.1-or-later
5 #
6 # This file is part of systemd.
7 #
8 # systemd is free software; you can redistribute it and/or modify it
9 # under the terms of the GNU Lesser General Public License as published by
10 # the Free Software Foundation; either version 2.1 of the License, or
11 # (at your option) any later version.
12 #
13 # systemd is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # General Public License for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public License
19 # along with systemd; If not, see <http://www.gnu.org/licenses/>.
20
21 skip_remaining=77
22
23 usage()
24 {
25 echo "Usage:"
26 echo " $0 [OPTIONS...] add KERNEL-VERSION KERNEL-IMAGE [INITRD-FILE ...]"
27 echo " $0 [OPTIONS...] remove KERNEL-VERSION"
28 echo " $0 [OPTIONS...] inspect"
29 echo "Options:"
30 echo " -h, --help Print this help"
31 echo " -v, --verbose Increase verbosity"
32 }
33
34 dropindirs_sort()
35 {
36 suffix="$1"
37 shift
38
39 for d; do
40 for i in "$d/"*"$suffix"; do
41 [ -e "$i" ] && echo "${i##*/}"
42 done
43 done | sort -Vu | while read -r f; do
44 for d; do
45 if [ -e "$d/$f" ]; then
46 [ -x "$d/$f" ] && echo "$d/$f"
47 continue 2
48 fi
49 done
50 done
51 }
52
53 export LC_COLLATE=C
54
55 for i; do
56 if [ "$i" = "--help" ] || [ "$i" = "-h" ]; then
57 usage
58 exit 0
59 fi
60 done
61
62 export KERNEL_INSTALL_VERBOSE=0
63 if [ "$1" = "--verbose" ] || [ "$1" = "-v" ]; then
64 shift
65 KERNEL_INSTALL_VERBOSE=1
66 fi
67
68 if [ "${0##*/}" = "installkernel" ]; then
69 COMMAND=add
70 # make install doesn't pass any initrds
71 else
72 COMMAND="$1"
73 [ $# -ge 1 ] && shift
74 fi
75
76 if [ "$COMMAND" = "inspect" ]; then
77 KERNEL_VERSION=""
78 else
79 if [ $# -lt 1 ]; then
80 echo "Error: not enough arguments" >&2
81 exit 1
82 fi
83
84 KERNEL_VERSION="$1"
85 shift
86 fi
87
88 # These two settings are settable in install.conf
89 layout=
90 initrd_generator=
91
92 if [ -r "/etc/kernel/install.conf" ]; then
93 . /etc/kernel/install.conf
94 elif [ -r "/usr/lib/kernel/install.conf" ]; then
95 . /usr/lib/kernel/install.conf
96 fi
97
98 # If /etc/machine-id is initialized we'll use it, otherwise we'll use a freshly
99 # generated one. If the user configured an explicit machine ID to use in
100 # /etc/machine-info to use for our purpose, we'll use that instead (for
101 # compatibility).
102 [ -z "$MACHINE_ID" ] && [ -r /etc/machine-info ] && . /etc/machine-info && MACHINE_ID="$KERNEL_INSTALL_MACHINE_ID"
103 [ -z "$MACHINE_ID" ] && [ -r /etc/machine-id ] && read -r MACHINE_ID </etc/machine-id
104 [ -z "$MACHINE_ID" ] && MACHINE_ID="$(systemd-id128 new)"
105
106 # Now that we determined the machine ID to use, let's determine the "token" for
107 # the boot loader entry to generate. We use that for naming the directory below
108 # $BOOT where we want to place the kernel/initrd and related resources, as well
109 # for naming the .conf boot loader spec entry. Typically this is just the
110 # machine ID, but it can be anything else, too, if we are told so.
111 [ -z "$ENTRY_TOKEN" ] && [ -r /etc/kernel/entry-token ] && read -r ENTRY_TOKEN </etc/kernel/entry-token
112 if [ -z "$ENTRY_TOKEN" ]; then
113 # If not configured explicitly, then use a few candidates: the machine ID,
114 # the IMAGE_ID= and ID= fields from /etc/os-release and finally the fixed
115 # string "Default"
116 ENTRY_TOKEN_SEARCH="$MACHINE_ID"
117 [ -r /etc/os-release ] && . /etc/os-release
118 [ -n "$IMAGE_ID" ] && ENTRY_TOKEN_SEARCH="$ENTRY_TOKEN_SEARCH $IMAGE_ID"
119 [ -n "$ID" ] && ENTRY_TOKEN_SEARCH="$ENTRY_TOKEN_SEARCH $ID"
120 ENTRY_TOKEN_SEARCH="$ENTRY_TOKEN_SEARCH Default"
121 else
122 ENTRY_TOKEN_SEARCH="$ENTRY_TOKEN"
123 fi
124
125 # NB: The $MACHINE_ID is guaranteed to be a valid machine ID, but
126 # $ENTRY_TOKEN can be any string that fits into a VFAT filename, though
127 # typically is just the machine ID.
128
129 [ -z "$BOOT_ROOT" ] && for suff in $ENTRY_TOKEN_SEARCH; do
130 for pref in "/efi" "/boot" "/boot/efi"; do
131 if [ -d "$pref/$suff" ]; then
132 BOOT_ROOT="$pref"
133 ENTRY_TOKEN="$suff"
134 break 2
135 fi
136 done
137 done
138
139 [ -z "$BOOT_ROOT" ] && for pref in "/efi" "/boot" "/boot/efi"; do
140 if [ -d "$pref/loader/entries" ]; then
141 BOOT_ROOT="$pref"
142 break
143 fi
144 done
145
146 [ -z "$BOOT_ROOT" ] && for pref in "/efi" "/boot/efi"; do
147 if mountpoint -q "$pref"; then
148 BOOT_ROOT="$pref"
149 break
150 fi
151 done
152
153 [ -z "$BOOT_ROOT" ] && BOOT_ROOT="/boot"
154
155 [ -z "$ENTRY_TOKEN" ] && ENTRY_TOKEN="$MACHINE_ID"
156
157 if [ -z "$layout" ]; then
158 # No layout configured by the administrator. Let's try to figure it out
159 # automatically from metadata already contained in $BOOT_ROOT.
160 if [ -e "$BOOT_ROOT/loader/entries.srel" ]; then
161 read -r ENTRIES_SREL <"$BOOT_ROOT/loader/entries.srel"
162 if [ "$ENTRIES_SREL" = "type1" ]; then
163 # The loader/entries.srel file clearly indicates that the installed
164 # boot loader implements the proper standard upstream boot loader
165 # spec for Type #1 entries. Let's default to that, then.
166 layout="bls"
167 else
168 # The loader/entries.srel file indicates some other spec is
169 # implemented and owns the /loader/entries/ directory. Since we
170 # have no idea what that means, let's stay away from it by default.
171 layout="other"
172 fi
173 elif [ -d "$BOOT_ROOT/$ENTRY_TOKEN" ]; then
174 # If the metadata in $BOOT_ROOT doesn't tell us anything, then check if
175 # the entry token directory already exists. If so, let's assume it's
176 # the standard boot loader spec, too.
177 layout="bls"
178 else
179 # There's no metadata in $BOOT_ROOT, and apparently no entry token
180 # directory installed? Then we really don't know anything.
181 layout="other"
182 fi
183 fi
184
185 ENTRY_DIR_ABS="$BOOT_ROOT/$ENTRY_TOKEN/$KERNEL_VERSION"
186
187 # Provide a directory where to store generated initrds
188 cleanup() {
189 [ -n "$KERNEL_INSTALL_STAGING_AREA" ] && rm -rf "$KERNEL_INSTALL_STAGING_AREA"
190 }
191
192 trap cleanup EXIT
193
194 KERNEL_INSTALL_STAGING_AREA="$(mktemp -d -t -p /tmp kernel-install.staging.XXXXXXX)"
195
196 export KERNEL_INSTALL_MACHINE_ID="$MACHINE_ID"
197 export KERNEL_INSTALL_ENTRY_TOKEN="$ENTRY_TOKEN"
198 export KERNEL_INSTALL_BOOT_ROOT="$BOOT_ROOT"
199 export KERNEL_INSTALL_LAYOUT="$layout"
200 export KERNEL_INSTALL_INITRD_GENERATOR="$initrd_generator"
201 export KERNEL_INSTALL_STAGING_AREA
202
203 [ "$layout" = "bls" ]
204 MAKE_ENTRY_DIR_ABS=$?
205
206 ret=0
207
208 PLUGINS="$(
209 dropindirs_sort ".install" \
210 "/etc/kernel/install.d" \
211 "/usr/lib/kernel/install.d"
212 )"
213 IFS="
214 "
215
216 case "$COMMAND" in
217 add)
218 if [ $# -lt 1 ]; then
219 echo "Error: command 'add' requires a kernel image" >&2
220 exit 1
221 fi
222
223 if ! [ -f "$1" ]; then
224 echo "Error: kernel image argument $1 not a file" >&2
225 exit 1
226 fi
227
228 if [ "$MAKE_ENTRY_DIR_ABS" -eq 0 ]; then
229 # Compatibility with earlier versions that used the presence of $BOOT_ROOT/$ENTRY_TOKEN
230 # to signal to 00-entry-directory to create $ENTRY_DIR_ABS
231 # to serve as the indication to use or to not use the BLS
232 if [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ]; then
233 echo "+mkdir -v -p $ENTRY_DIR_ABS"
234 mkdir -v -p "$ENTRY_DIR_ABS" || exit 1
235 else
236 mkdir -p "$ENTRY_DIR_ABS" || exit 1
237 fi
238 fi
239
240 for f in $PLUGINS; do
241 [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "+$f add $KERNEL_VERSION $ENTRY_DIR_ABS $*"
242 "$f" add "$KERNEL_VERSION" "$ENTRY_DIR_ABS" "$@"
243 err=$?
244 [ $err -eq $skip_remaining ] && break
245 ret=$(( ret + err ))
246 done
247 ;;
248
249 remove)
250 for f in $PLUGINS; do
251 [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "+$f remove $KERNEL_VERSION $ENTRY_DIR_ABS"
252 "$f" remove "$KERNEL_VERSION" "$ENTRY_DIR_ABS"
253 err=$?
254 [ $err -eq $skip_remaining ] && break
255 ret=$(( ret + err ))
256 done
257
258 if [ "$MAKE_ENTRY_DIR_ABS" -eq 0 ]; then
259 [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Removing $ENTRY_DIR_ABS/"
260 rm -rf "$ENTRY_DIR_ABS"
261 fi
262 ;;
263
264 inspect)
265 echo "KERNEL_INSTALL_MACHINE_ID: $KERNEL_INSTALL_MACHINE_ID"
266 echo "KERNEL_INSTALL_ENTRY_TOKEN: $KERNEL_INSTALL_ENTRY_TOKEN"
267 echo "KERNEL_INSTALL_BOOT_ROOT: $KERNEL_INSTALL_BOOT_ROOT"
268 echo "KERNEL_INSTALL_LAYOUT: $KERNEL_INSTALL_LAYOUT"
269 echo "KERNEL_INSTALL_INITRD_GENERATOR: $KERNEL_INSTALL_INITRD_GENERATOR"
270 echo "ENTRY_DIR_ABS: $KERNEL_INSTALL_BOOT_ROOT/$ENTRY_TOKEN/\$KERNEL_VERSION"
271
272 # Assert that ENTRY_DIR_ABS actually matches what we are printing here
273 [ "${ENTRY_DIR_ABS%/*}" = "$KERNEL_INSTALL_BOOT_ROOT/$ENTRY_TOKEN" ] || { echo "Assertion didn't pass." >&2; exit 1; }
274
275 ;;
276 *)
277 echo "Error: unknown command '$COMMAND'" >&2
278 exit 1
279 ;;
280 esac
281
282 exit "$ret"