All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] nested partitions
@ 2009-06-11 15:51 Vladimir 'phcoder' Serbinenko
  2009-07-16 20:52 ` Vladimir 'phcoder' Serbinenko
  0 siblings, 1 reply; 36+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-06-11 15:51 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 280 bytes --]

Hello. Here is a first version of nested partition support. Beware
it's EXPERIMENTAL and may be dagerous. Try at your own risk. With this
patch you lose however the ability to specify bsd partition without
specifying slice. Use search.


-- 
Regards
Vladimir 'phcoder' Serbinenko

[-- Attachment #2: nestpart.diff --]
[-- Type: text/x-patch, Size: 60229 bytes --]

diff --git a/ChangeLog b/ChangeLog
index 9802e0e..d748cc8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,71 @@
+2009-06-08  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	Nested partitions
+	
+	* commands/blocklist.c (grub_cmd_blocklist): handle nested partitions
+	* commands/hexdump.c (grub_cmd_hexdump): use grub_disk_read
+	* commands/loadenv.c (check_blocklists): handle nested partitions
+	* conf/common.rmk (grub_probe_SOURCES): add partmap/bsdlabel.c
+	(grub_fstest_SOURCES): likewise
+	(pkglib_MODULES): add bsdlabel.mod
+	(bsdlabel_mod_SOURCES): new variable
+	(bsdlabel_mod_CFLAGS): likewise
+	(bsdlabel_mod_LDFLAGS):likewise
+	* conf/i386-coreboot.rmk (grub_emu_SOURCES): add partmap/bsdlabel.c
+	* conf/i386-pc.rmk (grub_setup_SOURCES): likewise
+	(grub_emu_SOURCES): likewise
+	* conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): likewise
+	* conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): likewise
+	* include/grub/bsdlabel.h: new file
+	* include/grub/partition.h (grub_partition_map): remove probe and 
+	get_name
+	(grub_partition): add parent and number, remove index
+	* include/grub/pc_partition.h: Remove bsd-related entries
+	(grub_pc_partition): remove dos_part, bsd_part, add index. 
+	* kern/disk.c (grub_disk_open): free partition data
+	(grub_disk_adjust_range): handle nested partitions
+	* kern/partition.c (grub_partition_map_probe): new function
+	(grub_partition_probe): parse name to number, handle subpartitions
+	(get_partmap): new function
+	(grub_partition_iterate): handle subpartitions
+	(grub_partition_get_name): likewise
+	* loader/i386/pc/chainloader.c (grub_chainloader_cmd): likewise
+	* partmap/acorn.c (acorn_partition_map_iterate): don't force raw access
+	Use number instead of index
+	(acorn_partition_map_probe): remove
+	(acorn_partition_map_get_name): likewise
+	* partmap/amiga.c (amiga_partition_map_iterate): don't force raw access
+	Use number instead of index
+	(amiga_partition_map_probe): remove
+	(amiga_partition_map_get_name): likewise
+	* partmap/apple.c (apple_partition_map_iterate): don't force raw access
+	Use number instead of index
+	(apple_partition_map_probe): remove
+	(apple_partition_map_get_name): likewise
+	* partmap/bsdlabel.c: new file
+	* partmap/gpt.c (gpt_partition_map_iterate): don't force raw access
+	Use number instead of index
+	(gpt_partition_map_probe): remove
+	(gpt_partition_map_get_name): likewise
+	* partmap/pc.c (grub_partition_parse): remove
+	(pc_partition_map_iterate): don't force raw access
+	move index to pcdata
+	make pcdata a pointer
+	don't handle bsd labels
+	prevent pc_parition from being nested
+	(pc_partition_map_probe): remove
+	(pc_partition_map_get_name): remove
+	* partmap/sun.c (sun_partition_map_iterate): don't force raw access
+	Use number instead of index
+	(sun_partition_map_probe): remove
+	(sun_partition_map_get_name): likewise
+	* parttool/pcpart.c (grub_pcpart_boot): handle nested partitions
+	use index from data
+	(grub_pcpart_type): likewise
+	* util/hostdisk.c (open_device): handle new numbering scheme
+	(grub_util_biosdisk_get_grub_dev): handle nested partitions
+	* util/i386/pc/grub-setup.c (setuo): handle new numbering scheme
+	
 2009-06-10  Pavel Roskin  <proski@gnu.org>
 
 	* io/gzio.c (test_header): Don't reuse one buffer for all data.
diff --git a/commands/blocklist.c b/commands/blocklist.c
index b457b7c..796455a 100644
--- a/commands/blocklist.c
+++ b/commands/blocklist.c
@@ -35,6 +35,8 @@ grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
   unsigned num_sectors = 0;
   int num_entries = 0;
   grub_disk_addr_t part_start = 0;
+  grub_partition_t part;
+
   auto void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset,
 			    unsigned length);
   auto void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num,
@@ -89,8 +91,9 @@ grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
     return grub_error (GRUB_ERR_BAD_DEVICE,
 		       "this command is available only for disk devices.");
 
-  if (file->device->disk->partition)
-    part_start = grub_partition_get_start (file->device->disk->partition);
+  part_start = 0;
+  for (part = file->device->disk->partition; part; part = part->parent)
+    part_start += grub_partition_get_start (part);
 
   file->read_hook = read_blocklist;
 
diff --git a/commands/hexdump.c b/commands/hexdump.c
index 0e560c0..f59ba36 100644
--- a/commands/hexdump.c
+++ b/commands/hexdump.c
@@ -22,7 +22,6 @@
 #include <grub/disk.h>
 #include <grub/misc.h>
 #include <grub/gzio.h>
-#include <grub/partition.h>
 #include <grub/lib/hexdump.h>
 #include <grub/extcmd.h>
 
@@ -62,25 +61,20 @@ grub_cmd_hexdump (grub_extcmd_t cmd, int argc, char **args)
       if (! disk)
         return 0;
 
-      if (disk->partition)
-        skip += grub_partition_get_start (disk->partition) << GRUB_DISK_SECTOR_BITS;
-
       sector = (skip >> (GRUB_DISK_SECTOR_BITS + 2)) * 4;
       ofs = skip & (GRUB_DISK_SECTOR_SIZE * 4 - 1);
       while (length)
         {
-          grub_size_t len, n;
+          grub_size_t len;
 
           len = length;
-          if (ofs + len > sizeof (buf))
-            len = sizeof (buf) - ofs;
+          if (len > sizeof (buf))
+            len = sizeof (buf);
 
-          n = ((ofs + len + GRUB_DISK_SECTOR_SIZE - 1)
-               >> GRUB_DISK_SECTOR_BITS);
-          if (disk->dev->read (disk, sector, n, buf))
+          if (grub_disk_read (disk, sector, ofs, len, buf))
             break;
 
-          hexdump (skip, &buf[ofs], len);
+          hexdump (skip, buf, len);
 
           ofs = 0;
           skip += len;
diff --git a/commands/loadenv.c b/commands/loadenv.c
index 22665f9..1cbf0d4 100644
--- a/commands/loadenv.c
+++ b/commands/loadenv.c
@@ -204,6 +204,7 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
   grub_disk_t disk;
   grub_disk_addr_t part_start;
   struct blocklist *p;
+  grub_partition_t part;
   char *buf;
 
   /* Sanity checks.  */
@@ -236,10 +237,10 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
   /* One more sanity check. Re-read all sectors by blocklists, and compare
      those with the data read via a file.  */
   disk = file->device->disk;
-  if (disk->partition)
-    part_start = grub_partition_get_start (disk->partition);
-  else
-    part_start = 0;
+
+  part_start = 0;
+  for (part = disk->partition; part; part = part->parent)
+    part_start += grub_partition_get_start (part);
 
   buf = grub_envblk_buffer (envblk);
   for (p = blocklists, index = 0; p; p = p->next, index += p->length)
diff --git a/conf/common.rmk b/conf/common.rmk
index 027eff2..79b61a2 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -19,7 +19,8 @@ grub_probe_SOURCES = util/grub-probe.c	\
 	fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c		\
 	fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c			\
 	\
-	partmap/pc.c partmap/apple.c partmap/sun.c partmap/gpt.c\
+	partmap/pc.c partmap/bsdlabel.c partmap/apple.c \
+	partmap/sun.c partmap/gpt.c\
 	kern/fs.c kern/env.c fs/fshelp.c			\
 	disk/raid.c disk/mdraid_linux.c disk/lvm.c grub_probe_init.c
 
@@ -40,8 +41,8 @@ grub_fstest_SOURCES = util/grub-fstest.c util/hostfs.c util/misc.c 	\
 	fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c			\
 	fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c				\
 	\
-	kern/partition.c partmap/pc.c partmap/apple.c partmap/sun.c	\
-	partmap/gpt.c							\
+	kern/partition.c partmap/pc.c partmap/bsdlabel.c partmap/apple.c\
+	partmap/sun.c partmap/gpt.c					\
 	kern/fs.c kern/env.c fs/fshelp.c disk/raid.c			\
 	disk/raid5_recover.c disk/raid6_recover.c 			\
 	disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c 		\
@@ -275,7 +276,8 @@ afs_mod_CFLAGS = $(COMMON_CFLAGS)
 afs_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # Partition maps.
-pkglib_MODULES += amiga.mod apple.mod pc.mod sun.mod acorn.mod gpt.mod
+pkglib_MODULES += amiga.mod apple.mod pc.mod sun.mod acorn.mod gpt.mod \
+		  bsdlabel.mod
 
 # For amiga.mod
 amiga_mod_SOURCES = partmap/amiga.c
@@ -292,6 +294,11 @@ pc_mod_SOURCES = partmap/pc.c
 pc_mod_CFLAGS = $(COMMON_CFLAGS)
 pc_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For pc.mod
+bsdlabel_mod_SOURCES = partmap/bsdlabel.c
+bsdlabel_mod_CFLAGS = $(COMMON_CFLAGS)
+bsdlabel_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # For sun.mod
 sun_mod_SOURCES = partmap/sun.c
 sun_mod_CFLAGS = $(COMMON_CFLAGS)
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index 2f768c0..8ffd7da 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -86,8 +86,8 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	normal/color.c							\
 	script/sh/main.c script/sh/execute.c script/sh/function.c       \
 	script/sh/lexer.c script/sh/script.c grub_script.tab.c          \
-	partmap/amiga.c	partmap/apple.c partmap/pc.c partmap/sun.c	\
-	partmap/acorn.c partmap/gpt.c					\
+	partmap/amiga.c	partmap/apple.c partmap/pc.c partmap/bsdlabel.c \
+	partmap/sun.c partmap/acorn.c partmap/gpt.c			\
 	util/console.c util/hostfs.c util/grub-emu.c util/misc.c	\
 	util/hostdisk.c util/getroot.c					\
 	util/i386/pc/misc.c 						\
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index 961e616..8036eb1 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -84,8 +84,8 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	normal/color.c							\
 	script/sh/main.c script/sh/execute.c script/sh/function.c	\
 	script/sh/lexer.c script/sh/script.c grub_script.tab.c		\
-	partmap/amiga.c	partmap/apple.c partmap/pc.c partmap/sun.c	\
-	partmap/acorn.c partmap/gpt.c					\
+	partmap/amiga.c	partmap/apple.c partmap/pc.c partmap/bsdlabel.c \
+	partmap/sun.c partmap/acorn.c partmap/gpt.c			\
 	util/console.c util/hostfs.c util/grub-emu.c util/misc.c	\
 	util/hostdisk.c util/getroot.c					\
 	util/i386/pc/misc.c						\
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 4a94443..f79e350 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -110,7 +110,7 @@ grub_setup_SOURCES = util/i386/pc/grub-setup.c util/hostdisk.c	\
 	fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c		\
 	fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c			\
 	\
-	partmap/pc.c partmap/gpt.c				\
+	partmap/pc.c partmap/bsdlabel.c partmap/gpt.c		\
 	\
 	disk/raid.c disk/mdraid_linux.c disk/lvm.c		\
 	util/raid.c util/lvm.c					\
@@ -145,8 +145,8 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	normal/menu_text.c						\
 	script/sh/main.c script/sh/execute.c script/sh/function.c	\
 	script/sh/lexer.c script/sh/script.c grub_script.tab.c		\
-	partmap/amiga.c	partmap/apple.c partmap/pc.c partmap/sun.c	\
-	partmap/acorn.c partmap/gpt.c					\
+	partmap/amiga.c	partmap/apple.c partmap/bsdlabel.c partmap/pc.c \
+	partmap/sun.c partmap/acorn.c partmap/gpt.c			\
 	\
 	fs/affs.c fs/cpio.c  fs/fat.c fs/ext2.c fs/hfs.c		\
 	fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c		\
diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk
index 6411111..66c0ce4 100644
--- a/conf/powerpc-ieee1275.rmk
+++ b/conf/powerpc-ieee1275.rmk
@@ -69,8 +69,8 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	normal/color.c							\
 	script/sh/main.c script/sh/execute.c script/sh/function.c	\
 	script/sh/lexer.c script/sh/script.c				\
-	partmap/amiga.c	partmap/apple.c partmap/pc.c partmap/sun.c	\
-	partmap/acorn.c							\
+	partmap/amiga.c	partmap/apple.c partmap/pc.c partmap/bsdlabel.c \
+	partmap/sun.c partmap/acorn.c					\
 	util/console.c util/hostfs.c util/grub-emu.c util/misc.c	\
 	util/hostdisk.c util/getroot.c					\
 	util/powerpc/ieee1275/misc.c					\
diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk
index d061416..8d831eb 100644
--- a/conf/sparc64-ieee1275.rmk
+++ b/conf/sparc64-ieee1275.rmk
@@ -80,8 +80,8 @@ grub_setup_SOURCES = util/sparc64/ieee1275/grub-setup.c util/hostdisk.c	\
 	fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c		\
 	fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c			\
 	\
-	partmap/amiga.c	partmap/apple.c partmap/pc.c		\
-	partmap/sun.c partmap/acorn.c				\
+	partmap/amiga.c	partmap/apple.c partmap/pc.c 		\
+	partmap/bsdlabel.c partmap/sun.c partmap/acorn.c	\
 	\
 	disk/raid.c disk/mdraid_linux.c disk/lvm.c		\
 	util/raid.c util/lvm.c					\
diff --git a/include/grub/bsdlabel.h b/include/grub/bsdlabel.h
new file mode 100644
index 0000000..ba75897
--- /dev/null
+++ b/include/grub/bsdlabel.h
@@ -0,0 +1,91 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2004,2007  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_BSDLABEL_PARTITION_HEADER
+#define GRUB_BSDLABEL_PARTITION_HEADER	1
+
+/* Constants for BSD disk label.  */
+#define GRUB_PC_PARTITION_BSD_LABEL_SECTOR	1
+#define GRUB_PC_PARTITION_BSD_LABEL_MAGIC	0x82564557
+#define GRUB_PC_PARTITION_BSD_MAX_ENTRIES	8
+
+/* BSD partition types.  */
+#define GRUB_PC_PARTITION_BSD_TYPE_UNUSED	0
+#define GRUB_PC_PARTITION_BSD_TYPE_SWAP		1
+#define GRUB_PC_PARTITION_BSD_TYPE_V6		2
+#define GRUB_PC_PARTITION_BSD_TYPE_V7		3
+#define GRUB_PC_PARTITION_BSD_TYPE_SYSV		4
+#define GRUB_PC_PARTITION_BSD_TYPE_V71K		5
+#define GRUB_PC_PARTITION_BSD_TYPE_V8		6
+#define GRUB_PC_PARTITION_BSD_TYPE_BSDFFS	7
+#define GRUB_PC_PARTITION_BSD_TYPE_MSDOS	8
+#define GRUB_PC_PARTITION_BSD_TYPE_BSDLFS	9
+#define GRUB_PC_PARTITION_BSD_TYPE_OTHER	10
+#define GRUB_PC_PARTITION_BSD_TYPE_HPFS		11
+#define GRUB_PC_PARTITION_BSD_TYPE_ISO9660	12
+#define GRUB_PC_PARTITION_BSD_TYPE_BOOT		13
+
+/* FreeBSD-specific types.  */
+#define GRUB_PC_PARTITION_FREEBSD_TYPE_VINUM	14
+#define GRUB_PC_PARTITION_FREEBSD_TYPE_RAID	15
+#define GRUB_PC_PARTITION_FREEBSD_TYPE_JFS2	21
+
+/* NetBSD-specific types.  */
+#define	GRUB_PC_PARTITION_NETBSD_TYPE_ADOS	14
+#define	GRUB_PC_PARTITION_NETBSD_TYPE_HFS	15
+#define	GRUB_PC_PARTITION_NETBSD_TYPE_FILECORE	16
+#define	GRUB_PC_PARTITION_NETBSD_TYPE_EXT2FS	17
+#define	GRUB_PC_PARTITION_NETBSD_TYPE_NTFS	18
+#define	GRUB_PC_PARTITION_NETBSD_TYPE_RAID	19
+#define	GRUB_PC_PARTITION_NETBSD_TYPE_CCD	20
+#define	GRUB_PC_PARTITION_NETBSD_TYPE_JFS2	21
+#define	GRUB_PC_PARTITION_NETBSD_TYPE_APPLEUFS	22
+
+/* OpenBSD-specific types.  */
+#define	GRUB_PC_PARTITION_OPENBSD_TYPE_ADOS	14
+#define	GRUB_PC_PARTITION_OPENBSD_TYPE_HFS	15
+#define	GRUB_PC_PARTITION_OPENBSD_TYPE_FILECORE	16
+#define	GRUB_PC_PARTITION_OPENBSD_TYPE_EXT2FS	17
+#define	GRUB_PC_PARTITION_OPENBSD_TYPE_NTFS	18
+#define	GRUB_PC_PARTITION_OPENBSD_TYPE_RAID	19
+
+/* The BSD partition entry.  */
+struct grub_pc_partition_bsd_entry
+{
+  grub_uint32_t size;
+  grub_uint32_t offset;
+  grub_uint32_t fragment_size;
+  grub_uint8_t fs_type;
+  grub_uint8_t fs_fragments;
+  grub_uint16_t fs_cylinders;
+} __attribute__ ((packed));
+
+/* The BSD disk label. Only define members useful for GRUB.  */
+struct grub_pc_partition_disk_label
+{
+  grub_uint32_t magic;
+  grub_uint8_t padding[128];
+  grub_uint32_t magic2;
+  grub_uint16_t checksum;
+  grub_uint16_t num_partitions;
+  grub_uint32_t boot_size;
+  grub_uint32_t superblock_size;
+  struct grub_pc_partition_bsd_entry entries[GRUB_PC_PARTITION_BSD_MAX_ENTRIES];
+} __attribute__ ((packed));
+
+#endif /* ! GRUB_PC_PARTITION_HEADER */
diff --git a/include/grub/partition.h b/include/grub/partition.h
index 37c5f24..4b174ff 100644
--- a/include/grub/partition.h
+++ b/include/grub/partition.h
@@ -36,13 +36,6 @@ struct grub_partition_map
 			 int (*hook) (struct grub_disk *disk,
 				      const grub_partition_t partition));
 
-  /* Return the partition named STR on the disk DISK.  */
-  grub_partition_t (*probe) (struct grub_disk *disk,
-			     const char *str);
-
-  /* Return the name of the partition PARTITION.  */
-  char *(*get_name) (const grub_partition_t partition);
-
   /* The next partition map type.  */
   struct grub_partition_map *next;
 };
@@ -51,6 +44,9 @@ typedef struct grub_partition_map *grub_partition_map_t;
 /* Partition description.  */
 struct grub_partition
 {
+  /* The partition number.  */
+  int number;
+
   /* The start sector.  */
   grub_disk_addr_t start;
 
@@ -60,12 +56,12 @@ struct grub_partition
   /* The offset of the partition table.  */
   grub_disk_addr_t offset;
 
-  /* The index of this partition in the partition table.  */
-  int index;
-
   /* Partition map type specific data.  */
   void *data;
 
+  /* Parent partition map.  */
+  struct grub_partition *parent;
+
   /* The type partition map.  */
   grub_partition_map_t partmap;
 };
diff --git a/include/grub/pc_partition.h b/include/grub/pc_partition.h
index 67c312e..8f6a8b9 100644
--- a/include/grub/pc_partition.h
+++ b/include/grub/pc_partition.h
@@ -53,75 +53,6 @@
 #define GRUB_PC_PARTITION_TYPE_GPT_DISK		0xee
 #define GRUB_PC_PARTITION_TYPE_LINUX_RAID	0xfd
 
-/* Constants for BSD disk label.  */
-#define GRUB_PC_PARTITION_BSD_LABEL_SECTOR	1
-#define GRUB_PC_PARTITION_BSD_LABEL_MAGIC	0x82564557
-#define GRUB_PC_PARTITION_BSD_MAX_ENTRIES	8
-
-/* BSD partition types.  */
-#define GRUB_PC_PARTITION_BSD_TYPE_UNUSED	0
-#define GRUB_PC_PARTITION_BSD_TYPE_SWAP		1
-#define GRUB_PC_PARTITION_BSD_TYPE_V6		2
-#define GRUB_PC_PARTITION_BSD_TYPE_V7		3
-#define GRUB_PC_PARTITION_BSD_TYPE_SYSV		4
-#define GRUB_PC_PARTITION_BSD_TYPE_V71K		5
-#define GRUB_PC_PARTITION_BSD_TYPE_V8		6
-#define GRUB_PC_PARTITION_BSD_TYPE_BSDFFS	7
-#define GRUB_PC_PARTITION_BSD_TYPE_MSDOS	8
-#define GRUB_PC_PARTITION_BSD_TYPE_BSDLFS	9
-#define GRUB_PC_PARTITION_BSD_TYPE_OTHER	10
-#define GRUB_PC_PARTITION_BSD_TYPE_HPFS		11
-#define GRUB_PC_PARTITION_BSD_TYPE_ISO9660	12
-#define GRUB_PC_PARTITION_BSD_TYPE_BOOT		13
-
-/* FreeBSD-specific types.  */
-#define GRUB_PC_PARTITION_FREEBSD_TYPE_VINUM	14
-#define GRUB_PC_PARTITION_FREEBSD_TYPE_RAID	15
-#define GRUB_PC_PARTITION_FREEBSD_TYPE_JFS2	21
-
-/* NetBSD-specific types.  */
-#define	GRUB_PC_PARTITION_NETBSD_TYPE_ADOS	14
-#define	GRUB_PC_PARTITION_NETBSD_TYPE_HFS	15
-#define	GRUB_PC_PARTITION_NETBSD_TYPE_FILECORE	16
-#define	GRUB_PC_PARTITION_NETBSD_TYPE_EXT2FS	17
-#define	GRUB_PC_PARTITION_NETBSD_TYPE_NTFS	18
-#define	GRUB_PC_PARTITION_NETBSD_TYPE_RAID	19
-#define	GRUB_PC_PARTITION_NETBSD_TYPE_CCD	20
-#define	GRUB_PC_PARTITION_NETBSD_TYPE_JFS2	21
-#define	GRUB_PC_PARTITION_NETBSD_TYPE_APPLEUFS	22
-
-/* OpenBSD-specific types.  */
-#define	GRUB_PC_PARTITION_OPENBSD_TYPE_ADOS	14
-#define	GRUB_PC_PARTITION_OPENBSD_TYPE_HFS	15
-#define	GRUB_PC_PARTITION_OPENBSD_TYPE_FILECORE	16
-#define	GRUB_PC_PARTITION_OPENBSD_TYPE_EXT2FS	17
-#define	GRUB_PC_PARTITION_OPENBSD_TYPE_NTFS	18
-#define	GRUB_PC_PARTITION_OPENBSD_TYPE_RAID	19
-
-/* The BSD partition entry.  */
-struct grub_pc_partition_bsd_entry
-{
-  grub_uint32_t size;
-  grub_uint32_t offset;
-  grub_uint32_t fragment_size;
-  grub_uint8_t fs_type;
-  grub_uint8_t fs_fragments;
-  grub_uint16_t fs_cylinders;
-} __attribute__ ((packed));
-
-/* The BSD disk label. Only define members useful for GRUB.  */
-struct grub_pc_partition_disk_label
-{
-  grub_uint32_t magic;
-  grub_uint8_t padding[128];
-  grub_uint32_t magic2;
-  grub_uint16_t checksum;
-  grub_uint16_t num_partitions;
-  grub_uint32_t boot_size;
-  grub_uint32_t superblock_size;
-  struct grub_pc_partition_bsd_entry entries[GRUB_PC_PARTITION_BSD_MAX_ENTRIES];
-} __attribute__ ((packed));
-
 /* The partition entry.  */
 struct grub_pc_partition_entry
 {
@@ -170,20 +101,14 @@ struct grub_pc_partition_mbr
 \f
 struct grub_pc_partition
 {
-    /* The DOS partition number.  */
-  int dos_part;
-
-  /* The BSD partition number (a == 0).  */
-  int bsd_part;
-
   /* The DOS partition type.  */
   int dos_type;
 
-  /* The BSD partition type.  */
-  int bsd_type;
-
   /* The offset of the extended partition.  */
   unsigned long ext_offset;
+
+  /* The index of this partition in the partition table.  */
+  int index;
 };
 
 static inline int
@@ -200,12 +125,4 @@ grub_pc_partition_is_extended (int type)
 	  || type == GRUB_PC_PARTITION_TYPE_LINUX_EXTENDED);
 }
 
-static inline int
-grub_pc_partition_is_bsd (int type)
-{
-  return (type == GRUB_PC_PARTITION_TYPE_FREEBSD
-	  || type == GRUB_PC_PARTITION_TYPE_OPENBSD
-	  || type == GRUB_PC_PARTITION_TYPE_NETBSD);
-}
-
 #endif /* ! GRUB_PC_PARTITION_HEADER */
diff --git a/kern/disk.c b/kern/disk.c
index ad778d4..7ef2ae1 100644
--- a/kern/disk.c
+++ b/kern/disk.c
@@ -334,6 +334,7 @@ grub_disk_open (const char *name)
 void
 grub_disk_close (grub_disk_t disk)
 {
+  grub_partition_t part;
   grub_dprintf ("disk", "Closing `%s'.\n", disk->name);
 
   if (disk->dev && disk->dev->close)
