If the kernel is enabled with CONFIG_BOOT_CONFIG_FORCE, it will always append the bootconfig at the start of the kernel commandline. If reuse-cmdline option is used in kexec, the bootconfig will be repeatedly appended at the start of the commandline on every kexec. As there is a limit on the size of kernel commandline that can be used, --reuse-cmdline option will break kexec depending on the size of bootconfig on repeated kexec.
Bootconfig is embedded in the kernel, so it should not be considered when reusing kernel command line. Modify get_command_line() to first attempt reading kernel parameters from /proc/bootconfig before falling back to /proc/cmdline. This allows kexec to use the original boot parameters without bootconfig which is embedded in the kernel. The function will fallback to /proc/cmdline behavior when: - /proc/bootconfig doesn't exist - /proc/bootconfig is empty - /proc/bootconfig doesn't contain the expected marker format - The extracted parameter line is empty Signed-off-by: Usama Arif <usamaarif...@gmail.com> --- kexec/kexec.c | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/kexec/kexec.c b/kexec/kexec.c index 6bf12d7..b31cb1f 100644 --- a/kexec/kexec.c +++ b/kexec/kexec.c @@ -1235,15 +1235,53 @@ static char *slurp_proc_file(const char *filename, size_t *len) */ char *get_command_line(void) { - char *p, *line; + char *p, *line = NULL; size_t size; + char *bootconfig_line; + size_t bootconfig_size; + + /* First try to get command line parameters from /proc/bootconfig */ + bootconfig_line = slurp_proc_file("/proc/bootconfig", &bootconfig_size); + if (bootconfig_line && bootconfig_size > 0) { + /* Look for "# Parameters from bootloader:" */ + char *params_marker = strstr(bootconfig_line, "# Parameters from bootloader:"); + if (params_marker) { + /* Find the next line after the marker */ + char *params_start = strchr(params_marker, '\n'); + if (params_start) { + params_start++; /* Move past the newline */ + + /* Check if this line starts with "# " */ + if (strncmp(params_start, "# ", 2) == 0) { + /* Skip the "# " prefix */ + params_start += 2; + + /* Find the end of the line */ + char *params_end = strchr(params_start, '\n'); + if (params_end) { + *params_end = '\0'; + } + + /* Check if the extracted line is not empty */ + if (strlen(params_start) > 0) { + /* Allocate and copy the parameters */ + line = xstrdup(params_start); + } + } + } + } + free(bootconfig_line); + } - line = slurp_proc_file("/proc/cmdline", &size); - if (!line || !size) - die("Failed to read /proc/cmdline\n"); + /* Fall back to reading /proc/cmdline if we didn't get a line from bootconfig */ + if (!line) { + line = slurp_proc_file("/proc/cmdline", &size); + if (!line || !size) + die("Failed to read /proc/cmdline\n"); - /* strip newline */ - line[size-1] = '\0'; + /* strip newline */ + line[size-1] = '\0'; + } p = strpbrk(line, "\r\n"); if (p) -- 2.47.3