17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51f017db0Sjroberts * Common Development and Distribution License (the "License"). 61f017db0Sjroberts * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 211f017db0Sjroberts 227c478bd9Sstevel@tonic-gate /* 2378ed97a7Sjl139090 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <mem.h> 307c478bd9Sstevel@tonic-gate #include <fm/fmd_fmri.h> 317aec1d6eScindi #include <fm/libtopo.h> 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <string.h> 347c478bd9Sstevel@tonic-gate #include <strings.h> 357c478bd9Sstevel@tonic-gate #include <ctype.h> 367c478bd9Sstevel@tonic-gate 375f25dc2aSgavinm #define ISHCUNUM(unum) (strncmp(unum, "hc:/", 4) == 0) 385f25dc2aSgavinm 397c478bd9Sstevel@tonic-gate /* 407c478bd9Sstevel@tonic-gate * Given a DIMM or bank unum, mem_unum_burst will break it apart into individual 417c478bd9Sstevel@tonic-gate * DIMM names. If it's a DIMM, one name will be returned. If it's a bank, the 427c478bd9Sstevel@tonic-gate * unums for the individual DIMMs will be returned. 437c478bd9Sstevel@tonic-gate * 447c478bd9Sstevel@tonic-gate * Plain J-number DIMM and bank unums are simple. J DIMMs have one J number. J 457c478bd9Sstevel@tonic-gate * banks have multiple whitespace-separated J numbers. 467c478bd9Sstevel@tonic-gate * 477c478bd9Sstevel@tonic-gate * The others are more complex, and consist of a common portion c, a colon, and 487c478bd9Sstevel@tonic-gate * a DIMM-specific portion d. DIMMs are of the form "c: d", while banks are of 497c478bd9Sstevel@tonic-gate * the form "c: d d ...". The patterns are designed to handle the complex case, 507c478bd9Sstevel@tonic-gate * but also handle the simple ones as an afterthought. bd_pat is used to 517c478bd9Sstevel@tonic-gate * match specific styles of unum. In bd_pat, the first %n indicates the end of 527c478bd9Sstevel@tonic-gate * the common portion ("c" above). The second %n marks the beginning of the 537c478bd9Sstevel@tonic-gate * repetitive portion ("d" above). The third %n is used to determine whether or 547c478bd9Sstevel@tonic-gate * not the entire pattern matched. bd_reppat is used to match instances of the 557c478bd9Sstevel@tonic-gate * repetitive part. 567c478bd9Sstevel@tonic-gate * 577c478bd9Sstevel@tonic-gate * sscanf is your disturbingly powerful friend. 58822fb41dStsien * 59822fb41dStsien * The "bd_subst" element of the bank_dimm structure was added for Ontario 60822fb41dStsien * in order to accommodate its bank string names. Previously, to convert 61822fb41dStsien * from a bank representation <common piece> <dimm1> <dimm2> ... 62822fb41dStsien * we concatenated the common piece with each dimm-specific piece in turn, 63822fb41dStsien * possibly deleting some characters in between. Ontario is the first 64822fb41dStsien * platform which requires that characters be substituted (like a vi s/1/2/) 65822fb41dStsien * in place of characters deleted. "bd_subst" represents the character(s) 66822fb41dStsien * to be substituted between the common piece and each dimm-specific piece 67822fb41dStsien * as part of the bursting. For prior platforms, this value is skipped. 68822fb41dStsien * 69822fb41dStsien * Example: 70822fb41dStsien * input: "MB/CMP0/CH3: R1/D0/J1901 R1/D1/J2001" 71822fb41dStsien * outputs: "MB/CMP0/CH3/R1/D0/J1901", "MB/CMP0/CH3/R1/D1/J2001" 727c478bd9Sstevel@tonic-gate */ 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate typedef struct bank_dimm { 757c478bd9Sstevel@tonic-gate const char *bd_pat; 767c478bd9Sstevel@tonic-gate const char *bd_reppat; 77822fb41dStsien const char *bd_subst; 787c478bd9Sstevel@tonic-gate } bank_dimm_t; 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate static const bank_dimm_t bank_dimm[] = { 817c478bd9Sstevel@tonic-gate { "%n%nJ%*4d%n", " J%*4d%n" }, 827c478bd9Sstevel@tonic-gate { "MB/P%*d/%nB%*d:%n%n", " B%*d/D%*d%n" }, 837c478bd9Sstevel@tonic-gate { "MB/P%*d/%nB%*d/D%*d:%n%n", " B%*d/D%*d%n" }, 847c478bd9Sstevel@tonic-gate { "C%*d/P%*d/%nB%*d:%n%n", " B%*d/D%*d%n" }, 857c478bd9Sstevel@tonic-gate { "C%*d/P%*d/%nB%*d/D%*d:%n%n", " B%*d/D%*d%n" }, 867c478bd9Sstevel@tonic-gate { "Slot %*c: %n%nJ%*4d%n", " J%*4d%n" }, 877c478bd9Sstevel@tonic-gate { "%n%nDIMM%*d%n", " DIMM%*d%n" }, 887c478bd9Sstevel@tonic-gate { "MB/%nDIMM%*d MB/DIMM%*d: %n%n", " DIMM%*d%n" }, 897c478bd9Sstevel@tonic-gate { "MB/%nDIMM%*d:%n%n", " DIMM%*d%n" }, 90822fb41dStsien { "MB/CMP%*d/CH%*d%n:%n%n", " R%*d/D%*d/J%*4d%n", "/" }, 91822fb41dStsien { "MB/CMP%*d/CH%*d%n%n%n", "/R%*d/D%*d/J%*4d%n" }, 921f017db0Sjroberts { "MB/C%*d/P%*d/%nB%*d:%n%n", " B%*d/D%*d%n" }, 931f017db0Sjroberts { "MB/C%*d/P%*d/%nB%*d/D%*d:%n%n", " B%*d/D%*d%n" }, 940cc8ae86Sav145390 { "/MBU_A/MEMB%*d/%n%nMEM%*d%*1c%n", " MEM%*d%*1c%n" }, 950cc8ae86Sav145390 { "/MBU_B/MEMB%*d/%n%nMEM%*d%*1c%n", " MEM%*d%*1c%n" }, 9678ed97a7Sjl139090 { "/MBU_A/%n%nMEM%*d%*1c%n", " MEM%*d%*1c%n" }, 970cc8ae86Sav145390 { "/CMU%*2d/%n%nMEM%*2d%*1c%n", " MEM%*2d%*1c%n" }, 98ef884685Srb144127 { "MB/CMP%*d/BR%*d%n:%n%n", " CH%*d/D%*d/J%*4d%n", "/" }, 99fbd1c0daSsd77468 { "%n%nMB/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n", 100fbd1c0daSsd77468 "MB/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n" }, 101fbd1c0daSsd77468 { "%n%nMB/CMP%*d/BR%*d/CH%*d/D%*d%n", "MB/CMP%*d/BR%*d/CH%*d/D%*d%n" }, 10213faa912Ssd77468 { "MB/CPU%*d/CMP%*d/BR%*d%n:%n%n", " CH%*d/D%*d/J%*4d%n", "/"}, 10313faa912Ssd77468 { "MB/MEM%*d/CMP%*d/BR%*d%n:%n%n", " CH%*d/D%*d/J%*4d%n", "/"}, 10413faa912Ssd77468 { "%n%nMB/MEM%*d/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n", 10513faa912Ssd77468 "MB/MEM%*d/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n" }, 10613faa912Ssd77468 { "%n%nMB/CPU%*d/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n", 10713faa912Ssd77468 "MB/CPU%*d/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n" }, 10813faa912Ssd77468 { "%n%nMB/MEM%*d/CMP%*d/BR%*d/CH%*d/D%*d%n", 10913faa912Ssd77468 "MB/MEM%*d/CMP%*d/BR%*d/CH%*d/D%*d%n" }, 11013faa912Ssd77468 { "%n%nMB/CPU%*d/CMP%*d/BR%*d/CH%*d/D%*d%n", 11113faa912Ssd77468 "MB/CPU%*d/CMP%*d/BR%*d/CH%*d/D%*d%n" }, 1127c478bd9Sstevel@tonic-gate { NULL } 1137c478bd9Sstevel@tonic-gate }; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 116d00f0155Sayznaga * Burst Serengeti and Starcat-style unums. 117d00f0155Sayznaga * A DIMM unum string is expected to be in this form: 118d00f0155Sayznaga * "[/N0/]SB12/P0/B0/D2 [J13500]" 119d00f0155Sayznaga * A bank unum string is expected to be in this form: 120d00f0155Sayznaga * "[/N0/]SB12/P0/B0 [J13500, ...]" 121d00f0155Sayznaga */ 122d00f0155Sayznaga static int 123d00f0155Sayznaga mem_unum_burst_sgsc(const char *pat, char ***dimmsp, size_t *ndimmsp) 124d00f0155Sayznaga { 125d00f0155Sayznaga char buf[64]; 126d00f0155Sayznaga char **dimms; 127d00f0155Sayznaga char *base; 128d00f0155Sayznaga const char *c; 129d00f0155Sayznaga char *copy; 130d00f0155Sayznaga size_t copysz; 131d00f0155Sayznaga int i; 132d00f0155Sayznaga 133d00f0155Sayznaga /* 134d00f0155Sayznaga * No expansion is required for a DIMM unum 135d00f0155Sayznaga */ 136d00f0155Sayznaga if (strchr(pat, 'D') != NULL) { 137d00f0155Sayznaga dimms = fmd_fmri_alloc(sizeof (char *)); 138d00f0155Sayznaga dimms[0] = fmd_fmri_strdup(pat); 139d00f0155Sayznaga *dimmsp = dimms; 140d00f0155Sayznaga *ndimmsp = 1; 141d00f0155Sayznaga return (0); 142d00f0155Sayznaga } 143d00f0155Sayznaga 144d00f0155Sayznaga /* 145d00f0155Sayznaga * strtok is destructive so we need to work with 146d00f0155Sayznaga * a copy and keep track of the size allocated. 147d00f0155Sayznaga */ 148d00f0155Sayznaga copysz = strlen(pat) + 1; 149d00f0155Sayznaga copy = fmd_fmri_alloc(copysz); 150d00f0155Sayznaga (void) strcpy(copy, pat); 151d00f0155Sayznaga 152d00f0155Sayznaga base = strtok(copy, " "); 153d00f0155Sayznaga 154d00f0155Sayznaga /* There are four DIMMs in a bank */ 155d00f0155Sayznaga dimms = fmd_fmri_alloc(sizeof (char *) * 4); 156d00f0155Sayznaga 157d00f0155Sayznaga for (i = 0; i < 4; i++) { 158d00f0155Sayznaga (void) snprintf(buf, sizeof (buf), "%s/D%d", base, i); 159d00f0155Sayznaga 160d00f0155Sayznaga if ((c = strtok(NULL, " ")) != NULL) 161d00f0155Sayznaga (void) snprintf(buf, sizeof (buf), "%s %s", buf, c); 162d00f0155Sayznaga 163d00f0155Sayznaga dimms[i] = fmd_fmri_strdup(buf); 164d00f0155Sayznaga } 165d00f0155Sayznaga 166d00f0155Sayznaga fmd_fmri_free(copy, copysz); 167d00f0155Sayznaga 168d00f0155Sayznaga *dimmsp = dimms; 169d00f0155Sayznaga *ndimmsp = 4; 170d00f0155Sayznaga return (0); 171d00f0155Sayznaga } 172d00f0155Sayznaga 173d00f0155Sayznaga 174d00f0155Sayznaga /* 1757c478bd9Sstevel@tonic-gate * Returns 0 (with dimmsp and ndimmsp set) if the unum could be bursted, -1 1767c478bd9Sstevel@tonic-gate * otherwise. 1777c478bd9Sstevel@tonic-gate */ 178d00f0155Sayznaga static int 179d00f0155Sayznaga mem_unum_burst_pattern(const char *pat, char ***dimmsp, size_t *ndimmsp) 1807c478bd9Sstevel@tonic-gate { 1817c478bd9Sstevel@tonic-gate const bank_dimm_t *bd; 1827c478bd9Sstevel@tonic-gate char **dimms = NULL, **newdimms; 1837c478bd9Sstevel@tonic-gate size_t ndimms = 0; 1847c478bd9Sstevel@tonic-gate const char *c; 1857c478bd9Sstevel@tonic-gate 186d00f0155Sayznaga 1877c478bd9Sstevel@tonic-gate for (bd = bank_dimm; bd->bd_pat != NULL; bd++) { 1887c478bd9Sstevel@tonic-gate int replace, start, matched; 1897c478bd9Sstevel@tonic-gate char dimmname[64]; 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate replace = start = matched = -1; 1927c478bd9Sstevel@tonic-gate (void) sscanf(pat, bd->bd_pat, &replace, &start, &matched); 1937c478bd9Sstevel@tonic-gate if (matched == -1) 1947c478bd9Sstevel@tonic-gate continue; 1957c478bd9Sstevel@tonic-gate (void) strlcpy(dimmname, pat, sizeof (dimmname)); 196822fb41dStsien if (bd->bd_subst != NULL) { 197822fb41dStsien (void) strlcpy(dimmname+replace, bd->bd_subst, 198822fb41dStsien sizeof (dimmname) - strlen(bd->bd_subst)); 199822fb41dStsien replace += strlen(bd->bd_subst); 200822fb41dStsien } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate c = pat + start; 2037c478bd9Sstevel@tonic-gate while (*c != '\0') { 2047c478bd9Sstevel@tonic-gate int dimmlen = -1; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate (void) sscanf(c, bd->bd_reppat, &dimmlen); 2077c478bd9Sstevel@tonic-gate if (dimmlen == -1) 2087c478bd9Sstevel@tonic-gate break; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate while (*c == ' ') { 2117c478bd9Sstevel@tonic-gate c++; 2127c478bd9Sstevel@tonic-gate dimmlen--; 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate if (dimmlen > sizeof (dimmname) - replace) 2167c478bd9Sstevel@tonic-gate break; 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate (void) strlcpy(dimmname + replace, c, dimmlen + 1); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate newdimms = fmd_fmri_alloc(sizeof (char *) * 2217c478bd9Sstevel@tonic-gate (ndimms + 1)); 2227c478bd9Sstevel@tonic-gate if (ndimms != 0) { 2237c478bd9Sstevel@tonic-gate bcopy(dimms, newdimms, sizeof (char *) * 2247c478bd9Sstevel@tonic-gate ndimms); 2257c478bd9Sstevel@tonic-gate fmd_fmri_free(dimms, sizeof (char *) * ndimms); 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate newdimms[ndimms++] = fmd_fmri_strdup(dimmname); 2287c478bd9Sstevel@tonic-gate dimms = newdimms; 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate c += dimmlen; 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate if (*c != ' ' && *c != '\0') 2337c478bd9Sstevel@tonic-gate break; 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate if (*c != '\0') 2377c478bd9Sstevel@tonic-gate break; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate *dimmsp = dimms; 2407c478bd9Sstevel@tonic-gate *ndimmsp = ndimms; 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate return (0); 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate mem_strarray_free(dimms, ndimms); 246d00f0155Sayznaga 247*6684e119Spothier /* 248*6684e119Spothier * Set errno to ENOTSUP and return -1. This allows support for DIMMs 249*6684e119Spothier * with unknown unum strings and/or serial numbers. The only consumer 250*6684e119Spothier * of mem_unum_burst_pattern() that cares/checks for the returned 251*6684e119Spothier * errno is fmd_fmri_expand(). 252*6684e119Spothier */ 253*6684e119Spothier return (fmd_fmri_set_errno(ENOTSUP)); 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 256d00f0155Sayznaga int 257d00f0155Sayznaga mem_unum_burst(const char *pat, char ***dimmsp, size_t *ndimmsp) 258d00f0155Sayznaga { 259d00f0155Sayznaga const char *platform = fmd_fmri_get_platform(); 260d00f0155Sayznaga 261d00f0155Sayznaga /* 262d00f0155Sayznaga * Call mem_unum_burst_sgsc() for Starcat, Serengeti, and 263d00f0155Sayznaga * Lightweight 8 platforms. Call mem_unum_burst_pattern() 264d00f0155Sayznaga * for all other platforms. 265d00f0155Sayznaga */ 266d00f0155Sayznaga if (strcmp(platform, "SUNW,Sun-Fire-15000") == 0 || 267d00f0155Sayznaga strcmp(platform, "SUNW,Sun-Fire") == 0 || 268d00f0155Sayznaga strcmp(platform, "SUNW,Netra-T12") == 0) 269d00f0155Sayznaga return (mem_unum_burst_sgsc(pat, dimmsp, ndimmsp)); 270d00f0155Sayznaga else 271d00f0155Sayznaga return (mem_unum_burst_pattern(pat, dimmsp, ndimmsp)); 272d00f0155Sayznaga } 273d00f0155Sayznaga 2747c478bd9Sstevel@tonic-gate /* 2757c478bd9Sstevel@tonic-gate * The unum containership operation is designed to tell the caller whether a 2767c478bd9Sstevel@tonic-gate * given FMRI contains another. In the case of this plugin, we tell the caller 2777c478bd9Sstevel@tonic-gate * whether a given memory FMRI (usually a bank) contains another (usually a 2787c478bd9Sstevel@tonic-gate * DIMM). We do this in one of two ways, depending on the platform. For most 2797c478bd9Sstevel@tonic-gate * platforms, we can use the bursting routine to generate the list of member 2807c478bd9Sstevel@tonic-gate * unums from the container unum. Membership can then be determined by 2817c478bd9Sstevel@tonic-gate * searching the bursted list for the containee's unum. 2827c478bd9Sstevel@tonic-gate * 2837c478bd9Sstevel@tonic-gate * Some platforms, however, cannot be bursted, as their bank unums do not 2847c478bd9Sstevel@tonic-gate * contain all of the information needed to generate the complete list of 2857c478bd9Sstevel@tonic-gate * member DIMM unums. For these unums, we must make do with a substring 2867c478bd9Sstevel@tonic-gate * comparison. 2877c478bd9Sstevel@tonic-gate */ 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate static int 2907c478bd9Sstevel@tonic-gate unum_contains_bypat(const char *erunum, const char *eeunum) 2917c478bd9Sstevel@tonic-gate { 2927c478bd9Sstevel@tonic-gate char **ernms, **eenms; 293749f21d3Swesolows size_t nernms, neenms; 2947c478bd9Sstevel@tonic-gate int i, j, rv = 1; 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate if (mem_unum_burst(erunum, &ernms, &nernms) < 0) 2977c478bd9Sstevel@tonic-gate return (fmd_fmri_set_errno(EINVAL)); 2987c478bd9Sstevel@tonic-gate if (mem_unum_burst(eeunum, &eenms, &neenms) < 0) { 2997c478bd9Sstevel@tonic-gate mem_strarray_free(ernms, nernms); 3007c478bd9Sstevel@tonic-gate return (fmd_fmri_set_errno(EINVAL)); 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate for (i = 0; i < neenms; i++) { 3047c478bd9Sstevel@tonic-gate for (j = 0; j < nernms; j++) { 3057c478bd9Sstevel@tonic-gate if (strcmp(eenms[i], ernms[j]) == 0) 3067c478bd9Sstevel@tonic-gate break; 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate if (j == nernms) { 3107c478bd9Sstevel@tonic-gate /* 3117c478bd9Sstevel@tonic-gate * This DIMM was not found in the container. 3127c478bd9Sstevel@tonic-gate */ 3137c478bd9Sstevel@tonic-gate rv = 0; 3147c478bd9Sstevel@tonic-gate break; 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate mem_strarray_free(ernms, nernms); 3197c478bd9Sstevel@tonic-gate mem_strarray_free(eenms, neenms); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate return (rv); 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate static int 3257c478bd9Sstevel@tonic-gate unum_strip_one_jnum(const char *unum, uint_t *endp) 3267c478bd9Sstevel@tonic-gate { 3277c478bd9Sstevel@tonic-gate char *c; 3287c478bd9Sstevel@tonic-gate int i; 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate if ((c = strrchr(unum, 'J')) == NULL) 3317c478bd9Sstevel@tonic-gate return (0); 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate while (c > unum && isspace(c[-1])) 3347c478bd9Sstevel@tonic-gate c--; 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate (void) sscanf(c, " J%*[0-9] %n", &i); 3377c478bd9Sstevel@tonic-gate if (i == 0 || (uintptr_t)(c - unum) + i != strlen(unum)) 3387c478bd9Sstevel@tonic-gate return (0); 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate *endp = (uint_t)(c - unum); 3417c478bd9Sstevel@tonic-gate return (1); 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate static int 3467c478bd9Sstevel@tonic-gate unum_contains_bysubstr(const char *erunum, const char *eeunum) 3477c478bd9Sstevel@tonic-gate { 3487c478bd9Sstevel@tonic-gate uint_t erlen, eelen; 3495f25dc2aSgavinm int nojnumstrip = 0; 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate /* 3527c478bd9Sstevel@tonic-gate * This comparison method is only known to work on specific types of 3537c478bd9Sstevel@tonic-gate * unums. Check for those types here. 3547c478bd9Sstevel@tonic-gate */ 3557c478bd9Sstevel@tonic-gate if ((strncmp(erunum, "/N", 2) != 0 && strncmp(erunum, "/IO", 3) != 0 && 3567c478bd9Sstevel@tonic-gate strncmp(erunum, "/SB", 3) != 0) || 3577c478bd9Sstevel@tonic-gate (strncmp(eeunum, "/N", 2) != 0 && strncmp(eeunum, "/IO", 3) != 0 && 3585f25dc2aSgavinm strncmp(eeunum, "/SB", 3) != 0)) { 3598a40a695Sgavinm if (ISHCUNUM(erunum) && ISHCUNUM(eeunum)) { 3605f25dc2aSgavinm nojnumstrip = 1; 3618a40a695Sgavinm erlen = strlen(erunum); 3628a40a695Sgavinm eelen = strlen(eeunum); 3638a40a695Sgavinm } else { 3647c478bd9Sstevel@tonic-gate return (fmd_fmri_set_errno(EINVAL)); 3655f25dc2aSgavinm } 3668a40a695Sgavinm } 3677c478bd9Sstevel@tonic-gate 3685f25dc2aSgavinm if (!nojnumstrip) { 3695f25dc2aSgavinm erlen = unum_strip_one_jnum(erunum, &erlen) ? 3705f25dc2aSgavinm erlen : strlen(erunum); 3715f25dc2aSgavinm eelen = unum_strip_one_jnum(eeunum, &eelen) ? 3725f25dc2aSgavinm eelen : strlen(eeunum); 3735f25dc2aSgavinm } 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate return (strncmp(erunum, eeunum, MIN(erlen, eelen)) == 0); 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate typedef int unum_cmptor_f(const char *, const char *); 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate static unum_cmptor_f *const unum_cmptors[] = { 3817c478bd9Sstevel@tonic-gate unum_contains_bypat, 3827c478bd9Sstevel@tonic-gate unum_contains_bysubstr 3837c478bd9Sstevel@tonic-gate }; 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate int 3867c478bd9Sstevel@tonic-gate mem_unum_contains(const char *erunum, const char *eeunum) 3877c478bd9Sstevel@tonic-gate { 3887c478bd9Sstevel@tonic-gate static int cmptor = 0; 3897c478bd9Sstevel@tonic-gate int rc; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate while (isspace(*erunum)) 3927c478bd9Sstevel@tonic-gate erunum++; 3937c478bd9Sstevel@tonic-gate while (isspace(*eeunum)) 3947c478bd9Sstevel@tonic-gate eeunum++; 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate if ((rc = unum_cmptors[cmptor](erunum, eeunum)) >= 0) 3977c478bd9Sstevel@tonic-gate return (rc); 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate if ((rc = unum_cmptors[cmptor == 0](erunum, eeunum)) >= 0) { 4007c478bd9Sstevel@tonic-gate /* 4017c478bd9Sstevel@tonic-gate * We succeeded with the non-default comparator. Change the 4027c478bd9Sstevel@tonic-gate * default so we use the correct one next time. 4037c478bd9Sstevel@tonic-gate */ 4047c478bd9Sstevel@tonic-gate cmptor = (cmptor == 0); 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate return (rc); 4087c478bd9Sstevel@tonic-gate } 4097aec1d6eScindi 4107aec1d6eScindi /* 4117aec1d6eScindi * If an asru has a unum string that is an hc path string then return 4127aec1d6eScindi * a new nvl (to be freed by the caller) that is a duplicate of the 4137aec1d6eScindi * original but with an additional member of a reconstituted hc fmri. 4147aec1d6eScindi */ 4157aec1d6eScindi int 4167aec1d6eScindi mem_unum_rewrite(nvlist_t *nvl, nvlist_t **rnvl) 4177aec1d6eScindi { 4187aec1d6eScindi int err; 4197aec1d6eScindi char *unumstr; 4207aec1d6eScindi nvlist_t *unum; 4217aec1d6eScindi struct topo_hdl *thp; 4227aec1d6eScindi 4237aec1d6eScindi if (nvlist_lookup_string(nvl, FM_FMRI_MEM_UNUM, &unumstr) != 0 || 4245f25dc2aSgavinm !ISHCUNUM(unumstr)) 4257aec1d6eScindi return (0); 4267aec1d6eScindi 42724db4641Seschrock if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) 4287aec1d6eScindi return (EINVAL); 4297aec1d6eScindi 43024db4641Seschrock if (topo_fmri_str2nvl(thp, unumstr, &unum, &err) != 0) { 43124db4641Seschrock fmd_fmri_topo_rele(thp); 43224db4641Seschrock return (EINVAL); 43324db4641Seschrock } 43424db4641Seschrock 43524db4641Seschrock fmd_fmri_topo_rele(thp); 43624db4641Seschrock 4377aec1d6eScindi if ((err = nvlist_dup(nvl, rnvl, 0)) != 0) { 4387aec1d6eScindi nvlist_free(unum); 4397aec1d6eScindi return (err); 4407aec1d6eScindi } 4417aec1d6eScindi 4427aec1d6eScindi err = nvlist_add_nvlist(*rnvl, FM_FMRI_MEM_UNUM "-fmri", unum); 4437aec1d6eScindi nvlist_free(unum); 4447aec1d6eScindi 4457aec1d6eScindi if (err != 0) 4467aec1d6eScindi nvlist_free(*rnvl); 4477aec1d6eScindi 4487aec1d6eScindi return (err); 4497aec1d6eScindi } 450