summaryrefslogtreecommitdiffstats
path: root/src/kernel-install/kernel-install.in
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel-install/kernel-install.in')
-rwxr-xr-xsrc/kernel-install/kernel-install.in290
1 files changed, 290 insertions, 0 deletions
diff --git a/src/kernel-install/kernel-install.in b/src/kernel-install/kernel-install.in
new file mode 100755
index 0000000000..f6d262f522
--- /dev/null
+++ b/src/kernel-install/kernel-install.in
@@ -0,0 +1,290 @@
+#!/bin/sh
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+
+skip_remaining=77
+
+usage()
+{
+ echo "Usage:"
+ echo " kernel-install [OPTIONS...] add KERNEL-VERSION KERNEL-IMAGE [INITRD-FILE...]"
+ echo " kernel-install [OPTIONS...] remove KERNEL-VERSION"
+ echo " kernel-install [OPTIONS...] inspect"
+ echo "Options:"
+ echo " -h, --help Print this help and exit"
+ echo " --version Print version string and exit"
+ echo " -v, --verbose Increase verbosity"
+}
+
+dropindirs_sort()
+{
+ suffix="$1"
+ shift
+
+ for d; do
+ for i in "$d/"*"$suffix"; do
+ [ -e "$i" ] && echo "${i##*/}"
+ done
+ done | sort -Vu | while read -r f; do
+ for d; do
+ if [ -e "$d/$f" ]; then
+ [ -x "$d/$f" ] && echo "$d/$f"
+ continue 2
+ fi
+ done
+ done
+}
+
+export LC_COLLATE=C
+
+for i; do
+ if [ "$i" = "--help" ] || [ "$i" = "-h" ]; then
+ usage
+ exit 0
+ fi
+done
+
+for i; do
+ if [ "$i" = "--version" ]; then
+ echo "kernel-install {{PROJECT_VERSION}} ({{GIT_VERSION}})"
+ exit 0
+ fi
+done
+
+export KERNEL_INSTALL_VERBOSE=0
+if [ "$1" = "--verbose" ] || [ "$1" = "-v" ]; then
+ shift
+ KERNEL_INSTALL_VERBOSE=1
+fi
+
+if [ "${0##*/}" = "installkernel" ]; then
+ COMMAND=add
+ # make install doesn't pass any initrds
+else
+ COMMAND="$1"
+ [ $# -ge 1 ] && shift
+fi
+
+if [ "$COMMAND" = "inspect" ]; then
+ KERNEL_VERSION=""
+else
+ if [ $# -lt 1 ]; then
+ echo "Error: not enough arguments" >&2
+ exit 1
+ fi
+
+ KERNEL_VERSION="$1"
+ shift
+fi
+
+# These two settings are settable in install.conf
+layout=
+initrd_generator=
+
+if [ -r "/etc/kernel/install.conf" ]; then
+ . /etc/kernel/install.conf
+elif [ -r "/usr/lib/kernel/install.conf" ]; then
+ . /usr/lib/kernel/install.conf
+fi
+
+# If /etc/machine-id is initialized we'll use it, otherwise we'll use a freshly
+# generated one. If the user configured an explicit machine ID to use in
+# /etc/machine-info to use for our purpose, we'll use that instead (for
+# compatibility).
+[ -z "$MACHINE_ID" ] && [ -r /etc/machine-info ] && . /etc/machine-info && MACHINE_ID="$KERNEL_INSTALL_MACHINE_ID"
+[ -z "$MACHINE_ID" ] && [ -r /etc/machine-id ] && read -r MACHINE_ID </etc/machine-id
+[ -z "$MACHINE_ID" ] && MACHINE_ID="$(systemd-id128 new)"
+
+# Now that we determined the machine ID to use, let's determine the "token" for
+# the boot loader entry to generate. We use that for naming the directory below
+# $BOOT where we want to place the kernel/initrd and related resources, as well
+# for naming the .conf boot loader spec entry. Typically this is just the
+# machine ID, but it can be anything else, too, if we are told so.
+[ -z "$ENTRY_TOKEN" ] && [ -r /etc/kernel/entry-token ] && read -r ENTRY_TOKEN </etc/kernel/entry-token
+if [ -z "$ENTRY_TOKEN" ]; then
+ # If not configured explicitly, then use a few candidates: the machine ID,
+ # the IMAGE_ID= and ID= fields from /etc/os-release and finally the fixed
+ # string "Default"
+ ENTRY_TOKEN_SEARCH="$MACHINE_ID"
+ [ -r /etc/os-release ] && . /etc/os-release
+ [ -n "$IMAGE_ID" ] && ENTRY_TOKEN_SEARCH="$ENTRY_TOKEN_SEARCH $IMAGE_ID"
+ [ -n "$ID" ] && ENTRY_TOKEN_SEARCH="$ENTRY_TOKEN_SEARCH $ID"
+ ENTRY_TOKEN_SEARCH="$ENTRY_TOKEN_SEARCH Default"
+else
+ ENTRY_TOKEN_SEARCH="$ENTRY_TOKEN"
+fi
+
+# NB: The $MACHINE_ID is guaranteed to be a valid machine ID, but
+# $ENTRY_TOKEN can be any string that fits into a VFAT filename, though
+# typically is just the machine ID.
+
+[ -z "$BOOT_ROOT" ] && for suff in $ENTRY_TOKEN_SEARCH; do
+ for pref in "/efi" "/boot" "/boot/efi"; do
+ if [ -d "$pref/$suff" ]; then
+ BOOT_ROOT="$pref"
+ ENTRY_TOKEN="$suff"
+ break 2
+ fi
+ done
+done
+
+[ -z "$BOOT_ROOT" ] && for pref in "/efi" "/boot" "/boot/efi"; do
+ if [ -d "$pref/loader/entries" ]; then
+ BOOT_ROOT="$pref"
+ break
+ fi
+done
+
+[ -z "$BOOT_ROOT" ] && for pref in "/efi" "/boot/efi"; do
+ if mountpoint -q "$pref"; then
+ BOOT_ROOT="$pref"
+ break
+ fi
+done
+
+[ -z "$BOOT_ROOT" ] && BOOT_ROOT="/boot"
+
+[ -z "$ENTRY_TOKEN" ] && ENTRY_TOKEN="$MACHINE_ID"
+
+if [ -z "$layout" ]; then
+ # No layout configured by the administrator. Let's try to figure it out
+ # automatically from metadata already contained in $BOOT_ROOT.
+ if [ -e "$BOOT_ROOT/loader/entries.srel" ]; then
+ read -r ENTRIES_SREL <"$BOOT_ROOT/loader/entries.srel"
+ if [ "$ENTRIES_SREL" = "type1" ]; then
+ # The loader/entries.srel file clearly indicates that the installed
+ # boot loader implements the proper standard upstream boot loader
+ # spec for Type #1 entries. Let's default to that, then.
+ layout="bls"
+ else
+ # The loader/entries.srel file indicates some other spec is
+ # implemented and owns the /loader/entries/ directory. Since we
+ # have no idea what that means, let's stay away from it by default.
+ layout="other"
+ fi
+ elif [ -d "$BOOT_ROOT/$ENTRY_TOKEN" ]; then
+ # If the metadata in $BOOT_ROOT doesn't tell us anything, then check if
+ # the entry token directory already exists. If so, let's assume it's
+ # the standard boot loader spec, too.
+ layout="bls"
+ else
+ # There's no metadata in $BOOT_ROOT, and apparently no entry token
+ # directory installed? Then we really don't know anything.
+ layout="other"
+ fi
+fi
+
+ENTRY_DIR_ABS="$BOOT_ROOT/$ENTRY_TOKEN/$KERNEL_VERSION"
+
+# Provide a directory where to store generated initrds
+cleanup() {
+ [ -n "$KERNEL_INSTALL_STAGING_AREA" ] && rm -rf "$KERNEL_INSTALL_STAGING_AREA"
+}
+
+trap cleanup EXIT
+
+KERNEL_INSTALL_STAGING_AREA="$(mktemp -d -t -p /tmp kernel-install.staging.XXXXXXX)"
+
+export KERNEL_INSTALL_MACHINE_ID="$MACHINE_ID"
+export KERNEL_INSTALL_ENTRY_TOKEN="$ENTRY_TOKEN"
+export KERNEL_INSTALL_BOOT_ROOT="$BOOT_ROOT"
+export KERNEL_INSTALL_LAYOUT="$layout"
+export KERNEL_INSTALL_INITRD_GENERATOR="$initrd_generator"
+export KERNEL_INSTALL_STAGING_AREA
+
+[ "$layout" = "bls" ]
+MAKE_ENTRY_DIR_ABS=$?
+
+ret=0
+
+PLUGINS="$(
+ dropindirs_sort ".install" \
+ "/etc/kernel/install.d" \
+ "/usr/lib/kernel/install.d"
+)"
+IFS="
+"
+
+case "$COMMAND" in
+ add)
+ if [ $# -lt 1 ]; then
+ echo "Error: command 'add' requires a kernel image" >&2
+ exit 1
+ fi
+
+ if ! [ -f "$1" ]; then
+ echo "Error: kernel image argument $1 not a file" >&2
+ exit 1
+ fi
+
+ if [ "$MAKE_ENTRY_DIR_ABS" -eq 0 ]; then
+ # Compatibility with earlier versions that used the presence of $BOOT_ROOT/$ENTRY_TOKEN
+ # to signal to 00-entry-directory to create $ENTRY_DIR_ABS
+ # to serve as the indication to use or to not use the BLS
+ if [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ]; then
+ echo "+mkdir -v -p $ENTRY_DIR_ABS"
+ mkdir -v -p "$ENTRY_DIR_ABS" || exit 1
+ else
+ mkdir -p "$ENTRY_DIR_ABS" || exit 1
+ fi
+ fi
+
+ for f in $PLUGINS; do
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "+$f add $KERNEL_VERSION $ENTRY_DIR_ABS $*"
+ "$f" add "$KERNEL_VERSION" "$ENTRY_DIR_ABS" "$@"
+ err=$?
+ [ $err -eq $skip_remaining ] && break
+ ret=$(( ret + err ))
+ done
+ ;;
+
+ remove)
+ for f in $PLUGINS; do
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "+$f remove $KERNEL_VERSION $ENTRY_DIR_ABS"
+ "$f" remove "$KERNEL_VERSION" "$ENTRY_DIR_ABS"
+ err=$?
+ [ $err -eq $skip_remaining ] && break
+ ret=$(( ret + err ))
+ done
+
+ if [ "$MAKE_ENTRY_DIR_ABS" -eq 0 ]; then
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Removing $ENTRY_DIR_ABS/"
+ rm -rf "$ENTRY_DIR_ABS"
+ fi
+ ;;
+
+ inspect)
+ echo "KERNEL_INSTALL_MACHINE_ID: $KERNEL_INSTALL_MACHINE_ID"
+ echo "KERNEL_INSTALL_ENTRY_TOKEN: $KERNEL_INSTALL_ENTRY_TOKEN"
+ echo "KERNEL_INSTALL_BOOT_ROOT: $KERNEL_INSTALL_BOOT_ROOT"
+ echo "KERNEL_INSTALL_LAYOUT: $KERNEL_INSTALL_LAYOUT"
+ echo "KERNEL_INSTALL_INITRD_GENERATOR: $KERNEL_INSTALL_INITRD_GENERATOR"
+ echo "ENTRY_DIR_ABS: $KERNEL_INSTALL_BOOT_ROOT/$ENTRY_TOKEN/\$KERNEL_VERSION"
+
+ # Assert that ENTRY_DIR_ABS actually matches what we are printing here
+ [ "${ENTRY_DIR_ABS%/*}" = "$KERNEL_INSTALL_BOOT_ROOT/$ENTRY_TOKEN" ] || { echo "Assertion didn't pass." >&2; exit 1; }
+
+ ;;
+ *)
+ echo "Error: unknown command '$COMMAND'" >&2
+ exit 1
+ ;;
+esac
+
+exit "$ret"