merge from trunk
authorColin Watson <cjwatson@ubuntu.com>
Tue, 18 May 2010 10:14:13 +0000 (11:14 +0100)
committerColin Watson <cjwatson@ubuntu.com>
Tue, 18 May 2010 10:14:13 +0000 (11:14 +0100)
1  2 
conf/common.rmk
configure.ac
kern/emu/hostdisk.c

diff --cc conf/common.rmk
@@@ -3,8 -6,7 +6,8 @@@ script/lexer.c_DEPENDENCIES = grub_scri
  sbin_UTILITIES += grub-mkdevicemap
  grub_mkdevicemap_SOURCES = gnulib/progname.c util/grub-mkdevicemap.c \
        util/deviceiter.c \
-       util/misc.c \
-       kern/env.c kern/err.c kern/list.c kern/misc.c
 -      util/misc.c kern/emu/misc.c
++      util/misc.c kern/emu/misc.c \
++      kern/env.c kern/err.c kern/list.c kern/misc.c kern/emu/mm.c
  
  ifeq ($(target_cpu)-$(platform), sparc64-ieee1275)
  grub_mkdevicemap_SOURCES += util/ieee1275/ofpath.c util/ieee1275/devicemap.c
diff --cc configure.ac
Simple merge
@@@ -97,10 -98,18 +98,22 @@@ struct hd_geometr
  # include <sys/disk.h>
  #endif
  
 +#ifdef HAVE_DEVICE_MAPPER
 +# include <libdevmapper.h>
 +#endif
 +
+ #if defined(__NetBSD__)
+ # include <sys/ioctl.h>
+ # include <sys/disklabel.h>    /* struct disklabel */
+ # ifdef HAVE_GETRAWPARTITION
+ #  include <util.h>    /* getrawpartition */
+ # endif /* HAVE_GETRAWPARTITION */
+ # include <sys/fdio.h>
+ # ifndef RAW_FLOPPY_MAJOR
+ #  define RAW_FLOPPY_MAJOR    9
+ # endif /* ! RAW_FLOPPY_MAJOR */
+ #endif /* defined(__NetBSD__) */
  struct
  {
    char *drive;
@@@ -257,116 -312,18 +316,152 @@@ grub_util_biosdisk_open (const char *na
    return GRUB_ERR_NONE;
  }
  
- #if defined(__linux__) || defined(__CYGWIN__)
 +#ifdef HAVE_DEVICE_MAPPER
 +static int
 +device_is_mapped (const char *dev)
 +{
 +  struct stat st;
 +
 +  if (stat (dev, &st) < 0)
 +    return 0;
 +
 +  return dm_is_dm_major (major (st.st_rdev));
 +}
 +#endif /* HAVE_DEVICE_MAPPER */
 +
- #ifdef HAVE_DEVICE_MAPPER
++#if defined(__linux__) || defined(__CYGWIN__) || defined(__NetBSD__)
 +static grub_disk_addr_t
 +find_partition_start (const char *dev)
 +{
 +  int fd;
++# if !defined(__NetBSD__)
 +  struct hd_geometry hdg;
++# else /* defined(__NetBSD__) */
++  struct disklabel label;
++  int index;
++# endif /* !defined(__NetBSD__) */
 +
-                     dev, partition_start);
++# ifdef HAVE_DEVICE_MAPPER
 +  if (device_is_mapped (dev)) {
 +    struct dm_task *task = NULL;
 +    grub_uint64_t start, length;
 +    char *target_type, *params, *space;
 +    grub_disk_addr_t partition_start;
 +
 +    /* If any device-mapper operation fails, we fall back silently to
 +       HDIO_GETGEO.  */
 +    task = dm_task_create (DM_DEVICE_TABLE);
 +    if (! task)
 +      {
 +      grub_dprintf ("hostdisk", "dm_task_create failed\n");
 +      goto devmapper_fail;
 +      }
 +
 +    if (! dm_task_set_name (task, dev))
 +      {
 +      grub_dprintf ("hostdisk", "dm_task_set_name failed\n");
 +      goto devmapper_fail;
 +      }
 +
 +    if (! dm_task_run (task))
 +      {
 +      grub_dprintf ("hostdisk", "dm_task_run failed\n");
 +      goto devmapper_fail;
 +      }
 +
 +    dm_get_next_target (task, NULL, &start, &length, &target_type, &params);
 +    if (! target_type)
 +      {
 +      grub_dprintf ("hostdisk", "no dm target\n");
 +      goto devmapper_fail;
 +      }
 +    if (strcmp (target_type, "linear") != 0)
 +      {
 +      grub_dprintf ("hostdisk", "ignoring dm target %s (not linear)\n",
 +                    target_type);
 +      goto devmapper_fail;
 +      }
 +    if (! params)
 +      {
 +      grub_dprintf ("hostdisk", "no dm params\n");
 +      goto devmapper_fail;
 +      }
 +
 +    /* The params string for a linear target looks like this:
 +         DEVICE-NAME START-SECTOR
 +       Parse this out.  */
 +    space = strchr (params, ' ');
 +    if (! space)
 +      goto devmapper_fail;
 +    errno = 0;
 +    partition_start = strtoull (space + 1, NULL, 10);
 +    if (errno == 0)
 +      {
 +      grub_dprintf ("hostdisk", "dm %s starts at %llu\n",
- #endif /* HAVE_DEVICE_MAPPER */
++                    dev, (unsigned long long) partition_start);
 +      dm_task_destroy (task);
 +      return partition_start;
 +      }
 +
 +devmapper_fail:
 +    if (task)
 +      dm_task_destroy (task);
 +  }
-                 "cannot get geometry of `%s'", dev);
++# endif /* HAVE_DEVICE_MAPPER */
 +
 +  fd = open (dev, O_RDONLY);
 +  if (fd == -1)
 +    {
 +      grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk geometry", dev);
 +      return 0;
 +    }
 +
