grub-devel.gnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 0/6] NVMeoFC support on Grub
@ 2025-07-30  5:33 Avnish Chouhan
  2025-07-30  5:34 ` [PATCH v6 1/6] ieee1275/powerpc: implements fibre channel discovery for ofpathname Avnish Chouhan
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Avnish Chouhan @ 2025-07-30  5:33 UTC (permalink / raw)
  To: grub-devel; +Cc: daniel.kiper, brking, meghanaprakash, mchang, Avnish Chouhan

This patch series adds support of NVMeoFC and NVMe Multipath splitter on grub. It consists of six
patches.

Patch 1/6 (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/6(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/6(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/6(0004-ieee1275-add-support-for-NVMeoFC.patch):
This patch implements the functions to scan and discovery of NVMeoFC.

Patch 5/6(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.

Patch 6/6(0006-ieee1275-support-added-for-multiple-nvme-bootpaths.patch)
This patch sets mupltiple NVMe boot-devices for more robust boot.
Scenario where NVMe multipaths are available, all the available bootpaths (Max 5)
will be added as the boot-device.

Avnish Chouhan (5):
  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
  ieee1275: support added for multiple nvme bootpaths

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
 grub-core/osdep/unix/platform.c   
 include/grub/util/ofpath.h
 include/grub/util/install.h       
 6 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] 7+ messages in thread

* [PATCH v6 1/6] ieee1275/powerpc: implements fibre channel discovery for ofpathname
  2025-07-30  5:33 [PATCH v6 0/6] NVMeoFC support on Grub Avnish Chouhan
@ 2025-07-30  5:34 ` Avnish Chouhan
  2025-07-30  5:34 ` [PATCH v6 2/6] ieee1275: implement FCP methods for WWPN and LUNs Avnish Chouhan
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Avnish Chouhan @ 2025-07-30  5:34 UTC (permalink / raw)
  To: grub-devel
  Cc: daniel.kiper, brking, meghanaprakash, mchang, 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] 7+ messages in thread

* [PATCH v6 2/6] ieee1275: implement FCP methods for WWPN and LUNs
  2025-07-30  5:33 [PATCH v6 0/6] NVMeoFC support on Grub Avnish Chouhan
  2025-07-30  5:34 ` [PATCH v6 1/6] ieee1275/powerpc: implements fibre channel discovery for ofpathname Avnish Chouhan
@ 2025-07-30  5:34 ` Avnish Chouhan
  2025-07-30  5:34 ` [PATCH v6 3/6] ieee1275: change the logic of ieee1275_get_devargs() Avnish Chouhan
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Avnish Chouhan @ 2025-07-30  5:34 UTC (permalink / raw)
  To: grub-devel
  Cc: daniel.kiper, brking, meghanaprakash, mchang, 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] 7+ messages in thread

* [PATCH v6 3/6] ieee1275: change the logic of ieee1275_get_devargs()
  2025-07-30  5:33 [PATCH v6 0/6] NVMeoFC support on Grub Avnish Chouhan
  2025-07-30  5:34 ` [PATCH v6 1/6] ieee1275/powerpc: implements fibre channel discovery for ofpathname Avnish Chouhan
  2025-07-30  5:34 ` [PATCH v6 2/6] ieee1275: implement FCP methods for WWPN and LUNs Avnish Chouhan
@ 2025-07-30  5:34 ` Avnish Chouhan
  2025-07-30  5:34 ` [PATCH v6 4/6] ieee1275: add support for NVMeoFC Avnish Chouhan
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Avnish Chouhan @ 2025-07-30  5:34 UTC (permalink / raw)
  To: grub-devel
  Cc: daniel.kiper, brking, meghanaprakash, mchang, 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] 7+ messages in thread

* [PATCH v6 4/6] ieee1275: add support for NVMeoFC
  2025-07-30  5:33 [PATCH v6 0/6] NVMeoFC support on Grub Avnish Chouhan
                   ` (2 preceding siblings ...)
  2025-07-30  5:34 ` [PATCH v6 3/6] ieee1275: change the logic of ieee1275_get_devargs() Avnish Chouhan
