All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/5] NVMeoFC support on Grub
@ 2024-08-30 11:40 Avnish Chouhan
  2024-08-30 11:41 ` [PATCH v4 1/5] ieee1275/powerpc: implements fibre channel discovery for ofpathname Avnish Chouhan
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Avnish Chouhan @ 2024-08-30 11:40 UTC (permalink / raw)
  To: grub-devel
  Cc: daniel.kiper, brking, meghanaprakash, mchang, phcoder,
	Avnish Chouhan

This patch series adds support of NVMeoFC on grub. It consists of five
patches.

Patch 1/5 (0001-ieee1275-powerpc-implements-fibre-channel-discovery-.patch):
grub-ofpathname doesn't work with fibre channel because there is no
function currently implemented for it.
This patch enables it by prividing a function that looks for the port
name, building the entire path for OF devices.

Patch 2/5(0002-ieee1275-implement-FCP-methods-for-WWPN-and-LUNs.patch):
This patch enables the fcp-targets and fcp-luns methods which are
responsible to get WWPNs and LUNs for fibre channel devices.
Those methods are specially necessary if the boot directory and grub
installation are in different FCP disks, allowing the dev_iterate()
to find the WWPNs and LUNs when called by searchfs.uuid tool.

Patch 3/5(0003-change-partition-parser.patch):
Usually grub will parse the PFW arguments by searching for the first occurence of the character ':'.
However, we can have this char more than once on NQN.
This patch changes the logic to find the last occurence of this char so we can get the proper values
for NVMeoFC

Patch 4/5(0004-ieee1275-add-support-for-NVMeoFC.patch):
This patch implements the functions to scan and discovery of NVMeoFC.

Patch 5/5(0005-ieee1275-ofpath-enable-NVMeoF-logical-device-transla.patch):
This patch add code to enable the translation of logical devices to the of NVMeoFC paths.

Avnish Chouhan (4):
  ieee1275: implement FCP methods for WWPN and LUNs
  ieee1275: change the logic of ieee1275_get_devargs()
  ieee1275: add support for NVMeoFC
  ieee1275: ofpath enable NVMeoF logical device translate

Diego Domingos (1):
  ieee1275/powerpc: implements fibre channel discovery for ofpathname

 grub-core/disk/ieee1275/ofdisk.c 
 grub-core/kern/ieee1275/openfw.c 
 grub-core/osdep/linux/ofpath.c   
 include/grub/util/ofpath.h       
 4 files changed

-- 
2.31.1


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v4 1/5] ieee1275/powerpc: implements fibre channel discovery for ofpathname
  2024-08-30 11:40 [PATCH v4 0/5] NVMeoFC support on Grub Avnish Chouhan
@ 2024-08-30 11:41 ` Avnish Chouhan
  2024-08-30 11:41 ` [PATCH v4 2/5] ieee1275: implement FCP methods for WWPN and LUNs Avnish Chouhan
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Avnish Chouhan @ 2024-08-30 11:41 UTC (permalink / raw)
  To: grub-devel
  Cc: daniel.kiper, brking, meghanaprakash, mchang, phcoder,
	Avnish Chouhan, Diego Domingos

grub-ofpathname doesn't work with fibre channel because there is no
function currently implemented for it.
This patch enables it by prividing a function that looks for the port
name, building the entire path for OF devices.

Signed-off-by: Diego Domingos <diegodo@br.ibm.com>
Signed-off-by: Avnish Chouhan <avnish@linux.ibm.com>
---
 grub-core/osdep/linux/ofpath.c | 49 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index a6153d35954..0f5d54e9f2d 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -350,6 +350,38 @@ of_path_of_ide(const char *sys_devname __attribute__((unused)), const char *devi
   return ret;
 }
 
+
+static void
+of_fc_port_name (const char *path, const char *subpath, char *port_name)
+{
+  char *bname, *basepath, *p;
+  int fd;
+
+  bname = xmalloc (sizeof (char) * 150);
+  basepath = xmalloc (strlen (path));
+
+  /* Generate the path to get port name information from the drive */
+  strncpy (basepath, path, subpath-path);
+  basepath[subpath-path - 1] = '\0';
+  p = get_basename (basepath);
+  snprintf (bname, sizeof (char) * 150, "%s/fc_transport/%s/port_name", basepath, p);
+
+  /* Read the information from the port name */
+  fd = open (bname, O_RDONLY);
+  if (fd < 0)
+    grub_util_error (_("cannot open `%s': %s"), bname, strerror (errno));
+
+  if (read (fd, port_name, sizeof (char) *19) < 0)
+    grub_util_error (_("cannot read `%s': %s"), bname, strerror (errno));
+
+  sscanf (port_name, "0x%s", port_name);
+
+  close (fd);
+
+  free (bname);
+  free (basepath);
+}
+
 #ifdef __sparc__
 static char *
 of_path_of_nvme(const char *sys_devname __attribute__((unused)),
@@ -577,6 +609,16 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
   digit_string = trailing_digits (device);
   if (strncmp (of_path, "/vdevice/", sizeof ("/vdevice/") - 1) == 0)
     {
+      if (strstr (of_path, "vfc-client"))
+        {
+	   char * port_name = xmalloc (sizeof (char) * 17);
+	   of_fc_port_name (sysfs_path, p, port_name);
+
+          snprintf (disk, sizeof (disk), "/%s@%s", disk_name, port_name);
+	   free (port_name);
+        }
+      else
+        {
       unsigned long id = 0x8000 | (tgt << 8) | (bus << 5) | lun;
       if (*digit_string == '\0')
 	{
@@ -590,6 +632,13 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
 	  snprintf(disk, sizeof (disk),
 		   "/%s@%04lx000000000000:%c", disk_name, id, 'a' + (part - 1));
 	}
+	}
+    } else if (strstr (of_path, "fibre-channel") || (strstr (of_path, "vfc-client"))){
+        char * port_name = xmalloc (sizeof (char) * 17);
+        of_fc_port_name (sysfs_path, p, port_name);
+
+	 snprintf (disk, sizeof (disk), "/%s@%s", disk_name, port_name);
+	 free (port_name);
     }
   else
     {

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v4 2/5] ieee1275: implement FCP methods for WWPN and LUNs
  2024-08-30 11:40 [PATCH v4 0/5] NVMeoFC support on Grub Avnish Chouhan
  2024-08-30 11:41 ` [PATCH v4 1/5] ieee1275/powerpc: implements fibre channel discovery for ofpathname Avnish Chouhan
@ 2024-08-30 11:41 ` Avnish Chouhan
  2024-08-30 11:41 ` [PATCH v4 3/5] ieee1275: change the logic of ieee1275_get_devargs() Avnish Chouhan
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Avnish Chouhan @ 2024-08-30 11:41 UTC (permalink / raw)
  To: grub-devel
  Cc: daniel.kiper, brking, meghanaprakash, mchang, phcoder,
	Avnish Chouhan, Diego Domingos

This patch enables the fcp-targets and fcp-luns methods which are
responsible to get WWPNs and LUNs for fibre channel devices.

Those methods are specially necessary if the boot directory and grub
installation are in different FCP disks, allowing the dev_iterate()
to find the WWPNs and LUNs when called by searchfs.uuid tool.

Signed-off-by: Diego Domingos <diegodo@br.ibm.com>
Signed-off-by: Avnish Chouhan <avnish@linux.ibm.com>
---
 grub-core/disk/ieee1275/ofdisk.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 110 insertions(+), 1 deletion(-)

diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index 5534684..5958e5e 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -209,7 +209,116 @@ dev_iterate_real (const char *name, const char *path)
 static void
 dev_iterate (const struct grub_ieee1275_devalias *alias)
 {
-  if (grub_strcmp (alias->type, "vscsi") == 0)
+  if (grub_strcmp (alias->type, "fcp") == 0)
+    {
+      /*
+       * If we are dealing with fcp devices, we need
+       * to find the WWPNs and LUNs to iterate them
+       */
+      grub_ieee1275_ihandle_t ihandle;
+      grub_uint64_t *ptr_targets, *ptr_luns, k, l;
+      unsigned int i, j, pos;
+      char *buf, *bufptr;
+      struct set_fcp_targets_args
+      {
+        struct grub_ieee1275_common_hdr common;
+        grub_ieee1275_cell_t method;
+        grub_ieee1275_cell_t ihandle;
+        grub_ieee1275_cell_t catch_result;
+        grub_ieee1275_cell_t nentries;
+        grub_ieee1275_cell_t table;
+      } args_targets;
+
+      struct set_fcp_luns_args
+      {
+        struct grub_ieee1275_common_hdr common;
+        grub_ieee1275_cell_t method;
+        grub_ieee1275_cell_t ihandle;
+        grub_ieee1275_cell_t wwpn_h;
+        grub_ieee1275_cell_t wwpn_l;
+        grub_ieee1275_cell_t catch_result;
+        grub_ieee1275_cell_t nentries;
+        grub_ieee1275_cell_t table;
+      } args_luns;
+
+      struct args_ret
+      {
+        grub_uint64_t addr;
+        grub_uint64_t len;
+      };
+
+      if (grub_ieee1275_open (alias->path, &ihandle))
+        {
+          grub_dprintf ("disk", "failed to open the disk while iterating FCP disk path=%s\n", alias->path);
+          return;
+        }
+
+      /* Setup the fcp-targets method to call via pfw*/
+      INIT_IEEE1275_COMMON (&args_targets.common, "call-method", 2, 3);
+      args_targets.method = (grub_ieee1275_cell_t) "fcp-targets";
+      args_targets.ihandle = ihandle;
+
+      /* Setup the fcp-luns method to call via pfw */
+      INIT_IEEE1275_COMMON (&args_luns.common, "call-method", 4, 3);
+      args_luns.method = (grub_ieee1275_cell_t) "fcp-luns";
+      args_luns.ihandle = ihandle;
+      if (IEEE1275_CALL_ENTRY_FN (&args_targets) == -1)
+        {
+          grub_dprintf ("disk", "failed to get the targets while iterating FCP disk path=%s\n", alias->path);
+          grub_ieee1275_close (ihandle);
+          return;
+        }
+      buf = grub_malloc (grub_strlen (alias->path) + 32 + 32);
+      if (!buf)
+        {
+          grub_ieee1275_close (ihandle);
+          return;
+        }
+      bufptr = grub_stpcpy (buf, alias->path);
+
+      /*
+       * Iterate over entries returned by pfw. Each entry contains a
+       * pointer to wwpn table and his length.
+       */
+      struct args_ret *targets_table = (struct args_ret *) (args_targets.table);
+      for (i = 0; i < args_targets.nentries; i++)
+        {
+          ptr_targets = (grub_uint64_t*) targets_table[i].addr;
+          /* Iterate over all wwpns in given table */
+          for(k = 0; k < targets_table[i].len; k++)
+            {
+              args_luns.wwpn_l = (grub_ieee1275_cell_t) (*ptr_targets);
+              args_luns.wwpn_h = (grub_ieee1275_cell_t) (*ptr_targets >> 32);
+              pos = grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T,
+                                  grub_get_unaligned64 (*ptr_targets++));
+              /* Get the luns for given wwpn target */
+              if (IEEE1275_CALL_ENTRY_FN (&args_luns) == -1)
+                {
+                  grub_dprintf ("disk", "failed to get the LUNS while iterating FCP disk path=%s\n", buf);
+                  grub_ieee1275_close (ihandle);
+                  grub_free (buf);
+                  return;
+                }
+              struct args_ret *luns_table = (struct args_ret *) (args_luns.table);
+
+              /* Iterate over all LUNs */
+              for(j = 0; j < args_luns.nentries; j++)
+                {
+                  ptr_luns = (grub_uint64_t*) luns_table[j].addr;
+                  for(l = 0; l < luns_table[j].len; l++)
+                    {
+                      grub_snprintf (&bufptr[pos], 30, ",%" PRIxGRUB_UINT64_T,
+                                    grub_get_unaligned64 (*ptr_luns++));
+                      dev_iterate_real (buf, buf);
+                    }
+                }
+            }
+        }
+      grub_ieee1275_close (ihandle);
+      grub_free (buf);
+      return;
+    }
+  else if (grub_strcmp (alias->type, "vscsi") == 0)
     {
       static grub_ieee1275_ihandle_t ihandle;
       struct set_color_args
-- 
2.31.1


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v4 3/5] ieee1275: change the logic of ieee1275_get_devargs()
  2024-08-30 11:40 [PATCH v4 0/5] NVMeoFC support on Grub Avnish Chouhan
  2024-08-30 11:41 ` [PATCH v4 1/5] ieee1275/powerpc: implements fibre channel discovery for ofpathname Avnish Chouhan
  2024-08-30 11:41 ` [PATCH v4 2/5] ieee1275: implement FCP methods for WWPN and LUNs Avnish Chouhan
@ 2024-08-30 11:41 ` Avnish Chouhan
  2024-08-30 11:41 ` [PATCH v4 4/5] ieee1275: add support for NVMeoFC Avnish Chouhan
  2024-08-30 11:41 ` [PATCH v4 5/5] ieee1275: ofpath enable NVMeoF logical device translate Avnish Chouhan
  4 siblings, 0 replies; 8+ messages in thread
From: Avnish Chouhan @ 2024-08-30 11:41 UTC (permalink / raw)
  To: grub-devel
  Cc: daniel.kiper, brking, meghanaprakash, mchang, phcoder,
	Avnish Chouhan, Diego Domingos

Usually grub will parse the PFW arguments by searching for the first occurence of the character ':'.
However, we can have this char more than once on NQN.
This patch changes the logic to find the last occurence of this char so we can get the proper values
for NVMeoFC

Signed-off-by: Diego Domingos <diegodo@br.ibm.com>
Signed-off-by: Avnish Chouhan <avnish@linux.ibm.com>
---
 grub-core/kern/ieee1275/openfw.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
index 0278054..b97104c 100644
--- a/grub-core/kern/ieee1275/openfw.c
+++ b/grub-core/kern/ieee1275/openfw.c
@@ -324,7 +324,7 @@ grub_claimmap (grub_addr_t addr, grub_size_t size)
 static char *
 grub_ieee1275_get_devargs (const char *path)
 {
-  char *colon = grub_strchr (path, ':');
+  char *colon = grub_strrchr (path, ':');
 
   if (! colon)
     return 0;
@@ -339,6 +339,21 @@ grub_ieee1275_get_devname (const char *path)
   char *colon = grub_strchr (path, ':');
   int pathlen = grub_strlen (path);
   struct grub_ieee1275_devalias curalias;
+
+  /* Check some special cases */
+  if (grub_strstr (path, "nvme-of"))
+    {
+      char *namespace_split = grub_strstr (path, "/namespace@");
+      if (namespace_split)
+        {
+          colon = grub_strchr (namespace_split, ':');
+        }
+      else
+        {
+          colon = NULL;
+        }
+    }
+
   if (colon)
     pathlen = (int)(colon - path);
 
@@ -579,7 +594,7 @@ grub_ieee1275_get_boot_dev (void)
       return NULL;
     }
 
-  bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64);
+  bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64 + 256);
   if (! bootpath)
     {
       grub_print_error ();
-- 
2.31.1


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v4 4/5] ieee1275: add support for NVMeoFC
  2024-08-30 11:40 [PATCH v4 0/5] NVMeoFC support on Grub Avnish Chouhan
                   ` (2 preceding siblings ...)
  2024-08-30 11:41 ` [PATCH v4 3/5] ieee1275: change the logic of ieee1275_get_devargs() Avnish Chouhan
