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
[email protected]
https://lists.gnu.org/mailman/listinfo/grub-devel