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