Here is a revamped patch.

Samuel
=== modified file 'Makefile.util.def'
--- Makefile.util.def   2012-04-01 19:35:18 +0000
+++ Makefile.util.def   2012-04-22 18:26:01 +0000
@@ -170,7 +170,7 @@
   ldadd = libgrubgcry.a;
   ldadd = libgrubkern.a;
   ldadd = grub-core/gnulib/libgnu.a;
-  ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) 
$(LIBGEOM)';
+  ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) 
$(LIBGEOM) $(LIBSTORE)';
 };
 
 program = {
@@ -300,7 +300,7 @@
   ldadd = libgrubgcry.a;
   ldadd = libgrubkern.a;
   ldadd = grub-core/gnulib/libgnu.a;
-  ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) 
$(LIBGEOM)';
+  ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) 
$(LIBGEOM) $(LIBSTORE)';
 };
 
 program = {
@@ -316,7 +316,7 @@
   ldadd = libgrubkern.a;
   ldadd = libgrubgcry.a;
   ldadd = grub-core/gnulib/libgnu.a;
-  ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) 
$(LIBGEOM)';
+  ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) 
$(LIBGEOM) $(LIBSTORE)';
   cppflags = '-DGRUB_SETUP_BIOS=1';
 };
 
@@ -334,7 +334,7 @@
   ldadd = libgrubkern.a;
   ldadd = libgrubgcry.a;
   ldadd = grub-core/gnulib/libgnu.a;
-  ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) 
$(LIBGEOM)';
+  ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) 
$(LIBGEOM) $(LIBSTORE)';
   cppflags = '-DGRUB_SETUP_SPARC64=1';
 };
 

=== modified file 'configure.ac'
--- configure.ac        2012-04-19 09:34:43 +0000
+++ configure.ac        2012-04-22 17:50:59 +0000
@@ -341,6 +341,18 @@
 ])
 AC_SUBST([LIBUTIL])
 
+# On Hurd we need libstore for kern/emu/getroot.c
+case "$host_kernel" in 
+  hurd)
+    AC_CHECK_HEADER([hurd/store.h], [], [AC_MSG_ERROR([hurd/store.h is 
needed])])
+    AC_CHECK_LIB([store], [store_create], [], [AC_MSG_ERROR([libstore is 
needed])])
+    LIBSTORE="-lstore"
+    ;;
+  *)
+    ;;
+esac
+AC_SUBST([LIBSTORE])
+
 #
 # Check for host and build compilers.
 #

=== modified file 'util/getroot.c'
--- util/getroot.c      2012-04-22 19:02:55 +0000
+++ util/getroot.c      2012-04-24 01:27:50 +0000
@@ -45,8 +45,11 @@
 #endif
 
 #ifdef __GNU__
+#include <mach.h>
 #include <hurd.h>
 #include <hurd/lookup.h>
+#include <hurd/hurd_types.h>
+#include <hurd/store.h>
 #include <hurd/fs.h>
 #include <sys/mman.h>
 #endif
@@ -700,6 +703,115 @@
 
 #elif defined (__GNU__)
 
+/* Open a store for storage information only. */
+static struct store *
+storeinfo_store (const char *path)
+{
+  file_t file;
+  struct store *store;
+  int err;
+
+  file = file_name_lookup (path, 0, 0);
+  if (file == MACH_PORT_NULL)
+    return NULL;
+
+  err = store_create (file, STORE_INACTIVE | STORE_NO_FILEIO, NULL, &store);
+  if (err)
+    {
+      errno = err;
+      return NULL;
+    }
+
+  return store;
+}
+
+/* Retrieve the storage information for PATH, and search which partitions
+ * contains its start.  */
+static char *
+find_hurd_root_device (const char *path)
+{
+  struct store *path_store, *part_store;
+  char *devpath = NULL;
+  const char *prefix;
+  size_t len, prefix_len;
+  store_offset_t path_start;
+  int part;
+
+  path_store = storeinfo_store (path);
+  if (! path_store)
+    grub_util_error ("Could not retrieve storage information for `%s'", path);
+  if (! path_store->name)
+    grub_util_error ("No storage name associated with `%s'", path);
+
+  grub_util_info ("Storage is %s, type %d",
+      path_store->name, path_store->class->id);
+
+  if (path_store->class->id == STORAGE_DEVICE)
+    prefix = "/dev/";
+  else
+    prefix = "";
+
+  prefix_len = strlen (prefix);
+  len = strlen (path_store->name);
+  devpath = xmalloc (prefix_len + len + 4 + 1);
+
+  path_start = path_store->runs[0].start * path_store->block_size;
+
+  grub_util_info ("Path runs from %llu", path_start);
+
+  for (part = 1; part < 1000; part++)
+    {
+      struct store_run *first_run, *last_run;
+
+      snprintf (devpath, prefix_len + len + 4 + 1, "%s%ss%u",
+         prefix, path_store->name, part);
+
+      grub_util_info ("Trying partition %s", devpath);
+      part_store = storeinfo_store (devpath);
+      if (! part_store)
+       {
+         if (errno == ENOENT && part >= 5)
+           {
+             free (devpath);
+             devpath = NULL;
+             break;
+           }
+         continue;
+       }
+
+      first_run = &part_store->runs[0];
+      last_run = &part_store->runs[part_store->num_runs - 1];
+
+      grub_util_info ("Partition %u runs from %llu to %llu", part,
+       first_run->start * part_store->block_size,
+       (last_run->start + last_run->length) * part_store->block_size);
+
+      if (first_run->start * part_store->block_size <= path_start &&
+         (last_run->start + last_run->length) * part_store->block_size > 
path_start) {
+       store_free (part_store);
+       break;
+      }
+      store_free (part_store);
+    }
+
+  if (part >= 1000)
+    {
+      free (devpath);
+      devpath = NULL;
+    }
+
+  if (!devpath)
+    {
+      devpath = xmalloc (prefix_len + len + 1);
+      snprintf (devpath, prefix_len + len + 1, "%s%s", prefix, 
path_store->name);
+      grub_util_info ("End of partitions, assuming %s", devpath);
+    }
+
+  store_free (path_store);
+
+  return devpath;
+}
+
 #elif ! defined(__CYGWIN__)
 
 char *
