grub-devel
[Top][All Lists]
Advanced

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

[PATCH 12/15] ofdisk: only add aliases that exist


From: Eric Snowberg
Subject: [PATCH 12/15] ofdisk: only add aliases that exist
Date: Wed, 29 Jun 2016 14:43:25 -0700

Only add device aliases that really exist for SPARC.

SPARC hardware ships with devaliases the could exist in the
future.  For example a T7 might contain the following
predefined devalias list:

{20} ok devalias
disk0                    
/address@hidden/address@hidden/address@hidden/address@hidden
disk1                    
/address@hidden/address@hidden/address@hidden/address@hidden
disk2                    
/address@hidden/address@hidden/address@hidden/address@hidden
disk3                    
/address@hidden/address@hidden/address@hidden/address@hidden
disk4                    
/address@hidden/address@hidden/address@hidden/address@hidden
disk5                    
/address@hidden/address@hidden/address@hidden/address@hidden
disk                     
/address@hidden/address@hidden/address@hidden/address@hidden

However there could be just a single disk installed in disk0.

Now grub will no longer try to use these disks that don't
exist.  This was causing long delays on boot and showed
nonexistent drives in the shell.

Signed-off-by: Eric Snowberg <address@hidden>
---
 grub-core/disk/ieee1275/ofdisk.c           |  225 ++++++++++++++++++++++++++++
 grub-core/kern/ieee1275/cmain.c            |    3 +
 grub-core/kern/ieee1275/ieee1275.c         |   88 +++++++++++
 grub-core/kern/sparc64/ieee1275/ieee1275.c |  111 ++++++++++++++
 include/grub/ieee1275/ieee1275.h           |    9 +
 include/grub/sparc64/ieee1275/ieee1275.h   |    4 +
 6 files changed, 440 insertions(+), 0 deletions(-)

diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index 9c6b8b0..42d038c 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -22,8 +22,10 @@
 #include <grub/mm.h>
 #include <grub/ieee1275/ieee1275.h>
 #include <grub/ieee1275/ofdisk.h>
+#include <grub/scsicmd.h>
 #include <grub/i18n.h>
 #include <grub/time.h>
+#include <grub/list.h>
 
 static char *last_devpath;
 static grub_ieee1275_ihandle_t last_ihandle;
@@ -45,6 +47,14 @@ struct ofdisk_hash_ent
   struct ofdisk_hash_ent *next;
 };
 
+struct ofdisk_hba_ent
+{
+  struct ofdisk_hba_ent *next;
+  struct ofdisk_hba_ent **prev;
+  grub_ieee1275_ihandle_t ihandle;
+  char *path;
+};
+
 static grub_err_t
 grub_ofdisk_get_block_size (grub_uint32_t *block_size,
                             struct ofdisk_hash_ent *op);
@@ -52,9 +62,36 @@ grub_ofdisk_get_block_size (grub_uint32_t *block_size,
 static grub_err_t
 grub_ofdisk_open_real (grub_disk_t disk);
 
+static grub_err_t
+sparc_disk_present (const char *path);
+
+static char *
+get_hbaname_from_path (const char *path);
+
+static char *
+get_diskname_from_path (const char *path);
+
+static struct ofdisk_hba_ent *
+ofdisk_hba_find (const char *devpath);
+
+static grub_ieee1275_ihandle_t
+ofdisk_hba_open (const char *hba_name);
+
 #define OFDISK_HASH_SZ 8
 static struct ofdisk_hash_ent *ofdisk_hash[OFDISK_HASH_SZ];
 
+static struct ofdisk_hba_ent *ofdisk_hba_ents = NULL;
+
+static struct grub_scsi_test_unit_ready ofdisk_tur =
+{
+  .opcode = grub_scsi_cmd_test_unit_ready,
+  .lun = 0,
+  .reserved1 = 0,
+  .reserved2 = 0,
+  .reserved3 = 0,
+  .control = 0,
+};
+
 static int
 ofdisk_hash_fn (const char *devpath)
 {
@@ -363,6 +400,9 @@ scan (void)
     {
       if (grub_strcmp (alias.type, "block") != 0)
        continue;
+      if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_VALIDATE_DEV_ALIASES) &&
+          sparc_disk_present (alias.path) == 0)
+        continue;
       dev_iterate_real (alias.name, alias.path);
     }
 
