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 /*
23*efd31e1dSTrang Do  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24074bb90dSTom Pothier  */
25074bb90dSTom Pothier 
26074bb90dSTom Pothier /*
27074bb90dSTom Pothier  *  Subroutines used by the i86pc Generic Topology Enumerator
28074bb90dSTom Pothier  */
29074bb90dSTom Pothier 
30074bb90dSTom Pothier #include <sys/types.h>
31074bb90dSTom Pothier #include <strings.h>
32074bb90dSTom Pothier #include <deflt.h>
33074bb90dSTom Pothier #include <fcntl.h>
34074bb90dSTom Pothier #include <unistd.h>
35074bb90dSTom Pothier #include <fm/topo_mod.h>
36074bb90dSTom Pothier #include <fm/topo_hc.h>
37074bb90dSTom Pothier #include <sys/devfm.h>
3803f9f63dSTom Pothier #include <sys/pci.h>
39074bb90dSTom Pothier #include <sys/systeminfo.h>
40074bb90dSTom Pothier #include <sys/fm/protocol.h>
41074bb90dSTom Pothier #include <sys/utsname.h>
42074bb90dSTom Pothier #include <sys/smbios.h>
43074bb90dSTom Pothier #include <sys/smbios_impl.h>
44074bb90dSTom Pothier #include <x86pi_impl.h>
45074bb90dSTom Pothier 
46074bb90dSTom Pothier 
47074bb90dSTom Pothier static const topo_pgroup_info_t sys_pgroup = {
48074bb90dSTom Pothier 	TOPO_PGROUP_SYSTEM,
49074bb90dSTom Pothier 	TOPO_STABILITY_PRIVATE,
50074bb90dSTom Pothier 	TOPO_STABILITY_PRIVATE,
51074bb90dSTom Pothier 	1
52074bb90dSTom Pothier };
53074bb90dSTom Pothier 
54074bb90dSTom Pothier static const topo_pgroup_info_t auth_pgroup = {
55074bb90dSTom Pothier 	FM_FMRI_AUTHORITY,
56074bb90dSTom Pothier 	TOPO_STABILITY_PRIVATE,
57074bb90dSTom Pothier 	TOPO_STABILITY_PRIVATE,
58074bb90dSTom Pothier 	1
59074bb90dSTom Pothier };
60074bb90dSTom Pothier 
61074bb90dSTom Pothier 
62074bb90dSTom Pothier /*
63074bb90dSTom Pothier  * Free hcfmri strings.
64074bb90dSTom Pothier  */
65074bb90dSTom Pothier void
x86pi_hcfmri_info_fini(topo_mod_t * mod,x86pi_hcfmri_t * hc)66074bb90dSTom Pothier x86pi_hcfmri_info_fini(topo_mod_t *mod, x86pi_hcfmri_t *hc)
67074bb90dSTom Pothier {
68074bb90dSTom Pothier 	if (hc->hc_name != NULL)
69074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->hc_name);
70074bb90dSTom Pothier 	if (hc->manufacturer != NULL)
71074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->manufacturer);
72074bb90dSTom Pothier 	if (hc->product != NULL)
73074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->product);
74074bb90dSTom Pothier 	if (hc->version != NULL)
75074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->version);
76074bb90dSTom Pothier 	if (hc->serial_number != NULL)
77074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->serial_number);
78074bb90dSTom Pothier 	if (hc->asset_tag != NULL)
79074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->asset_tag);
80074bb90dSTom Pothier 	if (hc->location != NULL)
81074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->location);
82074bb90dSTom Pothier 	if (hc->part_number != NULL)
83074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->part_number);
84074bb90dSTom Pothier }
85074bb90dSTom Pothier 
86074bb90dSTom Pothier 
87074bb90dSTom Pothier /*
88074bb90dSTom Pothier  * Get the server hostname (the ID as far as the topo authority is
89074bb90dSTom Pothier  * concerned) from sysinfo and return a copy to the caller.
90074bb90dSTom Pothier  *
91074bb90dSTom Pothier  * The string must be freed with topo_mod_strfree()
92074bb90dSTom Pothier  */
93074bb90dSTom Pothier char *
x86pi_get_serverid(topo_mod_t * mod)94074bb90dSTom Pothier x86pi_get_serverid(topo_mod_t *mod)
95074bb90dSTom Pothier {
96074bb90dSTom Pothier 	int result;
97074bb90dSTom Pothier 	char hostname[MAXNAMELEN];
98074bb90dSTom Pothier 
99074bb90dSTom Pothier 	topo_mod_dprintf(mod, "x86pi_get_serverid\n");
100074bb90dSTom Pothier 
101074bb90dSTom Pothier 	result = sysinfo(SI_HOSTNAME, hostname, sizeof (hostname));
102074bb90dSTom Pothier 	/* Everything is freed up and it's time to return the platform-id */
103074bb90dSTom Pothier 	if (result == -1) {
104074bb90dSTom Pothier 		return (NULL);
105074bb90dSTom Pothier 	}
106074bb90dSTom Pothier 	topo_mod_dprintf(mod, "x86pi_get_serverid: hostname = %s\n", hostname);
107074bb90dSTom Pothier 
108074bb90dSTom Pothier 	return (topo_mod_strdup(mod, hostname));
109074bb90dSTom Pothier }
110074bb90dSTom Pothier 
111074bb90dSTom Pothier 
112074bb90dSTom Pothier /*
113074bb90dSTom Pothier  * Get copy of SMBIOS.
114074bb90dSTom Pothier  */
115074bb90dSTom Pothier smbios_hdl_t *
x86pi_smb_open(topo_mod_t * mod)116074bb90dSTom Pothier x86pi_smb_open(topo_mod_t *mod)
117074bb90dSTom Pothier {
118074bb90dSTom Pothier 	smbios_hdl_t *smb_hdl;
119074bb90dSTom Pothier 	char *f = "x86pi_smb_open";
120074bb90dSTom Pothier 
121074bb90dSTom Pothier 	topo_mod_dprintf(mod, "%s\n", f);
122074bb90dSTom Pothier 
123074bb90dSTom Pothier 	smb_hdl = topo_mod_smbios(mod);
124074bb90dSTom Pothier 	if (smb_hdl == NULL) {
125074bb90dSTom Pothier 		topo_mod_dprintf(mod, "%s: failed to load SMBIOS\n", f);
126074bb90dSTom Pothier 		return (NULL);
127074bb90dSTom Pothier 	}
128074bb90dSTom Pothier 
129074bb90dSTom Pothier 	return (smb_hdl);
130074bb90dSTom Pothier }
131074bb90dSTom Pothier 
132074bb90dSTom Pothier 
133074bb90dSTom Pothier /*
134074bb90dSTom Pothier  * Go through the smbios structures looking for a type. Fill in
135074bb90dSTom Pothier  * the structure count as well as the id(s) of the struct types.
136074bb90dSTom Pothier  */
137074bb90dSTom Pothier void
x86pi_smb_strcnt(topo_mod_t * mod,smbs_cnt_t * stype)138*efd31e1dSTrang Do x86pi_smb_strcnt(topo_mod_t *mod, smbs_cnt_t *stype)
139074bb90dSTom Pothier {
140*efd31e1dSTrang Do 	const smb_struct_t *sp;
141*efd31e1dSTrang Do 	int nstructs;
142074bb90dSTom Pothier 	int i, cnt;
143*efd31e1dSTrang Do 	smbios_hdl_t *shp;
144*efd31e1dSTrang Do 
145*efd31e1dSTrang Do 	shp = topo_mod_smbios(mod);
146*efd31e1dSTrang Do 	if (shp == NULL) {
147*efd31e1dSTrang Do 		stype->count = 0;
148*efd31e1dSTrang Do 		return;
149*efd31e1dSTrang Do 	}
150*efd31e1dSTrang Do 
151*efd31e1dSTrang Do 	nstructs = shp->sh_nstructs;
152*efd31e1dSTrang Do 	sp = shp->sh_structs;
153074bb90dSTom Pothier 
154074bb90dSTom Pothier 	for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
155074bb90dSTom Pothier 		if (sp->smbst_hdr->smbh_type == stype->type) {
156074bb90dSTom Pothier 			stype->ids[cnt].node = NULL;
157074bb90dSTom Pothier 			stype->ids[cnt].id = sp->smbst_hdr->smbh_hdl;
158074bb90dSTom Pothier 			cnt++;
159074bb90dSTom Pothier 		}
160074bb90dSTom Pothier 	}
161074bb90dSTom Pothier 
162074bb90dSTom Pothier 	stype->count = cnt;
163074bb90dSTom Pothier }
164074bb90dSTom Pothier 
165074bb90dSTom Pothier 
166074bb90dSTom Pothier /*
167074bb90dSTom Pothier  * Calculate the authority information for a node.  Inherit the data if
168074bb90dSTom Pothier  * possible, but always create an appropriate property group.
169074bb90dSTom Pothier  */
170074bb90dSTom Pothier int
x86pi_set_auth(topo_mod_t * mod,x86pi_hcfmri_t * hcfmri,tnode_t * t_parent,tnode_t * t_node)171074bb90dSTom Pothier x86pi_set_auth(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent,
172074bb90dSTom Pothier     tnode_t *t_node)
173074bb90dSTom Pothier {
174074bb90dSTom Pothier 	int 		result;
175074bb90dSTom Pothier 	int		err;
176074bb90dSTom Pothier 	int		is_chassis = 0;
177074bb90dSTom Pothier 	int		chassis_instance = 0;
178074bb90dSTom Pothier 	nvlist_t	*auth;
179074bb90dSTom Pothier 	char		*val = NULL;
180074bb90dSTom Pothier 	char		*prod = NULL;
181074bb90dSTom Pothier 	char		*psn = NULL;
182074bb90dSTom Pothier 	char		*csn = NULL;
183074bb90dSTom Pothier 	char		*server = NULL;
184074bb90dSTom Pothier 	char		*f = "x86pi_set_auth";
185074bb90dSTom Pothier 
186074bb90dSTom Pothier 	if (mod == NULL || t_parent == NULL || t_node == NULL) {
187074bb90dSTom Pothier 		return (-1);
188074bb90dSTom Pothier 	}
189074bb90dSTom Pothier 
190074bb90dSTom Pothier 	result = topo_pgroup_create(t_node, &auth_pgroup, &err);
191074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
192074bb90dSTom Pothier 		/*
193074bb90dSTom Pothier 		 * We failed to create the property group and it was not
194074bb90dSTom Pothier 		 * already defined.  Set the err code and return failure.
195074bb90dSTom Pothier 		 */
196d3c57c1fSTom Pothier 		(void) topo_mod_seterrno(mod, err);
197074bb90dSTom Pothier 		return (-1);
198074bb90dSTom Pothier 	}
199074bb90dSTom Pothier 
200074bb90dSTom Pothier 	/* Get the authority information already available from the parent */
201074bb90dSTom Pothier 	auth = topo_mod_auth(mod, t_parent);
202074bb90dSTom Pothier 
203074bb90dSTom Pothier 	/* Determnine if this is a chassis node and set it's instance */
204074bb90dSTom Pothier 	if ((strlen(hcfmri->hc_name) == strlen(CHASSIS)) &&
205074bb90dSTom Pothier 	    strncmp(hcfmri->hc_name, CHASSIS, strlen(CHASSIS)) == 0) {
206074bb90dSTom Pothier 		is_chassis = 1;
207074bb90dSTom Pothier 		chassis_instance = hcfmri->instance;
208074bb90dSTom Pothier 	}
209074bb90dSTom Pothier 
210074bb90dSTom Pothier 	/*
211074bb90dSTom Pothier 	 * Set the authority data, inheriting it if possible, but creating it
212074bb90dSTom Pothier 	 * if necessary.
213074bb90dSTom Pothier 	 */
214074bb90dSTom Pothier 
215074bb90dSTom Pothier 	/* product-id */
216074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
217074bb90dSTom Pothier 	    FM_FMRI_AUTH_PRODUCT, &err);
218074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
219074bb90dSTom Pothier 		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT,
220074bb90dSTom Pothier 		    &prod);
221074bb90dSTom Pothier 		if (result != 0 || prod == NULL) {
222074bb90dSTom Pothier 			/*
223074bb90dSTom Pothier 			 * No product information in the parent node or auth
224074bb90dSTom Pothier 			 * list. Use the product information in the hcfrmi
225074bb90dSTom Pothier 			 * struct.
226074bb90dSTom Pothier 			 */
227074bb90dSTom Pothier 			prod = (char *)hcfmri->product;
228074bb90dSTom Pothier 			if (prod == NULL) {
229074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: product name not "
230074bb90dSTom Pothier 				    "found for %s node\n", f, hcfmri->hc_name);
231074bb90dSTom Pothier 			}
232074bb90dSTom Pothier 		}
233074bb90dSTom Pothier 
234074bb90dSTom Pothier 		/*
235074bb90dSTom Pothier 		 * We continue even if the product information is not available
236074bb90dSTom Pothier 		 * to enumerate as much as possible.
237074bb90dSTom Pothier 		 */
238074bb90dSTom Pothier 		if (prod != NULL) {
239074bb90dSTom Pothier 			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
240074bb90dSTom Pothier 			    FM_FMRI_AUTH_PRODUCT, TOPO_PROP_IMMUTABLE, prod,
241074bb90dSTom Pothier 			    &err);
242074bb90dSTom Pothier 			if (result != 0) {
243074bb90dSTom Pothier 				/* Preserve the error and continue */
244d3c57c1fSTom Pothier 				(void) topo_mod_seterrno(mod, err);
245074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: failed to set "
246074bb90dSTom Pothier 				    "property %s (%d) : %s\n", f,
247074bb90dSTom Pothier 				    FM_FMRI_AUTH_PRODUCT, err,
248074bb90dSTom Pothier 				    topo_strerror(err));
249074bb90dSTom Pothier 			}
250074bb90dSTom Pothier 		}
251074bb90dSTom Pothier 	}
252074bb90dSTom Pothier 
253074bb90dSTom Pothier 	/* product-sn */
254074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
255074bb90dSTom Pothier 	    FM_FMRI_AUTH_PRODUCT_SN, &err);
256074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
257074bb90dSTom Pothier 		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN,
258074bb90dSTom Pothier 		    &psn);
259074bb90dSTom Pothier 		if (result != 0 || psn == NULL) {
260074bb90dSTom Pothier 			/*
261074bb90dSTom Pothier 			 * No product-sn information in the parent node or auth
262074bb90dSTom Pothier 			 * list.
263074bb90dSTom Pothier 			 */
264074bb90dSTom Pothier 			topo_mod_dprintf(mod, "%s: psn not found\n", f);
265074bb90dSTom Pothier 		} else {
266074bb90dSTom Pothier 			/*
267074bb90dSTom Pothier 			 * We continue even if the product-sn information is
268074bb90dSTom Pothier 			 * not available to enumerate as much as possible.
269074bb90dSTom Pothier 			 */
270074bb90dSTom Pothier 			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
271074bb90dSTom Pothier 			    FM_FMRI_AUTH_PRODUCT_SN, TOPO_PROP_IMMUTABLE, psn,
272074bb90dSTom Pothier 			    &err);
273074bb90dSTom Pothier 			if (result != 0) {
274074bb90dSTom Pothier 				/* Preserve the error and continue */
275d3c57c1fSTom Pothier 				(void) topo_mod_seterrno(mod, err);
276074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: failed to "
277074bb90dSTom Pothier 				    "set property %s (%d) : %s\n", f,
278074bb90dSTom Pothier 				    FM_FMRI_AUTH_PRODUCT_SN, err,
279074bb90dSTom Pothier 				    topo_strerror(err));
280074bb90dSTom Pothier 			}
281074bb90dSTom Pothier 		}
282074bb90dSTom Pothier 	}
283074bb90dSTom Pothier 
284074bb90dSTom Pothier 	/* chassis-id */
285074bb90dSTom Pothier 	if (is_chassis == 0 || (is_chassis == 1 && chassis_instance == 0)) {
286074bb90dSTom Pothier 		/* either not a chassis node, or chassis #0 */
287074bb90dSTom Pothier 		result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
288074bb90dSTom Pothier 		    FM_FMRI_AUTH_CHASSIS, &err);
289074bb90dSTom Pothier 	} else {
290074bb90dSTom Pothier 		/* chassis 'n' in a >1 chassis system */
291074bb90dSTom Pothier 		result = err = -1;
292074bb90dSTom Pothier 	}
293074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
294074bb90dSTom Pothier 		if (is_chassis == 0) {
295074bb90dSTom Pothier 			result = nvlist_lookup_string(auth,
296074bb90dSTom Pothier 			    FM_FMRI_AUTH_CHASSIS, &csn);
297074bb90dSTom Pothier 			if (result != 0 || csn == NULL) {
298074bb90dSTom Pothier 				/*
299074bb90dSTom Pothier 				 * No chassis information in the parent
300074bb90dSTom Pothier 				 * node or auth list.
301074bb90dSTom Pothier 				 */
302074bb90dSTom Pothier 				topo_mod_dprintf(mod,
303074bb90dSTom Pothier 				    "%s: csn name not found\n", f);
304074bb90dSTom Pothier 			}
305074bb90dSTom Pothier 		} else {
306074bb90dSTom Pothier 			/*
307074bb90dSTom Pothier 			 * So as not to blindly set the chassis-id to
308074bb90dSTom Pothier 			 * chassis #0's serial number.
309074bb90dSTom Pothier 			 */
310074bb90dSTom Pothier 			csn = val = topo_mod_strdup(mod, hcfmri->serial_number);
311074bb90dSTom Pothier 		}
312074bb90dSTom Pothier 
313074bb90dSTom Pothier 		/*
314074bb90dSTom Pothier 		 * We continue even if the chassis information is not available
315074bb90dSTom Pothier 		 * to enumerate as much as possible.
316074bb90dSTom Pothier 		 */
317074bb90dSTom Pothier 		if (csn != NULL) {
318074bb90dSTom Pothier 			if (is_chassis == 1)
319074bb90dSTom Pothier 				result = topo_prop_set_string(t_node,
320074bb90dSTom Pothier 				    FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
321074bb90dSTom Pothier 				    TOPO_PROP_MUTABLE, csn, &err);
322074bb90dSTom Pothier 			else
323074bb90dSTom Pothier 				result = topo_prop_set_string(t_node,
324074bb90dSTom Pothier 				    FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
325074bb90dSTom Pothier 				    TOPO_PROP_IMMUTABLE, csn, &err);
326074bb90dSTom Pothier 
327074bb90dSTom Pothier 			if (result != 0) {
328074bb90dSTom Pothier 				/* Preserve the error and continue */
329d3c57c1fSTom Pothier 				(void) topo_mod_seterrno(mod, err);
330074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: failed to "
331074bb90dSTom Pothier 				    "set property %s (%d) : %s\n", f,
332074bb90dSTom Pothier 				    FM_FMRI_AUTH_CHASSIS, err,
333074bb90dSTom Pothier 				    topo_strerror(err));
334074bb90dSTom Pothier 			}
335074bb90dSTom Pothier 		}
336074bb90dSTom Pothier 
337074bb90dSTom Pothier 		if (val != NULL) {
338074bb90dSTom Pothier 			topo_mod_strfree(mod, val);
339074bb90dSTom Pothier 			val = NULL;
340074bb90dSTom Pothier 		}
341074bb90dSTom Pothier 	}
342074bb90dSTom Pothier 
343074bb90dSTom Pothier 	/* server-id */
344074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
345074bb90dSTom Pothier 	    FM_FMRI_AUTH_SERVER, &err);
346074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
347074bb90dSTom Pothier 		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER,
348074bb90dSTom Pothier 		    &server);
349074bb90dSTom Pothier 		if (result != 0 || server == NULL) {
350074bb90dSTom Pothier 			/*
351074bb90dSTom Pothier 			 * No server information in the parent node or auth
352074bb90dSTom Pothier 			 * list.  Find the server information in hostname.
353074bb90dSTom Pothier 			 */
354074bb90dSTom Pothier 			server = val = x86pi_get_serverid(mod);
355074bb90dSTom Pothier 			if (server == NULL) {
356074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: server "
357074bb90dSTom Pothier 				    "name not found for %s node\n", f,
358074bb90dSTom Pothier 				    hcfmri->hc_name);
359074bb90dSTom Pothier 			}
360074bb90dSTom Pothier 		}
361074bb90dSTom Pothier 
362074bb90dSTom Pothier 		/*
363074bb90dSTom Pothier 		 * We continue even if the server information is not available
364074bb90dSTom Pothier 		 * to enumerate as much as possible.
365074bb90dSTom Pothier 		 */
366074bb90dSTom Pothier 		if (server != NULL) {
367074bb90dSTom Pothier 			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
368074bb90dSTom Pothier 			    FM_FMRI_AUTH_SERVER, TOPO_PROP_IMMUTABLE, server,
369074bb90dSTom Pothier 			    &err);
370074bb90dSTom Pothier 			if (result != 0) {
371074bb90dSTom Pothier 				/* Preserve the error and continue */
372d3c57c1fSTom Pothier 				(void) topo_mod_seterrno(mod, err);
373074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: failed to "
374074bb90dSTom Pothier 				    "set property %s (%d) : %s\n", f,
375074bb90dSTom Pothier 				    FM_FMRI_AUTH_SERVER, err,
376074bb90dSTom Pothier 				    topo_strerror(err));
377074bb90dSTom Pothier 			}
378074bb90dSTom Pothier 		}
379074bb90dSTom Pothier 
380074bb90dSTom Pothier 		if (val != NULL)
381074bb90dSTom Pothier 			topo_mod_strfree(mod, val);
382074bb90dSTom Pothier 	}
383074bb90dSTom Pothier 
384074bb90dSTom Pothier 	nvlist_free(auth);
385074bb90dSTom Pothier 
386074bb90dSTom Pothier 	return (0);
387074bb90dSTom Pothier }
388074bb90dSTom Pothier 
389074bb90dSTom Pothier 
390074bb90dSTom Pothier /*
391074bb90dSTom Pothier  * Calculate a generic FRU for the given node.  If the node is not a FRU,
392074bb90dSTom Pothier  * then inherit the FRU data from the nodes parent.
393074bb90dSTom Pothier  */
394074bb90dSTom Pothier int
x86pi_set_frufmri(topo_mod_t * mod,x86pi_hcfmri_t * hcfmri,tnode_t * t_parent,tnode_t * t_node,int flag)395074bb90dSTom Pothier x86pi_set_frufmri(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent,
396074bb90dSTom Pothier     tnode_t *t_node, int flag)
397074bb90dSTom Pothier {
398074bb90dSTom Pothier 	int		result;
399074bb90dSTom Pothier 	int		err;
400074bb90dSTom Pothier 
401074bb90dSTom Pothier 	nvlist_t	*auth = NULL;
402074bb90dSTom Pothier 	nvlist_t	*frufmri = NULL;
403074bb90dSTom Pothier 
404074bb90dSTom Pothier 	if (t_node == NULL || mod == NULL) {
405074bb90dSTom Pothier 		return (-1);
406074bb90dSTom Pothier 	}
407074bb90dSTom Pothier 
408074bb90dSTom Pothier 	/*
409074bb90dSTom Pothier 	 * Determine if this node is a FRU
410074bb90dSTom Pothier 	 */
411074bb90dSTom Pothier 	if (!(flag & X86PI_ENUM_FRU)) {
412074bb90dSTom Pothier 		/* This node is not a FRU.  Inherit from parent and return */
413d3c57c1fSTom Pothier 		(void) topo_node_fru_set(t_node, NULL, 0, &result);
414074bb90dSTom Pothier 		return (0);
415074bb90dSTom Pothier 	}
416074bb90dSTom Pothier 
417074bb90dSTom Pothier 	/*
418074bb90dSTom Pothier 	 * This node is a FRU.  Create an FMRI.
419074bb90dSTom Pothier 	 */
420074bb90dSTom Pothier 	auth	= topo_mod_auth(mod, t_parent);
421074bb90dSTom Pothier 	frufmri	= topo_mod_hcfmri(mod, t_parent, FM_HC_SCHEME_VERSION,
422074bb90dSTom Pothier 	    hcfmri->hc_name, hcfmri->instance, NULL, auth,
423074bb90dSTom Pothier 	    hcfmri->part_number, hcfmri->version, hcfmri->serial_number);
424074bb90dSTom Pothier 	if (frufmri == NULL) {
425074bb90dSTom Pothier 		topo_mod_dprintf(mod, "failed to create FRU: %s\n",
426074bb90dSTom Pothier 		    topo_strerror(topo_mod_errno(mod)));
427074bb90dSTom Pothier 	}
428074bb90dSTom Pothier 	nvlist_free(auth);
429074bb90dSTom Pothier 
430074bb90dSTom Pothier 	/* Set the FRU, whether NULL or not */
431074bb90dSTom Pothier 	result = topo_node_fru_set(t_node, frufmri, 0, &err);
432074bb90dSTom Pothier 	if (result != 0)  {
433d3c57c1fSTom Pothier 		(void) topo_mod_seterrno(mod, err);
434074bb90dSTom Pothier 	}
435074bb90dSTom Pothier 	nvlist_free(frufmri);
436074bb90dSTom Pothier 
437074bb90dSTom Pothier 	return (result);
438074bb90dSTom Pothier }
439074bb90dSTom Pothier 
440074bb90dSTom Pothier 
441074bb90dSTom Pothier /*
442074bb90dSTom Pothier  * Set the label for a topo node.
443074bb90dSTom Pothier  */
444074bb90dSTom Pothier int
x86pi_set_label(topo_mod_t * mod,const char * label,const char * name,tnode_t * t_node)445074bb90dSTom Pothier x86pi_set_label(topo_mod_t *mod, const char *label, const char *name,
446074bb90dSTom Pothier     tnode_t *t_node)
447074bb90dSTom Pothier {
448074bb90dSTom Pothier 	int	result;
449074bb90dSTom Pothier 	int	err;
450074bb90dSTom Pothier 
451074bb90dSTom Pothier 	if (mod == NULL) {
452074bb90dSTom Pothier 		return (-1);
453074bb90dSTom Pothier 	}
454074bb90dSTom Pothier 
455074bb90dSTom Pothier 	/*
456074bb90dSTom Pothier 	 * Set the label for this topology node.
457074bb90dSTom Pothier 	 * Note that a NULL label will inherit the label from topology
458074bb90dSTom Pothier 	 * node's parent.
459074bb90dSTom Pothier 	 */
460074bb90dSTom Pothier 	result = topo_node_label_set(t_node, (char *)label, &err);
461074bb90dSTom Pothier 	if (result != 0) {
462d3c57c1fSTom Pothier 		(void) topo_mod_seterrno(mod, err);
463074bb90dSTom Pothier 		topo_mod_dprintf(mod, "x86pi_set_label: failed with label %s "
464074bb90dSTom Pothier 		    "on %s node: %s\n", (label == NULL ? "NULL" : label),
465074bb90dSTom Pothier 		    name, topo_strerror(err));
466074bb90dSTom Pothier 	}
467074bb90dSTom Pothier 
468074bb90dSTom Pothier 	return (result);
469074bb90dSTom Pothier }
470074bb90dSTom Pothier 
471074bb90dSTom Pothier 
472074bb90dSTom Pothier /*
473074bb90dSTom Pothier  * Calculate the system information for a node.  Inherit the data if
474074bb90dSTom Pothier  * possible, but always create an appropriate property group.
475074bb90dSTom Pothier  */
476074bb90dSTom Pothier int
x86pi_set_system(topo_mod_t * mod,tnode_t * t_node)477074bb90dSTom Pothier x86pi_set_system(topo_mod_t *mod, tnode_t *t_node)
478074bb90dSTom Pothier {
479074bb90dSTom Pothier 	int		result;
480074bb90dSTom Pothier 	int		err;
481074bb90dSTom Pothier 	struct utsname	uts;
482074bb90dSTom Pothier 	char		isa[MAXNAMELEN];
483074bb90dSTom Pothier 
484074bb90dSTom Pothier 	if (mod == NULL || t_node == NULL) {
485074bb90dSTom Pothier 		return (-1);
486074bb90dSTom Pothier 	}
487074bb90dSTom Pothier 
488074bb90dSTom Pothier 	result = topo_pgroup_create(t_node, &sys_pgroup, &err);
489074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
490074bb90dSTom Pothier 		/*
491074bb90dSTom Pothier 		 * We failed to create the property group and it was not
492074bb90dSTom Pothier 		 * already defined.  Set the err code and return failure.
493074bb90dSTom Pothier 		 */
494d3c57c1fSTom Pothier 		(void) topo_mod_seterrno(mod, err);
495074bb90dSTom Pothier 		return (-1);
496074bb90dSTom Pothier 	}
497074bb90dSTom Pothier 
498074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA,
499074bb90dSTom Pothier 	    &err);
500074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
501074bb90dSTom Pothier 		isa[0] = '\0';
502074bb90dSTom Pothier 		result = sysinfo(SI_ARCHITECTURE, isa, sizeof (isa));
503074bb90dSTom Pothier 		if (result == -1) {
504074bb90dSTom Pothier 			/* Preserve the error and continue */
505074bb90dSTom Pothier 			topo_mod_dprintf(mod, "x86pi_set_system: failed to "
506074bb90dSTom Pothier 			    "read SI_ARCHITECTURE: %d\n", errno);
507074bb90dSTom Pothier 		}
508074bb90dSTom Pothier 		if (strnlen(isa, MAXNAMELEN) > 0) {
509074bb90dSTom Pothier 			result = topo_prop_set_string(t_node,
510074bb90dSTom Pothier 			    TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA,
511074bb90dSTom Pothier 			    TOPO_PROP_IMMUTABLE, isa, &err);
512074bb90dSTom Pothier 			if (result != 0) {
513074bb90dSTom Pothier 				/* Preserve the error and continue */
514d3c57c1fSTom Pothier 				(void) topo_mod_seterrno(mod, err);
515074bb90dSTom Pothier 				topo_mod_dprintf(mod,
516074bb90dSTom Pothier 				    "x86pi_set_auth: failed to "
517074bb90dSTom Pothier 				    "set property %s (%d) : %s\n",
518074bb90dSTom Pothier 				    TOPO_PROP_ISA, err, topo_strerror(err));
519074bb90dSTom Pothier 			}
520074bb90dSTom Pothier 		}
521074bb90dSTom Pothier 	}
522074bb90dSTom Pothier 
523074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, TOPO_PGROUP_SYSTEM,
524074bb90dSTom Pothier 	    TOPO_PROP_MACHINE, &err);
525074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
526074bb90dSTom Pothier 		result = uname(&uts);
527074bb90dSTom Pothier 		if (result == -1) {
528074bb90dSTom Pothier 			/* Preserve the error and continue */
529d3c57c1fSTom Pothier 			(void) topo_mod_seterrno(mod, errno);
530074bb90dSTom Pothier 			topo_mod_dprintf(mod, "x86pi_set_system: failed to "
531074bb90dSTom Pothier 			    "read uname: %d\n", errno);
532074bb90dSTom Pothier 		}
533074bb90dSTom Pothier 		if (strnlen(uts.machine, sizeof (uts.machine)) > 0) {
534074bb90dSTom Pothier 			result = topo_prop_set_string(t_node,
535074bb90dSTom Pothier 			    TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE,
536074bb90dSTom Pothier 			    TOPO_PROP_IMMUTABLE, uts.machine, &err);
537074bb90dSTom Pothier 			if (result != 0) {
538074bb90dSTom Pothier 				/* Preserve the error and continue */
539d3c57c1fSTom Pothier 				(void) topo_mod_seterrno(mod, err);
540074bb90dSTom Pothier 				topo_mod_dprintf(mod,
541074bb90dSTom Pothier 				    "x86pi_set_auth: failed to "
542074bb90dSTom Pothier 				    "set property %s (%d) : %s\n",
543074bb90dSTom Pothier 				    TOPO_PROP_MACHINE, err, topo_strerror(err));
544074bb90dSTom Pothier 			}
545074bb90dSTom Pothier 		}
546074bb90dSTom Pothier 	}
547074bb90dSTom Pothier 
548074bb90dSTom Pothier 	return (0);
549074bb90dSTom Pothier }
550074bb90dSTom Pothier 
551074bb90dSTom Pothier /*
552074bb90dSTom Pothier  * All the checks for compatibility are done within the kernel where the
553074bb90dSTom Pothier  * ereport generators are. They'll determine first if there's a problem
554074bb90dSTom Pothier  * and the topo enum will follow suit. The /dev/fm ioclt returns the value
555074bb90dSTom Pothier  * of the x86gentopo_legacy kernel variable which determines if this platform
556074bb90dSTom Pothier  * will provide an x86 generic topo or legacy topo enumeration.
557074bb90dSTom Pothier  */
558074bb90dSTom Pothier /* ARGSUSED */
559074bb90dSTom Pothier int
x86pi_check_comp(topo_mod_t * mod)560*efd31e1dSTrang Do x86pi_check_comp(topo_mod_t *mod)
561074bb90dSTom Pothier {
562074bb90dSTom Pothier 	int rv;
563074bb90dSTom Pothier 	int fd;
564074bb90dSTom Pothier 	int32_t legacy;
565074bb90dSTom Pothier 	nvlist_t *nvl = NULL;
566074bb90dSTom Pothier 	fm_ioc_data_t fid;
567074bb90dSTom Pothier 	char *ibuf = NULL, *obuf = NULL;
568074bb90dSTom Pothier 	size_t insz = 0, outsz = 0;
569074bb90dSTom Pothier 	char *f = "x86pi_check_comp";
570*efd31e1dSTrang Do 	smbios_hdl_t *shp;
571*efd31e1dSTrang Do 
572*efd31e1dSTrang Do 	shp = topo_mod_smbios(mod);
573*efd31e1dSTrang Do 	if (shp == NULL)
574*efd31e1dSTrang Do 		return (X86PI_NONE);
575074bb90dSTom Pothier 
576074bb90dSTom Pothier 	/* open /dev/fm */
577074bb90dSTom Pothier 	fd = open("/dev/fm", O_RDONLY);
578074bb90dSTom Pothier 	if (fd < 0) {
579074bb90dSTom Pothier 		topo_mod_dprintf(mod, "%s: failed to open /dev/fm.\n", f);
580074bb90dSTom Pothier 		return (X86PI_NONE);
581074bb90dSTom Pothier 	}
582074bb90dSTom Pothier 
583074bb90dSTom Pothier 	/* set up buffers and ioctl data structure */
584074bb90dSTom Pothier 	outsz = FM_IOC_MAXBUFSZ;
585074bb90dSTom Pothier 	obuf = topo_mod_alloc(mod, outsz);
586074bb90dSTom Pothier 	if (obuf == NULL) {
587074bb90dSTom Pothier 		perror("umem_alloc");
588074bb90dSTom Pothier 		return (X86PI_NONE);
589074bb90dSTom Pothier 	}
590074bb90dSTom Pothier 
591074bb90dSTom Pothier 	fid.fid_version = 1;
592074bb90dSTom Pothier 	fid.fid_insz = insz;
593074bb90dSTom Pothier 	fid.fid_inbuf = ibuf;
594074bb90dSTom Pothier 	fid.fid_outsz = outsz;
595074bb90dSTom Pothier 	fid.fid_outbuf = obuf;
596074bb90dSTom Pothier 
597074bb90dSTom Pothier 	/* send the ioctl to /dev/fm to retrieve legacy variable */
598074bb90dSTom Pothier 	rv = ioctl(fd, FM_IOC_GENTOPO_LEGACY, &fid);
599074bb90dSTom Pothier 	if (rv < 0) {
600074bb90dSTom Pothier 		topo_mod_dprintf(mod, "%s: ioctl to /dev/fm failed", f);
601074bb90dSTom Pothier 		perror("fm_ioctl");
602074bb90dSTom Pothier 		(void) close(fd);
603074bb90dSTom Pothier 		return (X86PI_NONE);
604074bb90dSTom Pothier 	}
605074bb90dSTom Pothier 	(void) close(fd);
606074bb90dSTom Pothier 
607074bb90dSTom Pothier 	(void) nvlist_unpack(fid.fid_outbuf, fid.fid_outsz, &nvl, 0);
608074bb90dSTom Pothier 	(void) nvlist_lookup_int32(nvl, FM_GENTOPO_LEGACY, &legacy);
609074bb90dSTom Pothier 
610074bb90dSTom Pothier 	nvlist_free(nvl);
611074bb90dSTom Pothier 	topo_mod_free(mod, obuf, outsz);
612074bb90dSTom Pothier 
613074bb90dSTom Pothier 	if (legacy == 1) {
614074bb90dSTom Pothier 		/* legacy kernel variable set; will do the same */
615074bb90dSTom Pothier 		return (X86PI_NONE);
616074bb90dSTom Pothier 	}
617074bb90dSTom Pothier 
618074bb90dSTom Pothier 	/* legacy kernel variable not set; generic topo enum */
619074bb90dSTom Pothier 	return (X86PI_FULL);
620074bb90dSTom Pothier }
621074bb90dSTom Pothier 
622074bb90dSTom Pothier const char *
x86pi_cleanup_smbios_str(topo_mod_t * mod,const char * begin,int str_type)623074bb90dSTom Pothier x86pi_cleanup_smbios_str(topo_mod_t *mod, const char *begin, int str_type)
624074bb90dSTom Pothier {
625074bb90dSTom Pothier 	char buf[MAXNAMELEN];
626074bb90dSTom Pothier 	const char *end, *cp;
627074bb90dSTom Pothier 	char *pp;
628074bb90dSTom Pothier 	char c;
629074bb90dSTom Pothier 	int i;
630074bb90dSTom Pothier 
631074bb90dSTom Pothier 	end = begin + strlen(begin);
632074bb90dSTom Pothier 
633074bb90dSTom Pothier 	while (begin < end && isspace(*begin))
634074bb90dSTom Pothier 		begin++;
635074bb90dSTom Pothier 	while (begin < end && isspace(*(end - 1)))
636074bb90dSTom Pothier 		end--;
637074bb90dSTom Pothier 
638074bb90dSTom Pothier 	if (begin >= end)
639074bb90dSTom Pothier 		return (NULL);
640074bb90dSTom Pothier 
641074bb90dSTom Pothier 	cp = begin;
642074bb90dSTom Pothier 	for (i = 0; i < MAXNAMELEN - 1; i++) {
643074bb90dSTom Pothier 		if (cp >= end)
644074bb90dSTom Pothier 			break;
645074bb90dSTom Pothier 		c = *cp;
646074bb90dSTom Pothier 		if (str_type == LABEL) {
647074bb90dSTom Pothier 			if (!isprint(c))
648074bb90dSTom Pothier 				buf[i] = '-';
649074bb90dSTom Pothier 			else
650074bb90dSTom Pothier 				buf[i] = c;
651074bb90dSTom Pothier 		} else {
652074bb90dSTom Pothier 			if (c == ':' || c == '=' || c == '/' ||
653074bb90dSTom Pothier 			    isspace(c) || !isprint(c))
654074bb90dSTom Pothier 				buf[i] = '-';
655074bb90dSTom Pothier 			else
656074bb90dSTom Pothier 				buf[i] = c;
657074bb90dSTom Pothier 		}
658074bb90dSTom Pothier 		cp++;
659074bb90dSTom Pothier 	}
660074bb90dSTom Pothier 	buf[i] = 0;
661074bb90dSTom Pothier 
662074bb90dSTom Pothier 	pp = topo_mod_strdup(mod, buf);
663074bb90dSTom Pothier 
664074bb90dSTom Pothier 	if (str_type == LABEL)
665074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)begin);
666074bb90dSTom Pothier 
667074bb90dSTom Pothier 	return (pp);
668074bb90dSTom Pothier }
66903f9f63dSTom Pothier 
67003f9f63dSTom Pothier /*
67103f9f63dSTom Pothier  * Return Bus/Dev/Func from "reg" devinfo property.
67203f9f63dSTom Pothier  */
67303f9f63dSTom Pothier uint16_t
x86pi_bdf(topo_mod_t * mod,di_node_t node)67403f9f63dSTom Pothier x86pi_bdf(topo_mod_t *mod, di_node_t node)
67503f9f63dSTom Pothier {
67603f9f63dSTom Pothier 	int *val;
67703f9f63dSTom Pothier 
67803f9f63dSTom Pothier 	if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &val) < 0) {
67903f9f63dSTom Pothier 		topo_mod_dprintf(mod, "couldn't get \"reg\" prop: %s.\n",
68003f9f63dSTom Pothier 		    strerror(errno));
68103f9f63dSTom Pothier 		return ((uint16_t)-1);
68203f9f63dSTom Pothier 	}
68303f9f63dSTom Pothier 
68403f9f63dSTom Pothier 	return (uint16_t)((*val & PCI_REG_BDFR_M) >> PCI_REG_FUNC_SHIFT);
68503f9f63dSTom Pothier }
68603f9f63dSTom Pothier 
68703f9f63dSTom Pothier /*
68803f9f63dSTom Pothier  * Return PHY from "sata-phy" devinfo proporty.
68903f9f63dSTom Pothier  */
69003f9f63dSTom Pothier int
x86pi_phy(topo_mod_t * mod,di_node_t node)69103f9f63dSTom Pothier x86pi_phy(topo_mod_t *mod, di_node_t node)
69203f9f63dSTom Pothier {
69303f9f63dSTom Pothier 	int *phy;
69403f9f63dSTom Pothier 
69503f9f63dSTom Pothier 	if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "sata-phy", &phy) < 0) {
69603f9f63dSTom Pothier 		topo_mod_dprintf(mod, "couldn't get \"sata-phy\" prop: %s.\n",
69703f9f63dSTom Pothier 		    strerror(errno));
69803f9f63dSTom Pothier 		return (-1);
69903f9f63dSTom Pothier 	}
70003f9f63dSTom Pothier 
70103f9f63dSTom Pothier 	return (*phy);
70203f9f63dSTom Pothier }
703