grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] grub-probe support for NetBSD


From: Grégoire Sutre
Subject: [PATCH] grub-probe support for NetBSD
Date: Sun, 27 Dec 2009 20:08:04 +0100
User-agent: Thunderbird 2.0.0.23 (X11/20091027)

Hi,

I finished adding NetBSD specific code for grub-probe.  A patch and a
changelog entry are attached.  A few notes:

- devices are required to be character (raw) devices.  In NetBSD, those
  are of the form "/dev/r[wsc]d[0-9]+[a-z]" for hard disk drives and
  CD-ROM drives, as far as I know.

- in grub_util_biosdisk_open, the disk size is obtained from the disk
  label.

- in grub_util_biosdisk_get_grub_dev, the code is derived from the Linux
  code: we get the start sector of the partition from the disk label,
  and we compare it with each partition GRUB recognizes.  I don't think
  we can do better, as device names correspond to disklabel entries, and
  those can be quite arbitrary.

- in make_device_name, I fixed what I believe to be a typo, but I may be
  wrong.

Please let me know if I missed something,

Grégoire
2009-12-27  Gregoire Sutre  <address@hidden>

        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 (grub_util_biosdisk_open): NetBSD specific code.
        (convert_system_partition_to_system_disk): Likewise.
        (grub_util_biosdisk_get_grub_dev): Likewise.
        (make_device_name): Fixed a typo in bsd_part_str.
diff -Naurp grub2_2009-12-27/util/getroot.c grub2/util/getroot.c
--- grub2_2009-12-27/util/getroot.c     2009-12-27 16:04:32.000000000 +0100
+++ grub2/util/getroot.c        2009-12-27 17:51:46.000000000 +0100
@@ -266,8 +266,14 @@ find_root_device (const char *dir, dev_t
          char *cwd;
 
          cwd = xgetcwd ();
+#if defined(__NetBSD__)
+         /* Convert this block device to its character (raw) device */
+         res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 3);
+         sprintf (res, "%s/r%s", cwd, ent->d_name);
+#else
          res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 2);
          sprintf (res, "%s/%s", cwd, ent->d_name);
+#endif
          strip_extra_slashes (res);
          free (cwd);
 
diff -Naurp grub2_2009-12-27/util/grub-probe.c grub2/util/grub-probe.c
--- grub2_2009-12-27/util/grub-probe.c  2009-12-27 16:04:32.000000000 +0100
+++ grub2/util/grub-probe.c     2009-12-27 17:49:02.000000000 +0100
@@ -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
diff -Naurp grub2_2009-12-27/util/hostdisk.c grub2/util/hostdisk.c
--- grub2_2009-12-27/util/hostdisk.c    2009-12-27 16:04:32.000000000 +0100
+++ grub2/util/hostdisk.c       2009-12-27 18:21:15.000000000 +0100
@@ -97,6 +97,12 @@ struct hd_geometry
 # include <sys/disk.h>
 #endif
 
+#if defined(__NetBSD__)
+# include <sys/ioctl.h>
+# include <sys/disklabel.h>    /* struct disklabel */
+# include <util.h>    /* getrawpartition */
+#endif
+
 struct
 {
   char *drive;
@@ -191,16 +197,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 +224,8 @@ grub_util_biosdisk_open (const char *nam
     if (ioctl (fd, DIOCGMEDIASIZE, &nr))
 # elif defined(__APPLE__)
     if (ioctl (fd, DKIOCGETBLOCKCOUNT, &nr))
+# elif defined(__NetBSD__)
+    if (ioctl (fd, DIOCGDINFO, &label))
 # else
     if (ioctl (fd, BLKGETSIZE64, &nr))
 # endif
@@ -224,14 +236,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);
 
@@ -683,7 +697,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 +867,26 @@ 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;
+          rawpart = getrawpartition();
+          if (rawpart < 0)
+            rawpart = 3;    /* default on i386 */
+          *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);
@@ -923,7 +957,7 @@ 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))
@@ -1107,6 +1141,133 @@ grub_util_biosdisk_get_grub_dev (const c
     return make_device_name (drive, dos_part, bsd_part);
   }
 
