Bug#585068: [PATCH] Fix grub-probe partition naming on FreeBSD

Colin Watson cjwatson at ubuntu.com
Sun Jun 13 10:48:11 UTC 2010


The following patch is aimed at fixing this Debian bug:

  http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=585068

I've tested it on Debian GNU/kFreeBSD and it seems to be producing sensible
output now.

The one glitch is that if you ask it to probe /dev/ad0s1a, it returns
(hd0,msdos1) rather than (hd0,msdos1,bsd1): this is because both /dev/ad0s1
and /dev/ad0s1a have the same start sector, and it just uses the first one
it finds.  When I set prefix to (hd0,msdos1)/boot/grub, GRUB can read from
that perfectly well, so can I ignore this glitch on the basis that it
doesn't cause a practical problem?

2010-06-13  Colin Watson  <cjwatson at ubuntu.com>

	* kern/emu/hostdisk.c: Include <sys/ioctl.h> and <sys/disklabel.h>
	on FreeBSD.  Define HAVE_DIOCGDINFO on NetBSD and FreeBSD to reduce
	the verbosity of later #ifs.
	(find_partition_start): Define this function on FreeBSD too.
	(device_is_wholedisk) [__FreeBSD__ || __FreeBSD_kernel__]: New
	function.
	(grub_util_biosdisk_get_grub_dev): Use partition-start-sector logic
	on FreeBSD.

=== modified file 'kern/emu/hostdisk.c'
--- kern/emu/hostdisk.c	2010-06-13 00:36:39 +0000
+++ kern/emu/hostdisk.c	2010-06-13 10:27:31 +0000
@@ -102,9 +102,15 @@ struct hd_geometry
 # include <libdevmapper.h>
 #endif
 
-#if defined(__NetBSD__)
+#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+# define HAVE_DIOCGDINFO
 # include <sys/ioctl.h>
 # include <sys/disklabel.h>    /* struct disklabel */
+#else /* !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) */
+# undef HAVE_DIOCGDINFO
+#endif /* defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
+
+#if defined(__NetBSD__)
 # ifdef HAVE_GETRAWPARTITION
 #  include <util.h>    /* getrawpartition */
 # endif /* HAVE_GETRAWPARTITION */
@@ -329,17 +335,17 @@ device_is_mapped (const char *dev)
 }
 #endif /* HAVE_DEVICE_MAPPER */
 
-#if defined(__linux__) || defined(__CYGWIN__) || defined(__NetBSD__)
+#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO)
 static grub_disk_addr_t
 find_partition_start (const char *dev)
 {
   int fd;
-# if !defined(__NetBSD__)
+# if !defined(HAVE_DIOCGDINFO)
   struct hd_geometry hdg;
-# else /* defined(__NetBSD__) */
+# else /* defined(HAVE_DIOCGDINFO) */
   struct disklabel label;
   int p_index;
-# endif /* !defined(__NetBSD__) */
+# endif /* !defined(HAVE_DIOCGDINFO) */
 
 # ifdef HAVE_DEVICE_MAPPER
   if (grub_device_mapper_supported () && device_is_mapped (dev)) {
@@ -413,36 +419,38 @@ devmapper_fail:
   if (fd == -1)
     {
       grub_error (GRUB_ERR_BAD_DEVICE,
-# if !defined(__NetBSD__)
+# if !defined(HAVE_DIOCGDINFO)
 		  "cannot open `%s' while attempting to get disk geometry", dev);
-# else /* defined(__NetBSD__) */
+# else /* defined(HAVE_DIOCGDINFO) */
 		  "cannot open `%s' while attempting to get disk label", dev);
-# endif /* !defined(__NetBSD__) */
+# endif /* !defined(HAVE_DIOCGDINFO) */
       return 0;
     }
 
-# if !defined(__NetBSD__)
+# if !defined(HAVE_DIOCGDINFO)
   if (ioctl (fd, HDIO_GETGEO, &hdg))
-# else /* defined(__NetBSD__) */
+# else /* defined(HAVE_DIOCGDINFO) */
+#  if defined(__NetBSD__)
   configure_device_driver (fd);
+#  endif /* defined(__NetBSD__) */
   if (ioctl (fd, DIOCGDINFO, &label) == -1)
-# endif /* !defined(__NetBSD__) */
+# endif /* !defined(HAVE_DIOCGDINFO) */
     {
       grub_error (GRUB_ERR_BAD_DEVICE,
-# if !defined(__NetBSD__)
+# if !defined(HAVE_DIOCGDINFO)
 		  "cannot get disk geometry of `%s'", dev);
-# else /* defined(__NetBSD__) */
+# else /* defined(HAVE_DIOCGDINFO) */
 		  "cannot get disk label of `%s'", dev);
-# endif /* !defined(__NetBSD__) */
+# endif /* !defined(HAVE_DIOCGDINFO) */
       close (fd);
       return 0;
     }
 
   close (fd);
 