@@ -930,65 +1042,7 @@
 grub_guess_root_devices (const char *dir)
 {
   char **os_dev = NULL;
-#ifdef __GNU__
-  file_t file;
-  mach_port_t *ports;
-  int *ints;
-  loff_t *offsets;
-  char *data;
-  error_t err;
-  mach_msg_type_number_t num_ports = 0, num_ints = 0, num_offsets = 0, 
data_len = 0;
-  size_t name_len;
-
-  file = file_name_lookup (dir, 0, 0);
-  if (file == MACH_PORT_NULL)
-    return 0;
-
-  err = file_get_storage_info (file,
-                              &ports, &num_ports,
-                              &ints, &num_ints,
-                              &offsets, &num_offsets,
-                              &data, &data_len);
-
-  if (num_ints < 1)
-    grub_util_error (_("Storage info for `%s' does not include type"), dir);
-  if (ints[0] != STORAGE_DEVICE)
-    grub_util_error (_("Filesystem of `%s' is not stored on local disk"), dir);
-
-  if (num_ints < 5)
-    grub_util_error (_("Storage info for `%s' does not include name"), dir);
-  name_len = ints[4];
-  if (name_len < data_len)
-    grub_util_error (_("Bogus name length for storage info for `%s'"), dir);
-  if (data[name_len - 1] != '\0')
-    grub_util_error (_("Storage name for `%s' not NUL-terminated"), dir);
-
-  os_dev = xmalloc (2 * sizeof (os_dev[0]));
-  os_dev[0] = xmalloc (sizeof ("/dev/") - 1 + data_len);
-  memcpy (os_dev[0], "/dev/", sizeof ("/dev/") - 1);
-  memcpy (os_dev[0] + sizeof ("/dev/") - 1, data, data_len);
-  os_dev[1] = 0;
-
-  if (ports && num_ports > 0)
-    {
-      mach_msg_type_number_t i;
-      for (i = 0; i < num_ports; i++)
-        {
-         mach_port_t port = ports[i];
-         if (port != MACH_PORT_NULL)
-           mach_port_deallocate (mach_task_self(), port);
-        }
-      munmap ((caddr_t) ports, num_ports * sizeof (*ports));
-    }
-
-  if (ints && num_ints > 0)
-    munmap ((caddr_t) ints, num_ints * sizeof (*ints));
-  if (offsets && num_offsets > 0)
-    munmap ((caddr_t) offsets, num_offsets * sizeof (*offsets));
-  if (data && data_len > 0)
-    munmap (data, data_len);
-  mach_port_deallocate (mach_task_self (), file);
-#else /* !__GNU__ */
+#ifndef __GNU__
   struct stat st;
   dev_t dev;
 
@@ -1035,6 +1089,7 @@
     grub_util_error (_("cannot stat `%s': %s"), dir, strerror (errno));
 
   dev = st.st_dev;
+#endif /* !__GNU__ */
 
   os_dev = xmalloc (2 * sizeof (os_dev[0]));
   
@@ -1042,6 +1097,10 @@
   /* Cygwin specific function.  */
   os_dev[0] = grub_find_device (dir, dev);
 
+#elif defined __GNU__
+  /* GNU/Hurd specific function.  */
+  os_dev[0] = find_hurd_root_device (dir);
+
 #else
 
   /* This might be truly slow, but is there any better way?  */
@@ -1054,7 +1113,6 @@
     }
 
   os_dev[1] = 0;
-#endif /* !__GNU__ */
 
   return os_dev;
 }

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to