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