xref: /onnv-gate/usr/src/uts/intel/os/fmsmb.c (revision 10942:eaa343de0d06)
1*10942STom.Pothier@Sun.COM /*
2*10942STom.Pothier@Sun.COM  * CDDL HEADER START
3*10942STom.Pothier@Sun.COM  *
4*10942STom.Pothier@Sun.COM  * The contents of this file are subject to the terms of the
5*10942STom.Pothier@Sun.COM  * Common Development and Distribution License (the "License").
6*10942STom.Pothier@Sun.COM  * You may not use this file except in compliance with the License.
7*10942STom.Pothier@Sun.COM  *
8*10942STom.Pothier@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10942STom.Pothier@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*10942STom.Pothier@Sun.COM  * See the License for the specific language governing permissions
11*10942STom.Pothier@Sun.COM  * and limitations under the License.
12*10942STom.Pothier@Sun.COM  *
13*10942STom.Pothier@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*10942STom.Pothier@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10942STom.Pothier@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*10942STom.Pothier@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*10942STom.Pothier@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*10942STom.Pothier@Sun.COM  *
19*10942STom.Pothier@Sun.COM  * CDDL HEADER END
20*10942STom.Pothier@Sun.COM  */
21*10942STom.Pothier@Sun.COM /*
22*10942STom.Pothier@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*10942STom.Pothier@Sun.COM  * Use is subject to license terms.
24*10942STom.Pothier@Sun.COM  */
25*10942STom.Pothier@Sun.COM 
26*10942STom.Pothier@Sun.COM #include <sys/types.h>
27*10942STom.Pothier@Sun.COM #include <sys/time.h>
28*10942STom.Pothier@Sun.COM #include <sys/nvpair.h>
29*10942STom.Pothier@Sun.COM #include <sys/cmn_err.h>
30*10942STom.Pothier@Sun.COM #include <sys/fm/util.h>
31*10942STom.Pothier@Sun.COM #include <sys/fm/protocol.h>
32*10942STom.Pothier@Sun.COM #include <sys/smbios.h>
33*10942STom.Pothier@Sun.COM #include <sys/smbios_impl.h>
34*10942STom.Pothier@Sun.COM 
35*10942STom.Pothier@Sun.COM /*
36*10942STom.Pothier@Sun.COM  * Variable used to determine if the x86 generic topology enumerator will
37*10942STom.Pothier@Sun.COM  * revert to legacy enumeration. I.E. Big Kill Switch... tunable via
38*10942STom.Pothier@Sun.COM  * /etc/system
39*10942STom.Pothier@Sun.COM  */
40*10942STom.Pothier@Sun.COM int x86gentopo_legacy = 0;
41*10942STom.Pothier@Sun.COM 
42*10942STom.Pothier@Sun.COM #define	MC		0
43*10942STom.Pothier@Sun.COM #define	PROC		1
44*10942STom.Pothier@Sun.COM #define	MAX_PAIRS	20
45*10942STom.Pothier@Sun.COM #define	MAX_CONT	40
46*10942STom.Pothier@Sun.COM 
47*10942STom.Pothier@Sun.COM typedef struct bbindex  {
48*10942STom.Pothier@Sun.COM 	int count;
49*10942STom.Pothier@Sun.COM 	uint16_t index[MAX_PAIRS];
50*10942STom.Pothier@Sun.COM } bbindex_t;
51*10942STom.Pothier@Sun.COM 
52*10942STom.Pothier@Sun.COM /*
53*10942STom.Pothier@Sun.COM  * the enum values come from DMTF
54*10942STom.Pothier@Sun.COM  */
55*10942STom.Pothier@Sun.COM typedef enum baseb {
56*10942STom.Pothier@Sun.COM 	BB_BAD = 0,		/* There is no bb value 0 */
57*10942STom.Pothier@Sun.COM 	BB_UNKNOWN,		/* Unknown */
58*10942STom.Pothier@Sun.COM 	BB_OTHER,		/* Other */
59*10942STom.Pothier@Sun.COM 	BB_BLADE,		/* Server Blade */
60*10942STom.Pothier@Sun.COM 	BB_CONNSW,		/* Connectivity Switch */
61*10942STom.Pothier@Sun.COM 	BB_SMM,			/* System Management Module */
62*10942STom.Pothier@Sun.COM 	BB_PROCMOD,		/* Processor Module */
63*10942STom.Pothier@Sun.COM 	BB_IOMOD,		/* I/O Module */
64*10942STom.Pothier@Sun.COM 	BB_MEMMOD,		/* Memory Module */
65*10942STom.Pothier@Sun.COM 	BB_DBOARD,		/* Daughter Board */
66*10942STom.Pothier@Sun.COM 	BB_MBOARD,		/* Motherboard */
67*10942STom.Pothier@Sun.COM 	BB_PROCMMOD,		/* Processor/Memory Module */
68*10942STom.Pothier@Sun.COM 	BB_PROCIOMOD,		/* Processor/IO Module */
69*10942STom.Pothier@Sun.COM 	BB_ICONNBD		/* Interconnect Board */
70*10942STom.Pothier@Sun.COM } bbd_t;
71*10942STom.Pothier@Sun.COM 
72*10942STom.Pothier@Sun.COM static struct bboard_type {
73*10942STom.Pothier@Sun.COM 	bbd_t		baseb;
74*10942STom.Pothier@Sun.COM 	const char	*name;
75*10942STom.Pothier@Sun.COM } bbd_type[] = {
76*10942STom.Pothier@Sun.COM 	{BB_BAD,		NULL},
77*10942STom.Pothier@Sun.COM 	{BB_UNKNOWN,		"unknown"},
78*10942STom.Pothier@Sun.COM 	{BB_OTHER,		"other"},
79*10942STom.Pothier@Sun.COM 	{BB_BLADE,		"systemboard"},
80*10942STom.Pothier@Sun.COM 	{BB_CONNSW,		"connswitch"},
81*10942STom.Pothier@Sun.COM 	{BB_SMM,		"smmodule"},
82*10942STom.Pothier@Sun.COM 	{BB_PROCMOD,		"cpuboard"},
83*10942STom.Pothier@Sun.COM 	{BB_IOMOD,		"ioboard"},
84*10942STom.Pothier@Sun.COM 	{BB_MEMMOD,		"memboard"},
85*10942STom.Pothier@Sun.COM 	{BB_DBOARD,		"systemboard"},
86*10942STom.Pothier@Sun.COM 	{BB_MBOARD,		"motherboard"},
87*10942STom.Pothier@Sun.COM 	{BB_PROCMMOD,		"systemboard"},
88*10942STom.Pothier@Sun.COM 	{BB_PROCIOMOD,		"systemboard"},
89*10942STom.Pothier@Sun.COM 	{BB_ICONNBD,		"systemboard"}
90*10942STom.Pothier@Sun.COM };
91*10942STom.Pothier@Sun.COM 
92*10942STom.Pothier@Sun.COM typedef struct smbs_con_ids {
93*10942STom.Pothier@Sun.COM 	int id;
94*10942STom.Pothier@Sun.COM 	int inst;
95*10942STom.Pothier@Sun.COM 	int cont_count;
96*10942STom.Pothier@Sun.COM 	uint16_t **cont_ids;
97*10942STom.Pothier@Sun.COM 	int cont_by_id;
98*10942STom.Pothier@Sun.COM 	int visited;
99*10942STom.Pothier@Sun.COM } smbs_con_ids_t;
100*10942STom.Pothier@Sun.COM 
101*10942STom.Pothier@Sun.COM typedef struct smbs_cnt {
102*10942STom.Pothier@Sun.COM 	int type;			/* SMBIOS stucture type */
103*10942STom.Pothier@Sun.COM 	int count;			/* number of table entries */
104*10942STom.Pothier@Sun.COM 	smbs_con_ids_t **ids;		/* SMBIOS table entry id(s) */
105*10942STom.Pothier@Sun.COM } smbs_cnt_t;
106*10942STom.Pothier@Sun.COM 
107*10942STom.Pothier@Sun.COM /*
108*10942STom.Pothier@Sun.COM  * dynamically allocate the storage for the smbs_cnt_t
109*10942STom.Pothier@Sun.COM  */
110*10942STom.Pothier@Sun.COM static smbs_cnt_t *
111*10942STom.Pothier@Sun.COM smb_create_strcnt(int count)
112*10942STom.Pothier@Sun.COM {
113*10942STom.Pothier@Sun.COM 	smbs_cnt_t *types = NULL;
114*10942STom.Pothier@Sun.COM 	int i, j;
115*10942STom.Pothier@Sun.COM 
116*10942STom.Pothier@Sun.COM 	types = kmem_zalloc(sizeof (smbs_cnt_t), KM_SLEEP);
117*10942STom.Pothier@Sun.COM 
118*10942STom.Pothier@Sun.COM 	types->ids = (smbs_con_ids_t **)kmem_zalloc(
119*10942STom.Pothier@Sun.COM 	    count * sizeof (smbs_con_ids_t *), KM_SLEEP);
120*10942STom.Pothier@Sun.COM 
121*10942STom.Pothier@Sun.COM 	for (i = 0; i < count; i++) {
122*10942STom.Pothier@Sun.COM 		types->ids[i] = (smbs_con_ids_t *)kmem_zalloc(
123*10942STom.Pothier@Sun.COM 		    sizeof (smbs_con_ids_t), KM_SLEEP);
124*10942STom.Pothier@Sun.COM 	}
125*10942STom.Pothier@Sun.COM 
126*10942STom.Pothier@Sun.COM 	for (i = 0; i < count; i++) {
127*10942STom.Pothier@Sun.COM 		types->ids[i]->cont_ids = (uint16_t **)kmem_zalloc(
128*10942STom.Pothier@Sun.COM 		    MAX_CONT * sizeof (uint16_t *), KM_SLEEP);
129*10942STom.Pothier@Sun.COM 	}
130*10942STom.Pothier@Sun.COM 
131*10942STom.Pothier@Sun.COM 	for (i = 0; i < count; i++) {
132*10942STom.Pothier@Sun.COM 		for (j = 0; j < MAX_CONT; j++) {
133*10942STom.Pothier@Sun.COM 			types->ids[i]->cont_ids[j] = (uint16_t *)kmem_zalloc(
134*10942STom.Pothier@Sun.COM 			    sizeof (uint16_t), KM_SLEEP);
135*10942STom.Pothier@Sun.COM 		}
136*10942STom.Pothier@Sun.COM 	}
137*10942STom.Pothier@Sun.COM 	return (types);
138*10942STom.Pothier@Sun.COM }
139*10942STom.Pothier@Sun.COM 
140*10942STom.Pothier@Sun.COM /*
141*10942STom.Pothier@Sun.COM  * free the smbs_cnt_t memory
142*10942STom.Pothier@Sun.COM  */
143*10942STom.Pothier@Sun.COM static void
144*10942STom.Pothier@Sun.COM smb_free_strcnt(smbs_cnt_t *types, int count)
145*10942STom.Pothier@Sun.COM {
146*10942STom.Pothier@Sun.COM 	int i, j;
147*10942STom.Pothier@Sun.COM 
148*10942STom.Pothier@Sun.COM 	if (types == NULL)
149*10942STom.Pothier@Sun.COM 		return;
150*10942STom.Pothier@Sun.COM 
151*10942STom.Pothier@Sun.COM 	for (i = 0; i < count; i++) {
152*10942STom.Pothier@Sun.COM 		for (j = 0; j < MAX_CONT; j++) {
153*10942STom.Pothier@Sun.COM 			if (types->ids[i]->cont_ids[j] != NULL)
154*10942STom.Pothier@Sun.COM 				kmem_free(types->ids[i]->cont_ids[j],
155*10942STom.Pothier@Sun.COM 				    sizeof (uint16_t));
156*10942STom.Pothier@Sun.COM 		}
157*10942STom.Pothier@Sun.COM 	}
158*10942STom.Pothier@Sun.COM 
159*10942STom.Pothier@Sun.COM 	for (i = 0; i < count; i++) {
160*10942STom.Pothier@Sun.COM 		if (types->ids[i]->cont_ids != NULL)
161*10942STom.Pothier@Sun.COM 			kmem_free(types->ids[i]->cont_ids,
162*10942STom.Pothier@Sun.COM 			    MAX_CONT * sizeof (uint16_t *));
163*10942STom.Pothier@Sun.COM 	}
164*10942STom.Pothier@Sun.COM 
165*10942STom.Pothier@Sun.COM 	for (i = 0; i < count; i++) {
166*10942STom.Pothier@Sun.COM 		if (types->ids[i] != NULL)
167*10942STom.Pothier@Sun.COM 			kmem_free(types->ids[i], sizeof (smbs_con_ids_t));
168*10942STom.Pothier@Sun.COM 	}
169*10942STom.Pothier@Sun.COM 
170*10942STom.Pothier@Sun.COM 	if (types->ids != NULL)
171*10942STom.Pothier@Sun.COM 		kmem_free(types->ids, count * sizeof (smbs_con_ids_t *));
172*10942STom.Pothier@Sun.COM 
173*10942STom.Pothier@Sun.COM 	if (types != NULL)
174*10942STom.Pothier@Sun.COM 		kmem_free(types, sizeof (smbs_cnt_t));
175*10942STom.Pothier@Sun.COM 
176*10942STom.Pothier@Sun.COM }
177*10942STom.Pothier@Sun.COM 
178*10942STom.Pothier@Sun.COM /*
179*10942STom.Pothier@Sun.COM  * count number of the structure type in the ksmbios
180*10942STom.Pothier@Sun.COM  */
181*10942STom.Pothier@Sun.COM static int
182*10942STom.Pothier@Sun.COM smb_cnttypes(smbios_hdl_t *shp, int type)
183*10942STom.Pothier@Sun.COM {
184*10942STom.Pothier@Sun.COM 	const smb_struct_t *sp = shp->sh_structs;
185*10942STom.Pothier@Sun.COM 	int nstructs = shp->sh_nstructs;
186*10942STom.Pothier@Sun.COM 	int i;
187*10942STom.Pothier@Sun.COM 	int cnt = 0;
188*10942STom.Pothier@Sun.COM 
189*10942STom.Pothier@Sun.COM 	for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
190*10942STom.Pothier@Sun.COM 		if (sp->smbst_hdr->smbh_type == type)
191*10942STom.Pothier@Sun.COM 			cnt++;
192*10942STom.Pothier@Sun.COM 	}
193*10942STom.Pothier@Sun.COM 	return (cnt);
194*10942STom.Pothier@Sun.COM }
195*10942STom.Pothier@Sun.COM 
196*10942STom.Pothier@Sun.COM static void
197*10942STom.Pothier@Sun.COM smb_strcnt(smbios_hdl_t *shp, smbs_cnt_t *stype)
198*10942STom.Pothier@Sun.COM {
199*10942STom.Pothier@Sun.COM 	const smb_struct_t *sp = shp->sh_structs;
200*10942STom.Pothier@Sun.COM 	int nstructs = shp->sh_nstructs;
201*10942STom.Pothier@Sun.COM 	smbios_bboard_t bb;
202*10942STom.Pothier@Sun.COM 	int i, cnt;
203*10942STom.Pothier@Sun.COM 	int mb_cnt = 0;
204*10942STom.Pothier@Sun.COM 	int cpub_cnt = 0;
205*10942STom.Pothier@Sun.COM 	int sysb_cnt = 0;
206*10942STom.Pothier@Sun.COM 	int memb_cnt = 0;
207*10942STom.Pothier@Sun.COM 	int iob_cnt = 0;
208*10942STom.Pothier@Sun.COM 	int inst = 0;
209*10942STom.Pothier@Sun.COM 	int rc = 0;
210*10942STom.Pothier@Sun.COM 
211*10942STom.Pothier@Sun.COM 	for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
212*10942STom.Pothier@Sun.COM 		if (sp->smbst_hdr->smbh_type == stype->type) {
213*10942STom.Pothier@Sun.COM 			stype->ids[cnt]->id = sp->smbst_hdr->smbh_hdl;
214*10942STom.Pothier@Sun.COM 			stype->ids[cnt]->inst = cnt;
215*10942STom.Pothier@Sun.COM 			stype->ids[cnt]->visited = 0;
216*10942STom.Pothier@Sun.COM 			stype->ids[cnt]->cont_by_id = -1;
217*10942STom.Pothier@Sun.COM 			if (stype->type == SMB_TYPE_BASEBOARD) {
218*10942STom.Pothier@Sun.COM 				rc = smbios_info_bboard(shp,
219*10942STom.Pothier@Sun.COM 				    stype->ids[cnt]->id, &bb);
220*10942STom.Pothier@Sun.COM 				if (rc == 0) {
221*10942STom.Pothier@Sun.COM 					switch (bb.smbb_type) {
222*10942STom.Pothier@Sun.COM 						case SMB_BBT_PROC :
223*10942STom.Pothier@Sun.COM 							inst = cpub_cnt++;
224*10942STom.Pothier@Sun.COM 							break;
225*10942STom.Pothier@Sun.COM 						case SMB_BBT_IO :
226*10942STom.Pothier@Sun.COM 							inst = iob_cnt++;
227*10942STom.Pothier@Sun.COM 							break;
228*10942STom.Pothier@Sun.COM 						case SMB_BBT_MEM :
229*10942STom.Pothier@Sun.COM 							inst = memb_cnt++;
230*10942STom.Pothier@Sun.COM 							break;
231*10942STom.Pothier@Sun.COM 						case SMB_BBT_MOTHER :
232*10942STom.Pothier@Sun.COM 							inst = mb_cnt++;
233*10942STom.Pothier@Sun.COM 							break;
234*10942STom.Pothier@Sun.COM 						default:
235*10942STom.Pothier@Sun.COM 							/*
236*10942STom.Pothier@Sun.COM 							 * SMB_BBT_UNKNOWN
237*10942STom.Pothier@Sun.COM 							 * SMB_BBT_OTHER
238*10942STom.Pothier@Sun.COM 							 * SMB_BBT_SBLADE
239*10942STom.Pothier@Sun.COM 							 * SMB_BBT_CSWITCH
240*10942STom.Pothier@Sun.COM 							 * SMB_BBT_SMM
241*10942STom.Pothier@Sun.COM 							 * SMB_BBT_DAUGHTER
242*10942STom.Pothier@Sun.COM 							 * SMB_BBT_PROCMEM
243*10942STom.Pothier@Sun.COM 							 * SMB_BBT_PROCIO
244*10942STom.Pothier@Sun.COM 							 * SMB_BBT_INTER
245*10942STom.Pothier@Sun.COM 							 */
246*10942STom.Pothier@Sun.COM 							inst = sysb_cnt++;
247*10942STom.Pothier@Sun.COM 							break;
248*10942STom.Pothier@Sun.COM 					}
249*10942STom.Pothier@Sun.COM 					stype->ids[cnt]->inst = inst;
250*10942STom.Pothier@Sun.COM 				}
251*10942STom.Pothier@Sun.COM 			}
252*10942STom.Pothier@Sun.COM 			cnt++;
253*10942STom.Pothier@Sun.COM 		}
254*10942STom.Pothier@Sun.COM 	}
255*10942STom.Pothier@Sun.COM 	stype->count = cnt;
256*10942STom.Pothier@Sun.COM }
257*10942STom.Pothier@Sun.COM 
258*10942STom.Pothier@Sun.COM /*
259*10942STom.Pothier@Sun.COM  * Go through the smbios structures looking for type 2. Fill in
260*10942STom.Pothier@Sun.COM  * the cont_id and cont_by_id for each type 2
261*10942STom.Pothier@Sun.COM  *
262*10942STom.Pothier@Sun.COM  */
263*10942STom.Pothier@Sun.COM static void
264*10942STom.Pothier@Sun.COM smb_bb_contains(smbios_hdl_t *shp, smbs_cnt_t *stype)
265*10942STom.Pothier@Sun.COM {
266*10942STom.Pothier@Sun.COM 	int i, j, cnt, c;
267*10942STom.Pothier@Sun.COM 	uint_t cont_count;
268*10942STom.Pothier@Sun.COM 	const smb_struct_t *spt;
269*10942STom.Pothier@Sun.COM 	smbios_bboard_t smb_bb;
270*10942STom.Pothier@Sun.COM 	uint16_t bb_id, cont_id;
271*10942STom.Pothier@Sun.COM 	uint_t cont_len;
272*10942STom.Pothier@Sun.COM 	id_t *cont_hdl = NULL;
273*10942STom.Pothier@Sun.COM 	int rc;
274*10942STom.Pothier@Sun.COM 
275*10942STom.Pothier@Sun.COM 	for (cnt = 0; cnt < stype->count; cnt++) {
276*10942STom.Pothier@Sun.COM 		bb_id = stype->ids[cnt]->id;
277*10942STom.Pothier@Sun.COM 		(void) smbios_info_bboard(shp, stype->ids[cnt]->id, &smb_bb);
278*10942STom.Pothier@Sun.COM 		cont_count = (uint_t)smb_bb.smbb_contn;
279*10942STom.Pothier@Sun.COM 		if (cont_count == 0) {
280*10942STom.Pothier@Sun.COM 			continue;
281*10942STom.Pothier@Sun.COM 		}
282*10942STom.Pothier@Sun.COM 
283*10942STom.Pothier@Sun.COM 		cont_len = sizeof (id_t);
284*10942STom.Pothier@Sun.COM 		cont_hdl = kmem_zalloc(cont_count * cont_len, KM_SLEEP);
285*10942STom.Pothier@Sun.COM 		if (cont_hdl == NULL)
286*10942STom.Pothier@Sun.COM 			continue;
287*10942STom.Pothier@Sun.COM 
288*10942STom.Pothier@Sun.COM 		rc = smbios_info_contains(shp, stype->ids[cnt]->id,
289*10942STom.Pothier@Sun.COM 		    cont_count, cont_hdl);
290*10942STom.Pothier@Sun.COM 		if (rc > SMB_CONT_MAX) {
291*10942STom.Pothier@Sun.COM 			kmem_free(cont_hdl, cont_count * cont_len);
292*10942STom.Pothier@Sun.COM 			continue;
293*10942STom.Pothier@Sun.COM 		}
294*10942STom.Pothier@Sun.COM 		cont_count = MIN(rc, cont_count);
295*10942STom.Pothier@Sun.COM 
296*10942STom.Pothier@Sun.COM 		/*
297*10942STom.Pothier@Sun.COM 		 * fill in the type 2 and type 4 ids which are
298*10942STom.Pothier@Sun.COM 		 * contained in this type 2
299*10942STom.Pothier@Sun.COM 		 */
300*10942STom.Pothier@Sun.COM 		c = 0;
301*10942STom.Pothier@Sun.COM 		for (j = 0; j < cont_count; j++) {
302*10942STom.Pothier@Sun.COM 			cont_id = (uint16_t)cont_hdl[j];
303*10942STom.Pothier@Sun.COM 			spt = smb_lookup_id(shp, cont_id);
304*10942STom.Pothier@Sun.COM 			if (spt->smbst_hdr->smbh_type == SMB_TYPE_BASEBOARD ||
305*10942STom.Pothier@Sun.COM 			    spt->smbst_hdr->smbh_type == SMB_TYPE_PROCESSOR) {
306*10942STom.Pothier@Sun.COM 				*stype->ids[cnt]->cont_ids[c] = cont_id;
307*10942STom.Pothier@Sun.COM 				c++;
308*10942STom.Pothier@Sun.COM 			}
309*10942STom.Pothier@Sun.COM 
310*10942STom.Pothier@Sun.COM 			if (spt->smbst_hdr->smbh_type == SMB_TYPE_BASEBOARD) {
311*10942STom.Pothier@Sun.COM 				for (i = 0; i < stype->count; i++) {
312*10942STom.Pothier@Sun.COM 					if (stype->ids[i]->id == cont_id) {
313*10942STom.Pothier@Sun.COM 						stype->ids[i]->cont_by_id =
314*10942STom.Pothier@Sun.COM 						    bb_id;
315*10942STom.Pothier@Sun.COM 					}
316*10942STom.Pothier@Sun.COM 				}
317*10942STom.Pothier@Sun.COM 			}
318*10942STom.Pothier@Sun.COM 
319*10942STom.Pothier@Sun.COM 		}
320*10942STom.Pothier@Sun.COM 		stype->ids[cnt]->cont_count = c;
321*10942STom.Pothier@Sun.COM 		if (cont_hdl != NULL)
322*10942STom.Pothier@Sun.COM 			kmem_free(cont_hdl, cont_count * cont_len);
323*10942STom.Pothier@Sun.COM 	}
324*10942STom.Pothier@Sun.COM }
325*10942STom.Pothier@Sun.COM 
326*10942STom.Pothier@Sun.COM /*
327*10942STom.Pothier@Sun.COM  * Verify SMBIOS structures for x86 generic topology.
328*10942STom.Pothier@Sun.COM  *
329*10942STom.Pothier@Sun.COM  * Return (0) on success.
330*10942STom.Pothier@Sun.COM  */
331*10942STom.Pothier@Sun.COM static int
332*10942STom.Pothier@Sun.COM fm_smb_check(smbios_hdl_t *shp)
333*10942STom.Pothier@Sun.COM {
334*10942STom.Pothier@Sun.COM 	int i;
335*10942STom.Pothier@Sun.COM 	int bb_cnt = 0;
336*10942STom.Pothier@Sun.COM 	int pr_cnt = 0;
337*10942STom.Pothier@Sun.COM 	int expr_cnt = 0;
338*10942STom.Pothier@Sun.COM 	int ma_cnt = 0;
339*10942STom.Pothier@Sun.COM 	int exma_cnt = 0;
340*10942STom.Pothier@Sun.COM 	int mdev_cnt = 0;
341*10942STom.Pothier@Sun.COM 	int exmdev_cnt = 0;
342*10942STom.Pothier@Sun.COM 	uint16_t bb_id;
343*10942STom.Pothier@Sun.COM 	uint16_t pr_id, expr_id;
344*10942STom.Pothier@Sun.COM 	uint16_t ma_id, exma_id;
345*10942STom.Pothier@Sun.COM 	uint16_t mdev_id, exmdev_id;
346*10942STom.Pothier@Sun.COM 	smbios_bboard_t bb;
347*10942STom.Pothier@Sun.COM 	smbios_processor_ext_t exproc;
348*10942STom.Pothier@Sun.COM 	smbios_memarray_ext_t exma;
349*10942STom.Pothier@Sun.COM 	smbios_memdevice_ext_t exmdev;
350*10942STom.Pothier@Sun.COM 	smbs_cnt_t *bb_stype;
351*10942STom.Pothier@Sun.COM 	smbs_cnt_t *pr_stype, *expr_stype;
352*10942STom.Pothier@Sun.COM 	smbs_cnt_t *ma_stype, *exma_stype;
353*10942STom.Pothier@Sun.COM 	smbs_cnt_t *mdev_stype, *exmdev_stype;
354*10942STom.Pothier@Sun.COM 
355*10942STom.Pothier@Sun.COM 	/*
356*10942STom.Pothier@Sun.COM 	 * Verify the existance of the requuired extended OEM-Specific
357*10942STom.Pothier@Sun.COM 	 * structures and they coincide with the structures they extend
358*10942STom.Pothier@Sun.COM 	 * (e.g. the number of extended processor structures equal the
359*10942STom.Pothier@Sun.COM 	 * number of processor structures).
360*10942STom.Pothier@Sun.COM 	 */
361*10942STom.Pothier@Sun.COM 	pr_cnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
362*10942STom.Pothier@Sun.COM 	expr_cnt = smb_cnttypes(shp, SUN_OEM_EXT_PROCESSOR);
363*10942STom.Pothier@Sun.COM 	ma_cnt = smb_cnttypes(shp, SMB_TYPE_MEMARRAY);
364*10942STom.Pothier@Sun.COM 	exma_cnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
365*10942STom.Pothier@Sun.COM 	mdev_cnt = smb_cnttypes(shp, SMB_TYPE_MEMDEVICE);
366*10942STom.Pothier@Sun.COM 	exmdev_cnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMDEVICE);
367*10942STom.Pothier@Sun.COM 	if (expr_cnt == 0 || exma_cnt == 0 || exmdev_cnt == 0 ||
368*10942STom.Pothier@Sun.COM 	    expr_cnt != pr_cnt || exma_cnt != ma_cnt ||
369*10942STom.Pothier@Sun.COM 	    exmdev_cnt != mdev_cnt) {
370*10942STom.Pothier@Sun.COM #ifdef	DEBUG
371*10942STom.Pothier@Sun.COM 		cmn_err(CE_NOTE, "Structure mismatch: ext_proc (%d) "
372*10942STom.Pothier@Sun.COM 		    "proc (%d) ext_ma (%d) ma (%d) ext_mdev (%d) mdev (%d)\n",
373*10942STom.Pothier@Sun.COM 		    expr_cnt, pr_cnt, exma_cnt, ma_cnt, exmdev_cnt,
374*10942STom.Pothier@Sun.COM 		    mdev_cnt);
375*10942STom.Pothier@Sun.COM #endif	/* DEBUG */
376*10942STom.Pothier@Sun.COM 		return (-1);
377*10942STom.Pothier@Sun.COM 	}
378*10942STom.Pothier@Sun.COM 
379*10942STom.Pothier@Sun.COM 	/*
380*10942STom.Pothier@Sun.COM 	 * Verify the OEM-Specific structrures are correctly
381*10942STom.Pothier@Sun.COM 	 * linked to the SMBIOS structure types they extend.
382*10942STom.Pothier@Sun.COM 	 */
383*10942STom.Pothier@Sun.COM 
384*10942STom.Pothier@Sun.COM 	/* allocate processor stypes */
385*10942STom.Pothier@Sun.COM 	pr_stype = smb_create_strcnt(pr_cnt);
386*10942STom.Pothier@Sun.COM 	expr_stype = smb_create_strcnt(expr_cnt);
387*10942STom.Pothier@Sun.COM 
388*10942STom.Pothier@Sun.COM 	/* fill in stypes */
389*10942STom.Pothier@Sun.COM 	pr_stype->type = SMB_TYPE_PROCESSOR;
390*10942STom.Pothier@Sun.COM 	smb_strcnt(shp, pr_stype);
391*10942STom.Pothier@Sun.COM 	expr_stype->type = SUN_OEM_EXT_PROCESSOR;
392*10942STom.Pothier@Sun.COM 	smb_strcnt(shp, expr_stype);
393*10942STom.Pothier@Sun.COM 
394*10942STom.Pothier@Sun.COM 	/* verify the ext proc struct belong to the proc struct */
395*10942STom.Pothier@Sun.COM 	for (i = 0; i < pr_cnt; i++) {
396*10942STom.Pothier@Sun.COM 		pr_id = pr_stype->ids[i]->id;
397*10942STom.Pothier@Sun.COM 		expr_id = expr_stype->ids[i]->id;
398*10942STom.Pothier@Sun.COM 		(void) smbios_info_extprocessor(shp, expr_id, &exproc);
399*10942STom.Pothier@Sun.COM 		if (exproc.smbpe_processor != pr_id) {
400*10942STom.Pothier@Sun.COM #ifdef	DEBUG
401*10942STom.Pothier@Sun.COM 			cmn_err(CE_NOTE, "Processor struct linkage (%d)", i);
402*10942STom.Pothier@Sun.COM #endif	/* DEBUG */
403*10942STom.Pothier@Sun.COM 			smb_free_strcnt(pr_stype, pr_cnt);
404*10942STom.Pothier@Sun.COM 			smb_free_strcnt(expr_stype, expr_cnt);
405*10942STom.Pothier@Sun.COM 			return (-1);
406*10942STom.Pothier@Sun.COM 		}
407*10942STom.Pothier@Sun.COM 	}
408*10942STom.Pothier@Sun.COM 
409*10942STom.Pothier@Sun.COM 	/* free stypes */
410*10942STom.Pothier@Sun.COM 	smb_free_strcnt(pr_stype, pr_cnt);
411*10942STom.Pothier@Sun.COM 	smb_free_strcnt(expr_stype, expr_cnt);
412*10942STom.Pothier@Sun.COM 
413*10942STom.Pothier@Sun.COM 	/* allocate memory array stypes */
414*10942STom.Pothier@Sun.COM 	ma_stype = smb_create_strcnt(ma_cnt);
415*10942STom.Pothier@Sun.COM 	exma_stype = smb_create_strcnt(exma_cnt);
416*10942STom.Pothier@Sun.COM 
417*10942STom.Pothier@Sun.COM 	/* fill in stypes */
418*10942STom.Pothier@Sun.COM 	ma_stype->type = SMB_TYPE_MEMARRAY;
419*10942STom.Pothier@Sun.COM 	smb_strcnt(shp, ma_stype);
420*10942STom.Pothier@Sun.COM 	exma_stype->type = SUN_OEM_EXT_MEMARRAY;
421*10942STom.Pothier@Sun.COM 	smb_strcnt(shp, exma_stype);
422*10942STom.Pothier@Sun.COM 
423*10942STom.Pothier@Sun.COM 	/* verify linkage from ext memarray struct to memarray struct */
424*10942STom.Pothier@Sun.COM 	for (i = 0; i < ma_cnt; i++) {
425*10942STom.Pothier@Sun.COM 		ma_id = ma_stype->ids[i]->id;
426*10942STom.Pothier@Sun.COM 		exma_id = exma_stype->ids[i]->id;
427*10942STom.Pothier@Sun.COM 		(void) smbios_info_extmemarray(shp, exma_id, &exma);
428*10942STom.Pothier@Sun.COM 		if (exma.smbmae_ma != ma_id) {
429*10942STom.Pothier@Sun.COM #ifdef	DEBUG
430*10942STom.Pothier@Sun.COM 			cmn_err(CE_NOTE, "Memory Array struct linkage (%d)", i);
431*10942STom.Pothier@Sun.COM #endif	/* DEBUG */
432*10942STom.Pothier@Sun.COM 			smb_free_strcnt(ma_stype, ma_cnt);
433*10942STom.Pothier@Sun.COM 			smb_free_strcnt(exma_stype, exma_cnt);
434*10942STom.Pothier@Sun.COM 			return (-1);
435*10942STom.Pothier@Sun.COM 		}
436*10942STom.Pothier@Sun.COM 	}
437*10942STom.Pothier@Sun.COM 
438*10942STom.Pothier@Sun.COM 	/* free stypes */
439*10942STom.Pothier@Sun.COM 	smb_free_strcnt(ma_stype, ma_cnt);
440*10942STom.Pothier@Sun.COM 	smb_free_strcnt(exma_stype, exma_cnt);
441*10942STom.Pothier@Sun.COM 
442*10942STom.Pothier@Sun.COM 	/* allocate memory device stypes */
443*10942STom.Pothier@Sun.COM 	mdev_stype = smb_create_strcnt(mdev_cnt);
444*10942STom.Pothier@Sun.COM 	exmdev_stype = smb_create_strcnt(exmdev_cnt);
445*10942STom.Pothier@Sun.COM 
446*10942STom.Pothier@Sun.COM 	/* fill in stypes */
447*10942STom.Pothier@Sun.COM 	mdev_stype->type = SMB_TYPE_MEMDEVICE;
448*10942STom.Pothier@Sun.COM 	smb_strcnt(shp, mdev_stype);
449*10942STom.Pothier@Sun.COM 	exmdev_stype->type = SUN_OEM_EXT_MEMDEVICE;
450*10942STom.Pothier@Sun.COM 	smb_strcnt(shp, exmdev_stype);
451*10942STom.Pothier@Sun.COM 
452*10942STom.Pothier@Sun.COM 	/* verify linkage */
453*10942STom.Pothier@Sun.COM 	for (i = 0; i < mdev_cnt; i++) {
454*10942STom.Pothier@Sun.COM 		mdev_id = mdev_stype->ids[i]->id;
455*10942STom.Pothier@Sun.COM 		exmdev_id = exmdev_stype->ids[i]->id;
456*10942STom.Pothier@Sun.COM 		(void) smbios_info_extmemdevice(shp, exmdev_id, &exmdev);
457*10942STom.Pothier@Sun.COM 		if (exmdev.smbmdeve_md != mdev_id) {
458*10942STom.Pothier@Sun.COM #ifdef	DEBUG
459*10942STom.Pothier@Sun.COM 			cmn_err(CE_NOTE, "Memory Device struct linkage (%d)",
460*10942STom.Pothier@Sun.COM 			    i);
461*10942STom.Pothier@Sun.COM #endif	/* DEBUG */
462*10942STom.Pothier@Sun.COM 			smb_free_strcnt(mdev_stype, mdev_cnt);
463*10942STom.Pothier@Sun.COM 			smb_free_strcnt(exmdev_stype, exmdev_cnt);
464*10942STom.Pothier@Sun.COM 			return (-1);
465*10942STom.Pothier@Sun.COM 		}
466*10942STom.Pothier@Sun.COM 	}
467*10942STom.Pothier@Sun.COM 
468*10942STom.Pothier@Sun.COM 	/* free stypes */
469*10942STom.Pothier@Sun.COM 	smb_free_strcnt(mdev_stype, mdev_cnt);
470*10942STom.Pothier@Sun.COM 	smb_free_strcnt(exmdev_stype, exmdev_cnt);
471*10942STom.Pothier@Sun.COM 
472*10942STom.Pothier@Sun.COM 	/*
473*10942STom.Pothier@Sun.COM 	 * Verify the presece of contained handles if there are more
474*10942STom.Pothier@Sun.COM 	 * than one Type-2 (Base Board) structures.
475*10942STom.Pothier@Sun.COM 	 */
476*10942STom.Pothier@Sun.COM 	bb_cnt = smb_cnttypes(shp, SMB_TYPE_BASEBOARD);
477*10942STom.Pothier@Sun.COM 	if (bb_cnt > 1) {
478*10942STom.Pothier@Sun.COM 		/* allocate base board stypes */
479*10942STom.Pothier@Sun.COM 		bb_stype = smb_create_strcnt(bb_cnt);
480*10942STom.Pothier@Sun.COM 
481*10942STom.Pothier@Sun.COM 		/* fill in stypes */
482*10942STom.Pothier@Sun.COM 		bb_stype->type = SMB_TYPE_BASEBOARD;
483*10942STom.Pothier@Sun.COM 		smb_strcnt(shp, bb_stype);
484*10942STom.Pothier@Sun.COM 
485*10942STom.Pothier@Sun.COM 		/* verify contained handles */
486*10942STom.Pothier@Sun.COM 		for (i = 0; i < bb_cnt; i++) {
487*10942STom.Pothier@Sun.COM 			bb_id = bb_stype->ids[i]->id;
488*10942STom.Pothier@Sun.COM 			(void) smbios_info_bboard(shp, bb_id, &bb);
489*10942STom.Pothier@Sun.COM 			if (bb.smbb_contn == 0) {
490*10942STom.Pothier@Sun.COM #ifdef	DEBUG
491*10942STom.Pothier@Sun.COM 				cmn_err(CE_NOTE, "No contained hanldes (%d)",
492*10942STom.Pothier@Sun.COM 				    i);
493*10942STom.Pothier@Sun.COM #endif	/* DEBUG */
494*10942STom.Pothier@Sun.COM 				smb_free_strcnt(bb_stype, bb_cnt);
495*10942STom.Pothier@Sun.COM 				return (-1);
496*10942STom.Pothier@Sun.COM 			}
497*10942STom.Pothier@Sun.COM 		}
498*10942STom.Pothier@Sun.COM 
499*10942STom.Pothier@Sun.COM 		/* free stypes */
500*10942STom.Pothier@Sun.COM 		smb_free_strcnt(bb_stype, bb_cnt);
501*10942STom.Pothier@Sun.COM 	}
502*10942STom.Pothier@Sun.COM 
503*10942STom.Pothier@Sun.COM 	return (0);
504*10942STom.Pothier@Sun.COM }
505*10942STom.Pothier@Sun.COM 
506*10942STom.Pothier@Sun.COM void
507*10942STom.Pothier@Sun.COM fm_smb_fmacompat()
508*10942STom.Pothier@Sun.COM {
509*10942STom.Pothier@Sun.COM 	int i, j;
510*10942STom.Pothier@Sun.COM 	int id;
511*10942STom.Pothier@Sun.COM 	int cnt;
512*10942STom.Pothier@Sun.COM 	const char **oem_strings = NULL;
513*10942STom.Pothier@Sun.COM 	smbs_cnt_t *oemstypes;
514*10942STom.Pothier@Sun.COM 	smbios_hdl_t *shp;
515*10942STom.Pothier@Sun.COM 	int strcnt;
516*10942STom.Pothier@Sun.COM 	int compat = 0;
517*10942STom.Pothier@Sun.COM 
518*10942STom.Pothier@Sun.COM 	/* check for BKS */
519*10942STom.Pothier@Sun.COM 	if (x86gentopo_legacy == 1) {
520*10942STom.Pothier@Sun.COM #ifdef DEBUG
521*10942STom.Pothier@Sun.COM 		cmn_err(CE_NOTE, "forced legacy x86 topology enumeration");
522*10942STom.Pothier@Sun.COM #endif /* DEBUG */
523*10942STom.Pothier@Sun.COM 		return;
524*10942STom.Pothier@Sun.COM 	}
525*10942STom.Pothier@Sun.COM 
526*10942STom.Pothier@Sun.COM 	shp = ksmbios;
527*10942STom.Pothier@Sun.COM 	if (shp == NULL) {
528*10942STom.Pothier@Sun.COM 		goto bad;
529*10942STom.Pothier@Sun.COM 	}
530*10942STom.Pothier@Sun.COM 
531*10942STom.Pothier@Sun.COM 	/* OEM strings (Type 11) */
532*10942STom.Pothier@Sun.COM 	strcnt = smb_cnttypes(shp, SMB_TYPE_OEMSTR);
533*10942STom.Pothier@Sun.COM 	if (strcnt == 0)
534*10942STom.Pothier@Sun.COM 		goto bad;
535*10942STom.Pothier@Sun.COM 
536*10942STom.Pothier@Sun.COM 	oemstypes = smb_create_strcnt(strcnt);
537*10942STom.Pothier@Sun.COM 	if (oemstypes == NULL)
538*10942STom.Pothier@Sun.COM 		goto bad;
539*10942STom.Pothier@Sun.COM 
540*10942STom.Pothier@Sun.COM 	oemstypes->type = SMB_TYPE_OEMSTR;
541*10942STom.Pothier@Sun.COM 	smb_strcnt(shp, oemstypes);
542*10942STom.Pothier@Sun.COM 
543*10942STom.Pothier@Sun.COM 	for (i = 0; i < oemstypes->count; i++) {
544*10942STom.Pothier@Sun.COM 		id = oemstypes->ids[i]->id;
545*10942STom.Pothier@Sun.COM 		cnt = smbios_info_strtab(shp, id, 0, NULL);
546*10942STom.Pothier@Sun.COM 		if (cnt > 0) {
547*10942STom.Pothier@Sun.COM 			oem_strings = kmem_zalloc(sizeof (char *) * cnt,
548*10942STom.Pothier@Sun.COM 			    KM_SLEEP);
549*10942STom.Pothier@Sun.COM 			(void) smbios_info_strtab(shp, id, cnt, oem_strings);
550*10942STom.Pothier@Sun.COM 
551*10942STom.Pothier@Sun.COM 			for (j = 0; j < cnt; j++) {
552*10942STom.Pothier@Sun.COM 				if (strncmp(oem_strings[j], SMB_PRMS1,
553*10942STom.Pothier@Sun.COM 				    strlen(SMB_PRMS1) + 1) == 0) {
554*10942STom.Pothier@Sun.COM 					kmem_free(oem_strings,
555*10942STom.Pothier@Sun.COM 					    sizeof (char *) * cnt);
556*10942STom.Pothier@Sun.COM 					smb_free_strcnt(oemstypes, strcnt);
557*10942STom.Pothier@Sun.COM 					compat = 1;
558*10942STom.Pothier@Sun.COM 					break;
559*10942STom.Pothier@Sun.COM 				}
560*10942STom.Pothier@Sun.COM 			}
561*10942STom.Pothier@Sun.COM 		}
562*10942STom.Pothier@Sun.COM 	}
563*10942STom.Pothier@Sun.COM 
564*10942STom.Pothier@Sun.COM 	if (compat == 0) {
565*10942STom.Pothier@Sun.COM 		/* didn't find x86pi magic cookie */
566*10942STom.Pothier@Sun.COM 		if (oem_strings != NULL)
567*10942STom.Pothier@Sun.COM 			kmem_free(oem_strings, sizeof (char *) * cnt);
568*10942STom.Pothier@Sun.COM 		smb_free_strcnt(oemstypes, strcnt);
569*10942STom.Pothier@Sun.COM 		goto bad;
570*10942STom.Pothier@Sun.COM 	}
571*10942STom.Pothier@Sun.COM 
572*10942STom.Pothier@Sun.COM 	/* sanity check SMBIOS structures */
573*10942STom.Pothier@Sun.COM 	if (fm_smb_check(shp) == 0)
574*10942STom.Pothier@Sun.COM 		return;
575*10942STom.Pothier@Sun.COM 
576*10942STom.Pothier@Sun.COM bad:
577*10942STom.Pothier@Sun.COM 	/* not compatible with x86gentopo; revert to legacy enumeration */
578*10942STom.Pothier@Sun.COM #ifdef	DEBUG
579*10942STom.Pothier@Sun.COM 	cmn_err(CE_NOTE, "SMBIOS is not compatible with x86 generic topology.");
580*10942STom.Pothier@Sun.COM 	cmn_err(CE_NOTE, "Invoking legacy x86 topology enumeration.");
581*10942STom.Pothier@Sun.COM #endif	/* DEBUG */
582*10942STom.Pothier@Sun.COM 	x86gentopo_legacy = 1;
583*10942STom.Pothier@Sun.COM }
584*10942STom.Pothier@Sun.COM 
585*10942STom.Pothier@Sun.COM static int
586*10942STom.Pothier@Sun.COM find_matching_apic(smbios_hdl_t *shp, uint16_t proc_id, uint_t strand_apicid)
587*10942STom.Pothier@Sun.COM {
588*10942STom.Pothier@Sun.COM 	uint16_t ext_id;
589*10942STom.Pothier@Sun.COM 	int i, j;
590*10942STom.Pothier@Sun.COM 	smbios_processor_ext_t ep;
591*10942STom.Pothier@Sun.COM 	smbs_cnt_t *pstypes;
592*10942STom.Pothier@Sun.COM 	int strcnt;
593*10942STom.Pothier@Sun.COM 
594*10942STom.Pothier@Sun.COM 	strcnt = smb_cnttypes(shp, SUN_OEM_EXT_PROCESSOR);
595*10942STom.Pothier@Sun.COM 	if (strcnt == 0)
596*10942STom.Pothier@Sun.COM 		return (0);
597*10942STom.Pothier@Sun.COM 
598*10942STom.Pothier@Sun.COM 	pstypes = smb_create_strcnt(strcnt);
599*10942STom.Pothier@Sun.COM 	if (pstypes == NULL)
600*10942STom.Pothier@Sun.COM 		return (0);
601*10942STom.Pothier@Sun.COM 
602*10942STom.Pothier@Sun.COM 	pstypes->type = SUN_OEM_EXT_PROCESSOR;
603*10942STom.Pothier@Sun.COM 	smb_strcnt(shp, pstypes);
604*10942STom.Pothier@Sun.COM 	for (i = 0; i < pstypes->count; i++) {
605*10942STom.Pothier@Sun.COM 		ext_id = pstypes->ids[i]->id;
606*10942STom.Pothier@Sun.COM 		(void) smbios_info_extprocessor(shp, ext_id, &ep);
607*10942STom.Pothier@Sun.COM 		if (ep.smbpe_processor == proc_id) {
608*10942STom.Pothier@Sun.COM 			for (j = 0; j < ep.smbpe_n; j++) {
609*10942STom.Pothier@Sun.COM 				if (ep.smbpe_apicid[j] == strand_apicid) {
610*10942STom.Pothier@Sun.COM 					smb_free_strcnt(pstypes, strcnt);
611*10942STom.Pothier@Sun.COM 					return (1);
612*10942STom.Pothier@Sun.COM 				}
613*10942STom.Pothier@Sun.COM 			}
614*10942STom.Pothier@Sun.COM 		}
615*10942STom.Pothier@Sun.COM 	}
616*10942STom.Pothier@Sun.COM 	smb_free_strcnt(pstypes, strcnt);
617*10942STom.Pothier@Sun.COM 	return (0);
618*10942STom.Pothier@Sun.COM }
619*10942STom.Pothier@Sun.COM 
620*10942STom.Pothier@Sun.COM /*
621*10942STom.Pothier@Sun.COM  * go throught the type 2 structure contained_ids looking for
622*10942STom.Pothier@Sun.COM  * the type 4 which  has strand_apicid == this strand_apicid
623*10942STom.Pothier@Sun.COM  */
624*10942STom.Pothier@Sun.COM static int
625*10942STom.Pothier@Sun.COM find_matching_proc(smbios_hdl_t *shp, uint_t strand_apicid,
626*10942STom.Pothier@Sun.COM     uint16_t bb_id, uint16_t proc_hdl, int is_proc)
627*10942STom.Pothier@Sun.COM {
628*10942STom.Pothier@Sun.COM 	int n;
629*10942STom.Pothier@Sun.COM 	const smb_struct_t *sp;
630*10942STom.Pothier@Sun.COM 	smbios_bboard_t bb;
631*10942STom.Pothier@Sun.COM 	uint_t cont_count, cont_len;
632*10942STom.Pothier@Sun.COM 	uint16_t cont_id;
633*10942STom.Pothier@Sun.COM 	id_t *cont_hdl = NULL;
634*10942STom.Pothier@Sun.COM 	int rc;
635*10942STom.Pothier@Sun.COM 
636*10942STom.Pothier@Sun.COM 
637*10942STom.Pothier@Sun.COM 	(void) smbios_info_bboard(shp, bb_id, &bb);
638*10942STom.Pothier@Sun.COM 	cont_count = (uint_t)bb.smbb_contn;
639*10942STom.Pothier@Sun.COM 	if (cont_count == 0)
640*10942STom.Pothier@Sun.COM 		return (0);
641*10942STom.Pothier@Sun.COM 
642*10942STom.Pothier@Sun.COM 	cont_len = sizeof (id_t);
643*10942STom.Pothier@Sun.COM 	cont_hdl = kmem_zalloc(cont_count * cont_len, KM_SLEEP);
644*10942STom.Pothier@Sun.COM 	if (cont_hdl == NULL)
645*10942STom.Pothier@Sun.COM 		return (0);
646*10942STom.Pothier@Sun.COM 
647*10942STom.Pothier@Sun.COM 	rc = smbios_info_contains(shp, bb_id, cont_count, cont_hdl);
648*10942STom.Pothier@Sun.COM 	if (rc > SMB_CONT_MAX) {
649*10942STom.Pothier@Sun.COM 		kmem_free(cont_hdl, cont_count * cont_len);
650*10942STom.Pothier@Sun.COM 		return (0);
651*10942STom.Pothier@Sun.COM 	}
652*10942STom.Pothier@Sun.COM 	cont_count = MIN(rc, cont_count);
653*10942STom.Pothier@Sun.COM 
654*10942STom.Pothier@Sun.COM 	for (n = 0; n < cont_count; n++) {
655*10942STom.Pothier@Sun.COM 		cont_id = (uint16_t)cont_hdl[n];
656*10942STom.Pothier@Sun.COM 		sp = smb_lookup_id(shp, cont_id);
657*10942STom.Pothier@Sun.COM 		if (sp->smbst_hdr->smbh_type == SMB_TYPE_PROCESSOR) {
658*10942STom.Pothier@Sun.COM 			if (is_proc) {
659*10942STom.Pothier@Sun.COM 				if (find_matching_apic(shp, cont_id,
660*10942STom.Pothier@Sun.COM 				    strand_apicid)) {
661*10942STom.Pothier@Sun.COM 					kmem_free(cont_hdl,
662*10942STom.Pothier@Sun.COM 					    cont_count * cont_len);
663*10942STom.Pothier@Sun.COM 					return (1);
664*10942STom.Pothier@Sun.COM 				}
665*10942STom.Pothier@Sun.COM 			} else {
666*10942STom.Pothier@Sun.COM 				if (cont_id == proc_hdl) {
667*10942STom.Pothier@Sun.COM 					kmem_free(cont_hdl,
668*10942STom.Pothier@Sun.COM 					    cont_count * cont_len);
669*10942STom.Pothier@Sun.COM 					return (1);
670*10942STom.Pothier@Sun.COM 				}
671*10942STom.Pothier@Sun.COM 			}
672*10942STom.Pothier@Sun.COM 		}
673*10942STom.Pothier@Sun.COM 	}
674*10942STom.Pothier@Sun.COM 	if (cont_hdl != NULL)
675*10942STom.Pothier@Sun.COM 		kmem_free(cont_hdl, cont_count * cont_len);
676*10942STom.Pothier@Sun.COM 
677*10942STom.Pothier@Sun.COM 	return (0);
678*10942STom.Pothier@Sun.COM }
679*10942STom.Pothier@Sun.COM 
680*10942STom.Pothier@Sun.COM void
681*10942STom.Pothier@Sun.COM get_bboard_index(smbs_cnt_t *bbstypes, uint_t bb_id, bbindex_t *bb_idx)
682*10942STom.Pothier@Sun.COM {
683*10942STom.Pothier@Sun.COM 	int curr_id, tmp_id;
684*10942STom.Pothier@Sun.COM 	int i, j, nb;
685*10942STom.Pothier@Sun.COM 	bbindex_t tmp_idx;
686*10942STom.Pothier@Sun.COM 
687*10942STom.Pothier@Sun.COM 	for (i = 0; i < MAX_PAIRS; i++)
688*10942STom.Pothier@Sun.COM 		tmp_idx.index[i] = 0;
689*10942STom.Pothier@Sun.COM 
690*10942STom.Pothier@Sun.COM 	tmp_idx.count = 0;
691*10942STom.Pothier@Sun.COM 
692*10942STom.Pothier@Sun.COM 	curr_id = bb_id;
693*10942STom.Pothier@Sun.COM 	for (nb = bbstypes->count-1, i = 0; nb >= 0; nb--) {
694*10942STom.Pothier@Sun.COM 		tmp_id = bbstypes->ids[nb]->id;
695*10942STom.Pothier@Sun.COM 		if (tmp_id == curr_id) {
696*10942STom.Pothier@Sun.COM 			tmp_idx.index[i] = nb;
697*10942STom.Pothier@Sun.COM 			tmp_idx.count++;
698*10942STom.Pothier@Sun.COM 			curr_id = bbstypes->ids[nb]->cont_by_id;
699*10942STom.Pothier@Sun.COM 			if (curr_id == -1)
700*10942STom.Pothier@Sun.COM 				break;
701*10942STom.Pothier@Sun.COM 			i++;
702*10942STom.Pothier@Sun.COM 		}
703*10942STom.Pothier@Sun.COM 	}
704*10942STom.Pothier@Sun.COM 
705*10942STom.Pothier@Sun.COM 	for (i = tmp_idx.count - 1, j = 0; i >= 0; i--) {
706*10942STom.Pothier@Sun.COM 		bb_idx->index[j] = tmp_idx.index[i];
707*10942STom.Pothier@Sun.COM 		j++;
708*10942STom.Pothier@Sun.COM 	}
709*10942STom.Pothier@Sun.COM 
710*10942STom.Pothier@Sun.COM 	bb_idx->count = tmp_idx.count;
711*10942STom.Pothier@Sun.COM }
712*10942STom.Pothier@Sun.COM 
713*10942STom.Pothier@Sun.COM int
714*10942STom.Pothier@Sun.COM get_chassis_inst(smbios_hdl_t *shp, uint16_t *chassis_inst,
715*10942STom.Pothier@Sun.COM     uint16_t bb_id, int *chcnt)
716*10942STom.Pothier@Sun.COM {
717*10942STom.Pothier@Sun.COM 	int ch_strcnt;
718*10942STom.Pothier@Sun.COM 	smbs_cnt_t *chstypes;
719*10942STom.Pothier@Sun.COM 	uint16_t chassis_id, tmp_id;
720*10942STom.Pothier@Sun.COM 	smbios_bboard_t bb;
721*10942STom.Pothier@Sun.COM 	int rc = 0;
722*10942STom.Pothier@Sun.COM 	int i;
723*10942STom.Pothier@Sun.COM 
724*10942STom.Pothier@Sun.COM 	rc = smbios_info_bboard(shp, bb_id, &bb);
725*10942STom.Pothier@Sun.COM 	if (rc != 0) {
726*10942STom.Pothier@Sun.COM 		return (-1);
727*10942STom.Pothier@Sun.COM 	}
728*10942STom.Pothier@Sun.COM 
729*10942STom.Pothier@Sun.COM 	chassis_id = bb.smbb_chassis;
730*10942STom.Pothier@Sun.COM 
731*10942STom.Pothier@Sun.COM 	ch_strcnt = smb_cnttypes(shp, SMB_TYPE_CHASSIS);
732*10942STom.Pothier@Sun.COM 
733*10942STom.Pothier@Sun.COM 	if (ch_strcnt == 0)
734*10942STom.Pothier@Sun.COM 		return (-1);
735*10942STom.Pothier@Sun.COM 
736*10942STom.Pothier@Sun.COM 	chstypes = smb_create_strcnt(ch_strcnt);
737*10942STom.Pothier@Sun.COM 	if (chstypes == NULL)
738*10942STom.Pothier@Sun.COM 		return (-1);
739*10942STom.Pothier@Sun.COM 
740*10942STom.Pothier@Sun.COM 	chstypes->type = SMB_TYPE_CHASSIS;
741*10942STom.Pothier@Sun.COM 	smb_strcnt(shp, chstypes);
742*10942STom.Pothier@Sun.COM 
743*10942STom.Pothier@Sun.COM 	for (i = 0; i < chstypes->count; i++) {
744*10942STom.Pothier@Sun.COM 		tmp_id = chstypes->ids[i]->id;
745*10942STom.Pothier@Sun.COM 		if (tmp_id == chassis_id) {
746*10942STom.Pothier@Sun.COM 			*chassis_inst = chstypes->ids[i]->inst;
747*10942STom.Pothier@Sun.COM 			if (chstypes->ids[i]->inst != 0)
748*10942STom.Pothier@Sun.COM 				*chcnt = 2;
749*10942STom.Pothier@Sun.COM 			else
750*10942STom.Pothier@Sun.COM 				*chcnt = 1;
751*10942STom.Pothier@Sun.COM 			smb_free_strcnt(chstypes, ch_strcnt);
752*10942STom.Pothier@Sun.COM 			return (0);
753*10942STom.Pothier@Sun.COM 		}
754*10942STom.Pothier@Sun.COM 	}
755*10942STom.Pothier@Sun.COM 
756*10942STom.Pothier@Sun.COM 	smb_free_strcnt(chstypes, ch_strcnt);
757*10942STom.Pothier@Sun.COM 	return (-1);
758*10942STom.Pothier@Sun.COM }
759*10942STom.Pothier@Sun.COM 
760*10942STom.Pothier@Sun.COM int
761*10942STom.Pothier@Sun.COM smb_get_bb_fmri(smbios_hdl_t *shp, nvlist_t *fmri,  uint_t parent,
762*10942STom.Pothier@Sun.COM     smbs_cnt_t *bbstypes)
763*10942STom.Pothier@Sun.COM {
764*10942STom.Pothier@Sun.COM 	int rc = 0;
765*10942STom.Pothier@Sun.COM 	int i, j, n, cnt;
766*10942STom.Pothier@Sun.COM 	int id, index;
767*10942STom.Pothier@Sun.COM 	nvlist_t *pairs[MAX_PAIRS];
768*10942STom.Pothier@Sun.COM 	smbios_bboard_t bb;
769*10942STom.Pothier@Sun.COM 	uint16_t chassis_inst, mch_inst;
770*10942STom.Pothier@Sun.COM 	char name[40];
771*10942STom.Pothier@Sun.COM 	char idstr[11];
772*10942STom.Pothier@Sun.COM 	bbindex_t bb_idx;
773*10942STom.Pothier@Sun.COM 	uint16_t bbid;
774*10942STom.Pothier@Sun.COM 	int chcnt = 0;
775*10942STom.Pothier@Sun.COM 
776*10942STom.Pothier@Sun.COM 	for (n = 0; n < MAX_PAIRS; n++) {
777*10942STom.Pothier@Sun.COM 		bb_idx.index[n] = 0;
778*10942STom.Pothier@Sun.COM 		pairs[n] = NULL;
779*10942STom.Pothier@Sun.COM 	}
780*10942STom.Pothier@Sun.COM 	bb_idx.count = 0;
781*10942STom.Pothier@Sun.COM 
782*10942STom.Pothier@Sun.COM 	get_bboard_index(bbstypes, parent, &bb_idx);
783*10942STom.Pothier@Sun.COM 
784*10942STom.Pothier@Sun.COM 	index = bb_idx.index[0];
785*10942STom.Pothier@Sun.COM 	bbid = bbstypes->ids[index]->id;
786*10942STom.Pothier@Sun.COM 
787*10942STom.Pothier@Sun.COM 	rc = get_chassis_inst(shp, &chassis_inst, bbid, &chcnt);
788*10942STom.Pothier@Sun.COM 
789*10942STom.Pothier@Sun.COM 	if (rc != 0) {
790*10942STom.Pothier@Sun.COM 		return (rc);
791*10942STom.Pothier@Sun.COM 	}
792*10942STom.Pothier@Sun.COM 
793*10942STom.Pothier@Sun.COM 	if ((bb_idx.count + chcnt) > MAX_PAIRS) {
794*10942STom.Pothier@Sun.COM 		return (-1);
795*10942STom.Pothier@Sun.COM 	}
796*10942STom.Pothier@Sun.COM 
797*10942STom.Pothier@Sun.COM 	i = 0;
798*10942STom.Pothier@Sun.COM 	if (chcnt > 1) {
799*10942STom.Pothier@Sun.COM 		/*
800*10942STom.Pothier@Sun.COM 		 * create main chassis pair
801*10942STom.Pothier@Sun.COM 		 */
802*10942STom.Pothier@Sun.COM 		pairs[i] = fm_nvlist_create(NULL);
803*10942STom.Pothier@Sun.COM 		if (pairs[i] == NULL) {
804*10942STom.Pothier@Sun.COM 			return (-1);
805*10942STom.Pothier@Sun.COM 		}
806*10942STom.Pothier@Sun.COM 		mch_inst = 0;
807*10942STom.Pothier@Sun.COM 		(void) snprintf(idstr, sizeof (idstr), "%u", mch_inst);
808*10942STom.Pothier@Sun.COM 		if ((nvlist_add_string(pairs[i], FM_FMRI_HC_NAME,
809*10942STom.Pothier@Sun.COM 		    "chassis") != 0) ||
810*10942STom.Pothier@Sun.COM 		    (nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr)) != 0) {
811*10942STom.Pothier@Sun.COM 			fm_nvlist_destroy(pairs[i], FM_NVA_FREE);
812*10942STom.Pothier@Sun.COM 			return (-1);
813*10942STom.Pothier@Sun.COM 		}
814*10942STom.Pothier@Sun.COM 		i++;
815*10942STom.Pothier@Sun.COM 	}
816*10942STom.Pothier@Sun.COM 
817*10942STom.Pothier@Sun.COM 	/*
818*10942STom.Pothier@Sun.COM 	 * create chassis pair
819*10942STom.Pothier@Sun.COM 	 */
820*10942STom.Pothier@Sun.COM 	pairs[i] = fm_nvlist_create(NULL);
821*10942STom.Pothier@Sun.COM 	if (pairs[i] == NULL) {
822*10942STom.Pothier@Sun.COM 		for (n = 0; n < MAX_PAIRS; n++) {
823*10942STom.Pothier@Sun.COM 			if (pairs[n] != NULL)
824*10942STom.Pothier@Sun.COM 				fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
825*10942STom.Pothier@Sun.COM 		}
826*10942STom.Pothier@Sun.COM 		return (-1);
827*10942STom.Pothier@Sun.COM 	}
828*10942STom.Pothier@Sun.COM 	(void) snprintf(idstr, sizeof (idstr), "%u", chassis_inst);
829*10942STom.Pothier@Sun.COM 	if ((nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, "chassis") != 0) ||
830*10942STom.Pothier@Sun.COM 	    (nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) != 0)) {
831*10942STom.Pothier@Sun.COM 		for (n = 0; n < MAX_PAIRS; n++) {
832*10942STom.Pothier@Sun.COM 			if (pairs[n] != NULL)
833*10942STom.Pothier@Sun.COM 				fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
834*10942STom.Pothier@Sun.COM 		}
835*10942STom.Pothier@Sun.COM 		return (-1);
836*10942STom.Pothier@Sun.COM 	}
837*10942STom.Pothier@Sun.COM 
838*10942STom.Pothier@Sun.COM 	for (j = 0, i = chcnt, cnt = chcnt; j < bb_idx.count; j++) {
839*10942STom.Pothier@Sun.COM 		index = bb_idx.index[j];
840*10942STom.Pothier@Sun.COM 		bbid = bbstypes->ids[index]->id;
841*10942STom.Pothier@Sun.COM 		rc =  smbios_info_bboard(shp, bbid, &bb);
842*10942STom.Pothier@Sun.COM 		if (rc != 0) {
843*10942STom.Pothier@Sun.COM 			rc = -1;
844*10942STom.Pothier@Sun.COM 			break;
845*10942STom.Pothier@Sun.COM 		}
846*10942STom.Pothier@Sun.COM 
847*10942STom.Pothier@Sun.COM 		pairs[i] = fm_nvlist_create(NULL);
848*10942STom.Pothier@Sun.COM 		if (pairs[i] == NULL) {
849*10942STom.Pothier@Sun.COM 			rc = -1;
850*10942STom.Pothier@Sun.COM 			break;
851*10942STom.Pothier@Sun.COM 		}
852*10942STom.Pothier@Sun.COM 
853*10942STom.Pothier@Sun.COM 		id = bbstypes->ids[index]->inst;
854*10942STom.Pothier@Sun.COM 		(void) snprintf(idstr, sizeof (idstr), "%u", id);
855*10942STom.Pothier@Sun.COM 		(void) strncpy(name, bbd_type[bb.smbb_type].name,
856*10942STom.Pothier@Sun.COM 		    sizeof (name));
857*10942STom.Pothier@Sun.COM 		cnt++;
858*10942STom.Pothier@Sun.COM 
859*10942STom.Pothier@Sun.COM 		if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, name) != 0 ||
860*10942STom.Pothier@Sun.COM 		    nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr)
861*10942STom.Pothier@Sun.COM 		    != 0) {
862*10942STom.Pothier@Sun.COM 			rc = -1;
863*10942STom.Pothier@Sun.COM 			break;
864*10942STom.Pothier@Sun.COM 		}
865*10942STom.Pothier@Sun.COM 		i++;
866*10942STom.Pothier@Sun.COM 	}
867*10942STom.Pothier@Sun.COM 
868*10942STom.Pothier@Sun.COM 	if (rc != -1) {
869*10942STom.Pothier@Sun.COM 		if (nvlist_add_nvlist_array(fmri, FM_FMRI_HC_LIST,
870*10942STom.Pothier@Sun.COM 		    pairs, cnt) != 0) {
871*10942STom.Pothier@Sun.COM 			rc = -1;
872*10942STom.Pothier@Sun.COM 		}
873*10942STom.Pothier@Sun.COM 	}
874*10942STom.Pothier@Sun.COM 
875*10942STom.Pothier@Sun.COM 	for (n = 0; n < cnt; n++) {
876*10942STom.Pothier@Sun.COM 		if (pairs[n] != NULL)
877*10942STom.Pothier@Sun.COM 			fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
878*10942STom.Pothier@Sun.COM 	}
879*10942STom.Pothier@Sun.COM 
880*10942STom.Pothier@Sun.COM 	return (rc);
881*10942STom.Pothier@Sun.COM }
882*10942STom.Pothier@Sun.COM 
883*10942STom.Pothier@Sun.COM /*
884*10942STom.Pothier@Sun.COM  * pass in strand_apic id
885*10942STom.Pothier@Sun.COM  * return chip's bboards list which has strand_apicid == passed
886*10942STom.Pothier@Sun.COM  * in strand_apic id
887*10942STom.Pothier@Sun.COM  */
888*10942STom.Pothier@Sun.COM static nvlist_t *
889*10942STom.Pothier@Sun.COM smb_bboard(uint_t strand_apicid, uint16_t proc_hdl, int is_proc)
890*10942STom.Pothier@Sun.COM {
891*10942STom.Pothier@Sun.COM 	smbios_hdl_t *shp;
892*10942STom.Pothier@Sun.COM 	smbs_cnt_t *bbstypes;
893*10942STom.Pothier@Sun.COM 	int nb;
894*10942STom.Pothier@Sun.COM 	int bb_smbid;
895*10942STom.Pothier@Sun.COM 	nvlist_t *fmri = NULL;
896*10942STom.Pothier@Sun.COM 	int rc = 0;
897*10942STom.Pothier@Sun.COM 	int bb_strcnt;
898*10942STom.Pothier@Sun.COM 
899*10942STom.Pothier@Sun.COM 	if (x86gentopo_legacy)
900*10942STom.Pothier@Sun.COM 		return (NULL);
901*10942STom.Pothier@Sun.COM 
902*10942STom.Pothier@Sun.COM 	shp = ksmbios;
903*10942STom.Pothier@Sun.COM 	if (shp == NULL) {
904*10942STom.Pothier@Sun.COM 		goto bad;
905*10942STom.Pothier@Sun.COM 	}
906*10942STom.Pothier@Sun.COM 
907*10942STom.Pothier@Sun.COM 	/*
908*10942STom.Pothier@Sun.COM 	 * Type 2 structs : "base board"
909*10942STom.Pothier@Sun.COM 	 */
910*10942STom.Pothier@Sun.COM 	bb_strcnt = smb_cnttypes(shp, SMB_TYPE_BASEBOARD);
911*10942STom.Pothier@Sun.COM 	if (bb_strcnt == 0) {
912*10942STom.Pothier@Sun.COM 		goto bad;
913*10942STom.Pothier@Sun.COM 	}
914*10942STom.Pothier@Sun.COM 
915*10942STom.Pothier@Sun.COM 	bbstypes = smb_create_strcnt(bb_strcnt);
916*10942STom.Pothier@Sun.COM 	if (bbstypes == NULL)  {
917*10942STom.Pothier@Sun.COM 		goto bad;
918*10942STom.Pothier@Sun.COM 	}
919*10942STom.Pothier@Sun.COM 
920*10942STom.Pothier@Sun.COM 	bbstypes->type = SMB_TYPE_BASEBOARD;
921*10942STom.Pothier@Sun.COM 	smb_strcnt(shp, bbstypes);
922*10942STom.Pothier@Sun.COM 	smb_bb_contains(shp, bbstypes);
923*10942STom.Pothier@Sun.COM 
924*10942STom.Pothier@Sun.COM 	for (nb = 0; nb < bbstypes->count; nb++) {
925*10942STom.Pothier@Sun.COM 		if (bbstypes->ids[nb]->visited) {
926*10942STom.Pothier@Sun.COM 			continue;
927*10942STom.Pothier@Sun.COM 		}
928*10942STom.Pothier@Sun.COM 
929*10942STom.Pothier@Sun.COM 		bbstypes->ids[nb]->visited = 1;
930*10942STom.Pothier@Sun.COM 		bb_smbid = bbstypes->ids[nb]->id;
931*10942STom.Pothier@Sun.COM 
932*10942STom.Pothier@Sun.COM 		/*
933*10942STom.Pothier@Sun.COM 		 * check if there is a matching  processor under
934*10942STom.Pothier@Sun.COM 		 * this board. If found, find base board(s) of this proc
935*10942STom.Pothier@Sun.COM 		 * If proc is not in contained handle of a base board and
936*10942STom.Pothier@Sun.COM 		 * there is only one base board in the system, treat that base
937*10942STom.Pothier@Sun.COM 		 * board as the parent of the proc
938*10942STom.Pothier@Sun.COM 		 */
939*10942STom.Pothier@Sun.COM 		if (find_matching_proc(shp, strand_apicid,
940*10942STom.Pothier@Sun.COM 		    bb_smbid, proc_hdl, is_proc) || (bbstypes->count == 1)) {
941*10942STom.Pothier@Sun.COM 			fmri = fm_nvlist_create(NULL);
942*10942STom.Pothier@Sun.COM 			if (fmri == NULL) {
943*10942STom.Pothier@Sun.COM 				smb_free_strcnt(bbstypes, bb_strcnt);
944*10942STom.Pothier@Sun.COM 				goto bad;
945*10942STom.Pothier@Sun.COM 			}
946*10942STom.Pothier@Sun.COM 			/*
947*10942STom.Pothier@Sun.COM 			 * find parent by walking the cont_by_id
948*10942STom.Pothier@Sun.COM 			 */
949*10942STom.Pothier@Sun.COM 			rc = smb_get_bb_fmri(shp, fmri, bb_smbid, bbstypes);
950*10942STom.Pothier@Sun.COM 			smb_free_strcnt(bbstypes, bb_strcnt);
951*10942STom.Pothier@Sun.COM 			if (rc == 0) {
952*10942STom.Pothier@Sun.COM 				return (fmri);
953*10942STom.Pothier@Sun.COM 			} else
954*10942STom.Pothier@Sun.COM 				goto bad;
955*10942STom.Pothier@Sun.COM 		}
956*10942STom.Pothier@Sun.COM 
957*10942STom.Pothier@Sun.COM 	}
958*10942STom.Pothier@Sun.COM 
959*10942STom.Pothier@Sun.COM 	smb_free_strcnt(bbstypes, bb_strcnt);
960*10942STom.Pothier@Sun.COM bad:
961*10942STom.Pothier@Sun.COM 	/* revert to legacy enumeration */
962*10942STom.Pothier@Sun.COM 	x86gentopo_legacy = 1;
963*10942STom.Pothier@Sun.COM 
964*10942STom.Pothier@Sun.COM 	return (NULL);
965*10942STom.Pothier@Sun.COM }
966*10942STom.Pothier@Sun.COM 
967*10942STom.Pothier@Sun.COM nvlist_t *
968*10942STom.Pothier@Sun.COM fm_smb_bboard(uint_t strand_apicid)
969*10942STom.Pothier@Sun.COM {
970*10942STom.Pothier@Sun.COM 	return (smb_bboard(strand_apicid, 0, PROC));
971*10942STom.Pothier@Sun.COM }
972*10942STom.Pothier@Sun.COM 
973*10942STom.Pothier@Sun.COM int
974*10942STom.Pothier@Sun.COM fm_smb_chipinst(uint_t strand_apicid, uint_t *chip_inst, uint16_t *smbiosid)
975*10942STom.Pothier@Sun.COM {
976*10942STom.Pothier@Sun.COM 	int n;
977*10942STom.Pothier@Sun.COM 	smbios_hdl_t *shp;
978*10942STom.Pothier@Sun.COM 	uint16_t proc_id;
979*10942STom.Pothier@Sun.COM 	smbs_cnt_t *pstypes;
980*10942STom.Pothier@Sun.COM 	int strcnt;
981*10942STom.Pothier@Sun.COM 
982*10942STom.Pothier@Sun.COM 	if (x86gentopo_legacy)
983*10942STom.Pothier@Sun.COM 		return (-1);
984*10942STom.Pothier@Sun.COM 
985*10942STom.Pothier@Sun.COM 	shp = ksmbios;
986*10942STom.Pothier@Sun.COM 	if (shp == NULL) {
987*10942STom.Pothier@Sun.COM 		goto bad;
988*10942STom.Pothier@Sun.COM 	}
989*10942STom.Pothier@Sun.COM 
990*10942STom.Pothier@Sun.COM 	strcnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
991*10942STom.Pothier@Sun.COM 	if (strcnt == 0)
992*10942STom.Pothier@Sun.COM 		goto bad;
993*10942STom.Pothier@Sun.COM 
994*10942STom.Pothier@Sun.COM 	pstypes = smb_create_strcnt(strcnt);
995*10942STom.Pothier@Sun.COM 	if (pstypes == NULL)
996*10942STom.Pothier@Sun.COM 		goto bad;
997*10942STom.Pothier@Sun.COM 
998*10942STom.Pothier@Sun.COM 	pstypes->type = SMB_TYPE_PROCESSOR;
999*10942STom.Pothier@Sun.COM 	smb_strcnt(shp, pstypes);
1000*10942STom.Pothier@Sun.COM 	for (n = 0; n < pstypes->count; n++) {
1001*10942STom.Pothier@Sun.COM 		proc_id = pstypes->ids[n]->id;
1002*10942STom.Pothier@Sun.COM 		if (find_matching_apic(shp, proc_id, strand_apicid)) {
1003*10942STom.Pothier@Sun.COM 			*chip_inst = pstypes->ids[n]->inst;
1004*10942STom.Pothier@Sun.COM 			*smbiosid = pstypes->ids[n]->id;
1005*10942STom.Pothier@Sun.COM 			smb_free_strcnt(pstypes, strcnt);
1006*10942STom.Pothier@Sun.COM 			return (0);
1007*10942STom.Pothier@Sun.COM 		}
1008*10942STom.Pothier@Sun.COM 	}
1009*10942STom.Pothier@Sun.COM 	smb_free_strcnt(pstypes, strcnt);
1010*10942STom.Pothier@Sun.COM bad:
1011*10942STom.Pothier@Sun.COM 	/* revert to legacy enumerarion */
1012*10942STom.Pothier@Sun.COM 	x86gentopo_legacy = 1;
1013*10942STom.Pothier@Sun.COM 
1014*10942STom.Pothier@Sun.COM 	return (-1);
1015*10942STom.Pothier@Sun.COM }
1016*10942STom.Pothier@Sun.COM 
1017*10942STom.Pothier@Sun.COM nvlist_t *
1018*10942STom.Pothier@Sun.COM fm_smb_mc_bboards(uint_t bdf)
1019*10942STom.Pothier@Sun.COM {
1020*10942STom.Pothier@Sun.COM 
1021*10942STom.Pothier@Sun.COM 	int i;
1022*10942STom.Pothier@Sun.COM 	smbios_hdl_t *shp;
1023*10942STom.Pothier@Sun.COM 	uint16_t ext_id;
1024*10942STom.Pothier@Sun.COM 	smbios_memarray_ext_t em;
1025*10942STom.Pothier@Sun.COM 	nvlist_t *fmri = NULL;
1026*10942STom.Pothier@Sun.COM 	smbs_cnt_t *mastypes;
1027*10942STom.Pothier@Sun.COM 	int strcnt;
1028*10942STom.Pothier@Sun.COM 
1029*10942STom.Pothier@Sun.COM 	if (x86gentopo_legacy)
1030*10942STom.Pothier@Sun.COM 		return (NULL);
1031*10942STom.Pothier@Sun.COM 
1032*10942STom.Pothier@Sun.COM 	shp = ksmbios;
1033*10942STom.Pothier@Sun.COM 	if (shp == NULL) {
1034*10942STom.Pothier@Sun.COM 		goto bad;
1035*10942STom.Pothier@Sun.COM 	}
1036*10942STom.Pothier@Sun.COM 
1037*10942STom.Pothier@Sun.COM 	strcnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
1038*10942STom.Pothier@Sun.COM 	if (strcnt == 0)
1039*10942STom.Pothier@Sun.COM 		goto bad;
1040*10942STom.Pothier@Sun.COM 
1041*10942STom.Pothier@Sun.COM 	mastypes = smb_create_strcnt(strcnt);
1042*10942STom.Pothier@Sun.COM 	if (mastypes == NULL)
1043*10942STom.Pothier@Sun.COM 		goto bad;
1044*10942STom.Pothier@Sun.COM 
1045*10942STom.Pothier@Sun.COM 	mastypes->type = SUN_OEM_EXT_MEMARRAY;
1046*10942STom.Pothier@Sun.COM 	smb_strcnt(shp, mastypes);
1047*10942STom.Pothier@Sun.COM 	for (i = 0; i < mastypes->count; i++) {
1048*10942STom.Pothier@Sun.COM 		ext_id = mastypes->ids[i]->id;
1049*10942STom.Pothier@Sun.COM 		(void) smbios_info_extmemarray(shp, ext_id, &em);
1050*10942STom.Pothier@Sun.COM 		if (em.smbmae_bdf == bdf) {
1051*10942STom.Pothier@Sun.COM 			fmri = smb_bboard(0, em.smbmae_comp, MC);
1052*10942STom.Pothier@Sun.COM 			smb_free_strcnt(mastypes, strcnt);
1053*10942STom.Pothier@Sun.COM 			return (fmri);
1054*10942STom.Pothier@Sun.COM 		}
1055*10942STom.Pothier@Sun.COM 	}
1056*10942STom.Pothier@Sun.COM 	smb_free_strcnt(mastypes, strcnt);
1057*10942STom.Pothier@Sun.COM bad:
1058*10942STom.Pothier@Sun.COM 	/* revert to legacy enumerarion */
1059*10942STom.Pothier@Sun.COM 	x86gentopo_legacy = 1;
1060*10942STom.Pothier@Sun.COM 
1061*10942STom.Pothier@Sun.COM 	return (NULL);
1062*10942STom.Pothier@Sun.COM }
1063*10942STom.Pothier@Sun.COM 
1064*10942STom.Pothier@Sun.COM int
1065*10942STom.Pothier@Sun.COM fm_smb_mc_chipinst(uint_t bdf, uint_t *chip_inst) {
1066*10942STom.Pothier@Sun.COM 
1067*10942STom.Pothier@Sun.COM 	int i, j;
1068*10942STom.Pothier@Sun.COM 	smbios_hdl_t *shp;
1069*10942STom.Pothier@Sun.COM 	smbios_memarray_ext_t em;
1070*10942STom.Pothier@Sun.COM 	uint16_t ext_id, proc_id;
1071*10942STom.Pothier@Sun.COM 	smbs_cnt_t *mastypes;
1072*10942STom.Pothier@Sun.COM 	smbs_cnt_t *pstypes;
1073*10942STom.Pothier@Sun.COM 	int ma_strcnt, p_strcnt;
1074*10942STom.Pothier@Sun.COM 
1075*10942STom.Pothier@Sun.COM 	if (x86gentopo_legacy)
1076*10942STom.Pothier@Sun.COM 		return (-1);
1077*10942STom.Pothier@Sun.COM 
1078*10942STom.Pothier@Sun.COM 	shp = ksmbios;
1079*10942STom.Pothier@Sun.COM 	if (shp == NULL) {
1080*10942STom.Pothier@Sun.COM 		goto bad;
1081*10942STom.Pothier@Sun.COM 	}
1082*10942STom.Pothier@Sun.COM 
1083*10942STom.Pothier@Sun.COM 	ma_strcnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
1084*10942STom.Pothier@Sun.COM 	if (ma_strcnt == 0)
1085*10942STom.Pothier@Sun.COM 		goto bad;
1086*10942STom.Pothier@Sun.COM 
1087*10942STom.Pothier@Sun.COM 	mastypes = smb_create_strcnt(ma_strcnt);
1088*10942STom.Pothier@Sun.COM 	if (mastypes == NULL)
1089*10942STom.Pothier@Sun.COM 		goto bad;
1090*10942STom.Pothier@Sun.COM 
1091*10942STom.Pothier@Sun.COM 	mastypes->type = SUN_OEM_EXT_MEMARRAY;
1092*10942STom.Pothier@Sun.COM 	smb_strcnt(shp, mastypes);
1093*10942STom.Pothier@Sun.COM 	for (i = 0; i < mastypes->count; i++) {
1094*10942STom.Pothier@Sun.COM 		ext_id = mastypes->ids[i]->id;
1095*10942STom.Pothier@Sun.COM 		(void) smbios_info_extmemarray(shp, ext_id, &em);
1096*10942STom.Pothier@Sun.COM 		    if (em.smbmae_bdf == bdf) {
1097*10942STom.Pothier@Sun.COM 			p_strcnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
1098*10942STom.Pothier@Sun.COM 			if (p_strcnt == 0) {
1099*10942STom.Pothier@Sun.COM 				smb_free_strcnt(mastypes, ma_strcnt);
1100*10942STom.Pothier@Sun.COM 				goto bad;
1101*10942STom.Pothier@Sun.COM 			}
1102*10942STom.Pothier@Sun.COM 
1103*10942STom.Pothier@Sun.COM 			pstypes = smb_create_strcnt(p_strcnt);
1104*10942STom.Pothier@Sun.COM 			if (pstypes == NULL) {
1105*10942STom.Pothier@Sun.COM 				smb_free_strcnt(mastypes, ma_strcnt);
1106*10942STom.Pothier@Sun.COM 				goto bad;
1107*10942STom.Pothier@Sun.COM 			}
1108*10942STom.Pothier@Sun.COM 
1109*10942STom.Pothier@Sun.COM 			pstypes->type = SMB_TYPE_PROCESSOR;
1110*10942STom.Pothier@Sun.COM 			smb_strcnt(shp, pstypes);
1111*10942STom.Pothier@Sun.COM 			for (j = 0; j < pstypes->count; j++) {
1112*10942STom.Pothier@Sun.COM 				proc_id = pstypes->ids[j]->id;
1113*10942STom.Pothier@Sun.COM 				if (proc_id == em.smbmae_comp) {
1114*10942STom.Pothier@Sun.COM 					*chip_inst = pstypes->ids[j]->inst;
1115*10942STom.Pothier@Sun.COM 					smb_free_strcnt(mastypes, ma_strcnt);
1116*10942STom.Pothier@Sun.COM 					smb_free_strcnt(pstypes, p_strcnt);
1117*10942STom.Pothier@Sun.COM 					return (0);
1118*10942STom.Pothier@Sun.COM 				}
1119*10942STom.Pothier@Sun.COM 			}
1120*10942STom.Pothier@Sun.COM 		}
1121*10942STom.Pothier@Sun.COM 	}
1122*10942STom.Pothier@Sun.COM 	smb_free_strcnt(mastypes, ma_strcnt);
1123*10942STom.Pothier@Sun.COM 	smb_free_strcnt(pstypes, p_strcnt);
1124*10942STom.Pothier@Sun.COM bad:
1125*10942STom.Pothier@Sun.COM 	/* revert to legacy enumeration */
1126*10942STom.Pothier@Sun.COM 	x86gentopo_legacy = 1;
1127*10942STom.Pothier@Sun.COM 
1128*10942STom.Pothier@Sun.COM 	return (-1);
1129*10942STom.Pothier@Sun.COM }
1130