]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Fix bunch of memory problems and implement hdbias
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 12 Sep 2010 12:01:02 +0000 (14:01 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 12 Sep 2010 12:01:02 +0000 (14:01 +0200)
grub-core/commands/legacycfg.c
grub-core/lib/legacy_parse.c
util/grub-menulst2cfg.c

index 82901b0e7be7f06a9faa642fc1b180b350117b0d..e42ca5878a100b658bf68434d1e9e6ece80b3b6e 100644 (file)
@@ -30,6 +30,8 @@
 #include <grub/legacy_parse.h>
 #include <grub/crypto.h>
 #include <grub/auth.h>
+#include <grub/disk.h>
+#include <grub/partition.h>
 
 static grub_err_t
 legacy_file (const char *filename)
@@ -67,7 +69,7 @@ legacy_file (const char *filename)
   while (1)
     {
       char *buf = grub_file_getline (file);
-      char *parsed;
+      char *parsed = NULL;
 
       if (!buf && grub_errno)
        {
@@ -84,7 +86,7 @@ legacy_file (const char *filename)
 
        oldname = entryname;
        parsed = grub_legacy_parse (buf, &entryname, &is_suffix);
-       grub_free (buf);
+       buf = NULL;
        if (is_suffix)
          {
            char *t;
@@ -100,7 +102,7 @@ legacy_file (const char *filename)
                grub_free (suffix);
                return grub_errno;
              }
-           grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed,
+           grub_memcpy (suffix + grub_strlen (suffix), parsed,
                         grub_strlen (parsed) + 1);
            grub_free (parsed);
            parsed = NULL;
@@ -117,6 +119,9 @@ legacy_file (const char *filename)
            args[0] = oldname;
            grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL,
                                        entrysrc);
+           grub_free (args);
+           entrysrc[0] = 0;
+           grub_free (oldname);
          }
       }
 
@@ -125,6 +130,7 @@ legacy_file (const char *filename)
          grub_normal_parse_line (parsed, getline);
          grub_print_error ();
          grub_free (parsed);
+         parsed = NULL;
        }
       else if (parsed)
        {
@@ -163,11 +169,13 @@ legacy_file (const char *filename)
        }
       args[0] = entryname;
       grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, entrysrc);
+      grub_free (args);
     }
 
   grub_normal_parse_line (suffix, getline);
   grub_print_error ();
   grub_free (suffix);
+  grub_free (entrysrc);
 
   if (menu && menu->size)
     grub_show_menu (menu, 1);
@@ -215,6 +223,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
   struct grub_command *cmd;
   char **cutargs;
   int cutargc;
+  
   for (i = 0; i < 2; i++)
     {
       /* FIXME: really support this.  */
@@ -309,46 +318,118 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
          grub_errno = GRUB_ERR_NONE;
        }
 