@ 2025-07-30  5:34 ` Avnish Chouhan
  2025-07-30  5:34 ` [PATCH v6 5/6] ieee1275: ofpath enable NVMeoF logical device translate Avnish Chouhan
  2025-07-30  5:34 ` [PATCH v6 6/6] ieee1275: support added for multiple nvme bootpaths Avnish Chouhan
  5 siblings, 0 replies; 7+ messages in thread
From: Avnish Chouhan @ 2025-07-30  5:34 UTC (permalink / raw)
  To: grub-devel
  Cc: daniel.kiper, brking, meghanaprakash, mchang, 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 | 397 +++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 298 insertions(+), 99 deletions(-)

diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index 5be23ec..1fb9611 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -220,118 +220,317 @@ dev_iterate_real (const char *name, const char *path)
   return;
 }
 
-static void
-dev_iterate (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;
-      };
+dev_iterate_fcp_disks (const struct grub_ieee1275_devalias *alias)
+ {
+  /*
+   * 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))
-        {
-          grub_dprintf ("disk", "failed to open the disk while iterating FCP disk path=%s\n", alias->path);
-          return;
-        }
+  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-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++)
+  /* 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++)
         {
-          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)
             {
-              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);
+              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++)
+          /* 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++)
                 {
-                  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_snprintf (&bufptr[pos], 30, ",%" PRIxGRUB_UINT64_T,
+                                 grub_get_unaligned64 (*ptr_luns++));
+                  dev_iterate_real (buf, buf);
                 }
             }
         }
-      grub_ieee1275_close (ihandle);
+    }
+  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];
+    }
+  grub_ieee1275_close (ihandle);
+  grub_dprintf ("ofdisk","NVMeoF: Found %d discovery controllers\n", discovery_controllers_table.len);
+
+  /* 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 ("ofdisk", "failed to open the disk while getting nvme-controllers  path=%s\n", buf);
+          continue;
+        }
+      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);
+          continue;
+	 }
+
+      /* 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++)
+        {
+	   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);
+
+      /* 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_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)
     {
       static grub_ieee1275_ihandle_t ihandle;
-- 
2.39.3


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

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

* [PATCH v6 5/6] ieee1275: ofpath enable NVMeoF logical device translate
  2025-07-30  5:33 [PATCH v6 0/6] NVMeoFC support on Grub Avnish Chouhan
                   ` (3 preceding siblings ...)
  2025-07-30  5:34 ` [PATCH v6 4/6] ieee1275: add support for NVMeoFC Avnish Chouhan
@ 2025-07-30  5:34 ` Avnish Chouhan
  2025-07-30  5:34 ` [PATCH v6 6/6] ieee1275: support added for multiple nvme bootpaths Avnish Chouhan
  5 siblings, 0 replies; 7+ messages in thread
From: Avnish Chouhan @ 2025-07-30  5:34 UTC (permalink / raw)
  To: grub-devel
  Cc: daniel.kiper, brking, meghanaprakash, mchang, 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>
Signed-Off-by: Michael Chang <mchang@suse.com>
---
 grub-core/osdep/linux/ofpath.c | 415 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 include/grub/util/ofpath.h     | 28 ++++++++++++++++++++++++++++
 1 file changed, 434 insertions(+), 9 deletions(-)

diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 64f95a2..dd81e6b 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,244 @@ 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);
+  if (! (fp = fopen (buf, "r")) ||
+      fscanf (fp, "%s", nvmeof_info->nqn) != 1)
+    {
+      if (fp)
+	fclose (fp);
+      free (nvmeof_info->host_wwpn);
+      free (nvmeof_info->target_wwpn);
+      free (nvmeof_info->nqn);
+      free (buf);
+      return -1;
+    }
+  fclose (fp);
+
+  snprintf (buf, 512, "%s/cntlid", sysfs_path);
+  if (! (fp = fopen (buf, "r")) ||
+      fscanf (fp, "%u", &(nvmeof_info->cntlid)) != 1)
+    {
+      if (fp)
+	fclose (fp);
+      free (nvmeof_info->host_wwpn);
+      free (nvmeof_info->target_wwpn);
+      free (nvmeof_info->nqn);
+      free (buf);
+      return -1;
+    }
+  fclose (fp);
+
+  snprintf (buf, 512, "%s/address", sysfs_path);
+  buf2 = NULL;
+  fp = NULL;
+  if (! (buf2 = malloc (sizeof (char) * 512)) ||
+      ! (fp = fopen (buf, "r")) ||
+      fscanf (fp, "%s", buf2) != 1)
+   {
+      if (fp)
+	fclose (fp);
+      free (nvmeof_info->host_wwpn);
+      free (nvmeof_info->target_wwpn);
+      free (nvmeof_info->nqn);
+      free (buf);
+      free (buf2);
+      return -1;
+    }
+
+  fclose (fp);
+
+  if (! (buf3 = strrchr (buf2, '-')))
+    {
+      free (nvmeof_info->host_wwpn);
+      free (nvmeof_info->target_wwpn);
+     free (nvmeof_info->nqn);
+      free (buf);
+      free (buf2);
+      return -1;
+    }
+  grub_memcpy (nvmeof_info->host_wwpn, buf3 + 1, 256);
+  if (! (buf3 = strchr (buf2, '-'))	||
+      ! (buf3 = strchr (buf3 + 1, '-')) ||
+      ! (buf3 = strchr (buf3 + 1, 'x')))
+    {
+      free (nvmeof_info->host_wwpn);
+      free (nvmeof_info->target_wwpn);
+      free (nvmeof_info->nqn);
+      free (buf);
+      free (buf2);
+      return -1;
+    }
+  grub_memcpy (nvmeof_info->target_wwpn, buf3 + 1, 256);
+  buf3 = strchr (nvmeof_info->target_wwpn, ',');
+  if (buf3)
+    *buf3 = '\0';
+  free (buf);
+  free (buf2);
+  return 0;
+}
+
+#define OFPATH_MAX_UINT_HEX_DIGITS 8
+#define OFPATH_MAX_INT_DIGITS 10
+
+static char *
+of_path_get_nvme_controller_name_node (const char* devname)
+{
+  char *controller_node, *end;
+
+  controller_node = xstrdup (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;
+
+  sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
+  if (strstr (sysfs_path, "nvme-subsystem"))
+    {
+      char *controller_node = of_path_get_nvme_controller_name_node (nvmedev);
+      char *buf = xmalloc (strlen (sysfs_path) + strlen ("/") + strlen (controller_node) + 1);
+      strcpy (buf, sysfs_path);
+      strcat (buf, "/");
+      strcat (buf, controller_node);
+      free (sysfs_path);
+      free (controller_node);
+      sysfs_path = xrealpath (buf);
+      free (buf);
+    }
+
+  return sysfs_path;
+}
+
 static char *
 of_path_of_nvme(const char *sys_devname __attribute__((unused)),
 	        const char *device,
@@ -391,6 +714,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 +735,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@") + OFPATH_MAX_UINT_HEX_DIGITS + OFPATH_MAX_INT_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) * OFPATH_MAX_UINT_HEX_DIGITS,
+                        "/namespace@%x", nsid);
+            }
+          free (nvmeof_info);
+        }
+      else
+        {
+          snprintf (disk, sizeof (disk), "/disk@1");
+        }
     }
 
   of_path = find_obppath (sysfs_path);
@@ -429,7 +829,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 +1178,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.39.3


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

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

* [PATCH v6 6/6] ieee1275: support added for multiple nvme bootpaths
  2025-07-30  5:33 [PATCH v6 0/6] NVMeoFC support on Grub Avnish Chouhan
                   ` (4 preceding siblings ...)
  2025-07-30  5:34 ` [PATCH v6 5/6] ieee1275: ofpath enable NVMeoF logical device translate Avnish Chouhan
@ 2025-07-30  5:34 ` Avnish Chouhan
  5 siblings, 0 replies; 7+ messages in thread