++# if !defined(__NetBSD__)
 +  if (ioctl (fd, HDIO_GETGEO, &hdg))
++# else /* defined(__NetBSD__) */
++  configure_device_driver (fd);
++  if (ioctl (fd, DIOCGDINFO, &label) == -1)
++# endif /* !defined(__NetBSD__) */
 +    {
 +      grub_error (GRUB_ERR_BAD_DEVICE,
++                "cannot get disk geometry of `%s'", dev);
 +      close (fd);
 +      return 0;
 +    }
 +
 +  close (fd);
 +
++# if !defined(__NetBSD__)
 +  return hdg.start;
++# else /* defined(__NetBSD__) */
++  /* Since dev and convert_system_partition_to_system_disk (dev) are
++   * different, we know that dev is of the form /dev/r[wsc]d[0-9]+[a-z]
++   * and in particular it cannot be a floppy device.  */
++  index = dev[strlen(dev) - 1] - 'a';
++
++  if (index >= label.d_npartitions)
++    {
++      grub_error (GRUB_ERR_BAD_DEVICE,
++                "no disk label entry for `%s'", dev);
++      return 0;
++    }
++  return (grub_disk_addr_t) label.d_partitions[index].p_offset;
++# endif /* !defined(__NetBSD__) */
 +}
 +#endif /* __linux__ || __CYGWIN__ */
 +
  #ifdef __linux__