@@ -451,6 +491,46 @@ compute_dev_path (const char *name)
   return devpath;
 }
 
+static char *
+get_hbaname_from_path (const char *path)
+{
+  char *sptr, *hba_name;
+
+  hba_name = grub_strdup (path);
+
+  if (!hba_name)
+    return NULL;
+
+  sptr = grub_strstr (hba_name, "/disk@");
+
+  if (!sptr)
+    return NULL;
+
+  *sptr = '\0';
+
+  return hba_name;
+}
+
+static char *
+get_diskname_from_path (const char *path)
+{
+  const char *disk_dev = "/disk@";
+  char *sptr, *disk_name;
+
+  sptr = grub_strstr (path, disk_dev);
+
+  if (!sptr)
+    return NULL;
+
+  disk_name = grub_strdup (sptr + grub_strlen (disk_dev));
+  sptr = grub_strstr (disk_name, ":");
+
+  if (sptr)
+    *sptr = '\0';
+
+  return disk_name;
+}
+
 static grub_err_t
 grub_ofdisk_open (const char *name, grub_disk_t disk)
 {
@@ -760,3 +840,148 @@ grub_ofdisk_open_real (grub_disk_t disk)
   last_devpath = disk->data;
   return 0;
 }
+
+static struct ofdisk_hba_ent *
+ofdisk_hba_find (const char *devpath)
+{
+  struct ofdisk_hba_ent *dev = NULL;
+
+  FOR_LIST_ELEMENTS (dev, ofdisk_hba_ents)
+    if (grub_strcmp (dev->path, devpath) == 0)
+      break;
+
+  return dev;
+}
+
+static struct ofdisk_hba_ent *
+ofdisk_hba_add (const char *devpath, grub_ieee1275_ihandle_t ihandle)
+{
+  struct ofdisk_hba_ent *dev;
+
+  dev = grub_zalloc (sizeof (struct ofdisk_hba_ent));
+
+  if (!dev)
+    return NULL;
+
+  dev->path = grub_strdup (devpath);
+
+  if (!dev->path)
+    {
+      grub_free (dev);
+      return NULL;
+    }
+
+  dev->ihandle = ihandle;
+  grub_list_push (GRUB_AS_LIST_P (&ofdisk_hba_ents), GRUB_AS_LIST (dev));
+
+  return dev;
+}
+
+static grub_ieee1275_ihandle_t
+ofdisk_hba_open (const char *hba_name)
+{
+  grub_ieee1275_ihandle_t ihandle;
+  struct ofdisk_hba_ent *dev;
+
+  dev = ofdisk_hba_find (hba_name);
+
+  if (dev)
+    ihandle = dev->ihandle;
+  else if (grub_ieee1275_open (hba_name, &ihandle))
+    ihandle = 0;
+  else
+    {
+      dev = ofdisk_hba_add (hba_name, ihandle);
+
+      if (!dev)
+        ihandle = 0;
+    }
+
+  return ihandle;
+}
+
+static grub_err_t
+sparc_disk_present (const char *full_path)
+{
+  char *disk_name = get_diskname_from_path (full_path);
+  char *hba_name = get_hbaname_from_path (full_path);
+  char *lun_name = NULL, *sptr = NULL, *device_type = 0;
+  grub_ieee1275_ihandle_t ihandle;
+  /* Per SPARC SCSI binding spec, default to 2 for legacy devices that may
+     not have this property */
+  grub_uint32_t address_cells = 2;
+  grub_ieee1275_phandle_t root;
+  grub_uint64_t lun = 0;
+  grub_ssize_t result;
+  grub_err_t rval = GRUB_ERR_NONE;
+
+  if ((!hba_name) || (!disk_name))
+    {
+      grub_free (hba_name);
+      grub_free (disk_name);
+      return GRUB_ERR_NONE;
+    }
+
+  ihandle = ofdisk_hba_open (hba_name);
+
+  if (ihandle == 0)
+    {
+      grub_free (hba_name);
+      grub_free (disk_name);
+      return GRUB_ERR_NONE;
+    }
+
+  sptr = grub_strstr (disk_name, ",");
+
+  if (sptr)
+    {
+      lun_name = grub_strdup (sptr + 1);
+      *sptr = '\0';
+      lun = grub_strtoull (lun_name, 0, 16);
+    }
+
+  grub_ieee1275_finddevice (hba_name, &root);
+  grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells,
+                                      sizeof address_cells, 0);
+  device_type = grub_ieee1275_get_device_type (hba_name);
+
+  if ((grub_strcmp (device_type, "scsi-2") == 0) ||
+      (grub_strcmp (device_type, "scsi-sas") == 0))
+    {
+      if (address_cells == 4)
+        {
+          if (grub_ieee1275_set_sas_address (ihandle, disk_name, lun) == 0)
+            if (grub_ieee1275_no_data_command (ihandle, &ofdisk_tur,
+                                               &result) == 0)
+              if (result == 0)
+                rval = GRUB_ERR_BAD_DEVICE;
+        }
+      else if ((address_cells == 2) && (grub_isxdigit (*disk_name)))
+        {
+          grub_uint32_t tgt;
+          tgt = grub_strtol (disk_name, 0, 16);
+          if (tgt <= 0xff)
+            if (grub_ieee1275_set_address (ihandle, tgt, lun) == 0)
+              if (grub_ieee1275_no_data_command (ihandle, &ofdisk_tur,
+                                                 &result) == 0)
+                if (result == 0)
+                  rval = GRUB_ERR_BAD_DEVICE;
+        }
+    }
+  else if (grub_strcmp (device_type, "scsi-usb") == 0)
+    {
+      if (grub_ieee1275_set_address (ihandle, 0, 0) == 0)
+        if (grub_ieee1275_no_data_command (ihandle, &ofdisk_tur, &result) == 0)
+          if (result == 0)
+            rval = GRUB_ERR_BAD_DEVICE;
+    }
+  else
+    {
+      /* ieee1275_finddevice would validate these already */
+      rval = GRUB_ERR_BAD_DEVICE;
+    }
+
+  grub_free (hba_name);
+  grub_free (disk_name);
+  return rval;
+}
diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c
index b016598..59271ae 100644
--- a/grub-core/kern/ieee1275/cmain.c
+++ b/grub-core/kern/ieee1275/cmain.c
@@ -110,7 +110,10 @@ grub_ieee1275_find_options (void)
       char *ptr;
 
       if (grub_strncmp (tmp, "sun4v", 5) == 0)
