public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/grub2] rawhide: ieee1275/powerpc: implements fibre channel discovery for ofpathname
@ 2026-06-26 18:05 Nicolas Frayer
0 siblings, 0 replies; only message in thread
From: Nicolas Frayer @ 2026-06-26 18:05 UTC (permalink / raw)
To: git-commits
A new commit has been pushed.
Repo : rpms/grub2
Branch : rawhide
Commit : d09439013e18832d91f0e3c24c3c424577f08859
Author : Nicolas Frayer <nfrayer@redhat.com>
Date : 2026-06-26T11:38:51+02:00
Stats : +1558/-1 in 8 file(s)
URL : https://src.fedoraproject.org/rpms/grub2/c/d09439013e18832d91f0e3c24c3c424577f08859?branch=rawhide
Log:
ieee1275/powerpc: implements fibre channel discovery for ofpathname
Signed-off-by: Nicolas Frayer <nfrayer@redhat.com>
---
diff --git a/0439-ieee1275-powerpc-implements-fibre-channel-discovery-.patch b/0439-ieee1275-powerpc-implements-fibre-channel-discovery-.patch
new file mode 100644
index 0000000..5846c02
--- /dev/null
+++ b/0439-ieee1275-powerpc-implements-fibre-channel-discovery-.patch
@@ -0,0 +1,120 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Avnish Chouhan <avnish@linux.ibm.com>
+Date: Thu, 25 Jun 2026 18:23:36 +0200
+Subject: [PATCH] ieee1275/powerpc: implements fibre channel discovery for
+ ofpathname
+
+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>
+Reviewed-by: Leo Sandoval <lsandova@redhat.com>
+Reviewed-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Part-of: <https://gitlab.freedesktop.org/gnu-grub/grub/-/merge_requests/146>
+---
+ grub-core/osdep/linux/ofpath.c | 58 +++++++++++++++++++++---------------------
+ 1 file changed, 29 insertions(+), 29 deletions(-)
+
+diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
+index 72772c87a66f..53cf39cd176d 100644
+--- a/grub-core/osdep/linux/ofpath.c
++++ b/grub-core/osdep/linux/ofpath.c
+@@ -351,36 +351,36 @@ of_path_of_ide(const char *sys_devname __attribute__((unused)), const char *devi
+ return ret;
+ }
+
+-
++#define BNAME_SIZE 150
+ static void
+-of_fc_port_name(const char *path, const char *subpath, char *port_name)
++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));
++ bname = xmalloc (sizeof (char) * BNAME_SIZE);
++ 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);
++ strncpy (basepath, path, subpath-path);
++ basepath[subpath-path - 1] = '\0';
++ p = get_basename (basepath);
++ snprintf (bname, sizeof (char) * BNAME_SIZE, "%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)
++ 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);
++ sscanf (port_name, "0x%s", port_name);
+
+- free(bname);
+- free(basepath);
++ close (fd);
++
++ free (bname);
++ free (basepath);
+ }
+
+ #ifdef __sparc__
+@@ -610,16 +610,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);
+- }
++ 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')
+ {
+@@ -634,12 +634,12 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
+ "/%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 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
+ {
diff --git a/0440-ieee1275-implement-FCP-methods-for-WWPN-and-LUNs.patch b/0440-ieee1275-implement-FCP-methods-for-WWPN-and-LUNs.patch
new file mode 100644
index 0000000..af8c87e
--- /dev/null
+++ b/0440-ieee1275-implement-FCP-methods-for-WWPN-and-LUNs.patch
@@ -0,0 +1,143 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Avnish Chouhan <avnish@linux.ibm.com>
+Date: Mon, 23 Feb 2026 19:14:07 +0530
+Subject: [PATCH] ieee1275: implement FCP methods for WWPN and LUNs
+
+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>
+Reviewed-by: Leo Sandoval <lsandova@redhat.com>
+Reviewed-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Part-of: <https://gitlab.freedesktop.org/gnu-grub/grub/-/merge_requests/146>
+---
+ 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 71237b256003..042f98797546 100644
+--- a/grub-core/disk/ieee1275/ofdisk.c
++++ b/grub-core/disk/ieee1275/ofdisk.c
+@@ -224,7 +224,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
diff --git a/0441-ieee1275-change-the-logic-of-ieee1275_get_devargs.patch b/0441-ieee1275-change-the-logic-of-ieee1275_get_devargs.patch
new file mode 100644
index 0000000..949a590
--- /dev/null
+++ b/0441-ieee1275-change-the-logic-of-ieee1275_get_devargs.patch
@@ -0,0 +1,63 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Avnish Chouhan <avnish@linux.ibm.com>
+Date: Mon, 23 Feb 2026 19:14:08 +0530
+Subject: [PATCH] ieee1275: change the logic of ieee1275_get_devargs()
+
+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>
+Reviewed-by: Leo Sandoval <lsandova@redhat.com>
+Reviewed-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Part-of: <https://gitlab.freedesktop.org/gnu-grub/grub/-/merge_requests/146>
+---
+ 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 65616254e021..0c9047769860 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 ();
diff --git a/0442-ieee1275-ofpath-enable-NVMeoF-logical-device-transla.patch b/0442-ieee1275-ofpath-enable-NVMeoF-logical-device-transla.patch
new file mode 100644
index 0000000..71b811b
--- /dev/null
+++ b/0442-ieee1275-ofpath-enable-NVMeoF-logical-device-transla.patch
@@ -0,0 +1,547 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Avnish Chouhan <avnish@linux.ibm.com>
+Date: Mon, 23 Feb 2026 19:14:10 +0530
+Subject: [PATCH] ieee1275: ofpath enable NVMeoF logical device translate
+
+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>
+Reviewed-by: Leo Sandoval <lsandova@redhat.com>
+Reviewed-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Part-of: <https://gitlab.freedesktop.org/gnu-grub/grub/-/merge_requests/146>
+---
+ grub-core/osdep/linux/ofpath.c | 431 ++++++++++++++++++++++++++++++++++++++++-
+ include/grub/util/ofpath.h | 28 +++
+ 2 files changed, 450 insertions(+), 9 deletions(-)
+
+diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
+index 53cf39cd176d..94bfa8e268dc 100644
+--- a/grub-core/osdep/linux/ofpath.c
++++ b/grub-core/osdep/linux/ofpath.c
+@@ -137,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)
+@@ -313,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,
+@@ -383,7 +468,257 @@ 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");
++ if (!fp)
++ {
++ node = node->next;
++ continue;
++ }
++
++ 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");
++ if (!fp)
++ {
++ free (sysfs_path);
++ free (buf);
++ return 0;
++ }
++
++ 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,
+@@ -392,6 +727,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;
+@@ -411,15 +748,94 @@ 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;
++ }
++
++ free (sysfs_path);
++ sysfs_path = of_find_fc_host (nvmeof_info->host_wwpn);
++ if (!sysfs_path)
++ {
++ free (nvmedev);
++ free (nvmeof_info->host_wwpn);
++ free (nvmeof_info->target_wwpn);
++ free (nvmeof_info->nqn);
++ 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);
+@@ -430,7 +846,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)
+@@ -841,11 +1256,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 b43c523cb267..7ab377c7cc43 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 */
diff --git a/0443-ieee1275-support-added-for-multiple-nvme-bootpaths.patch b/0443-ieee1275-support-added-for-multiple-nvme-bootpaths.patch
new file mode 100644
index 0000000..06c68e5
--- /dev/null
+++ b/0443-ieee1275-support-added-for-multiple-nvme-bootpaths.patch
@@ -0,0 +1,218 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Avnish Chouhan <avnish@linux.ibm.com>
+Date: Mon, 23 Feb 2026 19:14:11 +0530
+Subject: [PATCH] ieee1275: support added for multiple nvme bootpaths
+
+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>
+Reviewed-by: Leo Sandoval <lsandova@redhat.com>
+Reviewed-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Part-of: <https://gitlab.freedesktop.org/gnu-grub/grub/-/merge_requests/146>
+---
+ grub-core/osdep/linux/ofpath.c | 4 +-
+ grub-core/osdep/unix/platform.c | 122 +++++++++++++++++++++++++++++++++++++++-
+ include/grub/util/install.h | 3 +
+ include/grub/util/ofpath.h | 4 ++
+ 4 files changed, 130 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
+index 94bfa8e268dc..8252fd38b32a 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;
+@@ -697,7 +697,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/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
+index de712211cf09..2eda02bf5f20 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,111 @@ 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"))
++ {
++ char *tmp = xasprintf ("%s/device", sysfs_path);
++ free (sysfs_path);
++ sysfs_path = tmp;
++ is_FC = true;
++ }
++ else
++ {
++ char *tmp = xasprintf ("%s/subsystem", sysfs_path);
++ free (sysfs_path);
++ sysfs_path = tmp;
++ 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 +324,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/include/grub/util/install.h b/include/grub/util/install.h
+index dbf3c216d413..857ccbbe9c38 100644
+--- a/include/grub/util/install.h
++++ b/include/grub/util/install.h
+@@ -240,6 +240,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 7ab377c7cc43..9f9a753dcebb 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 */
diff --git a/0444-ieee1275-add-support-for-NVMeoFC.patch b/0444-ieee1275-add-support-for-NVMeoFC.patch
new file mode 100644
index 0000000..9142ea1
--- /dev/null
+++ b/0444-ieee1275-add-support-for-NVMeoFC.patch
@@ -0,0 +1,457 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Avnish Chouhan <avnish@linux.ibm.com>
+Date: Mon, 23 Feb 2026 19:14:09 +0530
+Subject: [PATCH] ieee1275: add support for NVMeoFC
+
+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>
+Reviewed-by: Leo Sandoval <lsandova@redhat.com>
+Reviewed-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Part-of: <https://gitlab.freedesktop.org/gnu-grub/grub/-/merge_requests/146>
+---
+ grub-core/disk/ieee1275/ofdisk.c | 418 +++++++++++++++++++++++++++++----------
+ 1 file changed, 312 insertions(+), 106 deletions(-)
+
+diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
+index 042f98797546..bbd61a32bee3 100644
+--- a/grub-core/disk/ieee1275/ofdisk.c
++++ b/grub-core/disk/ieee1275/ofdisk.c
+@@ -27,6 +27,10 @@
+ #include <grub/env.h>
+ #include <grub/safemath.h>
+
++#define EXTEND_PATH_64 64
++#define EXTEND_PATH_512 512
++#define TABLE_SIZE 256
++
+ static char *last_devpath;
+ static grub_ieee1275_ihandle_t last_ihandle;
+
+@@ -221,117 +225,319 @@ dev_iterate_real (const char *name, const char *path)
+ return;
+ }
+
++static void
++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;
++ }
++
++ /* 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;
++ }
++ /* 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*) (grub_addr_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 ((const void *) ptr_targets));
++ 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*) (grub_addr_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 ((const void *) ptr_luns));
++ 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[TABLE_SIZE];
++ 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[TABLE_SIZE];
++ char nqn[TABLE_SIZE];
++ };
++
++ struct nvme_controllers_table_entry_real
++ {
++ grub_uint16_t id;
++ char wwpn[TABLE_SIZE];
++ char nqn[TABLE_SIZE];
++ };
++
++ 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) * TABLE_SIZE);
++ /* 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)
+ {
+- /*
+- * 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;
++ /* Iterate disks */
++ dev_iterate_fcp_disks (alias);
++ /* Iterate NVMeoF */
++ dev_iterate_fcp_nvmeof (alias);
+ }
+ else if (grub_strcmp (alias->type, "vscsi") == 0)
+ {
diff --git a/grub.patches b/grub.patches
index 74f0ace..50bb055 100644
--- a/grub.patches
+++ b/grub.patches
@@ -435,3 +435,9 @@ Patch0435: 0435-util-grub-editenv-remove-stale-env_block-on-unsuppor.patch
Patch0436: 0436-Change-login-error-message.patch
Patch0437: 0437-mdraid-fix-metadata-1.0-detection-in-userspace-utils-on-IEEE1275.patch
Patch0438: 0438-grub-install-use-search.fs_uuid-for-RAID1-on-IEEE1275.patch
+Patch0439: 0439-ieee1275-powerpc-implements-fibre-channel-discovery-.patch
+Patch0440: 0440-ieee1275-implement-FCP-methods-for-WWPN-and-LUNs.patch
+Patch0441: 0441-ieee1275-change-the-logic-of-ieee1275_get_devargs.patch
+Patch0442: 0442-ieee1275-ofpath-enable-NVMeoF-logical-device-transla.patch
+Patch0443: 0443-ieee1275-support-added-for-multiple-nvme-bootpaths.patch
+Patch0444: 0444-ieee1275-add-support-for-NVMeoFC.patch
diff --git a/grub2.spec b/grub2.spec
index 8fa47b5..c951083 100644
--- a/grub2.spec
+++ b/grub2.spec
@@ -17,7 +17,7 @@
Name: grub2
Epoch: 1
Version: 2.12
-Release: 66%{?dist}
+Release: 67%{?dist}
Summary: Bootloader with support for Linux, Multiboot and more
License: GPL-3.0-or-later
URL: http://www.gnu.org/software/grub/
@@ -625,6 +625,9 @@ fi
%endif
%changelog
+* Thu Jun 25 2026 Nicolas Frayer <nfrayer@redhat.com> - 2.12-67
+- ieee1275/powerpc: implements fibre channel discovery for ofpathname
+
* Thu Jun 25 2026 Leo Sandoval <lsandova@redhat.com> - 2.12-66
- spec efi postttrans: remove mountpoint check
- Resolves: #2492140
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-06-26 18:05 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-26 18:05 [rpms/grub2] rawhide: ieee1275/powerpc: implements fibre channel discovery for ofpathname Nicolas Frayer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox