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 
22074bb90dSTom Pothier /*
23efd31e1dSTrang Do  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24074bb90dSTom Pothier  */
25074bb90dSTom Pothier 
26074bb90dSTom Pothier #include <unistd.h>
27074bb90dSTom Pothier #include <ctype.h>
28074bb90dSTom Pothier #include <strings.h>
29074bb90dSTom Pothier #include <sys/types.h>
30074bb90dSTom Pothier #include <sys/devfm.h>
31074bb90dSTom Pothier #include <libnvpair.h>
32074bb90dSTom Pothier #include <sys/smbios.h>
33074bb90dSTom Pothier #include <fm/topo_mod.h>
34074bb90dSTom Pothier #include <sys/fm/protocol.h>
35074bb90dSTom Pothier #include <sys/smbios_impl.h>
36074bb90dSTom Pothier 
37074bb90dSTom Pothier #include "chip.h"
38074bb90dSTom Pothier 
39074bb90dSTom Pothier #define	CPU_SLOTS	64
40074bb90dSTom Pothier #define	DIMM_SLOTS	512
41074bb90dSTom Pothier #define	MC_INSTANCES	128
42074bb90dSTom Pothier 
43074bb90dSTom Pothier #define	MAXNAMELEN	256
44074bb90dSTom Pothier #define	LABEL		1
45074bb90dSTom Pothier 
46074bb90dSTom Pothier #define	SKIP_CS		9999
47074bb90dSTom Pothier 
48074bb90dSTom Pothier 
49074bb90dSTom Pothier typedef struct cpu_smbios {
50074bb90dSTom Pothier 	id_t cpu_id;
51074bb90dSTom Pothier 	uint8_t status;
52074bb90dSTom Pothier 	uint8_t fru;
53074bb90dSTom Pothier }csmb_t;
54074bb90dSTom Pothier 
55074bb90dSTom Pothier typedef struct dimm_smbios {
56074bb90dSTom Pothier 	id_t dimm_id;
57074bb90dSTom Pothier 	id_t extdimm_id;
58074bb90dSTom Pothier 	const char *bankloc;
59074bb90dSTom Pothier }dsmb_t;
60074bb90dSTom Pothier 
61074bb90dSTom Pothier typedef struct mct_smbios {
62074bb90dSTom Pothier 	id_t extmct_id;
63074bb90dSTom Pothier 	id_t mct_id;
64074bb90dSTom Pothier 	id_t p_id;
65074bb90dSTom Pothier }msmb_t;
66074bb90dSTom Pothier 
67074bb90dSTom Pothier csmb_t cpusmb[CPU_SLOTS];
68074bb90dSTom Pothier dsmb_t dimmsmb[DIMM_SLOTS];
69074bb90dSTom Pothier msmb_t mctsmb[MC_INSTANCES];
70074bb90dSTom Pothier 
71074bb90dSTom Pothier static int ncpu_ids = 0;
72074bb90dSTom Pothier static int bb_count = 0;
73074bb90dSTom Pothier static int ndimm_ids, nmct_ids = 0;
74074bb90dSTom Pothier 
75074bb90dSTom Pothier static int fill_chip_smbios = 0;
76074bb90dSTom Pothier typedef int smbios_rec_f(topo_mod_t *, const smbios_struct_t *);
77074bb90dSTom Pothier 
78074bb90dSTom Pothier static smbios_struct_t *
smb_export(const smb_struct_t * stp,smbios_struct_t * sp)79074bb90dSTom Pothier smb_export(const smb_struct_t *stp, smbios_struct_t *sp)
80074bb90dSTom Pothier {
81074bb90dSTom Pothier 	const smb_header_t *hdr;
82074bb90dSTom Pothier 
83074bb90dSTom Pothier 	if (stp == NULL)
84074bb90dSTom Pothier 		return (NULL);
85074bb90dSTom Pothier 
86074bb90dSTom Pothier 	hdr = stp->smbst_hdr;
87074bb90dSTom Pothier 	sp->smbstr_id = hdr->smbh_hdl;
88074bb90dSTom Pothier 	sp->smbstr_type = hdr->smbh_type;
89074bb90dSTom Pothier 	sp->smbstr_data = hdr;
90074bb90dSTom Pothier 	sp->smbstr_size = (size_t)(stp->smbst_end - (uchar_t *)hdr);
91074bb90dSTom Pothier 
92074bb90dSTom Pothier 	return (sp);
93074bb90dSTom Pothier }
94074bb90dSTom Pothier 
95074bb90dSTom Pothier static int
extdimmslot_to_dimmslot(topo_mod_t * mod,id_t chip_smbid,int channum,int csnum)96efd31e1dSTrang Do extdimmslot_to_dimmslot(topo_mod_t *mod, id_t chip_smbid, int channum,
97efd31e1dSTrang Do     int csnum)
98074bb90dSTom Pothier {
99074bb90dSTom Pothier 	smbios_memdevice_ext_t emd;
100074bb90dSTom Pothier 	smbios_memdevice_t md;
101*679a141eSToomas Soome 	int i, j;
102074bb90dSTom Pothier 	int match = 0;
103efd31e1dSTrang Do 	smbios_hdl_t *shp;
104efd31e1dSTrang Do 
105efd31e1dSTrang Do 	shp = topo_mod_smbios(mod);
106efd31e1dSTrang Do 	if (shp == NULL)
107efd31e1dSTrang Do 		return (-1);
108074bb90dSTom Pothier 
109074bb90dSTom Pothier 	if (chip_smbid == IGNORE_ID && bb_count <= 1 && nmct_ids <= 1) {
110074bb90dSTom Pothier 		for (i = 0; i < ndimm_ids; i++) {
111*679a141eSToomas Soome 			if (smbios_info_extmemdevice(shp, dimmsmb[i].extdimm_id,
112*679a141eSToomas Soome 			    &emd) != 0) {
113*679a141eSToomas Soome 				continue;
114*679a141eSToomas Soome 			}
115*679a141eSToomas Soome 
116074bb90dSTom Pothier 			if (emd.smbmdeve_drch == channum) {
117*679a141eSToomas Soome 				uint_t ncs;
118*679a141eSToomas Soome 				uint8_t *cs;
119*679a141eSToomas Soome 
120*679a141eSToomas Soome 				if (csnum == SKIP_CS) {
121074bb90dSTom Pothier 					return (emd.smbmdeve_md);
122*679a141eSToomas Soome 				}
123*679a141eSToomas Soome 
124*679a141eSToomas Soome 				if (smbios_info_extmemdevice_cs(shp,
125*679a141eSToomas Soome 				    dimmsmb[i].extdimm_id, &ncs, &cs) != 0) {
126*679a141eSToomas Soome 					continue;
127*679a141eSToomas Soome 				}
128*679a141eSToomas Soome 
129*679a141eSToomas Soome 				for (uint_t k = 0; k < ncs; k++) {
130*679a141eSToomas Soome 					if (cs[k] != csnum) {
131*679a141eSToomas Soome 						continue;
132*679a141eSToomas Soome 					}
133*679a141eSToomas Soome 
134*679a141eSToomas Soome 					smbios_info_extmemdevice_cs_free(shp,
135*679a141eSToomas Soome 					    ncs, cs);
136*679a141eSToomas Soome 					return (emd.smbmdeve_md);
137*679a141eSToomas Soome 				}
138*679a141eSToomas Soome 
139*679a141eSToomas Soome 				smbios_info_extmemdevice_cs_free(shp, ncs, cs);
140074bb90dSTom Pothier 			}
141074bb90dSTom Pothier 		}
142074bb90dSTom Pothier 	}
143074bb90dSTom Pothier 
144074bb90dSTom Pothier 	for (j = 0; j < nmct_ids; j++) {
145074bb90dSTom Pothier 		if (mctsmb[j].p_id == chip_smbid) {
146074bb90dSTom Pothier 			for (i = 0; i < ndimm_ids; i++) {
147*679a141eSToomas Soome 				if (smbios_info_extmemdevice(shp,
148*679a141eSToomas Soome 				    dimmsmb[i].extdimm_id, &emd) != 0) {
149*679a141eSToomas Soome 					continue;
150*679a141eSToomas Soome 				}
151*679a141eSToomas Soome 
152074bb90dSTom Pothier 				(void) smbios_info_memdevice(shp,
153074bb90dSTom Pothier 				    emd.smbmdeve_md, &md);
154074bb90dSTom Pothier 				if (md.smbmd_array == mctsmb[j].mct_id &&
155074bb90dSTom Pothier 				    emd.smbmdeve_drch == channum) {
156074bb90dSTom Pothier 					match = 1;
157074bb90dSTom Pothier 					break;
158074bb90dSTom Pothier 				}
159074bb90dSTom Pothier 			}
160074bb90dSTom Pothier 			if (match) {
161*679a141eSToomas Soome 				uint_t ncs;
162*679a141eSToomas Soome 				uint8_t *cs;
163*679a141eSToomas Soome 
164*679a141eSToomas Soome 				if (csnum == SKIP_CS) {
165*679a141eSToomas Soome 					return (emd.smbmdeve_md);
166*679a141eSToomas Soome 				}
167*679a141eSToomas Soome 
168*679a141eSToomas Soome 				if (smbios_info_extmemdevice_cs(shp,
169*679a141eSToomas Soome 				    dimmsmb[i].extdimm_id, &ncs, &cs) != 0) {
170*679a141eSToomas Soome 					continue;
171*679a141eSToomas Soome 				}
172*679a141eSToomas Soome 
173*679a141eSToomas Soome 				for (uint_t k = 0; k < ncs; k++) {
174*679a141eSToomas Soome 					if (cs[k] != csnum) {
175*679a141eSToomas Soome 						continue;
176*679a141eSToomas Soome 					}
177*679a141eSToomas Soome 
178*679a141eSToomas Soome 					smbios_info_extmemdevice_cs_free(shp,
179*679a141eSToomas Soome 					    ncs, cs);
180074bb90dSTom Pothier 					return (emd.smbmdeve_md);
181*679a141eSToomas Soome 				}
182*679a141eSToomas Soome 				smbios_info_extmemdevice_cs_free(shp, ncs, cs);
183074bb90dSTom Pothier 			}
184074bb90dSTom Pothier 		}
185074bb90dSTom Pothier 	}
186074bb90dSTom Pothier 
187074bb90dSTom Pothier 	return (-1);
188074bb90dSTom Pothier }
189074bb90dSTom Pothier 
190074bb90dSTom Pothier id_t
memnode_to_smbiosid(topo_mod_t * mod,uint16_t chip_smbid,const char * name,uint64_t nodeid,void * data)191efd31e1dSTrang Do memnode_to_smbiosid(topo_mod_t *mod, uint16_t chip_smbid, const char *name,
192efd31e1dSTrang Do     uint64_t nodeid, void *data)
193074bb90dSTom Pothier {
194074bb90dSTom Pothier 
195074bb90dSTom Pothier 	if (strcmp(name, CS_NODE_NAME) == 0) {
196074bb90dSTom Pothier 		int channum, csnum;
197074bb90dSTom Pothier 		id_t dimmslot = -1;
198074bb90dSTom Pothier 
199074bb90dSTom Pothier 		if (data == NULL)
200074bb90dSTom Pothier 			return (-1);
201074bb90dSTom Pothier 		channum = *(int *)data;
202074bb90dSTom Pothier 		csnum = nodeid;
203074bb90dSTom Pothier 		/*
204074bb90dSTom Pothier 		 * Set the DIMM Slot label to the Chip Select Node
205074bb90dSTom Pothier 		 * Set the "data" to carry the DIMM instance
206074bb90dSTom Pothier 		 */
207efd31e1dSTrang Do 		dimmslot = extdimmslot_to_dimmslot(mod, chip_smbid, channum,
208efd31e1dSTrang Do 		    csnum);
209074bb90dSTom Pothier 		if (dimmslot != -1 && dimmsmb[0].dimm_id != 0)
210074bb90dSTom Pothier 			*((id_t *)data) = dimmslot % (dimmsmb[0].dimm_id);
211074bb90dSTom Pothier 		else
212074bb90dSTom Pothier 			*((id_t *)data) = -1;
213074bb90dSTom Pothier 
214074bb90dSTom Pothier 		return (dimmslot);
215074bb90dSTom Pothier 
216074bb90dSTom Pothier 	} else if (strcmp(name, DIMM_NODE_NAME) == 0) {
217074bb90dSTom Pothier 		static int dimmnum = 0;
218074bb90dSTom Pothier 
219074bb90dSTom Pothier 		/*
220074bb90dSTom Pothier 		 * On certain Intel Chips, topology does not have
221074bb90dSTom Pothier 		 * chip-select nodes, it has the below layout
222074bb90dSTom Pothier 		 * chip/memory-controller/dram-channel/dimm
223074bb90dSTom Pothier 		 * so we check if channel instance is passed
224074bb90dSTom Pothier 		 * and get the SMBIOS ID based on the channel
225074bb90dSTom Pothier 		 */
226074bb90dSTom Pothier 		if (data != NULL) {
227074bb90dSTom Pothier 			int channum;
228074bb90dSTom Pothier 			id_t dimmslot = -1;
229074bb90dSTom Pothier 
230074bb90dSTom Pothier 			channum = *(int *)data;
231efd31e1dSTrang Do 			dimmslot = extdimmslot_to_dimmslot(mod, chip_smbid,
232074bb90dSTom Pothier 			    channum, SKIP_CS);
233074bb90dSTom Pothier 
234074bb90dSTom Pothier 			return (dimmslot);
235074bb90dSTom Pothier 		}
236074bb90dSTom Pothier 		dimmnum = nodeid;
237074bb90dSTom Pothier 		return (dimmsmb[dimmnum].dimm_id);
238074bb90dSTom Pothier 	}
239074bb90dSTom Pothier 
240074bb90dSTom Pothier 	return (-1);
241074bb90dSTom Pothier }
242074bb90dSTom Pothier 
243074bb90dSTom Pothier 
244074bb90dSTom Pothier int
chip_get_smbstruct(topo_mod_t * mod,const smbios_struct_t * sp)245074bb90dSTom Pothier chip_get_smbstruct(topo_mod_t *mod, const smbios_struct_t *sp)
246074bb90dSTom Pothier {
247074bb90dSTom Pothier 	smbios_processor_t p;
248074bb90dSTom Pothier 	smbios_memdevice_t md;
249074bb90dSTom Pothier 	smbios_processor_ext_t extp;
250074bb90dSTom Pothier 	smbios_memarray_ext_t extma;
251bb1fad37SSrihari Venkatesan 	smbios_memdevice_ext_t extmd;
252bb1fad37SSrihari Venkatesan 	int ext_match = 0;
253efd31e1dSTrang Do 	smbios_hdl_t *shp;
254efd31e1dSTrang Do 
255efd31e1dSTrang Do 	shp = topo_mod_smbios(mod);
256efd31e1dSTrang Do 	if (shp == NULL)
257efd31e1dSTrang Do 		return (-1);
258074bb90dSTom Pothier 
259074bb90dSTom Pothier 	switch (sp->smbstr_type) {
260074bb90dSTom Pothier 	case SMB_TYPE_BASEBOARD:
261074bb90dSTom Pothier 		bb_count++;
262074bb90dSTom Pothier 		break;
263074bb90dSTom Pothier 	case SMB_TYPE_MEMARRAY:
264074bb90dSTom Pothier 		mctsmb[nmct_ids].mct_id = sp->smbstr_id;
265bb1fad37SSrihari Venkatesan 		nmct_ids++;
266074bb90dSTom Pothier 		break;
267074bb90dSTom Pothier 	case SUN_OEM_EXT_MEMARRAY:
268074bb90dSTom Pothier 		if (shp != NULL) {
269074bb90dSTom Pothier 			if (smbios_info_extmemarray(shp,
270074bb90dSTom Pothier 			    sp->smbstr_id, &extma) != 0) {
271074bb90dSTom Pothier 				topo_mod_dprintf(mod, "chip_get_smbstruct : "
272074bb90dSTom Pothier 				    "smbios_info_extmemarray()"
273074bb90dSTom Pothier 				    "failed\n");
274074bb90dSTom Pothier 				return (-1);
275074bb90dSTom Pothier 			}
276074bb90dSTom Pothier 		} else
277074bb90dSTom Pothier 			return (-1);
278bb1fad37SSrihari Venkatesan 		for (int i = 0; i < nmct_ids; i++) {
279bb1fad37SSrihari Venkatesan 			if (extma.smbmae_ma == mctsmb[i].mct_id) {
280bb1fad37SSrihari Venkatesan 				mctsmb[i].extmct_id = sp->smbstr_id;
281bb1fad37SSrihari Venkatesan 				mctsmb[i].p_id = extma.smbmae_comp;
282bb1fad37SSrihari Venkatesan 				ext_match = 1;
283bb1fad37SSrihari Venkatesan 				break;
284bb1fad37SSrihari Venkatesan 			}
285bb1fad37SSrihari Venkatesan 		}
286bb1fad37SSrihari Venkatesan 		if (!ext_match) {
287bb1fad37SSrihari Venkatesan 			topo_mod_dprintf(mod, "chip_get_smbstruct : "
288bb1fad37SSrihari Venkatesan 			    "EXT_MEMARRAY-MEMARRAY records are mismatched\n");
289bb1fad37SSrihari Venkatesan 			ext_match = 0;
290074bb90dSTom Pothier 			return (-1);
291bb1fad37SSrihari Venkatesan 		}
292074bb90dSTom Pothier 		break;
293074bb90dSTom Pothier 	case SMB_TYPE_MEMDEVICE:
294074bb90dSTom Pothier 		dimmsmb[ndimm_ids].dimm_id = sp->smbstr_id;
295074bb90dSTom Pothier 		if (shp != NULL) {
296074bb90dSTom Pothier 			if (smbios_info_memdevice(shp,
297074bb90dSTom Pothier 			    sp->smbstr_id, &md) != 0)
298074bb90dSTom Pothier 				return (-1);
299074bb90dSTom Pothier 		} else
300074bb90dSTom Pothier 			return (-1);
301074bb90dSTom Pothier 		dimmsmb[ndimm_ids].bankloc = md.smbmd_bloc;
302bb1fad37SSrihari Venkatesan 		ndimm_ids++;
303074bb90dSTom Pothier 		break;
304074bb90dSTom Pothier 	/*
305074bb90dSTom Pothier 	 * Every SMB_TYPE_MEMDEVICE SHOULD have a
306074bb90dSTom Pothier 	 * corresponding SUN_OEM_EXT_MEMDEVICE
307074bb90dSTom Pothier 	 */
308074bb90dSTom Pothier 	case SUN_OEM_EXT_MEMDEVICE:
309bb1fad37SSrihari Venkatesan 		if (smbios_info_extmemdevice(shp,
310bb1fad37SSrihari Venkatesan 		    sp->smbstr_id, &extmd) != 0) {
311bb1fad37SSrihari Venkatesan 			topo_mod_dprintf(mod, "chip_get_smbstruct : "
312bb1fad37SSrihari Venkatesan 			    "smbios_info_extmemdevice()"
313bb1fad37SSrihari Venkatesan 			    "failed\n");
314bb1fad37SSrihari Venkatesan 			return (-1);
315bb1fad37SSrihari Venkatesan 		}
316bb1fad37SSrihari Venkatesan 		for (int i = 0; i < ndimm_ids; i++) {
317bb1fad37SSrihari Venkatesan 			if (extmd.smbmdeve_md == dimmsmb[i].dimm_id) {
318bb1fad37SSrihari Venkatesan 				dimmsmb[i].extdimm_id = sp->smbstr_id;
319bb1fad37SSrihari Venkatesan 				ext_match = 1;
320bb1fad37SSrihari Venkatesan 				break;
321bb1fad37SSrihari Venkatesan 			}
322bb1fad37SSrihari Venkatesan 		}
323bb1fad37SSrihari Venkatesan 		if (!ext_match) {
324bb1fad37SSrihari Venkatesan 			topo_mod_dprintf(mod, "chip_get_smbstruct : "
325bb1fad37SSrihari Venkatesan 			    "EXT_MEMDEVICE-MEMDEVICE records are mismatched\n");
326bb1fad37SSrihari Venkatesan 			ext_match = 0;
327bb1fad37SSrihari Venkatesan 			return (-1);
328bb1fad37SSrihari Venkatesan 		}
329074bb90dSTom Pothier 		break;
330074bb90dSTom Pothier 	case SMB_TYPE_PROCESSOR:
331074bb90dSTom Pothier 		cpusmb[ncpu_ids].cpu_id = sp->smbstr_id;
332074bb90dSTom Pothier 		if (shp != NULL) {
333074bb90dSTom Pothier 			if (smbios_info_processor(shp,
334074bb90dSTom Pothier 			    sp->smbstr_id, &p) != 0) {
335074bb90dSTom Pothier 				topo_mod_dprintf(mod, "chip_get_smbstruct : "
336074bb90dSTom Pothier 				    "smbios_info_processor()"
337074bb90dSTom Pothier 				    "failed\n");
338074bb90dSTom Pothier 				return (-1);
339074bb90dSTom Pothier 			}
340074bb90dSTom Pothier 		}
341074bb90dSTom Pothier 		cpusmb[ncpu_ids].status = p.smbp_status;
342bb1fad37SSrihari Venkatesan 		ncpu_ids++;
343074bb90dSTom Pothier 		break;
344074bb90dSTom Pothier 	/*
345074bb90dSTom Pothier 	 * Every SMB_TYPE_PROCESSOR SHOULD have a
346074bb90dSTom Pothier 	 * corresponding SUN_OEM_EXT_PROCESSOR
347074bb90dSTom Pothier 	 */
348074bb90dSTom Pothier 	case SUN_OEM_EXT_PROCESSOR:
349074bb90dSTom Pothier 		if (smbios_info_extprocessor(shp,
350074bb90dSTom Pothier 		    sp->smbstr_id, &extp) != 0) {
351074bb90dSTom Pothier 			topo_mod_dprintf(mod, "chip_get_smbstruct : "
352074bb90dSTom Pothier 			    "smbios_info_extprocessor()"
353074bb90dSTom Pothier 			    "failed\n");
354074bb90dSTom Pothier 			return (-1);
355074bb90dSTom Pothier 		}
356bb1fad37SSrihari Venkatesan 		for (int i = 0; i < ncpu_ids; i++) {
357bb1fad37SSrihari Venkatesan 			if (extp.smbpe_processor == cpusmb[i].cpu_id) {
358bb1fad37SSrihari Venkatesan 				cpusmb[i].fru = extp.smbpe_fru;
359bb1fad37SSrihari Venkatesan 				ext_match = 1;
360bb1fad37SSrihari Venkatesan 				break;
361bb1fad37SSrihari Venkatesan 			}
362bb1fad37SSrihari Venkatesan 		}
363bb1fad37SSrihari Venkatesan 		if (!ext_match) {
364bb1fad37SSrihari Venkatesan 			topo_mod_dprintf(mod, "chip_get_smbstruct : "
365bb1fad37SSrihari Venkatesan 			    "EXT_PROCESSOR-PROCESSOR records are mismatched\n");
366bb1fad37SSrihari Venkatesan 			ext_match = 0;
367bb1fad37SSrihari Venkatesan 			return (-1);
368bb1fad37SSrihari Venkatesan 		}
369074bb90dSTom Pothier 		break;
370074bb90dSTom Pothier 	}
371074bb90dSTom Pothier 	return (0);
372074bb90dSTom Pothier }
373074bb90dSTom Pothier 
374074bb90dSTom Pothier static int
chip_smbios_iterate(topo_mod_t * mod,smbios_rec_f * func_iter)375074bb90dSTom Pothier chip_smbios_iterate(topo_mod_t *mod, smbios_rec_f *func_iter)
376074bb90dSTom Pothier {
377efd31e1dSTrang Do 	const smb_struct_t *sp;
378074bb90dSTom Pothier 	smbios_struct_t s;
379074bb90dSTom Pothier 	int i, rv = 0;
380efd31e1dSTrang Do 	smbios_hdl_t *shp;
381074bb90dSTom Pothier 
382efd31e1dSTrang Do 	shp = topo_mod_smbios(mod);
383efd31e1dSTrang Do 	if (shp == NULL)
384efd31e1dSTrang Do 		return (rv);
385efd31e1dSTrang Do 
386efd31e1dSTrang Do 	sp = shp->sh_structs;
387074bb90dSTom Pothier 	for (i = 0; i < shp->sh_nstructs; i++, sp++) {
388074bb90dSTom Pothier 		if (sp->smbst_hdr->smbh_type != SMB_TYPE_INACTIVE &&
389074bb90dSTom Pothier 		    (rv = func_iter(mod, smb_export(sp, &s))) != 0)
390074bb90dSTom Pothier 			break;
391074bb90dSTom Pothier 	}
392074bb90dSTom Pothier 	return (rv);
393074bb90dSTom Pothier }
394074bb90dSTom Pothier 
395074bb90dSTom Pothier int
init_chip_smbios(topo_mod_t * mod)396074bb90dSTom Pothier init_chip_smbios(topo_mod_t *mod)
397074bb90dSTom Pothier {
398074bb90dSTom Pothier 	if (!fill_chip_smbios) {
399074bb90dSTom Pothier 		if (chip_smbios_iterate(mod, chip_get_smbstruct) == -1)
400074bb90dSTom Pothier 			return (-1);
401074bb90dSTom Pothier 		fill_chip_smbios = 1;
402074bb90dSTom Pothier 	}
403074bb90dSTom Pothier 
404074bb90dSTom Pothier 	return (0);
405074bb90dSTom Pothier }
406074bb90dSTom Pothier 
407074bb90dSTom Pothier int
chip_status_smbios_get(topo_mod_t * mod,id_t smb_id)408074bb90dSTom Pothier chip_status_smbios_get(topo_mod_t *mod, id_t smb_id)
409074bb90dSTom Pothier {
410074bb90dSTom Pothier 	/*
411074bb90dSTom Pothier 	 * Type-4 Socket Status bit definitions per SMBIOS Version 2.6
412074bb90dSTom Pothier 	 *
413074bb90dSTom Pothier 	 * STATUS
414074bb90dSTom Pothier 	 * CPU Socket Populated
415074bb90dSTom Pothier 	 * CPU Socket Unpopulated
416074bb90dSTom Pothier 	 * Populated : Enabled
417074bb90dSTom Pothier 	 * Populated : Disabled by BIOS (Setup)
418074bb90dSTom Pothier 	 * Populated : Disabled by BIOS (Error)
419074bb90dSTom Pothier 	 * Populated : Idle
420074bb90dSTom Pothier 	 */
421074bb90dSTom Pothier 	uint8_t	enabled = 0x01;
422074bb90dSTom Pothier 	uint8_t	populated = 0x40;
423074bb90dSTom Pothier 
424074bb90dSTom Pothier 	for (int i = 0; i < ncpu_ids; i++) {
425074bb90dSTom Pothier 		if (smb_id == cpusmb[i].cpu_id) {
426074bb90dSTom Pothier 			if (cpusmb[i].status  == (enabled | populated))
427074bb90dSTom Pothier 				return (1);
428074bb90dSTom Pothier 		}
429074bb90dSTom Pothier 	}
430074bb90dSTom Pothier 
431bb1fad37SSrihari Venkatesan 	topo_mod_dprintf(mod, "chip_status_smbios_get() failed"
4326597d6fcSRobert Mustacchi 	    " considering that Type 4 ID : %ld is disabled", smb_id);
433074bb90dSTom Pothier 	return (0);
434074bb90dSTom Pothier }
435074bb90dSTom Pothier 
436074bb90dSTom Pothier int
chip_fru_smbios_get(topo_mod_t * mod,id_t smb_id)437074bb90dSTom Pothier chip_fru_smbios_get(topo_mod_t *mod, id_t smb_id)
438074bb90dSTom Pothier {
439074bb90dSTom Pothier 	/*
440074bb90dSTom Pothier 	 * smbios_processor_ext_t->smbpe_fru : if set to 1
441074bb90dSTom Pothier 	 * processor is a FRU
442074bb90dSTom Pothier 	 */
443074bb90dSTom Pothier 	uint8_t	fru = 1;
444074bb90dSTom Pothier 
445074bb90dSTom Pothier 	for (int i = 0; i < ncpu_ids; i++) {
446074bb90dSTom Pothier 		if (smb_id == cpusmb[i].cpu_id) {
447074bb90dSTom Pothier 			if (cpusmb[i].fru == fru)
448074bb90dSTom Pothier 				return (1);
449074bb90dSTom Pothier 			else
450074bb90dSTom Pothier 				return (0);
451074bb90dSTom Pothier 		}
452074bb90dSTom Pothier 	}
453074bb90dSTom Pothier 
454bb1fad37SSrihari Venkatesan 	topo_mod_dprintf(mod, "chip_fru_smbios_get() failed"
4556597d6fcSRobert Mustacchi 	    " considering that Type 4 ID : %ld is not a FRU", smb_id);
456074bb90dSTom Pothier 	return (0);
457074bb90dSTom Pothier }
458074bb90dSTom Pothier 
459074bb90dSTom Pothier /*
460074bb90dSTom Pothier  * This could be defined as topo_mod_strlen()
461074bb90dSTom Pothier  */
462074bb90dSTom Pothier size_t
chip_strlen(const char * str)463074bb90dSTom Pothier chip_strlen(const char *str)
464074bb90dSTom Pothier {
465074bb90dSTom Pothier 	int len = 0;
466074bb90dSTom Pothier 
467074bb90dSTom Pothier 	if (str != NULL)
468074bb90dSTom Pothier 		len = strlen(str);
469074bb90dSTom Pothier 
470074bb90dSTom Pothier 	return (len);
471074bb90dSTom Pothier }
472074bb90dSTom Pothier 
473074bb90dSTom Pothier /*
474074bb90dSTom Pothier  * We clean Serials, Revisions, Part No. strings, to
475074bb90dSTom Pothier  * avoid getting lost when fmd synthesizes these
476074bb90dSTom Pothier  * strings. :, =, /, ' ' characters are replaced
477074bb90dSTom Pothier  * with character '-' any non-printable characters
478074bb90dSTom Pothier  * as seen with !isprint() is also replaced with '-'
479074bb90dSTom Pothier  * Labels are checked only for non-printable characters.
480074bb90dSTom Pothier  */
481074bb90dSTom Pothier static const char *
chip_cleanup_smbios_str(topo_mod_t * mod,const char * begin,int str_type)482074bb90dSTom Pothier chip_cleanup_smbios_str(topo_mod_t *mod, const char *begin, int str_type)
483074bb90dSTom Pothier {
484074bb90dSTom Pothier 	char buf[MAXNAMELEN];
485074bb90dSTom Pothier 	const char *end, *cp;
486074bb90dSTom Pothier 	char *pp;
487074bb90dSTom Pothier 	char c;
488074bb90dSTom Pothier 	int i;
489074bb90dSTom Pothier 
490074bb90dSTom Pothier 	end = begin + strlen(begin);
491074bb90dSTom Pothier 
492074bb90dSTom Pothier 	while (begin < end && isspace(*begin))
493074bb90dSTom Pothier 		begin++;
494074bb90dSTom Pothier 	while (begin < end && isspace(*(end - 1)))
495074bb90dSTom Pothier 		end--;
496074bb90dSTom Pothier 
497074bb90dSTom Pothier 	if (begin >= end)
498074bb90dSTom Pothier 		return (NULL);
499074bb90dSTom Pothier 
500074bb90dSTom Pothier 	cp = begin;
501074bb90dSTom Pothier 	for (i = 0; i < MAXNAMELEN - 1; i++) {
502074bb90dSTom Pothier 		if (cp >= end)
503074bb90dSTom Pothier 			break;
504074bb90dSTom Pothier 		c = *cp;
505074bb90dSTom Pothier 		if (str_type == LABEL) {
506074bb90dSTom Pothier 			if (!isprint(c))
507074bb90dSTom Pothier 				buf[i] = '-';
508074bb90dSTom Pothier 			else
509074bb90dSTom Pothier 				buf[i] = c;
510074bb90dSTom Pothier 		} else {
511074bb90dSTom Pothier 			if (c == ':' || c == '=' || c == '/' ||
512074bb90dSTom Pothier 			    isspace(c) || !isprint(c))
513074bb90dSTom Pothier 				buf[i] = '-';
514074bb90dSTom Pothier 			else
515074bb90dSTom Pothier 				buf[i] = c;
516074bb90dSTom Pothier 		}
517074bb90dSTom Pothier 		cp++;
518074bb90dSTom Pothier 	}
519074bb90dSTom Pothier 	buf[i] = 0;
520074bb90dSTom Pothier 
521074bb90dSTom Pothier 	pp = topo_mod_strdup(mod, buf);
522074bb90dSTom Pothier 
523074bb90dSTom Pothier 	if (str_type == LABEL)
524074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)begin);
525074bb90dSTom Pothier 
526074bb90dSTom Pothier 	return (pp);
527074bb90dSTom Pothier }
528074bb90dSTom Pothier 
529074bb90dSTom Pothier const char *
chip_label_smbios_get(topo_mod_t * mod,tnode_t * pnode,id_t smb_id,char * ksmbios_label)530074bb90dSTom Pothier chip_label_smbios_get(topo_mod_t *mod, tnode_t *pnode, id_t smb_id,
531074bb90dSTom Pothier     char *ksmbios_label)
532074bb90dSTom Pothier {
533074bb90dSTom Pothier 	smbios_info_t c;
534074bb90dSTom Pothier 	char *label = NULL;
535074bb90dSTom Pothier 	char *buf = NULL;
536074bb90dSTom Pothier 	const char *lsmbios_label = NULL;
537074bb90dSTom Pothier 	int bufsz = 0;
538074bb90dSTom Pothier 	char *delim = NULL, *blank = " ";
539074bb90dSTom Pothier 	const char *dimm_bank = NULL;
540074bb90dSTom Pothier 	const char *clean_label = NULL;
541074bb90dSTom Pothier 	int err;
542efd31e1dSTrang Do 	smbios_hdl_t *shp;
543074bb90dSTom Pothier 
544efd31e1dSTrang Do 	shp = topo_mod_smbios(mod);
545074bb90dSTom Pothier 	if (shp != NULL) {
546074bb90dSTom Pothier 		/*
547074bb90dSTom Pothier 		 * Get Parent FRU's label
548074bb90dSTom Pothier 		 */
549074bb90dSTom Pothier 		if (topo_prop_get_string(pnode, TOPO_PGROUP_PROTOCOL,
550074bb90dSTom Pothier 		    TOPO_PROP_LABEL, &label, &err) == -1)
551074bb90dSTom Pothier 			topo_mod_dprintf(mod, "Failed to get"
552074bb90dSTom Pothier 			    " Label of Parent Node error : %d\n", err);
553074bb90dSTom Pothier 
554074bb90dSTom Pothier 		if (label != NULL)
555074bb90dSTom Pothier 			label = (char *)chip_cleanup_smbios_str(mod,
556074bb90dSTom Pothier 			    label, LABEL);
557074bb90dSTom Pothier 
558074bb90dSTom Pothier 		/*
559074bb90dSTom Pothier 		 * On Intel the driver gets the label from ksmbios
560074bb90dSTom Pothier 		 * so we check if we already have it, if not we
561074bb90dSTom Pothier 		 * get it from libsmbios
562074bb90dSTom Pothier 		 */
563074bb90dSTom Pothier 		if (ksmbios_label == NULL && smb_id != -1) {
564074bb90dSTom Pothier 			if (smbios_info_common(shp, smb_id, &c) != SMB_ERR) {
565074bb90dSTom Pothier 				for (int i = 0; i < ndimm_ids; i++) {
566074bb90dSTom Pothier 					if (smb_id == dimmsmb[i].dimm_id) {
567074bb90dSTom Pothier 						dimm_bank = dimmsmb[i].bankloc;
568074bb90dSTom Pothier 						break;
569074bb90dSTom Pothier 					}
570074bb90dSTom Pothier 				}
571074bb90dSTom Pothier 				if (dimm_bank != NULL) {
572074bb90dSTom Pothier 					bufsz += chip_strlen(blank) +
573074bb90dSTom Pothier 					    chip_strlen(dimm_bank);
574074bb90dSTom Pothier 				}
575074bb90dSTom Pothier 				lsmbios_label = c.smbi_location;
576074bb90dSTom Pothier 			}
577074bb90dSTom Pothier 		} else
578074bb90dSTom Pothier 			lsmbios_label = ksmbios_label;
579074bb90dSTom Pothier 
580074bb90dSTom Pothier 		if (label != NULL && lsmbios_label != NULL)
581074bb90dSTom Pothier 			delim = "/";
582074bb90dSTom Pothier 
583074bb90dSTom Pothier 		bufsz += chip_strlen(label) + chip_strlen(delim) +
584074bb90dSTom Pothier 		    chip_strlen(lsmbios_label) + 1;
585074bb90dSTom Pothier 
586074bb90dSTom Pothier 		buf = topo_mod_alloc(mod, bufsz);
587074bb90dSTom Pothier 
588074bb90dSTom Pothier 		if (buf != NULL) {
589074bb90dSTom Pothier 			if (label != NULL) {
590074bb90dSTom Pothier 				(void) strlcpy(buf, label, bufsz);
591074bb90dSTom Pothier 				if (lsmbios_label != NULL) {
592074bb90dSTom Pothier 					(void) strlcat(buf, delim, bufsz);
593074bb90dSTom Pothier 					/*
594074bb90dSTom Pothier 					 * If we are working on a DIMM
595074bb90dSTom Pothier 					 * and we are deriving from libsmbios
596074bb90dSTom Pothier 					 * smbi_location has the Device Locator.
597074bb90dSTom Pothier 					 * add the Device Locator
598074bb90dSTom Pothier 					 * add Bank Locator latter
599074bb90dSTom Pothier 					 */
600074bb90dSTom Pothier 					(void) strlcat(buf, lsmbios_label,
601074bb90dSTom Pothier 					    bufsz);
602074bb90dSTom Pothier 				}
603074bb90dSTom Pothier 			} else if (lsmbios_label != NULL)
604074bb90dSTom Pothier 				(void) strlcpy(buf, lsmbios_label,
605074bb90dSTom Pothier 				    bufsz);
606074bb90dSTom Pothier 
607074bb90dSTom Pothier 			if (dimm_bank != NULL) {
608074bb90dSTom Pothier 				(void) strlcat(buf, blank, bufsz);
609074bb90dSTom Pothier 				(void) strlcat(buf, dimm_bank, bufsz);
610074bb90dSTom Pothier 			}
611074bb90dSTom Pothier 		}
612074bb90dSTom Pothier 
613074bb90dSTom Pothier 		clean_label = chip_cleanup_smbios_str(mod, buf, LABEL);
614074bb90dSTom Pothier 		topo_mod_strfree(mod, label);
615074bb90dSTom Pothier 
616074bb90dSTom Pothier 		return (clean_label);
617074bb90dSTom Pothier 	}
618074bb90dSTom Pothier 
619074bb90dSTom Pothier 	topo_mod_dprintf(mod, "Failed to get Label\n");
620074bb90dSTom Pothier 	return (NULL);
621074bb90dSTom Pothier }
622074bb90dSTom Pothier 
623074bb90dSTom Pothier 
624074bb90dSTom Pothier const char *
chip_serial_smbios_get(topo_mod_t * mod,id_t smb_id)625074bb90dSTom Pothier chip_serial_smbios_get(topo_mod_t *mod, id_t smb_id)
626074bb90dSTom Pothier {
627074bb90dSTom Pothier 	smbios_info_t c;
628074bb90dSTom Pothier 	const char *clean_serial = NULL;
629efd31e1dSTrang Do 	smbios_hdl_t *shp;
630074bb90dSTom Pothier 
631efd31e1dSTrang Do 	shp = topo_mod_smbios(mod);
632074bb90dSTom Pothier 	if (shp != NULL && smb_id != -1)
633074bb90dSTom Pothier 		if (smbios_info_common(shp, smb_id, &c) != SMB_ERR) {
634074bb90dSTom Pothier 			clean_serial = chip_cleanup_smbios_str(mod,
635074bb90dSTom Pothier 			    c.smbi_serial, 0);
636074bb90dSTom Pothier 			return (clean_serial);
637074bb90dSTom Pothier 		}
638074bb90dSTom Pothier 
639074bb90dSTom Pothier 	topo_mod_dprintf(mod, "Failed to get Serial \n");
640074bb90dSTom Pothier 	return (NULL);
641074bb90dSTom Pothier }
642074bb90dSTom Pothier 
643074bb90dSTom Pothier 
644074bb90dSTom Pothier const char *
chip_part_smbios_get(topo_mod_t * mod,id_t smb_id)645074bb90dSTom Pothier chip_part_smbios_get(topo_mod_t *mod, id_t smb_id)
646074bb90dSTom Pothier {
647074bb90dSTom Pothier 	smbios_info_t c;
648074bb90dSTom Pothier 	const char *clean_part = NULL;
649efd31e1dSTrang Do 	smbios_hdl_t *shp;
650074bb90dSTom Pothier 
651efd31e1dSTrang Do 	shp = topo_mod_smbios(mod);
652074bb90dSTom Pothier 	if (shp != NULL && smb_id != -1)
653074bb90dSTom Pothier 		if (smbios_info_common(shp, smb_id, &c) != SMB_ERR) {
654074bb90dSTom Pothier 			clean_part = chip_cleanup_smbios_str(mod,
655074bb90dSTom Pothier 			    c.smbi_part, 0);
656074bb90dSTom Pothier 			return (clean_part);
657074bb90dSTom Pothier 		}
658074bb90dSTom Pothier 
659074bb90dSTom Pothier 	topo_mod_dprintf(mod, "Failed to get Part\n");
660074bb90dSTom Pothier 	return (NULL);
661074bb90dSTom Pothier }
662074bb90dSTom Pothier 
663074bb90dSTom Pothier const char *
chip_rev_smbios_get(topo_mod_t * mod,id_t smb_id)664074bb90dSTom Pothier chip_rev_smbios_get(topo_mod_t *mod, id_t smb_id)
665074bb90dSTom Pothier {
666074bb90dSTom Pothier 	smbios_info_t c;
667074bb90dSTom Pothier 	const char *clean_rev = NULL;
668efd31e1dSTrang Do 	smbios_hdl_t *shp;
669074bb90dSTom Pothier 
670efd31e1dSTrang Do 	shp = topo_mod_smbios(mod);
671074bb90dSTom Pothier 	if (shp != NULL && smb_id != -1)
672074bb90dSTom Pothier 		if (smbios_info_common(shp, smb_id, &c) != SMB_ERR) {
673074bb90dSTom Pothier 			clean_rev = chip_cleanup_smbios_str(mod,
674074bb90dSTom Pothier 			    c.smbi_version, 0);
675074bb90dSTom Pothier 			return (clean_rev);
676074bb90dSTom Pothier 		}
677074bb90dSTom Pothier 
678074bb90dSTom Pothier 	topo_mod_dprintf(mod, "Failed to get Revision\n");
679074bb90dSTom Pothier 	return (NULL);
680074bb90dSTom Pothier }
681