This patch increases the kernel command line size for x86_64 and i386
to 2048 characters. This is necessary because with kernel 2.6.21
and newer, the kernel command line size has increased and kexec needs
lot of command line space, so this solves some "command line overflow"
problems.

To be able to warn users running older kernels that the command line
is too long (and don't wait that the kernel truncates it), the
patch tries to get the kernel command line length from the kernel
image that is loaded if possible by checking the length of the
static array that holds the kernel command line when booting.

If this is not possible or the command line is not in the range
[256; 2048], the default value is used (2048).

The patch is against kexec-tools-testing from Simon Horman.

Signed-off-by: Bernhard Walle <[EMAIL PROTECTED]>

---
 include/x86/x86-linux.h              |    8 ++-----
 kexec/arch/i386/crashdump-x86.c      |   36 ++++++++++++++++++++++++++++++++---
 kexec/arch/i386/crashdump-x86.h      |    5 ++++
 kexec/arch/i386/kexec-bzImage.c      |    8 +++----
 kexec/arch/i386/kexec-elf-x86.c      |    8 +++----
 kexec/arch/i386/x86-linux-setup.c    |    6 +++--
 kexec/arch/x86_64/crashdump-x86_64.c |   35 +++++++++++++++++++++++++++++++---
 kexec/arch/x86_64/crashdump-x86_64.h |    3 ++
 kexec/arch/x86_64/kexec-elf-x86_64.c |   11 ++++++----
 9 files changed, 95 insertions(+), 25 deletions(-)

Index: kexec-tools-snap/include/x86/x86-linux.h
===================================================================
--- kexec-tools-snap.orig/include/x86/x86-linux.h
+++ kexec-tools-snap/include/x86/x86-linux.h
@@ -148,14 +148,12 @@ struct x86_linux_param_header {
 #endif
        struct e820entry e820_map[E820MAX];     /* 0x2d0 */
                                                /* 0x550 */
-#define COMMAND_LINE_SIZE 256
+#define COMMAND_LINE_SIZE 2048
 };
 
 struct x86_linux_faked_param_header {
-       struct x86_linux_param_header hdr;      /* 0x00 */
-       uint8_t reserved16[688];                /* 0x550 */
-       uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */
-       uint8_t reserved17[1792];               /* 0x900 - 0x1000 */
+       struct x86_linux_param_header hdr;
+       uint8_t command_line[COMMAND_LINE_SIZE];
 };
 
 struct x86_linux_header {
Index: kexec-tools-snap/kexec/arch/i386/crashdump-x86.c
===================================================================
--- kexec-tools-snap.orig/kexec/arch/i386/crashdump-x86.c
+++ kexec-tools-snap/kexec/arch/i386/crashdump-x86.c
@@ -46,6 +46,36 @@ static struct memory_range crash_memory_
 /* Memory region reserved for storing panic kernel and other data. */
 static struct memory_range crash_reserved_mem;
 
+/* real length of the command line from the kernel image, needed because
+ * command line size on x86-64 was increased recently in -mm tree */
+int real_command_line_size = COMMAND_LINE_SIZE;
+
+
+/* Tries to read the kernel command line size from the symbol table
+ * of the ELF kernel binary. */
+void set_command_line_size(struct mem_ehdr *ehdr)
+{
+       int ret;
+       struct mem_sym mem_sym;
+
+       /* > 2.6.20-rc6-mm */
+       ret = elf_rel_find_symbol(ehdr, "saved_command_line", &mem_sym);
+       if (ret != 0) {
+               /* older kernel */
+               ret = elf_rel_find_symbol(ehdr, "boot_command_line", &mem_sym);
+               if (ret != 0) {
+                       return;
+               }
+       }
+
+       /* current -mm kernel */
+       if (mem_sym.st_size >= 256 && mem_sym.st_size < COMMAND_LINE_SIZE) {
+               real_command_line_size = mem_sym.st_size;
+               return;
+       }
+}
+
+
 /* Reads the appropriate file and retrieves the SYSTEM RAM regions for whom to
  * create Elf headers. Keeping it separate from get_memory_ranges() as
  * requirements are different in the case of normal kexec and crashdumps.
@@ -363,7 +393,7 @@ static int cmdline_add_memmap(char *cmdl
        strcpy(str_mmap, " memmap=exactmap");
        len = strlen(str_mmap);
        cmdlen = strlen(cmdline) + len;
-       if (cmdlen > (COMMAND_LINE_SIZE - 1))
+       if (cmdlen > (real_command_line_size - 1))
                die("Command line overflow\n");
        strcat(cmdline, str_mmap);
 
@@ -388,7 +418,7 @@ static int cmdline_add_memmap(char *cmdl
                strcat (str_mmap, "K");
                len = strlen(str_mmap);
                cmdlen = strlen(cmdline) + len;
-               if (cmdlen > (COMMAND_LINE_SIZE - 1))
+               if (cmdlen > (real_command_line_size - 1))
                        die("Command line overflow\n");
                strcat(cmdline, str_mmap);
        }
@@ -418,7 +448,7 @@ static int cmdline_add_elfcorehdr(char *
        strcat(str, "K");
        len = strlen(str);
        cmdlen = strlen(cmdline) + len;
-       if (cmdlen > (COMMAND_LINE_SIZE - 1))
+       if (cmdlen > (real_command_line_size - 1))
                die("Command line overflow\n");
        strcat(cmdline, str);
 #if 0
Index: kexec-tools-snap/kexec/arch/i386/crashdump-x86.h
===================================================================
--- kexec-tools-snap.orig/kexec/arch/i386/crashdump-x86.h
+++ kexec-tools-snap/kexec/arch/i386/crashdump-x86.h
@@ -2,8 +2,11 @@
 #define CRASHDUMP_X86_H
 
 struct kexec_info;
+struct mem_ehdr;
 int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline,
                                unsigned long max_addr, unsigned long min_base);
+void set_command_line_size(struct mem_ehdr *ehdr);
+
 
 #define PAGE_OFFSET    0xc0000000
 #define __pa(x)                ((unsigned long)(x)-PAGE_OFFSET)
@@ -19,4 +22,6 @@ int load_crashdump_segments(struct kexec
 #define BACKUP_SRC_END         0x0009ffff
 #define BACKUP_SRC_SIZE        (BACKUP_SRC_END - BACKUP_SRC_START + 1)
 
+extern int real_command_line_size;
+
 #endif /* CRASHDUMP_X86_H */
Index: kexec-tools-snap/kexec/arch/x86_64/crashdump-x86_64.c
===================================================================
--- kexec-tools-snap.orig/kexec/arch/x86_64/crashdump-x86_64.c
+++ kexec-tools-snap/kexec/arch/x86_64/crashdump-x86_64.c
@@ -50,6 +50,35 @@ static struct crash_elf_info elf_info =
 /* Forward Declaration. */
 static int exclude_crash_reserve_region(int *nr_ranges);
 
+/* real length of the command line from the kernel image, needed because
+ * command line size on x86-64 was increased recently in -mm tree */
+int real_command_line_size = COMMAND_LINE_SIZE;
+
+
+/* Tries to read the kernel command line size from the symbol table
+ * of the ELF kernel binary. */
+void set_command_line_size(struct mem_ehdr *ehdr)
+{
+       int ret;
+       struct mem_sym mem_sym;
+
+       /* > 2.6.20-rc6-mm */
+       ret = elf_rel_find_symbol(ehdr, "saved_command_line", &mem_sym);
+       if (ret != 0) {
+               /* older kernel */
+               ret = elf_rel_find_symbol(ehdr, "boot_command_line", &mem_sym);
+               if (ret != 0) {
+                       return;
+               }
+       }
+
+       /* current -mm kernel */
+       if (mem_sym.st_size >= 256 && mem_sym.st_size < COMMAND_LINE_SIZE) {
+               real_command_line_size = mem_sym.st_size;
+               return;
+       }
+}
+
 #define KERN_VADDR_ALIGN       0x100000        /* 1MB */
 
 /* Read kernel physical load addr from /proc/iomem (Kernel Code) and
@@ -494,7 +523,7 @@ static int cmdline_add_memmap(char *cmdl
                strcat (str_mmap, "K");
                len = strlen(str_mmap);
                cmdlen = strlen(cmdline) + len;
-               if (cmdlen > (COMMAND_LINE_SIZE - 1))
+               if (cmdlen > (real_command_line_size - 1))
                        die("Command line overflow\n");
                strcat(cmdline, str_mmap);
        }
@@ -523,7 +552,7 @@ static int cmdline_add_elfcorehdr(char *
        strcat(str, "K");
        len = strlen(str);
        cmdlen = strlen(cmdline) + len;
-       if (cmdlen > (COMMAND_LINE_SIZE - 1))
+       if (cmdlen > (real_command_line_size - 1))
                die("Command line overflow\n");
        strcat(cmdline, str);
 #ifdef DEBUG
@@ -555,7 +584,7 @@ static int cmdline_add_memmap_acpi(char 
        strcat (str_mmap, "K");
        len = strlen(str_mmap);
        cmdlen = strlen(cmdline) + len;
-       if (cmdlen > (COMMAND_LINE_SIZE - 1))
+       if (cmdlen > (real_command_line_size - 1))
                die("Command line overflow\n");
        strcat(cmdline, str_mmap);
 
Index: kexec-tools-snap/kexec/arch/x86_64/crashdump-x86_64.h
===================================================================
--- kexec-tools-snap.orig/kexec/arch/x86_64/crashdump-x86_64.h
+++ kexec-tools-snap/kexec/arch/x86_64/crashdump-x86_64.h
@@ -3,6 +3,7 @@
 
 int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline,
                                unsigned long max_addr, unsigned long min_base);
+void set_command_line_size(struct mem_ehdr *ehdr);
 
 #define __START_KERNEL_map      0xffffffff80000000UL
 #define PAGE_OFFSET            0xffff810000000000UL
@@ -21,4 +22,6 @@ int load_crashdump_segments(struct kexec
 #define BACKUP_SRC_END         0x0009ffff
 #define BACKUP_SRC_SIZE                (BACKUP_SRC_END - BACKUP_SRC_START + 1)
 
+extern int real_command_line_size;
+
 #endif /* CRASHDUMP_X86_64_H */
Index: kexec-tools-snap/kexec/arch/x86_64/kexec-elf-x86_64.c
===================================================================
--- kexec-tools-snap.orig/kexec/arch/x86_64/kexec-elf-x86_64.c
+++ kexec-tools-snap/kexec/arch/x86_64/kexec-elf-x86_64.c
@@ -166,12 +166,12 @@ int elf_x86_64_load(int argc, char **arg
         * taking crash dumps.
         */
        if (info->kexec_flags & KEXEC_ON_CRASH) {
-               modified_cmdline = xmalloc(COMMAND_LINE_SIZE);
-               memset((void *)modified_cmdline, 0, COMMAND_LINE_SIZE);
+               modified_cmdline = xmalloc(real_command_line_size);
+               memset((void *)modified_cmdline, 0, real_command_line_size);
                if (command_line) {
                        strncpy(modified_cmdline, command_line,
-                                               COMMAND_LINE_SIZE);
-                       modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
+                                               real_command_line_size);
+                       modified_cmdline[real_command_line_size - 1] = '\0';
                }
                modified_cmdline_len = strlen(modified_cmdline);
        }
@@ -182,6 +182,9 @@ int elf_x86_64_load(int argc, char **arg
        entry = ehdr.e_entry;
        max_addr = elf_max_addr(&ehdr);
 
+       /* try to set the command line size correctly */
+       set_command_line_size(&ehdr);
+
        /* Do we want arguments? */
        if (arg_style != ARG_STYLE_NONE) {
                /* Load the setup code */
Index: kexec-tools-snap/kexec/arch/i386/kexec-bzImage.c
===================================================================
--- kexec-tools-snap.orig/kexec/arch/i386/kexec-bzImage.c
+++ kexec-tools-snap/kexec/arch/i386/kexec-bzImage.c
@@ -156,12 +156,12 @@ int do_bzImage_load(struct kexec_info *i
         * taking crash dumps.
         */
        if (info->kexec_flags & KEXEC_ON_CRASH) {
-               modified_cmdline = xmalloc(COMMAND_LINE_SIZE);
-               memset((void *)modified_cmdline, 0, COMMAND_LINE_SIZE);
+               modified_cmdline = xmalloc(real_command_line_size);
+               memset((void *)modified_cmdline, 0, real_command_line_size);
                if (command_line) {
                        strncpy(modified_cmdline, command_line,
-                                       COMMAND_LINE_SIZE);
-                       modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
+                                       real_command_line_size);
+                       modified_cmdline[real_command_line_size - 1] = '\0';
                }
 
                /* If panic kernel is being loaded, additional segments need
Index: kexec-tools-snap/kexec/arch/i386/kexec-elf-x86.c
===================================================================
--- kexec-tools-snap.orig/kexec/arch/i386/kexec-elf-x86.c
+++ kexec-tools-snap/kexec/arch/i386/kexec-elf-x86.c
@@ -166,12 +166,12 @@ int elf_x86_load(int argc, char **argv, 
         * taking crash dumps.
         */
        if (info->kexec_flags & KEXEC_ON_CRASH) {
-               modified_cmdline = xmalloc(COMMAND_LINE_SIZE);
-               memset((void *)modified_cmdline, 0, COMMAND_LINE_SIZE);
+               modified_cmdline = xmalloc(real_command_line_size);
+               memset((void *)modified_cmdline, 0, real_command_line_size);
                if (command_line) {
                        strncpy(modified_cmdline, command_line,
-                                               COMMAND_LINE_SIZE);
-                       modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
+                                               real_command_line_size);
+                       modified_cmdline[real_command_line_size - 1] = '\0';
                }
                modified_cmdline_len = strlen(modified_cmdline);
        }
Index: kexec-tools-snap/kexec/arch/i386/x86-linux-setup.c
===================================================================
--- kexec-tools-snap.orig/kexec/arch/i386/x86-linux-setup.c
+++ kexec-tools-snap/kexec/arch/i386/x86-linux-setup.c
@@ -32,6 +32,8 @@
 #include "kexec-x86.h"
 #include "x86-linux-setup.h"
 
+extern int real_command_line_size;
+
 void init_linux_parameters(struct x86_linux_param_header *real_mode)
 {
        /* Fill in the values that are usually provided by the kernel. */
@@ -91,8 +93,8 @@ void setup_linux_bootloader_parameters(
        }
 
        /* Fill in the command line */
-       if (cmdline_len > COMMAND_LINE_SIZE) {
-               cmdline_len = COMMAND_LINE_SIZE;
+       if (cmdline_len > real_command_line_size) {
+               cmdline_len = real_command_line_size;
        }
        cmdline_ptr = ((char *)real_mode) + cmdline_offset;
        memcpy(cmdline_ptr, cmdline, cmdline_len);
_______________________________________________
fastboot mailing list
fastboot@lists.osdl.org
https://lists.osdl.org/mailman/listinfo/fastboot

Reply via email to