From: Avnish Chouhan @ 2025-07-30  5:34 UTC (permalink / raw)
  To: grub-devel; +Cc: daniel.kiper, brking, meghanaprakash, mchang, Avnish Chouhan

This patch sets mupltiple NVMe boot-devices for more robust boot.
Scenario where NVMe multipaths are available, all the available bootpaths (Max 5)
will be added as the boot-device.

Signed-off-by: Avnish Chouhan <avnish@linux.ibm.com>
---
 grub-core/osdep/unix/platform.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 grub-core/osdep/linux/ofpath.c  |   4 ++--
 include/grub/util/install.h     |   3 +++
 include/grub/util/ofpath.h      |   4 ++++
 4 file changed, 126 insertions(+), 3 deletion(-)

diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
index de71221..4632f41 100644
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -28,6 +28,10 @@
 #include <dirent.h>
 #include <string.h>
 #include <errno.h>
+#include <grub/util/ofpath.h>
+#include <stdbool.h>
+
+#define BOOTDEV_BUFFER  1000
 
 static char *
 get_ofpathname (const char *dev)
@@ -176,6 +180,107 @@ grub_install_register_efi (grub_device_t efidir_grub_dev,
   return ret;
 }
 
+
+char *
+add_multiple_nvme_bootdevices (const char *install_device)
+{
+  char *sysfs_path, *nvme_ns, *ptr, *non_splitter_path;
+  unsigned int nsid;
+  char *multipath_boot, *ofpath, *ext_dir;
+  struct dirent *ep, *splitter_ep;
+  DIR *dp, *splitter_dp;
+  char *cntl_id, *dirR1, *dirR2, *splitter_info_path;
+  bool is_FC = false, is_splitter = false;
+
+  nvme_ns = grub_strstr (install_device, "nvme");
+  nsid = of_path_get_nvme_nsid (nvme_ns);
+  if (nsid == 0)
+    return NULL;
+
+  sysfs_path = nvme_get_syspath (nvme_ns);
+  ofpath = xasprintf ("%s", get_ofpathname (nvme_ns));
+
+  if (grub_strstr (ofpath, "fibre-channel"))
+    {
+      strcat (sysfs_path, "/device");
+      is_FC = true;
+    }
+  else
+    {
+      strcat (sysfs_path, "/subsystem");
+      is_FC = false;
+    }
+  if (is_FC == false)
+    {
+      cntl_id = grub_strstr (nvme_ns, "e");
+      dirR1 = xasprintf ("nvme%c",cntl_id[1]);
+
+      splitter_info_path = xasprintf ("/sys/block/%s/device", nvme_ns);
+      splitter_dp = opendir (splitter_info_path);
+      if (!splitter_dp)
+        return NULL;
+
+      while ((splitter_ep = readdir (splitter_dp)) != NULL)
+        {
+          if (grub_strstr (splitter_ep->d_name, "nvme"))
+	    {
+	      if (grub_strstr (splitter_ep->d_name, dirR1))
+	        continue;
+
+              ext_dir = grub_strchr (splitter_ep->d_name, 'e');
+              if (grub_strchr (ext_dir, 'n') == NULL)
+	        {
+                  dirR2 = xasprintf("%s", splitter_ep->d_name);
+	          is_splitter = true;
+	          break;
+	        }
+	    }
+        }
+      closedir (splitter_dp);
+    }
+  sysfs_path = xrealpath (sysfs_path);
+  dp = opendir (sysfs_path);
+  if (!dp)
+    return NULL;
+
+  ptr = multipath_boot = xmalloc (BOOTDEV_BUFFER);
+  if (is_splitter == false && is_FC == false)
+    {
+      non_splitter_path = xasprintf ("%s/namespace@%x:1 ", get_ofpathname (dirR1), nsid);
+      strncpy (ptr, non_splitter_path, strlen (non_splitter_path));
+      ptr += strlen (non_splitter_path);
+      free (non_splitter_path);
+    }
+  else
+    {
+      while ((ep = readdir (dp)) != NULL)
+        {
+          char *path;
+
+          if (grub_strstr (ep->d_name, "nvme") != NULL)
+            {
+              if (is_FC == false && grub_strstr (ep->d_name, dirR1) == NULL &&
+                  grub_strstr (ep->d_name, dirR2) == NULL)
+                continue;
+              path = xasprintf ("%s/namespace@%x ", get_ofpathname (ep->d_name), nsid);
+              if ((strlen (multipath_boot) + strlen (path)) > BOOTDEV_BUFFER)
+                {
+                  grub_util_warn (_("Maximum five entries are allowed in the bootlist"));
+                  free (path);
+                  break;
+                }
+              strncpy (ptr, path, strlen (path));
+              ptr += strlen (path);
+              free (path);
+            }
+        }
+    }
+  *--ptr = '\0';
+  closedir (dp);
+
+  return multipath_boot;
+}
+
 void
 grub_install_register_ieee1275 (int is_prep, const char *install_device,
 				int partno, const char *relpath)