+       {
          grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CACHE_OPEN);
+         grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_VALIDATE_DEV_ALIASES);
+       }
 
       for (ptr = tmp; ptr - tmp < actual; ptr += grub_strlen (ptr) + 1)
        {
diff --git a/grub-core/kern/ieee1275/ieee1275.c 
b/grub-core/kern/ieee1275/ieee1275.c
index 9821702..88999e0 100644
--- a/grub-core/kern/ieee1275/ieee1275.c
+++ b/grub-core/kern/ieee1275/ieee1275.c
@@ -607,3 +607,91 @@ grub_ieee1275_milliseconds (grub_uint32_t *msecs)
   *msecs = args.msecs;
   return 0;
 }
+
+int
+grub_ieee1275_set_address (grub_ieee1275_ihandle_t ihandle,
+                           grub_uint32_t target, grub_uint32_t lun)
+{
+  struct set_address
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t tgt;
+    grub_ieee1275_cell_t lun;
+    grub_ieee1275_cell_t catch_result;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 2);
+
+  /* IEEE Standard for Boot (Initialization Configuration)
+     Firmware: Core Requirements and Practices
+     E.3.2.2 Bus-specific methods for bus nodes
+
+     A package implementing the scsi-2 device type shall implement the
+     following bus-specific method:
+
+     set-address ( unit# target# -- )
+     Sets the SCSI target number (0x0..0xf) and unit number (0..7) to which
+     subsequent commands apply.
+  */
+  args.method = (grub_ieee1275_cell_t) "set-address";
+  args.ihandle = ihandle;
+  args.tgt = target;
+  args.lun = lun;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  return args.catch_result;
+}
+
+int
+grub_ieee1275_no_data_command (grub_ieee1275_ihandle_t ihandle,
+                               const void *cmd_addr, grub_ssize_t *result)
+{
+  struct set_address
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t cmd_addr;
+    grub_ieee1275_cell_t error;
+    grub_ieee1275_cell_t catch_result;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2);
+  /* IEEE 1275-1994 Standard for Boot (Initialization Configuration)
+     Firmware: Core Requirements and Practices
+
+     E.3.2.2 Bus-specific methods for bus nodes
+
+     A package implementing the scsi-2 device type shall implement the
+     following bus-specific method:
+
+     no-data-command ( cmd-addr -- error? )
+     Executes a simple SCSI command, automatically retrying under
+     certain conditions.  cmd-addr is the address of a 6-byte command buffer
+     containing an SCSI command that does not have a data transfer phase.
+     Executes the command, retrying indefinitely with the same retry criteria
+     as retry-command.
+
+     error? is nonzero if an error occurred, zero otherwise.
+     NOTE no-data-command is a convenience function. It provides
+     no capabilities that are not present in retry-command, but for
+     those commands that meet its restrictions, it is easier to use.
+   */
+  args.method = (grub_ieee1275_cell_t) "no-data-command";
+  args.ihandle = ihandle;
+  args.cmd_addr = (grub_ieee1275_cell_t) cmd_addr;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  if (result)
+    *result = args.error;
+
+  return args.catch_result;
+}
diff --git a/grub-core/kern/sparc64/ieee1275/ieee1275.c 
b/grub-core/kern/sparc64/ieee1275/ieee1275.c
index 53be692..16801f8 100644
--- a/grub-core/kern/sparc64/ieee1275/ieee1275.c
+++ b/grub-core/kern/sparc64/ieee1275/ieee1275.c
@@ -18,6 +18,7 @@
 
 #include <grub/ieee1275/ieee1275.h>
 #include <grub/types.h>