-      /* k*BSD didn't really work well with grub-legacy.  */
-      if (kernel_type == GUESS_IT || kernel_type == KFREEBSD)
+      {
+       int bsd_device = -1;
+       int bsd_slice = -1;
+       int bsd_part = -1;
        {
-         cmd = grub_command_find ("kfreebsd");
-         if (cmd)
+         grub_device_t dev;
+         char *hdbiasstr;
+         int hdbias = 0;
+         hdbiasstr = grub_env_get ("legacy_hdbias");
+         if (hdbiasstr)
            {
-             if (!(cmd->func) (cmd, cutargc, cutargs))
+             hdbias = grub_strtoul (hdbiasstr, 0, 0);
+             grub_errno = GRUB_ERR_NONE;
+           }
+         dev = grub_device_open (0);
+         if (dev && dev->disk
+             && dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID
+             && dev->disk->dev->id >= 0x80 && dev->disk->dev->id <= 0x90)
+           {
+             struct grub_partition *part = dev->disk->partition;
+             bsd_device = dev->disk->id - 0x80 - hdbias;
+             if (part && (grub_strcmp (part->partmap->name, "netbsd") == 0
+                          || grub_strcmp (part->partmap->name, "openbsd") == 0
+                          || grub_strcmp (part->partmap->name, "bsd") == 0))
                {
-                 kernel_type = KFREEBSD;
-                 return GRUB_ERR_NONE;
+                 bsd_part = part->number;
+                 part = part->parent;
                }
+             if (part && grub_strcmp (part->partmap->name, "msdos") == 0)
+               bsd_slice = part->number;
            }
-         grub_errno = GRUB_ERR_NONE;
        }
-      if (kernel_type == GUESS_IT || kernel_type == KNETBSD)
+       
+       /* k*BSD didn't really work well with grub-legacy.  */
+       if (kernel_type == GUESS_IT || kernel_type == KFREEBSD)
+         {
+           char buf[sizeof("adXXXXXXXXXXXXsXXXXXXXXXXXXYYY")];
+           if (bsd_device != -1)
+             {
+               if (bsd_slice != -1 && bsd_part != -1)
+                 grub_snprintf(buf, sizeof(buf), "ad%ds%d%c", bsd_device,
+                               bsd_slice, 'a' + bsd_part);
+               else if (bsd_slice != -1)
+                 grub_snprintf(buf, sizeof(buf), "ad%ds%d", bsd_device,
+                               bsd_slice);
+               else
+                 grub_snprintf(buf, sizeof(buf), "ad%d", bsd_device);
+               grub_env_set ("kFreeBSD.vfs.root.mountfrom", buf);
+             }
+           else
+             grub_env_unset ("kFreeBSD.vfs.root.mountfrom");
+           cmd = grub_command_find ("kfreebsd");
+           if (cmd)
+             {
+               if (!(cmd->func) (cmd, cutargc, cutargs))
+                 {
+                   kernel_type = KFREEBSD;
+                   return GRUB_ERR_NONE;
+                 }
+             }
+           grub_errno = GRUB_ERR_NONE;
+         }
        {
-         cmd = grub_command_find ("knetbsd");
-         if (cmd)
+         char **bsdargs;
+         int bsdargc;
+         char bsddevname[sizeof ("wdXXXXXXXXXXXXY")];
+         if (bsd_device == -1)
            {
-             if (!(cmd->func) (cmd, cutargc, cutargs))
+             bsdargs = cutargs;
+             bsdargc = cutargc;
+           }
+         else
+           {
+             bsdargc = cutargc + 2;
+             bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc);
+             grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0]));
+             bsdargs[argc] = "-r";
+             bsdargs[argc + 1] = bsddevname;
+             grub_snprintf (bsddevname, sizeof (bsddevname),
+                            "wd%d%c", bsd_device,
+                            bsd_part != -1 ? bsd_part + 'a' : 'c');
+           }
+         if (kernel_type == GUESS_IT || kernel_type == KNETBSD)
+           {
+             cmd = grub_command_find ("knetbsd");
+             if (cmd)
                {
-                 kernel_type = KNETBSD;
-                 return GRUB_ERR_NONE;
+                 if (!(cmd->func) (cmd, bsdargc, bsdargs))
+                   {
+                     kernel_type = KNETBSD;
+                     return GRUB_ERR_NONE;
+                   }
                }
+             grub_errno = GRUB_ERR_NONE;
            }
-         grub_errno = GRUB_ERR_NONE;
-       }
-      if (kernel_type == GUESS_IT || kernel_type == KOPENBSD)
-       {
-         cmd = grub_command_find ("kopenbsd");
-         if (cmd)
+         if (kernel_type == GUESS_IT || kernel_type == KOPENBSD)
            {
-             if (!(cmd->func) (cmd, cutargc, cutargs))
+             cmd = grub_command_find ("kopenbsd");
+             if (cmd)
                {
-                 kernel_type = KOPENBSD;
-                 return GRUB_ERR_NONE;
+                 if (!(cmd->func) (cmd, bsdargc, bsdargs))
+                   {
+                     kernel_type = KOPENBSD;
+                     return GRUB_ERR_NONE;
+                   }
                }
+             grub_errno = GRUB_ERR_NONE;
            }
-         grub_errno = GRUB_ERR_NONE;
+         if (bsdargs != cutargs)
+           grub_free (bsdargs);
        }
+      }
     }
   while (0);
 
index dabc497bee68b114e91aa66a897560de029367c6..01b836087fae47149fa278adc95ecf337dbb0b15 100644 (file)
@@ -195,7 +195,9 @@ struct legacy_command legacy_commands[] =
     {"reboot", "reboot\n", 0, {}, 0, 0, "Reboot your system."},
     /* FIXME: Support HDBIAS.  */
     /* FIXME: Support printing.  */