-# if !defined(__NetBSD__)
+# if !defined(HAVE_DIOCGDINFO)
   return hdg.start;
-# else /* defined(__NetBSD__) */
+# else /* defined(HAVE_DIOCGDINFO) */
   p_index = dev[strlen(dev) - 1] - 'a';
 
   if (p_index >= label.d_npartitions)
@@ -452,9 +460,9 @@ devmapper_fail:
       return 0;
     }
   return (grub_disk_addr_t) label.d_partitions[p_index].p_offset;
-# endif /* !defined(__NetBSD__) */
+# endif /* !defined(HAVE_DIOCGDINFO) */
 }
-#endif /* __linux__ || __CYGWIN__ */
+#endif /* __linux__ || __CYGWIN__ || HAVE_DIOCGDINFO */
 
 #ifdef __linux__
 /* Cache of partition start sectors for each disk.  */
@@ -994,8 +1002,7 @@ grub_util_biosdisk_fini (void)
 
 /*
  * Note: we do not use the new partition naming scheme as dos_part does not
- * necessarily correspond to an msdos partition.  See e.g. the FreeBSD code
- * in function grub_util_biosdisk_get_grub_dev.
+ * necessarily correspond to an msdos partition.
  */
 static char *
 make_device_name (int drive, int dos_part, int bsd_part)
@@ -1333,6 +1340,27 @@ device_is_wholedisk (const char *os_dev)
 }
 #endif /* defined(__NetBSD__) */
 
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+static int
+device_is_wholedisk (const char *os_dev)
+{
+  const char *p;
+
+  if (strncmp (os_dev, "/dev/", 5) != 0)
+    return 0;
+
+  for (p = os_dev + 5; *p; ++p)
+    if (grub_isdigit (*p))
+      {
+	if (strchr (p, 's'))
+	  return 0;
+	break;
+      }
+
+  return 1;
+}
+#endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
+
 static int
 find_system_device (const char *os_dev, struct stat *st)
 {
@@ -1392,7 +1420,7 @@ grub_util_biosdisk_get_grub_dev (const c
 #endif
     return make_device_name (drive, -1, -1);
 
-#if defined(__linux__) || defined(__CYGWIN__) || defined(__NetBSD__)
+#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO)
   /* 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
@@ -1402,8 +1430,8 @@ grub_util_biosdisk_get_grub_dev (const c
      does not count the extended partition and missing primary
      partitions.  Use same method as on Linux here.
 
-     For NetBSD, proceed as for Linux, except that the start sector is
-     obtained from the disk label.  */
+     For NetBSD and FreeBSD, proceed as for Linux, except that the start
+     sector is obtained from the disk label.  */
   {
     char *name, *partname;
     grub_disk_t disk;
@@ -1431,13 +1459,13 @@ grub_util_biosdisk_get_grub_dev (const c
 
     name = make_device_name (drive, -1, -1);
 
-# if !defined(__NetBSD__)
+# if !defined(HAVE_DIOCGDINFO)
     if (MAJOR (st.st_rdev) == FLOPPY_MAJOR)
       return name;
-# else /* defined(__NetBSD__) */
+# else /* defined(HAVE_DIOCGDINFO) */
     /* Since os_dev and convert_system_partition_to_system_disk (os_dev) are
      * different, we know that os_dev cannot be a floppy device.  */
-# endif /* !defined(__NetBSD__) */
+# endif /* !defined(HAVE_DIOCGDINFO) */
 
     start = find_partition_start (os_dev);
     if (grub_errno != GRUB_ERR_NONE)
@@ -1506,41 +1534,6 @@ grub_util_biosdisk_get_grub_dev (const c
     return make_device_name (drive, dos_part, bsd_part);
   }
 
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
-  /* FreeBSD uses "/dev/[a-z]+[0-9]+(s[0-9]+[a-z]?)?".  */
-  {
-    int dos_part = -1;
-    int bsd_part = -1;
-
-    if (strncmp ("/dev/", os_dev, 5) == 0)
-      {
-        const char *p;
-        char *q;
-        long int n;
-
-        for (p = os_dev + 5; *p; ++p)
-          if (grub_isdigit(*p))
-            {
-              p = strchr (p, 's');    /* msdos or apple (or ... ?) partition map */
-              if (p)
-                {
-                  p++;
-                  n = strtol (p, &q, 10);
-                  if (p != q && n != GRUB_LONG_MIN && n != GRUB_LONG_MAX)
-                    {
-                      dos_part = (int) n - 1;
-
-                      if (*q >= 'a' && *q <= 'g')
-                        bsd_part = *q - 'a';
-                    }
-                }
-              break;
-            }
-      }
-
-    return make_device_name (drive, dos_part, bsd_part);
-  }
-
 #else
 # warning "The function `grub_util_biosdisk_get_grub_dev' might not work on your OS correctly."
   return make_device_name (drive, -1, -1);

Thanks,

-- 
Colin Watson                                       [cjwatson at ubuntu.com]





More information about the Pkg-grub-devel mailing list