+#include <grub/misc.h>
 
 /* Sun specific ieee1275 interfaces used by GRUB.  */
 
@@ -89,3 +90,113 @@ grub_ieee1275_alloc_physmem (grub_addr_t *paddr, 
grub_size_t size,
 
   return args.catch_result;
 }
+
+int
+grub_ieee1275_set_sas_address (grub_ieee1275_ihandle_t ihandle,
+                               const char *disk_name,
+                               grub_uint64_t lun)
+{
+  struct dev_set_address
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t tgt_h;
+    grub_ieee1275_cell_t tgt_l;
+    grub_ieee1275_cell_t lun_h;
+    grub_ieee1275_cell_t lun_l;
+    grub_ieee1275_cell_t catch_result;
+  }
+  args;
+
+  grub_uint32_t sas_phy = 0, tgt = 0;
+  grub_uint64_t wwn = 0;
+
+  if (disk_name == 0)
+    return -1;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1);
+  args.method = (grub_ieee1275_cell_t) "set-address";
+  args.ihandle = ihandle;
+  args.lun_l = lun & 0xffffffff;
+  args.lun_h = lun >> 32;
+
+  /* PHY addressing */
+  if (*disk_name == 'p')
+    {
+      /*         Bit #   33222222 22221111 11111100 00000000
+                         10987654 32109876 54321098 76543210
+
+         sas.hi cell:    00000000 00000000 00000000 00000000
+         sas.lo cell:    00000000 00000001 jjjjjjjj iiiiiiii
+         lun.hi cell:    uuuuuuuu uuuuuuuu uuuuuuuu uuuuuuuu
+         lun.lo cell:    uuuuuuuu uuuuuuuu uuuuuuuu uuuuuuuu
+
+         00..00          Bits with the value zero
+         ii..ii          8-bit unsigned number phy identifier in the range
+                         of 0..FE .
+         jj..jj          Expander identifier. Either zero (indicating the PHY 
number
+                         iiiiiiii is on the SAS adapter itself) or identifies 
the PHY
+                         connecting to the expander, in which case iiiiiiii 
identifies
+                         a PHY on a SAS expander. In the non-zero case, 
jjjjjjjj is an
+                         8-bit unsigned number of the PHY plus one, in the 
range 1..FF
+         uu..uu          64-bit unsigned number logical unit number
+      */
+      sas_phy = grub_strtoul (disk_name + 1, 0, 16);
+      args.tgt_l = 0x10000 | sas_phy;
+      args.tgt_h = 0;
+    }
+  /* WWN addressing */
+  else if ((*disk_name =='w') && (*(disk_name + 1) == '5'))
+    {
+      /*          Bit #   33222222 22221111 11111100 00000000
+                          10987654 32109876 54321098 76543210
+
+          sas.hi cell:    0101vvvv vvvvvvvv vvvvvvvv vvvvssss
+          sas.lo cell:    ssssssss ssssssss ssssssss ssssssss
+          lun.hi cell:    uuuuuuuu uuuuuuuu uuuuuuuu uuuuuuuu
+          lun.lo cell:    uuuuuuuu uuuuuuuu uuuuuuuu uuuuuuuu
+
+          0101            The value "5" in the high-order NAA nibble
+          vv..vv          24-bit IEEE Organization ID
+          ss..ss          36-bit unsigned device serial number
+          uu..uu          64-bit unsigned number logical unit number
+      */
+      wwn = grub_strtoull (disk_name + 1, 0, 16);
+      args.tgt_l = wwn & 0xffffffff;
+      args.tgt_h = wwn >> 32;
+    }
+   /* Target LUN addressing */
+   else if (grub_isxdigit (*disk_name))
+    {
+      /* Deprecated
+                  Bit #   33222222 22221111 11111100 00000000
+                          10987654 32109876 54321098 76543210
+
+          sas.hi cell:    00000000 00000000 00000000 00000000
+          sas.lo cell:    00000000 00000000 00000000 tttttttt
+          lun.hi cell:    uuuuuuuu uuuuuuuu uuuuuuuu uuuuuuuu
+          lun.lo cell:    uuuuuuuu uuuuuuuu uuuuuuuu uuuuuuuu
+
+          00..00          Bits with the value zero
+          tt..tt          8-bit unsigned number target identifier in the range
+                          of 0..FF
+          uu..uu          64-bit unsigned number logical unit number
+      */
+      tgt = grub_strtol (disk_name, 0, 16);
+      if (tgt <= 0xff)
+        {
+          args.tgt_l = tgt;
+          args.tgt_h = 0;
+        }
+      else
+        return -1;
+    }
+  else
+    return -1;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  return args.catch_result;
+}
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
index b79e97b..7644956 100644
--- a/include/grub/ieee1275/ieee1275.h
+++ b/include/grub/ieee1275/ieee1275.h
@@ -148,6 +148,8 @@ enum grub_ieee1275_flag
   GRUB_IEEE1275_FLAG_CURSORONOFF_ANSI_BROKEN,
 
   GRUB_IEEE1275_FLAG_CACHE_OPEN,
