Support some annoying BSD and Minix subpartitions.

* Makefile.util.def (libgrub.a): Add grub-core/partmap/bsdlabel.c.
	* grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name):
	Properly handle concatenation.
	* grub-core/kern/device.c (grub_device_iterate): Likewise.
	* grub-core/normal/completion.c (iterate_partition): Likewise.
	* grub-core/kern/disk.c (grub_disk_open): Make disk->name not
	contain partition. All users updated.
	* grub-core/partmap/bsdlabel.c (grub_netbsdlabel_partition_map): New
	struct.
	(grub_openbsdlabel_partition_map): Likewise.
	(bsdlabel_partition_map_iterate): Rename to ..
	(iterate_real): ... this. New arguments sector, freebsd and pmap.
	(bsdlabel_partition_map_iterate): New function.
	(netopenbsdlabel_partition_map_iterate): Likewise.
	(netbsdlabel_partition_map_iterate): Likewise.
	(openbsdlabel_partition_map_iterate): Likewise.
	(GRUB_MOD_INIT): Register new partmaps.
	(GRUB_MOD_FINI): Unregister new partmaps.
	* grub-core/partmap/msdos.c (pc_partition_map_iterate): Rename to ...
	(grub_partition_msdos_iterate): ... this. All users updated.
	Don't support embedding other than in a minix partition.
	* include/grub/msdos_partition.h (grub_partition_msdos_iterate): New
	proto.
	* include/grub/partition.h (grub_partition): New field msdostype.
	* util/grub-install.in: Handle openbsd and netbsd types being in
	part_bsd module.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-09-20 21:45:06 +02:00
commit 74342e312f
11 changed files with 225 additions and 57 deletions

View file

@ -1,3 +1,34 @@
2010-09-20 Vladimir Serbinenko <phcoder@gmail.com>
Support some annoying BSD and Minix subpartitions.
* Makefile.util.def (libgrub.a): Add grub-core/partmap/bsdlabel.c.
* grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name):
Properly handle concatenation.
* grub-core/kern/device.c (grub_device_iterate): Likewise.
* grub-core/normal/completion.c (iterate_partition): Likewise.
* grub-core/kern/disk.c (grub_disk_open): Make disk->name not
contain partition. All users updated.
* grub-core/partmap/bsdlabel.c (grub_netbsdlabel_partition_map): New
struct.
(grub_openbsdlabel_partition_map): Likewise.
(bsdlabel_partition_map_iterate): Rename to ..
(iterate_real): ... this. New arguments sector, freebsd and pmap.
(bsdlabel_partition_map_iterate): New function.
(netopenbsdlabel_partition_map_iterate): Likewise.
(netbsdlabel_partition_map_iterate): Likewise.
(openbsdlabel_partition_map_iterate): Likewise.
(GRUB_MOD_INIT): Register new partmaps.
(GRUB_MOD_FINI): Unregister new partmaps.
* grub-core/partmap/msdos.c (pc_partition_map_iterate): Rename to ...
(grub_partition_msdos_iterate): ... this. All users updated.
Don't support embedding other than in a minix partition.
* include/grub/msdos_partition.h (grub_partition_msdos_iterate): New
proto.
* include/grub/partition.h (grub_partition): New field msdostype.
* util/grub-install.in: Handle openbsd and netbsd types being in
part_bsd module.
2010-09-20 Vladimir Serbinenko <phcoder@gmail.com>
Split mdraid.mod into mdraid09.mod and mdraid1x.mod.

View file

@ -82,6 +82,7 @@ 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/script/function.c;
common = grub-core/script/lexer.c;
common = grub-core/script/main.c;

View file

