Use libgeom on FreeBSD to detect partitions.

* Makefile.util.def (grub-mkimage): Add LIBGEOM to ldadd.
	(grub-mkrelpath): Likewise.
	(grub-script-check): Likewise.
	(grub-editenv): Likewise.
	(grub-mkpasswd-pbkdf2): Likewise.
	(grub-fstest): Likewise.
	(grub-mkfont): Likewise.
	(grub-mkdevicemap): Likewise.
	(grub-probe): Likewise.
	(grub-setup): Likewise.
	(grub-ofpathname): Likewise.
	(grub-mklayout): Likewise.
	(example_unit_test): Likewise.
	(grub-menulst2cfg): Likewise.
	* grub-core/Makefile.core.def (grub-emu): Likewise.
	(grub-emu-lite): Likewise.
	* configure.ac: Check for -lgeom on FreeBSD and set LIBGEOM.
	* grub-core/kern/emu/hostdisk.c [FreeBSD]: Include libgeom.h. Don't
	define HAVE_DIOCGDINFO.
	(follow_geom_up) [FreeBSD]: New function.
	(find_partition_start) [FreeBSD]: Rewritten using follow_geom_up.
	(convert_system_partition_to_system_disk) [FreeBSD]: Likewise.
	(grub_util_biosdisk_get_grub_dev) [FreeBSD]: Use FreeBSD path
	unconditionally of HAVE_DIOCGDINFO.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-03-26 12:59:02 +01:00
parent 82fe6c751b
commit f4727da93f
5 changed files with 132 additions and 20 deletions

View file

@ -104,7 +104,9 @@ struct hd_geometry
# include <libdevmapper.h>
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <libgeom.h>
#elif defined(__NetBSD__)
# define HAVE_DIOCGDINFO
# include <sys/ioctl.h>
# include <sys/disklabel.h> /* struct disklabel */
@ -339,7 +341,68 @@ device_is_mapped (const char *dev)
}
#endif /* HAVE_DEVICE_MAPPER */
#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO)
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
/* FIXME: geom actually gives us the whole container hierarchy.
It can be used more efficiently than this. */
static void
follow_geom_up (const char *name, grub_disk_addr_t *off_out, char **name_out)
{
struct gmesh mesh;
struct gclass *class;
int error;
struct ggeom *geom;
grub_util_info ("following geom '%s'", name);
error = geom_gettree (&mesh);
if (error != 0)
grub_util_error ("couldn't open geom");
LIST_FOREACH (class, &mesh.lg_class, lg_class)
if (strcasecmp (class->lg_name, "part") == 0)
break;
if (!class)
grub_util_error ("couldn't open geom part");
LIST_FOREACH (geom, &class->lg_geom, lg_geom)
{
struct gprovider *provider;
LIST_FOREACH (provider, &geom->lg_provider, lg_provider)
if (strcmp (provider->lg_name, name) == 0)
{
char *name_tmp = xstrdup (geom->lg_name);
grub_disk_addr_t off = 0;
struct gconfig *config;
grub_util_info ("geom '%s' has parent '%s'", name, geom->lg_name);
follow_geom_up (name_tmp, &off, name_out);
free (name_tmp);
LIST_FOREACH (config, &provider->lg_config, lg_config)
if (strcasecmp (config->lg_name, "start") == 0)
off += strtoull (config->lg_val, 0, 10);
if (off_out)
*off_out = off;
return;
}
}
grub_util_info ("geom '%s' has no parent", name);
if (name_out)
*name_out = xstrdup (name);
if (off_out)
*off_out = 0;
}
static grub_disk_addr_t
find_partition_start (const char *dev)
{
grub_disk_addr_t out;
if (strncmp (dev, "/dev/", sizeof ("/dev/") - 1) != 0)
return 0;
follow_geom_up (dev + sizeof ("/dev/") - 1, &out, NULL);
return out;
}
#elif defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO)
static grub_disk_addr_t
find_partition_start (const char *dev)
{
@ -1286,7 +1349,17 @@ devmapper_out:
path[8] = 0;
return path;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
char *out, *out2;
if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0)
return xstrdup (os_dev);
follow_geom_up (os_dev + sizeof ("/dev/") - 1, NULL, &out);
out2 = xasprintf ("/dev/%s", out);
free (out);
return out2;
#elif defined(__APPLE__)
char *path = xstrdup (os_dev);
if (strncmp ("/dev/", path, 5) == 0)
{
@ -1464,7 +1537,8 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
#endif
return make_device_name (drive, -1, -1);
#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO)
#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
/* Linux counts partitions uniformly, whether a BSD partition or a DOS
partition, so mapping them to GRUB devices is not trivial.
Here, get the start sector of a partition by HDIO_GETGEO, and