]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
fix several issues with nested labels
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Fri, 3 Sep 2010 22:49:45 +0000 (00:49 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Fri, 3 Sep 2010 22:49:45 +0000 (00:49 +0200)
Makefile.util.def
grub-core/Makefile.core.def
grub-core/partmap/bsdlabel.c
grub-core/partmap/msdos.c
grub-core/partmap/netbsdlabel.c [new file with mode: 0644]
grub-core/partmap/openbsdlabel.c [new file with mode: 0644]
include/grub/partition.h

index 35bcd81b2fecd49a99643ad3f2b53eae9d76f0e8..20224cf021711cee22b8ab4e7cd827c55bda6b48 100644 (file)
@@ -89,6 +89,9 @@ library = {
   common = grub-core/partmap/msdos.c;
   common = grub-core/partmap/sun.c;
   common = grub-core/partmap/sunpc.c;
+  common = grub-core/partmap/bsdlabel.c;
+  common = grub-core/partmap/netbsdlabel.c;
+  common = grub-core/partmap/openbsdlabel.c;
   common = grub-core/script/function.c;
   common = grub-core/script/lexer.c;
   common = grub-core/script/main.c;
index 353b9d123b65695401793e9fc43d7dc7bdb086af..4f28c54f4990761e8f0748f5b95110c87a914495 100644 (file)
@@ -1208,6 +1208,16 @@ module = {
   common = partmap/bsdlabel.c;
 };
 
+module = {
+  name = part_netbsd;
+  common = partmap/netbsdlabel.c;
+};
+
+module = {
+  name = part_openbsd;
+  common = partmap/openbsdlabel.c;
+};
+
 module = {
   name = part_sunpc;
   common = partmap/sunpc.c;
index a27b8eaecf0e30ef00cae8784cf2cfb7f5c2fe34..3d481843a019ed6469a4f47212bebaf9734f6603 100644 (file)
@@ -23,6 +23,7 @@
 #include <grub/mm.h>
 #include <grub/misc.h>
 #include <grub/dl.h>
+#include <grub/msdos_partition.h>
 
 #ifdef GRUB_UTIL
 #include <grub/util/misc.h>
@@ -32,9 +33,9 @@ static struct grub_partition_map grub_bsdlabel_partition_map;
 \f
 
 static grub_err_t
-bsdlabel_partition_map_iterate (grub_disk_t disk,
-                               int (*hook) (grub_disk_t disk,
-                                            const grub_partition_t partition))
+iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd,
+             int (*hook) (grub_disk_t disk,
+                          const grub_partition_t partition))
 {
   struct grub_partition_bsd_disk_label label;
   struct grub_partition p;
@@ -42,22 +43,27 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
   unsigned pos;
 
   /* Read the BSD label.  */
-  if (grub_disk_read (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR,
-                     0, sizeof (label), &label))
+  if (grub_disk_read (disk, sector, 0, sizeof (label), &label))
     return grub_errno;
 
   /* Check if it is valid.  */
   if (label.magic != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC))
-    return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
+    {
+      grub_dprintf ("partition",
+                   "bad signature (found 0x%08x, expected 0x%08x)\n",
+                   label.magic,
+                   grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC));
+      return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
+    }
 
   /* A kludge to determine a base of be.offset.  */
   if (GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION
-      < grub_cpu_to_le16 (label.num_partitions))
+      < grub_cpu_to_le16 (label.num_partitions) && freebsd)
     {
       struct grub_partition_bsd_entry whole_disk_be;
 
-      pos = sizeof (label) + GRUB_PC_PARTITION_BSD_LABEL_SECTOR
-       * GRUB_DISK_SECTOR_SIZE + sizeof (struct grub_partition_bsd_entry)
+      pos = sizeof (label) + sector * GRUB_DISK_SECTOR_SIZE
+       + sizeof (struct grub_partition_bsd_entry)
        * GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION;
 
       if (grub_disk_read (disk, pos / GRUB_DISK_SECTOR_SIZE,
@@ -68,8 +74,10 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
       delta = grub_le_to_cpu32 (whole_disk_be.offset);
     }
 
-  pos = sizeof (label) + GRUB_PC_PARTITION_BSD_LABEL_SECTOR
-    * GRUB_DISK_SECTOR_SIZE;
+  pos = sizeof (label) + sector * GRUB_DISK_SECTOR_SIZE;
+
+  grub_dprintf ("partition", "bsdlabel with %d partitions detected\n",
+               grub_cpu_to_le16 (label.num_partitions));
 
   for (p.number = 0;
        p.number < grub_cpu_to_le16 (label.num_partitions);
@@ -124,24 +132,112 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
       if (hook (disk, &p))
        return grub_errno;
     }
-
   return GRUB_ERR_NONE;
 }
 
+#if !defined (NETBSDLABEL) && !defined (OPENBSDLABEL)
+
+static grub_err_t
+bsdlabel_partition_map_iterate (grub_disk_t disk,
+                               int (*hook) (grub_disk_t disk,
+                                            const grub_partition_t partition))
+{
+
+  if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos")
+      == 0 && disk->partition->msdostype == GRUB_PC_PARTITION_TYPE_FREEBSD)
+    {
+      grub_dprintf ("partition", "FreeBSD embedded iterating\n");
+      return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 1,
+                          hook);
+    }
+
+  if (disk->partition 
+      && (grub_strcmp (disk->partition->partmap->name, "msdos") == 0
+         || grub_strcmp (disk->partition->partmap->name, "bsd") == 0
+         || grub_strcmp (disk->partition->partmap->name, "netbsd") == 0
+         || grub_strcmp (disk->partition->partmap->name, "openbsd") == 0))
+    {
+      grub_dprintf ("partition", "no embedded iterating\n");
+      return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");
+    }
+
+  return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, hook);
+}
+
+#else
+
+#ifdef OPENBSDLABEL
+#define GRUB_PC_PARTITION_TYPE_BSD GRUB_PC_PARTITION_TYPE_OPENBSD
+#else
+#define GRUB_PC_PARTITION_TYPE_BSD GRUB_PC_PARTITION_TYPE_NETBSD
+#endif
+
+static grub_err_t
+bsdlabel_partition_map_iterate (grub_disk_t disk,
+                               int (*hook) (grub_disk_t disk,
+                                            const grub_partition_t partition))
+{
+  grub_err_t err;
+
+  if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos")
+      == 0)
+    return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");
+
+  {
+    struct grub_msdos_partition_mbr mbr;
+    unsigned i;
+
+    err = grub_disk_read (disk, 0, 0, sizeof (mbr), &mbr);
+    if (err)
+      return err;
+
+    for (i = 0; i < ARRAY_SIZE (mbr.entries); i++)
+      if (mbr.entries[i].type == GRUB_PC_PARTITION_TYPE_BSD)
+       {
+         err = iterate_real (disk, mbr.entries[i].start
+                             + GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, hook);
+         if (err != GRUB_ERR_BAD_PART_TABLE)
+           return err;
+       }
+  }
+
+  return grub_error (GRUB_ERR_BAD_PART_TABLE, "no bsdlabel found");
+}
+
+#endif
+
 \f
 /* Partition map type.  */
 static struct grub_partition_map grub_bsdlabel_partition_map =
   {
+#if defined (OPENBSDLABEL)
+    .name = "openbsd",
+#elif defined (NETBSDLABEL)
+    .name = "netbsd",
+#else
     .name = "bsd",
+#endif
     .iterate = bsdlabel_partition_map_iterate,
   };
 