@ 2024-08-30 11:41 ` Avnish Chouhan
  2024-08-30 11:41 ` [PATCH v4 5/5] ieee1275: ofpath enable NVMeoF logical device translate Avnish Chouhan
  4 siblings, 0 replies; 8+ messages in thread
From: Avnish Chouhan @ 2024-08-30 11:41 UTC (permalink / raw)
  To: grub-devel
  Cc: daniel.kiper, brking, meghanaprakash, mchang, phcoder,
	Avnish Chouhan, Diego Domingos

This patch implements the functions to scan and discovery of NVMeoFC.

Signed-off-by: Diego Domingos <diegodo@br.ibm.com>
Signed-off-by: Avnish Chouhan <avnish@linux.ibm.com>
---
 grub-core/disk/ieee1275/ofdisk.c | 390 +++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 296 insertions(+), 94 deletions(-)

diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index afdc272..cea10e1 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -24,6 +24,8 @@
 #include <grub/ieee1275/ofdisk.h>
 #include <grub/i18n.h>
 #include <grub/time.h>
+#define EXTEND_PATH_64 64
+#define EXTEND_PATH_512 512
 
 static char *last_devpath;
 static grub_ieee1275_ihandle_t last_ihandle;
@@ -207,116 +209,316 @@ dev_iterate_real (const char *name, const char *path)
 }
 
 static void
-dev_iterate (const struct grub_ieee1275_devalias *alias)
+dev_iterate_fcp_disks (const struct grub_ieee1275_devalias *alias)
 {
-  if (grub_strcmp (alias->type, "fcp") == 0)
+  /*
+   * If we are dealing with fcp devices, we need
+   * to find the WWPNs and LUNs to iterate them
+   */
+  grub_ieee1275_ihandle_t ihandle;
+  grub_uint64_t *ptr_targets, *ptr_luns, k, l;
+  unsigned int i, j, pos;
+  char *buf, *bufptr;
+  struct set_fcp_targets_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t catch_result;
+    grub_ieee1275_cell_t nentries;
+    grub_ieee1275_cell_t table;
+  } args_targets;
+
+  struct set_fcp_luns_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t wwpn_h;
+    grub_ieee1275_cell_t wwpn_l;
+    grub_ieee1275_cell_t catch_result;
+    grub_ieee1275_cell_t nentries;
+    grub_ieee1275_cell_t table;
+  } args_luns;
+
+  struct args_ret
+  {
+    grub_uint64_t addr;
+    grub_uint64_t len;
+  };
+  struct args_ret *targets_table;
+  struct args_ret *luns_table;
+
+  if (grub_ieee1275_open (alias->path, &ihandle))
     {
-      /*
-       * If we are dealing with fcp devices, we need
-       * to find the WWPNs and LUNs to iterate them
-       */
-      grub_ieee1275_ihandle_t ihandle;
-      grub_uint64_t *ptr_targets, *ptr_luns, k, l;
-      unsigned int i, j, pos;
-      char *buf, *bufptr;
-      struct set_fcp_targets_args
-      {
-        struct grub_ieee1275_common_hdr common;
-        grub_ieee1275_cell_t method;
-        grub_ieee1275_cell_t ihandle;
-        grub_ieee1275_cell_t catch_result;
-        grub_ieee1275_cell_t nentries;
-        grub_ieee1275_cell_t table;
-      } args_targets;
-
-      struct set_fcp_luns_args
-      {
-        struct grub_ieee1275_common_hdr common;
-        grub_ieee1275_cell_t method;
-        grub_ieee1275_cell_t ihandle;
-        grub_ieee1275_cell_t wwpn_h;
-        grub_ieee1275_cell_t wwpn_l;
-        grub_ieee1275_cell_t catch_result;
-        grub_ieee1275_cell_t nentries;
-        grub_ieee1275_cell_t table;
-      } args_luns;
-
-      struct args_ret
-      {
-        grub_uint64_t addr;
-        grub_uint64_t len;
-      };
+      grub_dprintf ("disk", "failed to open the disk while iterating FCP disk path=%s\n", alias->path);
+      return;
+    }
+
+  /* Setup the fcp-targets method to call via pfw*/
+  INIT_IEEE1275_COMMON (&args_targets.common, "call-method", 2, 3);
+  args_targets.method = (grub_ieee1275_cell_t) "fcp-targets";
+  args_targets.ihandle = ihandle;
 
-      if (grub_ieee1275_open (alias->path, &ihandle))
+  /* Setup the fcp-luns method to call via pfw */
+  INIT_IEEE1275_COMMON (&args_luns.common, "call-method", 4, 3);
+  args_luns.method = (grub_ieee1275_cell_t) "fcp-luns";
+  args_luns.ihandle = ihandle;
+  if (IEEE1275_CALL_ENTRY_FN (&args_targets) == -1)
+    {
+      grub_dprintf ("disk", "failed to get the targets while iterating FCP disk path=%s\n", alias->path);
+      grub_ieee1275_close (ihandle);
+      return;
+    }
+  /* Allocate memory for building the path */
+  buf = grub_malloc (grub_strlen (alias->path) + EXTEND_PATH_64);
+  if (!buf)
+    {
+      grub_ieee1275_close (ihandle);
+      return;
+    }
+  bufptr = grub_stpcpy (buf, alias->path);
+
+  /*
+   * Iterate over entries returned by pfw. Each entry contains a
+   * pointer to wwpn table and his length.
+   */
+  targets_table = (struct args_ret *) (args_targets.table);
+  for (i = 0; i < args_targets.nentries; i++)
+    {
+      ptr_targets = (grub_uint64_t*) targets_table[i].addr;
+      /* Iterate over all wwpns in given table */
+      for (k = 0; k < targets_table[i].len; k++)
         {
-          grub_dprintf ("disk", "failed to open the disk while iterating FCP disk path=%s\n", alias->path);
-          return;
+          args_luns.wwpn_l = (grub_ieee1275_cell_t) (*ptr_targets);
+          args_luns.wwpn_h = (grub_ieee1275_cell_t) (*ptr_targets >> 32);
+          pos = grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T,
+                              grub_get_unaligned64 (*ptr_targets++));
+          /* Get the luns for given wwpn target */
+          if (IEEE1275_CALL_ENTRY_FN (&args_luns) == -1)
+            {
+              grub_dprintf ("disk", "failed to get the LUNS while iterating FCP disk path=%s\n", buf);
+              grub_ieee1275_close (ihandle);
+              grub_free (buf);
+              return;
+            }
+          luns_table = (struct args_ret *) (args_luns.table);
+
+          /* Iterate over all LUNs */
+          for (j = 0; j < args_luns.nentries; j++)
+            {
+              ptr_luns = (grub_uint64_t*) luns_table[j].addr;
+              for (l = 0; l < luns_table[j].len; l++)
+                {
+                  grub_snprintf (&bufptr[pos], 30, ",%" PRIxGRUB_UINT64_T,
+                                grub_get_unaligned64 (*ptr_luns++));
+                  dev_iterate_real (buf, buf);
+                }
+            }
         }