+#elif defined(__NetBSD__)
+  /* NetBSD uses "/dev/r[wsc]d[0-9]+[a-z]".  */
+  /* Adaptation of the Linux code above.
+     Here, get the start sector of a partition from the disklabel, and
+     compare it with each partition GRUB recognizes.  */
+  {
+    char *name;
+    grub_disk_t disk;
+    int fd;
+    struct disklabel label;
+    int index;
+    u_int32_t p_offset;
+    int dos_part = -1;
+    int bsd_part = -1;
+    auto int find_partition (grub_disk_t disk,
+                            const grub_partition_t partition);
+
+    int find_partition (grub_disk_t disk __attribute__ ((unused)),
+                       const grub_partition_t partition)
+      {
+       struct grub_msdos_partition *pcdata = NULL;
+
+       if (strcmp (partition->partmap->name, "part_msdos") == 0)
+         pcdata = partition->data;
+
+       if (pcdata)
+         {
+           if (pcdata->bsd_part < 0)
+             grub_util_info ("DOS partition %d starts from %lu",
+                             pcdata->dos_part, partition->start);
+           else
+             grub_util_info ("BSD partition %d,%c starts from %lu",
+                             pcdata->dos_part, pcdata->bsd_part + 'a',
+                             partition->start);
+         }
+       else
+         {
+             grub_util_info ("Partition %d starts from %lu",
+                             partition->index, partition->start);
+         }
+
+       if (p_offset == partition->start)
+         {
+           if (pcdata)
+             {
+               dos_part = pcdata->dos_part;
+               bsd_part = pcdata->bsd_part;
+             }
+           else
+             {
+               dos_part = partition->index;
+               bsd_part = -1;
+             }
+           return 1;
+         }
+
+       return 0;
+      }
+
+    name = make_device_name (drive, -1, -1);
+
+    /*
+     * Since os_dev and convert_system_partition_to_system_disk (os_dev) are
+     * different, we know that os_dev is of the form /dev/[wsc]d[0-9]+[a-z].
+     */
+
+    index = os_dev[strlen(os_dev) - 1] - 'a';
+
+    fd = open (os_dev, O_RDONLY);
+    if (fd == -1)
+      {
+       grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to 
get disk label", os_dev);
+       free (name);
+       return 0;
+      }
+
+    if (ioctl (fd, DIOCGDINFO, &label))
+      {
+       grub_error (GRUB_ERR_BAD_DEVICE,
+                   "cannot get disk label of `%s'", os_dev);
+       close (fd);
+       free (name);
+       return 0;
+      }
+
+    close (fd);
+
+    if (index >= label.d_npartitions)
+      {
+       grub_error (GRUB_ERR_BAD_DEVICE,
+                   "no disk label entry for `%s'", os_dev);
+       close (fd);
+       free (name);
+       return 0;
+      }
+
+    p_offset = label.d_partitions[index].p_offset;
+    grub_util_info ("%s starts from %lu", os_dev, p_offset);
+
+    if (p_offset == 0)
+      return name;    /* use whole disk */
+
+    grub_util_info ("opening the device %s", name);
+    disk = grub_disk_open (name);
+    free (name);
+
+    if (! disk)
+      return 0;
+
+    grub_partition_iterate (disk, find_partition);
+    if (grub_errno != GRUB_ERR_NONE)
+      {
+       grub_disk_close (disk);
+       return 0;
+      }
+
+    if (dos_part < 0)
+      {
+       grub_disk_close (disk);
+       grub_error (GRUB_ERR_BAD_DEVICE,
+                   "cannot find the partition of `%s'", os_dev);
+       return 0;
+      }
+
+    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);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]