diff --git a/man/kernel-install.xml b/man/kernel-install.xml index 5ae86aca180..7ad7f86c6da 100644 --- a/man/kernel-install.xml +++ b/man/kernel-install.xml @@ -144,6 +144,7 @@ The <varname>$BOOT</varname> partition + The partition where the kernels and Boot Loader Specification snippets are located is called $BOOT. kernel-install determines the location of this partition by checking @@ -173,77 +174,101 @@ Environment variables - If is used, $KERNEL_INSTALL_VERBOSE=1 will be set for - the plugins. They may output additional logs in this case. + + Environment variables exported for plugins - If $MACHINE_ID is set and not empty when kernel-install is - invoked, it will be used as MACHINE-ID, overriding any automatic detection - attempts. The value must be a valid machine ID (32 hexadecimal characters). + If is used, $KERNEL_INSTALL_VERBOSE=1 will be + exported for plugins. They may output additional logs in this case. - $KERNEL_INSTALL_MACHINE_ID is set for the plugins to the desired - MACHINE-ID to use. It's always a 128bit ID, and typically the ID from - /etc/machine-id or the one passed in via $MACHINE_ID. (If no - machine ID was specified via these methods it might be generated randomly by - kernel-install, in which case it only applies to this invocation.) + $KERNEL_INSTALL_MACHINE_ID is set for the plugins to the desired machine-id to + use. It's always a 128-bit ID. Normally it's read from /etc/machine-id, but it can + also be overriden via $MACHINE_ID (see below). If not specified via these methods a + fallback value will generated by kernel-install, and used only for a single + invocation. - $KERNEL_INSTALL_ENTRY_TOKEN is set for the plugins to the desired entry "token" - to use. It's an identifier that shall be used to identify the local installation, and is often the - machine ID, i.e. same as $KERNEL_INSTALL_MACHINE_ID, but might also be a different - type of identifier, for example a fixed string or the ID=, - IMAGE_ID= values from /etc/os-release. The string passed here - will be used to name Boot Loader Specification entries, or the directories the kernel image and initial - RAM disk images are placed into. Note that while oftentimes - $KERNEL_INSTALL_ENTRY_TOKEN and $KERNEL_INSTALL_MACHINE_ID are set - to the same value, the latter is guaranteed to be a valid 32 character ID in lowercase hexadecimals while - the former can be any short string. The entry token to use is read from - /etc/kernel/entry-token, if it exists. Otherwise a few possible candidates below the - $BOOT are searched for Boot Loader Specification Type 1 entry directories, and if - found the entry token is derived from that. If that is not successful the machine ID is used as - fallback. + $KERNEL_INSTALL_ENTRY_TOKEN is set for the plugins to the desired entry + "token" to use. It's an identifier that shall be used to identify the local installation, and is often + the machine ID, i.e. same as $KERNEL_INSTALL_MACHINE_ID, but might also be a + different type of identifier, for example a fixed string or the ID=, + IMAGE_ID= values from /etc/os-release. The string passed here + will be used to name Boot Loader Specification entries, or the directories the kernel image and initial + RAM disk images are placed into. - $KERNEL_INSTALL_BOOT_ROOT is set for the plugins to the absolute path of the - root directory (mount point, usually) of the hierarchy where boot loader entries, kernel images, and - associated resources should be placed. This usually is the path where the XBOOTLDR partition or the ESP - (EFI System Partition) are mounted, and also conceptually referred to as $BOOT. Can be - overridden by setting $BOOT_ROOT. + Note that while $KERNEL_INSTALL_ENTRY_TOKEN and + $KERNEL_INSTALL_MACHINE_ID are often set to the same value, the latter is guaranteed + to be a valid 32 character ID in lowercase hexadecimals while the former can be any short string. The + entry token to use is read from /etc/kernel/entry-token, if it exists. Otherwise a + few possible candidates below $BOOT are checked for Boot Loader Specification Type 1 + entry directories, and if found the entry token is derived from that. If that is not successful, + $KERNEL_INSTALL_MACHINE_ID is used as fallback. - $KERNEL_INSTALL_LAYOUT=bls|other|... is set for the plugins to specify the - installation layout. Defaults to if - $BOOT/ENTRY-TOKEN exists, or - otherwise. Additional layout names may be defined by convention. If a plugin uses a special layout, it's - encouraged to declare its own layout name and configure layout= in - install.conf upon initial installation. The following values are currently - understood: + $KERNEL_INSTALL_BOOT_ROOT is set for the plugins to the absolute path of the + root directory (mount point, usually) of the hierarchy where boot loader entries, kernel images, and + associated resources should be placed. This usually is the path where the XBOOTLDR partition or the ESP + (EFI System Partition) are mounted, and also conceptually referred to as $BOOT. Can + be overridden by setting $BOOT_ROOT (see below). - - - bls - - Standard Boot Loader - Specification Type #1 layout, compatible with - systemd-boot7: - entries in - $BOOT/loader/entries/ENTRY-TOKEN-KERNEL-VERSION[+TRIES].conf, - kernel and initrds under - $BOOT/ENTRY-TOKEN/KERNEL-VERSION/ - Implemented by 90-loaderentry.install. - - - - other - - Some other layout not understood natively by kernel-install. - - - + $KERNEL_INSTALL_LAYOUT=bls|other|... is set for the plugins to specify the + installation layout. Defaults to if + $BOOT/ENTRY-TOKEN exists, or + otherwise. Additional layout names may be defined by convention. If a plugin uses a special layout, + it's encouraged to declare its own layout name and configure layout= in + install.conf upon initial installation. The following values are currently + understood: - $KERNEL_INSTALL_INITRD_GENERATOR is set for plugins to select the initrd - generator. This may be configured as initrd_generator= in - install.conf. See below. + + + bls + + Standard Boot Loader + Specification Type #1 layout, compatible with + systemd-boot7: + entries in + $BOOT/loader/entries/ENTRY-TOKEN-KERNEL-VERSION[+TRIES].conf, + kernel and initrds under + $BOOT/ENTRY-TOKEN/KERNEL-VERSION/ + Implemented by 90-loaderentry.install. + + + + other + + Some other layout not understood natively by kernel-install. + + + - $KERNEL_INSTALL_STAGING_AREA is set for plugins to a path to a directory. - Plugins may drop files in that directory, and they will be installed as part of the loader entry, based - on the file name and extension. + $KERNEL_INSTALL_INITRD_GENERATOR is set for plugins to select the initrd + generator. This may be configured as initrd_generator= in + install.conf, see below. + + $KERNEL_INSTALL_STAGING_AREA is set for plugins to a path to a directory. + Plugins may drop files in that directory, and they will be installed as part of the loader entry, based + on the file name and extension. + + + + Environment variables understood by <command>kernel-install</command> + + $KERNEL_INSTALL_CONF_ROOT can be set to override the location of the + configuration files read by kernel-install. When set, + install.conf, entry-token, and other files will be + read from this directory. + + $KERNEL_INSTALL_PLUGINS can be set to override the list of plugins executed by + kernel-install. The argument is a whitespace-separated list of paths. + KERNEL_INSTALL_PLUGINS=: may be used to prevent any plugins from running. + + + $MACHINE_ID can be set for kernel-install to override + $KERNEL_INSTALL_MACHINE_ID, the machine ID. + + $BOOT_ROOT can be set for kernel-install to override + $KERNEL_INSTALL_BOOT_ROOT, the installation location for boot entries. + + The last two variables may also be set in install.conf. Variables set in the + environment take precedence over the values specified in the config file. + @@ -271,9 +296,10 @@ Read by 90-loaderentry.install. The content of the file - /etc/kernel/cmdline specifies the kernel command line to use. If that file does not - exist, /usr/lib/kernel/cmdline is used. If that also does not exist, - /proc/cmdline is used. + /etc/kernel/cmdline specifies the kernel command line to use. If that file + does not exist, /usr/lib/kernel/cmdline is used. If that also does not + exist, /proc/cmdline is used. $KERNEL_INSTALL_CONF_ROOT + may be used to override the path. @@ -286,7 +312,8 @@ $BOOT/loader/entries/MACHINE-ID-KERNEL-VERSION+TRIES.conf. This is useful for boot loaders such as systemd-boot7 which - implement boot attempt counting with a counter embedded in the entry file name. + implement boot attempt counting with a counter embedded in the entry file name. + $KERNEL_INSTALL_CONF_ROOT may be used to override the path. @@ -295,8 +322,9 @@ If this file exists it is read and used as "entry token" for this system, i.e. is used for - naming Boot Loader Specification entries, see - $KERNEL_INSTALL_ENTRY_TOKEN above for details. + naming Boot Loader Specification entries, see $KERNEL_INSTALL_ENTRY_TOKEN + above for details. $KERNEL_INSTALL_CONF_ROOT may be used to override the + path. @@ -327,8 +355,19 @@ Configuration options for kernel-install, as a series of KEY=VALUE assignments, compatible with shell - syntax. This currently supports two keys: layout= and - initrd_generator=, for details see the Environment variables section above. + syntax, following the same rules as described in + os-release5. + /etc/kernel/install.conf will be read if present, and + /usr/lib/kernel/install.conf otherwise. This file is optional. + $KERNEL_INSTALL_CONF_ROOT may be used to override the path. + + + Currently, the following keys are supported: + MACHINE_ID=, + BOOT_ROOT=, + layout=, + initrd_generator=. + See the Environment variables section above for details. diff --git a/meson.build b/meson.build index b4fd3692413..5d7c8699fe0 100644 --- a/meson.build +++ b/meson.build @@ -3752,7 +3752,7 @@ executable( install : true, install_dir : rootlibexecdir) -public_programs += custom_target( +exe = custom_target( 'kernel-install', input : kernel_install_in, output : 'kernel-install', @@ -3760,6 +3760,13 @@ public_programs += custom_target( install : want_kernel_install, install_mode : 'rwxr-xr-x', install_dir : bindir) +public_programs += exe + +if want_tests != 'false' + test('test-kernel-install', + test_kernel_install_sh, + args : [exe.full_path(), loaderentry_install]) +endif ############################################################ diff --git a/src/kernel-install/50-depmod.install b/src/kernel-install/50-depmod.install old mode 100644 new mode 100755 index 67319afe61d..d4b991cfd62 --- a/src/kernel-install/50-depmod.install +++ b/src/kernel-install/50-depmod.install @@ -18,8 +18,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . -COMMAND="$1" -KERNEL_VERSION="$2" +set -e + +COMMAND="${1:?}" +KERNEL_VERSION="${2:?}" case "$COMMAND" in add) @@ -44,4 +46,5 @@ case "$COMMAND" in ;; *) exit 0 + ;; esac diff --git a/src/kernel-install/90-loaderentry.install b/src/kernel-install/90-loaderentry.install old mode 100644 new mode 100755 index 549437c7cde..b34bbd83cdf --- a/src/kernel-install/90-loaderentry.install +++ b/src/kernel-install/90-loaderentry.install @@ -18,9 +18,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . -COMMAND="$1" -KERNEL_VERSION="$2" -ENTRY_DIR_ABS="$3" +set -e + +COMMAND="${1:?}" +KERNEL_VERSION="${2:?}" +ENTRY_DIR_ABS="${3:?}" KERNEL_IMAGE="$4" INITRD_OPTIONS_SHIFT=4 @@ -48,14 +50,14 @@ case "$COMMAND" in add) ;; *) - exit 1 + exit 0 ;; esac -if [ -r /etc/os-release ]; then +if [ -f /etc/os-release ]; then # shellcheck source=/dev/null . /etc/os-release -elif [ -r /usr/lib/os-release ]; then +elif [ -f /usr/lib/os-release ]; then # shellcheck source=/dev/null . /usr/lib/os-release fi @@ -65,9 +67,13 @@ fi SORT_KEY="$IMAGE_ID" [ -z "$SORT_KEY" ] && SORT_KEY="$ID" -if [ -r /etc/kernel/cmdline ]; then +if [ -n "$KERNEL_INSTALL_CONF_ROOT" ]; then + if [ -f "$KERNEL_INSTALL_CONF_ROOT/cmdline" ]; then + BOOT_OPTIONS="$(tr -s "$IFS" ' ' <"$KERNEL_INSTALL_CONF_ROOT/cmdline")" + fi +elif [ -f /etc/kernel/cmdline ]; then BOOT_OPTIONS="$(tr -s "$IFS" ' ' &2 + echo "$TRIES_FILE does not contain an integer." >&2 exit 1 fi LOADER_ENTRY="$BOOT_ROOT/loader/entries/$ENTRY_TOKEN-$KERNEL_VERSION+$TRIES.conf" @@ -99,10 +107,11 @@ if ! [ -d "$ENTRY_DIR_ABS" ]; then exit 1 fi -install -g root -o root -m 0644 "$KERNEL_IMAGE" "$ENTRY_DIR_ABS/linux" || { +install -m 0644 "$KERNEL_IMAGE" "$ENTRY_DIR_ABS/linux" || { echo "Error: could not copy '$KERNEL_IMAGE' to '$ENTRY_DIR_ABS/linux'." >&2 exit 1 } +chown root.root "$ENTRY_DIR_ABS/linux" || : shift "$INITRD_OPTIONS_SHIFT" # All files listed as arguments, and staged files starting with "initrd" are installed as initrds. @@ -115,10 +124,11 @@ for initrd in "$@" "${KERNEL_INSTALL_STAGING_AREA}"/initrd*; do initrd_basename="${initrd##*/}" [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Installing $ENTRY_DIR_ABS/$initrd_basename" - install -g root -o root -m 0644 "$initrd" "$ENTRY_DIR_ABS/$initrd_basename" || { + install -m 0644 "$initrd" "$ENTRY_DIR_ABS/$initrd_basename" || { echo "Error: could not copy '$initrd' to '$ENTRY_DIR_ABS/$initrd_basename'." >&2 exit 1 } + chown root.root "$ENTRY_DIR_ABS/$initrd_basename" || : done mkdir -p "${LOADER_ENTRY%/*}" || { diff --git a/src/kernel-install/kernel-install.in b/src/kernel-install/kernel-install.in index 96084860fd7..a597e411336 100755 --- a/src/kernel-install/kernel-install.in +++ b/src/kernel-install/kernel-install.in @@ -20,6 +20,8 @@ skip_remaining=77 +set -e + usage() { echo "Usage:" @@ -83,7 +85,7 @@ if [ "${0##*/}" = "installkernel" ]; then # kernel's install.sh invokes us as # /sbin/installkernel # We ignore the last two arguments. - set -- "$1" + set -- "${1:?}" "${2:?}" else COMMAND="$1" [ $# -ge 1 ] && shift @@ -101,23 +103,27 @@ else shift fi -# These two settings are settable in install.conf +# These two settings are only settable via install.conf layout= initrd_generator= +# These two settings can be inherited from the environment +_MACHINE_ID_SAVED="$MACHINE_ID" +_BOOT_ROOT_SAVED="$BOOT_ROOT" -if [ -r "/etc/kernel/install.conf" ]; then +if [ -n "$KERNEL_INSTALL_CONF_ROOT" ]; then + install_conf="$KERNEL_INSTALL_CONF_ROOT/install.conf" +elif [ -f "/etc/kernel/install.conf" ]; then install_conf="/etc/kernel/install.conf" -elif [ -r "/usr/lib/kernel/install.conf" ]; then +elif [ -f "/usr/lib/kernel/install.conf" ]; then install_conf="/usr/lib/kernel/install.conf" else install_conf= fi -if [ -n "$install_conf" ]; then +if [ -f "$install_conf" ]; then [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Reading $install_conf…" # shellcheck source=/dev/null . "$install_conf" - # FIXME: This may override configuration in environment variables, e.g. $BOOT_ROOT. fi [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && [ -n "$layout" ] && \ @@ -125,21 +131,37 @@ fi [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && [ -n "$initrd_generator" ] && \ echo "$install_conf configures initrd_generator=$initrd_generator" -[ -n "$MACHINE_ID" ] && [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ - echo "machine-id $MACHINE_ID set via environment or install.conf" -[ -n "$BOOT_ROOT" ] && [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ - echo "BOOT_ROOT=$BOOT_ROOT set via environment or install.conf" +if [ -n "$_MACHINE_ID_SAVED" ]; then + MACHINE_ID="$_MACHINE_ID_SAVED" + [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "MACHINE_ID=$MACHINE_ID set via environment" +else + [ -n "$MACHINE_ID" ] && [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "MACHINE_ID=$MACHINE_ID set via install.conf" +fi + +if [ -n "$_BOOT_ROOT_SAVED" ]; then + BOOT_ROOT="$_BOOT_ROOT_SAVED" + [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "BOOT_ROOT=$BOOT_ROOT set via environment" +else + [ -n "$BOOT_ROOT" ] && [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "BOOT_ROOT=$BOOT_ROOT set via 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). # shellcheck source=/dev/null -if [ -z "$MACHINE_ID" ] && [ -r /etc/machine-info ] && . /etc/machine-info && MACHINE_ID="$KERNEL_INSTALL_MACHINE_ID"; then +if [ -z "$MACHINE_ID" ] && [ -f /etc/machine-info ]; then + . /etc/machine-info + MACHINE_ID="$KERNEL_INSTALL_MACHINE_ID" [ -n "$MACHINE_ID" ] && [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ echo "machine-id $MACHINE_ID acquired from /etc/machine-info" fi -if [ -z "$MACHINE_ID" ] && [ -r /etc/machine-id ] && read -r MACHINE_ID "$D/sources/linux" +echo 'the initrd' >"$D/sources/initrd" +echo 'the-token' >"$D/sources/entry-token" +echo 'opt1 opt2' >"$D/sources/cmdline" + +cat >"$D/sources/install.conf" <"$D/sources/tries" + +"$kernel_install" -v add 1.1.1 "$D/sources/linux" "$D/sources/initrd" +entry="$BOOT_ROOT/loader/entries/the-token-1.1.1+56.conf" +test -f "$entry" +grep -qE '^title ' "$entry" +grep -qE '^version +1.1.1' "$entry" +grep -qE '^options +opt1 opt2' "$entry" +grep -qE '^linux .*/the-token/1.1.1/linux' "$entry" +grep -qE '^initrd .*/the-token/1.1.1/initrd' "$entry" + +grep -qE 'image' "$BOOT_ROOT/the-token/1.1.1/linux" +grep -qE 'initrd' "$BOOT_ROOT/the-token/1.1.1/initrd"