+
+  GRUB_IEEE1275_FLAG_VALIDATE_DEV_ALIASES,
 };
 
 extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag);
@@ -213,6 +215,13 @@ int EXPORT_FUNC(grub_ieee1275_set_color) 
(grub_ieee1275_ihandle_t ihandle,
                                          int index, int r, int g, int b);
 int EXPORT_FUNC(grub_ieee1275_milliseconds) (grub_uint32_t *msecs);
 
+int EXPORT_FUNC(grub_ieee1275_set_address) (grub_ieee1275_ihandle_t ihandle,
+                                            grub_uint32_t target,
+                                            grub_uint32_t lun);
+
+int EXPORT_FUNC(grub_ieee1275_no_data_command) (grub_ieee1275_ihandle_t 
ihandle,
+                                                const void *cmd_addr,
+                                                grub_ssize_t *result);
 
 grub_err_t EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size);
 
diff --git a/include/grub/sparc64/ieee1275/ieee1275.h 
b/include/grub/sparc64/ieee1275/ieee1275.h
index 32c77f8..632eb87 100644
--- a/include/grub/sparc64/ieee1275/ieee1275.h
+++ b/include/grub/sparc64/ieee1275/ieee1275.h
@@ -21,6 +21,7 @@
 #define GRUB_IEEE1275_MACHINE_HEADER   1
 
 #include <grub/types.h>
+#include <grub/ieee1275/ieee1275.h>
 
 #define GRUB_IEEE1275_CELL_SIZEOF 8
 typedef grub_uint64_t grub_ieee1275_cell_t;
@@ -42,6 +43,9 @@ extern int EXPORT_FUNC(grub_ieee1275_claim_vaddr) 
(grub_addr_t vaddr,
 extern int EXPORT_FUNC(grub_ieee1275_alloc_physmem) (grub_addr_t *paddr,
                                                     grub_size_t size,
                                                     grub_uint32_t align);
+extern int EXPORT_FUNC(grub_ieee1275_set_sas_address) (grub_uint32_t ihandle,
+                                                       const char *disk_name,
+                                                       grub_uint64_t lun);
 
 extern grub_addr_t EXPORT_VAR (grub_ieee1275_original_stack);
 
-- 
1.7.1




reply via email to

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