+    }
+  grub_ieee1275_close (ihandle);
+  grub_free (buf);
+  return;
+}
+
+static void
+dev_iterate_fcp_nvmeof (const struct grub_ieee1275_devalias *alias)
+{
+  char *bufptr;
+  grub_ieee1275_ihandle_t ihandle;
+
+  /* Create the structs for the parameters passing to PFW */
+  struct nvme_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t catch_result;
+    grub_ieee1275_cell_t nentries;
+    grub_ieee1275_cell_t table;
+  } nvme_discovery_controllers_args, nvme_controllers_args, nvme_namespaces_args;
+
+  /* Create the structs for the results from PFW */
+  struct discovery_controllers_table_struct
+  {
+    grub_uint64_t table[256];
+    grub_uint32_t len;
+  } discovery_controllers_table;
+
+  /*
+   * struct nvme_controllers_table_entry
+   * this the return of nvme-controllers method tables, containing:
+   * - 2-byte controller ID
+   * - 256-byte transport address string
+   * - 256-byte field containing null-terminated NVM subsystem NQN string up to 223 characters
+   */
+  struct nvme_controllers_table_entry
+  {
+    grub_uint16_t id;
+    char wwpn[256];
+    char nqn[256];
+  };
+
+  struct nvme_controllers_table_entry_real
+  {
+    grub_uint16_t id;
+    char wwpn[256];
+    char nqn[256];
+  };
+
+  struct nvme_controllers_table_entry* nvme_controllers_table;
+  grub_uint32_t nvme_controllers_table_entries;
+  char *buf;
+  unsigned int i = 0;
+  int current_buffer_index;
+  int nvme_controller_index;
+  int bufptr_pos2;
+  grub_uint32_t namespace_index = 0;
+  struct nvme_controllers_table_entry* nvme_controllers_table_buf;
+
+  nvme_controllers_table = grub_malloc (sizeof (struct nvme_controllers_table_entry) * 256);
+  /* Allocate memory for building the NVMeoF path */
+  buf = grub_malloc (grub_strlen (alias->path) + EXTEND_PATH_512);
+
+  if (!buf || !nvme_controllers_table)
+    {
+      grub_free (nvme_controllers_table);
+      grub_free (buf);
+      return;
+    }
+
+  /* Copy the alias->path to buf so we can work with */
+  bufptr = grub_stpcpy (buf, alias->path);
+  grub_snprintf (bufptr, 32, "/nvme-of");
+
+  /*
+   *  Open the nvme-of layer
+   *  Ex.  /pci@bus/fibre-channel@@dev,func/nvme-of
+   */
+  if (grub_ieee1275_open (buf, &ihandle))
+    {
+      grub_dprintf ("disk", "failed to open the disk while iterating FCP disk path=%s\n", buf);
+      grub_free (nvme_controllers_table);
+      grub_free (buf);
+      return;
+    }
+
+  /*
+   * Call to nvme-discovery-controllers method from the nvme-of layer
+   * to get a list of the NVMe discovery controllers per the binding
+   */
+  INIT_IEEE1275_COMMON (&nvme_discovery_controllers_args.common, "call-method", 2, 2);
+  nvme_discovery_controllers_args.method = (grub_ieee1275_cell_t) "nvme-discovery-controllers";
+  nvme_discovery_controllers_args.ihandle = ihandle;
+  if (IEEE1275_CALL_ENTRY_FN (&nvme_discovery_controllers_args) == -1)
+    {
+      grub_dprintf ("disk", "failed to get the targets while iterating FCP disk path=%s\n", buf);
+      grub_free (nvme_controllers_table);
+      grub_free (buf);
+      grub_ieee1275_close (ihandle);
+      return;
+    }
+
+  /* After closing the device, the info is lost. So lets copy each buffer in the buffers table */
+  discovery_controllers_table.len = (grub_uint32_t) nvme_discovery_controllers_args.nentries;
+
+  for (i = 0; i < discovery_controllers_table.len; i++)
+    {
+      discovery_controllers_table.table[i] = ((grub_uint64_t*) nvme_discovery_controllers_args.table)[i];
+    }
 
-      /* Setup the fcp-targets method to call via pfw*/
-      INIT_IEEE1275_COMMON (&args_targets.common, "call-method", 2, 3);
-      args_targets.method = (grub_ieee1275_cell_t) "fcp-targets";
-      args_targets.ihandle = ihandle;
+  grub_ieee1275_close (ihandle);
+  grub_dprintf ("ofdisk","NVMeoF: Found %d discovery controllers\n", discovery_controllers_table.len);
 
-      /* Setup the fcp-luns method to call via pfw */
-      INIT_IEEE1275_COMMON (&args_luns.common, "call-method", 4, 3);
-      args_luns.method = (grub_ieee1275_cell_t) "fcp-luns";
-      args_luns.ihandle = ihandle;
-      if (IEEE1275_CALL_ENTRY_FN (&args_targets) == -1)
+  /* For each nvme discovery controller */
+  for (current_buffer_index = 0; current_buffer_index < (int) discovery_controllers_table.len; current_buffer_index++)
+    {
+      grub_snprintf (bufptr, 64, "/nvme-of/controller@%" PRIxGRUB_UINT64_T ",ffff",
+                     discovery_controllers_table.table[current_buffer_index]);
+      grub_dprintf("ofdisk", "nvmeof controller=%s\n", buf);
+      if (grub_ieee1275_open (buf, &ihandle))
         {
-          grub_dprintf ("disk", "failed to get the targets while iterating FCP disk path=%s\n", alias->path);
-          grub_ieee1275_close (ihandle);
-          return;
+          grub_dprintf ("ofdisk", "failed to open the disk while getting nvme-controllers  path=%s\n", buf);
+          continue;
         }
-      buf = grub_malloc (grub_strlen (alias->path) + 32 + 32);
-      if (!buf)
+      INIT_IEEE1275_COMMON (&nvme_controllers_args.common, "call-method", 2, 2);
+      nvme_controllers_args.method = (grub_ieee1275_cell_t) "nvme-controllers";
+      nvme_controllers_args.ihandle = ihandle;
+      nvme_controllers_args.catch_result = 0;
+
+      if (IEEE1275_CALL_ENTRY_FN (&nvme_controllers_args) == -1)
         {
+          grub_dprintf ("ofdisk", "failed to get the nvme-controllers while iterating FCP disk path\n");
           grub_ieee1275_close (ihandle);
-          return;
+          continue;
         }
-      bufptr = grub_stpcpy (buf, alias->path);
 
-      /*
-       * Iterate over entries returned by pfw. Each entry contains a
-       * pointer to wwpn table and his length.
-       */
-      struct args_ret *targets_table = (struct args_ret *) (args_targets.table);
-      for (i = 0; i < args_targets.nentries; i++)
+      /* Copy the buffer list to nvme_controllers_table */
+      nvme_controllers_table_entries = ((grub_uint32_t) nvme_controllers_args.nentries);
+      nvme_controllers_table_buf = (struct nvme_controllers_table_entry*) nvme_controllers_args.table;
+      for (i = 0; i < nvme_controllers_table_entries; i++)
         {
-          ptr_targets = (grub_uint64_t*) targets_table[i].addr;
-          /* Iterate over all wwpns in given table */
-          for(k = 0; k < targets_table[i].len; k++)
-            {
-              args_luns.wwpn_l = (grub_ieee1275_cell_t) (*ptr_targets);
-              args_luns.wwpn_h = (grub_ieee1275_cell_t) (*ptr_targets >> 32);
-              pos = grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T,
-                                  grub_get_unaligned64 (*ptr_targets++));
-              /* Get the luns for given wwpn target */
-              if (IEEE1275_CALL_ENTRY_FN (&args_luns) == -1)
-                {
-                  grub_dprintf ("disk", "failed to get the LUNS while iterating FCP disk path=%s\n", buf);
-                  grub_ieee1275_close (ihandle);
-                  grub_free (buf);
-                  return;
-                }
-              struct args_ret *luns_table = (struct args_ret *) (args_luns.table);
+	  nvme_controllers_table[i].id = (grub_uint16_t) nvme_controllers_table_buf[i].id;
+	  grub_strcpy (nvme_controllers_table[i].wwpn, nvme_controllers_table_buf[i].wwpn);
+	  grub_strcpy (nvme_controllers_table[i].nqn, nvme_controllers_table_buf[i].nqn);
+	}
+      grub_ieee1275_close (ihandle);
+      grub_dprintf ("ofdisk", "NVMeoF: found %d nvme controllers\n", (int) nvme_controllers_args.nentries);
 
-              /* Iterate over all LUNs */
-              for(j = 0; j < args_luns.nentries; j++)
-                {
-                  ptr_luns = (grub_uint64_t*) luns_table[j].addr;
-                  for(l = 0; l < luns_table[j].len; l++)
-                    {
-                      grub_snprintf (&bufptr[pos], 30, ",%" PRIxGRUB_UINT64_T,
-                                    grub_get_unaligned64 (*ptr_luns++));
-                      dev_iterate_real (buf, buf);
-                    }
-                }
+      /* For each nvme controller */
+      for (nvme_controller_index = 0; nvme_controller_index < (int) nvme_controllers_args.nentries; nvme_controller_index++)
+        {
+          /*
+	   * Open the nvme controller
+           * /pci@bus/fibre-channel@dev,func/nvme-of/controller@transport-addr,ctlr-id:nqn=tgt-subsystem-nqn
+           */
+          bufptr_pos2 = grub_snprintf (bufptr, 512, "/nvme-of/controller@%s,ffff:nqn=%s",
+                                       nvme_controllers_table[nvme_controller_index].wwpn, nvme_controllers_table[nvme_controller_index].nqn);
+	  grub_dprintf ("ofdisk", "NVMeoF: nvmeof controller=%s\n", buf);
+          if (grub_ieee1275_open (buf, &ihandle))
+	    {
+             grub_dprintf ("ofdisk", "failed to open the path=%s\n", buf);
+	      continue;
+	    }
+          INIT_IEEE1275_COMMON (&nvme_namespaces_args.common, "call-method", 2, 2);
+          nvme_namespaces_args.method = (grub_ieee1275_cell_t) "get-namespace-list";
+          nvme_namespaces_args.ihandle = ihandle;
+          nvme_namespaces_args.catch_result = 0;
+
+	  if (IEEE1275_CALL_ENTRY_FN (&nvme_namespaces_args) == -1)
+            {
+              grub_dprintf ("ofdisk", "failed to get the nvme-namespace-list while iterating FCP disk path\n");
+              grub_ieee1275_close (ihandle);
+              continue;
             }
-        }
-      grub_ieee1275_close (ihandle);
-      grub_free (buf);
-      return;
+         grub_uint32_t *namespaces = (grub_uint32_t*) nvme_namespaces_args.table;
+	  grub_dprintf ("ofdisk", "NVMeoF: found %d namespaces\n", (int)nvme_namespaces_args.nentries);
+	  grub_ieee1275_close (ihandle);
+         namespace_index = 0;
+	  for (namespace_index=0; namespace_index < nvme_namespaces_args.nentries; namespace_index++)
+	    {
+	      grub_snprintf (bufptr+bufptr_pos2, 512, "/namespace@%"PRIxGRUB_UINT32_T, namespaces[namespace_index]);
+             grub_dprintf ("ofdisk", "NVMeoF: namespace=%s\n", buf);
+             dev_iterate_real (buf, buf);
+           }
+         dev_iterate_real (buf, buf);
+	}
+    }
+  grub_free (buf);
+  grub_free (nvme_controllers_table);
+  return;
+}
+
+static void
+dev_iterate (const struct grub_ieee1275_devalias *alias)
+{
+  if (grub_strcmp (alias->type, "fcp") == 0)
+    {
+      /* Iterate disks */
+      dev_iterate_fcp_disks (alias);
+      /* Iterate NVMeoF */
+      dev_iterate_fcp_nvmeof (alias);
     }
   else if (grub_strcmp (alias->type, "vscsi") == 0)
     {
-- 
2.31.1


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v4 5/5] ieee1275: ofpath enable NVMeoF logical device translate
  2024-08-30 11:40 [PATCH v4 0/5] NVMeoFC support on Grub Avnish Chouhan
                   ` (3 preceding siblings ...)
  2024-08-30 11:41 ` [PATCH v4 4/5] ieee1275: add support for NVMeoFC Avnish Chouhan
@ 2024-08-30 11:41 ` Avnish Chouhan
  2025-02-12  8:14   ` Michael Chang via Grub-devel
  4 siblings, 1 reply; 8+ messages in thread
From: Avnish Chouhan @ 2024-08-30 11:41 UTC (permalink / raw)
  To: grub-devel
  Cc: daniel.kiper, brking, meghanaprakash, mchang, phcoder,
	Avnish Chouhan, Diego Domingos

This patch adds code to enable the translation of logical devices to the of NVMeoFC paths.

Signed-off-by: Diego Domingos <diegodo@br.ibm.com>
Signed-off-by: Avnish Chouhan <avnish@linux.ibm.com>
---
 grub-core/osdep/linux/ofpath.c | 371 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 include/grub/util/ofpath.h     | 28 ++++++++++++++++++++++++++++
 2 files changed, 390 insertions(+), 9 deletions(-)

diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 0f5d54e..f0e7dcc 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -37,6 +37,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <ctype.h>
+#include <dirent.h>
 
 #ifdef __sparc__
 typedef enum
@@ -136,7 +137,7 @@ trim_newline (char *path)
     *end-- = '\0';
 }
 
