]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Improve loaders' kernel command line handling.
authorSzymon Janc <szymon@janc.net.pl>
Fri, 7 Jan 2011 16:09:39 +0000 (17:09 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Fri, 7 Jan 2011 16:09:39 +0000 (17:09 +0100)
* grub-core/lib/cmdline.c: New file.
* include/grub/lib/cmdline.h: Likewise.
* grub-core/loader/i386/linux.c (grub_cmd_linux): Use
grub_create_loader_cmdline to create kernel command line.
* grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Likewise.
* grub-core/loader/powerpc/ieee1275/linux.c (grub_cmd_linux): Likewise.
* grub-core/loader/sparc64/ieee1275/linux.c (grub_cmd_linux): Likewise.
* grub-core/Makefile.core.def (linux16): Add lib/cmdline.c on i386_pc.
(linux): Add lib/cmdline.c on common.

ChangeLog
grub-core/Makefile.core.def
grub-core/lib/cmdline.c [new file with mode: 0644]
grub-core/loader/i386/linux.c
grub-core/loader/i386/pc/linux.c
grub-core/loader/powerpc/ieee1275/linux.c
grub-core/loader/sparc64/ieee1275/linux.c
include/grub/lib/cmdline.h [new file with mode: 0644]

index ca63b0e8538d560897f331cf62f3362aa1791b6f..d1ddc8741bbebe5be5b60d792093bb259716dbd4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2011-01-07  Szymon Janc <szymon@janc.net.pl>
+
+       Improve loaders' kernel command line handling.
+
+       * grub-core/lib/cmdline.c: New file.
+       * include/grub/lib/cmdline.h: Likewise.
+       * grub-core/loader/i386/linux.c (grub_cmd_linux): Use
+       grub_create_loader_cmdline to create kernel command line.
+       * grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Likewise.
+       * grub-core/loader/powerpc/ieee1275/linux.c (grub_cmd_linux): Likewise.
+       * grub-core/loader/sparc64/ieee1275/linux.c (grub_cmd_linux): Likewise.
+       * grub-core/Makefile.core.def (linux16): Add lib/cmdline.c on i386_pc.
+       (linux): Add lib/cmdline.c on common.
+
 2011-01-07  Vladimir Serbinenko  <phcoder@gmail.com>
 
        * grub-core/fs/xfs.c (grub_xfs_iterate_dir): Take into account that
index 37c0ce9702a95ce77f78174ff5ca47452d13bf92..094bbc83510a71070d20eef064f8f9524b0199d1 100644 (file)
@@ -1149,6 +1149,7 @@ module = {
 module = {
   name = linux16;
   i386_pc = loader/i386/pc/linux.c;
+  i386_pc = lib/cmdline.c;
   enable = i386_pc;
 };
 
@@ -1183,6 +1184,7 @@ module = {
   mips = loader/mips/linux.c;
   powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c;
   sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c;
+  common = lib/cmdline.c;
   enable = noemu;
 };
 
diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c
new file mode 100644 (file)
index 0000000..a702e64
--- /dev/null
@@ -0,0 +1,105 @@
+/* cmdline.c - linux command line handling */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2010  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/lib/cmdline.h>
+#include <grub/misc.h>
+
+static unsigned int check_arg (char *c, int *has_space)
+{
+  int space = 0;
+  unsigned int size = 0;
+
+  while (*c)
+    {
+      if (*c == '\\' || *c == '\'' || *c == '"')
+       size++;
+      else if (*c == ' ')
+       space = 1;
+
+      size++;
+      c++;
+    }
+
+  if (space)
+    size += 2;
+
+  if (has_space)
+    *has_space = space;
+
+  return size;
+}
+
+unsigned int grub_loader_cmdline_size (int argc, char *argv[])
+{
+  int i;
+  unsigned int size = 0;
+
+  for (i = 0; i < argc; i++)
+    {
+      size += check_arg (argv[i], 0);
+      size++; /* Separator space or NULL.  */
+    }
+
+  return size;
+}
+
+int grub_create_loader_cmdline (int argc, char *argv[], char *buf,
+                               grub_size_t size)
+{
+  int i, space;
+  unsigned int arg_size;
+  char *c;
+
+  for (i = 0; i < argc; i++)
+    {
+      c = argv[i];
+      arg_size = check_arg(argv[i], &space);
+      arg_size++; /* Separator space or NULL.  */
+
+      if (size < arg_size)
+       break;
+
+      size -= arg_size;
+
+      if (space)
+       *buf++ = '"';
+
+      while (*c)
+       {
+         if (*c == '\\' || *c == '\'' || *c == '"')
+           *buf++ = '\\';
+
+         *buf++ = *c;
+         c++;
+       }
+
+      if (space)
+       *buf++ = '"';
+
+      *buf++ = ' ';
+    }
+
+  /* Replace last space with null.  */
+  if (i)
+    buf--;
+
+  *buf = 0;
+
+  return i;
+}
index ca88c7403ec4eff6ce05b421a3d8ca8dced3f4e3..80f583cefaf7b6fbe6cfc351e51c4ac7114f5fd6 100644 (file)
@@ -33,6 +33,7 @@
 #include <grub/command.h>
 #include <grub/i386/relocator.h>
 #include <grub/i18n.h>
+#include <grub/lib/cmdline.h>
 
 #ifdef GRUB_MACHINE_PCBIOS
 #include <grub/i386/pc/vesa_modes_table.h>
@@ -575,7 +576,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   grub_size_t real_size, prot_size;
   grub_ssize_t len;
   int i;
-  char *dest;
 
   grub_dl_ref (my_mod);
 
@@ -836,22 +836,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
        params->loadflags |= GRUB_LINUX_FLAG_QUIET;
       }
 
-
-  /* Specify the boot file.  */
-  dest = grub_stpcpy ((char *) real_mode_mem + GRUB_LINUX_CL_OFFSET,
-                     "BOOT_IMAGE=");
-  dest = grub_stpcpy (dest, argv[0]);
-
-  /* Copy kernel parameters.  */
-  for (i = 1;
-       i < argc
-        && dest + grub_strlen (argv[i]) + 1 < ((char *) real_mode_mem
-                                               + GRUB_LINUX_CL_END_OFFSET);
-       i++)
-    {
-      *dest++ = ' ';
-      dest = grub_stpcpy (dest, argv[i]);
-    }
+  /* Create kernel command line.  */
+  grub_memcpy ((char *)real_mode_mem + GRUB_LINUX_CL_OFFSET, LINUX_IMAGE,
+             sizeof (LINUX_IMAGE));
+  grub_create_loader_cmdline (argc, argv,
+                             (char *)real_mode_mem + GRUB_LINUX_CL_OFFSET
+                             + sizeof (LINUX_IMAGE) - 1,
+                             GRUB_LINUX_CL_END_OFFSET - GRUB_LINUX_CL_OFFSET
+                             - (sizeof (LINUX_IMAGE) - 1));
 
   len = prot_size;
   if (grub_file_read (file, prot_mode_mem, len) != len)
index 90de70f66478552bda3b4196db393e2f2fc25d21..96d00f927195bd16ef56ca2f6a0116e386ff14ca 100644 (file)
@@ -34,6 +34,7 @@
 #include <grub/cpu/relocator.h>
 #include <grub/video.h>
 #include <grub/i386/floppy.h>
+#include <grub/lib/cmdline.h>
 
 #define GRUB_LINUX_CL_OFFSET           0x9000
 #define GRUB_LINUX_CL_END_OFFSET       0x90FF
@@ -86,7 +87,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   grub_size_t real_size;
   grub_ssize_t len;
   int i;
-  char *dest;
   char *grub_linux_prot_chunk;
   int grub_linux_is_bzimage;
   grub_addr_t grub_linux_prot_target;
@@ -286,21 +286,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
                 ((GRUB_LINUX_MAX_SETUP_SECTS - setup_sects - 1)
                  << GRUB_DISK_SECTOR_BITS));
 
