# 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 */
}
#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)) {
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)
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. */
/*
* 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)
}
#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/", sizeof ("/dev/") - 1) != 0)
+ return 0;
+
+ for (p = os_dev + sizeof ("/dev/") - 1; *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, int add)
{
#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
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;
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)
return make_device_name (drive, dos_part, bsd_part);
}
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
- /* FreeBSD uses "/dev/[a-z]+[0-9]+([sp][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 = strpbrk (p, "sp"); /* 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);