-#define MAX_DISK_CAT    64
+#define MAX_DISK_CAT    512
 
 static char *
 find_obppath (const char *sysfs_path_orig)
@@ -312,6 +313,91 @@ get_basename(char *p)
   return ret;
 }
 
+int
+add_filename_to_pile (char *filename, struct ofpath_files_list_root* root)
+{
+  struct ofpath_files_list_node* file;
+
+  file = malloc (sizeof (struct ofpath_files_list_node));
+  if (!file)
+    return -1;
+
+  file->filename = malloc (sizeof (char) * 1024);
+  if (!file->filename)
+    {
+      free (file);
+      return -1;
+    }
+
+  grub_strcpy (file->filename, filename);
+  if (root->first == NULL)
+    {
+      root->items = 1;
+      root->first = file;
+      file->next = NULL;
+    }
+  else
+    {
+      root->items++;
+      file->next = root->first;
+      root->first = file;
+    }
+
+  return 0;
+}
+
+void
+find_file (char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth)
+{
+  struct dirent *ep;
+  struct stat statbuf;
+  DIR *dp;
+  int ret_val=0;
+  char* full_path;
+
+  if (depth > max_depth)
+    {
+      return;
+    }
+
+  if ((dp = opendir (directory)) == NULL)
+    {
+      return;
+    }
+
+  full_path = malloc (1024 * sizeof (char));
+  if (!full_path)
+    return;
+
+  while ((ep = readdir(dp)) != NULL)
+    {
+      snprintf (full_path, 1024, "%s/%s", directory, ep->d_name);
+      lstat (full_path, &statbuf);
+
+      if (S_ISLNK (statbuf.st_mode))
+        {
+          continue;
+        }
+
+      if (!strcmp (ep->d_name, ".") || !strcmp(ep->d_name, ".."))
+        {
+          continue;
+        }
+
+      if (!strcmp (ep->d_name, filename))
+        {
+          ret_val = add_filename_to_pile (full_path, root);
+          if (ret_val == -1)
+            continue;
+        }
+
+      find_file (filename, full_path, root, max_depth, depth+1);
+    }
+
+  free (full_path);
+  closedir (dp);
+}
+
 static char *
 of_path_of_vdisk(const char *sys_devname __attribute__((unused)),
 		 const char *device,
@@ -382,7 +468,200 @@ of_fc_port_name (const char *path, const char *subpath, char *port_name)
   free (basepath);
 }
 
-#ifdef __sparc__
+void
+free_ofpath_files_list (struct ofpath_files_list_root* root)
+{
+  struct ofpath_files_list_node* node = root->first;
+  struct ofpath_files_list_node* next;
+
+  while (node!=NULL)
+    {
+      next = node->next;
+      free (node->filename);
+      free (node);
+      node = next;
+    }
+
+  free (root);
+  return;
+}
+
+char*
+of_find_fc_host (char* host_wwpn)
+{
+  FILE* fp;
+  char *buf;
+  char *ret_val;
+  char portname_filename[sizeof ("port_name")] = "port_name";
+  char devices_path[sizeof ("/sys/devices")] = "/sys/devices";
+  struct ofpath_files_list_root* portnames_file_list;
+  struct ofpath_files_list_node* node;
+
+  ret_val = malloc (sizeof (char) * 1024);
+  if (!ret_val)
+    return NULL;
+
+  portnames_file_list = malloc (sizeof (struct ofpath_files_list_root));
+  if (!portnames_file_list)
+    {
+      free (ret_val);
+      return NULL;
+    }
+
+  portnames_file_list->items = 0;
+  portnames_file_list->first = NULL;
+  find_file (portname_filename, devices_path, portnames_file_list, 10, 0);
+  node = portnames_file_list->first;
+
+  while (node != NULL)
+    {
+      fp = fopen(node->filename, "r");
+      buf = malloc (sizeof (char) * 512);
+      if (!buf)
+        break;
+
+      fscanf (fp, "%s", buf);
+      fclose (fp);
+
+      if ((strcmp (buf, host_wwpn) == 0) && grub_strstr (node->filename, "fc_host"))
+        {
+          free (buf);
+          grub_strcpy (ret_val, node->filename);
+          free_ofpath_files_list (portnames_file_list);
+          return ret_val;
+        }
+
+      node = node->next;
+      free (buf);
+    }
+  free_ofpath_files_list (portnames_file_list);
+  free (ret_val);
+  return NULL;
+}
+
+int
+of_path_get_nvmeof_adapter_info (char* sysfs_path,
+                                 struct ofpath_nvmeof_info* nvmeof_info)
+{
+  FILE *fp;
+  char *buf, *buf2, *buf3;
+
+  nvmeof_info->host_wwpn = malloc (sizeof (char) * 256);
+  nvmeof_info->target_wwpn = malloc (sizeof (char) * 256);
+  nvmeof_info->nqn = malloc (sizeof (char) * 256);
+
+  if (nvmeof_info->host_wwpn == NULL || nvmeof_info->target_wwpn == NULL || nvmeof_info->nqn == NULL)
+    {
+      free (nvmeof_info->host_wwpn);
+      free (nvmeof_info->target_wwpn);
+      free (nvmeof_info->nqn);
+      return -1;
+    }
+
+  buf = malloc (sizeof (char) * 512);
+  if (!buf)
+    {
+      free (nvmeof_info->host_wwpn);
+      free (nvmeof_info->target_wwpn);
+      free (nvmeof_info->nqn);
+      return -1;
+    }
+
+  snprintf (buf, 512, "%s/subsysnqn", sysfs_path);
+  fp = fopen (buf, "r");
+  fscanf (fp, "%s", nvmeof_info->nqn);
+  fclose (fp);
+
+  snprintf (buf, 512, "%s/cntlid", sysfs_path);
+  fp = fopen (buf, "r");
+  fscanf (fp, "%u", &(nvmeof_info->cntlid));
+  fclose (fp);
+
+  snprintf (buf, 512, "%s/address", sysfs_path);
+  fp = fopen (buf, "r");
+  buf2 = malloc (sizeof (char) * 512);
+
+  if (!buf2)
+    {
+      free (nvmeof_info->host_wwpn);
+      free (nvmeof_info->target_wwpn);
+      free (nvmeof_info->nqn);
+      free (buf);
+      return -1;
+    }
+
+  fscanf (fp, "%s", buf2);
+  fclose (fp);
+
+  buf3 = strrchr (buf2, '-') + 1;
+  grub_memcpy (nvmeof_info->host_wwpn, buf3, 256);
+  buf3=strchr (buf2, '-') + 1;
+  buf3=strchr (buf3, '-') + 1;
+  buf3=strchr (buf3, 'x') + 1;
+  grub_memcpy (nvmeof_info->target_wwpn, buf3, 256);
+  buf3 = strchr (nvmeof_info->target_wwpn, ',');
+  *buf3 = '\0';
+  free (buf);
+  free (buf2);
+  return 0;
+}
+
+#define MAX_NVME_NSID_DIGITS 6
+
+static char *
+of_path_get_nvme_controller_name_node (const char* devname)
+{
+  char *controller_node, *end;
+
+  controller_node = strdup (devname);
+  end = grub_strchr (controller_node + 1, 'n');
+  if (end != NULL)
+    {
+      *end = '\0';
+    }
+
+  return controller_node;
+}
+
+unsigned int
+of_path_get_nvme_nsid (const char* devname)
+{
+  unsigned int nsid;
+  char *sysfs_path, *buf;
+  FILE *fp;
+
+  buf = malloc (sizeof(char) * 512);
+  if (!buf)
+    return 0;
+
+  sysfs_path = block_device_get_sysfs_path_and_link (devname);
+  snprintf (buf, 512, "%s/%s/nsid", sysfs_path, devname);
+  fp = fopen(buf, "r");
+  fscanf (fp, "%u", &(nsid));
+  fclose (fp);
+
+  free (sysfs_path);
+  free (buf);
+  return nsid;
+}
+
+static char *
+nvme_get_syspath (const char *nvmedev)
+{
+  char *sysfs_path, *controller_node;
+
+  sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
+  if (strstr (sysfs_path, "nvme-subsystem"))
+    {
+      controller_node = of_path_get_nvme_controller_name_node (nvmedev);
+      strcat (sysfs_path, "/");
+      strcat (sysfs_path, controller_node);
+      sysfs_path = xrealpath (sysfs_path);
+    }
+
+  return sysfs_path;
+}
+
 static char *
 of_path_of_nvme(const char *sys_devname __attribute__((unused)),
 	        const char *device,
@@ -391,6 +670,8 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
 {
   char *sysfs_path, *of_path, disk[MAX_DISK_CAT];
   const char *digit_string, *part_end;
+  int chars_written, ret_val;
+  struct ofpath_nvmeof_info* nvmeof_info;
 
   digit_string = trailing_digits (device);
   part_end = devicenode + strlen (devicenode) - 1;
@@ -410,15 +691,90 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
       /* Remove the p. */
       *end = '\0';
       sscanf (digit_string, "%d", &part);
-      snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
-      sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
+      sysfs_path = nvme_get_syspath (nvmedev);
+
+      /* If is a NVMeoF */
+      if (strstr (sysfs_path, "nvme-fabrics"))
+        {
+          nvmeof_info = malloc (sizeof (struct ofpath_nvmeof_info));
+          if (!nvmeof_info)
+            {
+              free (nvmedev);
+              return NULL;
+            }
+
+          ret_val = of_path_get_nvmeof_adapter_info (sysfs_path, nvmeof_info);
+          if (ret_val == -1)
+            {
+              free (nvmedev);
+              free (nvmeof_info);
+              return NULL;
+            }
+
+          sysfs_path = of_find_fc_host (nvmeof_info->host_wwpn);
+          if (!sysfs_path)
+            {
+              free (nvmedev);
+              free (nvmeof_info);
+              return NULL;
+            }
+
+          chars_written = snprintf (disk,sizeof(disk), "/nvme-of/controller@%s,%x:nqn=%s",
+                                    nvmeof_info->target_wwpn,0xffff,
+                                    nvmeof_info->nqn);
+          unsigned int nsid = of_path_get_nvme_nsid (nvmedev);
+          if (nsid)
+            {
+              snprintf (disk+chars_written, sizeof("/namespace@") + MAX_NVME_NSID_DIGITS,
+                        "/namespace@%x:%d", nsid, part);
+            }
+          free (nvmeof_info);
+        }
+      else
+        {
+          snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
+        }
       free (nvmedev);
     }
   else
     {
       /* We do not have the parition. */
-      snprintf (disk, sizeof (disk), "/disk@1");
-      sysfs_path = block_device_get_sysfs_path_and_link (device);
+      sysfs_path = nvme_get_syspath (device);
+      if (strstr (sysfs_path, "nvme-fabrics"))
+        {
+          nvmeof_info = malloc (sizeof (struct ofpath_nvmeof_info));
+          if (!nvmeof_info)
+            return NULL;
+
+          ret_val = of_path_get_nvmeof_adapter_info (sysfs_path, nvmeof_info);
+          if (ret_val == -1)
+            {
+              free (nvmeof_info);
+              return NULL;
+            }
+
+          sysfs_path = of_find_fc_host (nvmeof_info->host_wwpn);
+          if (!sysfs_path)
+            {
+              free (nvmeof_info);
+              return NULL;
+            }
+
+          chars_written = snprintf (disk,sizeof(disk), "/nvme-of/controller@%s,%x:nqn=%s",
+                                    nvmeof_info->target_wwpn, 0xffff,
+                                    nvmeof_info->nqn);
+          unsigned int nsid = of_path_get_nvme_nsid (device);
+          if (nsid)
+            {
+              snprintf (disk+chars_written,sizeof("/namespace@") + sizeof(char) * MAX_NVME_NSID_DIGITS,
+                        "/namespace@%x", nsid);
+            }
+          free (nvmeof_info);
+        }
+      else
+        {
+          snprintf (disk, sizeof (disk), "/disk@1");
+        }
     }
 
   of_path = find_obppath (sysfs_path);
@@ -429,7 +785,6 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
   free (sysfs_path);
   return of_path;
 }
