=== 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 #include #include +#include +#include #include #include #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; }