-  /* Specify the boot file.  */
-  dest = grub_stpcpy (grub_linux_real_chunk + GRUB_LINUX_CL_OFFSET,
-                     "BOOT_IMAGE=");
-  dest = grub_stpcpy (dest, argv[0]);
-
-  /* Copy kernel parameters.  */
-  for (i = 1;
-       i < argc
-        && dest + grub_strlen (argv[i]) + 1 < (grub_linux_real_chunk
-                                               + GRUB_LINUX_CL_END_OFFSET);
-       i++)
-    {
-      *dest++ = ' ';
-      dest = grub_stpcpy (dest, argv[i]);
-    }
+  /* Create kernel command line.  */
+  grub_memcpy ((char *)grub_linux_real_chunk + GRUB_LINUX_CL_OFFSET,
+               LINUX_IMAGE, sizeof (LINUX_IMAGE));
+  grub_create_loader_cmdline (argc, argv,
+                             (char *)grub_linux_real_chunk
+                             + GRUB_LINUX_CL_OFFSET + sizeof (LINUX_IMAGE) - 1,
+                             GRUB_LINUX_CL_END_OFFSET - GRUB_LINUX_CL_OFFSET
+                             - (sizeof (LINUX_IMAGE) - 1));
 
   if (grub_linux_is_bzimage)
     grub_linux_prot_target = GRUB_LINUX_BZIMAGE_ADDR;
