diff --git a/SOURCES/0537-Change-login-error-message.patch b/SOURCES/0537-Change-login-error-message.patch new file mode 100644 index 0000000..b20bd4f --- /dev/null +++ b/SOURCES/0537-Change-login-error-message.patch @@ -0,0 +1,130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Josue Hernandez +Date: Thu, 28 May 2026 16:26:40 -0600 +Subject: [PATCH] Change login error message + +Login error message shows the line of code where it was called +which is not user friendly, This proposal adds better and more +human log messages when authentication fails + +Resolves: #RHEL-180631 + +Signed-off-by: Josue Hernandez +--- + grub-core/commands/password.c | 2 +- + grub-core/commands/password_pbkdf2.c | 2 +- + grub-core/kern/err.c | 14 ++++++++++++++ + grub-core/normal/auth.c | 17 +++++++++++++---- + include/grub/err.h | 2 ++ + 5 files changed, 31 insertions(+), 6 deletions(-) + +diff --git a/grub-core/commands/password.c b/grub-core/commands/password.c +index 6d42c9b02..607ee6435 100644 +--- a/grub-core/commands/password.c ++++ b/grub-core/commands/password.c +@@ -35,7 +35,7 @@ check_password (const char *user, const char *entered, + void *password) + { + if (grub_crypto_memcmp (entered, password, GRUB_AUTH_MAX_PASSLEN) != 0) +- return GRUB_ACCESS_DENIED; ++ grub_user_error(GRUB_ERR_ACCESS_DENIED, N_("Authentication error")); + + grub_auth_authenticate (user); + +diff --git a/grub-core/commands/password_pbkdf2.c b/grub-core/commands/password_pbkdf2.c +index ab845d25e..17dffcd44 100644 +--- a/grub-core/commands/password_pbkdf2.c ++++ b/grub-core/commands/password_pbkdf2.c +@@ -58,7 +58,7 @@ check_password (const char *user, const char *entered, void *pin) + if (err) + ret = grub_crypto_gcry_error (err); + else if (grub_crypto_memcmp (buf, pass->expected, pass->buflen) != 0) +- ret = GRUB_ACCESS_DENIED; ++ ret = grub_user_error(GRUB_ERR_ACCESS_DENIED, N_("Authentication error")); + else + { + grub_auth_authenticate (user); +diff --git a/grub-core/kern/err.c b/grub-core/kern/err.c +index aebfe0cf8..d386e094f 100644 +--- a/grub-core/kern/err.c ++++ b/grub-core/kern/err.c +@@ -37,6 +37,20 @@ static int grub_error_stack_assert; + #undef grub_error + #endif + ++grub_err_t ++grub_user_error (grub_err_t n, const char *fmt, ...) ++{ ++ va_list ap; ++ ++ grub_errno = n; ++ ++ va_start (ap, fmt); ++ grub_vsnprintf (grub_errmsg, sizeof (grub_errmsg), _(fmt), ap); ++ va_end (ap); ++ ++ return n; ++} ++ + grub_err_t + grub_error (grub_err_t n, const char *file, const int line, const char *fmt, ...) + { +diff --git a/grub-core/normal/auth.c b/grub-core/normal/auth.c +index 075aba452..a7ed80a19 100644 +--- a/grub-core/normal/auth.c ++++ b/grub-core/normal/auth.c +@@ -253,12 +253,18 @@ grub_auth_check_authentication (const char *userlist) + grub_puts_ (N_("Enter username: ")); + + if (!grub_username_get (login, sizeof (login) - 1)) +- goto access_denied; ++ { ++ grub_user_error(GRUB_ERR_ACCESS_DENIED, N_("Error getting user")); ++ goto access_denied; ++ } + + grub_puts_ (N_("Enter password: ")); + + if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) +- goto access_denied; ++ { ++ grub_user_error(GRUB_ERR_ACCESS_DENIED, N_("Error getting password")); ++ goto access_denied; ++ } + + FOR_LIST_ELEMENTS (user, users) + { +@@ -267,7 +273,10 @@ grub_auth_check_authentication (const char *userlist) + } + + if (!cur || ! cur->callback) +- goto access_denied; ++ { ++ grub_user_error(GRUB_ERR_ACCESS_DENIED, N_("Authentication error")); ++ goto access_denied; ++ } + + cur->callback (login, entered, cur->arg); + if (is_authenticated (userlist)) +@@ -282,7 +291,7 @@ grub_auth_check_authentication (const char *userlist) + if (punishment_delay < GRUB_ULONG_MAX / 2) + punishment_delay *= 2; + +- return GRUB_ACCESS_DENIED; ++ return GRUB_ERR_ACCESS_DENIED; + } + + static grub_err_t +diff --git a/include/grub/err.h b/include/grub/err.h +index 4703cb33c..547dda478 100644 +--- a/include/grub/err.h ++++ b/include/grub/err.h +@@ -91,6 +91,8 @@ extern char EXPORT_VAR(grub_errmsg)[GRUB_MAX_ERRMSG]; + + grub_err_t EXPORT_FUNC(grub_error) (grub_err_t n, const char *file, const int line, const char *fmt, ...) + __attribute__ ((format (GNU_PRINTF, 4, 5))); ++grub_err_t EXPORT_FUNC(grub_user_error) (grub_err_t n, const char *fmt, ...) ++ __attribute__ ((format (GNU_PRINTF, 2, 3))); + + #define grub_error(n, fmt, ...) grub_error (n, __FILE__, __LINE__, fmt, ##__VA_ARGS__) + diff --git a/SOURCES/0538-ieee1275-powerpc-implements-fibre-channel-discovery-.patch b/SOURCES/0538-ieee1275-powerpc-implements-fibre-channel-discovery-.patch new file mode 100644 index 0000000..4daabf4 --- /dev/null +++ b/SOURCES/0538-ieee1275-powerpc-implements-fibre-channel-discovery-.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Avnish Chouhan +Date: Thu, 18 Jun 2026 10:49:54 +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 +Signed-off-by: Avnish Chouhan +Reviewed-by: Leo Sandoval +Reviewed-by: Sudhakar Kuppusamy +Part-of: +--- + 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 cc849d9c94c3..9ba1db74aadf 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/SOURCES/0539-ieee1275-implement-FCP-methods-for-WWPN-and-LUNs.patch b/SOURCES/0539-ieee1275-implement-FCP-methods-for-WWPN-and-LUNs.patch new file mode 100644 index 0000000..3af7ccf --- /dev/null +++ b/SOURCES/0539-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 +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 +Signed-off-by: Avnish Chouhan +Reviewed-by: Leo Sandoval +Reviewed-by: Sudhakar Kuppusamy +Part-of: +--- + 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 abb5082cdbfc..a16300a94745 100644 +--- a/grub-core/disk/ieee1275/ofdisk.c ++++ b/grub-core/disk/ieee1275/ofdisk.c +@@ -223,7 +223,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/SOURCES/0540-ieee1275-change-the-logic-of-ieee1275_get_devargs.patch b/SOURCES/0540-ieee1275-change-the-logic-of-ieee1275_get_devargs.patch new file mode 100644 index 0000000..af670f4 --- /dev/null +++ b/SOURCES/0540-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 +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 +Signed-off-by: Avnish Chouhan +Reviewed-by: Leo Sandoval +Reviewed-by: Sudhakar Kuppusamy +Part-of: +--- + 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 0278054c61e6..de0b8c299285 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/SOURCES/0541-ieee1275-ofpath-enable-NVMeoF-logical-device-transla.patch b/SOURCES/0541-ieee1275-ofpath-enable-NVMeoF-logical-device-transla.patch new file mode 100644 index 0000000..10bab3e --- /dev/null +++ b/SOURCES/0541-ieee1275-ofpath-enable-NVMeoF-logical-device-transla.patch @@ -0,0 +1,547 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Avnish Chouhan +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 +Signed-off-by: Avnish Chouhan +Signed-off-by: Michael Chang +Reviewed-by: Leo Sandoval +Reviewed-by: Sudhakar Kuppusamy +Part-of: +--- + 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 9ba1db74aadf..54094a87576b 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/SOURCES/0542-ieee1275-support-added-for-multiple-nvme-bootpaths.patch b/SOURCES/0542-ieee1275-support-added-for-multiple-nvme-bootpaths.patch new file mode 100644 index 0000000..2f0f867 --- /dev/null +++ b/SOURCES/0542-ieee1275-support-added-for-multiple-nvme-bootpaths.patch @@ -0,0 +1,218 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Avnish Chouhan +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 +Reviewed-by: Leo Sandoval +Reviewed-by: Sudhakar Kuppusamy +Part-of: +--- + 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 54094a87576b..46b23820c8b8 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 55b8f4016248..8ca94e3ee0fe 100644 +--- a/grub-core/osdep/unix/platform.c ++++ b/grub-core/osdep/unix/platform.c +@@ -28,6 +28,10 @@ + #include + #include + #include ++#include ++#include ++ ++#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 ccf799ff7169..5b4513904889 100644 +--- a/include/grub/util/install.h ++++ b/include/grub/util/install.h +@@ -238,6 +238,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/SOURCES/0543-ieee1275-add-support-for-NVMeoFC.patch b/SOURCES/0543-ieee1275-add-support-for-NVMeoFC.patch new file mode 100644 index 0000000..2b97802 --- /dev/null +++ b/SOURCES/0543-ieee1275-add-support-for-NVMeoFC.patch @@ -0,0 +1,457 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Avnish Chouhan +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 +Signed-off-by: Avnish Chouhan +Reviewed-by: Leo Sandoval +Reviewed-by: Sudhakar Kuppusamy +Part-of: +--- + 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 a16300a94745..cf0f003f90da 100644 +--- a/grub-core/disk/ieee1275/ofdisk.c ++++ b/grub-core/disk/ieee1275/ofdisk.c +@@ -26,6 +26,10 @@ + #include + #include + ++#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; + +@@ -220,117 +224,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/SOURCES/0544-mdraid-fix-metadata-1.0-detection-in-userspace-utils-on-IEEE1275.patch b/SOURCES/0544-mdraid-fix-metadata-1.0-detection-in-userspace-utils-on-IEEE1275.patch new file mode 100644 index 0000000..fba2f89 --- /dev/null +++ b/SOURCES/0544-mdraid-fix-metadata-1.0-detection-in-userspace-utils-on-IEEE1275.patch @@ -0,0 +1,47 @@ +From 3d5fd0d7c5984338902f651882c76ec122e450ff Mon Sep 17 00:00:00 2001 +From: Rolv Apneseth +Date: Mon, 18 May 2026 09:58:18 +0100 +Subject: [PATCH] mdraid: fix metadata 1.0 detection in userspace utilities on + IEEE1275 + +The powerpc guard in grub_mdraid_detect skips metadata 1.0 to avoid a +firmware block issue, but also ends up applying to userspace utilities +where reads will be going through the kernel. Extend the conditional +with !defined(GRUB_UTIL) so utilities like grub-install can detect +metadata 1.0 arrays. + +Signed-off-by: Rolv Apneseth +--- + grub-core/disk/mdraid1x_linux.c | 2 +- + grub-core/disk/mdraid_linux.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/grub-core/disk/mdraid1x_linux.c b/grub-core/disk/mdraid1x_linux.c +index 08c57ae..09f1065 100644 +--- a/grub-core/disk/mdraid1x_linux.c ++++ b/grub-core/disk/mdraid1x_linux.c +@@ -130,7 +130,7 @@ grub_mdraid_detect (grub_disk_t disk, + struct grub_diskfilter_vg *array; + char *uuid; + +-#ifdef __powerpc__ ++#if defined(__powerpc__) && !defined(GRUB_UTIL) + /* Firmware will yell at us for reading too far. */ + if (minor_version == 0) + continue; +diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c +index 98fcfb1..79145f8 100644 +--- a/grub-core/disk/mdraid_linux.c ++++ b/grub-core/disk/mdraid_linux.c +@@ -189,7 +189,7 @@ grub_mdraid_detect (grub_disk_t disk, + grub_uint32_t level; + struct grub_diskfilter_vg *ret; + +-#ifdef __powerpc__ ++#if defined(__powerpc__) && !defined(GRUB_UTIL) + /* Firmware will yell at us for reading too far. */ + return NULL; + #endif +-- +2.54.0 + diff --git a/SOURCES/0545-grub-install-use-search.fs_uuid-for-RAID1-on-IEEE1275.patch b/SOURCES/0545-grub-install-use-search.fs_uuid-for-RAID1-on-IEEE1275.patch new file mode 100644 index 0000000..6c88a9a --- /dev/null +++ b/SOURCES/0545-grub-install-use-search.fs_uuid-for-RAID1-on-IEEE1275.patch @@ -0,0 +1,39 @@ +From df2f1f23de0b79c156c70a72667ab98d85a29050 Mon Sep 17 00:00:00 2001 +From: Rolv Apneseth +Date: Mon, 18 May 2026 10:07:03 +0100 +Subject: [PATCH] grub-install: use search.fs_uuid for RAID1 on IEEE1275 + +On IEEE1275, grub-install hardcodes an mduuid prefix for RAID +abstractions, requiring array assembly at boot. This fails on metadata +1.0 partitions because detection is skipped due to a firmware issue. + +Since RAID1 mirrors are individually readable, use search.fs_uuid on +IEEE1275 to find the boot filesystem on any member partition and avoid +requiring array assembly. + +Signed-off-by: Rolv Apneseth +--- + util/grub-install.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/util/grub-install.c b/util/grub-install.c +index 162162b..c5cf20a 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -1385,7 +1385,12 @@ main (int argc, char *argv[]) + } + } + +- if (!have_abstractions) ++ int is_ieee1275_raid1 = have_abstractions ++ && (platform == GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275) ++ && grub_dev->disk ++ && probe_raid_level (grub_dev->disk) == 1; ++ ++ if (!have_abstractions || is_ieee1275_raid1) + { + if ((disk_module && grub_strcmp (disk_module, "biosdisk") != 0) + || grub_drives[1] +-- +2.54.0 + diff --git a/SOURCES/20-grub.install b/SOURCES/20-grub.install index 30e5d5b..b82dffa 100755 --- a/SOURCES/20-grub.install +++ b/SOURCES/20-grub.install @@ -153,7 +153,7 @@ case "$COMMAND" in fi fi if [ -n "$NEWDEFAULT" ]; then - grub2-editenv - set "saved_entry=${NEWDEFAULT}" + grub2-editenv - set "tmp_saved_entry=${NEWDEFAULT}" fi # this probably isn't the best place to do this, but it will do for now. diff --git a/SOURCES/95-set-boot-entry.install b/SOURCES/95-set-boot-entry.install new file mode 100755 index 0000000..9f92f9f --- /dev/null +++ b/SOURCES/95-set-boot-entry.install @@ -0,0 +1,44 @@ +#!/bin/bash + +[[ -f /etc/default/grub ]] && . /etc/default/grub +[[ -f /etc/os-release ]] && . /etc/os-release + +COMMAND="$1" +KERNEL_VERSION="$2" +BOOT_DIR_ABS="$3" +KERNEL_IMAGE="$4" + +case "$COMMAND" in + add) + if [[ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]] || [[ ! -f /sbin/new-kernel-pkg ]]; then + entry=$(grub2-editenv list | grep tmp_saved_entry) + if [ -n "$entry" ]; then + BLS_ID=${entry##tmp_saved_entry=} + BLS_DIR="/boot/loader/entries" + BLS_TARGET="${BLS_DIR}/${BLS_ID}.conf" + + LINUX="$(grep '^linux[ \t]' "${BLS_TARGET}" | sed -e 's,^linux[ \t]*,,' | awk '{print $1}')" + INITRD="$(grep '^initrd[ \t]' "${BLS_TARGET}" | sed -e 's,^initrd[ \t]*,,' | awk '{print $1}')" + + ROOTPREFIX="" + [ -z "$(grub2-mkrelpath /boot)" ] && ROOTPREFIX="/boot" + + if [ -e "${ROOTPREFIX}${LINUX}" -a -n "${INITRD}" ]; then + if [ ! -e "${ROOTPREFIX}${INITRD}" ]; then + echo "Error: ${ROOTPREFIX}${INITRD} not found." + exit 1 + fi + if ! lsinitrd ${ROOTPREFIX}${INITRD} > /dev/null; then + echo "Error: ${ROOTPREFIX}${INITRD} appears to be corrupt." + exit 1 + fi + fi + + grub2-editenv - unset "tmp_saved_entry" + grub2-editenv - set "saved_entry=$BLS_ID" + fi + fi + ;; + *) + ;; +esac diff --git a/SOURCES/grub.macros b/SOURCES/grub.macros index d519ca8..a008766 100755 --- a/SOURCES/grub.macros +++ b/SOURCES/grub.macros @@ -586,7 +586,6 @@ cp docs/grub-dev.info \\\ $RPM_BUILD_ROOT%{_infodir}/%{name}-dev.info \ install -d -m 0700 ${RPM_BUILD_ROOT}%{efi_esp_dir}/ \ install -d -m 0700 ${RPM_BUILD_ROOT}/boot/%{name}/ \ -install -d -m 0700 ${RPM_BUILD_ROOT}/boot/loader/entries \ install -d -m 0700 ${RPM_BUILD_ROOT}/boot/%{name}/themes/system \ install -d -m 0700 ${RPM_BUILD_ROOT}%{_sysconfdir}/default \ install -d -m 0700 ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig \ @@ -604,7 +603,6 @@ ln -s ../boot/%{name}/grub.cfg \\\ %defattr(-,root,root,-) \ %config(noreplace) %{_sysconfdir}/%{name}.cfg \ %ghost %config(noreplace) %attr(0600,root,root)/boot/%{name}/grub.cfg \ -%dir %attr(0700,root,root)/boot/loader/entries \ %attr(0644,root,root) %config(noreplace) /etc/dnf/protected.d/%{name}-%{1}.conf \ %ifarch ppc64le \ %dir %{_libdir}/grub/%{2}/ \ @@ -638,7 +636,6 @@ ln -s ../boot/%{name}/grub.cfg \\\ %endif \ %attr(0700,root,root)/boot/%{name}/fonts \ %attr(0700,root,root)/usr/bin/gen_grub_cfgstub \ -%dir %attr(0700,root,root)/boot/loader/entries \ %ghost %config(noreplace) %attr(0600,root,root)/boot/%{name}/grub.cfg \ %ghost %config(noreplace) %verify(not mtime) %attr(0700,root,root)%{efi_esp_dir}/grub.cfg \ %config(noreplace) %verify(not size mode md5 mtime) /boot/%{name}/grubenv \ diff --git a/SOURCES/grub.patches b/SOURCES/grub.patches index 72178dc..1bfdb00 100644 --- a/SOURCES/grub.patches +++ b/SOURCES/grub.patches @@ -533,3 +533,12 @@ Patch0533: 0533-commands-usbtest-Ensure-string-length-is-sufficient-.patch Patch0534: 0534-util-grub-mkimagexx-Stop-generating-unaligned-append.patch Patch0535: 0535-grub-mkimage-Do-not-generate-empty-SBAT-metadata.patch Patch0536: 0536-kern-efi-mm-Change-grub_efi_mm_add_regions-to-keep-t.patch +Patch0537: 0537-Change-login-error-message.patch +Patch0538: 0538-ieee1275-powerpc-implements-fibre-channel-discovery-.patch +Patch0539: 0539-ieee1275-implement-FCP-methods-for-WWPN-and-LUNs.patch +Patch0540: 0540-ieee1275-change-the-logic-of-ieee1275_get_devargs.patch +Patch0541: 0541-ieee1275-ofpath-enable-NVMeoF-logical-device-transla.patch +Patch0542: 0542-ieee1275-support-added-for-multiple-nvme-bootpaths.patch +Patch0543: 0543-ieee1275-add-support-for-NVMeoFC.patch +Patch0544: 0544-mdraid-fix-metadata-1.0-detection-in-userspace-utils-on-IEEE1275.patch +Patch0545: 0545-grub-install-use-search.fs_uuid-for-RAID1-on-IEEE1275.patch diff --git a/SPECS/grub2.spec b/SPECS/grub2.spec index e1cf18b..e2d6e30 100644 --- a/SPECS/grub2.spec +++ b/SPECS/grub2.spec @@ -16,7 +16,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 126%{?dist} +Release: 134%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -36,6 +36,7 @@ Source11: grub.patches Source12: sbat.csv.in Source13: gen_grub_cfgstub Source14: sbat.ppc.csv +Source15: 95-set-boot-entry.install %include %{SOURCE1} @@ -51,7 +52,7 @@ Source14: sbat.ppc.csv %if 0%{?centos} %ifarch x86_64 aarch64 ppc64le -%define sb_key centossecureboot202 +%define sb_key centossecureboot802 %endif %else %ifarch x86_64 aarch64 @@ -264,6 +265,7 @@ rm -vf ${RPM_BUILD_ROOT}/%{_sbindir}/%{name}-macbless # Install kernel-install scripts install -d -m 0755 %{buildroot}%{_prefix}/lib/kernel/install.d/ install -D -m 0755 -t %{buildroot}%{_prefix}/lib/kernel/install.d/ %{SOURCE10} +install -D -m 0755 -t %{buildroot}%{_prefix}/lib/kernel/install.d/ %{SOURCE15} install -D -m 0755 -t %{buildroot}%{_prefix}/lib/kernel/install.d/ %{SOURCE3} install -d -m 0755 %{buildroot}%{_sysconfdir}/kernel/install.d/ # Install systemd user service to set the boot_success flag @@ -302,6 +304,12 @@ ln -s ../%{name}-systemd-integration.service \ %undefine buildsubdir +%check +%if 0%{with_efi_arch} +pesigcheck -i $RPM_BUILD_ROOT%{efi_esp_dir}/%{grubefiname} -n0 -c %{sb_cer} +pesigcheck -i $RPM_BUILD_ROOT%{efi_esp_dir}/%{grubeficdname} -n0 -c %{sb_cer} +%endif + %pre tools if [ -f /boot/%{name}/user.cfg ]; then if grep -q '^GRUB_PASSWORD=' /boot/%{name}/user.cfg ; then @@ -374,11 +382,81 @@ if test -f ${EFI_HOME}/grubenv; then mv --force ${EFI_HOME}/grubenv ${GRUB_HOME}/grubenv fi +%if "%{platform}" == "pc" +%posttrans pc +set -eu +set -o pipefail + +SYS_FIRMWARE_EFI_DIR=/sys/firmware/efi +BOOT_DIR=/boot + +find_grub_devices() { + local boot_device + local component_devs=() + local block_devs=() + + # Exit if UEFI system running + if test -d $SYS_FIRMWARE_EFI_DIR ; then + exit 0 + fi + + # grub2-probe is required for device finding + if ! command -v grub2-probe &>/dev/null; then + exit 0; + fi + + # Get block devices where GRUB is located. We assume GRUB is on the same device + # as /boot partition is. In case that device is an md (Multiple Device) device, all + # of the component devices of such a device are considered. + boot_device=$(grub2-probe --target=device $BOOT_DIR) + + # Check if a given device is an md (Multiple Device) device + # It is expected that the "mdadm" command is available, + # if it's not it is assumed the device is not an md device. + if command -v mdadm &>/dev/null && \ + mdadm --detail --verbose --brief "$boot_device" &> /dev/null; then + out=$(mdadm --detail --verbose --brief "$boot_device") + # output would look like: + # ARRAY /dev/md0 level=raid1 num-devices=2 metadata=1.2 name=localhost.localdomain:0 UUID=c4acea6e:d56e1598:91822e3f:fb26832c disable=line-too-long devices=/dev/vda1,/dev/vdb1 + for d in $(echo "$out" | sed -n -e 's/.* devices=\([^ ]*\).*/\1/p' | sed 's/,/ /g'); do + component_devs+=("$d") + done + else + component_devs+=("$boot_device") + fi + + # Get blocks from partitions + for d in "${component_devs[@]}"; do + block_devs+=("$(lsblk -spnlo name "$d" | tail -1)") + done + + # Filter those GRUB blocks + for d in "${block_devs[@]}"; do + if dd if="$d" bs=446 count=1 status=none | grep -aq "GRUB"; then + echo "$d" + fi + done +} + +grub_install () { + if ! command -v grub2-install &>/dev/null; then + exit 0 + fi + for d in $(find_grub_devices); do + echo "Installing on $d" >&2 + grub2-install "$d" + done +} + +grub_install || : +%endif + %files common -f grub.lang %dir %{_libdir}/grub/ %dir %{_datarootdir}/grub/ %attr(0700,root,root) %dir %{_sysconfdir}/grub.d %{_prefix}/lib/kernel/install.d/20-grub.install +%{_prefix}/lib/kernel/install.d/95-set-boot-entry.install %{_prefix}/lib/kernel/install.d/99-grub-mkconfig.install %dir %{_datarootdir}/grub %exclude %{_datarootdir}/grub/* @@ -543,6 +621,39 @@ fi %endif %changelog +* Wed Jul 29 2026 Marta Lewandowska 2.06-134 +- Add pesigcheck to check for correct SB signature on UEFI +- Resolves: RHEL-188360 + +* Fri Jul 24 2026 Leo Sandoval - 2.06-133 +- Run grub2-install automatically on grub2-pc posttrans +- Resolves: #RHEL-216339 + +* Mon Jul 21 2026 Josue Hernandez - 2.06-132 +- Remove creation of /boot/loader/entries +- Resolves: #RHEL-212729 + +* Mon Jul 06 2026 Rolv Apneseth - 2.06-131 +- mdraid: fix metadata 1.0 detection in userspace utilities on IEEE1275 +- grub-install: use search.fs_uuid for RAID1 on IEEE1275 +- Resolves: #RHEL-186902 + +* Wed Jul 01 2026 Josue Hernandez 2.06-130 +- Wait for initrmafs and kernel to be installed before set default kernel +- Resolves: #RHEL-191464 + +* Thu Jun 18 2026 Nicolas Frayer 2.06-129 +- ieee1275/powerpc: implements fibre channel discovery for ofpathname +- Resolves: #RHEL-53369 + +* Fri Jun 05 2026 Nicolas Frayer 2.06-128 +- CentOS: Sign grub with 802 +- Resolves: #RHEL-182487 + +* Fri May 29 2026 Josue Hernandez 2.06-127 +- Change login error message for more user frienly version +- resolves: #RHEL-180631 + * Mon Mar 09 2026 Josue Hernandez 2.06-126 - kern/efi/mm: Change grub_efi_mm_add_regions() to keep track of map allocation size - Resolves: #RHEL-148310