@@ -342,7 +343,13 @@ grub_disk_close (grub_disk_t disk)
   /* Reset the timer.  */
   grub_last_time = grub_get_time_ms ();
 
-  grub_free (disk->partition);
+  while (disk->partition)
+    {
+      part = disk->partition->parent;
+      grub_free (disk->partition->data);
+      grub_free (disk->partition);
+      disk->partition = part;
+    }
   grub_free ((void *) disk->name);
   grub_free (disk);
 }
@@ -353,18 +360,19 @@ grub_disk_close (grub_disk_t disk)
    - Verify that the range is inside the partition.  */
 static grub_err_t
 grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector,
-		       grub_off_t *offset, grub_size_t size)
+			grub_off_t *offset, grub_size_t size)
 {
+  grub_partition_t part;
   *sector += *offset >> GRUB_DISK_SECTOR_BITS;
   *offset &= GRUB_DISK_SECTOR_SIZE - 1;
-
-  if (disk->partition)
+  
+  for (part = disk->partition; part; part = part->parent)
     {
       grub_disk_addr_t start;
       grub_uint64_t len;
 
-      start = grub_partition_get_start (disk->partition);
-      len = grub_partition_get_len (disk->partition);
+      start = grub_partition_get_start (part);
+      len = grub_partition_get_len (part);
 
       if (*sector >= len
 	  || len - *sector < ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
diff --git a/kern/partition.c b/kern/partition.c
index 4d5c63a..4f7f2d7 100644
--- a/kern/partition.c
+++ b/kern/partition.c
@@ -17,6 +17,7 @@
  */
 
 #include <grub/misc.h>
+#include <grub/mm.h>
 #include <grub/partition.h>
 #include <grub/disk.h>
 
@@ -54,17 +55,58 @@ grub_partition_map_iterate (int (*hook) (const grub_partition_map_t partmap))
   return 0;
 }
 
+static grub_partition_t
+grub_partition_map_probe (const grub_partition_map_t partmap,
+			  grub_disk_t disk, int partnum)
+{
+  grub_partition_t p = 0;
+
+  auto int find_func (grub_disk_t d, const grub_partition_t partition);
+    
+  int find_func (grub_disk_t d __attribute__ ((unused)),
+		 const grub_partition_t partition)
+    {
+      if (partnum == partition->number)
+	{
+	  p = (grub_partition_t) grub_malloc (sizeof (*p));
+	  if (! p)
+	    return 1;
+	  
+	  grub_memcpy (p, partition, sizeof (*p));
+	  return 1;
+	}
+      
+      return 0;
+    }
+  
+  partmap->iterate (disk, find_func);
+  if (grub_errno)
+    goto fail;
+
+  return p;
+
+ fail:
+  grub_free (p);
+  return 0;
+}
+
 grub_partition_t
 grub_partition_probe (struct grub_disk *disk, const char *str)
 {
   grub_partition_t part = 0;
+  grub_partition_t curpart = 0;
+  grub_partition_t tail;
+  const char *ptr;
+  int num;
 
   auto int part_map_probe (const grub_partition_map_t partmap);
 
   int part_map_probe (const grub_partition_map_t partmap)
     {
-      part = partmap->probe (disk, str);
-      if (part)
+      disk->partition = part;
+      curpart = grub_partition_map_probe (partmap, disk, num);
+      disk->partition = tail;
+      if (curpart)
 	return 1;
 
       if (grub_errno == GRUB_ERR_BAD_PART_TABLE)
@@ -77,27 +119,54 @@ grub_partition_probe (struct grub_disk *disk, const char *str)
       return 1;
     }
 
-  /* Use the first partition map type found.  */
-  grub_partition_map_iterate (part_map_probe);
+  part = tail = disk->partition;
+
+  for (ptr = str; *ptr;)
+    {
+      /* BSD-like partition specification.  */
+      if (*ptr >= 'a' && *ptr <= 'z')
+	num = *(ptr++) - 'a';
+      else
+	num = grub_strtoul (ptr, (char **) &ptr, 0) - 1;
+      
+      curpart = 0;
+      /* Use the first partition map type found.  */
+      grub_partition_map_iterate (part_map_probe);
+      
+      if (! curpart)
+	{
+	  while (part)
+	    {
+	      curpart = part->parent;
+	      grub_free (part);
+	      part = curpart;
+	    }
+	  return 0;
+	}
+      curpart->parent = part;
+      part = curpart;
+      if (! ptr || *ptr != ',')
+	break;
+      ptr++;
+    }
 
   return part;
 }
 
-int
-grub_partition_iterate (struct grub_disk *disk,
-			int (*hook) (grub_disk_t disk,
-				     const grub_partition_t partition))
+static grub_partition_map_t
+get_partmap (struct grub_disk *disk)
 {
   grub_partition_map_t partmap = 0;
-  int ret = 0;
-
+  struct grub_partition part;
+  int found = 0;
   auto int part_map_iterate (const grub_partition_map_t p);
   auto int part_map_iterate_hook (grub_disk_t d,
 				  const grub_partition_t partition);
-
   int part_map_iterate_hook (grub_disk_t d __attribute__ ((unused)),
-			     const grub_partition_t partition __attribute__ ((unused)))
+			     const grub_partition_t partition)
     {
+      found = 1;
+      part = *partition;
       return 1;
     }
 
@@ -106,28 +175,89 @@ grub_partition_iterate (struct grub_disk *disk,
       grub_dprintf ("partition", "Detecting %s...\n", p->name);
       p->iterate (disk, part_map_iterate_hook);
 
-      if (grub_errno != GRUB_ERR_NONE)
+      if (grub_errno != GRUB_ERR_NONE || ! found)
 	{
 	  /* Continue to next partition map type.  */
 	  grub_dprintf ("partition", "%s detection failed.\n", p->name);
 	  grub_errno = GRUB_ERR_NONE;
 	  return 0;
 	}
+      grub_free (part.data);
 
       grub_dprintf ("partition", "%s detection succeeded.\n", p->name);
       partmap = p;
       return 1;
     }
-
   grub_partition_map_iterate (part_map_iterate);
-  if (partmap)
-    ret = partmap->iterate (disk, hook);
+  return partmap;
+}
+
+int
+grub_partition_iterate (struct grub_disk *disk,
+			int (*hook) (grub_disk_t disk,
+				     const grub_partition_t partition))
+{
+  int ret = 0;
+  
+  auto int part_iterate (grub_disk_t dsk, const grub_partition_t p);
 
+  int part_iterate (grub_disk_t dsk,
+		    const grub_partition_t partition)
+    {
+      struct grub_partition p = *partition;
+      grub_partition_map_t partmap = 0;
+      p.parent = dsk->partition;
+      dsk->partition = 0;
+      if (hook (dsk, &p))
+	  return 1;
+      if (p.start != 0)
+	{
+	  dsk->partition = &p;
+	  partmap = get_partmap (dsk);
+	  if (partmap)
+	    ret = partmap->iterate (dsk, part_iterate);
+	}
+      dsk->partition = p.parent;
+      return ret;
+    }
+
+  {
+    grub_partition_map_t partmap = 0;
+    partmap = get_partmap (disk);
+    if (partmap)
+      ret = partmap->iterate (disk, part_iterate);
+  }
+  
   return ret;
 }
 
 char *
 grub_partition_get_name (const grub_partition_t partition)
 {
-  return partition->partmap->get_name (partition);
+  char *out = 0;
+  /* Even on 64-bit machines this buffer is enough to hold longest number.  */
+  char buf[25];
+  int curlen = 0;
+  grub_partition_t part;
+  for (part = partition; part; part = part->parent)
+    {
+      int strl;
+      grub_sprintf (buf, "%d", part->number + 1);
+      strl = grub_strlen (buf);
+      if (curlen)
+	{
+	  out = grub_realloc (out, curlen + strl + 2);
+	  grub_memcpy (out + strl + 1, out, curlen);
+	  out[curlen + 1 + strl] = 0;
+	  grub_memcpy (out, buf, strl);
+	  out[strl] = ',';
+	  curlen = curlen + 1 + strl;
+	}
+      else
+	{
+	  curlen = strl;
+	  out = grub_strdup (buf);
+	}
+    }
+  return out;
 }
diff --git a/loader/i386/pc/chainloader.c b/loader/i386/pc/chainloader.c
index 3befd5e..bcd69f0 100644
--- a/loader/i386/pc/chainloader.c
+++ b/loader/i386/pc/chainloader.c
@@ -101,12 +101,15 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags)
 	  /* In i386-pc, the id is equal to the BIOS drive number.  */
 	  drive = (int) disk->id;
 