@ -727,7 +727,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
{
/* This is a hard disk partition. */
grub_disk_t parent = 0;
char *partition_name = 0;
const grub_partition_t tpart = NULL;
char *device_name;
grub_efi_device_path_t *dup_dp, *dup_ldp;
grub_efi_hard_drive_device_path_t hd;
@ -766,7 +766,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
if (grub_partition_get_start (part) == hd.partition_start
&& grub_partition_get_len (part) == hd.partition_size)
{
partition_name = grub_partition_get_name (part);
tpart = part;
return 1;
}
@ -795,14 +795,17 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
grub_memcpy (&hd, ldp, sizeof (hd));
grub_partition_iterate (parent, find_partition);
if (! partition_name)
if (! tpart)
{
grub_disk_close (parent);
return 0;
}
{
char *partition_name = grub_partition_get_name (tpart);
device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
grub_free (partition_name);
}
grub_disk_close (parent);
return device_name;

View file

@ -135,28 +135,28 @@ grub_device_iterate (int (*hook) (const char *name))
int iterate_partition (grub_disk_t disk, const grub_partition_t partition)
{
char *partition_name;
struct part_ent *p;
partition_name = grub_partition_get_name (partition);
if (! partition_name)
return 1;
char *part_name;
p = grub_malloc (sizeof (*p));
if (!p)
{
grub_free (partition_name);
return 1;
}
p->name = grub_xasprintf ("%s,%s", disk->name, partition_name);
if (!p->name)
part_name = grub_partition_get_name (partition);
if (!part_name)
{
grub_free (p);
return 1;
}
p->name = grub_xasprintf ("%s,%s", disk->name, part_name);
grub_free (part_name);
if (!p->name)
{
grub_free (partition_name);
grub_free (p);
return 1;
}
grub_free (partition_name);
p->next = ents;
ents = p;

View file

@ -248,10 +248,6 @@ grub_disk_open (const char *name)
if (! disk)
return 0;
disk->name = grub_strdup (name);
if (! disk->name)
goto fail;
p = find_part_sep (name);
if (p)
{
@ -263,7 +259,13 @@ grub_disk_open (const char *name)
grub_memcpy (raw, name, len);
raw[len] = '\0';
disk->name = grub_strdup (raw);
}
else
disk->name = grub_strdup (name);
if (! disk->name)
goto fail;
for (dev = grub_disk_dev_list; dev; dev = dev->next)
{

View file

@ -100,15 +100,16 @@ static int
iterate_partition (grub_disk_t disk, const grub_partition_t p)
{
const char *disk_name = disk->name;
char *partition_name = grub_partition_get_name (p);
char *name;
int ret;
char *part_name;
if (! partition_name)
part_name = grub_partition_get_name (p);
if (! part_name)
return 1;
name = grub_xasprintf ("%s,%s", disk_name, partition_name);
grub_free (partition_name);
name = grub_xasprintf ("%s,%s", disk_name, part_name);
grub_free (part_name);
if (! name)
return 1;

View file

@ -23,16 +23,21 @@
#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>
#endif
static struct grub_partition_map grub_bsdlabel_partition_map;
static struct grub_partition_map grub_netbsdlabel_partition_map;
static struct grub_partition_map grub_openbsdlabel_partition_map;
static grub_err_t
bsdlabel_partition_map_iterate (grub_disk_t disk,
iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd,
struct grub_partition_map *pmap,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition))
{
@ -42,8 +47,7 @@ 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. */
@ -52,12 +56,12 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
/* 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 +72,7 @@ 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;
for (p.number = 0;
p.number < grub_cpu_to_le16 (label.num_partitions);
@ -88,13 +91,7 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
p.start = grub_le_to_cpu32 (be.offset);
p.len = grub_le_to_cpu32 (be.size);
p.partmap = &grub_bsdlabel_partition_map;
grub_dprintf ("partition",
"partition %d: type 0x%x, start 0x%llx, len 0x%llx\n",
p.number, be.fs_type,
(unsigned long long) p.start,
(unsigned long long) p.len);
p.partmap = pmap;
if (p.len == 0)
continue;
@ -103,13 +100,6 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
{
#ifdef GRUB_UTIL
char *partname;
#endif
grub_dprintf ("partition",
"partition %d: invalid start (found 0x%llx, wanted >= 0x%llx)\n",
p.number,
(unsigned long long) p.start,
(unsigned long long) delta);
#ifdef GRUB_UTIL
/* disk->partition != NULL as 0 < delta */
partname = grub_partition_get_name (disk->partition);
grub_util_warn ("Discarding improperly nested partition (%s,%s,%s%d)",
@ -124,24 +114,138 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
if (hook (disk, &p))
return grub_errno;
}
return GRUB_ERR_NONE;
}
/* Partition map type. */
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)
return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 1,
&grub_bsdlabel_partition_map, hook);
if (disk->partition
&& (grub_strcmp (disk->partition->partmap->name, "msdos") == 0
|| disk->partition->partmap == &grub_bsdlabel_partition_map
|| disk->partition->partmap == &grub_netbsdlabel_partition_map
|| disk->partition->partmap == &grub_openbsdlabel_partition_map))
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");
return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0,
&grub_bsdlabel_partition_map, hook);
}
/* This is a total breakage. Even when net-/openbsd label is inside partition
it actually describes the whole disk.
*/
static grub_err_t
netopenbsdlabel_partition_map_iterate (grub_disk_t disk, grub_uint8_t type,
struct grub_partition_map *pmap,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition))
{
int count = 0;
auto int check_msdos (grub_disk_t dsk,
const grub_partition_t partition);
int check_msdos (grub_disk_t dsk,
const grub_partition_t partition)
{
grub_err_t err;
if (partition->msdostype != type)
return 0;
err = iterate_real (dsk, partition->start
+ GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, pmap, hook);
if (err == GRUB_ERR_NONE)
{
count++;
return 1;
}
if (err == GRUB_ERR_BAD_PART_TABLE)
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
grub_print_error ();
return 0;
}
if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos")
== 0)
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");
{
grub_err_t err;
err = grub_partition_msdos_iterate (disk, check_msdos);
if (err)
return err;
if (!count)
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no bsdlabel found");
}
return GRUB_ERR_NONE;
}
static grub_err_t
netbsdlabel_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition))
{
return netopenbsdlabel_partition_map_iterate (disk,
GRUB_PC_PARTITION_TYPE_NETBSD,
&grub_netbsdlabel_partition_map,
hook);
}
static grub_err_t
openbsdlabel_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition))
{
return netopenbsdlabel_partition_map_iterate (disk,
GRUB_PC_PARTITION_TYPE_OPENBSD,
&grub_openbsdlabel_partition_map,
hook);
}
static struct grub_partition_map grub_bsdlabel_partition_map =
{
.name = "bsd",
.iterate = bsdlabel_partition_map_iterate,
};
static struct grub_partition_map grub_openbsdlabel_partition_map =
{
.name = "openbsd",
.iterate = openbsdlabel_partition_map_iterate,
};
static struct grub_partition_map grub_netbsdlabel_partition_map =
{
.name = "netbsd",
.iterate = netbsdlabel_partition_map_iterate,
};
GRUB_MOD_INIT(part_bsd)
{
grub_partition_map_register (&grub_bsdlabel_partition_map);
grub_partition_map_register (&grub_netbsdlabel_partition_map);
grub_partition_map_register (&grub_openbsdlabel_partition_map);
}
GRUB_MOD_FINI(part_bsd)
{
grub_partition_map_unregister (&grub_bsdlabel_partition_map);
grub_partition_map_unregister (&grub_netbsdlabel_partition_map);
grub_partition_map_unregister (&grub_openbsdlabel_partition_map);
}

