xref: /illumos-gate/usr/src/cmd/fm/schemes/mem/mem_unum.c (revision ff638e92)
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 /*
2378ed97a7Sjl  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
271f4c6dbcSPeter Tribble /*
281f4c6dbcSPeter Tribble  * Copyright 2019 Peter Tribble.
291f4c6dbcSPeter Tribble  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <mem.h>
327c478bd9Sstevel@tonic-gate #include <fm/fmd_fmri.h>
337aec1d6eScindi #include <fm/libtopo.h>
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include <string.h>
367c478bd9Sstevel@tonic-gate #include <strings.h>
377c478bd9Sstevel@tonic-gate #include <ctype.h>
387c478bd9Sstevel@tonic-gate 
395f25dc2aSgavinm #define	ISHCUNUM(unum) (strncmp(unum, "hc:/", 4) == 0)
405f25dc2aSgavinm 
417c478bd9Sstevel@tonic-gate /*
427c478bd9Sstevel@tonic-gate  * Given a DIMM or bank unum, mem_unum_burst will break it apart into individual
437c478bd9Sstevel@tonic-gate  * DIMM names.  If it's a DIMM, one name will be returned.  If it's a bank, the
447c478bd9Sstevel@tonic-gate  * unums for the individual DIMMs will be returned.
457c478bd9Sstevel@tonic-gate  *
467c478bd9Sstevel@tonic-gate  * Plain J-number DIMM and bank unums are simple.  J DIMMs have one J number.  J
477c478bd9Sstevel@tonic-gate  * banks have multiple whitespace-separated J numbers.
487c478bd9Sstevel@tonic-gate  *
497c478bd9Sstevel@tonic-gate  * The others are more complex, and consist of a common portion c, a colon, and
507c478bd9Sstevel@tonic-gate  * a DIMM-specific portion d.  DIMMs are of the form "c: d", while banks are of
517c478bd9Sstevel@tonic-gate  * the form "c: d d ...".  The patterns are designed to handle the complex case,
527c478bd9Sstevel@tonic-gate  * but also handle the simple ones as an afterthought.  bd_pat is used to
537c478bd9Sstevel@tonic-gate  * match specific styles of unum.  In bd_pat, the first %n indicates the end of
547c478bd9Sstevel@tonic-gate  * the common portion ("c" above).  The second %n marks the beginning of the
557c478bd9Sstevel@tonic-gate  * repetitive portion ("d" above).  The third %n is used to determine whether or
567c478bd9Sstevel@tonic-gate  * not the entire pattern matched.  bd_reppat is used to match instances of the
577c478bd9Sstevel@tonic-gate  * repetitive part.
587c478bd9Sstevel@tonic-gate  *
597c478bd9Sstevel@tonic-gate  * sscanf is your disturbingly powerful friend.
60822fb41dStsien  *
61822fb41dStsien  * The "bd_subst" element of the bank_dimm structure was added for Ontario
62822fb41dStsien  * in order to accommodate its bank string names.  Previously, to convert
63822fb41dStsien  * from a bank representation <common piece> <dimm1> <dimm2> ...
64822fb41dStsien  * we concatenated the common piece with each dimm-specific piece in turn,
65822fb41dStsien  * possibly deleting some characters in between.  Ontario is the first
66822fb41dStsien  * platform which requires that characters be substituted (like a vi s/1/2/)
67822fb41dStsien  * in place of characters deleted.  "bd_subst" represents the character(s)
68822fb41dStsien  * to be substituted between the common piece and each dimm-specific piece
69822fb41dStsien  * as part of the bursting.  For prior platforms, this value is skipped.
70822fb41dStsien  *
71822fb41dStsien  * Example:
72822fb41dStsien  * input: "MB/CMP0/CH3: R1/D0/J1901 R1/D1/J2001"
73822fb41dStsien  * outputs: "MB/CMP0/CH3/R1/D0/J1901", "MB/CMP0/CH3/R1/D1/J2001"
747c478bd9Sstevel@tonic-gate  */
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate typedef struct bank_dimm {
777c478bd9Sstevel@tonic-gate 	const char *bd_pat;
787c478bd9Sstevel@tonic-gate 	const char *bd_reppat;
79822fb41dStsien 	const char *bd_subst;
807c478bd9Sstevel@tonic-gate } bank_dimm_t;
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate static const bank_dimm_t bank_dimm[] = {
837c478bd9Sstevel@tonic-gate 	{ "%n%nJ%*4d%n",			" J%*4d%n" },
847c478bd9Sstevel@tonic-gate 	{ "MB/P%*d/%nB%*d:%n%n",		" B%*d/D%*d%n" },
857c478bd9Sstevel@tonic-gate 	{ "MB/P%*d/%nB%*d/D%*d:%n%n",		" B%*d/D%*d%n" },
867c478bd9Sstevel@tonic-gate 	{ "C%*d/P%*d/%nB%*d:%n%n",		" B%*d/D%*d%n" },
877c478bd9Sstevel@tonic-gate 	{ "C%*d/P%*d/%nB%*d/D%*d:%n%n",		" B%*d/D%*d%n" },
887c478bd9Sstevel@tonic-gate 	{ "Slot %*c: %n%nJ%*4d%n",		" J%*4d%n" },
897c478bd9Sstevel@tonic-gate 	{ "%n%nDIMM%*d%n",			" DIMM%*d%n" },
907c478bd9Sstevel@tonic-gate 	{ "MB/%nDIMM%*d MB/DIMM%*d: %n%n",	" DIMM%*d%n" },
917c478bd9Sstevel@tonic-gate 	{ "MB/%nDIMM%*d:%n%n",			" DIMM%*d%n" },
92822fb41dStsien 	{ "MB/CMP%*d/CH%*d%n:%n%n",		" R%*d/D%*d/J%*4d%n",	"/" },
93822fb41dStsien 	{ "MB/CMP%*d/CH%*d%n%n%n",		"/R%*d/D%*d/J%*4d%n" },
941f017db0Sjroberts 	{ "MB/C%*d/P%*d/%nB%*d:%n%n",		" B%*d/D%*d%n" },
951f017db0Sjroberts 	{ "MB/C%*d/P%*d/%nB%*d/D%*d:%n%n",	" B%*d/D%*d%n" },
960cc8ae86Sav 	{ "/MBU_A/MEMB%*d/%n%nMEM%*d%*1c%n",	" MEM%*d%*1c%n" },
970cc8ae86Sav 	{ "/MBU_B/MEMB%*d/%n%nMEM%*d%*1c%n",	" MEM%*d%*1c%n" },
9878ed97a7Sjl 	{ "/MBU_A/%n%nMEM%*d%*1c%n",		" MEM%*d%*1c%n" },
990cc8ae86Sav 	{ "/CMU%*2d/%n%nMEM%*2d%*1c%n",		" MEM%*2d%*1c%n" },
100ef884685Srb 	{ "MB/CMP%*d/BR%*d%n:%n%n",		" CH%*d/D%*d/J%*4d%n", "/" },
101fbd1c0daSsd 	{ "%n%nMB/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n",
102fbd1c0daSsd 	    "MB/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n" },
103fbd1c0daSsd 	{ "%n%nMB/CMP%*d/BR%*d/CH%*d/D%*d%n", "MB/CMP%*d/BR%*d/CH%*d/D%*d%n" },
10413faa912Ssd 	{ "MB/CPU%*d/CMP%*d/BR%*d%n:%n%n",	" CH%*d/D%*d/J%*4d%n", "/"},
10513faa912Ssd 	{ "MB/MEM%*d/CMP%*d/BR%*d%n:%n%n",	" CH%*d/D%*d/J%*4d%n", "/"},
10613faa912Ssd 	{ "%n%nMB/MEM%*d/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n",
10713faa912Ssd 	    "MB/MEM%*d/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n" },
10813faa912Ssd 	{ "%n%nMB/CPU%*d/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n",
10913faa912Ssd 	    "MB/CPU%*d/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n" },
11013faa912Ssd 	{ "%n%nMB/MEM%*d/CMP%*d/BR%*d/CH%*d/D%*d%n",
11113faa912Ssd 	    "MB/MEM%*d/CMP%*d/BR%*d/CH%*d/D%*d%n"  },
11213faa912Ssd 	{ "%n%nMB/CPU%*d/CMP%*d/BR%*d/CH%*d/D%*d%n",
11313faa912Ssd 	    "MB/CPU%*d/CMP%*d/BR%*d/CH%*d/D%*d%n"  },
1147c478bd9Sstevel@tonic-gate 	{ NULL }
1157c478bd9Sstevel@tonic-gate };
1167c478bd9Sstevel@tonic-gate 
117d00f0155Sayznaga /*
1181f4c6dbcSPeter Tribble  * Burst Serengeti-style unums.
119d00f0155Sayznaga  * A DIMM unum string is expected to be in this form:
120d00f0155Sayznaga  * "[/N0/]SB12/P0/B0/D2 [J13500]"
121d00f0155Sayznaga  * A bank unum string is expected to be in this form:
122d00f0155Sayznaga  * "[/N0/]SB12/P0/B0 [J13500, ...]"
123d00f0155Sayznaga  */
124d00f0155Sayznaga static int
mem_unum_burst_sgsc(const char * pat,char *** dimmsp,size_t * ndimmsp)125d00f0155Sayznaga mem_unum_burst_sgsc(const char *pat, char ***dimmsp, size_t *ndimmsp)
126d00f0155Sayznaga {
127d00f0155Sayznaga 	char buf[64];
128d00f0155Sayznaga 	char **dimms;
129d00f0155Sayznaga 	char *base;
130d00f0155Sayznaga 	const char *c;
131d00f0155Sayznaga 	char *copy;
132d00f0155Sayznaga 	size_t copysz;
133d00f0155Sayznaga 	int i;
134d00f0155Sayznaga 
135d00f0155Sayznaga 	/*
136d00f0155Sayznaga 	 * No expansion is required for a DIMM unum
137d00f0155Sayznaga 	 */
138d00f0155Sayznaga 	if (strchr(pat, 'D') != NULL) {
139d00f0155Sayznaga 		dimms = fmd_fmri_alloc(sizeof (char *));
140d00f0155Sayznaga 		dimms[0] = fmd_fmri_strdup(pat);
141d00f0155Sayznaga 		*dimmsp = dimms;
142d00f0155Sayznaga 		*ndimmsp = 1;
143d00f0155Sayznaga 		return (0);
144d00f0155Sayznaga 	}
145d00f0155Sayznaga 
146d00f0155Sayznaga 	/*
147d00f0155Sayznaga 	 * strtok is destructive so we need to work with
148d00f0155Sayznaga 	 * a copy and keep track of the size allocated.
149d00f0155Sayznaga 	 */
150d00f0155Sayznaga 	copysz = strlen(pat) + 1;
151d00f0155Sayznaga 	copy = fmd_fmri_alloc(copysz);
152d00f0155Sayznaga 	(void) strcpy(copy, pat);
153d00f0155Sayznaga 
154d00f0155Sayznaga 	base = strtok(copy, " ");
155d00f0155Sayznaga 
156d00f0155Sayznaga 	/* There are four DIMMs in a bank */
157d00f0155Sayznaga 	dimms = fmd_fmri_alloc(sizeof (char *) * 4);
158d00f0155Sayznaga 
159d00f0155Sayznaga 	for (i = 0; i < 4; i++) {
160d00f0155Sayznaga 		(void) snprintf(buf, sizeof (buf), "%s/D%d", base, i);
161d00f0155Sayznaga 
162*ff638e92SToomas Soome 		if ((c = strtok(NULL, " ")) != NULL) {
163*ff638e92SToomas Soome 			size_t len = strlen(buf);
164*ff638e92SToomas Soome 
165*ff638e92SToomas Soome 			(void) snprintf(buf + len, sizeof (buf) - len,
166*ff638e92SToomas Soome 			    " %s", c);
167*ff638e92SToomas Soome 		}
168d00f0155Sayznaga 
169d00f0155Sayznaga 		dimms[i] = fmd_fmri_strdup(buf);
170d00f0155Sayznaga 	}
171d00f0155Sayznaga 
172d00f0155Sayznaga 	fmd_fmri_free(copy, copysz);
173d00f0155Sayznaga 
174d00f0155Sayznaga 	*dimmsp = dimms;
175d00f0155Sayznaga 	*ndimmsp = 4;
176d00f0155Sayznaga 	return (0);
177d00f0155Sayznaga }
178d00f0155Sayznaga 
179d00f0155Sayznaga 
1807c478bd9Sstevel@tonic-gate /*
1817c478bd9Sstevel@tonic-gate  * Returns 0 (with dimmsp and ndimmsp set) if the unum could be bursted, -1
1827c478bd9Sstevel@tonic-gate  * otherwise.
1837c478bd9Sstevel@tonic-gate  */
184d00f0155Sayznaga static int
mem_unum_burst_pattern(const char * pat,char *** dimmsp,size_t * ndimmsp)185d00f0155Sayznaga mem_unum_burst_pattern(const char *pat, char ***dimmsp, size_t *ndimmsp)
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate 	const bank_dimm_t *bd;
1887c478bd9Sstevel@tonic-gate 	char **dimms = NULL, **newdimms;
1897c478bd9Sstevel@tonic-gate 	size_t ndimms = 0;
1907c478bd9Sstevel@tonic-gate 	const char *c;
1917c478bd9Sstevel@tonic-gate 
192d00f0155Sayznaga 
1937c478bd9Sstevel@tonic-gate 	for (bd = bank_dimm; bd->bd_pat != NULL; bd++) {
1947c478bd9Sstevel@tonic-gate 		int replace, start, matched;
1957c478bd9Sstevel@tonic-gate 		char dimmname[64];
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 		replace = start = matched = -1;
1987c478bd9Sstevel@tonic-gate 		(void) sscanf(pat, bd->bd_pat, &replace, &start, &matched);
1997c478bd9Sstevel@tonic-gate 		if (matched == -1)
2007c478bd9Sstevel@tonic-gate 			continue;
2017c478bd9Sstevel@tonic-gate 		(void) strlcpy(dimmname, pat, sizeof (dimmname));
202822fb41dStsien 		if (bd->bd_subst != NULL) {
203822fb41dStsien 			(void) strlcpy(dimmname+replace, bd->bd_subst,
204822fb41dStsien 			    sizeof (dimmname) - strlen(bd->bd_subst));
205822fb41dStsien 			replace += strlen(bd->bd_subst);
206822fb41dStsien 		}
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 		c = pat + start;
2097c478bd9Sstevel@tonic-gate 		while (*c != '\0') {
2107c478bd9Sstevel@tonic-gate 			int dimmlen = -1;
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 			(void) sscanf(c, bd->bd_reppat, &dimmlen);
2137c478bd9Sstevel@tonic-gate 			if (dimmlen == -1)
2147c478bd9Sstevel@tonic-gate 				break;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 			while (*c == ' ') {
2177c478bd9Sstevel@tonic-gate 				c++;
2187c478bd9Sstevel@tonic-gate 				dimmlen--;
2197c478bd9Sstevel@tonic-gate 			}
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 			if (dimmlen > sizeof (dimmname) - replace)
2227c478bd9Sstevel@tonic-gate 				break;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 			(void) strlcpy(dimmname + replace, c, dimmlen + 1);
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 			newdimms = fmd_fmri_alloc(sizeof (char *) *
2277c478bd9Sstevel@tonic-gate 			    (ndimms + 1));
2287c478bd9Sstevel@tonic-gate 			if (ndimms != 0) {
2297c478bd9Sstevel@tonic-gate 				bcopy(dimms, newdimms, sizeof (char *) *
2307c478bd9Sstevel@tonic-gate 				    ndimms);
2317c478bd9Sstevel@tonic-gate 				fmd_fmri_free(dimms, sizeof (char *) * ndimms);
2327c478bd9Sstevel@tonic-gate 			}
2337c478bd9Sstevel@tonic-gate 			newdimms[ndimms++] = fmd_fmri_strdup(dimmname);
2347c478bd9Sstevel@tonic-gate 			dimms = newdimms;
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 			c += dimmlen;
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 			if (*c != ' ' && *c != '\0')
2397c478bd9Sstevel@tonic-gate 				break;
2407c478bd9Sstevel@tonic-gate 		}
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 		if (*c != '\0')
2437c478bd9Sstevel@tonic-gate 			break;
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 		*dimmsp = dimms;
2467c478bd9Sstevel@tonic-gate 		*ndimmsp = ndimms;
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 		return (0);
2497c478bd9Sstevel@tonic-gate 	}
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	mem_strarray_free(dimms, ndimms);
252d00f0155Sayznaga 
2536684e119Spothier 	/*
2546684e119Spothier 	 * Set errno to ENOTSUP and return -1. This allows support for DIMMs
2556684e119Spothier 	 * with unknown unum strings and/or serial numbers. The only consumer
2566684e119Spothier 	 * of mem_unum_burst_pattern() that cares/checks for the returned
2576684e119Spothier 	 * errno is fmd_fmri_expand().
2586684e119Spothier 	 */
2596684e119Spothier 	return (fmd_fmri_set_errno(ENOTSUP));
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate 
262d00f0155Sayznaga int
mem_unum_burst(const char * pat,char *** dimmsp,size_t * ndimmsp)263d00f0155Sayznaga mem_unum_burst(const char *pat, char ***dimmsp, size_t *ndimmsp)
264d00f0155Sayznaga {
265d00f0155Sayznaga 	const char *platform = fmd_fmri_get_platform();
266d00f0155Sayznaga 
267d00f0155Sayznaga 	/*
2681f4c6dbcSPeter Tribble 	 * Call mem_unum_burst_sgsc() for Serengeti and
269d00f0155Sayznaga 	 * Lightweight 8 platforms.  Call mem_unum_burst_pattern()
270d00f0155Sayznaga 	 * for all other platforms.
271d00f0155Sayznaga 	 */
2721f4c6dbcSPeter Tribble 	if (strcmp(platform, "SUNW,Sun-Fire") == 0 ||
273d00f0155Sayznaga 	    strcmp(platform, "SUNW,Netra-T12") == 0)
274d00f0155Sayznaga 		return (mem_unum_burst_sgsc(pat, dimmsp, ndimmsp));
275d00f0155Sayznaga 	else
276d00f0155Sayznaga 		return (mem_unum_burst_pattern(pat, dimmsp, ndimmsp));
277d00f0155Sayznaga }
278d00f0155Sayznaga 
2797c478bd9Sstevel@tonic-gate /*
2807c478bd9Sstevel@tonic-gate  * The unum containership operation is designed to tell the caller whether a
2817c478bd9Sstevel@tonic-gate  * given FMRI contains another.  In the case of this plugin, we tell the caller
2827c478bd9Sstevel@tonic-gate  * whether a given memory FMRI (usually a bank) contains another (usually a
2837c478bd9Sstevel@tonic-gate  * DIMM).  We do this in one of two ways, depending on the platform.  For most
2847c478bd9Sstevel@tonic-gate  * platforms, we can use the bursting routine to generate the list of member
2857c478bd9Sstevel@tonic-gate  * unums from the container unum.  Membership can then be determined by
2867c478bd9Sstevel@tonic-gate  * searching the bursted list for the containee's unum.
2877c478bd9Sstevel@tonic-gate  *
2887c478bd9Sstevel@tonic-gate  * Some platforms, however, cannot be bursted, as their bank unums do not
2897c478bd9Sstevel@tonic-gate  * contain all of the information needed to generate the complete list of
2907c478bd9Sstevel@tonic-gate  * member DIMM unums.  For these unums, we must make do with a substring
2917c478bd9Sstevel@tonic-gate  * comparison.
2927c478bd9Sstevel@tonic-gate  */
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate static int
unum_contains_bypat(const char * erunum,const char * eeunum)2957c478bd9Sstevel@tonic-gate unum_contains_bypat(const char *erunum, const char *eeunum)
2967c478bd9Sstevel@tonic-gate {
2977c478bd9Sstevel@tonic-gate 	char **ernms, **eenms;
298749f21d3Swesolows 	size_t nernms, neenms;
2997c478bd9Sstevel@tonic-gate 	int i, j, rv = 1;
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	if (mem_unum_burst(erunum, &ernms, &nernms) < 0)
3027c478bd9Sstevel@tonic-gate 		return (fmd_fmri_set_errno(EINVAL));
3037c478bd9Sstevel@tonic-gate 	if (mem_unum_burst(eeunum, &eenms, &neenms) < 0) {
3047c478bd9Sstevel@tonic-gate 		mem_strarray_free(ernms, nernms);
3057c478bd9Sstevel@tonic-gate 		return (fmd_fmri_set_errno(EINVAL));
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	for (i = 0; i < neenms; i++) {
3097c478bd9Sstevel@tonic-gate 		for (j = 0; j < nernms; j++) {
3107c478bd9Sstevel@tonic-gate 			if (strcmp(eenms[i], ernms[j]) == 0)
3117c478bd9Sstevel@tonic-gate 				break;
3127c478bd9Sstevel@tonic-gate 		}
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 		if (j == nernms) {
3157c478bd9Sstevel@tonic-gate 			/*
3167c478bd9Sstevel@tonic-gate 			 * This DIMM was not found in the container.
3177c478bd9Sstevel@tonic-gate 			 */
3187c478bd9Sstevel@tonic-gate 			rv = 0;
3197c478bd9Sstevel@tonic-gate 			break;
3207c478bd9Sstevel@tonic-gate 		}
3217c478bd9Sstevel@tonic-gate 	}
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	mem_strarray_free(ernms, nernms);
3247c478bd9Sstevel@tonic-gate 	mem_strarray_free(eenms, neenms);
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	return (rv);
3277c478bd9Sstevel@tonic-gate }
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate static int
unum_strip_one_jnum(const char * unum,uint_t * endp)3307c478bd9Sstevel@tonic-gate unum_strip_one_jnum(const char *unum, uint_t *endp)
3317c478bd9Sstevel@tonic-gate {
3327c478bd9Sstevel@tonic-gate 	char *c;
3337c478bd9Sstevel@tonic-gate 	int i;
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	if ((c = strrchr(unum, 'J')) == NULL)
3367c478bd9Sstevel@tonic-gate 		return (0);
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 	while (c > unum && isspace(c[-1]))
3397c478bd9Sstevel@tonic-gate 		c--;
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	(void) sscanf(c, " J%*[0-9] %n", &i);
3427c478bd9Sstevel@tonic-gate 	if (i == 0 || (uintptr_t)(c - unum) + i != strlen(unum))
3437c478bd9Sstevel@tonic-gate 		return (0);
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	*endp = (uint_t)(c - unum);
3467c478bd9Sstevel@tonic-gate 	return (1);
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate static int
unum_contains_bysubstr(const char * erunum,const char * eeunum)3517c478bd9Sstevel@tonic-gate unum_contains_bysubstr(const char *erunum, const char *eeunum)
3527c478bd9Sstevel@tonic-gate {
3537c478bd9Sstevel@tonic-gate 	uint_t erlen, eelen;
3545f25dc2aSgavinm 	int nojnumstrip = 0;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	/*
3577c478bd9Sstevel@tonic-gate 	 * This comparison method is only known to work on specific types of
3587c478bd9Sstevel@tonic-gate 	 * unums.  Check for those types here.
3597c478bd9Sstevel@tonic-gate 	 */
3607c478bd9Sstevel@tonic-gate 	if ((strncmp(erunum, "/N", 2) != 0 && strncmp(erunum, "/IO", 3) != 0 &&
3617c478bd9Sstevel@tonic-gate 	    strncmp(erunum, "/SB", 3) != 0) ||
3627c478bd9Sstevel@tonic-gate 	    (strncmp(eeunum, "/N", 2) != 0 && strncmp(eeunum, "/IO", 3) != 0 &&
3635f25dc2aSgavinm 	    strncmp(eeunum, "/SB", 3) != 0)) {
3648a40a695Sgavinm 		if (ISHCUNUM(erunum) && ISHCUNUM(eeunum)) {
3655f25dc2aSgavinm 			nojnumstrip = 1;
3668a40a695Sgavinm 			erlen = strlen(erunum);
3678a40a695Sgavinm 			eelen = strlen(eeunum);
3688a40a695Sgavinm 		} else {
3695f25dc2aSgavinm 			return (fmd_fmri_set_errno(EINVAL));
3708a40a695Sgavinm 		}
3715f25dc2aSgavinm 	}
3727c478bd9Sstevel@tonic-gate 
3735f25dc2aSgavinm 	if (!nojnumstrip) {
3745f25dc2aSgavinm 		erlen = unum_strip_one_jnum(erunum, &erlen) ?
3755f25dc2aSgavinm 		    erlen : strlen(erunum);
3765f25dc2aSgavinm 		eelen = unum_strip_one_jnum(eeunum, &eelen) ?
3775f25dc2aSgavinm 		    eelen : strlen(eeunum);
3785f25dc2aSgavinm 	}
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	return (strncmp(erunum, eeunum, MIN(erlen, eelen)) == 0);
3817c478bd9Sstevel@tonic-gate }
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate typedef int unum_cmptor_f(const char *, const char *);
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate static unum_cmptor_f *const unum_cmptors[] = {
3867c478bd9Sstevel@tonic-gate 	unum_contains_bypat,
3877c478bd9Sstevel@tonic-gate 	unum_contains_bysubstr
3887c478bd9Sstevel@tonic-gate };
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate int
mem_unum_contains(const char * erunum,const char * eeunum)3917c478bd9Sstevel@tonic-gate mem_unum_contains(const char *erunum, const char *eeunum)
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate 	static int cmptor = 0;
3947c478bd9Sstevel@tonic-gate 	int rc;
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	while (isspace(*erunum))
3977c478bd9Sstevel@tonic-gate 		erunum++;
3987c478bd9Sstevel@tonic-gate 	while (isspace(*eeunum))
3997c478bd9Sstevel@tonic-gate 		eeunum++;
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	if ((rc = unum_cmptors[cmptor](erunum, eeunum)) >= 0)
4027c478bd9Sstevel@tonic-gate 		return (rc);
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	if ((rc = unum_cmptors[cmptor == 0](erunum, eeunum)) >= 0) {
4057c478bd9Sstevel@tonic-gate 		/*
4067c478bd9Sstevel@tonic-gate 		 * We succeeded with the non-default comparator.  Change the
4077c478bd9Sstevel@tonic-gate 		 * default so we use the correct one next time.
4087c478bd9Sstevel@tonic-gate 		 */
4097c478bd9Sstevel@tonic-gate 		cmptor = (cmptor == 0);
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	return (rc);
4137c478bd9Sstevel@tonic-gate }
4147aec1d6eScindi 
4157aec1d6eScindi /*
4167aec1d6eScindi  * If an asru has a unum string that is an hc path string then return
4177aec1d6eScindi  * a new nvl (to be freed by the caller) that is a duplicate of the
4187aec1d6eScindi  * original but with an additional member of a reconstituted hc fmri.
4197aec1d6eScindi  */
4207aec1d6eScindi int
mem_unum_rewrite(nvlist_t * nvl,nvlist_t ** rnvl)4217aec1d6eScindi mem_unum_rewrite(nvlist_t *nvl, nvlist_t **rnvl)
4227aec1d6eScindi {
4237aec1d6eScindi 	int err;
4247aec1d6eScindi 	char *unumstr;
4257aec1d6eScindi 	nvlist_t *unum;
4267aec1d6eScindi 	struct topo_hdl *thp;
4277aec1d6eScindi 
4287aec1d6eScindi 	if (nvlist_lookup_string(nvl, FM_FMRI_MEM_UNUM, &unumstr) != 0 ||
4295f25dc2aSgavinm 	    !ISHCUNUM(unumstr))
4307aec1d6eScindi 		return (0);
4317aec1d6eScindi 
43224db4641Seschrock 	if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL)
43324db4641Seschrock 		return (EINVAL);
4347aec1d6eScindi 
43524db4641Seschrock 	if (topo_fmri_str2nvl(thp, unumstr, &unum, &err) != 0) {
43624db4641Seschrock 		fmd_fmri_topo_rele(thp);
4377aec1d6eScindi 		return (EINVAL);
43824db4641Seschrock 	}
43924db4641Seschrock 
44024db4641Seschrock 	fmd_fmri_topo_rele(thp);
4417aec1d6eScindi 
4427aec1d6eScindi 	if ((err = nvlist_dup(nvl, rnvl, 0)) != 0) {
4437aec1d6eScindi 		nvlist_free(unum);
4447aec1d6eScindi 		return (err);
4457aec1d6eScindi 	}
4467aec1d6eScindi 
4477aec1d6eScindi 	err = nvlist_add_nvlist(*rnvl, FM_FMRI_MEM_UNUM "-fmri", unum);
4487aec1d6eScindi 	nvlist_free(unum);
4497aec1d6eScindi 
4507aec1d6eScindi 	if (err != 0)
4517aec1d6eScindi 		nvlist_free(*rnvl);
4527aec1d6eScindi 
4537aec1d6eScindi 	return (err);
4547aec1d6eScindi }
455