From c125cb45a7885d7bf168a05cfa4da3e681244649 Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Tue, 15 Feb 2022 13:11:48 -0500
Subject: [PATCH 1/4] ieee1275: add support for NVMeoFC

Implements the functions to scan and discovery of NVMeoFC.
---
 grub-core/disk/ieee1275/ofdisk.c | 217 ++++++++++++++++++++++++++++++-
 1 file changed, 213 insertions(+), 4 deletions(-)

diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index 410f4b849..852bb95be 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -206,12 +206,10 @@ dev_iterate_real (const char *name, const char *path)
   return;
 }
 
+
 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;
@@ -323,6 +321,217 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
     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_* nvme_controllers_table = grub_malloc(sizeof(struct nvme_controllers_table_entry_)*256);
+    
+    grub_uint32_t nvme_controllers_table_entries;
+
+    struct nvme_controllers_table_entry_real
+    {
+      grub_uint16_t id;
+      char wwpn[256];
+      char nqn[256];
+    };
+
+    /* Allocate memory for building the NVMeoF path */
+    char *buf = grub_malloc (grub_strlen (alias->path) + 512);
+    if (!buf)
+    {
+      grub_ieee1275_close(ihandle);
+      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);
+      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_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;
+
+    unsigned int i=0;
+    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 */
+    int current_buffer_index;
+    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);
+	struct nvme_controllers_table_entry_* nvme_controllers_table_ = (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_[i].id;
+		grub_strcpy(nvme_controllers_table[i].wwpn, nvme_controllers_table_[i].wwpn);
+		grub_strcpy(nvme_controllers_table[i].nqn, nvme_controllers_table_[i].nqn);
+	}
+
+	grub_ieee1275_close(ihandle);
+
+	int nvme_controller_index;
+        int bufptr_pos2;
+        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);
+
+	   grub_uint32_t 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);
+    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.35.3

