xref: /onnv-gate/usr/src/uts/intel/os/fmsmb.c (revision 11572:7542ca5131a0)
110942STom.Pothier@Sun.COM /*
210942STom.Pothier@Sun.COM  * CDDL HEADER START
310942STom.Pothier@Sun.COM  *
410942STom.Pothier@Sun.COM  * The contents of this file are subject to the terms of the
510942STom.Pothier@Sun.COM  * Common Development and Distribution License (the "License").
610942STom.Pothier@Sun.COM  * You may not use this file except in compliance with the License.
710942STom.Pothier@Sun.COM  *
810942STom.Pothier@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910942STom.Pothier@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1010942STom.Pothier@Sun.COM  * See the License for the specific language governing permissions
1110942STom.Pothier@Sun.COM  * and limitations under the License.
1210942STom.Pothier@Sun.COM  *
1310942STom.Pothier@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1410942STom.Pothier@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510942STom.Pothier@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1610942STom.Pothier@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1710942STom.Pothier@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1810942STom.Pothier@Sun.COM  *
1910942STom.Pothier@Sun.COM  * CDDL HEADER END
2010942STom.Pothier@Sun.COM  */
2110942STom.Pothier@Sun.COM /*
22*11572STom.Pothier@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2310942STom.Pothier@Sun.COM  * Use is subject to license terms.
2410942STom.Pothier@Sun.COM  */
2510942STom.Pothier@Sun.COM 
2610942STom.Pothier@Sun.COM #include <sys/types.h>
2710942STom.Pothier@Sun.COM #include <sys/time.h>
2810942STom.Pothier@Sun.COM #include <sys/nvpair.h>
2910942STom.Pothier@Sun.COM #include <sys/cmn_err.h>
3010942STom.Pothier@Sun.COM #include <sys/fm/util.h>
3110942STom.Pothier@Sun.COM #include <sys/fm/protocol.h>
3210942STom.Pothier@Sun.COM #include <sys/smbios.h>
3310942STom.Pothier@Sun.COM #include <sys/smbios_impl.h>
3410942STom.Pothier@Sun.COM 
3510942STom.Pothier@Sun.COM /*
3610942STom.Pothier@Sun.COM  * Variable used to determine if the x86 generic topology enumerator will
3710942STom.Pothier@Sun.COM  * revert to legacy enumeration. I.E. Big Kill Switch... tunable via
3810942STom.Pothier@Sun.COM  * /etc/system
3910942STom.Pothier@Sun.COM  */
4010942STom.Pothier@Sun.COM int x86gentopo_legacy = 0;
4110942STom.Pothier@Sun.COM 
4210942STom.Pothier@Sun.COM #define	MC		0
4310942STom.Pothier@Sun.COM #define	PROC		1
4410942STom.Pothier@Sun.COM #define	MAX_PAIRS	20
4510942STom.Pothier@Sun.COM #define	MAX_CONT	40
4610942STom.Pothier@Sun.COM 
4710942STom.Pothier@Sun.COM typedef struct bbindex  {
4810942STom.Pothier@Sun.COM 	int count;
4910942STom.Pothier@Sun.COM 	uint16_t index[MAX_PAIRS];
5010942STom.Pothier@Sun.COM } bbindex_t;
5110942STom.Pothier@Sun.COM 
5210942STom.Pothier@Sun.COM /*
5310942STom.Pothier@Sun.COM  * the enum values come from DMTF
5410942STom.Pothier@Sun.COM  */
5510942STom.Pothier@Sun.COM typedef enum baseb {
5610942STom.Pothier@Sun.COM 	BB_BAD = 0,		/* There is no bb value 0 */
5710942STom.Pothier@Sun.COM 	BB_UNKNOWN,		/* Unknown */
5810942STom.Pothier@Sun.COM 	BB_OTHER,		/* Other */
5910942STom.Pothier@Sun.COM 	BB_BLADE,		/* Server Blade */
6010942STom.Pothier@Sun.COM 	BB_CONNSW,		/* Connectivity Switch */
6110942STom.Pothier@Sun.COM 	BB_SMM,			/* System Management Module */
6210942STom.Pothier@Sun.COM 	BB_PROCMOD,		/* Processor Module */
6310942STom.Pothier@Sun.COM 	BB_IOMOD,		/* I/O Module */
6410942STom.Pothier@Sun.COM 	BB_MEMMOD,		/* Memory Module */
6510942STom.Pothier@Sun.COM 	BB_DBOARD,		/* Daughter Board */
6610942STom.Pothier@Sun.COM 	BB_MBOARD,		/* Motherboard */
6710942STom.Pothier@Sun.COM 	BB_PROCMMOD,		/* Processor/Memory Module */
6810942STom.Pothier@Sun.COM 	BB_PROCIOMOD,		/* Processor/IO Module */
6910942STom.Pothier@Sun.COM 	BB_ICONNBD		/* Interconnect Board */
7010942STom.Pothier@Sun.COM } bbd_t;
7110942STom.Pothier@Sun.COM 
7210942STom.Pothier@Sun.COM static struct bboard_type {
7310942STom.Pothier@Sun.COM 	bbd_t		baseb;
7410942STom.Pothier@Sun.COM 	const char	*name;
7510942STom.Pothier@Sun.COM } bbd_type[] = {
7610942STom.Pothier@Sun.COM 	{BB_BAD,		NULL},
7710942STom.Pothier@Sun.COM 	{BB_UNKNOWN,		"unknown"},
7810942STom.Pothier@Sun.COM 	{BB_OTHER,		"other"},
7910942STom.Pothier@Sun.COM 	{BB_BLADE,		"systemboard"},
8010942STom.Pothier@Sun.COM 	{BB_CONNSW,		"connswitch"},
8110942STom.Pothier@Sun.COM 	{BB_SMM,		"smmodule"},
8210942STom.Pothier@Sun.COM 	{BB_PROCMOD,		"cpuboard"},
8310942STom.Pothier@Sun.COM 	{BB_IOMOD,		"ioboard"},
8410942STom.Pothier@Sun.COM 	{BB_MEMMOD,		"memboard"},
8510942STom.Pothier@Sun.COM 	{BB_DBOARD,		"systemboard"},
8610942STom.Pothier@Sun.COM 	{BB_MBOARD,		"motherboard"},
8710942STom.Pothier@Sun.COM 	{BB_PROCMMOD,		"systemboard"},
8810942STom.Pothier@Sun.COM 	{BB_PROCIOMOD,		"systemboard"},
8910942STom.Pothier@Sun.COM 	{BB_ICONNBD,		"systemboard"}
9010942STom.Pothier@Sun.COM };
9110942STom.Pothier@Sun.COM 
9210942STom.Pothier@Sun.COM typedef struct smbs_con_ids {
9310942STom.Pothier@Sun.COM 	int id;
9410942STom.Pothier@Sun.COM 	int inst;
9510942STom.Pothier@Sun.COM 	int cont_count;
9610942STom.Pothier@Sun.COM 	uint16_t **cont_ids;
9710942STom.Pothier@Sun.COM 	int cont_by_id;
9810942STom.Pothier@Sun.COM 	int visited;
9910942STom.Pothier@Sun.COM } smbs_con_ids_t;
10010942STom.Pothier@Sun.COM 
10110942STom.Pothier@Sun.COM typedef struct smbs_cnt {
10210942STom.Pothier@Sun.COM 	int type;			/* SMBIOS stucture type */
10310942STom.Pothier@Sun.COM 	int count;			/* number of table entries */
10410942STom.Pothier@Sun.COM 	smbs_con_ids_t **ids;		/* SMBIOS table entry id(s) */
10510942STom.Pothier@Sun.COM } smbs_cnt_t;
10610942STom.Pothier@Sun.COM 
10710942STom.Pothier@Sun.COM /*
10810942STom.Pothier@Sun.COM  * dynamically allocate the storage for the smbs_cnt_t
10910942STom.Pothier@Sun.COM  */
11010942STom.Pothier@Sun.COM static smbs_cnt_t *
smb_create_strcnt(int count)11110942STom.Pothier@Sun.COM smb_create_strcnt(int count)
11210942STom.Pothier@Sun.COM {
11310942STom.Pothier@Sun.COM 	smbs_cnt_t *types = NULL;
11410942STom.Pothier@Sun.COM 	int i, j;
11510942STom.Pothier@Sun.COM 
11610942STom.Pothier@Sun.COM 	types = kmem_zalloc(sizeof (smbs_cnt_t), KM_SLEEP);
11710942STom.Pothier@Sun.COM 
11810942STom.Pothier@Sun.COM 	types->ids = (smbs_con_ids_t **)kmem_zalloc(
11910942STom.Pothier@Sun.COM 	    count * sizeof (smbs_con_ids_t *), KM_SLEEP);
12010942STom.Pothier@Sun.COM 
12110942STom.Pothier@Sun.COM 	for (i = 0; i < count; i++) {
12210942STom.Pothier@Sun.COM 		types->ids[i] = (smbs_con_ids_t *)kmem_zalloc(
12310942STom.Pothier@Sun.COM 		    sizeof (smbs_con_ids_t), KM_SLEEP);
12410942STom.Pothier@Sun.COM 	}
12510942STom.Pothier@Sun.COM 
12610942STom.Pothier@Sun.COM 	for (i = 0; i < count; i++) {
12710942STom.Pothier@Sun.COM 		types->ids[i]->cont_ids = (uint16_t **)kmem_zalloc(
12810942STom.Pothier@Sun.COM 		    MAX_CONT * sizeof (uint16_t *), KM_SLEEP);
12910942STom.Pothier@Sun.COM 	}
13010942STom.Pothier@Sun.COM 
13110942STom.Pothier@Sun.COM 	for (i = 0; i < count; i++) {
13210942STom.Pothier@Sun.COM 		for (j = 0; j < MAX_CONT; j++) {
13310942STom.Pothier@Sun.COM 			types->ids[i]->cont_ids[j] = (uint16_t *)kmem_zalloc(
13410942STom.Pothier@Sun.COM 			    sizeof (uint16_t), KM_SLEEP);
13510942STom.Pothier@Sun.COM 		}
13610942STom.Pothier@Sun.COM 	}
13710942STom.Pothier@Sun.COM 	return (types);
13810942STom.Pothier@Sun.COM }
13910942STom.Pothier@Sun.COM 
14010942STom.Pothier@Sun.COM /*
14110942STom.Pothier@Sun.COM  * free the smbs_cnt_t memory
14210942STom.Pothier@Sun.COM  */
14310942STom.Pothier@Sun.COM static void
smb_free_strcnt(smbs_cnt_t * types,int count)14410942STom.Pothier@Sun.COM smb_free_strcnt(smbs_cnt_t *types, int count)
14510942STom.Pothier@Sun.COM {
14610942STom.Pothier@Sun.COM 	int i, j;
14710942STom.Pothier@Sun.COM 
14810942STom.Pothier@Sun.COM 	if (types == NULL)
14910942STom.Pothier@Sun.COM 		return;
15010942STom.Pothier@Sun.COM 
15110942STom.Pothier@Sun.COM 	for (i = 0; i < count; i++) {
15210942STom.Pothier@Sun.COM 		for (j = 0; j < MAX_CONT; j++) {
15310942STom.Pothier@Sun.COM 			if (types->ids[i]->cont_ids[j] != NULL)
15410942STom.Pothier@Sun.COM 				kmem_free(types->ids[i]->cont_ids[j],
15510942STom.Pothier@Sun.COM 				    sizeof (uint16_t));
15610942STom.Pothier@Sun.COM 		}
15710942STom.Pothier@Sun.COM 	}
15810942STom.Pothier@Sun.COM 
15910942STom.Pothier@Sun.COM 	for (i = 0; i < count; i++) {
16010942STom.Pothier@Sun.COM 		if (types->ids[i]->cont_ids != NULL)
16110942STom.Pothier@Sun.COM 			kmem_free(types->ids[i]->cont_ids,
16210942STom.Pothier@Sun.COM 			    MAX_CONT * sizeof (uint16_t *));
16310942STom.Pothier@Sun.COM 	}
16410942STom.Pothier@Sun.COM 
16510942STom.Pothier@Sun.COM 	for (i = 0; i < count; i++) {
16610942STom.Pothier@Sun.COM 		if (types->ids[i] != NULL)
16710942STom.Pothier@Sun.COM 			kmem_free(types->ids[i], sizeof (smbs_con_ids_t));
16810942STom.Pothier@Sun.COM 	}
16910942STom.Pothier@Sun.COM 
17010942STom.Pothier@Sun.COM 	if (types->ids != NULL)
17110942STom.Pothier@Sun.COM 		kmem_free(types->ids, count * sizeof (smbs_con_ids_t *));
17210942STom.Pothier@Sun.COM 
17310942STom.Pothier@Sun.COM 	if (types != NULL)
17410942STom.Pothier@Sun.COM 		kmem_free(types, sizeof (smbs_cnt_t));
17510942STom.Pothier@Sun.COM 
17610942STom.Pothier@Sun.COM }
17710942STom.Pothier@Sun.COM 
17810942STom.Pothier@Sun.COM /*
17910942STom.Pothier@Sun.COM  * count number of the structure type in the ksmbios
18010942STom.Pothier@Sun.COM  */
18110942STom.Pothier@Sun.COM static int
smb_cnttypes(smbios_hdl_t * shp,int type)18210942STom.Pothier@Sun.COM smb_cnttypes(smbios_hdl_t *shp, int type)
18310942STom.Pothier@Sun.COM {
18410942STom.Pothier@Sun.COM 	const smb_struct_t *sp = shp->sh_structs;
18510942STom.Pothier@Sun.COM 	int nstructs = shp->sh_nstructs;
18610942STom.Pothier@Sun.COM 	int i;
18710942STom.Pothier@Sun.COM 	int cnt = 0;
18810942STom.Pothier@Sun.COM 
18910942STom.Pothier@Sun.COM 	for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
19010942STom.Pothier@Sun.COM 		if (sp->smbst_hdr->smbh_type == type)
19110942STom.Pothier@Sun.COM 			cnt++;
19210942STom.Pothier@Sun.COM 	}
19310942STom.Pothier@Sun.COM 	return (cnt);
19410942STom.Pothier@Sun.COM }
19510942STom.Pothier@Sun.COM 
19610942STom.Pothier@Sun.COM static void
smb_strcnt(smbios_hdl_t * shp,smbs_cnt_t * stype)19710942STom.Pothier@Sun.COM smb_strcnt(smbios_hdl_t *shp, smbs_cnt_t *stype)
19810942STom.Pothier@Sun.COM {
19910942STom.Pothier@Sun.COM 	const smb_struct_t *sp = shp->sh_structs;
20010942STom.Pothier@Sun.COM 	int nstructs = shp->sh_nstructs;
20110942STom.Pothier@Sun.COM 	smbios_bboard_t bb;
20210942STom.Pothier@Sun.COM 	int i, cnt;
20310942STom.Pothier@Sun.COM 	int mb_cnt = 0;
20410942STom.Pothier@Sun.COM 	int cpub_cnt = 0;
20510942STom.Pothier@Sun.COM 	int sysb_cnt = 0;
20610942STom.Pothier@Sun.COM 	int memb_cnt = 0;
20710942STom.Pothier@Sun.COM 	int iob_cnt = 0;
20810942STom.Pothier@Sun.COM 	int inst = 0;
20910942STom.Pothier@Sun.COM 	int rc = 0;
21010942STom.Pothier@Sun.COM 
21110942STom.Pothier@Sun.COM 	for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
21210942STom.Pothier@Sun.COM 		if (sp->smbst_hdr->smbh_type == stype->type) {
21310942STom.Pothier@Sun.COM 			stype->ids[cnt]->id = sp->smbst_hdr->smbh_hdl;
21410942STom.Pothier@Sun.COM 			stype->ids[cnt]->inst = cnt;
21510942STom.Pothier@Sun.COM 			stype->ids[cnt]->visited = 0;
21610942STom.Pothier@Sun.COM 			stype->ids[cnt]->cont_by_id = -1;
21710942STom.Pothier@Sun.COM 			if (stype->type == SMB_TYPE_BASEBOARD) {
21810942STom.Pothier@Sun.COM 				rc = smbios_info_bboard(shp,
21910942STom.Pothier@Sun.COM 				    stype->ids[cnt]->id, &bb);
22010942STom.Pothier@Sun.COM 				if (rc == 0) {
22110942STom.Pothier@Sun.COM 					switch (bb.smbb_type) {
22210942STom.Pothier@Sun.COM 						case SMB_BBT_PROC :
22310942STom.Pothier@Sun.COM 							inst = cpub_cnt++;
22410942STom.Pothier@Sun.COM 							break;
22510942STom.Pothier@Sun.COM 						case SMB_BBT_IO :
22610942STom.Pothier@Sun.COM 							inst = iob_cnt++;
22710942STom.Pothier@Sun.COM 							break;
22810942STom.Pothier@Sun.COM 						case SMB_BBT_MEM :
22910942STom.Pothier@Sun.COM 							inst = memb_cnt++;
23010942STom.Pothier@Sun.COM 							break;
23110942STom.Pothier@Sun.COM 						case SMB_BBT_MOTHER :
23210942STom.Pothier@Sun.COM 							inst = mb_cnt++;
23310942STom.Pothier@Sun.COM 							break;
23410942STom.Pothier@Sun.COM 						default:
23510942STom.Pothier@Sun.COM 							/*
23610942STom.Pothier@Sun.COM 							 * SMB_BBT_UNKNOWN
23710942STom.Pothier@Sun.COM 							 * SMB_BBT_OTHER
23810942STom.Pothier@Sun.COM 							 * SMB_BBT_SBLADE
23910942STom.Pothier@Sun.COM 							 * SMB_BBT_CSWITCH
24010942STom.Pothier@Sun.COM 							 * SMB_BBT_SMM
24110942STom.Pothier@Sun.COM 							 * SMB_BBT_DAUGHTER
24210942STom.Pothier@Sun.COM 							 * SMB_BBT_PROCMEM
24310942STom.Pothier@Sun.COM 							 * SMB_BBT_PROCIO
24410942STom.Pothier@Sun.COM 							 * SMB_BBT_INTER
24510942STom.Pothier@Sun.COM 							 */
24610942STom.Pothier@Sun.COM 							inst = sysb_cnt++;
24710942STom.Pothier@Sun.COM 							break;
24810942STom.Pothier@Sun.COM 					}
24910942STom.Pothier@Sun.COM 					stype->ids[cnt]->inst = inst;
25010942STom.Pothier@Sun.COM 				}
25110942STom.Pothier@Sun.COM 			}
25210942STom.Pothier@Sun.COM 			cnt++;
25310942STom.Pothier@Sun.COM 		}
25410942STom.Pothier@Sun.COM 	}
25510942STom.Pothier@Sun.COM 	stype->count = cnt;
25610942STom.Pothier@Sun.COM }
25710942STom.Pothier@Sun.COM 
25810942STom.Pothier@Sun.COM /*
25910942STom.Pothier@Sun.COM  * Go through the smbios structures looking for type 2. Fill in
26010942STom.Pothier@Sun.COM  * the cont_id and cont_by_id for each type 2
26110942STom.Pothier@Sun.COM  *
26210942STom.Pothier@Sun.COM  */
26310942STom.Pothier@Sun.COM static void
smb_bb_contains(smbios_hdl_t * shp,smbs_cnt_t * stype)26410942STom.Pothier@Sun.COM smb_bb_contains(smbios_hdl_t *shp, smbs_cnt_t *stype)
26510942STom.Pothier@Sun.COM {
26610942STom.Pothier@Sun.COM 	int i, j, cnt, c;
26710942STom.Pothier@Sun.COM 	uint_t cont_count;
26810942STom.Pothier@Sun.COM 	const smb_struct_t *spt;
26910942STom.Pothier@Sun.COM 	smbios_bboard_t smb_bb;
27010942STom.Pothier@Sun.COM 	uint16_t bb_id, cont_id;
27110942STom.Pothier@Sun.COM 	uint_t cont_len;
27210942STom.Pothier@Sun.COM 	id_t *cont_hdl = NULL;
27310942STom.Pothier@Sun.COM 	int rc;
27410942STom.Pothier@Sun.COM 
27510942STom.Pothier@Sun.COM 	for (cnt = 0; cnt < stype->count; cnt++) {
27610942STom.Pothier@Sun.COM 		bb_id = stype->ids[cnt]->id;
27710942STom.Pothier@Sun.COM 		(void) smbios_info_bboard(shp, stype->ids[cnt]->id, &smb_bb);
27810942STom.Pothier@Sun.COM 		cont_count = (uint_t)smb_bb.smbb_contn;
27910942STom.Pothier@Sun.COM 		if (cont_count == 0) {
28010942STom.Pothier@Sun.COM 			continue;
28110942STom.Pothier@Sun.COM 		}
28210942STom.Pothier@Sun.COM 
28310942STom.Pothier@Sun.COM 		cont_len = sizeof (id_t);
28410942STom.Pothier@Sun.COM 		cont_hdl = kmem_zalloc(cont_count * cont_len, KM_SLEEP);
28510942STom.Pothier@Sun.COM 		if (cont_hdl == NULL)
28610942STom.Pothier@Sun.COM 			continue;
28710942STom.Pothier@Sun.COM 
28810942STom.Pothier@Sun.COM 		rc = smbios_info_contains(shp, stype->ids[cnt]->id,
28910942STom.Pothier@Sun.COM 		    cont_count, cont_hdl);
29010942STom.Pothier@Sun.COM 		if (rc > SMB_CONT_MAX) {
29110942STom.Pothier@Sun.COM 			kmem_free(cont_hdl, cont_count * cont_len);
29210942STom.Pothier@Sun.COM 			continue;
29310942STom.Pothier@Sun.COM 		}
29410942STom.Pothier@Sun.COM 		cont_count = MIN(rc, cont_count);
29510942STom.Pothier@Sun.COM 
29610942STom.Pothier@Sun.COM 		/*
29710942STom.Pothier@Sun.COM 		 * fill in the type 2 and type 4 ids which are
29810942STom.Pothier@Sun.COM 		 * contained in this type 2
29910942STom.Pothier@Sun.COM 		 */
30010942STom.Pothier@Sun.COM 		c = 0;
30110942STom.Pothier@Sun.COM 		for (j = 0; j < cont_count; j++) {
30210942STom.Pothier@Sun.COM 			cont_id = (uint16_t)cont_hdl[j];
30310942STom.Pothier@Sun.COM 			spt = smb_lookup_id(shp, cont_id);
30410942STom.Pothier@Sun.COM 			if (spt->smbst_hdr->smbh_type == SMB_TYPE_BASEBOARD ||
30510942STom.Pothier@Sun.COM 			    spt->smbst_hdr->smbh_type == SMB_TYPE_PROCESSOR) {
30610942STom.Pothier@Sun.COM 				*stype->ids[cnt]->cont_ids[c] = cont_id;
30710942STom.Pothier@Sun.COM 				c++;
30810942STom.Pothier@Sun.COM 			}
30910942STom.Pothier@Sun.COM 
31010942STom.Pothier@Sun.COM 			if (spt->smbst_hdr->smbh_type == SMB_TYPE_BASEBOARD) {
31110942STom.Pothier@Sun.COM 				for (i = 0; i < stype->count; i++) {
31210942STom.Pothier@Sun.COM 					if (stype->ids[i]->id == cont_id) {
31310942STom.Pothier@Sun.COM 						stype->ids[i]->cont_by_id =
31410942STom.Pothier@Sun.COM 						    bb_id;
31510942STom.Pothier@Sun.COM 					}
31610942STom.Pothier@Sun.COM 				}
31710942STom.Pothier@Sun.COM 			}
31810942STom.Pothier@Sun.COM 
31910942STom.Pothier@Sun.COM 		}
32010942STom.Pothier@Sun.COM 		stype->ids[cnt]->cont_count = c;
32110942STom.Pothier@Sun.COM 		if (cont_hdl != NULL)
32210942STom.Pothier@Sun.COM 			kmem_free(cont_hdl, cont_count * cont_len);
32310942STom.Pothier@Sun.COM 	}
32410942STom.Pothier@Sun.COM }
32510942STom.Pothier@Sun.COM 
32610942STom.Pothier@Sun.COM /*
32710942STom.Pothier@Sun.COM  * Verify SMBIOS structures for x86 generic topology.
32810942STom.Pothier@Sun.COM  *
32910942STom.Pothier@Sun.COM  * Return (0) on success.
33010942STom.Pothier@Sun.COM  */
33110942STom.Pothier@Sun.COM static int
fm_smb_check(smbios_hdl_t * shp)33210942STom.Pothier@Sun.COM fm_smb_check(smbios_hdl_t *shp)
33310942STom.Pothier@Sun.COM {
334*11572STom.Pothier@Sun.COM 	int i, j;
33510942STom.Pothier@Sun.COM 	int bb_cnt = 0;
33610942STom.Pothier@Sun.COM 	int pr_cnt = 0;
33710942STom.Pothier@Sun.COM 	int expr_cnt = 0;
33810942STom.Pothier@Sun.COM 	int ma_cnt = 0;
33910942STom.Pothier@Sun.COM 	int exma_cnt = 0;
34010942STom.Pothier@Sun.COM 	int mdev_cnt = 0;
34110942STom.Pothier@Sun.COM 	int exmdev_cnt = 0;
34210942STom.Pothier@Sun.COM 	uint16_t bb_id;
34310942STom.Pothier@Sun.COM 	uint16_t pr_id, expr_id;
34410942STom.Pothier@Sun.COM 	uint16_t ma_id, exma_id;
34510942STom.Pothier@Sun.COM 	uint16_t mdev_id, exmdev_id;
346*11572STom.Pothier@Sun.COM 	uint16_t *sys_ma;
34710942STom.Pothier@Sun.COM 	smbios_bboard_t bb;
34810942STom.Pothier@Sun.COM 	smbios_processor_ext_t exproc;
349*11572STom.Pothier@Sun.COM 	smbios_memarray_t ma;
35010942STom.Pothier@Sun.COM 	smbios_memarray_ext_t exma;
351*11572STom.Pothier@Sun.COM 	smbios_memdevice_t mdev;
35210942STom.Pothier@Sun.COM 	smbios_memdevice_ext_t exmdev;
35310942STom.Pothier@Sun.COM 	smbs_cnt_t *bb_stype;
35410942STom.Pothier@Sun.COM 	smbs_cnt_t *pr_stype, *expr_stype;
35510942STom.Pothier@Sun.COM 	smbs_cnt_t *ma_stype, *exma_stype;
35610942STom.Pothier@Sun.COM 	smbs_cnt_t *mdev_stype, *exmdev_stype;
35710942STom.Pothier@Sun.COM 
35810942STom.Pothier@Sun.COM 	/*
35910942STom.Pothier@Sun.COM 	 * Verify the existance of the requuired extended OEM-Specific
36010942STom.Pothier@Sun.COM 	 * structures and they coincide with the structures they extend
36110942STom.Pothier@Sun.COM 	 * (e.g. the number of extended processor structures equal the
36210942STom.Pothier@Sun.COM 	 * number of processor structures).
36310942STom.Pothier@Sun.COM 	 */
36410942STom.Pothier@Sun.COM 	pr_cnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
36510942STom.Pothier@Sun.COM 	expr_cnt = smb_cnttypes(shp, SUN_OEM_EXT_PROCESSOR);
36610942STom.Pothier@Sun.COM 	ma_cnt = smb_cnttypes(shp, SMB_TYPE_MEMARRAY);
36710942STom.Pothier@Sun.COM 	exma_cnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
36810942STom.Pothier@Sun.COM 	mdev_cnt = smb_cnttypes(shp, SMB_TYPE_MEMDEVICE);
36910942STom.Pothier@Sun.COM 	exmdev_cnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMDEVICE);
37010942STom.Pothier@Sun.COM 	if (expr_cnt == 0 || exma_cnt == 0 || exmdev_cnt == 0 ||
371*11572STom.Pothier@Sun.COM 	    expr_cnt != pr_cnt || exma_cnt > ma_cnt ||
372*11572STom.Pothier@Sun.COM 	    exmdev_cnt > mdev_cnt) {
37310942STom.Pothier@Sun.COM #ifdef	DEBUG
37410987STom.Pothier@Sun.COM 		cmn_err(CE_NOTE, "!Structure mismatch: ext_proc (%d) "
37510942STom.Pothier@Sun.COM 		    "proc (%d) ext_ma (%d) ma (%d) ext_mdev (%d) mdev (%d)\n",
37610942STom.Pothier@Sun.COM 		    expr_cnt, pr_cnt, exma_cnt, ma_cnt, exmdev_cnt,
37710942STom.Pothier@Sun.COM 		    mdev_cnt);
37810942STom.Pothier@Sun.COM #endif	/* DEBUG */
37910942STom.Pothier@Sun.COM 		return (-1);
38010942STom.Pothier@Sun.COM 	}
38110942STom.Pothier@Sun.COM 
38210942STom.Pothier@Sun.COM 	/*
38310942STom.Pothier@Sun.COM 	 * Verify the OEM-Specific structrures are correctly
38410942STom.Pothier@Sun.COM 	 * linked to the SMBIOS structure types they extend.
38510942STom.Pothier@Sun.COM 	 */
38610942STom.Pothier@Sun.COM 
38710942STom.Pothier@Sun.COM 	/* allocate processor stypes */
38810942STom.Pothier@Sun.COM 	pr_stype = smb_create_strcnt(pr_cnt);
38910942STom.Pothier@Sun.COM 	expr_stype = smb_create_strcnt(expr_cnt);
39010942STom.Pothier@Sun.COM 
39110942STom.Pothier@Sun.COM 	/* fill in stypes */
39210942STom.Pothier@Sun.COM 	pr_stype->type = SMB_TYPE_PROCESSOR;
39310942STom.Pothier@Sun.COM 	smb_strcnt(shp, pr_stype);
39410942STom.Pothier@Sun.COM 	expr_stype->type = SUN_OEM_EXT_PROCESSOR;
39510942STom.Pothier@Sun.COM 	smb_strcnt(shp, expr_stype);
39610942STom.Pothier@Sun.COM 
39710942STom.Pothier@Sun.COM 	/* verify the ext proc struct belong to the proc struct */
39810942STom.Pothier@Sun.COM 	for (i = 0; i < pr_cnt; i++) {
39910942STom.Pothier@Sun.COM 		pr_id = pr_stype->ids[i]->id;
40010942STom.Pothier@Sun.COM 		expr_id = expr_stype->ids[i]->id;
40110942STom.Pothier@Sun.COM 		(void) smbios_info_extprocessor(shp, expr_id, &exproc);
40210942STom.Pothier@Sun.COM 		if (exproc.smbpe_processor != pr_id) {
40310942STom.Pothier@Sun.COM #ifdef	DEBUG
40410987STom.Pothier@Sun.COM 			cmn_err(CE_NOTE, "!Processor struct linkage (%d)", i);
40510942STom.Pothier@Sun.COM #endif	/* DEBUG */
40610942STom.Pothier@Sun.COM 			smb_free_strcnt(pr_stype, pr_cnt);
40710942STom.Pothier@Sun.COM 			smb_free_strcnt(expr_stype, expr_cnt);
40810942STom.Pothier@Sun.COM 			return (-1);
40910942STom.Pothier@Sun.COM 		}
41010942STom.Pothier@Sun.COM 	}
41110942STom.Pothier@Sun.COM 
41210942STom.Pothier@Sun.COM 	/* free stypes */
41310942STom.Pothier@Sun.COM 	smb_free_strcnt(pr_stype, pr_cnt);
41410942STom.Pothier@Sun.COM 	smb_free_strcnt(expr_stype, expr_cnt);
41510942STom.Pothier@Sun.COM 
41610942STom.Pothier@Sun.COM 	/* allocate memory array stypes */
41710942STom.Pothier@Sun.COM 	ma_stype = smb_create_strcnt(ma_cnt);
41810942STom.Pothier@Sun.COM 	exma_stype = smb_create_strcnt(exma_cnt);
419*11572STom.Pothier@Sun.COM 	sys_ma = kmem_zalloc(sizeof (uint16_t) * ma_cnt, KM_SLEEP);
42010942STom.Pothier@Sun.COM 
42110942STom.Pothier@Sun.COM 	/* fill in stypes */
42210942STom.Pothier@Sun.COM 	ma_stype->type = SMB_TYPE_MEMARRAY;
42310942STom.Pothier@Sun.COM 	smb_strcnt(shp, ma_stype);
42410942STom.Pothier@Sun.COM 	exma_stype->type = SUN_OEM_EXT_MEMARRAY;
42510942STom.Pothier@Sun.COM 	smb_strcnt(shp, exma_stype);
42610942STom.Pothier@Sun.COM 
42710942STom.Pothier@Sun.COM 	/* verify linkage from ext memarray struct to memarray struct */
42810942STom.Pothier@Sun.COM 	for (i = 0; i < ma_cnt; i++) {
429*11572STom.Pothier@Sun.COM 		sys_ma[i] = (uint16_t)-1;
43010942STom.Pothier@Sun.COM 		ma_id = ma_stype->ids[i]->id;
431*11572STom.Pothier@Sun.COM 		(void) smbios_info_memarray(shp, ma_id, &ma);
432*11572STom.Pothier@Sun.COM 		if (ma.smbma_use != SMB_MAU_SYSTEM)
433*11572STom.Pothier@Sun.COM 			continue;
434*11572STom.Pothier@Sun.COM 		/* this memarray is system memory */
435*11572STom.Pothier@Sun.COM 		sys_ma[i] = ma_id;
43610942STom.Pothier@Sun.COM 		exma_id = exma_stype->ids[i]->id;
43710942STom.Pothier@Sun.COM 		(void) smbios_info_extmemarray(shp, exma_id, &exma);
43810942STom.Pothier@Sun.COM 		if (exma.smbmae_ma != ma_id) {
43910942STom.Pothier@Sun.COM #ifdef	DEBUG
44010987STom.Pothier@Sun.COM 			cmn_err(CE_NOTE,
44110987STom.Pothier@Sun.COM 			    "!Memory Array struct linkage (%d)", i);
44210942STom.Pothier@Sun.COM #endif	/* DEBUG */
44310942STom.Pothier@Sun.COM 			smb_free_strcnt(ma_stype, ma_cnt);
44410942STom.Pothier@Sun.COM 			smb_free_strcnt(exma_stype, exma_cnt);
445*11572STom.Pothier@Sun.COM 			kmem_free(sys_ma, sizeof (uint16_t) * ma_cnt);
44610942STom.Pothier@Sun.COM 			return (-1);
44710942STom.Pothier@Sun.COM 		}
44810942STom.Pothier@Sun.COM 	}
44910942STom.Pothier@Sun.COM 
45010942STom.Pothier@Sun.COM 	/* free stypes */
45110942STom.Pothier@Sun.COM 	smb_free_strcnt(ma_stype, ma_cnt);
45210942STom.Pothier@Sun.COM 	smb_free_strcnt(exma_stype, exma_cnt);
45310942STom.Pothier@Sun.COM 
45410942STom.Pothier@Sun.COM 	/* allocate memory device stypes */
45510942STom.Pothier@Sun.COM 	mdev_stype = smb_create_strcnt(mdev_cnt);
45610942STom.Pothier@Sun.COM 	exmdev_stype = smb_create_strcnt(exmdev_cnt);
45710942STom.Pothier@Sun.COM 
45810942STom.Pothier@Sun.COM 	/* fill in stypes */
45910942STom.Pothier@Sun.COM 	mdev_stype->type = SMB_TYPE_MEMDEVICE;
46010942STom.Pothier@Sun.COM 	smb_strcnt(shp, mdev_stype);
46110942STom.Pothier@Sun.COM 	exmdev_stype->type = SUN_OEM_EXT_MEMDEVICE;
46210942STom.Pothier@Sun.COM 	smb_strcnt(shp, exmdev_stype);
46310942STom.Pothier@Sun.COM 
46410942STom.Pothier@Sun.COM 	/* verify linkage */
46510942STom.Pothier@Sun.COM 	for (i = 0; i < mdev_cnt; i++) {
46610942STom.Pothier@Sun.COM 		mdev_id = mdev_stype->ids[i]->id;
467*11572STom.Pothier@Sun.COM 		(void) smbios_info_memdevice(shp, mdev_id, &mdev);
468*11572STom.Pothier@Sun.COM 		/* only check system memory devices */
469*11572STom.Pothier@Sun.COM 		for (j = 0; j < ma_cnt; j++) {
470*11572STom.Pothier@Sun.COM 			if (sys_ma[j] == mdev.smbmd_array)
471*11572STom.Pothier@Sun.COM 				break;
472*11572STom.Pothier@Sun.COM 		}
473*11572STom.Pothier@Sun.COM 		if (j == ma_cnt)
474*11572STom.Pothier@Sun.COM 			continue;
47510942STom.Pothier@Sun.COM 		exmdev_id = exmdev_stype->ids[i]->id;
47610942STom.Pothier@Sun.COM 		(void) smbios_info_extmemdevice(shp, exmdev_id, &exmdev);
47710942STom.Pothier@Sun.COM 		if (exmdev.smbmdeve_md != mdev_id) {
47810942STom.Pothier@Sun.COM #ifdef	DEBUG
47910987STom.Pothier@Sun.COM 			cmn_err(CE_NOTE, "!Memory Device struct linkage (%d)",
48010942STom.Pothier@Sun.COM 			    i);
48110942STom.Pothier@Sun.COM #endif	/* DEBUG */
48210942STom.Pothier@Sun.COM 			smb_free_strcnt(mdev_stype, mdev_cnt);
48310942STom.Pothier@Sun.COM 			smb_free_strcnt(exmdev_stype, exmdev_cnt);
484*11572STom.Pothier@Sun.COM 			kmem_free(sys_ma, sizeof (uint16_t) * ma_cnt);
48510942STom.Pothier@Sun.COM 			return (-1);
48610942STom.Pothier@Sun.COM 		}
48710942STom.Pothier@Sun.COM 	}
48810942STom.Pothier@Sun.COM 
48910942STom.Pothier@Sun.COM 	/* free stypes */
49010942STom.Pothier@Sun.COM 	smb_free_strcnt(mdev_stype, mdev_cnt);
49110942STom.Pothier@Sun.COM 	smb_free_strcnt(exmdev_stype, exmdev_cnt);
492*11572STom.Pothier@Sun.COM 	kmem_free(sys_ma, sizeof (uint16_t) * ma_cnt);
49310942STom.Pothier@Sun.COM 
49410942STom.Pothier@Sun.COM 	/*
49510942STom.Pothier@Sun.COM 	 * Verify the presece of contained handles if there are more
49610942STom.Pothier@Sun.COM 	 * than one Type-2 (Base Board) structures.
49710942STom.Pothier@Sun.COM 	 */
49810942STom.Pothier@Sun.COM 	bb_cnt = smb_cnttypes(shp, SMB_TYPE_BASEBOARD);
49910942STom.Pothier@Sun.COM 	if (bb_cnt > 1) {
50010942STom.Pothier@Sun.COM 		/* allocate base board stypes */
50110942STom.Pothier@Sun.COM 		bb_stype = smb_create_strcnt(bb_cnt);
50210942STom.Pothier@Sun.COM 
50310942STom.Pothier@Sun.COM 		/* fill in stypes */
50410942STom.Pothier@Sun.COM 		bb_stype->type = SMB_TYPE_BASEBOARD;
50510942STom.Pothier@Sun.COM 		smb_strcnt(shp, bb_stype);
50610942STom.Pothier@Sun.COM 
50710942STom.Pothier@Sun.COM 		/* verify contained handles */
50810942STom.Pothier@Sun.COM 		for (i = 0; i < bb_cnt; i++) {
50910942STom.Pothier@Sun.COM 			bb_id = bb_stype->ids[i]->id;
51010942STom.Pothier@Sun.COM 			(void) smbios_info_bboard(shp, bb_id, &bb);
51110942STom.Pothier@Sun.COM 			if (bb.smbb_contn == 0) {
51210942STom.Pothier@Sun.COM #ifdef	DEBUG
51310987STom.Pothier@Sun.COM 				cmn_err(CE_NOTE, "!No contained hanldes (%d)",
51410942STom.Pothier@Sun.COM 				    i);
51510942STom.Pothier@Sun.COM #endif	/* DEBUG */
51610942STom.Pothier@Sun.COM 				smb_free_strcnt(bb_stype, bb_cnt);
51710942STom.Pothier@Sun.COM 				return (-1);
51810942STom.Pothier@Sun.COM 			}
51910942STom.Pothier@Sun.COM 		}
52010942STom.Pothier@Sun.COM 
52110942STom.Pothier@Sun.COM 		/* free stypes */
52210942STom.Pothier@Sun.COM 		smb_free_strcnt(bb_stype, bb_cnt);
52310942STom.Pothier@Sun.COM 	}
52410942STom.Pothier@Sun.COM 
52510942STom.Pothier@Sun.COM 	return (0);
52610942STom.Pothier@Sun.COM }
52710942STom.Pothier@Sun.COM 
52810942STom.Pothier@Sun.COM void
fm_smb_fmacompat()52910942STom.Pothier@Sun.COM fm_smb_fmacompat()
53010942STom.Pothier@Sun.COM {
53110942STom.Pothier@Sun.COM 	int i, j;
53210942STom.Pothier@Sun.COM 	int id;
53310942STom.Pothier@Sun.COM 	int cnt;
53410942STom.Pothier@Sun.COM 	const char **oem_strings = NULL;
53510942STom.Pothier@Sun.COM 	smbs_cnt_t *oemstypes;
53610942STom.Pothier@Sun.COM 	smbios_hdl_t *shp;
53710942STom.Pothier@Sun.COM 	int strcnt;
53810942STom.Pothier@Sun.COM 	int compat = 0;
53910942STom.Pothier@Sun.COM 
54010942STom.Pothier@Sun.COM 	/* check for BKS */
54110942STom.Pothier@Sun.COM 	if (x86gentopo_legacy == 1) {
54210942STom.Pothier@Sun.COM 		return;
54310942STom.Pothier@Sun.COM 	}
54410942STom.Pothier@Sun.COM 
54510942STom.Pothier@Sun.COM 	shp = ksmbios;
54610942STom.Pothier@Sun.COM 	if (shp == NULL) {
54710942STom.Pothier@Sun.COM 		goto bad;
54810942STom.Pothier@Sun.COM 	}
54910942STom.Pothier@Sun.COM 
55010942STom.Pothier@Sun.COM 	/* OEM strings (Type 11) */
55110942STom.Pothier@Sun.COM 	strcnt = smb_cnttypes(shp, SMB_TYPE_OEMSTR);
55210942STom.Pothier@Sun.COM 	if (strcnt == 0)
55310942STom.Pothier@Sun.COM 		goto bad;
55410942STom.Pothier@Sun.COM 
55510942STom.Pothier@Sun.COM 	oemstypes = smb_create_strcnt(strcnt);
55610942STom.Pothier@Sun.COM 	if (oemstypes == NULL)
55710942STom.Pothier@Sun.COM 		goto bad;
55810942STom.Pothier@Sun.COM 
55910942STom.Pothier@Sun.COM 	oemstypes->type = SMB_TYPE_OEMSTR;
56010942STom.Pothier@Sun.COM 	smb_strcnt(shp, oemstypes);
56110942STom.Pothier@Sun.COM 
56210942STom.Pothier@Sun.COM 	for (i = 0; i < oemstypes->count; i++) {
56310942STom.Pothier@Sun.COM 		id = oemstypes->ids[i]->id;
56410942STom.Pothier@Sun.COM 		cnt = smbios_info_strtab(shp, id, 0, NULL);
56510942STom.Pothier@Sun.COM 		if (cnt > 0) {
56610942STom.Pothier@Sun.COM 			oem_strings = kmem_zalloc(sizeof (char *) * cnt,
56710942STom.Pothier@Sun.COM 			    KM_SLEEP);
56810942STom.Pothier@Sun.COM 			(void) smbios_info_strtab(shp, id, cnt, oem_strings);
56910942STom.Pothier@Sun.COM 
57010942STom.Pothier@Sun.COM 			for (j = 0; j < cnt; j++) {
57110942STom.Pothier@Sun.COM 				if (strncmp(oem_strings[j], SMB_PRMS1,
57210942STom.Pothier@Sun.COM 				    strlen(SMB_PRMS1) + 1) == 0) {
57310942STom.Pothier@Sun.COM 					kmem_free(oem_strings,
57410942STom.Pothier@Sun.COM 					    sizeof (char *) * cnt);
57510942STom.Pothier@Sun.COM 					smb_free_strcnt(oemstypes, strcnt);
57610942STom.Pothier@Sun.COM 					compat = 1;
57710942STom.Pothier@Sun.COM 					break;
57810942STom.Pothier@Sun.COM 				}
57910942STom.Pothier@Sun.COM 			}
58010942STom.Pothier@Sun.COM 		}
58110942STom.Pothier@Sun.COM 	}
58210942STom.Pothier@Sun.COM 
58310942STom.Pothier@Sun.COM 	if (compat == 0) {
58410942STom.Pothier@Sun.COM 		/* didn't find x86pi magic cookie */
58510942STom.Pothier@Sun.COM 		if (oem_strings != NULL)
58610942STom.Pothier@Sun.COM 			kmem_free(oem_strings, sizeof (char *) * cnt);
58710942STom.Pothier@Sun.COM 		smb_free_strcnt(oemstypes, strcnt);
58810942STom.Pothier@Sun.COM 		goto bad;
58910942STom.Pothier@Sun.COM 	}
59010942STom.Pothier@Sun.COM 
59110942STom.Pothier@Sun.COM 	/* sanity check SMBIOS structures */
59210942STom.Pothier@Sun.COM 	if (fm_smb_check(shp) == 0)
59310942STom.Pothier@Sun.COM 		return;
59410942STom.Pothier@Sun.COM 
59510942STom.Pothier@Sun.COM bad:
59610942STom.Pothier@Sun.COM 	/* not compatible with x86gentopo; revert to legacy enumeration */
59710942STom.Pothier@Sun.COM #ifdef	DEBUG
59810987STom.Pothier@Sun.COM 	cmn_err(CE_NOTE,
59910987STom.Pothier@Sun.COM 	    "!SMBIOS is not compatible with x86 generic topology.");
60010987STom.Pothier@Sun.COM 	cmn_err(CE_NOTE, "!Invoking legacy x86 topology enumeration.");
60110942STom.Pothier@Sun.COM #endif	/* DEBUG */
60210942STom.Pothier@Sun.COM 	x86gentopo_legacy = 1;
60310942STom.Pothier@Sun.COM }
60410942STom.Pothier@Sun.COM 
60510942STom.Pothier@Sun.COM static int
find_matching_apic(smbios_hdl_t * shp,uint16_t proc_id,uint_t strand_apicid)60610942STom.Pothier@Sun.COM find_matching_apic(smbios_hdl_t *shp, uint16_t proc_id, uint_t strand_apicid)
60710942STom.Pothier@Sun.COM {
60810942STom.Pothier@Sun.COM 	uint16_t ext_id;
60910942STom.Pothier@Sun.COM 	int i, j;
61010942STom.Pothier@Sun.COM 	smbios_processor_ext_t ep;
61110942STom.Pothier@Sun.COM 	smbs_cnt_t *pstypes;
61210942STom.Pothier@Sun.COM 	int strcnt;
61310942STom.Pothier@Sun.COM 
61410942STom.Pothier@Sun.COM 	strcnt = smb_cnttypes(shp, SUN_OEM_EXT_PROCESSOR);
61510942STom.Pothier@Sun.COM 	if (strcnt == 0)
61610942STom.Pothier@Sun.COM 		return (0);
61710942STom.Pothier@Sun.COM 
61810942STom.Pothier@Sun.COM 	pstypes = smb_create_strcnt(strcnt);
61910942STom.Pothier@Sun.COM 	if (pstypes == NULL)
62010942STom.Pothier@Sun.COM 		return (0);
62110942STom.Pothier@Sun.COM 
62210942STom.Pothier@Sun.COM 	pstypes->type = SUN_OEM_EXT_PROCESSOR;
62310942STom.Pothier@Sun.COM 	smb_strcnt(shp, pstypes);
62410942STom.Pothier@Sun.COM 	for (i = 0; i < pstypes->count; i++) {
62510942STom.Pothier@Sun.COM 		ext_id = pstypes->ids[i]->id;
62610942STom.Pothier@Sun.COM 		(void) smbios_info_extprocessor(shp, ext_id, &ep);
62710942STom.Pothier@Sun.COM 		if (ep.smbpe_processor == proc_id) {
62810942STom.Pothier@Sun.COM 			for (j = 0; j < ep.smbpe_n; j++) {
62910942STom.Pothier@Sun.COM 				if (ep.smbpe_apicid[j] == strand_apicid) {
63010942STom.Pothier@Sun.COM 					smb_free_strcnt(pstypes, strcnt);
63110942STom.Pothier@Sun.COM 					return (1);
63210942STom.Pothier@Sun.COM 				}
63310942STom.Pothier@Sun.COM 			}
63410942STom.Pothier@Sun.COM 		}
63510942STom.Pothier@Sun.COM 	}
63610942STom.Pothier@Sun.COM 	smb_free_strcnt(pstypes, strcnt);
63710942STom.Pothier@Sun.COM 	return (0);
63810942STom.Pothier@Sun.COM }
63910942STom.Pothier@Sun.COM 
64010942STom.Pothier@Sun.COM /*
64110942STom.Pothier@Sun.COM  * go throught the type 2 structure contained_ids looking for
64210942STom.Pothier@Sun.COM  * the type 4 which  has strand_apicid == this strand_apicid
64310942STom.Pothier@Sun.COM  */
64410942STom.Pothier@Sun.COM static int
find_matching_proc(smbios_hdl_t * shp,uint_t strand_apicid,uint16_t bb_id,uint16_t proc_hdl,int is_proc)64510942STom.Pothier@Sun.COM find_matching_proc(smbios_hdl_t *shp, uint_t strand_apicid,
64610942STom.Pothier@Sun.COM     uint16_t bb_id, uint16_t proc_hdl, int is_proc)
64710942STom.Pothier@Sun.COM {
64810942STom.Pothier@Sun.COM 	int n;
64910942STom.Pothier@Sun.COM 	const smb_struct_t *sp;
65010942STom.Pothier@Sun.COM 	smbios_bboard_t bb;
65110942STom.Pothier@Sun.COM 	uint_t cont_count, cont_len;
65210942STom.Pothier@Sun.COM 	uint16_t cont_id;
65310942STom.Pothier@Sun.COM 	id_t *cont_hdl = NULL;
65410942STom.Pothier@Sun.COM 	int rc;
65510942STom.Pothier@Sun.COM 
65610942STom.Pothier@Sun.COM 
65710942STom.Pothier@Sun.COM 	(void) smbios_info_bboard(shp, bb_id, &bb);
65810942STom.Pothier@Sun.COM 	cont_count = (uint_t)bb.smbb_contn;
65910942STom.Pothier@Sun.COM 	if (cont_count == 0)
66010942STom.Pothier@Sun.COM 		return (0);
66110942STom.Pothier@Sun.COM 
66210942STom.Pothier@Sun.COM 	cont_len = sizeof (id_t);
66310942STom.Pothier@Sun.COM 	cont_hdl = kmem_zalloc(cont_count * cont_len, KM_SLEEP);
66410942STom.Pothier@Sun.COM 	if (cont_hdl == NULL)
66510942STom.Pothier@Sun.COM 		return (0);
66610942STom.Pothier@Sun.COM 
66710942STom.Pothier@Sun.COM 	rc = smbios_info_contains(shp, bb_id, cont_count, cont_hdl);
66810942STom.Pothier@Sun.COM 	if (rc > SMB_CONT_MAX) {
66910942STom.Pothier@Sun.COM 		kmem_free(cont_hdl, cont_count * cont_len);
67010942STom.Pothier@Sun.COM 		return (0);
67110942STom.Pothier@Sun.COM 	}
67210942STom.Pothier@Sun.COM 	cont_count = MIN(rc, cont_count);
67310942STom.Pothier@Sun.COM 
67410942STom.Pothier@Sun.COM 	for (n = 0; n < cont_count; n++) {
67510942STom.Pothier@Sun.COM 		cont_id = (uint16_t)cont_hdl[n];
67610942STom.Pothier@Sun.COM 		sp = smb_lookup_id(shp, cont_id);
67710942STom.Pothier@Sun.COM 		if (sp->smbst_hdr->smbh_type == SMB_TYPE_PROCESSOR) {
67810942STom.Pothier@Sun.COM 			if (is_proc) {
67910942STom.Pothier@Sun.COM 				if (find_matching_apic(shp, cont_id,
68010942STom.Pothier@Sun.COM 				    strand_apicid)) {
68110942STom.Pothier@Sun.COM 					kmem_free(cont_hdl,
68210942STom.Pothier@Sun.COM 					    cont_count * cont_len);
68310942STom.Pothier@Sun.COM 					return (1);
68410942STom.Pothier@Sun.COM 				}
68510942STom.Pothier@Sun.COM 			} else {
68610942STom.Pothier@Sun.COM 				if (cont_id == proc_hdl) {
68710942STom.Pothier@Sun.COM 					kmem_free(cont_hdl,
68810942STom.Pothier@Sun.COM 					    cont_count * cont_len);
68910942STom.Pothier@Sun.COM 					return (1);
69010942STom.Pothier@Sun.COM 				}
69110942STom.Pothier@Sun.COM 			}
69210942STom.Pothier@Sun.COM 		}
69310942STom.Pothier@Sun.COM 	}
69410942STom.Pothier@Sun.COM 	if (cont_hdl != NULL)
69510942STom.Pothier@Sun.COM 		kmem_free(cont_hdl, cont_count * cont_len);
69610942STom.Pothier@Sun.COM 
69710942STom.Pothier@Sun.COM 	return (0);
69810942STom.Pothier@Sun.COM }
69910942STom.Pothier@Sun.COM 
70010942STom.Pothier@Sun.COM void
get_bboard_index(smbs_cnt_t * bbstypes,uint_t bb_id,bbindex_t * bb_idx)70110942STom.Pothier@Sun.COM get_bboard_index(smbs_cnt_t *bbstypes, uint_t bb_id, bbindex_t *bb_idx)
70210942STom.Pothier@Sun.COM {
70310942STom.Pothier@Sun.COM 	int curr_id, tmp_id;
70410942STom.Pothier@Sun.COM 	int i, j, nb;
70510942STom.Pothier@Sun.COM 	bbindex_t tmp_idx;
70610942STom.Pothier@Sun.COM 
70710942STom.Pothier@Sun.COM 	for (i = 0; i < MAX_PAIRS; i++)
70810942STom.Pothier@Sun.COM 		tmp_idx.index[i] = 0;
70910942STom.Pothier@Sun.COM 
71010942STom.Pothier@Sun.COM 	tmp_idx.count = 0;
71110942STom.Pothier@Sun.COM 
71210942STom.Pothier@Sun.COM 	curr_id = bb_id;
71310942STom.Pothier@Sun.COM 	for (nb = bbstypes->count-1, i = 0; nb >= 0; nb--) {
71410942STom.Pothier@Sun.COM 		tmp_id = bbstypes->ids[nb]->id;
71510942STom.Pothier@Sun.COM 		if (tmp_id == curr_id) {
71610942STom.Pothier@Sun.COM 			tmp_idx.index[i] = nb;
71710942STom.Pothier@Sun.COM 			tmp_idx.count++;
71810942STom.Pothier@Sun.COM 			curr_id = bbstypes->ids[nb]->cont_by_id;
71910942STom.Pothier@Sun.COM 			if (curr_id == -1)
72010942STom.Pothier@Sun.COM 				break;
72110942STom.Pothier@Sun.COM 			i++;
72210942STom.Pothier@Sun.COM 		}
72310942STom.Pothier@Sun.COM 	}
72410942STom.Pothier@Sun.COM 
72510942STom.Pothier@Sun.COM 	for (i = tmp_idx.count - 1, j = 0; i >= 0; i--) {
72610942STom.Pothier@Sun.COM 		bb_idx->index[j] = tmp_idx.index[i];
72710942STom.Pothier@Sun.COM 		j++;
72810942STom.Pothier@Sun.COM 	}
72910942STom.Pothier@Sun.COM 
73010942STom.Pothier@Sun.COM 	bb_idx->count = tmp_idx.count;
73110942STom.Pothier@Sun.COM }
73210942STom.Pothier@Sun.COM 
73310942STom.Pothier@Sun.COM int
get_chassis_inst(smbios_hdl_t * shp,uint16_t * chassis_inst,uint16_t bb_id,int * chcnt)73410942STom.Pothier@Sun.COM get_chassis_inst(smbios_hdl_t *shp, uint16_t *chassis_inst,
73510942STom.Pothier@Sun.COM     uint16_t bb_id, int *chcnt)
73610942STom.Pothier@Sun.COM {
73710942STom.Pothier@Sun.COM 	int ch_strcnt;
73810942STom.Pothier@Sun.COM 	smbs_cnt_t *chstypes;
73910942STom.Pothier@Sun.COM 	uint16_t chassis_id, tmp_id;
74010942STom.Pothier@Sun.COM 	smbios_bboard_t bb;
74110942STom.Pothier@Sun.COM 	int rc = 0;
74210942STom.Pothier@Sun.COM 	int i;
74310942STom.Pothier@Sun.COM 
74410942STom.Pothier@Sun.COM 	rc = smbios_info_bboard(shp, bb_id, &bb);
74510942STom.Pothier@Sun.COM 	if (rc != 0) {
74610942STom.Pothier@Sun.COM 		return (-1);
74710942STom.Pothier@Sun.COM 	}
74810942STom.Pothier@Sun.COM 
74910942STom.Pothier@Sun.COM 	chassis_id = bb.smbb_chassis;
75010942STom.Pothier@Sun.COM 
75110942STom.Pothier@Sun.COM 	ch_strcnt = smb_cnttypes(shp, SMB_TYPE_CHASSIS);
75210942STom.Pothier@Sun.COM 
75310942STom.Pothier@Sun.COM 	if (ch_strcnt == 0)
75410942STom.Pothier@Sun.COM 		return (-1);
75510942STom.Pothier@Sun.COM 
75610942STom.Pothier@Sun.COM 	chstypes = smb_create_strcnt(ch_strcnt);
75710942STom.Pothier@Sun.COM 	if (chstypes == NULL)
75810942STom.Pothier@Sun.COM 		return (-1);
75910942STom.Pothier@Sun.COM 
76010942STom.Pothier@Sun.COM 	chstypes->type = SMB_TYPE_CHASSIS;
76110942STom.Pothier@Sun.COM 	smb_strcnt(shp, chstypes);
76210942STom.Pothier@Sun.COM 
76310942STom.Pothier@Sun.COM 	for (i = 0; i < chstypes->count; i++) {
76410942STom.Pothier@Sun.COM 		tmp_id = chstypes->ids[i]->id;
76510942STom.Pothier@Sun.COM 		if (tmp_id == chassis_id) {
76610942STom.Pothier@Sun.COM 			*chassis_inst = chstypes->ids[i]->inst;
76710942STom.Pothier@Sun.COM 			if (chstypes->ids[i]->inst != 0)
76810942STom.Pothier@Sun.COM 				*chcnt = 2;
76910942STom.Pothier@Sun.COM 			else
77010942STom.Pothier@Sun.COM 				*chcnt = 1;
77110942STom.Pothier@Sun.COM 			smb_free_strcnt(chstypes, ch_strcnt);
77210942STom.Pothier@Sun.COM 			return (0);
77310942STom.Pothier@Sun.COM 		}
77410942STom.Pothier@Sun.COM 	}
77510942STom.Pothier@Sun.COM 
77610942STom.Pothier@Sun.COM 	smb_free_strcnt(chstypes, ch_strcnt);
77710942STom.Pothier@Sun.COM 	return (-1);
77810942STom.Pothier@Sun.COM }
77910942STom.Pothier@Sun.COM 
78010942STom.Pothier@Sun.COM int
smb_get_bb_fmri(smbios_hdl_t * shp,nvlist_t * fmri,uint_t parent,smbs_cnt_t * bbstypes)78110942STom.Pothier@Sun.COM smb_get_bb_fmri(smbios_hdl_t *shp, nvlist_t *fmri,  uint_t parent,
78210942STom.Pothier@Sun.COM     smbs_cnt_t *bbstypes)
78310942STom.Pothier@Sun.COM {
78410942STom.Pothier@Sun.COM 	int rc = 0;
78510942STom.Pothier@Sun.COM 	int i, j, n, cnt;
78610942STom.Pothier@Sun.COM 	int id, index;
78710942STom.Pothier@Sun.COM 	nvlist_t *pairs[MAX_PAIRS];
78810942STom.Pothier@Sun.COM 	smbios_bboard_t bb;
78910942STom.Pothier@Sun.COM 	uint16_t chassis_inst, mch_inst;
79010942STom.Pothier@Sun.COM 	char name[40];
79110942STom.Pothier@Sun.COM 	char idstr[11];
79210942STom.Pothier@Sun.COM 	bbindex_t bb_idx;
79310942STom.Pothier@Sun.COM 	uint16_t bbid;
79410942STom.Pothier@Sun.COM 	int chcnt = 0;
79510942STom.Pothier@Sun.COM 
79610942STom.Pothier@Sun.COM 	for (n = 0; n < MAX_PAIRS; n++) {
79710942STom.Pothier@Sun.COM 		bb_idx.index[n] = 0;
79810942STom.Pothier@Sun.COM 		pairs[n] = NULL;
79910942STom.Pothier@Sun.COM 	}
80010942STom.Pothier@Sun.COM 	bb_idx.count = 0;
80110942STom.Pothier@Sun.COM 
80210942STom.Pothier@Sun.COM 	get_bboard_index(bbstypes, parent, &bb_idx);
80310942STom.Pothier@Sun.COM 
80410942STom.Pothier@Sun.COM 	index = bb_idx.index[0];
80510942STom.Pothier@Sun.COM 	bbid = bbstypes->ids[index]->id;
80610942STom.Pothier@Sun.COM 
80710942STom.Pothier@Sun.COM 	rc = get_chassis_inst(shp, &chassis_inst, bbid, &chcnt);
80810942STom.Pothier@Sun.COM 
80910942STom.Pothier@Sun.COM 	if (rc != 0) {
81010942STom.Pothier@Sun.COM 		return (rc);
81110942STom.Pothier@Sun.COM 	}
81210942STom.Pothier@Sun.COM 
81310942STom.Pothier@Sun.COM 	if ((bb_idx.count + chcnt) > MAX_PAIRS) {
81410942STom.Pothier@Sun.COM 		return (-1);
81510942STom.Pothier@Sun.COM 	}
81610942STom.Pothier@Sun.COM 
81710942STom.Pothier@Sun.COM 	i = 0;
81810942STom.Pothier@Sun.COM 	if (chcnt > 1) {
81910942STom.Pothier@Sun.COM 		/*
82010942STom.Pothier@Sun.COM 		 * create main chassis pair
82110942STom.Pothier@Sun.COM 		 */
82210942STom.Pothier@Sun.COM 		pairs[i] = fm_nvlist_create(NULL);
82310942STom.Pothier@Sun.COM 		if (pairs[i] == NULL) {
82410942STom.Pothier@Sun.COM 			return (-1);
82510942STom.Pothier@Sun.COM 		}
82610942STom.Pothier@Sun.COM 		mch_inst = 0;
82710942STom.Pothier@Sun.COM 		(void) snprintf(idstr, sizeof (idstr), "%u", mch_inst);
82810942STom.Pothier@Sun.COM 		if ((nvlist_add_string(pairs[i], FM_FMRI_HC_NAME,
82910942STom.Pothier@Sun.COM 		    "chassis") != 0) ||
83010942STom.Pothier@Sun.COM 		    (nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr)) != 0) {
83110942STom.Pothier@Sun.COM 			fm_nvlist_destroy(pairs[i], FM_NVA_FREE);
83210942STom.Pothier@Sun.COM 			return (-1);
83310942STom.Pothier@Sun.COM 		}
83410942STom.Pothier@Sun.COM 		i++;
83510942STom.Pothier@Sun.COM 	}
83610942STom.Pothier@Sun.COM 
83710942STom.Pothier@Sun.COM 	/*
83810942STom.Pothier@Sun.COM 	 * create chassis pair
83910942STom.Pothier@Sun.COM 	 */
84010942STom.Pothier@Sun.COM 	pairs[i] = fm_nvlist_create(NULL);
84110942STom.Pothier@Sun.COM 	if (pairs[i] == NULL) {
84210942STom.Pothier@Sun.COM 		for (n = 0; n < MAX_PAIRS; n++) {
84310942STom.Pothier@Sun.COM 			if (pairs[n] != NULL)
84410942STom.Pothier@Sun.COM 				fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
84510942STom.Pothier@Sun.COM 		}
84610942STom.Pothier@Sun.COM 		return (-1);
84710942STom.Pothier@Sun.COM 	}
84810942STom.Pothier@Sun.COM 	(void) snprintf(idstr, sizeof (idstr), "%u", chassis_inst);
84910942STom.Pothier@Sun.COM 	if ((nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, "chassis") != 0) ||
85010942STom.Pothier@Sun.COM 	    (nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) != 0)) {
85110942STom.Pothier@Sun.COM 		for (n = 0; n < MAX_PAIRS; n++) {
85210942STom.Pothier@Sun.COM 			if (pairs[n] != NULL)
85310942STom.Pothier@Sun.COM 				fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
85410942STom.Pothier@Sun.COM 		}
85510942STom.Pothier@Sun.COM 		return (-1);
85610942STom.Pothier@Sun.COM 	}
85710942STom.Pothier@Sun.COM 
85810942STom.Pothier@Sun.COM 	for (j = 0, i = chcnt, cnt = chcnt; j < bb_idx.count; j++) {
85910942STom.Pothier@Sun.COM 		index = bb_idx.index[j];
86010942STom.Pothier@Sun.COM 		bbid = bbstypes->ids[index]->id;
86110942STom.Pothier@Sun.COM 		rc =  smbios_info_bboard(shp, bbid, &bb);
86210942STom.Pothier@Sun.COM 		if (rc != 0) {
86310942STom.Pothier@Sun.COM 			rc = -1;
86410942STom.Pothier@Sun.COM 			break;
86510942STom.Pothier@Sun.COM 		}
86610942STom.Pothier@Sun.COM 
86710942STom.Pothier@Sun.COM 		pairs[i] = fm_nvlist_create(NULL);
86810942STom.Pothier@Sun.COM 		if (pairs[i] == NULL) {
86910942STom.Pothier@Sun.COM 			rc = -1;
87010942STom.Pothier@Sun.COM 			break;
87110942STom.Pothier@Sun.COM 		}
87210942STom.Pothier@Sun.COM 
87310942STom.Pothier@Sun.COM 		id = bbstypes->ids[index]->inst;
87410942STom.Pothier@Sun.COM 		(void) snprintf(idstr, sizeof (idstr), "%u", id);
87510942STom.Pothier@Sun.COM 		(void) strncpy(name, bbd_type[bb.smbb_type].name,
87610942STom.Pothier@Sun.COM 		    sizeof (name));
87710942STom.Pothier@Sun.COM 		cnt++;
87810942STom.Pothier@Sun.COM 
87910942STom.Pothier@Sun.COM 		if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, name) != 0 ||
88010942STom.Pothier@Sun.COM 		    nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr)
88110942STom.Pothier@Sun.COM 		    != 0) {
88210942STom.Pothier@Sun.COM 			rc = -1;
88310942STom.Pothier@Sun.COM 			break;
88410942STom.Pothier@Sun.COM 		}
88510942STom.Pothier@Sun.COM 		i++;
88610942STom.Pothier@Sun.COM 	}
88710942STom.Pothier@Sun.COM 
88810942STom.Pothier@Sun.COM 	if (rc != -1) {
88910942STom.Pothier@Sun.COM 		if (nvlist_add_nvlist_array(fmri, FM_FMRI_HC_LIST,
89010942STom.Pothier@Sun.COM 		    pairs, cnt) != 0) {
89110942STom.Pothier@Sun.COM 			rc = -1;
89210942STom.Pothier@Sun.COM 		}
89310942STom.Pothier@Sun.COM 	}
89410942STom.Pothier@Sun.COM 
89510942STom.Pothier@Sun.COM 	for (n = 0; n < cnt; n++) {
89610942STom.Pothier@Sun.COM 		if (pairs[n] != NULL)
89710942STom.Pothier@Sun.COM 			fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
89810942STom.Pothier@Sun.COM 	}
89910942STom.Pothier@Sun.COM 
90010942STom.Pothier@Sun.COM 	return (rc);
90110942STom.Pothier@Sun.COM }
90210942STom.Pothier@Sun.COM 
90310942STom.Pothier@Sun.COM /*
90410942STom.Pothier@Sun.COM  * pass in strand_apic id
90510942STom.Pothier@Sun.COM  * return chip's bboards list which has strand_apicid == passed
90610942STom.Pothier@Sun.COM  * in strand_apic id
90710942STom.Pothier@Sun.COM  */
90810942STom.Pothier@Sun.COM static nvlist_t *
smb_bboard(uint_t strand_apicid,uint16_t proc_hdl,int is_proc)90910942STom.Pothier@Sun.COM smb_bboard(uint_t strand_apicid, uint16_t proc_hdl, int is_proc)
91010942STom.Pothier@Sun.COM {
91110942STom.Pothier@Sun.COM 	smbios_hdl_t *shp;
91210942STom.Pothier@Sun.COM 	smbs_cnt_t *bbstypes;
91310942STom.Pothier@Sun.COM 	int nb;
91410942STom.Pothier@Sun.COM 	int bb_smbid;
91510942STom.Pothier@Sun.COM 	nvlist_t *fmri = NULL;
91610942STom.Pothier@Sun.COM 	int rc = 0;
91710942STom.Pothier@Sun.COM 	int bb_strcnt;
91810942STom.Pothier@Sun.COM 
91910942STom.Pothier@Sun.COM 	if (x86gentopo_legacy)
92010942STom.Pothier@Sun.COM 		return (NULL);
92110942STom.Pothier@Sun.COM 
92210942STom.Pothier@Sun.COM 	shp = ksmbios;
92310942STom.Pothier@Sun.COM 	if (shp == NULL) {
92410942STom.Pothier@Sun.COM 		goto bad;
92510942STom.Pothier@Sun.COM 	}
92610942STom.Pothier@Sun.COM 
92710942STom.Pothier@Sun.COM 	/*
92810942STom.Pothier@Sun.COM 	 * Type 2 structs : "base board"
92910942STom.Pothier@Sun.COM 	 */
93010942STom.Pothier@Sun.COM 	bb_strcnt = smb_cnttypes(shp, SMB_TYPE_BASEBOARD);
93110942STom.Pothier@Sun.COM 	if (bb_strcnt == 0) {
93210942STom.Pothier@Sun.COM 		goto bad;
93310942STom.Pothier@Sun.COM 	}
93410942STom.Pothier@Sun.COM 
93510942STom.Pothier@Sun.COM 	bbstypes = smb_create_strcnt(bb_strcnt);
93610942STom.Pothier@Sun.COM 	if (bbstypes == NULL)  {
93710942STom.Pothier@Sun.COM 		goto bad;
93810942STom.Pothier@Sun.COM 	}
93910942STom.Pothier@Sun.COM 
94010942STom.Pothier@Sun.COM 	bbstypes->type = SMB_TYPE_BASEBOARD;
94110942STom.Pothier@Sun.COM 	smb_strcnt(shp, bbstypes);
94210942STom.Pothier@Sun.COM 	smb_bb_contains(shp, bbstypes);
94310942STom.Pothier@Sun.COM 
94410942STom.Pothier@Sun.COM 	for (nb = 0; nb < bbstypes->count; nb++) {
94510942STom.Pothier@Sun.COM 		if (bbstypes->ids[nb]->visited) {
94610942STom.Pothier@Sun.COM 			continue;
94710942STom.Pothier@Sun.COM 		}
94810942STom.Pothier@Sun.COM 
94910942STom.Pothier@Sun.COM 		bbstypes->ids[nb]->visited = 1;
95010942STom.Pothier@Sun.COM 		bb_smbid = bbstypes->ids[nb]->id;
95110942STom.Pothier@Sun.COM 
95210942STom.Pothier@Sun.COM 		/*
95310942STom.Pothier@Sun.COM 		 * check if there is a matching  processor under
95410942STom.Pothier@Sun.COM 		 * this board. If found, find base board(s) of this proc
95510942STom.Pothier@Sun.COM 		 * If proc is not in contained handle of a base board and
95610942STom.Pothier@Sun.COM 		 * there is only one base board in the system, treat that base
95710942STom.Pothier@Sun.COM 		 * board as the parent of the proc
95810942STom.Pothier@Sun.COM 		 */
95910942STom.Pothier@Sun.COM 		if (find_matching_proc(shp, strand_apicid,
96010942STom.Pothier@Sun.COM 		    bb_smbid, proc_hdl, is_proc) || (bbstypes->count == 1)) {
96110942STom.Pothier@Sun.COM 			fmri = fm_nvlist_create(NULL);
96210942STom.Pothier@Sun.COM 			if (fmri == NULL) {
96310942STom.Pothier@Sun.COM 				smb_free_strcnt(bbstypes, bb_strcnt);
96410942STom.Pothier@Sun.COM 				goto bad;
96510942STom.Pothier@Sun.COM 			}
96610942STom.Pothier@Sun.COM 			/*
96710942STom.Pothier@Sun.COM 			 * find parent by walking the cont_by_id
96810942STom.Pothier@Sun.COM 			 */
96910942STom.Pothier@Sun.COM 			rc = smb_get_bb_fmri(shp, fmri, bb_smbid, bbstypes);
97010942STom.Pothier@Sun.COM 			smb_free_strcnt(bbstypes, bb_strcnt);
97110942STom.Pothier@Sun.COM 			if (rc == 0) {
97210942STom.Pothier@Sun.COM 				return (fmri);
97310942STom.Pothier@Sun.COM 			} else
97410942STom.Pothier@Sun.COM 				goto bad;
97510942STom.Pothier@Sun.COM 		}
97610942STom.Pothier@Sun.COM 
97710942STom.Pothier@Sun.COM 	}
97810942STom.Pothier@Sun.COM 
97910942STom.Pothier@Sun.COM 	smb_free_strcnt(bbstypes, bb_strcnt);
98010942STom.Pothier@Sun.COM bad:
98110942STom.Pothier@Sun.COM 	/* revert to legacy enumeration */
98210942STom.Pothier@Sun.COM 	x86gentopo_legacy = 1;
98310942STom.Pothier@Sun.COM 
98410942STom.Pothier@Sun.COM 	return (NULL);
98510942STom.Pothier@Sun.COM }
98610942STom.Pothier@Sun.COM 
98710942STom.Pothier@Sun.COM nvlist_t *
fm_smb_bboard(uint_t strand_apicid)98810942STom.Pothier@Sun.COM fm_smb_bboard(uint_t strand_apicid)
98910942STom.Pothier@Sun.COM {
99010942STom.Pothier@Sun.COM 	return (smb_bboard(strand_apicid, 0, PROC));
99110942STom.Pothier@Sun.COM }
99210942STom.Pothier@Sun.COM 
99310942STom.Pothier@Sun.COM int
fm_smb_chipinst(uint_t strand_apicid,uint_t * chip_inst,uint16_t * smbiosid)99410942STom.Pothier@Sun.COM fm_smb_chipinst(uint_t strand_apicid, uint_t *chip_inst, uint16_t *smbiosid)
99510942STom.Pothier@Sun.COM {
99610942STom.Pothier@Sun.COM 	int n;
99710942STom.Pothier@Sun.COM 	smbios_hdl_t *shp;
99810942STom.Pothier@Sun.COM 	uint16_t proc_id;
99910942STom.Pothier@Sun.COM 	smbs_cnt_t *pstypes;
100010942STom.Pothier@Sun.COM 	int strcnt;
100110942STom.Pothier@Sun.COM 
100210942STom.Pothier@Sun.COM 	if (x86gentopo_legacy)
100310942STom.Pothier@Sun.COM 		return (-1);
100410942STom.Pothier@Sun.COM 
100510942STom.Pothier@Sun.COM 	shp = ksmbios;
100610942STom.Pothier@Sun.COM 	if (shp == NULL) {
100710942STom.Pothier@Sun.COM 		goto bad;
100810942STom.Pothier@Sun.COM 	}
100910942STom.Pothier@Sun.COM 
101010942STom.Pothier@Sun.COM 	strcnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
101110942STom.Pothier@Sun.COM 	if (strcnt == 0)
101210942STom.Pothier@Sun.COM 		goto bad;
101310942STom.Pothier@Sun.COM 
101410942STom.Pothier@Sun.COM 	pstypes = smb_create_strcnt(strcnt);
101510942STom.Pothier@Sun.COM 	if (pstypes == NULL)
101610942STom.Pothier@Sun.COM 		goto bad;
101710942STom.Pothier@Sun.COM 
101810942STom.Pothier@Sun.COM 	pstypes->type = SMB_TYPE_PROCESSOR;
101910942STom.Pothier@Sun.COM 	smb_strcnt(shp, pstypes);
102010942STom.Pothier@Sun.COM 	for (n = 0; n < pstypes->count; n++) {
102110942STom.Pothier@Sun.COM 		proc_id = pstypes->ids[n]->id;
102210942STom.Pothier@Sun.COM 		if (find_matching_apic(shp, proc_id, strand_apicid)) {
102310942STom.Pothier@Sun.COM 			*chip_inst = pstypes->ids[n]->inst;
102410942STom.Pothier@Sun.COM 			*smbiosid = pstypes->ids[n]->id;
102510942STom.Pothier@Sun.COM 			smb_free_strcnt(pstypes, strcnt);
102610942STom.Pothier@Sun.COM 			return (0);
102710942STom.Pothier@Sun.COM 		}
102810942STom.Pothier@Sun.COM 	}
102910942STom.Pothier@Sun.COM 	smb_free_strcnt(pstypes, strcnt);
103010942STom.Pothier@Sun.COM bad:
103110942STom.Pothier@Sun.COM 	/* revert to legacy enumerarion */
103210942STom.Pothier@Sun.COM 	x86gentopo_legacy = 1;
103310942STom.Pothier@Sun.COM 
103410942STom.Pothier@Sun.COM 	return (-1);
103510942STom.Pothier@Sun.COM }
103610942STom.Pothier@Sun.COM 
103710942STom.Pothier@Sun.COM nvlist_t *
fm_smb_mc_bboards(uint_t bdf)103810942STom.Pothier@Sun.COM fm_smb_mc_bboards(uint_t bdf)
103910942STom.Pothier@Sun.COM {
104010942STom.Pothier@Sun.COM 
104110942STom.Pothier@Sun.COM 	int i;
104210942STom.Pothier@Sun.COM 	smbios_hdl_t *shp;
104310942STom.Pothier@Sun.COM 	uint16_t ext_id;
104410942STom.Pothier@Sun.COM 	smbios_memarray_ext_t em;
104510942STom.Pothier@Sun.COM 	nvlist_t *fmri = NULL;
104610942STom.Pothier@Sun.COM 	smbs_cnt_t *mastypes;
104710942STom.Pothier@Sun.COM 	int strcnt;
104810942STom.Pothier@Sun.COM 
104910942STom.Pothier@Sun.COM 	if (x86gentopo_legacy)
105010942STom.Pothier@Sun.COM 		return (NULL);
105110942STom.Pothier@Sun.COM 
105210942STom.Pothier@Sun.COM 	shp = ksmbios;
105310942STom.Pothier@Sun.COM 	if (shp == NULL) {
105410942STom.Pothier@Sun.COM 		goto bad;
105510942STom.Pothier@Sun.COM 	}
105610942STom.Pothier@Sun.COM 
105710942STom.Pothier@Sun.COM 	strcnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
105810942STom.Pothier@Sun.COM 	if (strcnt == 0)
105910942STom.Pothier@Sun.COM 		goto bad;
106010942STom.Pothier@Sun.COM 
106110942STom.Pothier@Sun.COM 	mastypes = smb_create_strcnt(strcnt);
106210942STom.Pothier@Sun.COM 	if (mastypes == NULL)
106310942STom.Pothier@Sun.COM 		goto bad;
106410942STom.Pothier@Sun.COM 
106510942STom.Pothier@Sun.COM 	mastypes->type = SUN_OEM_EXT_MEMARRAY;
106610942STom.Pothier@Sun.COM 	smb_strcnt(shp, mastypes);
106710942STom.Pothier@Sun.COM 	for (i = 0; i < mastypes->count; i++) {
106810942STom.Pothier@Sun.COM 		ext_id = mastypes->ids[i]->id;
106910942STom.Pothier@Sun.COM 		(void) smbios_info_extmemarray(shp, ext_id, &em);
107010942STom.Pothier@Sun.COM 		if (em.smbmae_bdf == bdf) {
107110942STom.Pothier@Sun.COM 			fmri = smb_bboard(0, em.smbmae_comp, MC);
107210942STom.Pothier@Sun.COM 			smb_free_strcnt(mastypes, strcnt);
107310942STom.Pothier@Sun.COM 			return (fmri);
107410942STom.Pothier@Sun.COM 		}
107510942STom.Pothier@Sun.COM 	}
107610942STom.Pothier@Sun.COM 	smb_free_strcnt(mastypes, strcnt);
107710942STom.Pothier@Sun.COM bad:
107810942STom.Pothier@Sun.COM 	/* revert to legacy enumerarion */
107910942STom.Pothier@Sun.COM 	x86gentopo_legacy = 1;
108010942STom.Pothier@Sun.COM 
108110942STom.Pothier@Sun.COM 	return (NULL);
108210942STom.Pothier@Sun.COM }
108310942STom.Pothier@Sun.COM 
108410942STom.Pothier@Sun.COM int
fm_smb_mc_chipinst(uint_t bdf,uint_t * chip_inst)108510942STom.Pothier@Sun.COM fm_smb_mc_chipinst(uint_t bdf, uint_t *chip_inst) {
108610942STom.Pothier@Sun.COM 
108710942STom.Pothier@Sun.COM 	int i, j;
108810942STom.Pothier@Sun.COM 	smbios_hdl_t *shp;
108910942STom.Pothier@Sun.COM 	smbios_memarray_ext_t em;
109010942STom.Pothier@Sun.COM 	uint16_t ext_id, proc_id;
109110942STom.Pothier@Sun.COM 	smbs_cnt_t *mastypes;
109210942STom.Pothier@Sun.COM 	smbs_cnt_t *pstypes;
109310942STom.Pothier@Sun.COM 	int ma_strcnt, p_strcnt;
109410942STom.Pothier@Sun.COM 
109510942STom.Pothier@Sun.COM 	if (x86gentopo_legacy)
109610942STom.Pothier@Sun.COM 		return (-1);
109710942STom.Pothier@Sun.COM 
109810942STom.Pothier@Sun.COM 	shp = ksmbios;
109910942STom.Pothier@Sun.COM 	if (shp == NULL) {
110010942STom.Pothier@Sun.COM 		goto bad;
110110942STom.Pothier@Sun.COM 	}
110210942STom.Pothier@Sun.COM 
110310942STom.Pothier@Sun.COM 	ma_strcnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
110410942STom.Pothier@Sun.COM 	if (ma_strcnt == 0)
110510942STom.Pothier@Sun.COM 		goto bad;
110610942STom.Pothier@Sun.COM 
110710942STom.Pothier@Sun.COM 	mastypes = smb_create_strcnt(ma_strcnt);
110810942STom.Pothier@Sun.COM 	if (mastypes == NULL)
110910942STom.Pothier@Sun.COM 		goto bad;
111010942STom.Pothier@Sun.COM 
111110942STom.Pothier@Sun.COM 	mastypes->type = SUN_OEM_EXT_MEMARRAY;
111210942STom.Pothier@Sun.COM 	smb_strcnt(shp, mastypes);
111310942STom.Pothier@Sun.COM 	for (i = 0; i < mastypes->count; i++) {
111410942STom.Pothier@Sun.COM 		ext_id = mastypes->ids[i]->id;
111510942STom.Pothier@Sun.COM 		(void) smbios_info_extmemarray(shp, ext_id, &em);
111610942STom.Pothier@Sun.COM 		    if (em.smbmae_bdf == bdf) {
111710942STom.Pothier@Sun.COM 			p_strcnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
111810942STom.Pothier@Sun.COM 			if (p_strcnt == 0) {
111910942STom.Pothier@Sun.COM 				smb_free_strcnt(mastypes, ma_strcnt);
112010942STom.Pothier@Sun.COM 				goto bad;
112110942STom.Pothier@Sun.COM 			}
112210942STom.Pothier@Sun.COM 
112310942STom.Pothier@Sun.COM 			pstypes = smb_create_strcnt(p_strcnt);
112410942STom.Pothier@Sun.COM 			if (pstypes == NULL) {
112510942STom.Pothier@Sun.COM 				smb_free_strcnt(mastypes, ma_strcnt);
112610942STom.Pothier@Sun.COM 				goto bad;
112710942STom.Pothier@Sun.COM 			}
112810942STom.Pothier@Sun.COM 
112910942STom.Pothier@Sun.COM 			pstypes->type = SMB_TYPE_PROCESSOR;
113010942STom.Pothier@Sun.COM 			smb_strcnt(shp, pstypes);
113110942STom.Pothier@Sun.COM 			for (j = 0; j < pstypes->count; j++) {
113210942STom.Pothier@Sun.COM 				proc_id = pstypes->ids[j]->id;
113310942STom.Pothier@Sun.COM 				if (proc_id == em.smbmae_comp) {
113410942STom.Pothier@Sun.COM 					*chip_inst = pstypes->ids[j]->inst;
113510942STom.Pothier@Sun.COM 					smb_free_strcnt(mastypes, ma_strcnt);
113610942STom.Pothier@Sun.COM 					smb_free_strcnt(pstypes, p_strcnt);
113710942STom.Pothier@Sun.COM 					return (0);
113810942STom.Pothier@Sun.COM 				}
113910942STom.Pothier@Sun.COM 			}
114010942STom.Pothier@Sun.COM 		}
114110942STom.Pothier@Sun.COM 	}
114210942STom.Pothier@Sun.COM 	smb_free_strcnt(mastypes, ma_strcnt);
114310942STom.Pothier@Sun.COM 	smb_free_strcnt(pstypes, p_strcnt);
114410942STom.Pothier@Sun.COM bad:
114510942STom.Pothier@Sun.COM 	/* revert to legacy enumeration */
114610942STom.Pothier@Sun.COM 	x86gentopo_legacy = 1;
114710942STom.Pothier@Sun.COM 
114810942STom.Pothier@Sun.COM 	return (-1);
114910942STom.Pothier@Sun.COM }
1150