All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Grégoire Sutre" <gregoire.sutre@labri.fr>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: Re: [PATCH] grub-probe support for NetBSD
Date: Mon, 04 Jan 2010 02:32:04 +0100	[thread overview]
Message-ID: <4B414514.7080704@labri.fr> (raw)
In-Reply-To: <4B37B094.7040102@labri.fr>

[-- Attachment #1: Type: text/plain, Size: 1179 bytes --]

Hi,

This the new version of the patch adding grub-probe (and grub-setup) 
support for NetBSD.  The main changes are:

- in function grub_util_biosdisk_get_grub_dev(), merge of the new
   NetBSD code with the original Linux code.

- re-enabled disk size detection for floppy.  This is done as for the
   other devices via the disklabel.  Hence, the floppy must have been
   labeled before, which is the recommended usage according to [1].
   I couldn't find another way to get the disk size for floppies.
   For the record, an example of successfull installation on a floppy
   (with grub-install) is also attached.

- as the floppy driver takes a long time to abort when the floppy drive
   is empty, the option NORETRY is set on the floppy driver.  The running
   time of grub-probe gets divided by 6 (30s instead of 3 minutes).  It
   is still long, but is also due to the fact that grub-probe tries to
   read the floppy 4 times.  Of course, this is only if the device map
   contains a floppy device, and grub-install --no-floppy does not suffer
   from this problem.

Thanks,

Grégoire

[1] http://www.netbsd.org/docs/guide/en/chap-rmmedia.html

[-- Attachment #2: patch-grub-probe-netbsd --]
[-- Type: text/plain, Size: 12820 bytes --]

Description: adds support for NetBSD in GRUB utilities.
See: http://lists.gnu.org/archive/html/grub-devel/2009-12/msg00432.html

Change log
----------
2010-??-??  Gregoire Sutre  <gregoire.sutre@labri.fr>

	Add grub-probe support for NetBSD.

	* util/getroot.c (find_root_device): Convert block device to
	character device on NetBSD.
	* util/probe.c (probe): Require character device on NetBSD.
	* util/hostdisk.c: NetBSD specific headers.
	(configure_device_driver): new function to tune device driver
	parameters (currently only for NetBSD floppy driver).
	(grub_util_biosdisk_open): NetBSD specific code (get disk size
	via disklabel ioctl).
	(open_device): call configure_device_driver on NetBSD.
	(convert_system_partition_to_system_disk): NetBSD specific code.
	(device_is_wholedisk): Likewise.
	(grub_util_biosdisk_get_grub_dev): Likewise.
	(make_device_name): Fixed a typo in bsd_part_str.
	* configure.ac: check for opendisk() and getrawpartition() on
	NetBSD and set LIBUTIL.
	* Makefile.in: add LIBUTIL to LIBS.

--- util/getroot.c.orig	2010-01-02 14:42:38.000000000 +0100
+++ util/getroot.c
@@ -264,10 +264,17 @@ find_root_device (const char *dir, dev_t
 	  /* Found!  */
 	  char *res;
 	  char *cwd;
+#if defined(__NetBSD__)
+	  /* Convert this block device to its character (raw) device.  */
+	  const char *template = "%s/r%s";
+#else
+	  /* Keep the device name as it is.  */
+	  const char *template = "%s/%s";
+#endif
 
 	  cwd = xgetcwd ();
-	  res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 2);
-	  sprintf (res, "%s/%s", cwd, ent->d_name);
+	  res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 3);
+	  sprintf (res, template, cwd, ent->d_name);
 	  strip_extra_slashes (res);
 	  free (cwd);
 
--- util/grub-probe.c.orig	2010-01-02 14:42:38.000000000 +0100
+++ util/grub-probe.c
@@ -111,7 +111,7 @@ probe (const char *path, char *device_na
 
   if (path == NULL)
     {
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
       if (! grub_util_check_char_device (device_name))
         grub_util_error ("%s is not a character device.\n", device_name);
 #else
--- util/hostdisk.c.orig	2010-01-02 14:42:38.000000000 +0100
+++ util/hostdisk.c
@@ -97,6 +97,18 @@ struct hd_geometry
 # include <sys/disk.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;
@@ -121,6 +133,31 @@ have_devfs (void)
 }
 #endif /* __linux__ */
 
+#if defined(__NetBSD__)
+/* Adjust device driver parameters.  This function should be called just
+   after successfully opening the device.  For now, it simply prevents the
+   floppy driver from retrying operations on failure, as otherwise the
+   driver takes a while to abort when there is no floppy in the drive.  */
+static void
+configure_device_driver (int fd)
+{
+  struct stat st;
+
+  if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode))
+    return;
+  if (major(st.st_rdev) == RAW_FLOPPY_MAJOR)
+    {
+      int floppy_opts;
+
+      if (ioctl (fd, FDIOCGETOPTS, &floppy_opts) == -1)
+	return;
+      floppy_opts |= FDOPT_NORETRY;
+      if (ioctl (fd, FDIOCSETOPTS, &floppy_opts) == -1)
+	return;
+    }
+}
+#endif /* defined(__NetBSD__) */
+
 static int
 find_grub_drive (const char *name)
 {
@@ -191,16 +228,20 @@ grub_util_biosdisk_open (const char *nam
     return GRUB_ERR_NONE;
   }
 #elif defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
-      defined(__FreeBSD_kernel__) || defined(__APPLE__)
+      defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
   {
+# if defined(__NetBSD__)
+    struct disklabel label;
+# else
     unsigned long long nr;
+# endif
     int fd;
 
     fd = open (map[drive].device, O_RDONLY);
     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__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
     if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode))
 # else
     if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
