> without being able to perform any task other than getting "error: > unknown filesystem." > > The problem comes from DIOCGDINFO which apparently is broken on FreeBSD (and this is just one way it misbehaves). So I rewrote it with geom. Patch attached. Was tested on IRC and it fixed the problem. Needs to be tested on GPT.
-- Regards Vladimir 'φ-coder/phcoder' Serbinenko
=== modified file 'Makefile.util.def'
--- Makefile.util.def 2010-12-01 21:42:11 +0000
+++ Makefile.util.def 2011-03-25 16:07:37 +0000
@@ -122,7 +122,7 @@
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBLZMA)';
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
cppflags = '-DGRUB_PKGLIBROOTDIR=\"$(pkglibrootdir)\"';
};
@@ -135,7 +135,7 @@
ldadd = libgrubmods.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
program = {
@@ -147,7 +147,7 @@
ldadd = libgrubmods.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
program = {
@@ -159,7 +159,7 @@
ldadd = libgrubmods.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
program = {
@@ -171,7 +171,7 @@
ldadd = libgrubmods.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
cflags = '$(CFLAGS_GCRY)';
cppflags = '$(CPPFLAGS_GCRY)';
};
@@ -209,7 +209,7 @@
ldadd = libgrubmods.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
program = {
@@ -224,7 +224,7 @@
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(freetype_libs)';
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
condition = COND_GRUB_MKFONT;
};
@@ -243,7 +243,7 @@
ldadd = libgrubmods.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
program = {
@@ -255,7 +255,7 @@
ldadd = libgrubmods.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
program = {
@@ -272,7 +272,7 @@
ldadd = libgrubmods.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
enable = i386_pc;
enable = sparc64_ieee1275;
@@ -287,7 +287,7 @@
ldadd = libgrubmods.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBGEOM)';
enable = sparc64_ieee1275;
};
@@ -301,7 +301,7 @@
ldadd = libgrubmods.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
data = {
@@ -611,7 +611,7 @@
ldadd = libgrubmods.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
- ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
program = {
@@ -624,5 +624,5 @@
ldadd = libgrubmods.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
=== modified file 'configure.ac'
--- configure.ac 2011-01-16 11:54:03 +0000
+++ configure.ac 2011-03-25 16:07:37 +0000
@@ -890,6 +890,15 @@
AC_SUBST([LIBDEVMAPPER])
+LIBGEOM=
+if test x$host_kernel = xkfreebsd; then
+ AC_CHECK_LIB([geom], [geom_gettree], [],
+ [AC_MSG_ERROR([Your platform requires libgeom])])
+ LIBGEOM="-lgeom"
+fi
+
+AC_SUBST([LIBGEOM])
+
AC_CHECK_LIB([lzma], [lzma_code],
[LIBLZMA="-llzma"
AC_DEFINE([HAVE_LIBLZMA], [1],
=== modified file 'grub-core/Makefile.core.def'
--- grub-core/Makefile.core.def 2011-01-14 18:21:06 +0000
+++ grub-core/Makefile.core.def 2011-03-25 19:41:24 +0000
@@ -200,7 +200,7 @@
ldadd = 'kernel.img$(EXEEXT)';
ldadd = '$(MODULE_FILES)';
- ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
enable = emu;
};
@@ -212,7 +212,7 @@
emu_nodist = symlist.c;
ldadd = 'kernel.img$(EXEEXT)';
- ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
+ ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
enable = emu;
};
=== modified file 'grub-core/kern/emu/hostdisk.c'
--- grub-core/kern/emu/hostdisk.c 2010-11-06 23:10:49 +0000
+++ grub-core/kern/emu/hostdisk.c 2011-03-25 21:19:16 +0000
@@ -92,6 +92,8 @@
# include <sys/disk.h> /* DIOCGMEDIASIZE */
# include <sys/param.h>
# include <sys/sysctl.h>
+# define MAJOR(dev) major(dev)
+# define FLOPPY_MAJOR 2
#endif
#if defined(__APPLE__)
@@ -102,7 +104,9 @@
# 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 */
@@ -337,7 +341,68 @@
}
#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)
{
@@ -1284,7 +1349,17 @@
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)
{
@@ -1440,6 +1515,7 @@
if (stat (os_dev, &st) < 0)
{
grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);
+ grub_util_info ("cannot stat `%s'", os_dev);
return 0;
}
@@ -1448,6 +1524,7 @@
{
grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"no mapping exists for `%s'", os_dev);
+ grub_util_info ("no mapping exists for `%s'", os_dev);
return 0;
}
@@ -1462,7 +1539,8 @@
#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
signature.asc
Description: OpenPGP digital signature

