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


Reply via email to