-	  if (p)
+	  if (p && grub_strcmp (p->partmap->name, "pc_partition_map") == 0)
 	    {
+	      disk->parition = p->parent;
 	      grub_disk_read (disk, p->offset, 446, 64,
 			      (void *) GRUB_MEMORY_MACHINE_PART_TABLE_ADDR);
 	      part_addr = (void *) (GRUB_MEMORY_MACHINE_PART_TABLE_ADDR
-				    + (p->index << 4));
+				    + (((struct grub_pc_partition *) p->data)
+				       ->index << 4));
+	      disk->parition = p;
 	    }
 	}
 
diff --git a/partmap/acorn.c b/partmap/acorn.c
index 42fd61f..0abd961 100644
--- a/partmap/acorn.c
+++ b/partmap/acorn.c
@@ -96,21 +96,17 @@ acorn_partition_map_iterate (grub_disk_t disk,
 					  const grub_partition_t partition))
 {
   struct grub_partition part;
-  struct grub_disk raw;
   struct linux_part map[LINUX_MAP_ENTRIES];
   int i;
-  grub_disk_addr_t sector;
+  grub_disk_addr_t sector = 0;
   grub_err_t err;
 
-  /* Enforce raw disk access.  */
-  raw = *disk;
-  raw.partition = 0;
-
-  err = acorn_partition_map_find (&raw, map, &sector);
+  err = acorn_partition_map_find (disk, map, &sector);
   if (err)
     return err;
 
   part.partmap = &grub_acorn_partition_map;
+  part.data = 0;
 
   for (i = 0; i != LINUX_MAP_ENTRIES; ++i)
     {
@@ -121,7 +117,7 @@ acorn_partition_map_iterate (grub_disk_t disk,
       part.start = sector + map[i].start;
       part.len = map[i].size;
       part.offset = 6;
-      part.index = i;
+      part.number = i;
 
       if (hook (disk, &part))
 	return grub_errno;
@@ -130,60 +126,6 @@ acorn_partition_map_iterate (grub_disk_t disk,
   return GRUB_ERR_NONE;
 }
 
-
-static grub_partition_t
-acorn_partition_map_probe (grub_disk_t disk, const char *str)
-{
-  struct linux_part map[LINUX_MAP_ENTRIES];
-  struct grub_disk raw = *disk;
-  unsigned long partnum = grub_strtoul (str, 0, 10) - 1;
-  grub_disk_addr_t sector;
-  grub_err_t err;
-  grub_partition_t p;
-
-  /* Enforce raw disk access.  */
-  raw.partition = 0;
-
-  /* Get the partition number.  */
-  if (partnum > LINUX_MAP_ENTRIES)
-    goto fail;
-
-  err = acorn_partition_map_find (&raw, map, &sector);
-  if (err)
-    return 0;
-
-  if (map[partnum].magic != LINUX_NATIVE_MAGIC
-      && map[partnum].magic != LINUX_SWAP_MAGIC)
-    goto fail;
-
-  p = grub_malloc (sizeof (struct grub_partition));
-  if (! p)
-    return 0;
-
-  p->start = sector + map[partnum].start;
-  p->len = map[partnum].size;
-  p->offset = 6;
-  p->index = partnum;
-  return p;
-
-fail:
-  grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
-  return 0;
-}
-
-
-static char *
-acorn_partition_map_get_name (const grub_partition_t p)
-{
-  char *name;
-
-  name = grub_malloc (13);
-  if (! name)
-    return 0;
-
-  grub_sprintf (name, "%d", p->index + 1);
-  return name;
-}
 \f
 
 /* Partition map type.  */
@@ -191,8 +133,6 @@ static struct grub_partition_map grub_acorn_partition_map =
 {
   .name = "Linux/ADFS partition map",
   .iterate = acorn_partition_map_iterate,
-  .probe = acorn_partition_map_probe,
-  .get_name = acorn_partition_map_get_name
 };
 
 GRUB_MOD_INIT(acorn_partition_map)
diff --git a/partmap/amiga.c b/partmap/amiga.c
index ffb807f..b246ca4 100644
--- a/partmap/amiga.c
+++ b/partmap/amiga.c
@@ -76,20 +76,15 @@ amiga_partition_map_iterate (grub_disk_t disk,
 {
   struct grub_partition part;
   struct grub_amiga_rdsk rdsk;
-  struct grub_disk raw;
   int partno = 0;
   int next = -1;
   unsigned pos;
 
-  /* Enforce raw disk access.  */
-  raw = *disk;
-  raw.partition = 0;
-
   /* The RDSK block is one of the first 15 blocks.  */
   for (pos = 0; pos < 15; pos++)
     {
       /* Read the RDSK block which is a descriptor for the entire disk.  */
-      if (grub_disk_read (&raw, pos, 0, sizeof (rdsk), &rdsk))
+      if (grub_disk_read (disk, pos, 0, sizeof (rdsk), &rdsk))
 	return grub_errno;
 
       if (grub_strcmp ((char *) rdsk.magic, "RDSK") == 0)
@@ -104,13 +99,15 @@ amiga_partition_map_iterate (grub_disk_t disk,
     return grub_error (GRUB_ERR_BAD_PART_TABLE,
 		       "Amiga partition map not found.");
 
+  part.data = 0;
+
   /* The end of the partition list is marked using "-1".  */
   while (next != -1)
     {
       struct grub_amiga_partition apart;
 
       /* Read the RDSK block which is a descriptor for the entire disk.  */
-      if (grub_disk_read (&raw, next, 0, sizeof (apart), &apart))
+      if (grub_disk_read (disk, next, 0, sizeof (apart), &apart))
 	return grub_errno;
 
       /* Calculate the first block and the size of the partition.  */
@@ -123,7 +120,7 @@ amiga_partition_map_iterate (grub_disk_t disk,
 		  * grub_be_to_cpu32 (apart.block_per_track));
 
       part.offset = (grub_off_t) next * 512;
-      part.index = partno;
+      part.number = partno;
       part.partmap = &grub_amiga_partition_map;
 
       if (hook (disk, &part))
@@ -136,72 +133,12 @@ amiga_partition_map_iterate (grub_disk_t disk,
   return 0;
 }
 
-
-static grub_partition_t
-amiga_partition_map_probe (grub_disk_t disk, const char *str)
-{
-  grub_partition_t p = 0;
-  int partnum = 0;
-  char *s = (char *) str;
-
-  auto int find_func (grub_disk_t d, const grub_partition_t partition);
-
-  int find_func (grub_disk_t d __attribute__ ((unused)),
-		 const grub_partition_t partition)
-    {
-      if (partnum == partition->index)
-	{
-	  p = (grub_partition_t) grub_malloc (sizeof (*p));
-	  if (! p)
-	    return 1;
-
-	  grub_memcpy (p, partition, sizeof (*p));
-	  return 1;
-	}
-
-      return 0;
-    }
-
-  /* Get the partition number.  */
-  partnum = grub_strtoul (s, 0, 10) - 1;
-  if (grub_errno)
-    {
-      grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
-      return 0;
-    }
-
-  if (amiga_partition_map_iterate (disk, find_func))
-    goto fail;
-
-  return p;
-
- fail:
-  grub_free (p);
-  return 0;
-}
-
-
-static char *
-amiga_partition_map_get_name (const grub_partition_t p)
-{
-  char *name;
-
-  name = grub_malloc (13);
-  if (! name)
-    return 0;
-
-  grub_sprintf (name, "%d", p->index + 1);
-  return name;
-}
-
 \f
 /* Partition map type.  */
 static struct grub_partition_map grub_amiga_partition_map =
   {
     .name = "amiga_partition_map",
     .iterate = amiga_partition_map_iterate,
-    .probe = amiga_partition_map_probe,
-    .get_name = amiga_partition_map_get_name
   };
 
 GRUB_MOD_INIT(amiga_partition_map)
diff --git a/partmap/apple.c b/partmap/apple.c
index fce2f2c..1621086 100644
--- a/partmap/apple.c
+++ b/partmap/apple.c
@@ -104,17 +104,12 @@ apple_partition_map_iterate (grub_disk_t disk,
   struct grub_partition part;
   struct grub_apple_header aheader;
   struct grub_apple_part apart;
-  struct grub_disk raw;
   int partno = 0;
   unsigned pos = GRUB_DISK_SECTOR_SIZE;
 
-  /* Enforce raw disk access.  */
-  raw = *disk;
-  raw.partition = 0;
-
   part.partmap = &grub_apple_partition_map;
 
-  if (grub_disk_read (&raw, 0, 0, sizeof (aheader), &aheader))
+  if (grub_disk_read (disk, 0, 0, sizeof (aheader), &aheader))
     return grub_errno;
 
   if (grub_be_to_cpu16 (aheader.magic) != GRUB_APPLE_HEADER_MAGIC)
@@ -126,9 +121,11 @@ apple_partition_map_iterate (grub_disk_t disk,
       goto fail;
     }
 
+  part.data = 0;
+
   for (;;)
     {
-      if (grub_disk_read (&raw, pos / GRUB_DISK_SECTOR_SIZE,
+      if (grub_disk_read (disk, pos / GRUB_DISK_SECTOR_SIZE,
 			  pos % GRUB_DISK_SECTOR_SIZE,
 			  sizeof (struct grub_apple_part),  &apart))
 	return grub_errno;
@@ -145,7 +142,7 @@ apple_partition_map_iterate (grub_disk_t disk,
       part.start = grub_be_to_cpu32 (apart.first_phys_block);
       part.len = grub_be_to_cpu32 (apart.blockcnt);
       part.offset = pos;
-      part.index = partno;
+      part.number = partno;
 
       grub_dprintf ("partition",
 		    "partition %d: name %s, type %s, start 0x%x, len 0x%x\n",
@@ -172,72 +169,12 @@ apple_partition_map_iterate (grub_disk_t disk,
 		     "Apple partition map not found.");
 }
 
-
-static grub_partition_t
-apple_partition_map_probe (grub_disk_t disk, const char *str)
-{
-  grub_partition_t p = 0;
-  int partnum = 0;
-  char *s = (char *) str;
-
-  auto int find_func (grub_disk_t d, const grub_partition_t partition);
-
-  int find_func (grub_disk_t d __attribute__ ((unused)),
-		 const grub_partition_t partition)
-    {
-      if (partnum == partition->index)
-	{
-	  p = (grub_partition_t) grub_malloc (sizeof (*p));
-	  if (! p)
-	    return 1;
-
-	  grub_memcpy (p, partition, sizeof (*p));
-	  return 1;
-	}
-
-      return 0;
-    }
-
-  /* Get the partition number.  */
-  partnum = grub_strtoul (s, 0, 10) - 1;
-  if (grub_errno)
-    {
-      grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
-      return 0;
-    }
-
-  if (apple_partition_map_iterate (disk, find_func))
-    goto fail;
-
-  return p;
-
- fail:
-  grub_free (p);
-  return 0;
-}
-
-
-static char *
-apple_partition_map_get_name (const grub_partition_t p)
-{
-  char *name;
-
-  name = grub_malloc (13);
-  if (! name)
-    return 0;
-
-  grub_sprintf (name, "%d", p->index + 1);
-  return name;
-}
-
 \f
 /* Partition map type.  */
 static struct grub_partition_map grub_apple_partition_map =
   {
     .name = "apple_partition_map",
     .iterate = apple_partition_map_iterate,
-    .probe = apple_partition_map_probe,
-    .get_name = apple_partition_map_get_name
   };
 
 GRUB_MOD_INIT(apple_partition_map)
diff --git a/partmap/bsdlabel.c b/partmap/bsdlabel.c
new file mode 100644
index 0000000..b7cbfb2
--- /dev/null
+++ b/partmap/bsdlabel.c
@@ -0,0 +1,89 @@
+/* bsdlabel.c - Read BSD style partition tables.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2004,2005,2006,2007,2008,2009  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/partition.h>
+#include <grub/bsdlabel.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/dl.h>
+
+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))
+{
+  struct grub_pc_partition_disk_label label;  
+  struct grub_partition p;
+  grub_partition_t part;
+  grub_disk_addr_t delta = 0;
+
+  /* BSDLabel offsets are absolute even when it's embed inside partition.  */
+  for (part = disk->partition; part; part = part->parent)
+    delta += grub_partition_get_start (part);
+
+  /* Read the BSD label.  */
+  if (grub_disk_read (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR,
+		      0, sizeof (label), &label))
+    goto finish;
+
+  /* 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");
+  for (p.number = 0;
+       p.number < grub_cpu_to_le16 (label.num_partitions);
+       p.number++)
+    {
+      struct grub_pc_partition_bsd_entry *be
+	= label.entries + p.number;
+
+      p.start = grub_le_to_cpu32 (be->offset) - delta;
+      p.len = grub_le_to_cpu32 (be->size);
+      p.offset = GRUB_PC_PARTITION_BSD_LABEL_SECTOR;
+      p.partmap = &grub_bsdlabel_partition_map;
+      p.data = 0;
+		      
+      if (be->fs_type != GRUB_PC_PARTITION_BSD_TYPE_UNUSED)
+	if (hook (disk, &p))
+	  return 1;
+    }
+ finish:
+  return grub_errno;
+}
+
+\f
+/* Partition map type.  */
+static struct grub_partition_map grub_bsdlabel_partition_map =
+  {
+    .name = "bsdlabel_partition_map",
+    .iterate = bsdlabel_partition_map_iterate,
+  };
+
+GRUB_MOD_INIT(bsdlabel_partition_map)
+{
+  grub_partition_map_register (&grub_bsdlabel_partition_map);
+}
+
+GRUB_MOD_FINI(bsdlabel_partition_map)
+{
+  grub_partition_map_unregister (&grub_bsdlabel_partition_map);
+}
diff --git a/partmap/gpt.c b/partmap/gpt.c
index d646d41..bfe6269 100644
--- a/partmap/gpt.c
+++ b/partmap/gpt.c
@@ -44,18 +44,13 @@ gpt_partition_map_iterate (grub_disk_t disk,
   struct grub_partition part;
   struct grub_gpt_header gpt;
   struct grub_gpt_partentry entry;
-  struct grub_disk raw;
   struct grub_pc_partition_mbr mbr;
   grub_uint64_t entries;
   unsigned int i;
   int last_offset = 0;
 
-  /* Enforce raw disk access.  */
-  raw = *disk;
-  raw.partition = 0;
-
   /* Read the protective MBR.  */
-  if (grub_disk_read (&raw, 0, 0, sizeof (mbr), &mbr))
+  if (grub_disk_read (disk, 0, 0, sizeof (mbr), &mbr))
     return grub_errno;
 
   /* Check if it is valid.  */
@@ -67,7 +62,7 @@ gpt_partition_map_iterate (grub_disk_t disk,
     return grub_error (GRUB_ERR_BAD_PART_TABLE, "no GPT partition map found");
 
   /* Read the GPT header.  */
-  if (grub_disk_read (&raw, 1, 0, sizeof (gpt), &gpt))
+  if (grub_disk_read (disk, 1, 0, sizeof (gpt), &gpt))
     return grub_errno;
 
   if (grub_memcmp (gpt.magic, grub_gpt_magic, sizeof (grub_gpt_magic)))
@@ -78,7 +73,7 @@ gpt_partition_map_iterate (grub_disk_t disk,
   entries = grub_le_to_cpu64 (gpt.partitions);
   for (i = 0; i < grub_le_to_cpu32 (gpt.maxpart); i++)
     {
-      if (grub_disk_read (&raw, entries, last_offset,
+      if (grub_disk_read (disk, entries, last_offset,
 			  sizeof (entry), &entry))
 	return grub_errno;
 
@@ -90,9 +85,9 @@ gpt_partition_map_iterate (grub_disk_t disk,
 	  part.len = (grub_le_to_cpu64 (entry.end)
 		      - grub_le_to_cpu64 (entry.start) + 1);
 	  part.offset = entries;
-	  part.index = i;
+	  part.number = i;
 	  part.partmap = &grub_gpt_partition_map;
-	  part.data = &entry;
+	  part.data = 0;
 
 	  grub_dprintf ("gpt", "GPT entry %d: start=%lld, length=%lld\n", i,
 			(unsigned long long) part.start,
@@ -113,73 +108,12 @@ gpt_partition_map_iterate (grub_disk_t disk,
   return 0;
 }
 
-
-static grub_partition_t
-gpt_partition_map_probe (grub_disk_t disk, const char *str)
-{
-  grub_partition_t p = 0;
-  int partnum = 0;
-  char *s = (char *) str;
-
-  auto int find_func (grub_disk_t d, const grub_partition_t partition);
-
-  int find_func (grub_disk_t d __attribute__ ((unused)),
-		 const grub_partition_t partition)
-    {
-      if (partnum == partition->index)
-	{
-	  p = (grub_partition_t) grub_malloc (sizeof (*p));
-	  if (! p)
-	    return 1;
-
-	  grub_memcpy (p, partition, sizeof (*p));
-	  return 1;
-	}
-
-      return 0;
-    }
-
-  /* Get the partition number.  */
-  partnum = grub_strtoul (s, 0, 10) - 1;
-  if (grub_errno)
-    {
-      grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
-      return 0;
-    }
-
-  gpt_partition_map_iterate (disk, find_func);
-  if (grub_errno)
-    goto fail;
-
-  return p;
-
- fail:
-  grub_free (p);
-  return 0;
-}
-
-
-static char *
-gpt_partition_map_get_name (const grub_partition_t p)
-{
-  char *name;
-
-  name = grub_malloc (13);
-  if (! name)
-    return 0;
-
-  grub_sprintf (name, "%d", p->index + 1);
-  return name;
-}
-
 \f
 /* Partition map type.  */
 static struct grub_partition_map grub_gpt_partition_map =
   {
     .name = "gpt_partition_map",
     .iterate = gpt_partition_map_iterate,
-    .probe = gpt_partition_map_probe,
-    .get_name = gpt_partition_map_get_name
   };
 
 GRUB_MOD_INIT(gpt_partition_map)
diff --git a/partmap/pc.c b/partmap/pc.c
index 6f68ecf..fdc2e5c 100644
--- a/partmap/pc.c
+++ b/partmap/pc.c
@@ -27,178 +27,82 @@
 static struct grub_partition_map grub_pc_partition_map;
 \f
 
-/* Parse the partition representation in STR and return a partition.  */
-static grub_partition_t
-grub_partition_parse (const char *str)
-{
-  grub_partition_t p;
-  struct grub_pc_partition *pcdata;
-
-  char *s = (char *) str;
-
-  p = (grub_partition_t) grub_malloc (sizeof (*p));
-  if (! p)
-    return 0;
-
-  pcdata = (struct grub_pc_partition *) grub_malloc (sizeof (*pcdata));
-  if (! pcdata)
-    goto fail;
-
-  p->data = pcdata;
-  p->partmap = &grub_pc_partition_map;
-
-  /* Initialize some of the fields with invalid values.  */
-  pcdata->bsd_part = pcdata->dos_type = pcdata->bsd_type = p->index = -1;
-
-  /* Get the DOS partition number. The number is counted from one for
-     the user interface, and from zero internally.  */
-  pcdata->dos_part = grub_strtoul (s, &s, 0) - 1;
-
-  if (grub_errno)
-    {
-      /* Not found. Maybe only a BSD label is specified.  */
-      pcdata->dos_part = -1;
-      grub_errno = GRUB_ERR_NONE;
-    }
-  else if (*s == ',')
-    s++;
-
-  if (*s)
-    {
-      if (*s >= 'a' && *s <= 'h')
-	{
-	  pcdata->bsd_part = *s - 'a';
-	  s++;
-	}
-
-      if (*s)
-	goto fail;
-    }
-
-  if (pcdata->dos_part == -1 && pcdata->bsd_part == -1)
-    goto fail;
-
-  return p;
-
- fail:
-  grub_free (p);
-  grub_free (pcdata);
-  grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
-  return 0;
-}
-
 static grub_err_t
 pc_partition_map_iterate (grub_disk_t disk,
 			  int (*hook) (grub_disk_t disk,
 				       const grub_partition_t partition))
 {
   struct grub_partition p;
-  struct grub_pc_partition pcdata;
+  struct grub_pc_partition *pcdata;
   struct grub_pc_partition_mbr mbr;
-  struct grub_pc_partition_disk_label label;
-  struct grub_disk raw;
-
-  /* Enforce raw disk access.  */
-  raw = *disk;
-  raw.partition = 0;
 
+  pcdata = grub_malloc (sizeof (*pcdata));
   p.offset = 0;
-  pcdata.ext_offset = 0;
-  pcdata.dos_part = -1;
-  p.data = &pcdata;
+  pcdata->ext_offset = 0;
+  p.data = pcdata;
+  p.number = -1;
   p.partmap = &grub_pc_partition_map;
 
+  /* Signature check is known to cause false positives 
+     because the same signature is used for bootsectors.  */
+  if (disk->partition)
+    {
+      grub_free (pcdata);
+      return grub_error (GRUB_ERR_BAD_PART_TABLE, 
+			 "pc partition can't be nested");
+    }
+
   while (1)
     {
       int i;
       struct grub_pc_partition_entry *e;
 
       /* Read the MBR.  */
-      if (grub_disk_read (&raw, p.offset, 0, sizeof (mbr), &mbr))
+      if (grub_disk_read (disk, p.offset, 0, sizeof (mbr), &mbr))
 	goto finish;
 
       /* Check if it is valid.  */
       if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
-	return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
+	{
+	  grub_free (pcdata);
+	  return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
+	}
 
       /* Analyze DOS partitions.  */
-      for (p.index = 0; p.index < 4; p.index++)
+      for (pcdata->index = 0; pcdata->index < 4; pcdata->index++)
 	{
-	  e = mbr.entries + p.index;
-
+	  e = mbr.entries + pcdata->index;
+	  
 	  p.start = p.offset + grub_le_to_cpu32 (e->start);
 	  p.len = grub_le_to_cpu32 (e->length);
-	  pcdata.bsd_part = -1;
-	  pcdata.dos_type = e->type;
-	  pcdata.bsd_type = -1;
+	  pcdata->dos_type = e->type;
 
 	  grub_dprintf ("partition",
 			"partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n",
-			p.index, e->flag, pcdata.dos_type,
+			pcdata->index, e->flag, pcdata->dos_type,
 			(unsigned long long) p.start,
 			(unsigned long long) p.len);
 
 	  /* If this is a GPT partition, this MBR is just a dummy.  */
-	  if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && p.index == 0)
-	    return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr");
+	  if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && pcdata->index == 0)
+	    {
+	      grub_free (pcdata);
+	      return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr");
+	    }
 
 	  /* If this partition is a normal one, call the hook.  */
 	  if (! grub_pc_partition_is_empty (e->type)
 	      && ! grub_pc_partition_is_extended (e->type))
 	    {
-	      pcdata.dos_part++;
-
+	      p.number++;
+	      
 	      if (hook (disk, &p))
 		return 1;
-
-	      /* Check if this is a BSD partition.  */
-	      if (grub_pc_partition_is_bsd (e->type))
-		{
-		  /* Check if the BSD label is within the DOS partition.  */
-		  if (p.len <= GRUB_PC_PARTITION_BSD_LABEL_SECTOR)
-		    {
-		      grub_dprintf ("partition", "no space for disk label\n");
-		      continue;
-		    }
-		  /* Read the BSD label.  */
-		  if (grub_disk_read (&raw,
-				      (p.start
-				       + GRUB_PC_PARTITION_BSD_LABEL_SECTOR),
-				      0,
-				      sizeof (label),
-				      &label))
-		    goto finish;
-
-		  /* Check if it is valid.  */
-		  if (label.magic
-		      != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC))
-		    {
-		      grub_dprintf ("partition",
-				    "invalid disk label magic 0x%x on partition %d\n",
-				    label.magic, p.index);
-		      continue;
-		    }
-		  for (pcdata.bsd_part = 0;
-		       pcdata.bsd_part < grub_cpu_to_le16 (label.num_partitions);
-		       pcdata.bsd_part++)
-		    {
-		      struct grub_pc_partition_bsd_entry *be
-			= label.entries + pcdata.bsd_part;
-
-		      p.start = grub_le_to_cpu32 (be->offset);
-		      p.len = grub_le_to_cpu32 (be->size);
-		      pcdata.bsd_type = be->fs_type;
-
-		      if (be->fs_type != GRUB_PC_PARTITION_BSD_TYPE_UNUSED)
-			if (hook (disk, &p))
-			  return 1;
-		    }
-		}
 	    }
-	  else if (pcdata.dos_part < 4)
+	  else if (p.number < 4)
 	    /* If this partition is a logical one, shouldn't increase the
 	       partition number.  */
-	    pcdata.dos_part++;
+	    p.number++;
 	}
 
       /* Find an extended partition.  */
@@ -208,9 +112,9 @@ pc_partition_map_iterate (grub_disk_t disk,
 
 	  if (grub_pc_partition_is_extended (e->type))
 	    {
-	      p.offset = pcdata.ext_offset + grub_le_to_cpu32 (e->start);
-	      if (! pcdata.ext_offset)
-		pcdata.ext_offset = p.offset;
+	      p.offset = pcdata->ext_offset + grub_le_to_cpu32 (e->start);
+	      if (! pcdata->ext_offset)
+		pcdata->ext_offset = p.offset;
 
 	      break;
 	    }
@@ -222,77 +126,8 @@ pc_partition_map_iterate (grub_disk_t disk,
     }
 
  finish:
-  return grub_errno;
-}
-
-
-static grub_partition_t
-pc_partition_map_probe (grub_disk_t disk, const char *str)
-{
-  grub_partition_t p;
-  struct grub_pc_partition *pcdata;
-
-  auto int find_func (grub_disk_t d, const grub_partition_t partition);
-
-  int find_func (grub_disk_t d __attribute__ ((unused)),
-		 const grub_partition_t partition)
-    {
-      struct grub_pc_partition *partdata = partition->data;
-
-      if ((pcdata->dos_part == partdata->dos_part || pcdata->dos_part == -1)
-	  && pcdata->bsd_part == partdata->bsd_part)
-	{
-	  grub_memcpy (p, partition, sizeof (*p));
-	  p->data = pcdata;
-	  grub_memcpy (pcdata, partdata, sizeof (*pcdata));
-	  return 1;
-	}
-
-      return 0;
-    }
-
-  p = grub_partition_parse (str);
-  if (! p)
-    return 0;
-
-  pcdata = p->data;
-  pc_partition_map_iterate (disk, find_func);
-  if (grub_errno)
-    goto fail;
-
-  if (p->index < 0)
-    {
-      grub_error (GRUB_ERR_BAD_DEVICE, "no such partition");
-      goto fail;
-    }
-
-  return p;
-
- fail:
-  grub_free (p);
   grub_free (pcdata);
-  return 0;
-}
-
-
-static char *
-pc_partition_map_get_name (const grub_partition_t p)
-{
-  char *name;
-  struct grub_pc_partition *pcdata = p->data;
-
-  name = grub_malloc (13);
-  if (! name)
-    return 0;
-
-  if (pcdata->bsd_part < 0)
-    grub_sprintf (name, "%d", pcdata->dos_part + 1);
-  else if (pcdata->dos_part < 0)
-    grub_sprintf (name, "%c", pcdata->bsd_part + 'a');
-  else
-    grub_sprintf (name, "%d,%c", pcdata->dos_part + 1, pcdata->bsd_part + 'a');
-
-  return name;
+  return grub_errno;
 }
 
 \f
@@ -301,8 +136,6 @@ static struct grub_partition_map grub_pc_partition_map =
   {
     .name = "pc_partition_map",
     .iterate = pc_partition_map_iterate,
-    .probe = pc_partition_map_probe,
-    .get_name = pc_partition_map_get_name
   };
 
 GRUB_MOD_INIT(pc_partition_map)
diff --git a/partmap/sun.c b/partmap/sun.c
index 6094777..c6633a1 100644
--- a/partmap/sun.c
+++ b/partmap/sun.c
@@ -88,13 +88,9 @@ sun_partition_map_iterate (grub_disk_t disk,
 					const grub_partition_t partition))
 {
   grub_partition_t p;
-  struct grub_disk raw;
   struct grub_sun_block block;
   int partnum;
 
-  raw = *disk;
-  raw.partition = 0;
-
   p = (grub_partition_t) grub_malloc (sizeof (struct grub_partition));
   if (! p)
     return grub_errno;
@@ -102,7 +98,7 @@ sun_partition_map_iterate (grub_disk_t disk,
   p->offset = 0;
   p->data = 0;
   p->partmap = &grub_sun_partition_map;
-  if (grub_disk_read (&raw, 0, 0, sizeof (struct grub_sun_block),
+  if (grub_disk_read (disk, 0, 0, sizeof (struct grub_sun_block),
 		      &block) == GRUB_ERR_NONE)
     {
       if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic))
@@ -126,7 +122,7 @@ sun_partition_map_iterate (grub_disk_t disk,
 		      * grub_be_to_cpu16 (block.ntrks)
 		      * grub_be_to_cpu16 (block.nsect));
 	  p->len = grub_be_to_cpu32 (desc->num_sectors);
-	  p->index = partnum;
+	  p->number = partnum;
 	  if (p->len)
 	    {
 	      if (hook (disk, p))
@@ -140,68 +136,11 @@ sun_partition_map_iterate (grub_disk_t disk,
   return grub_errno;
 }
 
-static grub_partition_t
-sun_partition_map_probe (grub_disk_t disk, const char *str)
-{
-  grub_partition_t p = 0;
-  int partnum = 0;
-  char *s = (char *) str;
-
-  auto int find_func (grub_disk_t d, const grub_partition_t partition);
-
-  int find_func (grub_disk_t d __attribute__ ((unused)),
-		 const grub_partition_t partition)
-    {
-      if (partnum == partition->index)
-        {
-          p = (grub_partition_t) grub_malloc (sizeof (*p));
-          if (p)
-            grub_memcpy (p, partition, sizeof (*p));
-
-          return 1;
-        }
-
-      return 0;
-    }
-
-  grub_errno = GRUB_ERR_NONE;
-  partnum = grub_strtoul (s, 0, 10) - 1;
-  if (grub_errno == GRUB_ERR_NONE)
-    {
-      if (sun_partition_map_iterate (disk, find_func))
-        {
-          grub_free (p);
-          p = 0;
-        }
-    }
-  else
-    {
-      grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
-      p = 0;
-    }
-
-  return p;
-}
-
-static char *
-sun_partition_map_get_name (const grub_partition_t p)
-{
-  char *name;
-
-  name = grub_malloc (13);
-  if (name)
-    grub_sprintf (name, "%d", p->index + 1);
-
-  return name;
-}
-
 /* Partition map type.  */
 static struct grub_partition_map grub_sun_partition_map =
   {
     .name = "sun_partition_map",
     .iterate = sun_partition_map_iterate,
-    .probe = sun_partition_map_probe,
-    .get_name = sun_partition_map_get_name
   };
 
 GRUB_MOD_INIT(sun_partition_map)
diff --git a/parttool/pcpart.c b/parttool/pcpart.c
index 6876d0d..c0c53e6 100644
--- a/parttool/pcpart.c
+++ b/parttool/pcpart.c
@@ -47,9 +47,9 @@ static grub_err_t grub_pcpart_boot (const grub_device_t dev,
   if (dev->disk->partition->offset)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a primary partition");
 
-  index = dev->disk->partition->index;
+  index = ((struct grub_pc_partition *) dev->disk->partition->data)->index;
   part = dev->disk->partition;
-  dev->disk->partition = 0;
+  dev->disk->partition = part->parent;
 
   /* Read the MBR.  */
   if (grub_disk_read (dev->disk, 0, 0, sizeof (mbr), &mbr))
@@ -94,9 +94,9 @@ static grub_err_t grub_pcpart_type (const grub_device_t dev,
   grub_partition_t part;
   struct grub_pc_partition_mbr mbr;
 
-  index = dev->disk->partition->index;
+  index = ((struct grub_pc_partition *) dev->disk->partition->data)->index;
   part = dev->disk->partition;
-  dev->disk->partition = 0;
+  dev->disk->partition = part->parent;
 
   /* Read the parttable.  */
   if (grub_disk_read (dev->disk, part->offset, 0,
diff --git a/util/hostdisk.c b/util/hostdisk.c
index 1844a7e..675d117 100644
--- a/util/hostdisk.c
+++ b/util/hostdisk.c
@@ -321,10 +321,15 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
   {
     int is_partition = 0;
     char dev[PATH_MAX];
+    grub_partition_t part;
+    grub_disk_addr_t part_start = 0;
+
+    for (part = disk->partition; part; part = part->parent)
+      part_start += grub_partition_get_start (part);
 
     strcpy (dev, map[disk->id].device);
     if (disk->partition && strncmp (map[disk->id].device, "/dev/", 5) == 0)
-      is_partition = linux_find_partition (dev, disk->partition->start);
+      is_partition = linux_find_partition (dev, part_start);
 
     /* Open the partition.  */
     grub_dprintf ("hostdisk", "opening the device `%s' in open_device()", dev);
@@ -339,7 +344,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
     ioctl (fd, BLKFLSBUF, 0);
 
     if (is_partition)
-      sector -= disk->partition->start;
+      sector -= part_start;
   }
 #else /* ! __linux__ */
 #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
@@ -917,39 +922,27 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
     int find_partition (grub_disk_t disk __attribute__ ((unused)),
 			const grub_partition_t partition)
       {
- 	struct grub_pc_partition *pcdata = NULL;
-
-	if (strcmp (partition->partmap->name, "pc_partition_map") == 0)
-	  pcdata = partition->data;
+	grub_partition_t part;
+	grub_disk_addr_t part_start = 0;
+	grub_util_info ("Partition %d starts from %lu",
+			partition->number, partition->start);
 
-	if (pcdata)
-	  {
-	    if (pcdata->bsd_part < 0)
-	      grub_util_info ("DOS partition %d starts from %lu",
-			      pcdata->dos_part, partition->start);
-	    else
-	      grub_util_info ("BSD partition %d,%c starts from %lu",
-			      pcdata->dos_part, pcdata->bsd_part + 'a',
-			      partition->start);
-	  }
-	else
-	  {
-	      grub_util_info ("Partition %d starts from %lu",
-			      partition->index, partition->start);
-	  }
+	for (part = partition; part; part = part->parent)
+	  part_start += grub_partition_get_start (part);
 
-	if (hdg.start == partition->start)
+	if (hdg.start == part_start)
 	  {
-	    if (pcdata)
+	    if (partition->parent)
 	      {
-		dos_part = pcdata->dos_part;
-		bsd_part = pcdata->bsd_part;
+		dos_part = partition->parent->number;
+		bsd_part = partition->number;
 	      }
 	    else
 	      {
-		dos_part = partition->index;
+		dos_part = partition->number;	  
 		bsd_part = -1;
 	      }
+
 	    return 1;
 	  }
 
diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c
index bdf234c..193fa99 100644
--- a/util/i386/pc/grub-setup.c
+++ b/util/i386/pc/grub-setup.c
@@ -128,7 +128,6 @@ setup (const char *dir,
 
       /* For its end offset, include as many dummy partitions as we can.  */
       if (! grub_pc_partition_is_empty (pcdata->dos_type)
-	  && ! grub_pc_partition_is_bsd (pcdata->dos_type)
 	  && embed_region.end > p->start)
 	embed_region.end = p->start;
 
@@ -279,22 +278,19 @@ setup (const char *dir,
       /* Embed information about the installed location.  */
       if (root_dev->disk->partition)
 	{
-	  if (strcmp (root_dev->disk->partition->partmap->name,
-		      "pc_partition_map") == 0)
+	  if (root_dev->disk->partition->parent)
 	    {
-	      struct grub_pc_partition *pcdata =
-		root_dev->disk->partition->data;
-	      dos_part = pcdata->dos_part;
-	      bsd_part = pcdata->bsd_part;
+	      if (root_dev->disk->partition->parent->parent)
+		grub_util_error ("Installing on doubly nested partitiond is "
+				 "not supported");
+	      dos_part = root_dev->disk->partition->parent->number;
+	      bsd_part = root_dev->disk->partition->number;
 	    }
-	  else if (strcmp (root_dev->disk->partition->partmap->name,
-			   "gpt_partition_map") == 0)
+	  else
 	    {
-	      dos_part = root_dev->disk->partition->index;
+	      dos_part = root_dev->disk->partition->number;	  
 	      bsd_part = -1;
 	    }
-	  else
-	    grub_util_error ("No PC style partitions found");
 	}
       else
 	dos_part = bsd_part = -1;

^ permalink raw reply related	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2010-01-25  8:26 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-06-11 15:51 [PATCH] nested partitions Vladimir 'phcoder' Serbinenko
2009-07-16 20:52 ` Vladimir 'phcoder' Serbinenko
2009-07-31  7:58   ` Marco Gerards
2009-07-31  9:39     ` Vladimir 'phcoder' Serbinenko
2009-07-31 19:48       ` Vladimir 'phcoder' Serbinenko
2009-07-31 20:25         ` Vladimir 'phcoder' Serbinenko
2009-08-02 22:17         ` Robert Millan
2009-08-02 22:36           ` Vladimir 'phcoder' Serbinenko
2009-08-02 22:02   ` Robert Millan
2009-08-02 22:09     ` Vladimir 'phcoder' Serbinenko
2009-08-02 22:25       ` Robert Millan
2009-08-02 22:44         ` Vladimir 'phcoder' Serbinenko
2009-08-04 20:15           ` Robert Millan
2009-08-17 13:00             ` Vladimir 'phcoder' Serbinenko
2009-08-17 14:06               ` Robert Millan
2009-08-17 14:34                 ` Vladimir 'phcoder' Serbinenko
2009-08-23 22:57                   ` Vladimir 'phcoder' Serbinenko
2009-08-24 13:39                     ` Vladimir 'phcoder' Serbinenko
2009-08-25 20:14                       ` Vladimir 'phcoder' Serbinenko
2009-08-25 23:07                         ` Robert Millan
2009-08-25 23:13                           ` Vladimir 'phcoder' Serbinenko
2009-08-26  0:50                             ` Robert Millan
2009-08-25 20:35                       ` Seth Goldberg
2009-08-25 21:12                         ` Vladimir 'phcoder' Serbinenko
2010-01-22 16:53                           ` Robert Millan
2010-01-22 18:03                             ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-01-24 20:41                               ` Robert Millan
2010-01-24 21:20                                 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-01-25  7:23                                   ` Robert Millan
2010-01-25  0:38                                 ` Bruce Dubbs
2010-01-25  4:56                                   ` Michal Suchanek
2010-01-25  7:31                                   ` Robert Millan
2010-01-25  7:52                                     ` Robert Millan
2010-01-25  8:25                                 ` Grégoire Sutre
2010-01-22 18:43                             ` Seth Goldberg
2010-01-24 20:44                               ` Robert Millan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.