-#endif
 
 static int
 vendor_is_ATA(const char *path)
@@ -779,11 +1134,9 @@ grub_util_devname_to_ofpath (const char *sys_devname)
     /* All the models I've seen have a devalias "floppy".
        New models have no floppy at all. */
     ofpath = xstrdup ("floppy");
-#ifdef __sparc__
   else if (device[0] == 'n' && device[1] == 'v' && device[2] == 'm'
            && device[3] == 'e')
     ofpath = of_path_of_nvme (name_buf, device, devnode, devicenode);
-#endif
   else
     {
       grub_util_warn (_("unknown device type %s"), device);
diff --git a/include/grub/util/ofpath.h b/include/grub/util/ofpath.h
index b43c523..85172bc 100644
--- a/include/grub/util/ofpath.h
+++ b/include/grub/util/ofpath.h
@@ -3,4 +3,32 @@
 
 char *grub_util_devname_to_ofpath (const char *devname);
 
+struct ofpath_files_list_node
+{
+  char* filename;
+  struct ofpath_files_list_node* next;
+};
+
+struct ofpath_files_list_root
+{
+  int items;
+  struct ofpath_files_list_node* first;
+};
+
+struct ofpath_nvmeof_info
+{
+  char* host_wwpn;
+  char* target_wwpn;
+  char* nqn;
+  int cntlid;
+  int nsid;
+};
+
+int of_path_get_nvmeof_adapter_info (char* sysfs_path, struct ofpath_nvmeof_info* nvmeof_info);
+unsigned int of_path_get_nvme_nsid (const char* devname);
+int add_filename_to_pile (char *filename, struct ofpath_files_list_root* root);
+void find_file (char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth);
+char* of_find_fc_host (char* host_wwpn);
+void free_ofpath_files_list (struct ofpath_files_list_root* root);
+
 #endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */
-- 
2.31.1

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v4 5/5] ieee1275: ofpath enable NVMeoF logical device translate
  2024-08-30 11:41 ` [PATCH v4 5/5] ieee1275: ofpath enable NVMeoF logical device translate Avnish Chouhan
@ 2025-02-12  8:14   ` Michael Chang via Grub-devel
  2025-02-13  6:32     ` Avnish Chouhan
  0 siblings, 1 reply; 8+ messages in thread
From: Michael Chang via Grub-devel @ 2025-02-12  8:14 UTC (permalink / raw)
  To: Avnish Chouhan
  Cc: Michael Chang, grub-devel, daniel.kiper, brking, meghanaprakash,
	phcoder, Diego Domingos

Hi Avnish,

This patch doesn't build:

  ../grub-core/osdep/linux/ofpath.c: In function ‘of_path_of_nvme’:
  ../grub-core/osdep/linux/ofpath.c:729:37: error: ‘%x’ directive output may be truncated writing between 1 and 8 bytes into a region of size 7 [-Werror=format-truncation=]
    729 |                         "/namespace@%x:%d", nsid, part);
	|                                     ^~
  ../grub-core/osdep/linux/ofpath.c:729:25: note: directive argument in the range [1, 4294967295]
    729 |                         "/namespace@%x:%d", nsid, part);
	|                         ^~~~~~~~~~~~~~~~~~
  ../grub-core/osdep/linux/ofpath.c:728:15: note: ‘snprintf’ output between 15 and 32 bytes into a destination of size 18
    728 |               snprintf (disk+chars_written, sizeof("/namespace@") + MAX_NVME_NSID_DIGITS,
	|               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    729 |                         "/namespace@%x:%d", nsid, part);
	|                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ../grub-core/osdep/linux/ofpath.c:770:37: error: ‘%x’ directive output may be truncated writing between 1 and 8 bytes into a region of size 7 [-Werror=format-truncation=]
    770 |                         "/namespace@%x", nsid);
	|                                     ^~
  ../grub-core/osdep/linux/ofpath.c:770:25: note: directive argument in the range [1, 4294967295]
    770 |                         "/namespace@%x", nsid);
	|                         ^~~~~~~~~~~~~~~
  ../grub-core/osdep/linux/ofpath.c:769:15: note: ‘snprintf’ output between 13 and 20 bytes into a destination of size 18
    769 |               snprintf (disk+chars_written,sizeof("/namespace@") + sizeof(char) * MAX_NVME_NSID_DIGITS,
	|               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    770 |                         "/namespace@%x", nsid);
	|                         ~~~~~~~~~~~~~~~~~~~~~~
  cc1: all warnings being treated as errors

The error is valid. It is pointing to that the size,
MAX_NVME_NSID_DIGITS, provided for snprintf() is too small to the worse
case of format specifier output, thus the result truncated.

The `gcc --version`:
  gcc (SUSE Linux) 14.2.1 20241007 [revision 4af44f2cf7d281f3e4f3957efce10e8b2ccb2ad3]

Moreover, it has a few critical memory related issue that may crash the
program. (See below)

On Fri, Aug 30, 2024 at 05:11:04PM +0530, Avnish Chouhan wrote:
> This patch adds code to enable the translation of logical devices to the of NVMeoFC paths.
> 
> Signed-off-by: Diego Domingos <diegodo@br.ibm.com>
> Signed-off-by: Avnish Chouhan <avnish@linux.ibm.com>
> ---
>  grub-core/osdep/linux/ofpath.c | 371 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  include/grub/util/ofpath.h     | 28 ++++++++++++++++++++++++++++
>  2 files changed, 390 insertions(+), 9 deletions(-)
> 
> diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
> index 0f5d54e..f0e7dcc 100644
> --- a/grub-core/osdep/linux/ofpath.c
> +++ b/grub-core/osdep/linux/ofpath.c
> @@ -37,6 +37,7 @@
>  #include <fcntl.h>
>  #include <errno.h>
>  #include <ctype.h>
> +#include <dirent.h>
>  
>  #ifdef __sparc__
>  typedef enum
> @@ -136,7 +137,7 @@ trim_newline (char *path)
>      *end-- = '\0';
>  }
>  
> -#define MAX_DISK_CAT    64
> +#define MAX_DISK_CAT    512
>  
>  static char *
>  find_obppath (const char *sysfs_path_orig)
> @@ -312,6 +313,91 @@ get_basename(char *p)
>    return ret;
>  }
>  
> +int
> +add_filename_to_pile (char *filename, struct ofpath_files_list_root* root)
> +{
> +  struct ofpath_files_list_node* file;
> +
> +  file = malloc (sizeof (struct ofpath_files_list_node));
> +  if (!file)
> +    return -1;
> +
> +  file->filename = malloc (sizeof (char) * 1024);
> +  if (!file->filename)
> +    {
> +      free (file);
> +      return -1;
> +    }
> +
> +  grub_strcpy (file->filename, filename);
> +  if (root->first == NULL)
> +    {
> +      root->items = 1;
> +      root->first = file;
> +      file->next = NULL;
> +    }
> +  else
> +    {
> +      root->items++;
> +      file->next = root->first;
> +      root->first = file;
> +    }
> +
> +  return 0;
> +}
> +
> +void
> +find_file (char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth)
> +{
> +  struct dirent *ep;
> +  struct stat statbuf;
> +  DIR *dp;
> +  int ret_val=0;
> +  char* full_path;
> +
> +  if (depth > max_depth)
> +    {
> +      return;
> +    }
> +
> +  if ((dp = opendir (directory)) == NULL)
> +    {
> +      return;
> +    }
> +
> +  full_path = malloc (1024 * sizeof (char));
> +  if (!full_path)
> +    return;
> +
> +  while ((ep = readdir(dp)) != NULL)
> +    {
> +      snprintf (full_path, 1024, "%s/%s", directory, ep->d_name);
> +      lstat (full_path, &statbuf);
> +
> +      if (S_ISLNK (statbuf.st_mode))
> +        {
> +          continue;
> +        }
> +
> +      if (!strcmp (ep->d_name, ".") || !strcmp(ep->d_name, ".."))
> +        {
> +          continue;
> +        }
> +
> +      if (!strcmp (ep->d_name, filename))
> +        {
> +          ret_val = add_filename_to_pile (full_path, root);
> +          if (ret_val == -1)
> +            continue;
> +        }
> +
> +      find_file (filename, full_path, root, max_depth, depth+1);
> +    }
> +
> +  free (full_path);
> +  closedir (dp);
> +}
> +
>  static char *
>  of_path_of_vdisk(const char *sys_devname __attribute__((unused)),
>  		 const char *device,
> @@ -382,7 +468,200 @@ of_fc_port_name (const char *path, const char *subpath, char *port_name)
>    free (basepath);
>  }
>  
> -#ifdef __sparc__
> +void
> +free_ofpath_files_list (struct ofpath_files_list_root* root)
> +{
> +  struct ofpath_files_list_node* node = root->first;
> +  struct ofpath_files_list_node* next;
> +
> +  while (node!=NULL)
> +    {
> +      next = node->next;
> +      free (node->filename);
> +      free (node);
> +      node = next;
> +    }
> +
> +  free (root);
> +  return;
> +}
> +
> +char*
> +of_find_fc_host (char* host_wwpn)
> +{
> +  FILE* fp;
> +  char *buf;
> +  char *ret_val;
> +  char portname_filename[sizeof ("port_name")] = "port_name";
> +  char devices_path[sizeof ("/sys/devices")] = "/sys/devices";
> +  struct ofpath_files_list_root* portnames_file_list;
> +  struct ofpath_files_list_node* node;
> +
> +  ret_val = malloc (sizeof (char) * 1024);
> +  if (!ret_val)
> +    return NULL;
> +
> +  portnames_file_list = malloc (sizeof (struct ofpath_files_list_root));
> +  if (!portnames_file_list)
> +    {
> +      free (ret_val);
> +      return NULL;
> +    }
> +
> +  portnames_file_list->items = 0;
> +  portnames_file_list->first = NULL;
> +  find_file (portname_filename, devices_path, portnames_file_list, 10, 0);
> +  node = portnames_file_list->first;
> +
> +  while (node != NULL)
> +    {
> +      fp = fopen(node->filename, "r");
> +      buf = malloc (sizeof (char) * 512);
> +      if (!buf)
> +        break;
> +
> +      fscanf (fp, "%s", buf);
> +      fclose (fp);
> +
> +      if ((strcmp (buf, host_wwpn) == 0) && grub_strstr (node->filename, "fc_host"))
> +        {
> +          free (buf);
> +          grub_strcpy (ret_val, node->filename);
> +          free_ofpath_files_list (portnames_file_list);
> +          return ret_val;
> +        }
> +
> +      node = node->next;
> +      free (buf);
> +    }
> +  free_ofpath_files_list (portnames_file_list);
> +  free (ret_val);
> +  return NULL;
> +}
> +
> +int
> +of_path_get_nvmeof_adapter_info (char* sysfs_path,
> +                                 struct ofpath_nvmeof_info* nvmeof_info)
> +{
> +  FILE *fp;
> +  char *buf, *buf2, *buf3;
> +
> +  nvmeof_info->host_wwpn = malloc (sizeof (char) * 256);
> +  nvmeof_info->target_wwpn = malloc (sizeof (char) * 256);
> +  nvmeof_info->nqn = malloc (sizeof (char) * 256);
> +
> +  if (nvmeof_info->host_wwpn == NULL || nvmeof_info->target_wwpn == NULL || nvmeof_info->nqn == NULL)
> +    {
> +      free (nvmeof_info->host_wwpn);
> +      free (nvmeof_info->target_wwpn);
> +      free (nvmeof_info->nqn);
> +      return -1;
> +    }
> +
> +  buf = malloc (sizeof (char) * 512);
> +  if (!buf)
> +    {
> +      free (nvmeof_info->host_wwpn);
> +      free (nvmeof_info->target_wwpn);
> +      free (nvmeof_info->nqn);
> +      return -1;
> +    }
> +
> +  snprintf (buf, 512, "%s/subsysnqn", sysfs_path);
> +  fp = fopen (buf, "r");

The fp == NULL check is missing.

> +  fscanf (fp, "%s", nvmeof_info->nqn);

The return value of fscanf() should be checked to verify that the nqn
read from the file is successful.

> +  fclose (fp);
> +
> +  snprintf (buf, 512, "%s/cntlid", sysfs_path);
> +  fp = fopen (buf, "r");

Ditto.

> +  fscanf (fp, "%u", &(nvmeof_info->cntlid));

Ditto.

> +  fclose (fp);
> +
> +  snprintf (buf, 512, "%s/address", sysfs_path);
> +  fp = fopen (buf, "r");

Ditto.

> +  buf2 = malloc (sizeof (char) * 512);
> +
> +  if (!buf2)
> +    {
> +      free (nvmeof_info->host_wwpn);
> +      free (nvmeof_info->target_wwpn);
> +      free (nvmeof_info->nqn);
> +      free (buf);
> +      return -1;
> +    }
> +
> +  fscanf (fp, "%s", buf2);

Ditto.

> +  fclose (fp);
> +
> +  buf3 = strrchr (buf2, '-') + 1;

Missing check for strrchr() != NULL so that buf3 may be assigned invalid
address "1". This is very likely to happen given no check for buf2 read
from file is successful.

> +  grub_memcpy (nvmeof_info->host_wwpn, buf3, 256);

The strrchr()/strchr() may return NULL if the characters being searched
is not present. As a consequence this will cause segvfault by reading
illegal address "1".

> +  buf3=strchr (buf2, '-') + 1;
> +  buf3=strchr (buf3, '-') + 1;
> +  buf3=strchr (buf3, 'x') + 1;
> +  grub_memcpy (nvmeof_info->target_wwpn, buf3, 256);

Ditto.

> +  buf3 = strchr (nvmeof_info->target_wwpn, ',');
> +  *buf3 = '\0';

The buf3 != NULL check is missing before dereference.

> +  free (buf);
> +  free (buf2);
> +  return 0;
> +}
> +
> +#define MAX_NVME_NSID_DIGITS 6
> +
> +static char *
> +of_path_get_nvme_controller_name_node (const char* devname)
> +{
> +  char *controller_node, *end;
> +
> +  controller_node = strdup (devname);
> +  end = grub_strchr (controller_node + 1, 'n');
> +  if (end != NULL)
> +    {
> +      *end = '\0';
> +    }
> +
> +  return controller_node;
> +}
> +
> +unsigned int
> +of_path_get_nvme_nsid (const char* devname)
> +{
> +  unsigned int nsid;
> +  char *sysfs_path, *buf;
> +  FILE *fp;
> +
> +  buf = malloc (sizeof(char) * 512);
> +  if (!buf)
> +    return 0;
> +
> +  sysfs_path = block_device_get_sysfs_path_and_link (devname);
> +  snprintf (buf, 512, "%s/%s/nsid", sysfs_path, devname);
> +  fp = fopen(buf, "r");
> +  fscanf (fp, "%u", &(nsid));
> +  fclose (fp);

Ditto

> +
> +  free (sysfs_path);
> +  free (buf);
> +  return nsid;
> +}
> +
> +static char *
> +nvme_get_syspath (const char *nvmedev)
> +{
> +  char *sysfs_path, *controller_node;
> +
> +  sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
> +  if (strstr (sysfs_path, "nvme-subsystem"))
> +    {
> +      controller_node = of_path_get_nvme_controller_name_node (nvmedev);
> +      strcat (sysfs_path, "/");
> +      strcat (sysfs_path, controller_node);

The strcat() would lead to out-of-bounds writes as the destination
buffer, sysfs_path, didn't have more space to cancat any new string.

Thanks,
Michael

> +      sysfs_path = xrealpath (sysfs_path);
> +    }
> +
> +  return sysfs_path;
> +}
> +
>  static char *
>  of_path_of_nvme(const char *sys_devname __attribute__((unused)),
>  	        const char *device,
> @@ -391,6 +670,8 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
>  {
>    char *sysfs_path, *of_path, disk[MAX_DISK_CAT];
>    const char *digit_string, *part_end;
> +  int chars_written, ret_val;
> +  struct ofpath_nvmeof_info* nvmeof_info;
>  
>    digit_string = trailing_digits (device);
>    part_end = devicenode + strlen (devicenode) - 1;
> @@ -410,15 +691,90 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
>        /* Remove the p. */
>        *end = '\0';
>        sscanf (digit_string, "%d", &part);
> -      snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
> -      sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
> +      sysfs_path = nvme_get_syspath (nvmedev);
> +
> +      /* If is a NVMeoF */
> +      if (strstr (sysfs_path, "nvme-fabrics"))
> +        {
> +          nvmeof_info = malloc (sizeof (struct ofpath_nvmeof_info));
> +          if (!nvmeof_info)
> +            {
> +              free (nvmedev);
> +              return NULL;
> +            }
> +
> +          ret_val = of_path_get_nvmeof_adapter_info (sysfs_path, nvmeof_info);
> +          if (ret_val == -1)
> +            {
> +              free (nvmedev);
> +              free (nvmeof_info);
> +              return NULL;
> +            }
> +
> +          sysfs_path = of_find_fc_host (nvmeof_info->host_wwpn);
> +          if (!sysfs_path)
> +            {
> +              free (nvmedev);
> +              free (nvmeof_info);
> +              return NULL;
> +            }
> +
> +          chars_written = snprintf (disk,sizeof(disk), "/nvme-of/controller@%s,%x:nqn=%s",
> +                                    nvmeof_info->target_wwpn,0xffff,
> +                                    nvmeof_info->nqn);
> +          unsigned int nsid = of_path_get_nvme_nsid (nvmedev);
> +          if (nsid)
> +            {
> +              snprintf (disk+chars_written, sizeof("/namespace@") + MAX_NVME_NSID_DIGITS,
> +                        "/namespace@%x:%d", nsid, part);
> +            }
> +          free (nvmeof_info);
> +        }
> +      else
> +        {
> +          snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
> +        }
>        free (nvmedev);
>      }
>    else
>      {
>        /* We do not have the parition. */
> -      snprintf (disk, sizeof (disk), "/disk@1");
> -      sysfs_path = block_device_get_sysfs_path_and_link (device);
> +      sysfs_path = nvme_get_syspath (device);
> +      if (strstr (sysfs_path, "nvme-fabrics"))
> +        {
> +          nvmeof_info = malloc (sizeof (struct ofpath_nvmeof_info));
> +          if (!nvmeof_info)
> +            return NULL;
> +
> +          ret_val = of_path_get_nvmeof_adapter_info (sysfs_path, nvmeof_info);
> +          if (ret_val == -1)
> +            {
> +              free (nvmeof_info);
> +              return NULL;
> +            }
> +
> +          sysfs_path = of_find_fc_host (nvmeof_info->host_wwpn);
> +          if (!sysfs_path)
> +            {
> +              free (nvmeof_info);
> +              return NULL;
> +            }
> +
> +          chars_written = snprintf (disk,sizeof(disk), "/nvme-of/controller@%s,%x:nqn=%s",
> +                                    nvmeof_info->target_wwpn, 0xffff,
> +                                    nvmeof_info->nqn);
> +          unsigned int nsid = of_path_get_nvme_nsid (device);
> +          if (nsid)
> +            {
> +              snprintf (disk+chars_written,sizeof("/namespace@") + sizeof(char) * MAX_NVME_NSID_DIGITS,
> +                        "/namespace@%x", nsid);
> +            }
> +          free (nvmeof_info);
> +        }
> +      else
> +        {
> +          snprintf (disk, sizeof (disk), "/disk@1");
> +        }
>      }
>  
>    of_path = find_obppath (sysfs_path);
> @@ -429,7 +785,6 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
>    free (sysfs_path);
>    return of_path;
>  }
> -#endif
>  
>  static int
>  vendor_is_ATA(const char *path)
> @@ -779,11 +1134,9 @@ grub_util_devname_to_ofpath (const char *sys_devname)
>      /* All the models I've seen have a devalias "floppy".
>         New models have no floppy at all. */
>      ofpath = xstrdup ("floppy");
> -#ifdef __sparc__
>    else if (device[0] == 'n' && device[1] == 'v' && device[2] == 'm'
>             && device[3] == 'e')
>      ofpath = of_path_of_nvme (name_buf, device, devnode, devicenode);
> -#endif
>    else
>      {
>        grub_util_warn (_("unknown device type %s"), device);
> diff --git a/include/grub/util/ofpath.h b/include/grub/util/ofpath.h
> index b43c523..85172bc 100644
> --- a/include/grub/util/ofpath.h
> +++ b/include/grub/util/ofpath.h
> @@ -3,4 +3,32 @@
>  
>  char *grub_util_devname_to_ofpath (const char *devname);
>  
> +struct ofpath_files_list_node
> +{
> +  char* filename;
> +  struct ofpath_files_list_node* next;
> +};
> +
> +struct ofpath_files_list_root
> +{
> +  int items;
> +  struct ofpath_files_list_node* first;
> +};
> +
> +struct ofpath_nvmeof_info
> +{
> +  char* host_wwpn;
> +  char* target_wwpn;
> +  char* nqn;
> +  int cntlid;
> +  int nsid;
> +};
> +
> +int of_path_get_nvmeof_adapter_info (char* sysfs_path, struct ofpath_nvmeof_info* nvmeof_info);
> +unsigned int of_path_get_nvme_nsid (const char* devname);
> +int add_filename_to_pile (char *filename, struct ofpath_files_list_root* root);
> +void find_file (char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth);
> +char* of_find_fc_host (char* host_wwpn);
> +void free_ofpath_files_list (struct ofpath_files_list_root* root);
> +
>  #endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */
> -- 
> 2.31.1

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v4 5/5] ieee1275: ofpath enable NVMeoF logical device translate
  2025-02-12  8:14   ` Michael Chang via Grub-devel