+ /* Cache of partition start sectors for each disk.  */
+ struct linux_partition_cache
+ {
+   struct linux_partition_cache *next;
+   char *dev;
+   unsigned long start;
+   int partno;
+ };
+ struct linux_partition_cache *linux_partition_cache_list;
  static int
  linux_find_partition (char *dev, unsigned long sector)
  {
        fd = open (real_dev, O_RDONLY);
        if (fd == -1)
        return 0;
 -
 -      if (ioctl (fd, HDIO_GETGEO, &hdg))
 -      {
 -        close (fd);
 -        return 0;
 -      }
 -
        close (fd);
  
 -      if (hdg.start == sector)
 +      start = find_partition_start (real_dev);
 +      /* We don't care about errors here.  */
 +      grub_errno = GRUB_ERR_NONE;
 +
 +      if (start == sector)
        {
 -        new_cache_item->start = hdg.start;
+         struct linux_partition_cache *new_cache_item;
+         new_cache_item = xmalloc (sizeof *new_cache_item);
+         new_cache_item->dev = xstrdup (dev);
++        new_cache_item->start = start;
+         new_cache_item->partno = i;
+         grub_list_push (GRUB_AS_LIST_P (&linux_partition_cache_list),
+                         GRUB_AS_LIST (new_cache_item));
          strcpy (dev, real_dev);
          return 1;
        }
@@@ -1072,8 -1070,28 +1296,28 @@@ device_is_wholedisk (const char *os_dev
  }
  #endif
  
+ #if defined(__NetBSD__)
+ /* Try to determine whether a given device name corresponds to a whole disk.
+    This function should give in most cases a definite answer, but it may
+    actually give an approximate one in the following sense: if the return
+    value is 0 then the device name does not correspond to a whole disk.  */
+ static int
+ device_is_wholedisk (const char *os_dev)
+ {
+   int len = strlen (os_dev);
+   int rawpart = -1;
+ # ifdef HAVE_GETRAWPARTITION
+   rawpart = getrawpartition();
+ # endif /* HAVE_GETRAWPARTITION */
+   if (rawpart < 0)
+     return 1;
+   return (os_dev[len - 1] == ('a' + rawpart));
+ }
+ #endif /* defined(__NetBSD__) */
  static int
 -find_system_device (const char *os_dev)
 +find_system_device (const char *os_dev, struct stat *st)
  {
    unsigned int i;
    char *os_disk;
@@@ -1112,19 -1130,19 +1356,19 @@@ grub_util_biosdisk_get_grub_dev (const 
        return 0;
      }
  
 -  drive = find_system_device (os_dev);
 +  drive = find_system_device (os_dev, &st);
    if (drive < 0)
      {
-       grub_error (GRUB_ERR_BAD_DEVICE,
+       grub_error (GRUB_ERR_UNKNOWN_DEVICE,
                  "no mapping exists for `%s'", os_dev);
        return 0;
      }
  
 -  if (grub_strcmp (os_dev, convert_system_partition_to_system_disk (os_dev))
 -      == 0)
 +  if (grub_strcmp (os_dev,
 +                 convert_system_partition_to_system_disk (os_dev, &st)) == 0)
      return make_device_name (drive, -1, -1);
  
- #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
+ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
    if (! S_ISCHR (st.st_mode))
  #else
    if (! S_ISBLK (st.st_mode))
    {
      char *name;
      grub_disk_t disk;
 -    int fd;
 -# if !defined(__NetBSD__)
 -    struct hd_geometry hdg;
 -    typeof (hdg.start) p_offset;
 -# else /* defined(__NetBSD__) */
 -    struct disklabel label;
 -    int index;
 -    u_int32_t p_offset;
 -# endif /* !defined(__NetBSD__) */
 +    grub_disk_addr_t start;
      int dos_part = -1;
      int bsd_part = -1;
-     auto int find_partition (grub_disk_t disk,
+     auto int find_partition (grub_disk_t dsk,
                             const grub_partition_t partition);
  
-     int find_partition (grub_disk_t disk __attribute__ ((unused)),
+     int find_partition (grub_disk_t dsk __attribute__ ((unused)),
                        const grub_partition_t partition)
        {
-       struct grub_msdos_partition *pcdata = NULL;
-       if (strcmp (partition->partmap->name, "part_msdos") == 0)
-         pcdata = partition->data;
+       grub_disk_addr_t part_start = 0;
+       grub_util_info ("Partition %d starts from %lu",
+                       partition->number, partition->start);
  
-       if (pcdata)
-         {
-           if (pcdata->bsd_part < 0)
-             grub_util_info ("DOS partition %d starts from %lu",
-                             pcdata->dos_part, partition->start);
-           else
-             grub_util_info ("BSD partition %d,%c starts from %lu",
-                             pcdata->dos_part, pcdata->bsd_part + 'a',
-                             partition->start);
-         }
-       else
-         {
-             grub_util_info ("Partition %d starts from %lu",
-                             partition->index, partition->start);
-         }
+       part_start = grub_partition_get_start (partition);
  
-       if (start == partition->start)
 -      if (p_offset == part_start)
++      if (start == part_start)
          {
-           if (pcdata)
+           if (partition->parent)
              {
-               dos_part = pcdata->dos_part;
-               bsd_part = pcdata->bsd_part;
+               dos_part = partition->parent->number;
+               bsd_part = partition->number;
              }
            else
              {
  
      name = make_device_name (drive, -1, -1);
  
+ # if !defined(__NetBSD__)
      if (MAJOR (st.st_rdev) == FLOPPY_MAJOR)
        return name;
+ # else /* defined(__NetBSD__) */
+     /* Since os_dev and convert_system_partition_to_system_disk (os_dev) are
+      * different, we know that os_dev is of the form /dev/r[wsc]d[0-9]+[a-z]
+      * and in particular it cannot be a floppy device.  */
+     index = os_dev[strlen(os_dev) - 1] - 'a';
+ # endif /* !defined(__NetBSD__) */
  
 -    fd = open (os_dev, O_RDONLY);
 -    if (fd == -1)
 -      {
 -      grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk geometry", os_dev);
 -      free (name);
 -      return 0;
 -      }
 -
 -# if !defined(__NetBSD__)
 -    if (ioctl (fd, HDIO_GETGEO, &hdg))
 -# else /* defined(__NetBSD__) */
 -    configure_device_driver (fd);
 -    if (ioctl (fd, DIOCGDINFO, &label) == -1)
 -# endif /* !defined(__NetBSD__) */
 -      {
 -      grub_error (GRUB_ERR_BAD_DEVICE,
 -                  "cannot get disk geometry of `%s'", os_dev);
 -      close (fd);
 -      free (name);
 -      return 0;
 -      }
 -
 -    close (fd);
 -
 -# if !defined(__NetBSD__)
 -    p_offset = hdg.start;
 -# else /* defined(__NetBSD__) */
 -    if (index >= label.d_npartitions)
 +    start = find_partition_start (os_dev);
 +    if (grub_errno != GRUB_ERR_NONE)
        {
 -      grub_error (GRUB_ERR_BAD_DEVICE,
 -                  "no disk label entry for `%s'", os_dev);
        free (name);
        return 0;
        }