summaryrefslogtreecommitdiffstats
path: root/src/kernel-install
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel-install')
-rw-r--r--src/kernel-install/00-entry-directory.install32
-rw-r--r--src/kernel-install/50-depmod.install27
-rw-r--r--src/kernel-install/90-loaderentry.install124
-rwxr-xr-xsrc/kernel-install/kernel-install181
-rw-r--r--src/kernel-install/meson.build21
5 files changed, 385 insertions, 0 deletions
diff --git a/src/kernel-install/00-entry-directory.install b/src/kernel-install/00-entry-directory.install
new file mode 100644
index 0000000..21c09fa
--- /dev/null
+++ b/src/kernel-install/00-entry-directory.install
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+COMMAND="$1"
+KERNEL_VERSION="$2"
+ENTRY_DIR_ABS="$3"
+KERNEL_IMAGE="$4"
+INITRD_OPTIONS_START="5"
+
+if ! [[ $KERNEL_INSTALL_MACHINE_ID ]]; then
+ exit 0
+fi
+
+if [[ $COMMAND != add ]]; then
+ exit 0
+fi
+
+# If the boot dir exists (e.g. $ESP/<machine-id>),
+# create the entry directory ($ESP/<machine-id>/<kernel-version>).
+# This is the only function of this plugin.
+MACHINE_ID_DIR="${ENTRY_DIR_ABS%/*}"
+if ! [ -d "$MACHINE_ID_DIR" ]; then
+ exit 0
+fi
+
+if [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ]; then
+ echo "+mkdir -v -p $ENTRY_DIR_ABS"
+ exec mkdir -v -p "$ENTRY_DIR_ABS"
+else
+ exec mkdir -p "$ENTRY_DIR_ABS"
+fi
diff --git a/src/kernel-install/50-depmod.install b/src/kernel-install/50-depmod.install
new file mode 100644
index 0000000..3850eac
--- /dev/null
+++ b/src/kernel-install/50-depmod.install
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+COMMAND="$1"
+KERNEL_VERSION="$2"
+ENTRY_DIR_ABS="$3"
+KERNEL_IMAGE="$4"
+INITRD_OPTIONS_START="5"
+
+[[ $KERNEL_VERSION ]] || exit 1
+
+case "$COMMAND" in
+ add)
+ [[ -d "/lib/modules/${KERNEL_VERSION}/kernel" ]] || exit 0
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \
+ echo "Running depmod -a ${KERNEL_VERSION}"
+ exec depmod -a "${KERNEL_VERSION}"
+ ;;
+ remove)
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \
+ echo "Removing /lib/modules/${KERNEL_VERSION}/modules.dep and associated files"
+ exec rm -f /lib/modules/"${KERNEL_VERSION}"/modules.{alias{,.bin},builtin.bin,dep{,.bin},devname,softdep,symbols{,.bin}}
+ ;;
+ *)
+ exit 0
+esac
diff --git a/src/kernel-install/90-loaderentry.install b/src/kernel-install/90-loaderentry.install
new file mode 100644
index 0000000..d096745
--- /dev/null
+++ b/src/kernel-install/90-loaderentry.install
@@ -0,0 +1,124 @@
+#!/usr/bin/env bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+COMMAND="$1"
+KERNEL_VERSION="$2"
+ENTRY_DIR_ABS="$3"
+KERNEL_IMAGE="$4"
+INITRD_OPTIONS_START="5"
+
+if ! [[ $KERNEL_INSTALL_MACHINE_ID ]]; then
+ exit 0
+fi
+
+if ! [[ -d "$ENTRY_DIR_ABS" ]]; then
+ exit 0
+fi
+
+MACHINE_ID=$KERNEL_INSTALL_MACHINE_ID
+
+BOOT_ROOT=${ENTRY_DIR_ABS%/$MACHINE_ID/$KERNEL_VERSION}
+BOOT_MNT=$(stat -c %m $BOOT_ROOT)
+ENTRY_DIR=${ENTRY_DIR_ABS#$BOOT_MNT}
+
+if [[ $COMMAND == remove ]]; then
+ rm -f "$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION.conf"
+ rm -f "$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION+"*".conf"
+ exit 0
+fi
+
+if ! [[ $COMMAND == add ]]; then
+ exit 1
+fi
+
+if ! [[ $KERNEL_IMAGE ]]; then
+ exit 1
+fi
+
+if [[ -f /etc/os-release ]]; then
+ . /etc/os-release
+elif [[ -f /usr/lib/os-release ]]; then
+ . /usr/lib/os-release
+fi
+
+if ! [[ $PRETTY_NAME ]]; then
+ PRETTY_NAME="Linux $KERNEL_VERSION"
+fi
+
+if [[ -f /etc/kernel/cmdline ]]; then
+ read -r -d '' -a BOOT_OPTIONS < /etc/kernel/cmdline
+elif [[ -f /usr/lib/kernel/cmdline ]]; then
+ read -r -d '' -a BOOT_OPTIONS < /usr/lib/kernel/cmdline
+else
+ declare -a BOOT_OPTIONS
+
+ read -r -d '' -a line < /proc/cmdline
+ for i in "${line[@]}"; do
+ [[ "${i#initrd=*}" != "$i" ]] && continue
+ [[ "${i#BOOT_IMAGE=*}" != "$i" ]] && continue
+ BOOT_OPTIONS+=("$i")
+ done
+fi
+
+if [[ -f /etc/kernel/tries ]]; then
+ read -r TRIES </etc/kernel/tries
+ if ! [[ "$TRIES" =~ ^[0-9]+$ ]] ; then
+ echo "/etc/kernel/tries does not contain an integer." >&2
+ exit 1
+ fi
+ LOADER_ENTRY="$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION+$TRIES.conf"
+else
+ LOADER_ENTRY="$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION.conf"
+fi
+
+cp "$KERNEL_IMAGE" "$ENTRY_DIR_ABS/linux" &&
+ chown root:root "$ENTRY_DIR_ABS/linux" &&
+ chmod 0644 "$ENTRY_DIR_ABS/linux" || {
+ echo "Could not copy '$KERNEL_IMAGE to '$ENTRY_DIR_ABS/linux'." >&2
+ exit 1
+}
+
+INITRD_OPTIONS=( "${@:${INITRD_OPTIONS_START}}" )
+
+for initrd in "${INITRD_OPTIONS[@]}"; do
+ if [[ -f "${initrd}" ]]; then
+ initrd_basename="$(basename ${initrd})"
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \
+ echo "Installing $ENTRY_DIR_ABS/${initrd_basename}"
+ cp "${initrd}" "$ENTRY_DIR_ABS/${initrd_basename}" &&
+ chown root:root "$ENTRY_DIR_ABS/${initrd_basename}" &&
+ chmod 0644 "$ENTRY_DIR_ABS/${initrd_basename}" || {
+ echo "Could not copy '${initrd}' to '$ENTRY_DIR_ABS/${initrd_basename}'." >&2
+ exit 1
+ }
+ fi
+done
+
+# If no initrd option is supplied, fall back to "initrd" which is
+# the name used by dracut when generating it in its kernel-install hook
+[[ ${#INITRD_OPTIONS[@]} == 0 ]] && INITRD_OPTIONS=( initrd )
+
+mkdir -p "${LOADER_ENTRY%/*}" || {
+ echo "Could not create loader entry directory '${LOADER_ENTRY%/*}'." >&2
+ exit 1
+}
+
+[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \
+ echo "Creating $LOADER_ENTRY"
+{
+ echo "title $PRETTY_NAME"
+ echo "version $KERNEL_VERSION"
+ echo "machine-id $MACHINE_ID"
+ echo "options ${BOOT_OPTIONS[*]}"
+ echo "linux $ENTRY_DIR/linux"
+ for initrd in "${INITRD_OPTIONS[@]}"; do
+ [[ -f $ENTRY_DIR_ABS/$(basename ${initrd}) ]] && \
+ echo "initrd $ENTRY_DIR/$(basename ${initrd})"
+ done
+ :
+} > "$LOADER_ENTRY" || {
+ echo "Could not create loader entry '$LOADER_ENTRY'." >&2
+ exit 1
+}
+exit 0
diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install
new file mode 100755
index 0000000..e7457e9
--- /dev/null
+++ b/src/kernel-install/kernel-install
@@ -0,0 +1,181 @@
+#!/usr/bin/env bash
+# -*- 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 " $0 [OPTIONS...] add KERNEL-VERSION KERNEL-IMAGE [INITRD-FILE ...]"
+ echo " $0 [OPTIONS...] remove KERNEL-VERSION"
+ echo "Options:"
+ echo " -h,--help Print this help"
+ echo " -v,--verbose Increase verbosity"
+}
+
+dropindirs_sort()
+{
+ local suffix=$1; shift
+ local -a files
+ local f d i
+
+ readarray -t files <<<"$(
+ for d in "$@"; do
+ for i in "$d/"*"$suffix"; do
+ if [[ -e "$i" ]]; then
+ echo "${i##*/}"
+ fi
+ done
+ done | sort -Vu
+ )"
+
+ for f in "${files[@]}"; do
+ for d in "$@"; do
+ if [[ -e "$d/$f" ]]; then
+ echo "$d/$f"
+ continue 2
+ fi
+ done
+ done
+}
+
+export LC_COLLATE=C
+
+for i in "$@"; do
+ if [ "$i" == "--help" -o "$i" == "-h" ]; then
+ usage
+ exit 0
+ fi
+done
+
+KERNEL_INSTALL_VERBOSE=0
+if [ "$1" == "--verbose" -o "$1" == "-v" ]; then
+ shift
+ KERNEL_INSTALL_VERBOSE=1
+fi
+export KERNEL_INSTALL_VERBOSE
+
+if [[ "${0##*/}" == 'installkernel' ]]; then
+ COMMAND='add'
+ # make install doesn't pass any parameter wrt initrd handling
+ INITRD_OPTIONS=()
+else
+ COMMAND="$1"
+ shift
+ INITRD_OPTIONS=( "${@:3}" )
+fi
+
+KERNEL_VERSION="$1"
+KERNEL_IMAGE="$2"
+
+# Reuse directory created without a machine ID present if it exists.
+if [[ -d /efi/Default ]] || [[ -d /boot/Default ]] || [[ -d /boot/efi/Default ]]; then
+ MACHINE_ID="Default"
+elif [[ -f /etc/machine-id ]]; then
+ read MACHINE_ID < /etc/machine-id
+else
+ MACHINE_ID="Default"
+fi
+
+if [[ ! $COMMAND ]] || [[ ! $KERNEL_VERSION ]]; then
+ echo "Not enough arguments" >&2
+ exit 1
+fi
+
+if [[ -d /efi/loader/entries ]] || [[ -d /efi/$MACHINE_ID ]]; then
+ ENTRY_DIR_ABS="/efi/$MACHINE_ID/$KERNEL_VERSION"
+elif [[ -d /boot/loader/entries ]] || [[ -d /boot/$MACHINE_ID ]]; then
+ ENTRY_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION"
+elif [[ -d /boot/efi/loader/entries ]] || [[ -d /boot/efi/$MACHINE_ID ]]; then
+ ENTRY_DIR_ABS="/boot/efi/$MACHINE_ID/$KERNEL_VERSION"
+elif mountpoint -q /efi; then
+ ENTRY_DIR_ABS="/efi/$MACHINE_ID/$KERNEL_VERSION"
+elif mountpoint -q /boot/efi; then
+ ENTRY_DIR_ABS="/boot/efi/$MACHINE_ID/$KERNEL_VERSION"
+else
+ ENTRY_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION"
+fi
+
+export KERNEL_INSTALL_MACHINE_ID=$MACHINE_ID
+
+ret=0
+
+readarray -t PLUGINS <<<"$(
+ dropindirs_sort ".install" \
+ "/etc/kernel/install.d" \
+ "/usr/lib/kernel/install.d"
+)"
+
+case $COMMAND in
+ add)
+ if [[ ! "$KERNEL_IMAGE" ]]; then
+ echo "Command 'add' requires an argument" >&2
+ exit 1
+ fi
+
+ if [[ ! -f "$KERNEL_IMAGE" ]]; then
+ echo "Kernel image argument ${KERNEL_IMAGE} not a file" >&2
+ exit 1
+ fi
+
+ for f in "${PLUGINS[@]}"; do
+ if [[ -x $f ]]; then
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \
+ echo "+$f add $KERNEL_VERSION $ENTRY_DIR_ABS $KERNEL_IMAGE ${INITRD_OPTIONS[@]}"
+ "$f" add "$KERNEL_VERSION" "$ENTRY_DIR_ABS" "$KERNEL_IMAGE" "${INITRD_OPTIONS[@]}"
+ x=$?
+ if [[ $x == $SKIP_REMAINING ]]; then
+ ret=0
+ break
+ fi
+ ((ret+=$x))
+ fi
+ done
+ ;;
+
+ remove)
+ for f in "${PLUGINS[@]}"; do
+ if [[ -x $f ]]; then
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \
+ echo "+$f remove $KERNEL_VERSION $ENTRY_DIR_ABS"
+ "$f" remove "$KERNEL_VERSION" "$ENTRY_DIR_ABS"
+ x=$?
+ if [[ $x == $SKIP_REMAINING ]]; then
+ ret=0
+ break
+ fi
+ ((ret+=$x))
+ fi
+ done
+
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \
+ echo "Removing $ENTRY_DIR_ABS"
+
+ rm -rf "$ENTRY_DIR_ABS"
+ ((ret+=$?))
+ ;;
+
+ *)
+ echo "Unknown command '$COMMAND'" >&2
+ exit 1
+ ;;
+esac
+
+exit $ret
diff --git a/src/kernel-install/meson.build b/src/kernel-install/meson.build
new file mode 100644
index 0000000..4117188
--- /dev/null
+++ b/src/kernel-install/meson.build
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+want_kernel_install = get_option('kernel-install')
+
+if want_kernel_install
+ install_data('kernel-install',
+ install_mode : 'rwxr-xr-x',
+ install_dir : bindir)
+
+ install_data('00-entry-directory.install',
+ '50-depmod.install',
+ '90-loaderentry.install',
+ install_mode : 'rwxr-xr-x',
+ install_dir : kernelinstalldir)
+
+ if install_sysconfdir
+ meson.add_install_script('sh', '-c',
+ mkdir_p.format(join_paths(sysconfdir, 'kernel/install.d')))
+ endif
+
+endif