From c125cb45a7885d7bf168a05cfa4da3e681244649 Mon Sep 17 00:00:00 2001 From: Diego Domingos 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