xref: /illumos-gate/usr/src/uts/intel/os/fmsmb.c (revision 584b574a)
1074bb90dSTom Pothier /*
2074bb90dSTom Pothier  * CDDL HEADER START
3074bb90dSTom Pothier  *
4074bb90dSTom Pothier  * The contents of this file are subject to the terms of the
5074bb90dSTom Pothier  * Common Development and Distribution License (the "License").
6074bb90dSTom Pothier  * You may not use this file except in compliance with the License.
7074bb90dSTom Pothier  *
8074bb90dSTom Pothier  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9074bb90dSTom Pothier  * or http://www.opensolaris.org/os/licensing.
10074bb90dSTom Pothier  * See the License for the specific language governing permissions
11074bb90dSTom Pothier  * and limitations under the License.
12074bb90dSTom Pothier  *
13074bb90dSTom Pothier  * When distributing Covered Code, include this CDDL HEADER in each
14074bb90dSTom Pothier  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15074bb90dSTom Pothier  * If applicable, add the following below this CDDL HEADER, with the
16074bb90dSTom Pothier  * fields enclosed by brackets "[]" replaced with your own identifying
17074bb90dSTom Pothier  * information: Portions Copyright [yyyy] [name of copyright owner]
18074bb90dSTom Pothier  *
19074bb90dSTom Pothier  * CDDL HEADER END
20074bb90dSTom Pothier  */
21074bb90dSTom Pothier /*
2211ccb6bfSTom Pothier  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23074bb90dSTom Pothier  * Use is subject to license terms.
24074bb90dSTom Pothier  */
25074bb90dSTom Pothier 
26074bb90dSTom Pothier #include <sys/types.h>
27074bb90dSTom Pothier #include <sys/time.h>
28074bb90dSTom Pothier #include <sys/nvpair.h>
29074bb90dSTom Pothier #include <sys/cmn_err.h>
30074bb90dSTom Pothier #include <sys/fm/util.h>
31074bb90dSTom Pothier #include <sys/fm/protocol.h>
32074bb90dSTom Pothier #include <sys/smbios.h>
33074bb90dSTom Pothier #include <sys/smbios_impl.h>
34074bb90dSTom Pothier 
35074bb90dSTom Pothier /*
36074bb90dSTom Pothier  * Variable used to determine if the x86 generic topology enumerator will
37074bb90dSTom Pothier  * revert to legacy enumeration. I.E. Big Kill Switch... tunable via
38074bb90dSTom Pothier  * /etc/system
39074bb90dSTom Pothier  */
40074bb90dSTom Pothier int x86gentopo_legacy = 0;
41074bb90dSTom Pothier 
42074bb90dSTom Pothier #define	MC		0
43074bb90dSTom Pothier #define	PROC		1
44074bb90dSTom Pothier #define	MAX_PAIRS	20
45074bb90dSTom Pothier #define	MAX_CONT	40
46074bb90dSTom Pothier 
47074bb90dSTom Pothier typedef struct bbindex  {
48074bb90dSTom Pothier 	int count;
49074bb90dSTom Pothier 	uint16_t index[MAX_PAIRS];
50074bb90dSTom Pothier } bbindex_t;
51074bb90dSTom Pothier 
52074bb90dSTom Pothier /*
53074bb90dSTom Pothier  * the enum values come from DMTF
54074bb90dSTom Pothier  */
55074bb90dSTom Pothier typedef enum baseb {
56074bb90dSTom Pothier 	BB_BAD = 0,		/* There is no bb value 0 */
57074bb90dSTom Pothier 	BB_UNKNOWN,		/* Unknown */
58074bb90dSTom Pothier 	BB_OTHER,		/* Other */
59074bb90dSTom Pothier 	BB_BLADE,		/* Server Blade */
60074bb90dSTom Pothier 	BB_CONNSW,		/* Connectivity Switch */
61074bb90dSTom Pothier 	BB_SMM,			/* System Management Module */
62074bb90dSTom Pothier 	BB_PROCMOD,		/* Processor Module */
63074bb90dSTom Pothier 	BB_IOMOD,		/* I/O Module */
64074bb90dSTom Pothier 	BB_MEMMOD,		/* Memory Module */
65074bb90dSTom Pothier 	BB_DBOARD,		/* Daughter Board */
66074bb90dSTom Pothier 	BB_MBOARD,		/* Motherboard */
67074bb90dSTom Pothier 	BB_PROCMMOD,		/* Processor/Memory Module */
68074bb90dSTom Pothier 	BB_PROCIOMOD,		/* Processor/IO Module */
69074bb90dSTom Pothier 	BB_ICONNBD		/* Interconnect Board */
70074bb90dSTom Pothier } bbd_t;
71074bb90dSTom Pothier 
72074bb90dSTom Pothier static struct bboard_type {
73074bb90dSTom Pothier 	bbd_t		baseb;
74074bb90dSTom Pothier 	const char	*name;
75074bb90dSTom Pothier } bbd_type[] = {
76074bb90dSTom Pothier 	{BB_BAD,		NULL},
77074bb90dSTom Pothier 	{BB_UNKNOWN,		"unknown"},
78074bb90dSTom Pothier 	{BB_OTHER,		"other"},
79074bb90dSTom Pothier 	{BB_BLADE,		"systemboard"},
80074bb90dSTom Pothier 	{BB_CONNSW,		"connswitch"},
81074bb90dSTom Pothier 	{BB_SMM,		"smmodule"},
82074bb90dSTom Pothier 	{BB_PROCMOD,		"cpuboard"},
83074bb90dSTom Pothier 	{BB_IOMOD,		"ioboard"},
84074bb90dSTom Pothier 	{BB_MEMMOD,		"memboard"},
85074bb90dSTom Pothier 	{BB_DBOARD,		"systemboard"},
86074bb90dSTom Pothier 	{BB_MBOARD,		"motherboard"},
87074bb90dSTom Pothier 	{BB_PROCMMOD,		"systemboard"},
88074bb90dSTom Pothier 	{BB_PROCIOMOD,		"systemboard"},
89074bb90dSTom Pothier 	{BB_ICONNBD,		"systemboard"}
90074bb90dSTom Pothier };
91074bb90dSTom Pothier 
92074bb90dSTom Pothier typedef struct smbs_con_ids {
93074bb90dSTom Pothier 	int id;
94074bb90dSTom Pothier 	int inst;
95074bb90dSTom Pothier 	int cont_count;
96074bb90dSTom Pothier 	uint16_t **cont_ids;
97074bb90dSTom Pothier 	int cont_by_id;
98074bb90dSTom Pothier 	int visited;
99074bb90dSTom Pothier } smbs_con_ids_t;
100074bb90dSTom Pothier 
101074bb90dSTom Pothier typedef struct smbs_cnt {
102074bb90dSTom Pothier 	int type;			/* SMBIOS stucture type */
103074bb90dSTom Pothier 	int count;			/* number of table entries */
104074bb90dSTom Pothier 	smbs_con_ids_t **ids;		/* SMBIOS table entry id(s) */
105074bb90dSTom Pothier } smbs_cnt_t;
106074bb90dSTom Pothier 
107074bb90dSTom Pothier /*
108074bb90dSTom Pothier  * dynamically allocate the storage for the smbs_cnt_t
109074bb90dSTom Pothier  */
110074bb90dSTom Pothier static smbs_cnt_t *
smb_create_strcnt(int count)111074bb90dSTom Pothier smb_create_strcnt(int count)
112074bb90dSTom Pothier {
113074bb90dSTom Pothier 	smbs_cnt_t *types = NULL;
114074bb90dSTom Pothier 	int i, j;
115074bb90dSTom Pothier 
116074bb90dSTom Pothier 	types = kmem_zalloc(sizeof (smbs_cnt_t), KM_SLEEP);
117074bb90dSTom Pothier 
118074bb90dSTom Pothier 	types->ids = (smbs_con_ids_t **)kmem_zalloc(
119074bb90dSTom Pothier 	    count * sizeof (smbs_con_ids_t *), KM_SLEEP);
120074bb90dSTom Pothier 
121074bb90dSTom Pothier 	for (i = 0; i < count; i++) {
122074bb90dSTom Pothier 		types->ids[i] = (smbs_con_ids_t *)kmem_zalloc(
123074bb90dSTom Pothier 		    sizeof (smbs_con_ids_t), KM_SLEEP);
124074bb90dSTom Pothier 	}
125074bb90dSTom Pothier 
126074bb90dSTom Pothier 	for (i = 0; i < count; i++) {
127074bb90dSTom Pothier 		types->ids[i]->cont_ids = (uint16_t **)kmem_zalloc(
128074bb90dSTom Pothier 		    MAX_CONT * sizeof (uint16_t *), KM_SLEEP);
129074bb90dSTom Pothier 	}
130074bb90dSTom Pothier 
131074bb90dSTom Pothier 	for (i = 0; i < count; i++) {
132074bb90dSTom Pothier 		for (j = 0; j < MAX_CONT; j++) {
133074bb90dSTom Pothier 			types->ids[i]->cont_ids[j] = (uint16_t *)kmem_zalloc(
134074bb90dSTom Pothier 			    sizeof (uint16_t), KM_SLEEP);
135074bb90dSTom Pothier 		}
136074bb90dSTom Pothier 	}
137074bb90dSTom Pothier 	return (types);
138074bb90dSTom Pothier }
139074bb90dSTom Pothier 
140074bb90dSTom Pothier /*
141074bb90dSTom Pothier  * free the smbs_cnt_t memory
142074bb90dSTom Pothier  */
143074bb90dSTom Pothier static void
smb_free_strcnt(smbs_cnt_t * types,int count)144074bb90dSTom Pothier smb_free_strcnt(smbs_cnt_t *types, int count)
145074bb90dSTom Pothier {
146074bb90dSTom Pothier 	int i, j;
147074bb90dSTom Pothier 
148074bb90dSTom Pothier 	if (types == NULL)
149074bb90dSTom Pothier 		return;
150074bb90dSTom Pothier 
151074bb90dSTom Pothier 	for (i = 0; i < count; i++) {
152074bb90dSTom Pothier 		for (j = 0; j < MAX_CONT; j++) {
153074bb90dSTom Pothier 			if (types->ids[i]->cont_ids[j] != NULL)
154074bb90dSTom Pothier 				kmem_free(types->ids[i]->cont_ids[j],
155074bb90dSTom Pothier 				    sizeof (uint16_t));
156074bb90dSTom Pothier 		}
157074bb90dSTom Pothier 	}
158074bb90dSTom Pothier 
159074bb90dSTom Pothier 	for (i = 0; i < count; i++) {
160074bb90dSTom Pothier 		if (types->ids[i]->cont_ids != NULL)
161074bb90dSTom Pothier 			kmem_free(types->ids[i]->cont_ids,
162074bb90dSTom Pothier 			    MAX_CONT * sizeof (uint16_t *));
163074bb90dSTom Pothier 	}
164074bb90dSTom Pothier 
165074bb90dSTom Pothier 	for (i = 0; i < count; i++) {
166074bb90dSTom Pothier 		if (types->ids[i] != NULL)
167074bb90dSTom Pothier 			kmem_free(types->ids[i], sizeof (smbs_con_ids_t));
168074bb90dSTom Pothier 	}
169074bb90dSTom Pothier 
170074bb90dSTom Pothier 	if (types->ids != NULL)
171074bb90dSTom Pothier 		kmem_free(types->ids, count * sizeof (smbs_con_ids_t *));
172074bb90dSTom Pothier 
173074bb90dSTom Pothier 	if (types != NULL)
174074bb90dSTom Pothier 		kmem_free(types, sizeof (smbs_cnt_t));
175074bb90dSTom Pothier 
176074bb90dSTom Pothier }
177074bb90dSTom Pothier 
178074bb90dSTom Pothier /*
179074bb90dSTom Pothier  * count number of the structure type in the ksmbios
180074bb90dSTom Pothier  */
181074bb90dSTom Pothier static int
smb_cnttypes(smbios_hdl_t * shp,int type)182074bb90dSTom Pothier smb_cnttypes(smbios_hdl_t *shp, int type)
183074bb90dSTom Pothier {
184074bb90dSTom Pothier 	const smb_struct_t *sp = shp->sh_structs;
185074bb90dSTom Pothier 	int nstructs = shp->sh_nstructs;
186074bb90dSTom Pothier 	int i;
187074bb90dSTom Pothier 	int cnt = 0;
188074bb90dSTom Pothier 
189074bb90dSTom Pothier 	for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
190074bb90dSTom Pothier 		if (sp->smbst_hdr->smbh_type == type)
191074bb90dSTom Pothier 			cnt++;
192074bb90dSTom Pothier 	}
193074bb90dSTom Pothier 	return (cnt);
194074bb90dSTom Pothier }
195074bb90dSTom Pothier 
196074bb90dSTom Pothier static void
smb_strcnt(smbios_hdl_t * shp,smbs_cnt_t * stype)197074bb90dSTom Pothier smb_strcnt(smbios_hdl_t *shp, smbs_cnt_t *stype)
198074bb90dSTom Pothier {
199074bb90dSTom Pothier 	const smb_struct_t *sp = shp->sh_structs;
200074bb90dSTom Pothier 	int nstructs = shp->sh_nstructs;
201074bb90dSTom Pothier 	smbios_bboard_t bb;
202074bb90dSTom Pothier 	int i, cnt;
203074bb90dSTom Pothier 	int mb_cnt = 0;
204074bb90dSTom Pothier 	int cpub_cnt = 0;
205074bb90dSTom Pothier 	int sysb_cnt = 0;
206074bb90dSTom Pothier 	int memb_cnt = 0;
207074bb90dSTom Pothier 	int iob_cnt = 0;
208074bb90dSTom Pothier 	int inst = 0;
209074bb90dSTom Pothier 	int rc = 0;
210074bb90dSTom Pothier 
211074bb90dSTom Pothier 	for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
212074bb90dSTom Pothier 		if (sp->smbst_hdr->smbh_type == stype->type) {
213074bb90dSTom Pothier 			stype->ids[cnt]->id = sp->smbst_hdr->smbh_hdl;
214074bb90dSTom Pothier 			stype->ids[cnt]->inst = cnt;
215074bb90dSTom Pothier 			stype->ids[cnt]->visited = 0;
216074bb90dSTom Pothier 			stype->ids[cnt]->cont_by_id = -1;
217074bb90dSTom Pothier 			if (stype->type == SMB_TYPE_BASEBOARD) {
218074bb90dSTom Pothier 				rc = smbios_info_bboard(shp,
219074bb90dSTom Pothier 				    stype->ids[cnt]->id, &bb);
220074bb90dSTom Pothier 				if (rc == 0) {
221074bb90dSTom Pothier 					switch (bb.smbb_type) {
222074bb90dSTom Pothier 						case SMB_BBT_PROC :
223074bb90dSTom Pothier 							inst = cpub_cnt++;
224074bb90dSTom Pothier 							break;
225074bb90dSTom Pothier 						case SMB_BBT_IO :
226074bb90dSTom Pothier 							inst = iob_cnt++;
227074bb90dSTom Pothier 							break;
228074bb90dSTom Pothier 						case SMB_BBT_MEM :
229074bb90dSTom Pothier 							inst = memb_cnt++;
230074bb90dSTom Pothier 							break;
231074bb90dSTom Pothier 						case SMB_BBT_MOTHER :
232074bb90dSTom Pothier 							inst = mb_cnt++;
233074bb90dSTom Pothier 							break;
234074bb90dSTom Pothier 						default:
235074bb90dSTom Pothier 							/*
236074bb90dSTom Pothier 							 * SMB_BBT_UNKNOWN
237074bb90dSTom Pothier 							 * SMB_BBT_OTHER
238074bb90dSTom Pothier 							 * SMB_BBT_SBLADE
239074bb90dSTom Pothier 							 * SMB_BBT_CSWITCH
240074bb90dSTom Pothier 							 * SMB_BBT_SMM
241074bb90dSTom Pothier 							 * SMB_BBT_DAUGHTER
242074bb90dSTom Pothier 							 * SMB_BBT_PROCMEM
243074bb90dSTom Pothier 							 * SMB_BBT_PROCIO
244074bb90dSTom Pothier 							 * SMB_BBT_INTER
245074bb90dSTom Pothier 							 */
246074bb90dSTom Pothier 							inst = sysb_cnt++;
247074bb90dSTom Pothier 							break;
248074bb90dSTom Pothier 					}
249074bb90dSTom Pothier 					stype->ids[cnt]->inst = inst;
250074bb90dSTom Pothier 				}
251074bb90dSTom Pothier 			}
252074bb90dSTom Pothier 			cnt++;
253074bb90dSTom Pothier 		}
254074bb90dSTom Pothier 	}
255074bb90dSTom Pothier 	stype->count = cnt;
256074bb90dSTom Pothier }
257074bb90dSTom Pothier 
258074bb90dSTom Pothier /*
259074bb90dSTom Pothier  * Go through the smbios structures looking for type 2. Fill in
260074bb90dSTom Pothier  * the cont_id and cont_by_id for each type 2
261074bb90dSTom Pothier  *
262074bb90dSTom Pothier  */
263074bb90dSTom Pothier static void
smb_bb_contains(smbios_hdl_t * shp,smbs_cnt_t * stype)264074bb90dSTom Pothier smb_bb_contains(smbios_hdl_t *shp, smbs_cnt_t *stype)
265074bb90dSTom Pothier {
266074bb90dSTom Pothier 	int i, j, cnt, c;
267074bb90dSTom Pothier 	uint_t cont_count;
268074bb90dSTom Pothier 	const smb_struct_t *spt;
269074bb90dSTom Pothier 	smbios_bboard_t smb_bb;
270074bb90dSTom Pothier 	uint16_t bb_id, cont_id;
271074bb90dSTom Pothier 	uint_t cont_len;
272074bb90dSTom Pothier 	id_t *cont_hdl = NULL;
273074bb90dSTom Pothier 	int rc;
274074bb90dSTom Pothier 
275074bb90dSTom Pothier 	for (cnt = 0; cnt < stype->count; cnt++) {
276074bb90dSTom Pothier 		bb_id = stype->ids[cnt]->id;
277074bb90dSTom Pothier 		(void) smbios_info_bboard(shp, stype->ids[cnt]->id, &smb_bb);
278074bb90dSTom Pothier 		cont_count = (uint_t)smb_bb.smbb_contn;
279074bb90dSTom Pothier 		if (cont_count == 0) {
280074bb90dSTom Pothier 			continue;
281074bb90dSTom Pothier 		}
282074bb90dSTom Pothier 
283074bb90dSTom Pothier 		cont_len = sizeof (id_t);
284074bb90dSTom Pothier 		cont_hdl = kmem_zalloc(cont_count * cont_len, KM_SLEEP);
285074bb90dSTom Pothier 		if (cont_hdl == NULL)
286074bb90dSTom Pothier 			continue;
287074bb90dSTom Pothier 
288074bb90dSTom Pothier 		rc = smbios_info_contains(shp, stype->ids[cnt]->id,
289074bb90dSTom Pothier 		    cont_count, cont_hdl);
290074bb90dSTom Pothier 		if (rc > SMB_CONT_MAX) {
291074bb90dSTom Pothier 			kmem_free(cont_hdl, cont_count * cont_len);
292074bb90dSTom Pothier 			continue;
293074bb90dSTom Pothier 		}
294074bb90dSTom Pothier 		cont_count = MIN(rc, cont_count);
295074bb90dSTom Pothier 
296074bb90dSTom Pothier 		/*
297074bb90dSTom Pothier 		 * fill in the type 2 and type 4 ids which are
298074bb90dSTom Pothier 		 * contained in this type 2
299074bb90dSTom Pothier 		 */
300074bb90dSTom Pothier 		c = 0;
301074bb90dSTom Pothier 		for (j = 0; j < cont_count; j++) {
302074bb90dSTom Pothier 			cont_id = (uint16_t)cont_hdl[j];
303074bb90dSTom Pothier 			spt = smb_lookup_id(shp, cont_id);
304074bb90dSTom Pothier 			if (spt->smbst_hdr->smbh_type == SMB_TYPE_BASEBOARD ||
305074bb90dSTom Pothier 			    spt->smbst_hdr->smbh_type == SMB_TYPE_PROCESSOR) {
306074bb90dSTom Pothier 				*stype->ids[cnt]->cont_ids[c] = cont_id;
307074bb90dSTom Pothier 				c++;
308074bb90dSTom Pothier 			}
309074bb90dSTom Pothier 
310074bb90dSTom Pothier 			if (spt->smbst_hdr->smbh_type == SMB_TYPE_BASEBOARD) {
311074bb90dSTom Pothier 				for (i = 0; i < stype->count; i++) {
312074bb90dSTom Pothier 					if (stype->ids[i]->id == cont_id) {
313074bb90dSTom Pothier 						stype->ids[i]->cont_by_id =
314074bb90dSTom Pothier 						    bb_id;
315074bb90dSTom Pothier 					}
316074bb90dSTom Pothier 				}
317074bb90dSTom Pothier 			}
318074bb90dSTom Pothier 
319074bb90dSTom Pothier 		}
320074bb90dSTom Pothier 		stype->ids[cnt]->cont_count = c;
321074bb90dSTom Pothier 		if (cont_hdl != NULL)
322074bb90dSTom Pothier 			kmem_free(cont_hdl, cont_count * cont_len);
323074bb90dSTom Pothier 	}
324074bb90dSTom Pothier }
325074bb90dSTom Pothier 
326074bb90dSTom Pothier /*
327074bb90dSTom Pothier  * Verify SMBIOS structures for x86 generic topology.
328074bb90dSTom Pothier  *
329074bb90dSTom Pothier  * Return (0) on success.
330074bb90dSTom Pothier  */
331074bb90dSTom Pothier static int
fm_smb_check(smbios_hdl_t * shp)332074bb90dSTom Pothier fm_smb_check(smbios_hdl_t *shp)
333074bb90dSTom Pothier {
33411ccb6bfSTom Pothier 	int i, j;
335074bb90dSTom Pothier 	int bb_cnt = 0;
336074bb90dSTom Pothier 	int pr_cnt = 0;
337074bb90dSTom Pothier 	int expr_cnt = 0;
338074bb90dSTom Pothier 	int ma_cnt = 0;
339074bb90dSTom Pothier 	int exma_cnt = 0;
340074bb90dSTom Pothier 	int mdev_cnt = 0;
341074bb90dSTom Pothier 	int exmdev_cnt = 0;
342074bb90dSTom Pothier 	uint16_t bb_id;
343074bb90dSTom Pothier 	uint16_t pr_id, expr_id;
344074bb90dSTom Pothier 	uint16_t ma_id, exma_id;
345074bb90dSTom Pothier 	uint16_t mdev_id, exmdev_id;
34611ccb6bfSTom Pothier 	uint16_t *sys_ma;
347074bb90dSTom Pothier 	smbios_bboard_t bb;
348074bb90dSTom Pothier 	smbios_processor_ext_t exproc;
34911ccb6bfSTom Pothier 	smbios_memarray_t ma;
350074bb90dSTom Pothier 	smbios_memarray_ext_t exma;
35111ccb6bfSTom Pothier 	smbios_memdevice_t mdev;
352074bb90dSTom Pothier 	smbios_memdevice_ext_t exmdev;
353074bb90dSTom Pothier 	smbs_cnt_t *bb_stype;
354074bb90dSTom Pothier 	smbs_cnt_t *pr_stype, *expr_stype;
355074bb90dSTom Pothier 	smbs_cnt_t *ma_stype, *exma_stype;
356074bb90dSTom Pothier 	smbs_cnt_t *mdev_stype, *exmdev_stype;
357074bb90dSTom Pothier 
358074bb90dSTom Pothier 	/*
359074bb90dSTom Pothier 	 * Verify the existance of the requuired extended OEM-Specific
360074bb90dSTom Pothier 	 * structures and they coincide with the structures they extend
361074bb90dSTom Pothier 	 * (e.g. the number of extended processor structures equal the
362074bb90dSTom Pothier 	 * number of processor structures).
363074bb90dSTom Pothier 	 */
364074bb90dSTom Pothier 	pr_cnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
365074bb90dSTom Pothier 	expr_cnt = smb_cnttypes(shp, SUN_OEM_EXT_PROCESSOR);
366074bb90dSTom Pothier 	ma_cnt = smb_cnttypes(shp, SMB_TYPE_MEMARRAY);
367074bb90dSTom Pothier 	exma_cnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
368074bb90dSTom Pothier 	mdev_cnt = smb_cnttypes(shp, SMB_TYPE_MEMDEVICE);
369074bb90dSTom Pothier 	exmdev_cnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMDEVICE);
370074bb90dSTom Pothier 	if (expr_cnt == 0 || exma_cnt == 0 || exmdev_cnt == 0 ||
37111ccb6bfSTom Pothier 	    expr_cnt != pr_cnt || exma_cnt > ma_cnt ||
37211ccb6bfSTom Pothier 	    exmdev_cnt > mdev_cnt) {
373074bb90dSTom Pothier #ifdef	DEBUG
3747991dd24STom Pothier 		cmn_err(CE_NOTE, "!Structure mismatch: ext_proc (%d) "
375074bb90dSTom Pothier 		    "proc (%d) ext_ma (%d) ma (%d) ext_mdev (%d) mdev (%d)\n",
376074bb90dSTom Pothier 		    expr_cnt, pr_cnt, exma_cnt, ma_cnt, exmdev_cnt,
377074bb90dSTom Pothier 		    mdev_cnt);
378074bb90dSTom Pothier #endif	/* DEBUG */
379074bb90dSTom Pothier 		return (-1);
380074bb90dSTom Pothier 	}
381074bb90dSTom Pothier 
382074bb90dSTom Pothier 	/*
383074bb90dSTom Pothier 	 * Verify the OEM-Specific structrures are correctly
384074bb90dSTom Pothier 	 * linked to the SMBIOS structure types they extend.
385074bb90dSTom Pothier 	 */
386074bb90dSTom Pothier 
387074bb90dSTom Pothier 	/* allocate processor stypes */
388074bb90dSTom Pothier 	pr_stype = smb_create_strcnt(pr_cnt);
389074bb90dSTom Pothier 	expr_stype = smb_create_strcnt(expr_cnt);
390074bb90dSTom Pothier 
391074bb90dSTom Pothier 	/* fill in stypes */
392074bb90dSTom Pothier 	pr_stype->type = SMB_TYPE_PROCESSOR;
393074bb90dSTom Pothier 	smb_strcnt(shp, pr_stype);
394074bb90dSTom Pothier 	expr_stype->type = SUN_OEM_EXT_PROCESSOR;
395074bb90dSTom Pothier 	smb_strcnt(shp, expr_stype);
396074bb90dSTom Pothier 
397074bb90dSTom Pothier 	/* verify the ext proc struct belong to the proc struct */
398074bb90dSTom Pothier 	for (i = 0; i < pr_cnt; i++) {
399074bb90dSTom Pothier 		pr_id = pr_stype->ids[i]->id;
400074bb90dSTom Pothier 		expr_id = expr_stype->ids[i]->id;
401074bb90dSTom Pothier 		(void) smbios_info_extprocessor(shp, expr_id, &exproc);
402074bb90dSTom Pothier 		if (exproc.smbpe_processor != pr_id) {
403074bb90dSTom Pothier #ifdef	DEBUG
4047991dd24STom Pothier 			cmn_err(CE_NOTE, "!Processor struct linkage (%d)", i);
405074bb90dSTom Pothier #endif	/* DEBUG */
406074bb90dSTom Pothier 			smb_free_strcnt(pr_stype, pr_cnt);
407074bb90dSTom Pothier 			smb_free_strcnt(expr_stype, expr_cnt);
408074bb90dSTom Pothier 			return (-1);
409074bb90dSTom Pothier 		}
410074bb90dSTom Pothier 	}
411074bb90dSTom Pothier 
412074bb90dSTom Pothier 	/* free stypes */
413074bb90dSTom Pothier 	smb_free_strcnt(pr_stype, pr_cnt);
414074bb90dSTom Pothier 	smb_free_strcnt(expr_stype, expr_cnt);
415074bb90dSTom Pothier 
416074bb90dSTom Pothier 	/* allocate memory array stypes */
417074bb90dSTom Pothier 	ma_stype = smb_create_strcnt(ma_cnt);
418074bb90dSTom Pothier 	exma_stype = smb_create_strcnt(exma_cnt);
41911ccb6bfSTom Pothier 	sys_ma = kmem_zalloc(sizeof (uint16_t) * ma_cnt, KM_SLEEP);
420074bb90dSTom Pothier 
421074bb90dSTom Pothier 	/* fill in stypes */
422074bb90dSTom Pothier 	ma_stype->type = SMB_TYPE_MEMARRAY;
423074bb90dSTom Pothier 	smb_strcnt(shp, ma_stype);
424074bb90dSTom Pothier 	exma_stype->type = SUN_OEM_EXT_MEMARRAY;
425074bb90dSTom Pothier 	smb_strcnt(shp, exma_stype);
426074bb90dSTom Pothier 
427074bb90dSTom Pothier 	/* verify linkage from ext memarray struct to memarray struct */
428074bb90dSTom Pothier 	for (i = 0; i < ma_cnt; i++) {
42911ccb6bfSTom Pothier 		sys_ma[i] = (uint16_t)-1;
430074bb90dSTom Pothier 		ma_id = ma_stype->ids[i]->id;
43111ccb6bfSTom Pothier 		(void) smbios_info_memarray(shp, ma_id, &ma);
43211ccb6bfSTom Pothier 		if (ma.smbma_use != SMB_MAU_SYSTEM)
43311ccb6bfSTom Pothier 			continue;
43411ccb6bfSTom Pothier 		/* this memarray is system memory */
43511ccb6bfSTom Pothier 		sys_ma[i] = ma_id;
436074bb90dSTom Pothier 		exma_id = exma_stype->ids[i]->id;
437074bb90dSTom Pothier 		(void) smbios_info_extmemarray(shp, exma_id, &exma);
438074bb90dSTom Pothier 		if (exma.smbmae_ma != ma_id) {
439074bb90dSTom Pothier #ifdef	DEBUG
4407991dd24STom Pothier 			cmn_err(CE_NOTE,
4417991dd24STom Pothier 			    "!Memory Array struct linkage (%d)", i);
442074bb90dSTom Pothier #endif	/* DEBUG */
443074bb90dSTom Pothier 			smb_free_strcnt(ma_stype, ma_cnt);
444074bb90dSTom Pothier 			smb_free_strcnt(exma_stype, exma_cnt);
44511ccb6bfSTom Pothier 			kmem_free(sys_ma, sizeof (uint16_t) * ma_cnt);
446074bb90dSTom Pothier 			return (-1);
447074bb90dSTom Pothier 		}
448074bb90dSTom Pothier 	}
449074bb90dSTom Pothier 
450074bb90dSTom Pothier 	/* free stypes */
451074bb90dSTom Pothier 	smb_free_strcnt(ma_stype, ma_cnt);
452074bb90dSTom Pothier 	smb_free_strcnt(exma_stype, exma_cnt);
453074bb90dSTom Pothier 
454074bb90dSTom Pothier 	/* allocate memory device stypes */
455074bb90dSTom Pothier 	mdev_stype = smb_create_strcnt(mdev_cnt);
456074bb90dSTom Pothier 	exmdev_stype = smb_create_strcnt(exmdev_cnt);
457074bb90dSTom Pothier 
458074bb90dSTom Pothier 	/* fill in stypes */
459074bb90dSTom Pothier 	mdev_stype->type = SMB_TYPE_MEMDEVICE;
460074bb90dSTom Pothier 	smb_strcnt(shp, mdev_stype);
461074bb90dSTom Pothier 	exmdev_stype->type = SUN_OEM_EXT_MEMDEVICE;
462074bb90dSTom Pothier 	smb_strcnt(shp, exmdev_stype);
463074bb90dSTom Pothier 
464074bb90dSTom Pothier 	/* verify linkage */
465074bb90dSTom Pothier 	for (i = 0; i < mdev_cnt; i++) {
466074bb90dSTom Pothier 		mdev_id = mdev_stype->ids[i]->id;
46711ccb6bfSTom Pothier 		(void) smbios_info_memdevice(shp, mdev_id, &mdev);
46811ccb6bfSTom Pothier 		/* only check system memory devices */
46911ccb6bfSTom Pothier 		for (j = 0; j < ma_cnt; j++) {
47011ccb6bfSTom Pothier 			if (sys_ma[j] == mdev.smbmd_array)
47111ccb6bfSTom Pothier 				break;
47211ccb6bfSTom Pothier 		}
47311ccb6bfSTom Pothier 		if (j == ma_cnt)
47411ccb6bfSTom Pothier 			continue;
475074bb90dSTom Pothier 		exmdev_id = exmdev_stype->ids[i]->id;
476074bb90dSTom Pothier 		(void) smbios_info_extmemdevice(shp, exmdev_id, &exmdev);
477074bb90dSTom Pothier 		if (exmdev.smbmdeve_md != mdev_id) {
478074bb90dSTom Pothier #ifdef	DEBUG
4797991dd24STom Pothier 			cmn_err(CE_NOTE, "!Memory Device struct linkage (%d)",
480074bb90dSTom Pothier 			    i);
481074bb90dSTom Pothier #endif	/* DEBUG */
482074bb90dSTom Pothier 			smb_free_strcnt(mdev_stype, mdev_cnt);
483074bb90dSTom Pothier 			smb_free_strcnt(exmdev_stype, exmdev_cnt);
48411ccb6bfSTom Pothier 			kmem_free(sys_ma, sizeof (uint16_t) * ma_cnt);
485074bb90dSTom Pothier 			return (-1);
486074bb90dSTom Pothier 		}
487074bb90dSTom Pothier 	}
488074bb90dSTom Pothier 
489074bb90dSTom Pothier 	/* free stypes */
490074bb90dSTom Pothier 	smb_free_strcnt(mdev_stype, mdev_cnt);
491074bb90dSTom Pothier 	smb_free_strcnt(exmdev_stype, exmdev_cnt);
49211ccb6bfSTom Pothier 	kmem_free(sys_ma, sizeof (uint16_t) * ma_cnt);
493074bb90dSTom Pothier 
494074bb90dSTom Pothier 	/*
495074bb90dSTom Pothier 	 * Verify the presece of contained handles if there are more
496074bb90dSTom Pothier 	 * than one Type-2 (Base Board) structures.
497074bb90dSTom Pothier 	 */
498074bb90dSTom Pothier 	bb_cnt = smb_cnttypes(shp, SMB_TYPE_BASEBOARD);
499074bb90dSTom Pothier 	if (bb_cnt > 1) {
500074bb90dSTom Pothier 		/* allocate base board stypes */
501074bb90dSTom Pothier 		bb_stype = smb_create_strcnt(bb_cnt);
502074bb90dSTom Pothier 
503074bb90dSTom Pothier 		/* fill in stypes */
504074bb90dSTom Pothier 		bb_stype->type = SMB_TYPE_BASEBOARD;
505074bb90dSTom Pothier 		smb_strcnt(shp, bb_stype);
506074bb90dSTom Pothier 
507074bb90dSTom Pothier 		/* verify contained handles */
508074bb90dSTom Pothier 		for (i = 0; i < bb_cnt; i++) {
509074bb90dSTom Pothier 			bb_id = bb_stype->ids[i]->id;
510074bb90dSTom Pothier 			(void) smbios_info_bboard(shp, bb_id, &bb);
511074bb90dSTom Pothier 			if (bb.smbb_contn == 0) {
512074bb90dSTom Pothier #ifdef	DEBUG
5137991dd24STom Pothier 				cmn_err(CE_NOTE, "!No contained hanldes (%d)",
514074bb90dSTom Pothier 				    i);
515074bb90dSTom Pothier #endif	/* DEBUG */
516074bb90dSTom Pothier 				smb_free_strcnt(bb_stype, bb_cnt);
517074bb90dSTom Pothier 				return (-1);
518074bb90dSTom Pothier 			}
519074bb90dSTom Pothier 		}
520074bb90dSTom Pothier 
521074bb90dSTom Pothier 		/* free stypes */
522074bb90dSTom Pothier 		smb_free_strcnt(bb_stype, bb_cnt);
523074bb90dSTom Pothier 	}
524074bb90dSTom Pothier 
525074bb90dSTom Pothier 	return (0);
526074bb90dSTom Pothier }
527074bb90dSTom Pothier 
528074bb90dSTom Pothier void
fm_smb_fmacompat()529074bb90dSTom Pothier fm_smb_fmacompat()
530074bb90dSTom Pothier {
531074bb90dSTom Pothier 	int i, j;
532074bb90dSTom Pothier 	int id;
533074bb90dSTom Pothier 	int cnt;
534074bb90dSTom Pothier 	const char **oem_strings = NULL;
535074bb90dSTom Pothier 	smbs_cnt_t *oemstypes;
536074bb90dSTom Pothier 	smbios_hdl_t *shp;
537074bb90dSTom Pothier 	int strcnt;
538074bb90dSTom Pothier 	int compat = 0;
539074bb90dSTom Pothier 
540074bb90dSTom Pothier 	/* check for BKS */
541074bb90dSTom Pothier 	if (x86gentopo_legacy == 1) {
542074bb90dSTom Pothier 		return;
543074bb90dSTom Pothier 	}
544074bb90dSTom Pothier 
545074bb90dSTom Pothier 	shp = ksmbios;
546074bb90dSTom Pothier 	if (shp == NULL) {
547074bb90dSTom Pothier 		goto bad;
548074bb90dSTom Pothier 	}
549074bb90dSTom Pothier 
550074bb90dSTom Pothier 	/* OEM strings (Type 11) */
551074bb90dSTom Pothier 	strcnt = smb_cnttypes(shp, SMB_TYPE_OEMSTR);
552074bb90dSTom Pothier 	if (strcnt == 0)
553074bb90dSTom Pothier 		goto bad;
554074bb90dSTom Pothier 
555074bb90dSTom Pothier 	oemstypes = smb_create_strcnt(strcnt);
556074bb90dSTom Pothier 	if (oemstypes == NULL)
557074bb90dSTom Pothier 		goto bad;
558074bb90dSTom Pothier 
559074bb90dSTom Pothier 	oemstypes->type = SMB_TYPE_OEMSTR;
560074bb90dSTom Pothier 	smb_strcnt(shp, oemstypes);
561074bb90dSTom Pothier 
5629f67f65cSJens Rosenboom 	for (i = 0; i < oemstypes->count && compat == 0; i++) {
563074bb90dSTom Pothier 		id = oemstypes->ids[i]->id;
564074bb90dSTom Pothier 		cnt = smbios_info_strtab(shp, id, 0, NULL);
565074bb90dSTom Pothier 		if (cnt > 0) {
566074bb90dSTom Pothier 			oem_strings = kmem_zalloc(sizeof (char *) * cnt,
567074bb90dSTom Pothier 			    KM_SLEEP);
568074bb90dSTom Pothier 			(void) smbios_info_strtab(shp, id, cnt, oem_strings);
569074bb90dSTom Pothier 
570074bb90dSTom Pothier 			for (j = 0; j < cnt; j++) {
571074bb90dSTom Pothier 				if (strncmp(oem_strings[j], SMB_PRMS1,
572074bb90dSTom Pothier 				    strlen(SMB_PRMS1) + 1) == 0) {
573074bb90dSTom Pothier 					compat = 1;
574074bb90dSTom Pothier 					break;
575074bb90dSTom Pothier 				}
576074bb90dSTom Pothier 			}
577074bb90dSTom Pothier 			kmem_free(oem_strings, sizeof (char *) * cnt);
5789f67f65cSJens Rosenboom 		}
579074bb90dSTom Pothier 	}
5809f67f65cSJens Rosenboom 	smb_free_strcnt(oemstypes, strcnt);
581074bb90dSTom Pothier 
582074bb90dSTom Pothier 	/* sanity check SMBIOS structures */
5839f67f65cSJens Rosenboom 	if ((compat != 0) && (fm_smb_check(shp) == 0))
584074bb90dSTom Pothier 		return;
585074bb90dSTom Pothier 
586074bb90dSTom Pothier bad:
587074bb90dSTom Pothier 	/* not compatible with x86gentopo; revert to legacy enumeration */
588074bb90dSTom Pothier #ifdef	DEBUG
5897991dd24STom Pothier 	cmn_err(CE_NOTE,
5907991dd24STom Pothier 	    "!SMBIOS is not compatible with x86 generic topology.");
5917991dd24STom Pothier 	cmn_err(CE_NOTE, "!Invoking legacy x86 topology enumeration.");
592074bb90dSTom Pothier #endif	/* DEBUG */
593074bb90dSTom Pothier 	x86gentopo_legacy = 1;
594074bb90dSTom Pothier }
595074bb90dSTom Pothier 
596074bb90dSTom Pothier static int
find_matching_apic(smbios_hdl_t * shp,uint16_t proc_id,uint_t strand_apicid)597074bb90dSTom Pothier find_matching_apic(smbios_hdl_t *shp, uint16_t proc_id, uint_t strand_apicid)
598074bb90dSTom Pothier {
599074bb90dSTom Pothier 	uint16_t ext_id;
600074bb90dSTom Pothier 	int i, j;
601074bb90dSTom Pothier 	smbios_processor_ext_t ep;
602074bb90dSTom Pothier 	smbs_cnt_t *pstypes;
603074bb90dSTom Pothier 	int strcnt;
604074bb90dSTom Pothier 
605074bb90dSTom Pothier 	strcnt = smb_cnttypes(shp, SUN_OEM_EXT_PROCESSOR);
606074bb90dSTom Pothier 	if (strcnt == 0)
607074bb90dSTom Pothier 		return (0);
608074bb90dSTom Pothier 
609074bb90dSTom Pothier 	pstypes = smb_create_strcnt(strcnt);
610074bb90dSTom Pothier 	if (pstypes == NULL)
611074bb90dSTom Pothier 		return (0);
612074bb90dSTom Pothier 
613074bb90dSTom Pothier 	pstypes->type = SUN_OEM_EXT_PROCESSOR;
614074bb90dSTom Pothier 	smb_strcnt(shp, pstypes);
615074bb90dSTom Pothier 	for (i = 0; i < pstypes->count; i++) {
616074bb90dSTom Pothier 		ext_id = pstypes->ids[i]->id;
617074bb90dSTom Pothier 		(void) smbios_info_extprocessor(shp, ext_id, &ep);
618074bb90dSTom Pothier 		if (ep.smbpe_processor == proc_id) {
619074bb90dSTom Pothier 			for (j = 0; j < ep.smbpe_n; j++) {
620074bb90dSTom Pothier 				if (ep.smbpe_apicid[j] == strand_apicid) {
621074bb90dSTom Pothier 					smb_free_strcnt(pstypes, strcnt);
622074bb90dSTom Pothier 					return (1);
623074bb90dSTom Pothier 				}
624074bb90dSTom Pothier 			}
625074bb90dSTom Pothier 		}
626074bb90dSTom Pothier 	}
627074bb90dSTom Pothier 	smb_free_strcnt(pstypes, strcnt);
628074bb90dSTom Pothier 	return (0);
629074bb90dSTom Pothier }
630074bb90dSTom Pothier 
631074bb90dSTom Pothier /*
632074bb90dSTom Pothier  * go throught the type 2 structure contained_ids looking for
633074bb90dSTom Pothier  * the type 4 which  has strand_apicid == this strand_apicid
634074bb90dSTom Pothier  */
635074bb90dSTom Pothier static int
find_matching_proc(smbios_hdl_t * shp,uint_t strand_apicid,uint16_t bb_id,uint16_t proc_hdl,int is_proc)636074bb90dSTom Pothier find_matching_proc(smbios_hdl_t *shp, uint_t strand_apicid,
637074bb90dSTom Pothier     uint16_t bb_id, uint16_t proc_hdl, int is_proc)
638074bb90dSTom Pothier {
639074bb90dSTom Pothier 	int n;
640074bb90dSTom Pothier 	const smb_struct_t *sp;
641074bb90dSTom Pothier 	smbios_bboard_t bb;
642074bb90dSTom Pothier 	uint_t cont_count, cont_len;
643074bb90dSTom Pothier 	uint16_t cont_id;
644074bb90dSTom Pothier 	id_t *cont_hdl = NULL;
645074bb90dSTom Pothier 	int rc;
646074bb90dSTom Pothier 
647074bb90dSTom Pothier 
648074bb90dSTom Pothier 	(void) smbios_info_bboard(shp, bb_id, &bb);
649074bb90dSTom Pothier 	cont_count = (uint_t)bb.smbb_contn;
650074bb90dSTom Pothier 	if (cont_count == 0)
651074bb90dSTom Pothier 		return (0);
652074bb90dSTom Pothier 
653074bb90dSTom Pothier 	cont_len = sizeof (id_t);
654074bb90dSTom Pothier 	cont_hdl = kmem_zalloc(cont_count * cont_len, KM_SLEEP);
655074bb90dSTom Pothier 	if (cont_hdl == NULL)
656074bb90dSTom Pothier 		return (0);
657074bb90dSTom Pothier 
658074bb90dSTom Pothier 	rc = smbios_info_contains(shp, bb_id, cont_count, cont_hdl);
659074bb90dSTom Pothier 	if (rc > SMB_CONT_MAX) {
660074bb90dSTom Pothier 		kmem_free(cont_hdl, cont_count * cont_len);
661074bb90dSTom Pothier 		return (0);
662074bb90dSTom Pothier 	}
663074bb90dSTom Pothier 	cont_count = MIN(rc, cont_count);
664074bb90dSTom Pothier 
665074bb90dSTom Pothier 	for (n = 0; n < cont_count; n++) {
666074bb90dSTom Pothier 		cont_id = (uint16_t)cont_hdl[n];
667074bb90dSTom Pothier 		sp = smb_lookup_id(shp, cont_id);
668074bb90dSTom Pothier 		if (sp->smbst_hdr->smbh_type == SMB_TYPE_PROCESSOR) {
669074bb90dSTom Pothier 			if (is_proc) {
670074bb90dSTom Pothier 				if (find_matching_apic(shp, cont_id,
671074bb90dSTom Pothier 				    strand_apicid)) {
672074bb90dSTom Pothier 					kmem_free(cont_hdl,
673074bb90dSTom Pothier 					    cont_count * cont_len);
674074bb90dSTom Pothier 					return (1);
675074bb90dSTom Pothier 				}
676074bb90dSTom Pothier 			} else {
677074bb90dSTom Pothier 				if (cont_id == proc_hdl) {
678074bb90dSTom Pothier 					kmem_free(cont_hdl,
679074bb90dSTom Pothier 					    cont_count * cont_len);
680074bb90dSTom Pothier 					return (1);
681074bb90dSTom Pothier 				}
682074bb90dSTom Pothier 			}
683074bb90dSTom Pothier 		}
684074bb90dSTom Pothier 	}
685074bb90dSTom Pothier 	if (cont_hdl != NULL)
686074bb90dSTom Pothier 		kmem_free(cont_hdl, cont_count * cont_len);
687074bb90dSTom Pothier 
688074bb90dSTom Pothier 	return (0);
689074bb90dSTom Pothier }
690074bb90dSTom Pothier 
691074bb90dSTom Pothier void
get_bboard_index(smbs_cnt_t * bbstypes,uint_t bb_id,bbindex_t * bb_idx)692074bb90dSTom Pothier get_bboard_index(smbs_cnt_t *bbstypes, uint_t bb_id, bbindex_t *bb_idx)
693074bb90dSTom Pothier {
694074bb90dSTom Pothier 	int curr_id, tmp_id;
695074bb90dSTom Pothier 	int i, j, nb;
696074bb90dSTom Pothier 	bbindex_t tmp_idx;
697074bb90dSTom Pothier 
698074bb90dSTom Pothier 	for (i = 0; i < MAX_PAIRS; i++)
699074bb90dSTom Pothier 		tmp_idx.index[i] = 0;
700074bb90dSTom Pothier 
701074bb90dSTom Pothier 	tmp_idx.count = 0;
702074bb90dSTom Pothier 
703074bb90dSTom Pothier 	curr_id = bb_id;
704074bb90dSTom Pothier 	for (nb = bbstypes->count-1, i = 0; nb >= 0; nb--) {
705074bb90dSTom Pothier 		tmp_id = bbstypes->ids[nb]->id;
706074bb90dSTom Pothier 		if (tmp_id == curr_id) {
707074bb90dSTom Pothier 			tmp_idx.index[i] = nb;
708074bb90dSTom Pothier 			tmp_idx.count++;
709074bb90dSTom Pothier 			curr_id = bbstypes->ids[nb]->cont_by_id;
710074bb90dSTom Pothier 			if (curr_id == -1)
711074bb90dSTom Pothier 				break;
712074bb90dSTom Pothier 			i++;
713074bb90dSTom Pothier 		}
714074bb90dSTom Pothier 	}
715074bb90dSTom Pothier 
716074bb90dSTom Pothier 	for (i = tmp_idx.count - 1, j = 0; i >= 0; i--) {
717074bb90dSTom Pothier 		bb_idx->index[j] = tmp_idx.index[i];
718074bb90dSTom Pothier 		j++;
719074bb90dSTom Pothier 	}
720074bb90dSTom Pothier 
721074bb90dSTom Pothier 	bb_idx->count = tmp_idx.count;
722074bb90dSTom Pothier }
723074bb90dSTom Pothier 
724074bb90dSTom Pothier int
get_chassis_inst(smbios_hdl_t * shp,uint16_t * chassis_inst,uint16_t bb_id,int * chcnt)725074bb90dSTom Pothier get_chassis_inst(smbios_hdl_t *shp, uint16_t *chassis_inst,
726074bb90dSTom Pothier     uint16_t bb_id, int *chcnt)
727074bb90dSTom Pothier {
728074bb90dSTom Pothier 	int ch_strcnt;
729074bb90dSTom Pothier 	smbs_cnt_t *chstypes;
730074bb90dSTom Pothier 	uint16_t chassis_id, tmp_id;
731074bb90dSTom Pothier 	smbios_bboard_t bb;
732074bb90dSTom Pothier 	int rc = 0;
733074bb90dSTom Pothier 	int i;
734074bb90dSTom Pothier 
735074bb90dSTom Pothier 	rc = smbios_info_bboard(shp, bb_id, &bb);
736074bb90dSTom Pothier 	if (rc != 0) {
737074bb90dSTom Pothier 		return (-1);
738074bb90dSTom Pothier 	}
739074bb90dSTom Pothier 
740074bb90dSTom Pothier 	chassis_id = bb.smbb_chassis;
741074bb90dSTom Pothier 
742074bb90dSTom Pothier 	ch_strcnt = smb_cnttypes(shp, SMB_TYPE_CHASSIS);
743074bb90dSTom Pothier 
744074bb90dSTom Pothier 	if (ch_strcnt == 0)
745074bb90dSTom Pothier 		return (-1);
746074bb90dSTom Pothier 
747074bb90dSTom Pothier 	chstypes = smb_create_strcnt(ch_strcnt);
748074bb90dSTom Pothier 	if (chstypes == NULL)
749074bb90dSTom Pothier 		return (-1);
750074bb90dSTom Pothier 
751074bb90dSTom Pothier 	chstypes->type = SMB_TYPE_CHASSIS;
752074bb90dSTom Pothier 	smb_strcnt(shp, chstypes);
753074bb90dSTom Pothier 
754074bb90dSTom Pothier 	for (i = 0; i < chstypes->count; i++) {
755074bb90dSTom Pothier 		tmp_id = chstypes->ids[i]->id;
756074bb90dSTom Pothier 		if (tmp_id == chassis_id) {
757074bb90dSTom Pothier 			*chassis_inst = chstypes->ids[i]->inst;
758074bb90dSTom Pothier 			if (chstypes->ids[i]->inst != 0)
759074bb90dSTom Pothier 				*chcnt = 2;
760074bb90dSTom Pothier 			else
761074bb90dSTom Pothier 				*chcnt = 1;
762074bb90dSTom Pothier 			smb_free_strcnt(chstypes, ch_strcnt);
763074bb90dSTom Pothier 			return (0);
764074bb90dSTom Pothier 		}
765074bb90dSTom Pothier 	}
766074bb90dSTom Pothier 
767074bb90dSTom Pothier 	smb_free_strcnt(chstypes, ch_strcnt);
768074bb90dSTom Pothier 	return (-1);
769074bb90dSTom Pothier }
770074bb90dSTom Pothier 
771074bb90dSTom Pothier int
smb_get_bb_fmri(smbios_hdl_t * shp,nvlist_t * fmri,uint_t parent,smbs_cnt_t * bbstypes)772074bb90dSTom Pothier smb_get_bb_fmri(smbios_hdl_t *shp, nvlist_t *fmri,  uint_t parent,
773074bb90dSTom Pothier     smbs_cnt_t *bbstypes)
774074bb90dSTom Pothier {
775074bb90dSTom Pothier 	int rc = 0;
776074bb90dSTom Pothier 	int i, j, n, cnt;
777074bb90dSTom Pothier 	int id, index;
778074bb90dSTom Pothier 	nvlist_t *pairs[MAX_PAIRS];
779074bb90dSTom Pothier 	smbios_bboard_t bb;
780074bb90dSTom Pothier 	uint16_t chassis_inst, mch_inst;
781074bb90dSTom Pothier 	char name[40];
782074bb90dSTom Pothier 	char idstr[11];
783074bb90dSTom Pothier 	bbindex_t bb_idx;
784074bb90dSTom Pothier 	uint16_t bbid;
785074bb90dSTom Pothier 	int chcnt = 0;
786074bb90dSTom Pothier 
787074bb90dSTom Pothier 	for (n = 0; n < MAX_PAIRS; n++) {
788074bb90dSTom Pothier 		bb_idx.index[n] = 0;
789074bb90dSTom Pothier 		pairs[n] = NULL;
790074bb90dSTom Pothier 	}
791074bb90dSTom Pothier 	bb_idx.count = 0;
792074bb90dSTom Pothier 
793074bb90dSTom Pothier 	get_bboard_index(bbstypes, parent, &bb_idx);
794074bb90dSTom Pothier 
795074bb90dSTom Pothier 	index = bb_idx.index[0];
796074bb90dSTom Pothier 	bbid = bbstypes->ids[index]->id;
797074bb90dSTom Pothier 
798074bb90dSTom Pothier 	rc = get_chassis_inst(shp, &chassis_inst, bbid, &chcnt);
799074bb90dSTom Pothier 
800074bb90dSTom Pothier 	if (rc != 0) {
801074bb90dSTom Pothier 		return (rc);
802074bb90dSTom Pothier 	}
803074bb90dSTom Pothier 
804074bb90dSTom Pothier 	if ((bb_idx.count + chcnt) > MAX_PAIRS) {
805074bb90dSTom Pothier 		return (-1);
806074bb90dSTom Pothier 	}
807074bb90dSTom Pothier 
808074bb90dSTom Pothier 	i = 0;
809074bb90dSTom Pothier 	if (chcnt > 1) {
810074bb90dSTom Pothier 		/*
811074bb90dSTom Pothier 		 * create main chassis pair
812074bb90dSTom Pothier 		 */
813074bb90dSTom Pothier 		pairs[i] = fm_nvlist_create(NULL);
814074bb90dSTom Pothier 		if (pairs[i] == NULL) {
815074bb90dSTom Pothier 			return (-1);
816074bb90dSTom Pothier 		}
817074bb90dSTom Pothier 		mch_inst = 0;
818074bb90dSTom Pothier 		(void) snprintf(idstr, sizeof (idstr), "%u", mch_inst);
819074bb90dSTom Pothier 		if ((nvlist_add_string(pairs[i], FM_FMRI_HC_NAME,
820074bb90dSTom Pothier 		    "chassis") != 0) ||
821074bb90dSTom Pothier 		    (nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr)) != 0) {
822074bb90dSTom Pothier 			fm_nvlist_destroy(pairs[i], FM_NVA_FREE);
823074bb90dSTom Pothier 			return (-1);
824074bb90dSTom Pothier 		}
825074bb90dSTom Pothier 		i++;
826074bb90dSTom Pothier 	}
827074bb90dSTom Pothier 
828074bb90dSTom Pothier 	/*
829074bb90dSTom Pothier 	 * create chassis pair
830074bb90dSTom Pothier 	 */
831074bb90dSTom Pothier 	pairs[i] = fm_nvlist_create(NULL);
832074bb90dSTom Pothier 	if (pairs[i] == NULL) {
833074bb90dSTom Pothier 		for (n = 0; n < MAX_PAIRS; n++) {
834074bb90dSTom Pothier 			if (pairs[n] != NULL)
835074bb90dSTom Pothier 				fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
836074bb90dSTom Pothier 		}
837074bb90dSTom Pothier 		return (-1);
838074bb90dSTom Pothier 	}
839074bb90dSTom Pothier 	(void) snprintf(idstr, sizeof (idstr), "%u", chassis_inst);
840074bb90dSTom Pothier 	if ((nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, "chassis") != 0) ||
841074bb90dSTom Pothier 	    (nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) != 0)) {
842074bb90dSTom Pothier 		for (n = 0; n < MAX_PAIRS; n++) {
843074bb90dSTom Pothier 			if (pairs[n] != NULL)
844074bb90dSTom Pothier 				fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
845074bb90dSTom Pothier 		}
846074bb90dSTom Pothier 		return (-1);
847074bb90dSTom Pothier 	}
848074bb90dSTom Pothier 
849074bb90dSTom Pothier 	for (j = 0, i = chcnt, cnt = chcnt; j < bb_idx.count; j++) {
850074bb90dSTom Pothier 		index = bb_idx.index[j];
851074bb90dSTom Pothier 		bbid = bbstypes->ids[index]->id;
852074bb90dSTom Pothier 		rc =  smbios_info_bboard(shp, bbid, &bb);
853074bb90dSTom Pothier 		if (rc != 0) {
854074bb90dSTom Pothier 			rc = -1;
855074bb90dSTom Pothier 			break;
856074bb90dSTom Pothier 		}
857074bb90dSTom Pothier 
858074bb90dSTom Pothier 		pairs[i] = fm_nvlist_create(NULL);
859074bb90dSTom Pothier 		if (pairs[i] == NULL) {
860074bb90dSTom Pothier 			rc = -1;
861074bb90dSTom Pothier 			break;
862074bb90dSTom Pothier 		}
863074bb90dSTom Pothier 
864074bb90dSTom Pothier 		id = bbstypes->ids[index]->inst;
865074bb90dSTom Pothier 		(void) snprintf(idstr, sizeof (idstr), "%u", id);
866074bb90dSTom Pothier 		(void) strncpy(name, bbd_type[bb.smbb_type].name,
867074bb90dSTom Pothier 		    sizeof (name));
868074bb90dSTom Pothier 		cnt++;
869074bb90dSTom Pothier 
870074bb90dSTom Pothier 		if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, name) != 0 ||
871074bb90dSTom Pothier 		    nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr)
872074bb90dSTom Pothier 		    != 0) {
873074bb90dSTom Pothier 			rc = -1;
874074bb90dSTom Pothier 			break;
875074bb90dSTom Pothier 		}
876074bb90dSTom Pothier 		i++;
877074bb90dSTom Pothier 	}
878074bb90dSTom Pothier 
879074bb90dSTom Pothier 	if (rc != -1) {
880074bb90dSTom Pothier 		if (nvlist_add_nvlist_array(fmri, FM_FMRI_HC_LIST,
881074bb90dSTom Pothier 		    pairs, cnt) != 0) {
882074bb90dSTom Pothier 			rc = -1;
883074bb90dSTom Pothier 		}
884074bb90dSTom Pothier 	}
885074bb90dSTom Pothier 
886074bb90dSTom Pothier 	for (n = 0; n < cnt; n++) {
887074bb90dSTom Pothier 		if (pairs[n] != NULL)
888074bb90dSTom Pothier 			fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
889074bb90dSTom Pothier 	}
890074bb90dSTom Pothier 
891074bb90dSTom Pothier 	return (rc);
892074bb90dSTom Pothier }
893074bb90dSTom Pothier 
894074bb90dSTom Pothier /*
895074bb90dSTom Pothier  * pass in strand_apic id
896074bb90dSTom Pothier  * return chip's bboards list which has strand_apicid == passed
897074bb90dSTom Pothier  * in strand_apic id
898074bb90dSTom Pothier  */
899074bb90dSTom Pothier static nvlist_t *
smb_bboard(uint_t strand_apicid,uint16_t proc_hdl,int is_proc)900074bb90dSTom Pothier smb_bboard(uint_t strand_apicid, uint16_t proc_hdl, int is_proc)
901074bb90dSTom Pothier {
902074bb90dSTom Pothier 	smbios_hdl_t *shp;
903074bb90dSTom Pothier 	smbs_cnt_t *bbstypes;
904074bb90dSTom Pothier 	int nb;
905074bb90dSTom Pothier 	int bb_smbid;
906074bb90dSTom Pothier 	nvlist_t *fmri = NULL;
907074bb90dSTom Pothier 	int rc = 0;
908074bb90dSTom Pothier 	int bb_strcnt;
909074bb90dSTom Pothier 
910074bb90dSTom Pothier 	if (x86gentopo_legacy)
911074bb90dSTom Pothier 		return (NULL);
912074bb90dSTom Pothier 
913074bb90dSTom Pothier 	shp = ksmbios;
914074bb90dSTom Pothier 	if (shp == NULL) {
915074bb90dSTom Pothier 		goto bad;
916074bb90dSTom Pothier 	}
917074bb90dSTom Pothier 
918074bb90dSTom Pothier 	/*
919074bb90dSTom Pothier 	 * Type 2 structs : "base board"
920074bb90dSTom Pothier 	 */
921074bb90dSTom Pothier 	bb_strcnt = smb_cnttypes(shp, SMB_TYPE_BASEBOARD);
922074bb90dSTom Pothier 	if (bb_strcnt == 0) {
923074bb90dSTom Pothier 		goto bad;
924074bb90dSTom Pothier 	}
925074bb90dSTom Pothier 
926074bb90dSTom Pothier 	bbstypes = smb_create_strcnt(bb_strcnt);
927074bb90dSTom Pothier 	if (bbstypes == NULL)  {
928074bb90dSTom Pothier 		goto bad;
929074bb90dSTom Pothier 	}
930074bb90dSTom Pothier 
931074bb90dSTom Pothier 	bbstypes->type = SMB_TYPE_BASEBOARD;
932074bb90dSTom Pothier 	smb_strcnt(shp, bbstypes);
933074bb90dSTom Pothier 	smb_bb_contains(shp, bbstypes);
934074bb90dSTom Pothier 
935074bb90dSTom Pothier 	for (nb = 0; nb < bbstypes->count; nb++) {
936074bb90dSTom Pothier 		if (bbstypes->ids[nb]->visited) {
937074bb90dSTom Pothier 			continue;
938074bb90dSTom Pothier 		}
939074bb90dSTom Pothier 
940074bb90dSTom Pothier 		bbstypes->ids[nb]->visited = 1;
941074bb90dSTom Pothier 		bb_smbid = bbstypes->ids[nb]->id;
942074bb90dSTom Pothier 
943074bb90dSTom Pothier 		/*
944074bb90dSTom Pothier 		 * check if there is a matching  processor under
945074bb90dSTom Pothier 		 * this board. If found, find base board(s) of this proc
946074bb90dSTom Pothier 		 * If proc is not in contained handle of a base board and
947074bb90dSTom Pothier 		 * there is only one base board in the system, treat that base
948074bb90dSTom Pothier 		 * board as the parent of the proc
949074bb90dSTom Pothier 		 */
950074bb90dSTom Pothier 		if (find_matching_proc(shp, strand_apicid,
951074bb90dSTom Pothier 		    bb_smbid, proc_hdl, is_proc) || (bbstypes->count == 1)) {
952074bb90dSTom Pothier 			fmri = fm_nvlist_create(NULL);
953074bb90dSTom Pothier 			if (fmri == NULL) {
954074bb90dSTom Pothier 				smb_free_strcnt(bbstypes, bb_strcnt);
955074bb90dSTom Pothier 				goto bad;
956074bb90dSTom Pothier 			}
957074bb90dSTom Pothier 			/*
958074bb90dSTom Pothier 			 * find parent by walking the cont_by_id
959074bb90dSTom Pothier 			 */
960074bb90dSTom Pothier 			rc = smb_get_bb_fmri(shp, fmri, bb_smbid, bbstypes);
961074bb90dSTom Pothier 			smb_free_strcnt(bbstypes, bb_strcnt);
962074bb90dSTom Pothier 			if (rc == 0) {
963074bb90dSTom Pothier 				return (fmri);
964074bb90dSTom Pothier 			} else
965074bb90dSTom Pothier 				goto bad;
966074bb90dSTom Pothier 		}
967074bb90dSTom Pothier 
968074bb90dSTom Pothier 	}
969074bb90dSTom Pothier 
970074bb90dSTom Pothier 	smb_free_strcnt(bbstypes, bb_strcnt);
971074bb90dSTom Pothier bad:
972074bb90dSTom Pothier 	/* revert to legacy enumeration */
973074bb90dSTom Pothier 	x86gentopo_legacy = 1;
974074bb90dSTom Pothier 
975074bb90dSTom Pothier 	return (NULL);
976074bb90dSTom Pothier }
977074bb90dSTom Pothier 
978074bb90dSTom Pothier nvlist_t *
fm_smb_bboard(uint_t strand_apicid)979074bb90dSTom Pothier fm_smb_bboard(uint_t strand_apicid)
980074bb90dSTom Pothier {
981074bb90dSTom Pothier 	return (smb_bboard(strand_apicid, 0, PROC));
982074bb90dSTom Pothier }
983074bb90dSTom Pothier 
984074bb90dSTom Pothier int
fm_smb_chipinst(uint_t strand_apicid,uint_t * chip_inst,uint16_t * smbiosid)985074bb90dSTom Pothier fm_smb_chipinst(uint_t strand_apicid, uint_t *chip_inst, uint16_t *smbiosid)
986074bb90dSTom Pothier {
987074bb90dSTom Pothier 	int n;
988074bb90dSTom Pothier 	smbios_hdl_t *shp;
989074bb90dSTom Pothier 	uint16_t proc_id;
990074bb90dSTom Pothier 	smbs_cnt_t *pstypes;
991074bb90dSTom Pothier 	int strcnt;
992074bb90dSTom Pothier 
993074bb90dSTom Pothier 	if (x86gentopo_legacy)
994074bb90dSTom Pothier 		return (-1);
995074bb90dSTom Pothier 
996074bb90dSTom Pothier 	shp = ksmbios;
997074bb90dSTom Pothier 	if (shp == NULL) {
998074bb90dSTom Pothier 		goto bad;
999074bb90dSTom Pothier 	}
1000074bb90dSTom Pothier 
1001074bb90dSTom Pothier 	strcnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
1002074bb90dSTom Pothier 	if (strcnt == 0)
1003074bb90dSTom Pothier 		goto bad;
1004074bb90dSTom Pothier 
1005074bb90dSTom Pothier 	pstypes = smb_create_strcnt(strcnt);
1006074bb90dSTom Pothier 	if (pstypes == NULL)
1007074bb90dSTom Pothier 		goto bad;
1008074bb90dSTom Pothier 
1009074bb90dSTom Pothier 	pstypes->type = SMB_TYPE_PROCESSOR;
1010074bb90dSTom Pothier 	smb_strcnt(shp, pstypes);
1011074bb90dSTom Pothier 	for (n = 0; n < pstypes->count; n++) {
1012074bb90dSTom Pothier 		proc_id = pstypes->ids[n]->id;
1013074bb90dSTom Pothier 		if (find_matching_apic(shp, proc_id, strand_apicid)) {
1014074bb90dSTom Pothier 			*chip_inst = pstypes->ids[n]->inst;
1015074bb90dSTom Pothier 			*smbiosid = pstypes->ids[n]->id;
1016074bb90dSTom Pothier 			smb_free_strcnt(pstypes, strcnt);
1017074bb90dSTom Pothier 			return (0);
1018074bb90dSTom Pothier 		}
1019074bb90dSTom Pothier 	}
1020074bb90dSTom Pothier 	smb_free_strcnt(pstypes, strcnt);
1021074bb90dSTom Pothier bad:
1022074bb90dSTom Pothier 	/* revert to legacy enumerarion */
1023074bb90dSTom Pothier 	x86gentopo_legacy = 1;
1024074bb90dSTom Pothier 
1025074bb90dSTom Pothier 	return (-1);
1026074bb90dSTom Pothier }
1027074bb90dSTom Pothier 
1028074bb90dSTom Pothier nvlist_t *
fm_smb_mc_bboards(uint_t bdf)1029074bb90dSTom Pothier fm_smb_mc_bboards(uint_t bdf)
1030074bb90dSTom Pothier {
1031074bb90dSTom Pothier 
1032074bb90dSTom Pothier 	int i;
1033074bb90dSTom Pothier 	smbios_hdl_t *shp;
1034074bb90dSTom Pothier 	uint16_t ext_id;
1035074bb90dSTom Pothier 	smbios_memarray_ext_t em;
1036074bb90dSTom Pothier 	nvlist_t *fmri = NULL;
1037074bb90dSTom Pothier 	smbs_cnt_t *mastypes;
1038074bb90dSTom Pothier 	int strcnt;
1039074bb90dSTom Pothier 
1040074bb90dSTom Pothier 	if (x86gentopo_legacy)
1041074bb90dSTom Pothier 		return (NULL);
1042074bb90dSTom Pothier 
1043074bb90dSTom Pothier 	shp = ksmbios;
1044074bb90dSTom Pothier 	if (shp == NULL) {
1045074bb90dSTom Pothier 		goto bad;
1046074bb90dSTom Pothier 	}
1047074bb90dSTom Pothier 
1048074bb90dSTom Pothier 	strcnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
1049074bb90dSTom Pothier 	if (strcnt == 0)
1050074bb90dSTom Pothier 		goto bad;
1051074bb90dSTom Pothier 
1052074bb90dSTom Pothier 	mastypes = smb_create_strcnt(strcnt);
1053074bb90dSTom Pothier 	if (mastypes == NULL)
1054074bb90dSTom Pothier 		goto bad;
1055074bb90dSTom Pothier 
1056074bb90dSTom Pothier 	mastypes->type = SUN_OEM_EXT_MEMARRAY;
1057074bb90dSTom Pothier 	smb_strcnt(shp, mastypes);
1058074bb90dSTom Pothier 	for (i = 0; i < mastypes->count; i++) {
1059074bb90dSTom Pothier 		ext_id = mastypes->ids[i]->id;
1060074bb90dSTom Pothier 		(void) smbios_info_extmemarray(shp, ext_id, &em);
1061074bb90dSTom Pothier 		if (em.smbmae_bdf == bdf) {
1062074bb90dSTom Pothier 			fmri = smb_bboard(0, em.smbmae_comp, MC);
1063074bb90dSTom Pothier 			smb_free_strcnt(mastypes, strcnt);
1064074bb90dSTom Pothier 			return (fmri);
1065074bb90dSTom Pothier 		}
1066074bb90dSTom Pothier 	}
1067074bb90dSTom Pothier 	smb_free_strcnt(mastypes, strcnt);
1068074bb90dSTom Pothier bad:
1069074bb90dSTom Pothier 	/* revert to legacy enumerarion */
1070074bb90dSTom Pothier 	x86gentopo_legacy = 1;
1071074bb90dSTom Pothier 
1072074bb90dSTom Pothier 	return (NULL);
1073074bb90dSTom Pothier }
1074074bb90dSTom Pothier 
1075074bb90dSTom Pothier int
fm_smb_mc_chipinst(uint_t bdf,uint_t * chip_inst)1076*584b574aSToomas Soome fm_smb_mc_chipinst(uint_t bdf, uint_t *chip_inst)
1077*584b574aSToomas Soome {
1078074bb90dSTom Pothier 
1079074bb90dSTom Pothier 	int i, j;
1080074bb90dSTom Pothier 	smbios_hdl_t *shp;
1081074bb90dSTom Pothier 	smbios_memarray_ext_t em;
1082074bb90dSTom Pothier 	uint16_t ext_id, proc_id;
1083074bb90dSTom Pothier 	smbs_cnt_t *mastypes;
1084074bb90dSTom Pothier 	smbs_cnt_t *pstypes;
1085074bb90dSTom Pothier 	int ma_strcnt, p_strcnt;
1086074bb90dSTom Pothier 
1087074bb90dSTom Pothier 	if (x86gentopo_legacy)
1088074bb90dSTom Pothier 		return (-1);
1089074bb90dSTom Pothier 
1090074bb90dSTom Pothier 	shp = ksmbios;
1091074bb90dSTom Pothier 	if (shp == NULL) {
1092074bb90dSTom Pothier 		goto bad;
1093074bb90dSTom Pothier 	}
1094074bb90dSTom Pothier 
1095074bb90dSTom Pothier 	ma_strcnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
1096074bb90dSTom Pothier 	if (ma_strcnt == 0)
1097074bb90dSTom Pothier 		goto bad;
1098074bb90dSTom Pothier 
1099074bb90dSTom Pothier 	mastypes = smb_create_strcnt(ma_strcnt);
1100074bb90dSTom Pothier 	if (mastypes == NULL)
1101074bb90dSTom Pothier 		goto bad;
1102074bb90dSTom Pothier 
1103074bb90dSTom Pothier 	mastypes->type = SUN_OEM_EXT_MEMARRAY;
1104074bb90dSTom Pothier 	smb_strcnt(shp, mastypes);
1105*584b574aSToomas Soome 	pstypes = NULL;
1106*584b574aSToomas Soome 	p_strcnt = 0;
1107074bb90dSTom Pothier 	for (i = 0; i < mastypes->count; i++) {
1108074bb90dSTom Pothier 		ext_id = mastypes->ids[i]->id;
1109074bb90dSTom Pothier 		(void) smbios_info_extmemarray(shp, ext_id, &em);
1110*584b574aSToomas Soome 		if (em.smbmae_bdf == bdf) {
1111074bb90dSTom Pothier 			p_strcnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
1112074bb90dSTom Pothier 			if (p_strcnt == 0) {
1113074bb90dSTom Pothier 				smb_free_strcnt(mastypes, ma_strcnt);
1114074bb90dSTom Pothier 				goto bad;
1115074bb90dSTom Pothier 			}
1116074bb90dSTom Pothier 
1117074bb90dSTom Pothier 			pstypes = smb_create_strcnt(p_strcnt);
1118074bb90dSTom Pothier 			if (pstypes == NULL) {
1119074bb90dSTom Pothier 				smb_free_strcnt(mastypes, ma_strcnt);
1120074bb90dSTom Pothier 				goto bad;
1121074bb90dSTom Pothier 			}
1122074bb90dSTom Pothier 
1123074bb90dSTom Pothier 			pstypes->type = SMB_TYPE_PROCESSOR;
1124074bb90dSTom Pothier 			smb_strcnt(shp, pstypes);
1125074bb90dSTom Pothier 			for (j = 0; j < pstypes->count; j++) {
1126074bb90dSTom Pothier 				proc_id = pstypes->ids[j]->id;
1127074bb90dSTom Pothier 				if (proc_id == em.smbmae_comp) {
1128074bb90dSTom Pothier 					*chip_inst = pstypes->ids[j]->inst;
1129074bb90dSTom Pothier 					smb_free_strcnt(mastypes, ma_strcnt);
1130074bb90dSTom Pothier 					smb_free_strcnt(pstypes, p_strcnt);
1131074bb90dSTom Pothier 					return (0);
1132074bb90dSTom Pothier 				}
1133074bb90dSTom Pothier 			}
1134074bb90dSTom Pothier 		}
1135074bb90dSTom Pothier 	}
1136074bb90dSTom Pothier 	smb_free_strcnt(mastypes, ma_strcnt);
1137074bb90dSTom Pothier 	smb_free_strcnt(pstypes, p_strcnt);
1138074bb90dSTom Pothier bad:
1139074bb90dSTom Pothier 	/* revert to legacy enumeration */
1140074bb90dSTom Pothier 	x86gentopo_legacy = 1;
1141074bb90dSTom Pothier 
1142074bb90dSTom Pothier 	return (-1);
1143074bb90dSTom Pothier }
1144