From: Luca Boccassi Date: Thu, 16 Apr 2026 22:50:07 +0000 (+0100) Subject: systemctl: add --kernel-cmdline= argument X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2e79f8aa4103665d573da6d19def76d23139cdb9;p=thirdparty%2Fsystemd.git systemctl: add --kernel-cmdline= argument Allows appending kernel command line arguments, like kexec-tool does. This is especially needed for the integration tests, as mkosi adds a bunch of options that are needed for the test suite to work, and it breaks without them. --- diff --git a/man/systemctl.xml b/man/systemctl.xml index 2a542ba466a..8b8d1065556 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -2795,6 +2795,21 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err + + + + + When used with kexec, append the specified string to the kernel command + line options of the kexec kernel. The kernel command line is taken from the boot loader entry of + the currently booted kernel (as selected automatically when no kexec kernel is preloaded, see + kexec above). This string is appended verbatim, separated from the existing + options by a single space. systemctl kexec will fail if this option is specified + when a kexec kernel is already loaded. + + + + + diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in index c34c7fb10eb..9f52115b732 100644 --- a/shell-completion/bash/systemctl.in +++ b/shell-completion/bash/systemctl.in @@ -137,7 +137,7 @@ _systemctl () { --show-transaction -T --mkdir --read-only' [ARG]='--host -H --kill-whom --property -p -P --signal -s --type -t --state --job-mode --root --preset-mode -n --lines -o --output -M --machine --message --timestamp --check-inhibitors --what - --image --boot-loader-menu --boot-loader-entry --reboot-argument --drop-in' + --image --boot-loader-menu --boot-loader-entry --reboot-argument --kernel-cmdline --drop-in' ) if __contains_word "--user" ${COMP_WORDS[*]}; then diff --git a/src/systemctl/systemctl-start-special.c b/src/systemctl/systemctl-start-special.c index b7d10eb891d..fd38c678ea6 100644 --- a/src/systemctl/systemctl-start-special.c +++ b/src/systemctl/systemctl-start-special.c @@ -28,6 +28,9 @@ static int load_kexec_kernel(void) { int r; if (kexec_loaded()) { + if (arg_kernel_cmdline) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--kernel-cmdline= specified but kexec kernel already loaded"); log_debug("Kexec kernel already loaded."); return 0; } @@ -78,6 +81,9 @@ static int load_kexec_kernel(void) { if (!options) return log_oom(); + if (!isempty(arg_kernel_cmdline) && !strextend_with_separator(&options, " ", arg_kernel_cmdline)) + return log_oom(); + log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, "%s %s kernel=\"%s\" cmdline=\"%s\"%s%s%s", arg_dry_run ? "Would call" : "Calling", diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 3d3ed98fcd2..5c9a24b119a 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -27,6 +27,7 @@ #include "systemctl-compat-shutdown.h" #include "systemctl-logind.h" #include "time-util.h" +#include "utf8.h" char **arg_types = NULL; char **arg_states = NULL; @@ -68,6 +69,7 @@ char *arg_image = NULL; usec_t arg_when = 0; bool arg_stdin = false; const char *arg_reboot_argument = NULL; +char *arg_kernel_cmdline = NULL; enum action arg_action = ACTION_SYSTEMCTL; BusTransport arg_transport = BUS_TRANSPORT_LOCAL; const char *arg_host = NULL; @@ -98,6 +100,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_kill_whom, unsetp); STATIC_DESTRUCTOR_REGISTER(arg_root, freep); STATIC_DESTRUCTOR_REGISTER(arg_image, freep); STATIC_DESTRUCTOR_REGISTER(arg_reboot_argument, unsetp); +STATIC_DESTRUCTOR_REGISTER(arg_kernel_cmdline, freep); STATIC_DESTRUCTOR_REGISTER(arg_host, unsetp); STATIC_DESTRUCTOR_REGISTER(arg_boot_loader_entry, unsetp); STATIC_DESTRUCTOR_REGISTER(arg_clean_what, strv_freep); @@ -305,6 +308,9 @@ static int systemctl_help(void) { " Boot into a specific boot loader entry on next boot\n" " --reboot-argument=ARG\n" " Specify argument string to pass to reboot()\n" + " --kernel-cmdline=CMDLINE\n" + " Append to the kernel command line when loading the\n" + " kernel from the booted boot loader entry\n" " --plain Print unit dependencies as a list instead of a tree\n" " --timestamp=FORMAT Change format of printed timestamps (pretty, unix,\n" " us, utc, us+utc)\n" @@ -434,6 +440,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { ARG_WAIT, ARG_WHAT, ARG_REBOOT_ARG, + ARG_KERNEL_CMDLINE, ARG_TIMESTAMP_STYLE, ARG_READ_ONLY, ARG_MKDIR, @@ -505,6 +512,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { { "show-transaction", no_argument, NULL, 'T' }, { "what", required_argument, NULL, ARG_WHAT }, { "reboot-argument", required_argument, NULL, ARG_REBOOT_ARG }, + { "kernel-cmdline", required_argument, NULL, ARG_KERNEL_CMDLINE }, { "timestamp", required_argument, NULL, ARG_TIMESTAMP_STYLE }, { "read-only", no_argument, NULL, ARG_READ_ONLY }, { "mkdir", no_argument, NULL, ARG_MKDIR }, @@ -960,6 +968,19 @@ static int systemctl_parse_argv(int argc, char *argv[]) { arg_reboot_argument = optarg; break; + case ARG_KERNEL_CMDLINE: + if (!utf8_is_valid(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--kernel-cmdline= argument is not valid UTF-8: %s", optarg); + if (string_has_cc(optarg, NULL)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--kernel-cmdline= argument contains control characters: %s", optarg); + + r = free_and_strdup_warn(&arg_kernel_cmdline, optarg); + if (r < 0) + return r; + break; + case ARG_TIMESTAMP_STYLE: if (streq(optarg, "help")) return DUMP_STRING_TABLE(timestamp_style, TimestampStyle, _TIMESTAMP_STYLE_MAX); diff --git a/src/systemctl/systemctl.h b/src/systemctl/systemctl.h index 8d4b1a614da..bc52e96fe3b 100644 --- a/src/systemctl/systemctl.h +++ b/src/systemctl/systemctl.h @@ -76,6 +76,7 @@ extern char *arg_image; extern usec_t arg_when; extern bool arg_stdin; extern const char *arg_reboot_argument; +extern char *arg_kernel_cmdline; extern enum action arg_action; extern BusTransport arg_transport; extern const char *arg_host;