grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] nested partitions


From: Marco Gerards
Subject: Re: [PATCH] nested partitions
Date: Fri, 31 Jul 2009 09:58:39 +0200
User-agent: Gnus/5.110006 (No Gnus v0.6) Emacs/21.4 (gnu/linux)

"Vladimir 'phcoder' Serbinenko" <address@hidden> writes:

> Rediff
>
> On Thu, Jun 11, 2009 at 5:51 PM, Vladimir 'phcoder'
> Serbinenko<address@hidden> wrote:
>> 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.

Can you please explain what you mean by that you have to specify the
slice and you have to use search?

What makes this experimental and dangerous?  Can you send in a patch
that isn't?

Here a only a few comments on this patch.  In order to properly review
it, can you explain what the design of the patch is and how it
essentially works?  It is important to discuss that as well.  Can you
also describe which problems the patch solves and introduces?

> Personal git repository: http://repo.or.cz/w/grub2/phcoder.git
>
> diff --git a/ChangeLog b/ChangeLog
> index e617831..0e02e01 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,3 +1,71 @@
> +2009-06-08  Vladimir Serbinenko  <address@hidden>
> +
> +     Nested partitions
> +
> +     * commands/blocklist.c (grub_cmd_blocklist): handle nested partitions

Please start with a capital letter and end with a `.'.  I noticed that
you have committed other patches with this problem in the changelog
entry.  If you commit something else and if you have the time, I would
be happy if you could fix that too :-)

> +     * 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

What do you mean by "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-07-16  Vladimir Serbinenko  <address@hidden>
>  
>       Enable all targets that can be built by default
> 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);

Why do you need this change?  Can you explain what this does?

>    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 07ff04e..8fec4f6 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 c70f7d2..075569d 100644
> --- a/conf/i386-coreboot.rmk
> +++ b/conf/i386-coreboot.rmk
> @@ -134,8 +134,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                                  \
>       \
> diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
> index 513e1b7..f109375 100644
> --- a/conf/i386-ieee1275.rmk
> +++ b/conf/i386-ieee1275.rmk
> @@ -88,8 +88,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                                  \
>       \
> diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
> index f1915b6..c4f7710 100644
> --- a/conf/i386-pc.rmk
> +++ b/conf/i386-pc.rmk
> @@ -112,7 +112,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                                  \
> @@ -148,8 +148,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 b12635e..74decbe 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                                  \
>       \
> diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk
> index 8183cbc..af932d8 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.

2009?

> + *  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
>  
>  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 e167fb6..6eb9e4b 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..4bcd8c7 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,22 +175,58 @@ 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;
>  }
> @@ -129,5 +234,30 @@ grub_partition_iterate (struct grub_disk *disk,
>  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/bsd.c b/loader/i386/bsd.c
> index 468e6d0..d9135b2 100644
> --- a/loader/i386/bsd.c
> +++ b/loader/i386/bsd.c
> @@ -86,7 +86,6 @@ grub_bsd_get_device (grub_uint32_t * biosdev,
>                    grub_uint32_t * unit,
>                    grub_uint32_t * slice, grub_uint32_t * part)
>  {
> -  char *p;
>    grub_device_t dev; 
>  
>    *biosdev = grub_get_root_biosnumber () & 0xff;
> @@ -96,21 +95,13 @@ grub_bsd_get_device (grub_uint32_t * biosdev,
>    dev = grub_device_open (0);
>    if (dev && dev->disk && dev->disk->partition)
>      {
> -
> -      p = dev->disk->partition->partmap->get_name (dev->disk->partition);
> -      if (p)
> +      if (dev->disk->partition->parent)
>       {
> -       if ((p[0] >= '0') && (p[0] <= '9'))
> -         {
> -           *slice = grub_strtoul (p, &p, 0);
> -
> -           if ((p) && (p[0] == ','))
> -             p++;
> -         }
> -
> -       if ((p[0] >= 'a') && (p[0] <= 'z'))
> -         *part = p[0] - 'a';
> +       *part = dev->disk->partition->number;
> +       *slice = dev->disk->partition->parent->number + 1;
>       }
> +      else
> +     *slice = dev->disk->partition->number + 1;
>      }
>    if (dev)
>      grub_device_close (dev);
> diff --git a/loader/i386/multiboot.c b/loader/i386/multiboot.c
> index 8ce315e..8b8a1a9 100644
> --- a/loader/i386/multiboot.c
> +++ b/loader/i386/multiboot.c
> @@ -155,7 +155,6 @@ static int
>  grub_multiboot_get_bootdev (grub_uint32_t *bootdev)
>  {
>  #ifdef GRUB_MACHINE_PCBIOS
> -  char *p;
>    grub_uint32_t biosdev, slice = ~0, part = ~0;
>    grub_device_t dev;
>  
> @@ -164,21 +163,13 @@ grub_multiboot_get_bootdev (grub_uint32_t *bootdev)
>    dev = grub_device_open (0);
>    if (dev && dev->disk && dev->disk->partition)
>      {
> -
> -      p = dev->disk->partition->partmap->get_name (dev->disk->partition);
> -      if (p)
> +      if (dev->disk->partition->parent)
>       {
> -       if ((p[0] >= '0') && (p[0] <= '9'))
> -         {
> -           slice = grub_strtoul (p, &p, 0) - 1;
> -
> -           if ((p) && (p[0] == ','))
> -             p++;
> -         }
> -
> -       if ((p[0] >= 'a') && (p[0] <= 'z'))
> -         part = p[0] - 'a';
> +       part = dev->disk->partition->number;
> +       slice = dev->disk->partition->parent->number;
>       }
> +      else
> +     slice = dev->disk->partition->number;
>      }
>    if (dev)
>      grub_device_close (dev);
> diff --git a/loader/i386/pc/chainloader.c b/loader/i386/pc/chainloader.c
> index caf1450..108884b 100644
> --- a/loader/i386/pc/chainloader.c
> +++ b/loader/i386/pc/chainloader.c
> @@ -31,6 +31,7 @@
>  #include <grub/machine/memory.h>
>  #include <grub/dl.h>
>  #include <grub/command.h>
> +#include <grub/pc_partition.h>
>  #include <grub/machine/biosnum.h>
>  
>  static grub_dl_t my_mod;
> @@ -94,10 +95,28 @@ grub_chainloader_cmd (const char *filename, 
> grub_chainloader_flags_t flags)
>    dev = grub_device_open (0);
>    if (dev && dev->disk && dev->disk->partition)
>      {
> -      grub_disk_read (dev->disk, dev->disk->partition->offset, 446, 64,
> -                   (void *) GRUB_MEMORY_MACHINE_PART_TABLE_ADDR);
> -      part_addr = (void *) (GRUB_MEMORY_MACHINE_PART_TABLE_ADDR
> -                         + (dev->disk->partition->index << 4));
> +      grub_disk_t disk = dev->disk;
> +
> +      if (disk)
> +     {
> +       grub_partition_t p = disk->partition;
> +
> +       /* In i386-pc, the id is equal to the BIOS drive number.  */
> +       drive = (int) disk->id;
> +
> +       if (p && grub_strcmp (p->partmap->name, "pc_partition_map") == 0)
> +         {
> +           disk->partition = 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
> +                                 + (((struct grub_pc_partition *) p->data)
> +                                    ->index << 4));
> +           disk->partition = p;
> +         }
> +     }
> +
> +      grub_device_close (dev);
>      }
>  
>    if (dev)
> 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;
> -}
>  
>  
>  /* 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;
> -}
> -
>  
>  /* 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;
> -}
> -
>  
>  /* 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..68c199f
> --- /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;
> +
> +
> +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;
> +}
> +
> +
> +/* 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;
> -}
> -
>  
>  /* 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..b195087 100644
> --- a/partmap/pc.c
> +++ b/partmap/pc.c
> @@ -27,178 +27,82 @@
>  static struct grub_partition_map grub_pc_partition_map;
>  
>  
> -/* 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;
>  }
>  
>  
> @@ -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 d84e7f3..994e256 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__)
> @@ -919,39 +924,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 5a51964..aa30fa3 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;
>  
> @@ -278,22 +277,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;
> _______________________________________________
> Grub-devel mailing list
> address@hidden
> http://lists.gnu.org/mailman/listinfo/grub-devel





reply via email to

[Prev in Thread] Current Thread [Next in Thread]