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
mem_unum_burst_sgsc(const char * pat,char *** dimmsp,size_t * ndimmsp)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
mem_unum_burst_pattern(const char * pat,char *** dimmsp,size_t * ndimmsp)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
mem_unum_burst(const char * pat,char *** dimmsp,size_t * ndimmsp)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
unum_contains_bypat(const char * erunum,const char * eeunum)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
unum_strip_one_jnum(const char * unum,uint_t * endp)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
unum_contains_bysubstr(const char * erunum,const char * eeunum)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
mem_unum_contains(const char * erunum,const char * eeunum)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
mem_unum_rewrite(nvlist_t * nvl,nvlist_t ** rnvl)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