@@ -214,6 +255,9 @@ grub_util_biosdisk_open (const char *nam
     if (ioctl (fd, DIOCGMEDIASIZE, &nr))
 # elif defined(__APPLE__)
     if (ioctl (fd, DKIOCGETBLOCKCOUNT, &nr))
+# elif defined(__NetBSD__)
+    configure_device_driver (fd);
+    if (ioctl (fd, DIOCGDINFO, &label) == -1)
 # else
     if (ioctl (fd, BLKGETSIZE64, &nr))
 # endif
@@ -224,14 +268,16 @@ grub_util_biosdisk_open (const char *nam
 
     close (fd);
 
-#if defined (__APPLE__)
+# if defined (__APPLE__)
     disk->total_sectors = nr;
-#else
+# elif defined(__NetBSD__)
+    disk->total_sectors = label.d_secperunit;
+# else
     disk->total_sectors = nr / 512;
 
     if (nr % 512)
       grub_util_error ("unaligned device size");
-#endif
+# endif
 
     grub_util_info ("the size of %s is %llu", name, disk->total_sectors);
 
@@ -398,6 +444,10 @@ open_device (const grub_disk_t disk, gru
     }
 #endif /* ! __linux__ */
 
+#if defined(__NetBSD__)
+  configure_device_driver (fd);
+#endif /* defined(__NetBSD__) */
+
 #if defined(__linux__) && (!defined(__GLIBC__) || \
         ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
   /* Maybe libc doesn't have large file support.  */
@@ -683,7 +733,7 @@ make_device_name (int drive, int dos_par
     dos_part_str = xasprintf (",%d", dos_part + 1);
 
   if (bsd_part >= 0)
-    bsd_part_str = xasprintf (",%c", dos_part + 'a');
+    bsd_part_str = xasprintf (",%c", bsd_part + 'a');
 
   ret = xasprintf ("%s%s%s", map[drive].drive,
                    dos_part_str ? : "",
@@ -853,6 +903,27 @@ convert_system_partition_to_system_disk 
     }
   return path;
 
+#elif defined(__NetBSD__)
+  /* NetBSD uses "/dev/r[wsc]d[0-9]+[a-z]".  */
+  char *path = xstrdup (os_dev);
+  if (strncmp ("/dev/rwd", path, 8) == 0 ||
+      strncmp ("/dev/rsd", path, 8) == 0 ||
+      strncmp ("/dev/rcd", path, 8) == 0)
+    {
+      char *q;
+      q = path + strlen(path) - 1;    /* last character */
+      if (grub_isalpha(*q) && grub_isdigit(*(q-1)))
+        {
+          int rawpart = -1;
+# ifdef HAVE_GETRAWPARTITION
+          rawpart = getrawpartition();
+# endif /* HAVE_GETRAWPARTITION */
+          if (rawpart >= 0)
+            *q = 'a' + rawpart;
+        }
+    }
+  return path;
+
 #else
 # warning "The function `convert_system_partition_to_system_disk' might not work on your OS correctly."
   return xstrdup (os_dev);
@@ -871,6 +942,26 @@ 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)
 {
@@ -923,14 +1014,14 @@ grub_util_biosdisk_get_grub_dev (const c
       == 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))
 #endif
     return make_device_name (drive, -1, -1);
 
-#if defined(__linux__) || defined(__CYGWIN__)
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__NetBSD__)
   /* 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
@@ -938,12 +1029,24 @@ grub_util_biosdisk_get_grub_dev (const c
 
      Cygwin /dev/sdXN emulation uses Windows partition mapping. It
      does not count the extended partition and missing primary
-     partitions.  Use same method as on Linux here.  */
+     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.  */
   {
     char *name;
     grub_disk_t disk;
     int fd;
+# if !defined(__NetBSD__)
+    const char *disk_info_msg = "geometry";
     struct hd_geometry hdg;
+    unsigned long p_offset;
+# else /* defined(__NetBSD__) */
+    const char *disk_info_msg = "label";
+    struct disklabel label;
+    int index;
+    u_int32_t p_offset;
+# endif /* !defined(__NetBSD__) */
     int dos_part = -1;
     int bsd_part = -1;
     auto int find_partition (grub_disk_t disk,
@@ -973,7 +1076,7 @@ grub_util_biosdisk_get_grub_dev (const c
 			      partition->index, partition->start);
 	  }
 
-	if (hdg.start == partition->start)
+	if (p_offset == partition->start)
 	  {
 	    if (pcdata)
 	      {
@@ -993,21 +1096,33 @@ grub_util_biosdisk_get_grub_dev (const c
 
     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);
+	grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk %s", os_dev, disk_info_msg);
 	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 geometry of `%s'", os_dev);
+		    "cannot get disk %s of `%s'", disk_info_msg, os_dev);
 	close (fd);
 	free (name);
 	return 0;
@@ -1015,9 +1130,22 @@ grub_util_biosdisk_get_grub_dev (const c
 
     close (fd);
 
-    grub_util_info ("%s starts from %lu", os_dev, hdg.start);
+# if !defined(__NetBSD__)
+    p_offset = hdg.start;
+# else /* defined(__NetBSD__) */
+    if (index >= label.d_npartitions)
+      {
+	grub_error (GRUB_ERR_BAD_DEVICE,
+		    "no disk label entry for `%s'", os_dev);
+	free (name);
+	return 0;
+      }
+    p_offset = label.d_partitions[index].p_offset;
+# endif /* !defined(__NetBSD__) */
+
+    grub_util_info ("%s starts from %lu", os_dev, p_offset);
 
-    if (hdg.start == 0 && device_is_wholedisk (os_dev))
+    if (p_offset == 0 && device_is_wholedisk (os_dev))
       return name;
 
     grub_util_info ("opening the device %s", name);
--- configure.ac.orig	2010-01-02 14:42:26.000000000 +0100
+++ configure.ac
@@ -208,6 +208,20 @@ AC_CHECK_FUNCS(memmove sbrk strdup lstat
 AC_CHECK_HEADERS(sys/mkdev.h sys/sysmacros.h malloc.h termios.h sys/types.h)
 AC_CHECK_HEADERS(unistd.h string.h strings.h sys/stat.h sys/fcntl.h)
 
+# For opendisk() and getrawpartition() on NetBSD.
+# Used in util/deviceiter.c and in util/hostdisk.c.
+AC_CHECK_HEADER([util.h], [
+  AC_CHECK_LIB([util], [opendisk], [
+    LIBUTIL="-lutil"
+    AC_DEFINE(HAVE_OPENDISK, 1, [Define if opendisk() in -lutil can be used])
+  ])
+  AC_CHECK_LIB([util], [getrawpartition], [
+    LIBUTIL="-lutil"
+    AC_DEFINE(HAVE_GETRAWPARTITION, 1, [Define if getrawpartition() in -lutil can be used])
+  ])
+])
+AC_SUBST([LIBUTIL])
+
 #
 # Check for target programs.
 #
--- Makefile.in.orig	2010-01-02 14:42:01.000000000 +0100
+++ Makefile.in
@@ -44,6 +44,9 @@ pkglibdir =  $(libdir)/`echo @PACKAGE_TA
 # Internationalization library.
 LIBINTL = @LIBINTL@
 
+# Util library.
+LIBUTIL = @LIBUTIL@
+
 XGETTEXT = @XGETTEXT@
 MSGMERGE = @MSGMERGE@
 MSGFMT = @MSGFMT@
@@ -75,7 +78,7 @@ MKDIR_P = @MKDIR_P@
 
 mkinstalldirs = $(srcdir)/mkinstalldirs
 
-LIBS = @LIBS@ $(LIBINTL)
+LIBS = @LIBS@ $(LIBINTL) $(LIBUTIL)
 
 CC = @CC@
 CFLAGS = @CFLAGS@

[-- Attachment #3: Grub-Install-Floppy-NetBSD.txt --]
[-- Type: text/plain, Size: 446 bytes --]

Example Installation of GRUB 2 on a common 1440 KB floppy
*with grub-install* on NetBSD 5.0 i386/amd64

Format the floppy with:
$ fdformat -f /dev/rfd0a

Install a standard floppy disk label with:
$ disklabel -rw fd0a floppy

Create a filesystem on the floppy with:
$ newfs -m 0 /dev/rfd0a

Mount this filesystem e.g. on /mnt with:
$ mount /dev/fd0a /mnt

Finally, install grub with:
$ grub2-install --force --root-directory=/mnt/grub /dev/rfd0a

      parent reply	other threads:[~2010-01-04  1:32 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-27 19:08 [PATCH] grub-probe support for NetBSD Grégoire Sutre
2009-12-29  1:31 ` Grégoire Sutre
2010-01-01 11:39   ` Robert Millan
2010-01-02 11:35     ` Grégoire Sutre
2010-01-02 11:40       ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-01-02 11:46         ` Grégoire Sutre
2010-01-03 16:27       ` Robert Millan
2010-01-04  1:32 ` Grégoire Sutre [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4B414514.7080704@labri.fr \
    --to=gregoire.sutre@labri.fr \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.