-    {"root", "set root='%s'\n", 1, {TYPE_PARTITION}, 0, "[DEVICE [HDBIAS]]",
+    {"root", "set root='%s'; set legacy_hdbias='%s'\n",
+     2, {TYPE_PARTITION, TYPE_INT}, 0,
+     "[DEVICE [HDBIAS]]",
      "Set the current \"root device\" to the device DEVICE, then"
      " attempt to mount it to get the partition size (for passing the"
      " partition descriptor in `ES:ESI', used by some chain-loaded"
@@ -206,7 +208,8 @@ struct legacy_command legacy_commands[] =
      " how many BIOS drive numbers are on controllers before the current"
      " one. For example, if there is an IDE disk and a SCSI disk, and your"
      " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS."},
-    {"rootnoverify", "set root='%s'\n", 1, {TYPE_PARTITION}, 0,
+    {"rootnoverify", "set root='%s'; set legacy_hdbias='%s'\n",
+     2, {TYPE_PARTITION, TYPE_INT}, 0,
      "[DEVICE [HDBIAS]]",
      "Similar to `root', but don't attempt to mount the partition. This"
      " is useful for when an OS is outside of the area of the disk that"
@@ -265,7 +268,7 @@ grub_legacy_escape (const char *in, grub_size_t len)
   for (ptr = in; ptr < in + len && *ptr; ptr++)
     if (*ptr == '\'' || *ptr == '\\')
       overhead++;
-  ret = grub_malloc (ptr - in + overhead);
+  ret = grub_malloc (ptr - in + overhead + 1);
   if (!ret)
     return NULL;
   outptr = ret;
@@ -371,7 +374,15 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix)
 
   for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++);
   if (!*ptr || *ptr == '#')
-    return grub_strdup (buf);
+    {
+      char *ret;
+      int len = grub_strlen (buf);
+      ret = grub_malloc (len + 2);
+      grub_memcpy (ret, buf, len);
+      ret[len] = '\n';
+      ret[len + 1] = 0;
+      return ret;
+    }
 
   cmdname = ptr;
   for (ptr = buf; *ptr && !grub_isspace (*ptr) && *ptr != '='; ptr++);
@@ -412,7 +423,7 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix)
     unsigned j = 0;
     int hold_arg = 0;
     const char *curarg = NULL; 
-    for (i = 0; i < legacy_commands[cmdnum].argc; i++)
+    for (i = 0; i < legacy_commands[cmdnum].argc + hold_arg; i++)
       {
        grub_size_t curarglen;
        if (hold_arg)
@@ -495,7 +506,7 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix)
                args[j++] = grub_strndup (curarg, curarglen);
                break;
              }
-           args[j++] = "";
+           args[j++] = grub_strdup ("");
            hold_arg = 1;
            break;
          case TYPE_INT:
@@ -536,7 +547,14 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix)
          }
       }
   }
-  
-  return grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], args[2],
-                        args[3]);
+
+  {
+    char *ret = grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1],
+                               args[2], args[3]);
+    grub_free (args[0]);
+    grub_free (args[1]);
+    grub_free (args[2]);
+    grub_free (args[3]);
+    return ret;
+  }
 }
index 0184b3fe3844c20fe16e144b4ee17e756b80b7d1..38a906c0a033db550ac3aee7d4b5c1c1e6f8e7b1 100644 (file)
@@ -88,12 +88,18 @@ main (int argc, char **argv)
        if (oldname != entryname && oldname)
          fprintf (out, "}\n\n");
        if (oldname != entryname)
-         fprintf (out, "menuentry \'%s\' {\n",
-                  grub_legacy_escape (entryname, strlen (entryname)));
+         {
+           char *escaped = grub_legacy_escape (entryname, strlen (entryname));
+           fprintf (out, "menuentry \'%s\' {\n", escaped);
+           grub_free (escaped);
+           grub_free (oldname);
+         }
       }
 
       if (parsed)
        fprintf (out, "%s%s", entryname ? "  " : "", parsed);
+      grub_free (parsed);
+      parsed = NULL;
     }
 
   if (entryname)
@@ -101,6 +107,10 @@ main (int argc, char **argv)
 
   fwrite (out, 1, suffixlen, suffix);
 
+  grub_free (buf);
+  grub_free (suffix);
+  grub_free (entryname);
+
   if (in != stdin)
     fclose (in);
   if (out != stdout)