fix several issues with nested labels

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-09-04 00:49:45 +02:00
parent c8e7bf5ff7
commit 56a4b23d37
7 changed files with 140 additions and 13 deletions

View file

@ -89,6 +89,9 @@ library = {
common = grub-core/partmap/msdos.c;
common = grub-core/partmap/sun.c;
common = grub-core/partmap/sunpc.c;
common = grub-core/partmap/bsdlabel.c;
common = grub-core/partmap/netbsdlabel.c;
common = grub-core/partmap/openbsdlabel.c;
common = grub-core/script/function.c;
common = grub-core/script/lexer.c;
common = grub-core/script/main.c;

View file

@ -1208,6 +1208,16 @@ module = {
common = partmap/bsdlabel.c;
};
module = {
name = part_netbsd;
common = partmap/netbsdlabel.c;
};
module = {
name = part_openbsd;
common = partmap/openbsdlabel.c;
};
module = {
name = part_sunpc;
common = partmap/sunpc.c;

View file

@ -23,6 +23,7 @@
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/dl.h>
#include <grub/msdos_partition.h>
#ifdef GRUB_UTIL
#include <grub/util/misc.h>
@ -32,9 +33,9 @@ static struct grub_partition_map grub_bsdlabel_partition_map;
static grub_err_t
bsdlabel_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition))
iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition))
{
struct grub_partition_bsd_disk_label label;
struct grub_partition p;
@ -42,22 +43,27 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
unsigned pos;
/* Read the BSD label. */
if (grub_disk_read (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR,
0, sizeof (label), &label))
if (grub_disk_read (disk, sector, 0, sizeof (label), &label))
return grub_errno;
/* Check if it is valid. */
if (label.magic != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC))
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
{
grub_dprintf ("partition",
"bad signature (found 0x%08x, expected 0x%08x)\n",
label.magic,
grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC));
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
}
/* A kludge to determine a base of be.offset. */
if (GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION
< grub_cpu_to_le16 (label.num_partitions))
< grub_cpu_to_le16 (label.num_partitions) && freebsd)
{
struct grub_partition_bsd_entry whole_disk_be;
pos = sizeof (label) + GRUB_PC_PARTITION_BSD_LABEL_SECTOR
* GRUB_DISK_SECTOR_SIZE + sizeof (struct grub_partition_bsd_entry)
pos = sizeof (label) + sector * GRUB_DISK_SECTOR_SIZE
+ sizeof (struct grub_partition_bsd_entry)
* GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION;
if (grub_disk_read (disk, pos / GRUB_DISK_SECTOR_SIZE,
@ -68,8 +74,10 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
delta = grub_le_to_cpu32 (whole_disk_be.offset);
}
pos = sizeof (label) + GRUB_PC_PARTITION_BSD_LABEL_SECTOR
* GRUB_DISK_SECTOR_SIZE;
pos = sizeof (label) + sector * GRUB_DISK_SECTOR_SIZE;
grub_dprintf ("partition", "bsdlabel with %d partitions detected\n",
grub_cpu_to_le16 (label.num_partitions));
for (p.number = 0;
p.number < grub_cpu_to_le16 (label.num_partitions);
@ -124,24 +132,112 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
if (hook (disk, &p))
return grub_errno;
}
return GRUB_ERR_NONE;
}
#if !defined (NETBSDLABEL) && !defined (OPENBSDLABEL)
static grub_err_t
bsdlabel_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition))
{
if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos")
== 0 && disk->partition->msdostype == GRUB_PC_PARTITION_TYPE_FREEBSD)
{
grub_dprintf ("partition", "FreeBSD embedded iterating\n");
return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 1,
hook);
}
if (disk->partition
&& (grub_strcmp (disk->partition->partmap->name, "msdos") == 0
|| grub_strcmp (disk->partition->partmap->name, "bsd") == 0
|| grub_strcmp (disk->partition->partmap->name, "netbsd") == 0
|| grub_strcmp (disk->partition->partmap->name, "openbsd") == 0))
{
grub_dprintf ("partition", "no embedded iterating\n");
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");
}
return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, hook);
}
#else
#ifdef OPENBSDLABEL
#define GRUB_PC_PARTITION_TYPE_BSD GRUB_PC_PARTITION_TYPE_OPENBSD
#else
#define GRUB_PC_PARTITION_TYPE_BSD GRUB_PC_PARTITION_TYPE_NETBSD
#endif
static grub_err_t
bsdlabel_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition))
{
grub_err_t err;
if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos")
== 0)
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");
{
struct grub_msdos_partition_mbr mbr;
unsigned i;
err = grub_disk_read (disk, 0, 0, sizeof (mbr), &mbr);
if (err)
return err;
for (i = 0; i < ARRAY_SIZE (mbr.entries); i++)
if (mbr.entries[i].type == GRUB_PC_PARTITION_TYPE_BSD)
{
err = iterate_real (disk, mbr.entries[i].start
+ GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, hook);
if (err != GRUB_ERR_BAD_PART_TABLE)
return err;
}
}
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no bsdlabel found");
}
#endif
/* Partition map type. */
static struct grub_partition_map grub_bsdlabel_partition_map =
{
#if defined (OPENBSDLABEL)
.name = "openbsd",
#elif defined (NETBSDLABEL)
.name = "netbsd",
#else
.name = "bsd",
#endif
.iterate = bsdlabel_partition_map_iterate,
};
#if defined (OPENBSDLABEL)
GRUB_MOD_INIT(part_openbsd)
#elif defined (NETBSDLABEL)
GRUB_MOD_INIT(part_netbsd)
#else
GRUB_MOD_INIT(part_bsd)
#endif
{
grub_partition_map_register (&grub_bsdlabel_partition_map);
}
#if defined (OPENBSDLABEL)
GRUB_MOD_FINI(part_openbsd)
#elif defined (NETBSDLABEL)
GRUB_MOD_FINI(part_netbsd)
#else
GRUB_MOD_FINI(part_bsd)
#endif
{
grub_partition_map_unregister (&grub_bsdlabel_partition_map);
}

View file

@ -37,6 +37,15 @@ pc_partition_map_iterate (grub_disk_t disk,
int labeln = 0;
grub_disk_addr_t lastaddr;
grub_disk_addr_t ext_offset;
grub_disk_addr_t delta = 0;
if (disk->partition && disk->partition->partmap == &grub_msdos_partition_map)
{
if (disk->partition->msdostype == GRUB_PC_PARTITION_TYPE_LINUX_MINIX)
delta = disk->partition->offset;
else
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");
}
p.offset = 0;
ext_offset = 0;
@ -81,8 +90,9 @@ pc_partition_map_iterate (grub_disk_t disk,
{
e = mbr.entries + p.index;
p.start = p.offset + grub_le_to_cpu32 (e->start);
p.start = p.offset + grub_le_to_cpu32 (e->start) - delta;
p.len = grub_le_to_cpu32 (e->length);
p.msdostype = e->type;
grub_dprintf ("partition",
"partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n",

View file

@ -0,0 +1,2 @@
#define NETBSDLABEL 1
#include "bsdlabel.c"

View file

@ -0,0 +1,2 @@
#define OPENBSDLABEL 1
#include "bsdlabel.c"

View file

@ -65,6 +65,10 @@ struct grub_partition
/* The type partition map. */
grub_partition_map_t partmap;
/* The type of partition whne it's on MSDOS.
Used for embedding detection. */
grub_uint8_t msdostype;
};
grub_partition_t EXPORT_FUNC(grub_partition_probe) (struct grub_disk *disk,