@@ -215,8 +320,19 @@ grub_install_register_ieee1275 (int is_prep, const char *install_device,
 	}
       *ptr = '\0';
     }
+  else if (grub_strstr (install_device, "nvme"))
+    {
+      boot_device = add_multiple_nvme_bootdevices (install_device);
+    }
   else
-    boot_device = get_ofpathname (install_device);
+    {
+      boot_device = get_ofpathname (install_device);
+      if (grub_strstr (boot_device, "nvme-of"))
+        {
+          free (boot_device);
+          boot_device = add_multiple_nvme_bootdevices (install_device);
+        }
+    }
 
   if (grub_util_exec ((const char * []){ "nvsetenv", "boot-device",
 	  boot_device, NULL }))
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 7158c8c..3a778e0 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -209,7 +209,7 @@ find_obppath (const char *sysfs_path_orig)
     }
 }

-static char *
+char *
 xrealpath (const char *in)
 {
   char *out;
@@ -684,7 +684,7 @@ of_path_get_nvme_nsid (const char* devname)
   return nsid;
 }

-static char *
+char *
 nvme_get_syspath (const char *nvmedev)
 {
   char *sysfs_path;
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 51f3b13..a67e225 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -235,6 +235,9 @@ grub_install_register_efi (grub_device_t efidir_grub_dev,
 			   const char *efifile_path,
 			   const char *efi_distributor);
 
+char *
+add_multiple_nvme_bootdevices (const char *install_device);
+
 void
 grub_install_register_ieee1275 (int is_prep, const char *install_device,
 				int partno, const char *relpath);
diff --git a/include/grub/util/ofpath.h b/include/grub/util/ofpath.h
index 5962322..78e78e7 100644
--- a/include/grub/util/ofpath.h
+++ b/include/grub/util/ofpath.h
@@ -30,5 +30,9 @@ 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);
+char* nvme_get_syspath (const char *nvmedev);
+unsigned int of_path_get_nvme_nsid (const char* devname);
+char* xrealpath (const char *in);
+
 
 #endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */
-- 
2.43.0


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

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

end of thread, other threads:[~2025-07-30  5:37 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-30  5:33 [PATCH v6 0/6] NVMeoFC support on Grub Avnish Chouhan
2025-07-30  5:34 ` [PATCH v6 1/6] ieee1275/powerpc: implements fibre channel discovery for ofpathname Avnish Chouhan
2025-07-30  5:34 ` [PATCH v6 2/6] ieee1275: implement FCP methods for WWPN and LUNs Avnish Chouhan
2025-07-30  5:34 ` [PATCH v6 3/6] ieee1275: change the logic of ieee1275_get_devargs() Avnish Chouhan
2025-07-30  5:34 ` [PATCH v6 4/6] ieee1275: add support for NVMeoFC Avnish Chouhan
2025-07-30  5:34 ` [PATCH v6 5/6] ieee1275: ofpath enable NVMeoF logical device translate Avnish Chouhan
2025-07-30  5:34 ` [PATCH v6 6/6] ieee1275: support added for multiple nvme bootpaths Avnish Chouhan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).