@ 2025-02-13  6:32     ` Avnish Chouhan
  0 siblings, 0 replies; 8+ messages in thread
From: Avnish Chouhan @ 2025-02-13  6:32 UTC (permalink / raw)
  To: mchang
  Cc: grub-devel, daniel.kiper, brking, meghanaprakash, phcoder,
	Diego Domingos

Hi Michael,
Thank you so much for a review!

I'll add the failure checks in the code mentioned by you.

On build issue. I haven't observed any of these errors on my machine. 
Today, I built the latest upstream grub with this patch on my machine 
and no errors are observed.

Regards,
Avnish Chouhan

On 2025-02-12 13:44, Michael Chang wrote:
> Hi Avnish,
> 
> This patch doesn't build:
> 
>   ../grub-core/osdep/linux/ofpath.c: In function ‘of_path_of_nvme’:
>   ../grub-core/osdep/linux/ofpath.c:729:37: error: ‘%x’ directive
> output may be truncated writing between 1 and 8 bytes into a region of
> size 7 [-Werror=format-truncation=]
>     729 |                         "/namespace@%x:%d", nsid, part);
> 	|                                     ^~
>   ../grub-core/osdep/linux/ofpath.c:729:25: note: directive argument
> in the range [1, 4294967295]
>     729 |                         "/namespace@%x:%d", nsid, part);
> 	|                         ^~~~~~~~~~~~~~~~~~
>   ../grub-core/osdep/linux/ofpath.c:728:15: note: ‘snprintf’ output
> between 15 and 32 bytes into a destination of size 18
>     728 |               snprintf (disk+chars_written,
> sizeof("/namespace@") + MAX_NVME_NSID_DIGITS,
> 	|
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     729 |                         "/namespace@%x:%d", nsid, part);
> 	|                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>   ../grub-core/osdep/linux/ofpath.c:770:37: error: ‘%x’ directive
> output may be truncated writing between 1 and 8 bytes into a region of
> size 7 [-Werror=format-truncation=]
>     770 |                         "/namespace@%x", nsid);
> 	|                                     ^~
>   ../grub-core/osdep/linux/ofpath.c:770:25: note: directive argument
> in the range [1, 4294967295]
>     770 |                         "/namespace@%x", nsid);
> 	|                         ^~~~~~~~~~~~~~~
>   ../grub-core/osdep/linux/ofpath.c:769:15: note: ‘snprintf’ output
> between 13 and 20 bytes into a destination of size 18
>     769 |               snprintf
> (disk+chars_written,sizeof("/namespace@") + sizeof(char) *
> MAX_NVME_NSID_DIGITS,
> 	|
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     770 |                         "/namespace@%x", nsid);
> 	|                         ~~~~~~~~~~~~~~~~~~~~~~
>   cc1: all warnings being treated as errors
> 
> The error is valid. It is pointing to that the size,
> MAX_NVME_NSID_DIGITS, provided for snprintf() is too small to the worse
> case of format specifier output, thus the result truncated.
> 
> The `gcc --version`:
>   gcc (SUSE Linux) 14.2.1 20241007 [revision
> 4af44f2cf7d281f3e4f3957efce10e8b2ccb2ad3]
> 
> Moreover, it has a few critical memory related issue that may crash the
> program. (See below)
> 
> On Fri, Aug 30, 2024 at 05:11:04PM +0530, Avnish Chouhan wrote:
>> This patch adds code to enable the translation of logical devices to 
>> the of NVMeoFC paths.
>> 
>> Signed-off-by: Diego Domingos <diegodo@br.ibm.com>
>> Signed-off-by: Avnish Chouhan <avnish@linux.ibm.com>
>> ---
>>  grub-core/osdep/linux/ofpath.c | 371 
>> +++++++++++++++++++++++++++++++++++++++++++++++++++++--
>>  include/grub/util/ofpath.h     | 28 ++++++++++++++++++++++++++++
>>  2 files changed, 390 insertions(+), 9 deletions(-)
>> 
>> diff --git a/grub-core/osdep/linux/ofpath.c 
>> b/grub-core/osdep/linux/ofpath.c
>> index 0f5d54e..f0e7dcc 100644
>> --- a/grub-core/osdep/linux/ofpath.c
>> +++ b/grub-core/osdep/linux/ofpath.c
>> @@ -37,6 +37,7 @@
>>  #include <fcntl.h>
>>  #include <errno.h>
>>  #include <ctype.h>
>> +#include <dirent.h>
>> 
>>  #ifdef __sparc__
>>  typedef enum
>> @@ -136,7 +137,7 @@ trim_newline (char *path)
>>      *end-- = '\0';
>>  }
>> 
>> -#define MAX_DISK_CAT    64
>> +#define MAX_DISK_CAT    512
>> 
>>  static char *
>>  find_obppath (const char *sysfs_path_orig)
>> @@ -312,6 +313,91 @@ get_basename(char *p)
>>    return ret;
>>  }
>> 
>> +int
>> +add_filename_to_pile (char *filename, struct ofpath_files_list_root* 
>> root)
>> +{
>> +  struct ofpath_files_list_node* file;
>> +
>> +  file = malloc (sizeof (struct ofpath_files_list_node));
>> +  if (!file)
>> +    return -1;
>> +
>> +  file->filename = malloc (sizeof (char) * 1024);
>> +  if (!file->filename)
>> +    {
>> +      free (file);
>> +      return -1;
>> +    }
>> +
>> +  grub_strcpy (file->filename, filename);
>> +  if (root->first == NULL)
>> +    {
>> +      root->items = 1;
>> +      root->first = file;
>> +      file->next = NULL;
>> +    }
>> +  else
>> +    {
>> +      root->items++;
>> +      file->next = root->first;
>> +      root->first = file;
>> +    }
>> +
>> +  return 0;
>> +}
>> +
>> +void
>> +find_file (char* filename, char* directory, struct 
>> ofpath_files_list_root* root, int max_depth, int depth)
>> +{
>> +  struct dirent *ep;
>> +  struct stat statbuf;
>> +  DIR *dp;
>> +  int ret_val=0;
>> +  char* full_path;
>> +
>> +  if (depth > max_depth)
>> +    {
>> +      return;
>> +    }
>> +
>> +  if ((dp = opendir (directory)) == NULL)
>> +    {
>> +      return;
>> +    }
>> +
>> +  full_path = malloc (1024 * sizeof (char));
>> +  if (!full_path)
>> +    return;
>> +
>> +  while ((ep = readdir(dp)) != NULL)
>> +    {
>> +      snprintf (full_path, 1024, "%s/%s", directory, ep->d_name);
>> +      lstat (full_path, &statbuf);
>> +
>> +      if (S_ISLNK (statbuf.st_mode))
>> +        {
>> +          continue;
>> +        }
>> +
>> +      if (!strcmp (ep->d_name, ".") || !strcmp(ep->d_name, ".."))
>> +        {
>> +          continue;
>> +        }
>> +
>> +      if (!strcmp (ep->d_name, filename))
>> +        {
>> +          ret_val = add_filename_to_pile (full_path, root);
>> +          if (ret_val == -1)
>> +            continue;
>> +        }
>> +
>> +      find_file (filename, full_path, root, max_depth, depth+1);
>> +    }
>> +
>> +  free (full_path);
>> +  closedir (dp);
>> +}
>> +
>>  static char *
>>  of_path_of_vdisk(const char *sys_devname __attribute__((unused)),
>>  		 const char *device,
>> @@ -382,7 +468,200 @@ of_fc_port_name (const char *path, const char 
>> *subpath, char *port_name)
>>    free (basepath);
>>  }
>> 
>> -#ifdef __sparc__
>> +void
>> +free_ofpath_files_list (struct ofpath_files_list_root* root)
>> +{
>> +  struct ofpath_files_list_node* node = root->first;
>> +  struct ofpath_files_list_node* next;
>> +
>> +  while (node!=NULL)
>> +    {
>> +      next = node->next;
>> +      free (node->filename);
>> +      free (node);
>> +      node = next;
>> +    }
>> +
>> +  free (root);
>> +  return;
>> +}
>> +
>> +char*
>> +of_find_fc_host (char* host_wwpn)
>> +{
>> +  FILE* fp;
>> +  char *buf;
>> +  char *ret_val;
>> +  char portname_filename[sizeof ("port_name")] = "port_name";
>> +  char devices_path[sizeof ("/sys/devices")] = "/sys/devices";
>> +  struct ofpath_files_list_root* portnames_file_list;
>> +  struct ofpath_files_list_node* node;
>> +
>> +  ret_val = malloc (sizeof (char) * 1024);
>> +  if (!ret_val)
>> +    return NULL;
>> +
>> +  portnames_file_list = malloc (sizeof (struct 
>> ofpath_files_list_root));
>> +  if (!portnames_file_list)
>> +    {
>> +      free (ret_val);
>> +      return NULL;
>> +    }
>> +
>> +  portnames_file_list->items = 0;
>> +  portnames_file_list->first = NULL;
>> +  find_file (portname_filename, devices_path, portnames_file_list, 
>> 10, 0);
>> +  node = portnames_file_list->first;
>> +
>> +  while (node != NULL)
>> +    {
>> +      fp = fopen(node->filename, "r");
>> +      buf = malloc (sizeof (char) * 512);
>> +      if (!buf)
>> +        break;
>> +
>> +      fscanf (fp, "%s", buf);
>> +      fclose (fp);
>> +
>> +      if ((strcmp (buf, host_wwpn) == 0) && grub_strstr 
>> (node->filename, "fc_host"))
>> +        {
>> +          free (buf);
>> +          grub_strcpy (ret_val, node->filename);
>> +          free_ofpath_files_list (portnames_file_list);
>> +          return ret_val;
>> +        }
>> +
>> +      node = node->next;
>> +      free (buf);
>> +    }
>> +  free_ofpath_files_list (portnames_file_list);
>> +  free (ret_val);
>> +  return NULL;
>> +}
>> +
>> +int
>> +of_path_get_nvmeof_adapter_info (char* sysfs_path,
>> +                                 struct ofpath_nvmeof_info* 
>> nvmeof_info)
>> +{
>> +  FILE *fp;
>> +  char *buf, *buf2, *buf3;
>> +
>> +  nvmeof_info->host_wwpn = malloc (sizeof (char) * 256);
>> +  nvmeof_info->target_wwpn = malloc (sizeof (char) * 256);
>> +  nvmeof_info->nqn = malloc (sizeof (char) * 256);
>> +
>> +  if (nvmeof_info->host_wwpn == NULL || nvmeof_info->target_wwpn == 
>> NULL || nvmeof_info->nqn == NULL)
>> +    {
>> +      free (nvmeof_info->host_wwpn);
>> +      free (nvmeof_info->target_wwpn);
>> +      free (nvmeof_info->nqn);
>> +      return -1;
>> +    }
>> +
>> +  buf = malloc (sizeof (char) * 512);
>> +  if (!buf)
>> +    {
>> +      free (nvmeof_info->host_wwpn);
>> +      free (nvmeof_info->target_wwpn);
>> +      free (nvmeof_info->nqn);
>> +      return -1;
>> +    }
>> +
>> +  snprintf (buf, 512, "%s/subsysnqn", sysfs_path);
>> +  fp = fopen (buf, "r");
> 
> The fp == NULL check is missing.
> 
>> +  fscanf (fp, "%s", nvmeof_info->nqn);
> 
> The return value of fscanf() should be checked to verify that the nqn
> read from the file is successful.
> 
>> +  fclose (fp);
>> +
>> +  snprintf (buf, 512, "%s/cntlid", sysfs_path);
>> +  fp = fopen (buf, "r");
> 
> Ditto.
> 
>> +  fscanf (fp, "%u", &(nvmeof_info->cntlid));
> 
> Ditto.
> 
>> +  fclose (fp);
>> +
>> +  snprintf (buf, 512, "%s/address", sysfs_path);
>> +  fp = fopen (buf, "r");
> 
> Ditto.
> 
>> +  buf2 = malloc (sizeof (char) * 512);
>> +
>> +  if (!buf2)
>> +    {
>> +      free (nvmeof_info->host_wwpn);
>> +      free (nvmeof_info->target_wwpn);
>> +      free (nvmeof_info->nqn);
>> +      free (buf);
>> +      return -1;
>> +    }
>> +
>> +  fscanf (fp, "%s", buf2);
> 
> Ditto.
> 
>> +  fclose (fp);
>> +
>> +  buf3 = strrchr (buf2, '-') + 1;
> 
> Missing check for strrchr() != NULL so that buf3 may be assigned 
> invalid
> address "1". This is very likely to happen given no check for buf2 read
> from file is successful.
> 
>> +  grub_memcpy (nvmeof_info->host_wwpn, buf3, 256);
> 
> The strrchr()/strchr() may return NULL if the characters being searched
> is not present. As a consequence this will cause segvfault by reading
> illegal address "1".
> 
>> +  buf3=strchr (buf2, '-') + 1;
>> +  buf3=strchr (buf3, '-') + 1;
>> +  buf3=strchr (buf3, 'x') + 1;
>> +  grub_memcpy (nvmeof_info->target_wwpn, buf3, 256);
> 
> Ditto.
> 
>> +  buf3 = strchr (nvmeof_info->target_wwpn, ',');
>> +  *buf3 = '\0';
> 
> The buf3 != NULL check is missing before dereference.
> 
>> +  free (buf);
>> +  free (buf2);
>> +  return 0;
>> +}
>> +
>> +#define MAX_NVME_NSID_DIGITS 6
>> +
>> +static char *
>> +of_path_get_nvme_controller_name_node (const char* devname)
>> +{
>> +  char *controller_node, *end;
>> +
>> +  controller_node = strdup (devname);
>> +  end = grub_strchr (controller_node + 1, 'n');
>> +  if (end != NULL)
>> +    {
>> +      *end = '\0';
>> +    }
>> +
>> +  return controller_node;
>> +}
>> +
>> +unsigned int
>> +of_path_get_nvme_nsid (const char* devname)
>> +{
>> +  unsigned int nsid;
>> +  char *sysfs_path, *buf;
>> +  FILE *fp;
>> +
>> +  buf = malloc (sizeof(char) * 512);
>> +  if (!buf)
>> +    return 0;
>> +
>> +  sysfs_path = block_device_get_sysfs_path_and_link (devname);
>> +  snprintf (buf, 512, "%s/%s/nsid", sysfs_path, devname);
>> +  fp = fopen(buf, "r");
>> +  fscanf (fp, "%u", &(nsid));
>> +  fclose (fp);
> 
> Ditto
> 
>> +
>> +  free (sysfs_path);
>> +  free (buf);
>> +  return nsid;
>> +}
>> +
>> +static char *
>> +nvme_get_syspath (const char *nvmedev)
>> +{
>> +  char *sysfs_path, *controller_node;
>> +
>> +  sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
>> +  if (strstr (sysfs_path, "nvme-subsystem"))
>> +    {
>> +      controller_node = of_path_get_nvme_controller_name_node 
>> (nvmedev);
>> +      strcat (sysfs_path, "/");
>> +      strcat (sysfs_path, controller_node);
> 
> The strcat() would lead to out-of-bounds writes as the destination
> buffer, sysfs_path, didn't have more space to cancat any new string.
> 
> Thanks,
> Michael
> 
>> +      sysfs_path = xrealpath (sysfs_path);
>> +    }
>> +
>> +  return sysfs_path;
>> +}
>> +
>>  static char *
>>  of_path_of_nvme(const char *sys_devname __attribute__((unused)),
>>  	        const char *device,
>> @@ -391,6 +670,8 @@ of_path_of_nvme(const char *sys_devname 
>> __attribute__((unused)),
>>  {
>>    char *sysfs_path, *of_path, disk[MAX_DISK_CAT];
>>    const char *digit_string, *part_end;
>> +  int chars_written, ret_val;
>> +  struct ofpath_nvmeof_info* nvmeof_info;
>> 
>>    digit_string = trailing_digits (device);
>>    part_end = devicenode + strlen (devicenode) - 1;
>> @@ -410,15 +691,90 @@ of_path_of_nvme(const char *sys_devname 
>> __attribute__((unused)),
>>        /* Remove the p. */
>>        *end = '\0';
>>        sscanf (digit_string, "%d", &part);
>> -      snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
>> -      sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
>> +      sysfs_path = nvme_get_syspath (nvmedev);
>> +
>> +      /* If is a NVMeoF */
>> +      if (strstr (sysfs_path, "nvme-fabrics"))
>> +        {
>> +          nvmeof_info = malloc (sizeof (struct ofpath_nvmeof_info));
>> +          if (!nvmeof_info)
>> +            {
>> +              free (nvmedev);
>> +              return NULL;
>> +            }
>> +
>> +          ret_val = of_path_get_nvmeof_adapter_info (sysfs_path, 
>> nvmeof_info);
>> +          if (ret_val == -1)
>> +            {
>> +              free (nvmedev);
>> +              free (nvmeof_info);
>> +              return NULL;
>> +            }
>> +
>> +          sysfs_path = of_find_fc_host (nvmeof_info->host_wwpn);
>> +          if (!sysfs_path)
>> +            {
>> +              free (nvmedev);
>> +              free (nvmeof_info);
>> +              return NULL;
>> +            }
>> +
>> +          chars_written = snprintf (disk,sizeof(disk), 
>> "/nvme-of/controller@%s,%x:nqn=%s",
>> +                                    nvmeof_info->target_wwpn,0xffff,
>> +                                    nvmeof_info->nqn);
>> +          unsigned int nsid = of_path_get_nvme_nsid (nvmedev);
>> +          if (nsid)
>> +            {
>> +              snprintf (disk+chars_written, sizeof("/namespace@") + 
>> MAX_NVME_NSID_DIGITS,
>> +                        "/namespace@%x:%d", nsid, part);
>> +            }
>> +          free (nvmeof_info);
>> +        }
>> +      else
>> +        {
>> +          snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 
>> 1));
>> +        }
>>        free (nvmedev);
>>      }
>>    else
>>      {
>>        /* We do not have the parition. */
>> -      snprintf (disk, sizeof (disk), "/disk@1");
>> -      sysfs_path = block_device_get_sysfs_path_and_link (device);
>> +      sysfs_path = nvme_get_syspath (device);
>> +      if (strstr (sysfs_path, "nvme-fabrics"))
>> +        {
>> +          nvmeof_info = malloc (sizeof (struct ofpath_nvmeof_info));
>> +          if (!nvmeof_info)
>> +            return NULL;
>> +
>> +          ret_val = of_path_get_nvmeof_adapter_info (sysfs_path, 
>> nvmeof_info);
>> +          if (ret_val == -1)
>> +            {
>> +              free (nvmeof_info);
>> +              return NULL;
>> +            }
>> +
>> +          sysfs_path = of_find_fc_host (nvmeof_info->host_wwpn);
>> +          if (!sysfs_path)
>> +            {
>> +              free (nvmeof_info);
>> +              return NULL;
>> +            }
>> +
>> +          chars_written = snprintf (disk,sizeof(disk), 
>> "/nvme-of/controller@%s,%x:nqn=%s",
>> +                                    nvmeof_info->target_wwpn, 0xffff,
>> +                                    nvmeof_info->nqn);
>> +          unsigned int nsid = of_path_get_nvme_nsid (device);
>> +          if (nsid)
>> +            {
>> +              snprintf (disk+chars_written,sizeof("/namespace@") + 
>> sizeof(char) * MAX_NVME_NSID_DIGITS,
>> +                        "/namespace@%x", nsid);
>> +            }
>> +          free (nvmeof_info);
>> +        }
>> +      else
>> +        {
>> +          snprintf (disk, sizeof (disk), "/disk@1");
>> +        }
>>      }
>> 
>>    of_path = find_obppath (sysfs_path);
>> @@ -429,7 +785,6 @@ of_path_of_nvme(const char *sys_devname 
>> __attribute__((unused)),
>>    free (sysfs_path);
>>    return of_path;
>>  }
>> -#endif
>> 
>>  static int
>>  vendor_is_ATA(const char *path)
>> @@ -779,11 +1134,9 @@ grub_util_devname_to_ofpath (const char 
>> *sys_devname)
>>      /* All the models I've seen have a devalias "floppy".
>>         New models have no floppy at all. */
>>      ofpath = xstrdup ("floppy");
>> -#ifdef __sparc__
>>    else if (device[0] == 'n' && device[1] == 'v' && device[2] == 'm'
>>             && device[3] == 'e')
>>      ofpath = of_path_of_nvme (name_buf, device, devnode, devicenode);
>> -#endif
>>    else
>>      {
>>        grub_util_warn (_("unknown device type %s"), device);
>> diff --git a/include/grub/util/ofpath.h b/include/grub/util/ofpath.h
>> index b43c523..85172bc 100644
>> --- a/include/grub/util/ofpath.h
>> +++ b/include/grub/util/ofpath.h
>> @@ -3,4 +3,32 @@
>> 
>>  char *grub_util_devname_to_ofpath (const char *devname);
>> 
>> +struct ofpath_files_list_node
>> +{
>> +  char* filename;
>> +  struct ofpath_files_list_node* next;
>> +};
>> +
>> +struct ofpath_files_list_root
>> +{
>> +  int items;
>> +  struct ofpath_files_list_node* first;
>> +};
>> +
>> +struct ofpath_nvmeof_info
>> +{
>> +  char* host_wwpn;
>> +  char* target_wwpn;
>> +  char* nqn;
>> +  int cntlid;
>> +  int nsid;
>> +};
>> +
>> +int of_path_get_nvmeof_adapter_info (char* sysfs_path, struct 
>> ofpath_nvmeof_info* nvmeof_info);
>> +unsigned int of_path_get_nvme_nsid (const char* devname);
>> +int add_filename_to_pile (char *filename, struct 
>> ofpath_files_list_root* root);
>> +void find_file (char* filename, char* directory, struct 
>> ofpath_files_list_root* root, int max_depth, int depth);
>> +char* of_find_fc_host (char* host_wwpn);
>> +void free_ofpath_files_list (struct ofpath_files_list_root* root);
>> +
>>  #endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */
>> --
>> 2.31.1

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2025-02-13  6:32 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-30 11:40 [PATCH v4 0/5] NVMeoFC support on Grub Avnish Chouhan
2024-08-30 11:41 ` [PATCH v4 1/5] ieee1275/powerpc: implements fibre channel discovery for ofpathname Avnish Chouhan
2024-08-30 11:41 ` [PATCH v4 2/5] ieee1275: implement FCP methods for WWPN and LUNs Avnish Chouhan
2024-08-30 11:41 ` [PATCH v4 3/5] ieee1275: change the logic of ieee1275_get_devargs() Avnish Chouhan
2024-08-30 11:41 ` [PATCH v4 4/5] ieee1275: add support for NVMeoFC Avnish Chouhan
2024-08-30 11:41 ` [PATCH v4 5/5] ieee1275: ofpath enable NVMeoF logical device translate Avnish Chouhan
2025-02-12  8:14   ` Michael Chang via Grub-devel
2025-02-13  6:32     ` Avnish Chouhan

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.