View file

@ -27,8 +27,8 @@
static struct grub_partition_map grub_msdos_partition_map;
static grub_err_t
pc_partition_map_iterate (grub_disk_t disk,
grub_err_t
grub_partition_msdos_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition))
{
@ -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->start;
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",
@ -251,7 +261,7 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int nsectors,
static struct grub_partition_map grub_msdos_partition_map =
{
.name = "msdos",
.iterate = pc_partition_map_iterate,
.iterate = grub_partition_msdos_iterate,
#ifdef GRUB_UTIL
.embed = pc_partition_map_embed
#endif

View file

@ -22,6 +22,8 @@
#include <grub/symbol.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/disk.h>
#include <grub/partition.h>
/* The signature. */
#define GRUB_PC_PARTITION_SIGNATURE 0xaa55
@ -114,4 +116,9 @@ grub_msdos_partition_is_extended (int type)
|| type == GRUB_PC_PARTITION_TYPE_LINUX_EXTENDED);
}
grub_err_t
grub_partition_msdos_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition));
#endif /* ! GRUB_PC_PARTITION_HEADER */

View file

@ -77,6 +77,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,

View file

@ -470,7 +470,12 @@ fi
# filesystem will be accessible).
partmap_module=
for x in `$grub_probe --target=partmap --device ${grub_device} 2> /dev/null`; do
partmap_module="$partmap_module part_$x";
case "$x" in
netbsd | openbsd)
partmap_module="$partmap_module part_bsd";;
*)
partmap_module="$partmap_module part_$x";;
esac
done
# Device abstraction module, if any (lvm, raid).