+#if defined (OPENBSDLABEL)
+GRUB_MOD_INIT(part_openbsd)
+#elif defined (NETBSDLABEL)
+GRUB_MOD_INIT(part_netbsd)
+#else
 GRUB_MOD_INIT(part_bsd)
+#endif
 {
   grub_partition_map_register (&grub_bsdlabel_partition_map);
 }
 
+#if defined (OPENBSDLABEL)
+GRUB_MOD_FINI(part_openbsd)
+#elif defined (NETBSDLABEL)
+GRUB_MOD_FINI(part_netbsd)
+#else
 GRUB_MOD_FINI(part_bsd)
+#endif
 {
   grub_partition_map_unregister (&grub_bsdlabel_partition_map);
 }
index 3898d09fac2812ae3913638fa81897678b97fb68..02105e622564613021b19f2ef8cab6986f4f39cc 100644 (file)
@@ -37,6 +37,15 @@ pc_partition_map_iterate (grub_disk_t disk,
   int labeln = 0;
   grub_disk_addr_t lastaddr;
   grub_disk_addr_t ext_offset;
+  grub_disk_addr_t delta = 0;
+
+  if (disk->partition && disk->partition->partmap == &grub_msdos_partition_map)
+    {
+      if (disk->partition->msdostype == GRUB_PC_PARTITION_TYPE_LINUX_MINIX)
+       delta = disk->partition->offset;
+      else
+       return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");
+    }
 
   p.offset = 0;
   ext_offset = 0;
@@ -81,8 +90,9 @@ pc_partition_map_iterate (grub_disk_t disk,
        {
          e = mbr.entries + p.index;
 
-         p.start = p.offset + grub_le_to_cpu32 (e->start);
+         p.start = p.offset + grub_le_to_cpu32 (e->start) - delta;
          p.len = grub_le_to_cpu32 (e->length);
+         p.msdostype = e->type;
 
          grub_dprintf ("partition",
                        "partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n",
diff --git a/grub-core/partmap/netbsdlabel.c b/grub-core/partmap/netbsdlabel.c
new file mode 100644 (file)
index 0000000..63c0166
--- /dev/null
@@ -0,0 +1,2 @@
+#define NETBSDLABEL 1
+#include "bsdlabel.c"
diff --git a/grub-core/partmap/openbsdlabel.c b/grub-core/partmap/openbsdlabel.c
new file mode 100644 (file)
index 0000000..4df075a
--- /dev/null
@@ -0,0 +1,2 @@
+#define OPENBSDLABEL 1
+#include "bsdlabel.c"
index 20705c5276d0331508d33251111a7dd3492d7e96..d5398def7bccbf7cf36994c758b7a3dc6290e435 100644 (file)
@@ -65,6 +65,10 @@ struct grub_partition
 
   /* The type partition map.  */
   grub_partition_map_t partmap;
+
+  /* The type of partition whne it's on MSDOS.
+     Used for embedding detection.  */
+  grub_uint8_t msdostype;
 };
 
 grub_partition_t EXPORT_FUNC(grub_partition_probe) (struct grub_disk *disk,