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 /*
23074bb90dSTom Pothier  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24074bb90dSTom Pothier  * Use is subject to license terms.
25074bb90dSTom Pothier  */
26074bb90dSTom Pothier 
27074bb90dSTom Pothier /*
28074bb90dSTom Pothier  *  Subroutines used by the i86pc Generic Topology Enumerator
29074bb90dSTom Pothier  */
30074bb90dSTom Pothier 
31074bb90dSTom Pothier #include <sys/types.h>
32074bb90dSTom Pothier #include <strings.h>
33074bb90dSTom Pothier #include <deflt.h>
34074bb90dSTom Pothier #include <fcntl.h>
35074bb90dSTom Pothier #include <unistd.h>
36074bb90dSTom Pothier #include <fm/topo_mod.h>
37074bb90dSTom Pothier #include <fm/topo_hc.h>
38074bb90dSTom Pothier #include <sys/devfm.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
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 *
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 *
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
138074bb90dSTom Pothier x86pi_smb_strcnt(smbios_hdl_t *shp, smbs_cnt_t *stype)
139074bb90dSTom Pothier {
140074bb90dSTom Pothier 	const smb_struct_t *sp = shp->sh_structs;
141074bb90dSTom Pothier 	int nstructs = shp->sh_nstructs;
142074bb90dSTom Pothier 	int i, cnt;
143074bb90dSTom Pothier 
144074bb90dSTom Pothier 	for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
145074bb90dSTom Pothier 		if (sp->smbst_hdr->smbh_type == stype->type) {
146074bb90dSTom Pothier 			stype->ids[cnt].node = NULL;
147074bb90dSTom Pothier 			stype->ids[cnt].id = sp->smbst_hdr->smbh_hdl;
148074bb90dSTom Pothier 			cnt++;
149074bb90dSTom Pothier 		}
150074bb90dSTom Pothier 	}
151074bb90dSTom Pothier 
152074bb90dSTom Pothier 	stype->count = cnt;
153074bb90dSTom Pothier }
154074bb90dSTom Pothier 
155074bb90dSTom Pothier 
156074bb90dSTom Pothier /*
157074bb90dSTom Pothier  * Calculate the authority information for a node.  Inherit the data if
158074bb90dSTom Pothier  * possible, but always create an appropriate property group.
159074bb90dSTom Pothier  */
160074bb90dSTom Pothier int
161074bb90dSTom Pothier x86pi_set_auth(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent,
162074bb90dSTom Pothier     tnode_t *t_node)
163074bb90dSTom Pothier {
164074bb90dSTom Pothier 	int 		result;
165074bb90dSTom Pothier 	int		err;
166074bb90dSTom Pothier 	int		is_chassis = 0;
167074bb90dSTom Pothier 	int		chassis_instance = 0;
168074bb90dSTom Pothier 	nvlist_t	*auth;
169074bb90dSTom Pothier 	char		*val = NULL;
170074bb90dSTom Pothier 	char		*prod = NULL;
171074bb90dSTom Pothier 	char		*psn = NULL;
172074bb90dSTom Pothier 	char		*csn = NULL;
173074bb90dSTom Pothier 	char		*server = NULL;
174074bb90dSTom Pothier 	char		*f = "x86pi_set_auth";
175074bb90dSTom Pothier 
176074bb90dSTom Pothier 	if (mod == NULL || t_parent == NULL || t_node == NULL) {
177074bb90dSTom Pothier 		return (-1);
178074bb90dSTom Pothier 	}
179074bb90dSTom Pothier 
180074bb90dSTom Pothier 	result = topo_pgroup_create(t_node, &auth_pgroup, &err);
181074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
182074bb90dSTom Pothier 		/*
183074bb90dSTom Pothier 		 * We failed to create the property group and it was not
184074bb90dSTom Pothier 		 * already defined.  Set the err code and return failure.
185074bb90dSTom Pothier 		 */
186*d3c57c1fSTom Pothier 		(void) topo_mod_seterrno(mod, err);
187074bb90dSTom Pothier 		return (-1);
188074bb90dSTom Pothier 	}
189074bb90dSTom Pothier 
190074bb90dSTom Pothier 	/* Get the authority information already available from the parent */
191074bb90dSTom Pothier 	auth = topo_mod_auth(mod, t_parent);
192074bb90dSTom Pothier 
193074bb90dSTom Pothier 	/* Determnine if this is a chassis node and set it's instance */
194074bb90dSTom Pothier 	if ((strlen(hcfmri->hc_name) == strlen(CHASSIS)) &&
195074bb90dSTom Pothier 	    strncmp(hcfmri->hc_name, CHASSIS, strlen(CHASSIS)) == 0) {
196074bb90dSTom Pothier 		is_chassis = 1;
197074bb90dSTom Pothier 		chassis_instance = hcfmri->instance;
198074bb90dSTom Pothier 	}
199074bb90dSTom Pothier 
200074bb90dSTom Pothier 	/*
201074bb90dSTom Pothier 	 * Set the authority data, inheriting it if possible, but creating it
202074bb90dSTom Pothier 	 * if necessary.
203074bb90dSTom Pothier 	 */
204074bb90dSTom Pothier 
205074bb90dSTom Pothier 	/* product-id */
206074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
207074bb90dSTom Pothier 	    FM_FMRI_AUTH_PRODUCT, &err);
208074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
209074bb90dSTom Pothier 		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT,
210074bb90dSTom Pothier 		    &prod);
211074bb90dSTom Pothier 		if (result != 0 || prod == NULL) {
212074bb90dSTom Pothier 			/*
213074bb90dSTom Pothier 			 * No product information in the parent node or auth
214074bb90dSTom Pothier 			 * list. Use the product information in the hcfrmi
215074bb90dSTom Pothier 			 * struct.
216074bb90dSTom Pothier 			 */
217074bb90dSTom Pothier 			prod = (char *)hcfmri->product;
218074bb90dSTom Pothier 			if (prod == NULL) {
219074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: product name not "
220074bb90dSTom Pothier 				    "found for %s node\n", f, hcfmri->hc_name);
221074bb90dSTom Pothier 			}
222074bb90dSTom Pothier 		}
223074bb90dSTom Pothier 
224074bb90dSTom Pothier 		/*
225074bb90dSTom Pothier 		 * We continue even if the product information is not available
226074bb90dSTom Pothier 		 * to enumerate as much as possible.
227074bb90dSTom Pothier 		 */
228074bb90dSTom Pothier 		if (prod != NULL) {
229074bb90dSTom Pothier 			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
230074bb90dSTom Pothier 			    FM_FMRI_AUTH_PRODUCT, TOPO_PROP_IMMUTABLE, prod,
231074bb90dSTom Pothier 			    &err);
232074bb90dSTom Pothier 			if (result != 0) {
233074bb90dSTom Pothier 				/* Preserve the error and continue */
234*d3c57c1fSTom Pothier 				(void) topo_mod_seterrno(mod, err);
235074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: failed to set "
236074bb90dSTom Pothier 				    "property %s (%d) : %s\n", f,
237074bb90dSTom Pothier 				    FM_FMRI_AUTH_PRODUCT, err,
238074bb90dSTom Pothier 				    topo_strerror(err));
239074bb90dSTom Pothier 			}
240074bb90dSTom Pothier 		}
241074bb90dSTom Pothier 	}
242074bb90dSTom Pothier 
243074bb90dSTom Pothier 	/* product-sn */
244074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
245074bb90dSTom Pothier 	    FM_FMRI_AUTH_PRODUCT_SN, &err);
246074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
247074bb90dSTom Pothier 		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN,
248074bb90dSTom Pothier 		    &psn);
249074bb90dSTom Pothier 		if (result != 0 || psn == NULL) {
250074bb90dSTom Pothier 			/*
251074bb90dSTom Pothier 			 * No product-sn information in the parent node or auth
252074bb90dSTom Pothier 			 * list.
253074bb90dSTom Pothier 			 */
254074bb90dSTom Pothier 			topo_mod_dprintf(mod, "%s: psn not found\n", f);
255074bb90dSTom Pothier 		} else {
256074bb90dSTom Pothier 			/*
257074bb90dSTom Pothier 			 * We continue even if the product-sn information is
258074bb90dSTom Pothier 			 * not available to enumerate as much as possible.
259074bb90dSTom Pothier 			 */
260074bb90dSTom Pothier 			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
261074bb90dSTom Pothier 			    FM_FMRI_AUTH_PRODUCT_SN, TOPO_PROP_IMMUTABLE, psn,
262074bb90dSTom Pothier 			    &err);
263074bb90dSTom Pothier 			if (result != 0) {
264074bb90dSTom Pothier 				/* Preserve the error and continue */
265*d3c57c1fSTom Pothier 				(void) topo_mod_seterrno(mod, err);
266074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: failed to "
267074bb90dSTom Pothier 				    "set property %s (%d) : %s\n", f,
268074bb90dSTom Pothier 				    FM_FMRI_AUTH_PRODUCT_SN, err,
269074bb90dSTom Pothier 				    topo_strerror(err));
270074bb90dSTom Pothier 			}
271074bb90dSTom Pothier 		}
272074bb90dSTom Pothier 	}
273074bb90dSTom Pothier 
274074bb90dSTom Pothier 	/* chassis-id */
275074bb90dSTom Pothier 	if (is_chassis == 0 || (is_chassis == 1 && chassis_instance == 0)) {
276074bb90dSTom Pothier 		/* either not a chassis node, or chassis #0 */
277074bb90dSTom Pothier 		result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
278074bb90dSTom Pothier 		    FM_FMRI_AUTH_CHASSIS, &err);
279074bb90dSTom Pothier 	} else {
280074bb90dSTom Pothier 		/* chassis 'n' in a >1 chassis system */
281074bb90dSTom Pothier 		result = err = -1;
282074bb90dSTom Pothier 	}
283074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
284074bb90dSTom Pothier 		if (is_chassis == 0) {
285074bb90dSTom Pothier 			result = nvlist_lookup_string(auth,
286074bb90dSTom Pothier 			    FM_FMRI_AUTH_CHASSIS, &csn);
287074bb90dSTom Pothier 			if (result != 0 || csn == NULL) {
288074bb90dSTom Pothier 				/*
289074bb90dSTom Pothier 				 * No chassis information in the parent
290074bb90dSTom Pothier 				 * node or auth list.
291074bb90dSTom Pothier 				 */
292074bb90dSTom Pothier 				topo_mod_dprintf(mod,
293074bb90dSTom Pothier 				    "%s: csn name not found\n", f);
294074bb90dSTom Pothier 			}
295074bb90dSTom Pothier 		} else {
296074bb90dSTom Pothier 			/*
297074bb90dSTom Pothier 			 * So as not to blindly set the chassis-id to
298074bb90dSTom Pothier 			 * chassis #0's serial number.
299074bb90dSTom Pothier 			 */
300074bb90dSTom Pothier 			csn = val = topo_mod_strdup(mod, hcfmri->serial_number);
301074bb90dSTom Pothier 		}
302074bb90dSTom Pothier 
303074bb90dSTom Pothier 		/*
304074bb90dSTom Pothier 		 * We continue even if the chassis information is not available
305074bb90dSTom Pothier 		 * to enumerate as much as possible.
306074bb90dSTom Pothier 		 */
307074bb90dSTom Pothier 		if (csn != NULL) {
308074bb90dSTom Pothier 			if (is_chassis == 1)
309074bb90dSTom Pothier 				result = topo_prop_set_string(t_node,
310074bb90dSTom Pothier 				    FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
311074bb90dSTom Pothier 				    TOPO_PROP_MUTABLE, csn, &err);
312074bb90dSTom Pothier 			else
313074bb90dSTom Pothier 				result = topo_prop_set_string(t_node,
314074bb90dSTom Pothier 				    FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
315074bb90dSTom Pothier 				    TOPO_PROP_IMMUTABLE, csn, &err);
316074bb90dSTom Pothier 
317074bb90dSTom Pothier 			if (result != 0) {
318074bb90dSTom Pothier 				/* Preserve the error and continue */
319*d3c57c1fSTom Pothier 				(void) topo_mod_seterrno(mod, err);
320074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: failed to "
321074bb90dSTom Pothier 				    "set property %s (%d) : %s\n", f,
322074bb90dSTom Pothier 				    FM_FMRI_AUTH_CHASSIS, err,
323074bb90dSTom Pothier 				    topo_strerror(err));
324074bb90dSTom Pothier 			}
325074bb90dSTom Pothier 		}
326074bb90dSTom Pothier 
327074bb90dSTom Pothier 		if (val != NULL) {
328074bb90dSTom Pothier 			topo_mod_strfree(mod, val);
329074bb90dSTom Pothier 			val = NULL;
330074bb90dSTom Pothier 		}
331074bb90dSTom Pothier 	}
332074bb90dSTom Pothier 
333074bb90dSTom Pothier 	/* server-id */
334074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
335074bb90dSTom Pothier 	    FM_FMRI_AUTH_SERVER, &err);
336074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
337074bb90dSTom Pothier 		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER,
338074bb90dSTom Pothier 		    &server);
339074bb90dSTom Pothier 		if (result != 0 || server == NULL) {
340074bb90dSTom Pothier 			/*
341074bb90dSTom Pothier 			 * No server information in the parent node or auth
342074bb90dSTom Pothier 			 * list.  Find the server information in hostname.
343074bb90dSTom Pothier 			 */
344074bb90dSTom Pothier 			server = val = x86pi_get_serverid(mod);
345074bb90dSTom Pothier 			if (server == NULL) {
346074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: server "
347074bb90dSTom Pothier 				    "name not found for %s node\n", f,
348074bb90dSTom Pothier 				    hcfmri->hc_name);
349074bb90dSTom Pothier 			}
350074bb90dSTom Pothier 		}
351074bb90dSTom Pothier 
352074bb90dSTom Pothier 		/*
353074bb90dSTom Pothier 		 * We continue even if the server information is not available
354074bb90dSTom Pothier 		 * to enumerate as much as possible.
355074bb90dSTom Pothier 		 */
356074bb90dSTom Pothier 		if (server != NULL) {
357074bb90dSTom Pothier 			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
358074bb90dSTom Pothier 			    FM_FMRI_AUTH_SERVER, TOPO_PROP_IMMUTABLE, server,
359074bb90dSTom Pothier 			    &err);
360074bb90dSTom Pothier 			if (result != 0) {
361074bb90dSTom Pothier 				/* Preserve the error and continue */
362*d3c57c1fSTom Pothier 				(void) topo_mod_seterrno(mod, err);
363074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: failed to "
364074bb90dSTom Pothier 				    "set property %s (%d) : %s\n", f,
365074bb90dSTom Pothier 				    FM_FMRI_AUTH_SERVER, err,
366074bb90dSTom Pothier 				    topo_strerror(err));
367074bb90dSTom Pothier 			}
368074bb90dSTom Pothier 		}
369074bb90dSTom Pothier 
370074bb90dSTom Pothier 		if (val != NULL)
371074bb90dSTom Pothier 			topo_mod_strfree(mod, val);
372074bb90dSTom Pothier 	}
373074bb90dSTom Pothier 
374074bb90dSTom Pothier 	nvlist_free(auth);
375074bb90dSTom Pothier 
376074bb90dSTom Pothier 	return (0);
377074bb90dSTom Pothier }
378074bb90dSTom Pothier 
379074bb90dSTom Pothier 
380074bb90dSTom Pothier /*
381074bb90dSTom Pothier  * Calculate a generic FRU for the given node.  If the node is not a FRU,
382074bb90dSTom Pothier  * then inherit the FRU data from the nodes parent.
383074bb90dSTom Pothier  */
384074bb90dSTom Pothier int
385074bb90dSTom Pothier x86pi_set_frufmri(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent,
386074bb90dSTom Pothier     tnode_t *t_node, int flag)
387074bb90dSTom Pothier {
388074bb90dSTom Pothier 	int		result;
389074bb90dSTom Pothier 	int		err;
390074bb90dSTom Pothier 
391074bb90dSTom Pothier 	nvlist_t	*auth = NULL;
392074bb90dSTom Pothier 	nvlist_t	*frufmri = NULL;
393074bb90dSTom Pothier 
394074bb90dSTom Pothier 	if (t_node == NULL || mod == NULL) {
395074bb90dSTom Pothier 		return (-1);
396074bb90dSTom Pothier 	}
397074bb90dSTom Pothier 
398074bb90dSTom Pothier 	/*
399074bb90dSTom Pothier 	 * Determine if this node is a FRU
400074bb90dSTom Pothier 	 */
401074bb90dSTom Pothier 	if (!(flag & X86PI_ENUM_FRU)) {
402074bb90dSTom Pothier 		/* This node is not a FRU.  Inherit from parent and return */
403*d3c57c1fSTom Pothier 		(void) topo_node_fru_set(t_node, NULL, 0, &result);
404074bb90dSTom Pothier 		return (0);
405074bb90dSTom Pothier 	}
406074bb90dSTom Pothier 
407074bb90dSTom Pothier 	/*
408074bb90dSTom Pothier 	 * This node is a FRU.  Create an FMRI.
409074bb90dSTom Pothier 	 */
410074bb90dSTom Pothier 	auth	= topo_mod_auth(mod, t_parent);
411074bb90dSTom Pothier 	frufmri	= topo_mod_hcfmri(mod, t_parent, FM_HC_SCHEME_VERSION,
412074bb90dSTom Pothier 	    hcfmri->hc_name, hcfmri->instance, NULL, auth,
413074bb90dSTom Pothier 	    hcfmri->part_number, hcfmri->version, hcfmri->serial_number);
414074bb90dSTom Pothier 	if (frufmri == NULL) {
415074bb90dSTom Pothier 		topo_mod_dprintf(mod, "failed to create FRU: %s\n",
416074bb90dSTom Pothier 		    topo_strerror(topo_mod_errno(mod)));
417074bb90dSTom Pothier 	}
418074bb90dSTom Pothier 	nvlist_free(auth);
419074bb90dSTom Pothier 
420074bb90dSTom Pothier 	/* Set the FRU, whether NULL or not */
421074bb90dSTom Pothier 	result = topo_node_fru_set(t_node, frufmri, 0, &err);
422074bb90dSTom Pothier 	if (result != 0)  {
423*d3c57c1fSTom Pothier 		(void) topo_mod_seterrno(mod, err);
424074bb90dSTom Pothier 	}
425074bb90dSTom Pothier 	nvlist_free(frufmri);
426074bb90dSTom Pothier 
427074bb90dSTom Pothier 	return (result);
428074bb90dSTom Pothier }
429074bb90dSTom Pothier 
430074bb90dSTom Pothier 
431074bb90dSTom Pothier /*
432074bb90dSTom Pothier  * Set the label for a topo node.
433074bb90dSTom Pothier  */
434074bb90dSTom Pothier int
435074bb90dSTom Pothier x86pi_set_label(topo_mod_t *mod, const char *label, const char *name,
436074bb90dSTom Pothier     tnode_t *t_node)
437074bb90dSTom Pothier {
438074bb90dSTom Pothier 	int	result;
439074bb90dSTom Pothier 	int	err;
440074bb90dSTom Pothier 
441074bb90dSTom Pothier 	if (mod == NULL) {
442074bb90dSTom Pothier 		return (-1);
443074bb90dSTom Pothier 	}
444074bb90dSTom Pothier 
445074bb90dSTom Pothier 	/*
446074bb90dSTom Pothier 	 * Set the label for this topology node.
447074bb90dSTom Pothier 	 * Note that a NULL label will inherit the label from topology
448074bb90dSTom Pothier 	 * node's parent.
449074bb90dSTom Pothier 	 */
450074bb90dSTom Pothier 	result = topo_node_label_set(t_node, (char *)label, &err);
451074bb90dSTom Pothier 	if (result != 0) {
452*d3c57c1fSTom Pothier 		(void) topo_mod_seterrno(mod, err);
453074bb90dSTom Pothier 		topo_mod_dprintf(mod, "x86pi_set_label: failed with label %s "
454074bb90dSTom Pothier 		    "on %s node: %s\n", (label == NULL ? "NULL" : label),
455074bb90dSTom Pothier 		    name, topo_strerror(err));
456074bb90dSTom Pothier 	}
457074bb90dSTom Pothier 
458074bb90dSTom Pothier 	return (result);
459074bb90dSTom Pothier }
460074bb90dSTom Pothier 
461074bb90dSTom Pothier 
462074bb90dSTom Pothier /*
463074bb90dSTom Pothier  * Calculate the system information for a node.  Inherit the data if
464074bb90dSTom Pothier  * possible, but always create an appropriate property group.
465074bb90dSTom Pothier  */
466074bb90dSTom Pothier int
467074bb90dSTom Pothier x86pi_set_system(topo_mod_t *mod, tnode_t *t_node)
468074bb90dSTom Pothier {
469074bb90dSTom Pothier 	int		result;
470074bb90dSTom Pothier 	int		err;
471074bb90dSTom Pothier 	struct utsname	uts;
472074bb90dSTom Pothier 	char		isa[MAXNAMELEN];
473074bb90dSTom Pothier 
474074bb90dSTom Pothier 	if (mod == NULL || t_node == NULL) {
475074bb90dSTom Pothier 		return (-1);
476074bb90dSTom Pothier 	}
477074bb90dSTom Pothier 
478074bb90dSTom Pothier 	result = topo_pgroup_create(t_node, &sys_pgroup, &err);
479074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
480074bb90dSTom Pothier 		/*
481074bb90dSTom Pothier 		 * We failed to create the property group and it was not
482074bb90dSTom Pothier 		 * already defined.  Set the err code and return failure.
483074bb90dSTom Pothier 		 */
484*d3c57c1fSTom Pothier 		(void) topo_mod_seterrno(mod, err);
485074bb90dSTom Pothier 		return (-1);
486074bb90dSTom Pothier 	}
487074bb90dSTom Pothier 
488074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA,
489074bb90dSTom Pothier 	    &err);
490074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
491074bb90dSTom Pothier 		isa[0] = '\0';
492074bb90dSTom Pothier 		result = sysinfo(SI_ARCHITECTURE, isa, sizeof (isa));
493074bb90dSTom Pothier 		if (result == -1) {
494074bb90dSTom Pothier 			/* Preserve the error and continue */
495074bb90dSTom Pothier 			topo_mod_dprintf(mod, "x86pi_set_system: failed to "
496074bb90dSTom Pothier 			    "read SI_ARCHITECTURE: %d\n", errno);
497074bb90dSTom Pothier 		}
498074bb90dSTom Pothier 		if (strnlen(isa, MAXNAMELEN) > 0) {
499074bb90dSTom Pothier 			result = topo_prop_set_string(t_node,
500074bb90dSTom Pothier 			    TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA,
501074bb90dSTom Pothier 			    TOPO_PROP_IMMUTABLE, isa, &err);
502074bb90dSTom Pothier 			if (result != 0) {
503074bb90dSTom Pothier 				/* Preserve the error and continue */
504*d3c57c1fSTom Pothier 				(void) topo_mod_seterrno(mod, err);
505074bb90dSTom Pothier 				topo_mod_dprintf(mod,
506074bb90dSTom Pothier 				    "x86pi_set_auth: failed to "
507074bb90dSTom Pothier 				    "set property %s (%d) : %s\n",
508074bb90dSTom Pothier 				    TOPO_PROP_ISA, err, topo_strerror(err));
509074bb90dSTom Pothier 			}
510074bb90dSTom Pothier 		}
511074bb90dSTom Pothier 	}
512074bb90dSTom Pothier 
513074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, TOPO_PGROUP_SYSTEM,
514074bb90dSTom Pothier 	    TOPO_PROP_MACHINE, &err);
515074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
516074bb90dSTom Pothier 		result = uname(&uts);
517074bb90dSTom Pothier 		if (result == -1) {
518074bb90dSTom Pothier 			/* Preserve the error and continue */
519*d3c57c1fSTom Pothier 			(void) topo_mod_seterrno(mod, errno);
520074bb90dSTom Pothier 			topo_mod_dprintf(mod, "x86pi_set_system: failed to "
521074bb90dSTom Pothier 			    "read uname: %d\n", errno);
522074bb90dSTom Pothier 		}
523074bb90dSTom Pothier 		if (strnlen(uts.machine, sizeof (uts.machine)) > 0) {
524074bb90dSTom Pothier 			result = topo_prop_set_string(t_node,
525074bb90dSTom Pothier 			    TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE,
526074bb90dSTom Pothier 			    TOPO_PROP_IMMUTABLE, uts.machine, &err);
527074bb90dSTom Pothier 			if (result != 0) {
528074bb90dSTom Pothier 				/* Preserve the error and continue */
529*d3c57c1fSTom Pothier 				(void) topo_mod_seterrno(mod, err);
530074bb90dSTom Pothier 				topo_mod_dprintf(mod,
531074bb90dSTom Pothier 				    "x86pi_set_auth: failed to "
532074bb90dSTom Pothier 				    "set property %s (%d) : %s\n",
533074bb90dSTom Pothier 				    TOPO_PROP_MACHINE, err, topo_strerror(err));
534074bb90dSTom Pothier 			}
535074bb90dSTom Pothier 		}
536074bb90dSTom Pothier 	}
537074bb90dSTom Pothier 
538074bb90dSTom Pothier 	return (0);
539074bb90dSTom Pothier }
540074bb90dSTom Pothier 
541074bb90dSTom Pothier /*
542074bb90dSTom Pothier  * All the checks for compatibility are done within the kernel where the
543074bb90dSTom Pothier  * ereport generators are. They'll determine first if there's a problem
544074bb90dSTom Pothier  * and the topo enum will follow suit. The /dev/fm ioclt returns the value
545074bb90dSTom Pothier  * of the x86gentopo_legacy kernel variable which determines if this platform
546074bb90dSTom Pothier  * will provide an x86 generic topo or legacy topo enumeration.
547074bb90dSTom Pothier  */
548074bb90dSTom Pothier /* ARGSUSED */
549074bb90dSTom Pothier int
550074bb90dSTom Pothier x86pi_check_comp(topo_mod_t *mod, smbios_hdl_t *shp)
551074bb90dSTom Pothier {
552074bb90dSTom Pothier 	int rv;
553074bb90dSTom Pothier 	int fd;
554074bb90dSTom Pothier 	int32_t legacy;
555074bb90dSTom Pothier 	nvlist_t *nvl = NULL;
556074bb90dSTom Pothier 	fm_ioc_data_t fid;
557074bb90dSTom Pothier 	char *ibuf = NULL, *obuf = NULL;
558074bb90dSTom Pothier 	size_t insz = 0, outsz = 0;
559074bb90dSTom Pothier 	char *f = "x86pi_check_comp";
560074bb90dSTom Pothier 
561074bb90dSTom Pothier 	/* open /dev/fm */
562074bb90dSTom Pothier 	fd = open("/dev/fm", O_RDONLY);
563074bb90dSTom Pothier 	if (fd < 0) {
564074bb90dSTom Pothier 		topo_mod_dprintf(mod, "%s: failed to open /dev/fm.\n", f);
565074bb90dSTom Pothier 		return (X86PI_NONE);
566074bb90dSTom Pothier 	}
567074bb90dSTom Pothier 
568074bb90dSTom Pothier 	/* set up buffers and ioctl data structure */
569074bb90dSTom Pothier 	outsz = FM_IOC_MAXBUFSZ;
570074bb90dSTom Pothier 	obuf = topo_mod_alloc(mod, outsz);
571074bb90dSTom Pothier 	if (obuf == NULL) {
572074bb90dSTom Pothier 		perror("umem_alloc");
573074bb90dSTom Pothier 		return (X86PI_NONE);
574074bb90dSTom Pothier 	}
575074bb90dSTom Pothier 
576074bb90dSTom Pothier 	fid.fid_version = 1;
577074bb90dSTom Pothier 	fid.fid_insz = insz;
578074bb90dSTom Pothier 	fid.fid_inbuf = ibuf;
579074bb90dSTom Pothier 	fid.fid_outsz = outsz;
580074bb90dSTom Pothier 	fid.fid_outbuf = obuf;
581074bb90dSTom Pothier 
582074bb90dSTom Pothier 	/* send the ioctl to /dev/fm to retrieve legacy variable */
583074bb90dSTom Pothier 	rv = ioctl(fd, FM_IOC_GENTOPO_LEGACY, &fid);
584074bb90dSTom Pothier 	if (rv < 0) {
585074bb90dSTom Pothier 		topo_mod_dprintf(mod, "%s: ioctl to /dev/fm failed", f);
586074bb90dSTom Pothier 		perror("fm_ioctl");
587074bb90dSTom Pothier 		(void) close(fd);
588074bb90dSTom Pothier 		return (X86PI_NONE);
589074bb90dSTom Pothier 	}
590074bb90dSTom Pothier 	(void) close(fd);
591074bb90dSTom Pothier 
592074bb90dSTom Pothier 	(void) nvlist_unpack(fid.fid_outbuf, fid.fid_outsz, &nvl, 0);
593074bb90dSTom Pothier 	(void) nvlist_lookup_int32(nvl, FM_GENTOPO_LEGACY, &legacy);
594074bb90dSTom Pothier 
595074bb90dSTom Pothier 	nvlist_free(nvl);
596074bb90dSTom Pothier 	topo_mod_free(mod, obuf, outsz);
597074bb90dSTom Pothier 
598074bb90dSTom Pothier 	if (legacy == 1) {
599074bb90dSTom Pothier 		/* legacy kernel variable set; will do the same */
600074bb90dSTom Pothier 		return (X86PI_NONE);
601074bb90dSTom Pothier 	}
602074bb90dSTom Pothier 
603074bb90dSTom Pothier 	/* legacy kernel variable not set; generic topo enum */
604074bb90dSTom Pothier 	return (X86PI_FULL);
605074bb90dSTom Pothier }
606074bb90dSTom Pothier 
607074bb90dSTom Pothier const char *
608074bb90dSTom Pothier x86pi_cleanup_smbios_str(topo_mod_t *mod, const char *begin, int str_type)
609074bb90dSTom Pothier {
610074bb90dSTom Pothier 	char buf[MAXNAMELEN];
611074bb90dSTom Pothier 	const char *end, *cp;
612074bb90dSTom Pothier 	char *pp;
613074bb90dSTom Pothier 	char c;
614074bb90dSTom Pothier 	int i;
615074bb90dSTom Pothier 
616074bb90dSTom Pothier 	end = begin + strlen(begin);
617074bb90dSTom Pothier 
618074bb90dSTom Pothier 	while (begin < end && isspace(*begin))
619074bb90dSTom Pothier 		begin++;
620074bb90dSTom Pothier 	while (begin < end && isspace(*(end - 1)))
621074bb90dSTom Pothier 		end--;
622074bb90dSTom Pothier 
623074bb90dSTom Pothier 	if (begin >= end)
624074bb90dSTom Pothier 		return (NULL);
625074bb90dSTom Pothier 
626074bb90dSTom Pothier 	cp = begin;
627074bb90dSTom Pothier 	for (i = 0; i < MAXNAMELEN - 1; i++) {
628074bb90dSTom Pothier 		if (cp >= end)
629074bb90dSTom Pothier 			break;
630074bb90dSTom Pothier 		c = *cp;
631074bb90dSTom Pothier 		if (str_type == LABEL) {
632074bb90dSTom Pothier 			if (!isprint(c))
633074bb90dSTom Pothier 				buf[i] = '-';
634074bb90dSTom Pothier 			else
635074bb90dSTom Pothier 				buf[i] = c;
636074bb90dSTom Pothier 		} else {
637074bb90dSTom Pothier 			if (c == ':' || c == '=' || c == '/' ||
638074bb90dSTom Pothier 			    isspace(c) || !isprint(c))
639074bb90dSTom Pothier 				buf[i] = '-';
640074bb90dSTom Pothier 			else
641074bb90dSTom Pothier 				buf[i] = c;
642074bb90dSTom Pothier 		}
643074bb90dSTom Pothier 		cp++;
644074bb90dSTom Pothier 	}
645074bb90dSTom Pothier 	buf[i] = 0;
646074bb90dSTom Pothier 
647074bb90dSTom Pothier 	pp = topo_mod_strdup(mod, buf);
648074bb90dSTom Pothier 
649074bb90dSTom Pothier 	if (str_type == LABEL)
650074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)begin);
651074bb90dSTom Pothier 
652074bb90dSTom Pothier 	return (pp);
653074bb90dSTom Pothier }
654