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