Fix the Open Firmware (OF) path property for sun4v SPARC systems. These platforms do not have a /sas/ within their path. Over time different OF addressing schemes have been supported. There is no generic addressing scheme that works across every HBA.
Signed-off-by: Eric Snowberg <[email protected]> --- grub-core/osdep/linux/ofpath.c | 162 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 160 insertions(+), 2 deletions(-) diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c index a79682a..0994e08 100644 --- a/grub-core/osdep/linux/ofpath.c +++ b/grub-core/osdep/linux/ofpath.c @@ -38,6 +38,42 @@ #include <errno.h> #include <ctype.h> +typedef enum + { + GRUB_OFPATH_SPARC_PHY_ADDR = 1, + GRUB_OFPATH_SPARC_TGT_LUN, + } ofpath_sparc_addressing; + +struct ofpath_sparc_hba +{ + grub_uint32_t device_id; + ofpath_sparc_addressing addressing; +}; + +static struct ofpath_sparc_hba sparc_lsi_hba[] = { + /* Rhea, Jasper 320, LSI53C1020/1030 */ + {0x30, GRUB_OFPATH_SPARC_TGT_LUN}, + /* SAS-1068E */ + {0x50, GRUB_OFPATH_SPARC_TGT_LUN}, + /* SAS-1064E */ + {0x56, GRUB_OFPATH_SPARC_TGT_LUN}, + /* Pandora SAS-1068E */ + {0x58, GRUB_OFPATH_SPARC_TGT_LUN}, + /* Aspen, Invader, LSI SAS-3108 */ + {0x5d, GRUB_OFPATH_SPARC_TGT_LUN}, + /* Niwot, SAS 2108 */ + {0x79, GRUB_OFPATH_SPARC_TGT_LUN}, + /* Erie, Falcon, LSI SAS 2008 */ + {0x72, GRUB_OFPATH_SPARC_PHY_ADDR}, + /* LSI WarpDrive 6203 */ + {0x7e, GRUB_OFPATH_SPARC_PHY_ADDR}, + /* LSI SAS 2308 */ + {0x87, GRUB_OFPATH_SPARC_PHY_ADDR}, + /* LSI SAS 3008 */ + {0x97, GRUB_OFPATH_SPARC_PHY_ADDR}, + {0, 0} +}; + #ifdef OFPATH_STANDALONE #define xmalloc malloc void @@ -336,6 +372,85 @@ vendor_is_ATA(const char *path) } static void +check_hba_identifiers(const char *sysfs_path, int *vendor, int *device_id) +{ + char *ed = strstr (sysfs_path, "host"); + size_t path_size; + char *p = NULL, *path = NULL; + char buf[8]; + int fd; + + if (!ed) + return; + + p = xstrdup (sysfs_path); + ed = strstr (p, "host"); + + if (!ed) + { + free (p); + return; + } + *ed = '\0'; + + path_size = (strlen (p) + sizeof("vendor")); + path = xmalloc (path_size); + + if (!path) + { + free (p); + return; + } + + snprintf (path, path_size, "%svendor", p); + fd = open (path, O_RDONLY); + + if (fd < 0) + { + free (p); + free (path); + return; + } + + memset (buf, 0, sizeof (buf)); + + if (read (fd, buf, sizeof (buf) - 1) < 0) + { + close (fd); + free (p); + free (path); + return; + } + + close (fd); + sscanf (buf, "%x", vendor); + snprintf (path, path_size, "%sdevice", p); + fd = open (path, O_RDONLY); + + if (fd < 0) + { + free (p); + free (path); + return; + } + + memset (buf, 0, sizeof (buf)); + + if (read (fd, buf, sizeof (buf) - 1) < 0) + { + close (fd); + free (p); + free (path); + return; + } + + close (fd); + sscanf (buf, "%x", device_id); + free (path); + free (p); +} + +static void check_sas (const char *sysfs_path, int *tgt, unsigned long int *sas_address) { char *ed = strstr (sysfs_path, "end_device"); @@ -413,9 +528,11 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev } of_path = find_obppath(sysfs_path); - free (sysfs_path); if (!of_path) - return NULL; + { + free (sysfs_path); + return NULL; + } if (strstr (of_path, "qlc")) strcat (of_path, "/fp@0,0"); @@ -444,6 +561,45 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev } else { +#ifdef __sparc__ + ofpath_sparc_addressing addressing = GRUB_OFPATH_SPARC_TGT_LUN; + int vendor = 0, device_id = 0; + char *optr = disk; + + check_hba_identifiers (sysfs_path, &vendor, &device_id); + + /* Over time different OF addressing schemes have been supported */ + /* There is no generic addressing scheme that works across */ + /* every HBA */ + if (vendor == 0x1000) /* LSI Logic Vendor ID */ + { + struct ofpath_sparc_hba *lsi_hba; + + for (lsi_hba = sparc_lsi_hba; lsi_hba->device_id; lsi_hba++) + if (lsi_hba->device_id == device_id) + { + addressing = lsi_hba->addressing; + break; + } + } + + if (addressing == GRUB_OFPATH_SPARC_PHY_ADDR) + optr += snprintf (disk, sizeof (disk), "/%s@p%x", disk_name, tgt); + else + optr += snprintf (disk, sizeof (disk), "/%s@%x", disk_name, tgt); + + if (lun) + optr += snprintf (optr, sizeof (disk) - (optr - disk - 1), ",%x", lun); + + if (*digit_string != '\0') + { + int part; + + sscanf (digit_string, "%d", &part); + snprintf (optr, sizeof (disk) - (optr - disk - 1), ":%c", 'a' + + (part - 1)); + } +#else if (lun == 0) { int sas_id = 0; @@ -491,7 +647,9 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev } free (lunstr); } +#endif } + free (sysfs_path); strcat(of_path, disk); return of_path; } -- 1.7.1 _______________________________________________ Grub-devel mailing list [email protected] https://lists.gnu.org/mailman/listinfo/grub-devel
