Index: include/grub/util/getroot.h
===================================================================
--- include/grub/util/getroot.h	(revision 2068)
+++ include/grub/util/getroot.h	(working copy)
@@ -30,5 +30,6 @@
 int grub_util_get_dev_abstraction (const char *os_dev);
 char *grub_util_get_grub_dev (const char *os_dev);
 const char *grub_util_check_block_device (const char *blk_dev);
+const char *grub_util_check_char_device (const char *blk_dev);
 
 #endif /* ! GRUB_UTIL_GETROOT_HEADER */
Index: util/grub-probe.c
===================================================================
--- util/grub-probe.c	(revision 2068)
+++ util/grub-probe.c	(working copy)
@@ -112,8 +112,13 @@
   
   if (path == NULL)
     {
+#if defined(__FreeBSD__)
+      if (! grub_util_check_char_device (device_name))
+        grub_util_error ("%s is not a character device.\n", device_name);
+#else
       if (! grub_util_check_block_device (device_name))
         grub_util_error ("%s is not a block device.\n", device_name);
+#endif
     }
   else
     device_name = grub_guess_root_device (path);
Index: util/getroot.c
===================================================================
--- util/getroot.c	(revision 2068)
+++ util/getroot.c	(working copy)
@@ -238,7 +238,11 @@
 	    }
 	}
 
+#ifdef __FreeBSD__ 
+      if (S_ISCHR (st.st_mode) && st.st_rdev == dev)
+#else
       if (S_ISBLK (st.st_mode) && st.st_rdev == dev)
+#endif
 	{
 #ifdef __linux__
 	  /* Skip device names like /dev/dm-0, which are short-hand aliases
@@ -519,3 +523,18 @@
   else
     return 0;
 }
+
+const char *
+grub_util_check_char_device (const char *blk_dev)
+{
+  struct stat st;
+
+  if (stat (blk_dev, &st) < 0)
+    grub_util_error ("Cannot stat `%s'", blk_dev);
+
+  if (S_ISCHR (st.st_mode))
+    return (blk_dev);
+  else
+    return 0;
+}
+
Index: util/hostdisk.c
===================================================================
--- util/hostdisk.c	(revision 2068)
+++ util/hostdisk.c	(working copy)
@@ -86,6 +86,10 @@
 # define FLOPPY_MAJOR	2
 #endif
 
+#ifdef __FreeBSD__
+# include <sys/disk.h> /* DIOCGMEDIASIZE */
+#endif
+
 struct
 {
   char *drive;
@@ -179,7 +183,7 @@
 
     return GRUB_ERR_NONE;
   }
-#elif defined(__linux__) || defined(__CYGWIN__)
+#elif defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__)
   {
     unsigned long long nr;
     int fd;
@@ -188,13 +192,21 @@
     if (fd == -1)
       return grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk size", map[drive].device);
 
+#if defined(__FreeBSD__)
+    if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode))
+#else
     if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
+#endif
       {
 	close (fd);
 	goto fail;
       }
     
+#if defined(__FreeBSD__)
+    if (ioctl (fd, DIOCGMEDIASIZE, &nr))
+#else
     if (ioctl (fd, BLKGETSIZE64, &nr))
+#endif
       {
 	close (fd);
 	goto fail;
@@ -746,6 +758,22 @@
     path[8] = 0;
   return path;
 
+#elif defined(__FreeBSD__)
+  char *path = xstrdup (os_dev);
+  if (strncmp ("/dev/", path, 5) == 0)
+    {
+      char *p;
+      for (p = path + 5; *p; ++p)
+        if (grub_isdigit(*p))
+          {
+            p = strchr (p, 's');
+            if (p)
+              *p = '\0';
+            break;
+          }
+    }
+  return path;
+
 #else
 # warning "The function `convert_system_partition_to_system_disk' might not work on your OS correctly."
   return xstrdup (os_dev);
@@ -793,7 +821,11 @@
       return 0;
     }
   
+#if defined(__FreeBSD__)
+  if (! S_ISCHR (st.st_mode))
+#else
   if (! S_ISBLK (st.st_mode))
+#endif
     return make_device_name (drive, -1, -1);
   
 #if defined(__linux__) || defined(__CYGWIN__)
@@ -938,6 +970,40 @@
     return make_device_name (drive, dos_part, bsd_part);
   }
   
+#elif defined(__FreeBSD__)
+  /* 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)
+      {
+        char *p, *q;
+        long int n;
+
+        for (p = os_dev + 5; *p; ++p)
+          if (grub_isdigit(*p))
+            {
+              p = strchr (p, 's');
+              if (p)
+                {
+                  p++;
+                  n = strtol (p, &q, 10);
+                  if (p != q && n != LONG_MIN && n != 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);