index 231aec1d34ccd4f1323ddf8fd6a088de296bbdbd..a99310cfda727b2b7e0e1b93bef07c54d495b4ac 100644 (file)
@@ -27,6 +27,7 @@
 #include <grub/command.h>
 #include <grub/i18n.h>
 #include <grub/memory.h>
+#include <grub/lib/cmdline.h>
 
 #define ELF32_LOADMASK (0xc0000000UL)
 #define ELF64_LOADMASK (0xc000000000000000ULL)
@@ -238,9 +239,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
                int argc, char *argv[])
 {
   grub_elf_t elf = 0;
-  int i;
   int size;
-  char *dest;
 
   grub_dl_ref (my_mod);
 
@@ -275,23 +274,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
       goto out;
     }
 
-  size = sizeof ("BOOT_IMAGE=") + grub_strlen (argv[0]);
-  for (i = 0; i < argc; i++)
-    size += grub_strlen (argv[i]) + 1;
-
-  linux_args = grub_malloc (size);
+  size = grub_loader_cmdline_size(argc, argv);
+  linux_args = grub_malloc (size + sizeof (LINUX_IMAGE));
   if (! linux_args)
     goto out;
 
-  /* Specify the boot file.  */
-  dest = grub_stpcpy (linux_args, "BOOT_IMAGE=");
-  dest = grub_stpcpy (dest, argv[0]);
-
-  for (i = 1; i < argc; i++)
-    {
-      *dest++ = ' ';
-      dest = grub_stpcpy (dest, argv[i]);
-    }
+  /* Create kernel command line.  */
+  grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
+  grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1,
+                             size);
 
 out:
 
index 8ea96f1c984f27efba4cd3a83b34e6ab8cc143a5..a262049a70ec28e868d15d46f2953a24993d886a 100644 (file)
@@ -27,6 +27,7 @@
 #include <grub/command.h>
 #include <grub/i18n.h>
 #include <grub/memory.h>
+#include <grub/lib/cmdline.h>
 
 static grub_dl_t my_mod;
 
@@ -295,9 +296,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 {
   grub_file_t file = 0;
   grub_elf_t elf = 0;
-  int i;
   int size;
-  char *dest;
 
   grub_dl_ref (my_mod);
 
@@ -333,23 +332,16 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
       goto out;
     }
 
-  size = sizeof ("BOOT_IMAGE=") + grub_strlen (argv[0]);
-  for (i = 0; i < argc; i++)
-    size += grub_strlen (argv[i]) + 1;
+  size = grub_loader_cmdline_size(argc, argv);
 
-  linux_args = grub_malloc (size);
+  linux_args = grub_malloc (size + sizeof (LINUX_IMAGE));
   if (! linux_args)
     goto out;
 
-  /* Specify the boot file.  */
-  dest = grub_stpcpy (linux_args, "BOOT_IMAGE=");
-  dest = grub_stpcpy (dest, argv[0]);
-
-  for (i = 1; i < argc; i++)
-    {
-      *dest++ = ' ';
-      dest = grub_stpcpy (dest, argv[i]);
-    }
+  /* Create kernel command line.  */
+  grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
+  grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1,
+                             size);
 
 out:
   if (elf)
diff --git a/include/grub/lib/cmdline.h b/include/grub/lib/cmdline.h
new file mode 100644 (file)
index 0000000..1fe8d01
--- /dev/null
@@ -0,0 +1,31 @@
+/* cmdline.h - linux command line handling */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2010  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CMDLINE_HEADER
+#define GRUB_CMDLINE_HEADER    1
+
+#include <grub/types.h>
+
+#define LINUX_IMAGE "BOOT_IMAGE="
+
+unsigned int grub_loader_cmdline_size (int argc, char *argv[]);
+int grub_create_loader_cmdline (int argc, char *argv[], char *buf,
+                               grub_size_t size);
+
+#endif /* ! GRUB_CMDLINE_HEADER */