1*074bb90dSTom Pothier /*
2*074bb90dSTom Pothier  * CDDL HEADER START
3*074bb90dSTom Pothier  *
4*074bb90dSTom Pothier  * The contents of this file are subject to the terms of the
5*074bb90dSTom Pothier  * Common Development and Distribution License (the "License").
6*074bb90dSTom Pothier  * You may not use this file except in compliance with the License.
7*074bb90dSTom Pothier  *
8*074bb90dSTom Pothier  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*074bb90dSTom Pothier  * or http://www.opensolaris.org/os/licensing.
10*074bb90dSTom Pothier  * See the License for the specific language governing permissions
11*074bb90dSTom Pothier  * and limitations under the License.
12*074bb90dSTom Pothier  *
13*074bb90dSTom Pothier  * When distributing Covered Code, include this CDDL HEADER in each
14*074bb90dSTom Pothier  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*074bb90dSTom Pothier  * If applicable, add the following below this CDDL HEADER, with the
16*074bb90dSTom Pothier  * fields enclosed by brackets "[]" replaced with your own identifying
17*074bb90dSTom Pothier  * information: Portions Copyright [yyyy] [name of copyright owner]
18*074bb90dSTom Pothier  *
19*074bb90dSTom Pothier  * CDDL HEADER END
20*074bb90dSTom Pothier  */
21*074bb90dSTom Pothier 
22*074bb90dSTom Pothier /*
23*074bb90dSTom Pothier  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*074bb90dSTom Pothier  * Use is subject to license terms.
25*074bb90dSTom Pothier  */
26*074bb90dSTom Pothier 
27*074bb90dSTom Pothier /*
28*074bb90dSTom Pothier  *  Subroutines used by the i86pc Generic Topology Enumerator
29*074bb90dSTom Pothier  */
30*074bb90dSTom Pothier 
31*074bb90dSTom Pothier #include <sys/types.h>
32*074bb90dSTom Pothier #include <strings.h>
33*074bb90dSTom Pothier #include <deflt.h>
34*074bb90dSTom Pothier #include <fcntl.h>
35*074bb90dSTom Pothier #include <unistd.h>
36*074bb90dSTom Pothier #include <fm/topo_mod.h>
37*074bb90dSTom Pothier #include <fm/topo_hc.h>
38*074bb90dSTom Pothier #include <sys/devfm.h>
39*074bb90dSTom Pothier #include <sys/systeminfo.h>
40*074bb90dSTom Pothier #include <sys/fm/protocol.h>
41*074bb90dSTom Pothier #include <sys/utsname.h>
42*074bb90dSTom Pothier #include <sys/smbios.h>
43*074bb90dSTom Pothier #include <sys/smbios_impl.h>
44*074bb90dSTom Pothier #include <x86pi_impl.h>
45*074bb90dSTom Pothier 
46*074bb90dSTom Pothier 
47*074bb90dSTom Pothier static const topo_pgroup_info_t sys_pgroup = {
48*074bb90dSTom Pothier 	TOPO_PGROUP_SYSTEM,
49*074bb90dSTom Pothier 	TOPO_STABILITY_PRIVATE,
50*074bb90dSTom Pothier 	TOPO_STABILITY_PRIVATE,
51*074bb90dSTom Pothier 	1
52*074bb90dSTom Pothier };
53*074bb90dSTom Pothier 
54*074bb90dSTom Pothier static const topo_pgroup_info_t auth_pgroup = {
55*074bb90dSTom Pothier 	FM_FMRI_AUTHORITY,
56*074bb90dSTom Pothier 	TOPO_STABILITY_PRIVATE,
57*074bb90dSTom Pothier 	TOPO_STABILITY_PRIVATE,
58*074bb90dSTom Pothier 	1
59*074bb90dSTom Pothier };
60*074bb90dSTom Pothier 
61*074bb90dSTom Pothier 
62*074bb90dSTom Pothier /*
63*074bb90dSTom Pothier  * Free hcfmri strings.
64*074bb90dSTom Pothier  */
65*074bb90dSTom Pothier void
66*074bb90dSTom Pothier x86pi_hcfmri_info_fini(topo_mod_t *mod, x86pi_hcfmri_t *hc)
67*074bb90dSTom Pothier {
68*074bb90dSTom Pothier 	if (hc->hc_name != NULL)
69*074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->hc_name);
70*074bb90dSTom Pothier 	if (hc->manufacturer != NULL)
71*074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->manufacturer);
72*074bb90dSTom Pothier 	if (hc->product != NULL)
73*074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->product);
74*074bb90dSTom Pothier 	if (hc->version != NULL)
75*074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->version);
76*074bb90dSTom Pothier 	if (hc->serial_number != NULL)
77*074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->serial_number);
78*074bb90dSTom Pothier 	if (hc->asset_tag != NULL)
79*074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->asset_tag);
80*074bb90dSTom Pothier 	if (hc->location != NULL)
81*074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->location);
82*074bb90dSTom Pothier 	if (hc->part_number != NULL)
83*074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)hc->part_number);
84*074bb90dSTom Pothier }
85*074bb90dSTom Pothier 
86*074bb90dSTom Pothier 
87*074bb90dSTom Pothier /*
88*074bb90dSTom Pothier  * Get the server hostname (the ID as far as the topo authority is
89*074bb90dSTom Pothier  * concerned) from sysinfo and return a copy to the caller.
90*074bb90dSTom Pothier  *
91*074bb90dSTom Pothier  * The string must be freed with topo_mod_strfree()
92*074bb90dSTom Pothier  */
93*074bb90dSTom Pothier char *
94*074bb90dSTom Pothier x86pi_get_serverid(topo_mod_t *mod)
95*074bb90dSTom Pothier {
96*074bb90dSTom Pothier 	int result;
97*074bb90dSTom Pothier 	char hostname[MAXNAMELEN];
98*074bb90dSTom Pothier 
99*074bb90dSTom Pothier 	topo_mod_dprintf(mod, "x86pi_get_serverid\n");
100*074bb90dSTom Pothier 
101*074bb90dSTom Pothier 	result = sysinfo(SI_HOSTNAME, hostname, sizeof (hostname));
102*074bb90dSTom Pothier 	/* Everything is freed up and it's time to return the platform-id */
103*074bb90dSTom Pothier 	if (result == -1) {
104*074bb90dSTom Pothier 		return (NULL);
105*074bb90dSTom Pothier 	}
106*074bb90dSTom Pothier 	topo_mod_dprintf(mod, "x86pi_get_serverid: hostname = %s\n", hostname);
107*074bb90dSTom Pothier 
108*074bb90dSTom Pothier 	return (topo_mod_strdup(mod, hostname));
109*074bb90dSTom Pothier }
110*074bb90dSTom Pothier 
111*074bb90dSTom Pothier 
112*074bb90dSTom Pothier /*
113*074bb90dSTom Pothier  * Get copy of SMBIOS.
114*074bb90dSTom Pothier  */
115*074bb90dSTom Pothier smbios_hdl_t *
116*074bb90dSTom Pothier x86pi_smb_open(topo_mod_t *mod)
117*074bb90dSTom Pothier {
118*074bb90dSTom Pothier 	smbios_hdl_t *smb_hdl;
119*074bb90dSTom Pothier 	char *f = "x86pi_smb_open";
120*074bb90dSTom Pothier 
121*074bb90dSTom Pothier 	topo_mod_dprintf(mod, "%s\n", f);
122*074bb90dSTom Pothier 
123*074bb90dSTom Pothier 	smb_hdl = topo_mod_smbios(mod);
124*074bb90dSTom Pothier 	if (smb_hdl == NULL) {
125*074bb90dSTom Pothier 		topo_mod_dprintf(mod, "%s: failed to load SMBIOS\n", f);
126*074bb90dSTom Pothier 		return (NULL);
127*074bb90dSTom Pothier 	}
128*074bb90dSTom Pothier 
129*074bb90dSTom Pothier 	return (smb_hdl);
130*074bb90dSTom Pothier }
131*074bb90dSTom Pothier 
132*074bb90dSTom Pothier 
133*074bb90dSTom Pothier /*
134*074bb90dSTom Pothier  * Go through the smbios structures looking for a type. Fill in
135*074bb90dSTom Pothier  * the structure count as well as the id(s) of the struct types.
136*074bb90dSTom Pothier  */
137*074bb90dSTom Pothier void
138*074bb90dSTom Pothier x86pi_smb_strcnt(smbios_hdl_t *shp, smbs_cnt_t *stype)
139*074bb90dSTom Pothier {
140*074bb90dSTom Pothier 	const smb_struct_t *sp = shp->sh_structs;
141*074bb90dSTom Pothier 	int nstructs = shp->sh_nstructs;
142*074bb90dSTom Pothier 	int i, cnt;
143*074bb90dSTom Pothier 
144*074bb90dSTom Pothier 	for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
145*074bb90dSTom Pothier 		if (sp->smbst_hdr->smbh_type == stype->type) {
146*074bb90dSTom Pothier 			stype->ids[cnt].node = NULL;
147*074bb90dSTom Pothier 			stype->ids[cnt].id = sp->smbst_hdr->smbh_hdl;
148*074bb90dSTom Pothier 			cnt++;
149*074bb90dSTom Pothier 		}
150*074bb90dSTom Pothier 	}
151*074bb90dSTom Pothier 
152*074bb90dSTom Pothier 	stype->count = cnt;
153*074bb90dSTom Pothier }
154*074bb90dSTom Pothier 
155*074bb90dSTom Pothier 
156*074bb90dSTom Pothier /*
157*074bb90dSTom Pothier  * Calculate the authority information for a node.  Inherit the data if
158*074bb90dSTom Pothier  * possible, but always create an appropriate property group.
159*074bb90dSTom Pothier  */
160*074bb90dSTom Pothier int
161*074bb90dSTom Pothier x86pi_set_auth(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent,
162*074bb90dSTom Pothier     tnode_t *t_node)
163*074bb90dSTom Pothier {
164*074bb90dSTom Pothier 	int 		result;
165*074bb90dSTom Pothier 	int		err;
166*074bb90dSTom Pothier 	int		is_chassis = 0;
167*074bb90dSTom Pothier 	int		chassis_instance = 0;
168*074bb90dSTom Pothier 	nvlist_t	*auth;
169*074bb90dSTom Pothier 	char		*val = NULL;
170*074bb90dSTom Pothier 	char		*prod = NULL;
171*074bb90dSTom Pothier 	char		*psn = NULL;
172*074bb90dSTom Pothier 	char		*csn = NULL;
173*074bb90dSTom Pothier 	char		*server = NULL;
174*074bb90dSTom Pothier 	char		*f = "x86pi_set_auth";
175*074bb90dSTom Pothier 
176*074bb90dSTom Pothier 	if (mod == NULL || t_parent == NULL || t_node == NULL) {
177*074bb90dSTom Pothier 		return (-1);
178*074bb90dSTom Pothier 	}
179*074bb90dSTom Pothier 
180*074bb90dSTom Pothier 	result = topo_pgroup_create(t_node, &auth_pgroup, &err);
181*074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
182*074bb90dSTom Pothier 		/*
183*074bb90dSTom Pothier 		 * We failed to create the property group and it was not
184*074bb90dSTom Pothier 		 * already defined.  Set the err code and return failure.
185*074bb90dSTom Pothier 		 */
186*074bb90dSTom Pothier 		topo_mod_seterrno(mod, err);
187*074bb90dSTom Pothier 		return (-1);
188*074bb90dSTom Pothier 	}
189*074bb90dSTom Pothier 
190*074bb90dSTom Pothier 	/* Get the authority information already available from the parent */
191*074bb90dSTom Pothier 	auth = topo_mod_auth(mod, t_parent);
192*074bb90dSTom Pothier 
193*074bb90dSTom Pothier 	/* Determnine if this is a chassis node and set it's instance */
194*074bb90dSTom Pothier 	if ((strlen(hcfmri->hc_name) == strlen(CHASSIS)) &&
195*074bb90dSTom Pothier 	    strncmp(hcfmri->hc_name, CHASSIS, strlen(CHASSIS)) == 0) {
196*074bb90dSTom Pothier 		is_chassis = 1;
197*074bb90dSTom Pothier 		chassis_instance = hcfmri->instance;
198*074bb90dSTom Pothier 	}
199*074bb90dSTom Pothier 
200*074bb90dSTom Pothier 	/*
201*074bb90dSTom Pothier 	 * Set the authority data, inheriting it if possible, but creating it
202*074bb90dSTom Pothier 	 * if necessary.
203*074bb90dSTom Pothier 	 */
204*074bb90dSTom Pothier 
205*074bb90dSTom Pothier 	/* product-id */
206*074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
207*074bb90dSTom Pothier 	    FM_FMRI_AUTH_PRODUCT, &err);
208*074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
209*074bb90dSTom Pothier 		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT,
210*074bb90dSTom Pothier 		    &prod);
211*074bb90dSTom Pothier 		if (result != 0 || prod == NULL) {
212*074bb90dSTom Pothier 			/*
213*074bb90dSTom Pothier 			 * No product information in the parent node or auth
214*074bb90dSTom Pothier 			 * list. Use the product information in the hcfrmi
215*074bb90dSTom Pothier 			 * struct.
216*074bb90dSTom Pothier 			 */
217*074bb90dSTom Pothier 			prod = (char *)hcfmri->product;
218*074bb90dSTom Pothier 			if (prod == NULL) {
219*074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: product name not "
220*074bb90dSTom Pothier 				    "found for %s node\n", f, hcfmri->hc_name);
221*074bb90dSTom Pothier 			}
222*074bb90dSTom Pothier 		}
223*074bb90dSTom Pothier 
224*074bb90dSTom Pothier 		/*
225*074bb90dSTom Pothier 		 * We continue even if the product information is not available
226*074bb90dSTom Pothier 		 * to enumerate as much as possible.
227*074bb90dSTom Pothier 		 */
228*074bb90dSTom Pothier 		if (prod != NULL) {
229*074bb90dSTom Pothier 			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
230*074bb90dSTom Pothier 			    FM_FMRI_AUTH_PRODUCT, TOPO_PROP_IMMUTABLE, prod,
231*074bb90dSTom Pothier 			    &err);
232*074bb90dSTom Pothier 			if (result != 0) {
233*074bb90dSTom Pothier 				/* Preserve the error and continue */
234*074bb90dSTom Pothier 				topo_mod_seterrno(mod, err);
235*074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: failed to set "
236*074bb90dSTom Pothier 				    "property %s (%d) : %s\n", f,
237*074bb90dSTom Pothier 				    FM_FMRI_AUTH_PRODUCT, err,
238*074bb90dSTom Pothier 				    topo_strerror(err));
239*074bb90dSTom Pothier 			}
240*074bb90dSTom Pothier 		}
241*074bb90dSTom Pothier 	}
242*074bb90dSTom Pothier 
243*074bb90dSTom Pothier 	/* product-sn */
244*074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
245*074bb90dSTom Pothier 	    FM_FMRI_AUTH_PRODUCT_SN, &err);
246*074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
247*074bb90dSTom Pothier 		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN,
248*074bb90dSTom Pothier 		    &psn);
249*074bb90dSTom Pothier 		if (result != 0 || psn == NULL) {
250*074bb90dSTom Pothier 			/*
251*074bb90dSTom Pothier 			 * No product-sn information in the parent node or auth
252*074bb90dSTom Pothier 			 * list.
253*074bb90dSTom Pothier 			 */
254*074bb90dSTom Pothier 			topo_mod_dprintf(mod, "%s: psn not found\n", f);
255*074bb90dSTom Pothier 		} else {
256*074bb90dSTom Pothier 			/*
257*074bb90dSTom Pothier 			 * We continue even if the product-sn information is
258*074bb90dSTom Pothier 			 * not available to enumerate as much as possible.
259*074bb90dSTom Pothier 			 */
260*074bb90dSTom Pothier 			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
261*074bb90dSTom Pothier 			    FM_FMRI_AUTH_PRODUCT_SN, TOPO_PROP_IMMUTABLE, psn,
262*074bb90dSTom Pothier 			    &err);
263*074bb90dSTom Pothier 			if (result != 0) {
264*074bb90dSTom Pothier 				/* Preserve the error and continue */
265*074bb90dSTom Pothier 				topo_mod_seterrno(mod, err);
266*074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: failed to "
267*074bb90dSTom Pothier 				    "set property %s (%d) : %s\n", f,
268*074bb90dSTom Pothier 				    FM_FMRI_AUTH_PRODUCT_SN, err,
269*074bb90dSTom Pothier 				    topo_strerror(err));
270*074bb90dSTom Pothier 			}
271*074bb90dSTom Pothier 		}
272*074bb90dSTom Pothier 	}
273*074bb90dSTom Pothier 
274*074bb90dSTom Pothier 	/* chassis-id */
275*074bb90dSTom Pothier 	if (is_chassis == 0 || (is_chassis == 1 && chassis_instance == 0)) {
276*074bb90dSTom Pothier 		/* either not a chassis node, or chassis #0 */
277*074bb90dSTom Pothier 		result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
278*074bb90dSTom Pothier 		    FM_FMRI_AUTH_CHASSIS, &err);
279*074bb90dSTom Pothier 	} else {
280*074bb90dSTom Pothier 		/* chassis 'n' in a >1 chassis system */
281*074bb90dSTom Pothier 		result = err = -1;
282*074bb90dSTom Pothier 	}
283*074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
284*074bb90dSTom Pothier 		if (is_chassis == 0) {
285*074bb90dSTom Pothier 			result = nvlist_lookup_string(auth,
286*074bb90dSTom Pothier 			    FM_FMRI_AUTH_CHASSIS, &csn);
287*074bb90dSTom Pothier 			if (result != 0 || csn == NULL) {
288*074bb90dSTom Pothier 				/*
289*074bb90dSTom Pothier 				 * No chassis information in the parent
290*074bb90dSTom Pothier 				 * node or auth list.
291*074bb90dSTom Pothier 				 */
292*074bb90dSTom Pothier 				topo_mod_dprintf(mod,
293*074bb90dSTom Pothier 				    "%s: csn name not found\n", f);
294*074bb90dSTom Pothier 			}
295*074bb90dSTom Pothier 		} else {
296*074bb90dSTom Pothier 			/*
297*074bb90dSTom Pothier 			 * So as not to blindly set the chassis-id to
298*074bb90dSTom Pothier 			 * chassis #0's serial number.
299*074bb90dSTom Pothier 			 */
300*074bb90dSTom Pothier 			csn = val = topo_mod_strdup(mod, hcfmri->serial_number);
301*074bb90dSTom Pothier 		}
302*074bb90dSTom Pothier 
303*074bb90dSTom Pothier 		/*
304*074bb90dSTom Pothier 		 * We continue even if the chassis information is not available
305*074bb90dSTom Pothier 		 * to enumerate as much as possible.
306*074bb90dSTom Pothier 		 */
307*074bb90dSTom Pothier 		if (csn != NULL) {
308*074bb90dSTom Pothier 			if (is_chassis == 1)
309*074bb90dSTom Pothier 				result = topo_prop_set_string(t_node,
310*074bb90dSTom Pothier 				    FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
311*074bb90dSTom Pothier 				    TOPO_PROP_MUTABLE, csn, &err);
312*074bb90dSTom Pothier 			else
313*074bb90dSTom Pothier 				result = topo_prop_set_string(t_node,
314*074bb90dSTom Pothier 				    FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
315*074bb90dSTom Pothier 				    TOPO_PROP_IMMUTABLE, csn, &err);
316*074bb90dSTom Pothier 
317*074bb90dSTom Pothier 			if (result != 0) {
318*074bb90dSTom Pothier 				/* Preserve the error and continue */
319*074bb90dSTom Pothier 				topo_mod_seterrno(mod, err);
320*074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: failed to "
321*074bb90dSTom Pothier 				    "set property %s (%d) : %s\n", f,
322*074bb90dSTom Pothier 				    FM_FMRI_AUTH_CHASSIS, err,
323*074bb90dSTom Pothier 				    topo_strerror(err));
324*074bb90dSTom Pothier 			}
325*074bb90dSTom Pothier 		}
326*074bb90dSTom Pothier 
327*074bb90dSTom Pothier 		if (val != NULL) {
328*074bb90dSTom Pothier 			topo_mod_strfree(mod, val);
329*074bb90dSTom Pothier 			val = NULL;
330*074bb90dSTom Pothier 		}
331*074bb90dSTom Pothier 	}
332*074bb90dSTom Pothier 
333*074bb90dSTom Pothier 	/* server-id */
334*074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
335*074bb90dSTom Pothier 	    FM_FMRI_AUTH_SERVER, &err);
336*074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
337*074bb90dSTom Pothier 		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER,
338*074bb90dSTom Pothier 		    &server);
339*074bb90dSTom Pothier 		if (result != 0 || server == NULL) {
340*074bb90dSTom Pothier 			/*
341*074bb90dSTom Pothier 			 * No server information in the parent node or auth
342*074bb90dSTom Pothier 			 * list.  Find the server information in hostname.
343*074bb90dSTom Pothier 			 */
344*074bb90dSTom Pothier 			server = val = x86pi_get_serverid(mod);
345*074bb90dSTom Pothier 			if (server == NULL) {
346*074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: server "
347*074bb90dSTom Pothier 				    "name not found for %s node\n", f,
348*074bb90dSTom Pothier 				    hcfmri->hc_name);
349*074bb90dSTom Pothier 			}
350*074bb90dSTom Pothier 		}
351*074bb90dSTom Pothier 
352*074bb90dSTom Pothier 		/*
353*074bb90dSTom Pothier 		 * We continue even if the server information is not available
354*074bb90dSTom Pothier 		 * to enumerate as much as possible.
355*074bb90dSTom Pothier 		 */
356*074bb90dSTom Pothier 		if (server != NULL) {
357*074bb90dSTom Pothier 			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
358*074bb90dSTom Pothier 			    FM_FMRI_AUTH_SERVER, TOPO_PROP_IMMUTABLE, server,
359*074bb90dSTom Pothier 			    &err);
360*074bb90dSTom Pothier 			if (result != 0) {
361*074bb90dSTom Pothier 				/* Preserve the error and continue */
362*074bb90dSTom Pothier 				topo_mod_seterrno(mod, err);
363*074bb90dSTom Pothier 				topo_mod_dprintf(mod, "%s: failed to "
364*074bb90dSTom Pothier 				    "set property %s (%d) : %s\n", f,
365*074bb90dSTom Pothier 				    FM_FMRI_AUTH_SERVER, err,
366*074bb90dSTom Pothier 				    topo_strerror(err));
367*074bb90dSTom Pothier 			}
368*074bb90dSTom Pothier 		}
369*074bb90dSTom Pothier 
370*074bb90dSTom Pothier 		if (val != NULL)
371*074bb90dSTom Pothier 			topo_mod_strfree(mod, val);
372*074bb90dSTom Pothier 	}
373*074bb90dSTom Pothier 
374*074bb90dSTom Pothier 	nvlist_free(auth);
375*074bb90dSTom Pothier 
376*074bb90dSTom Pothier 	return (0);
377*074bb90dSTom Pothier }
378*074bb90dSTom Pothier 
379*074bb90dSTom Pothier 
380*074bb90dSTom Pothier /*
381*074bb90dSTom Pothier  * Calculate a generic FRU for the given node.  If the node is not a FRU,
382*074bb90dSTom Pothier  * then inherit the FRU data from the nodes parent.
383*074bb90dSTom Pothier  */
384*074bb90dSTom Pothier int
385*074bb90dSTom Pothier x86pi_set_frufmri(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent,
386*074bb90dSTom Pothier     tnode_t *t_node, int flag)
387*074bb90dSTom Pothier {
388*074bb90dSTom Pothier 	int		result;
389*074bb90dSTom Pothier 	int		err;
390*074bb90dSTom Pothier 
391*074bb90dSTom Pothier 	nvlist_t	*auth = NULL;
392*074bb90dSTom Pothier 	nvlist_t	*frufmri = NULL;
393*074bb90dSTom Pothier 
394*074bb90dSTom Pothier 	if (t_node == NULL || mod == NULL) {
395*074bb90dSTom Pothier 		return (-1);
396*074bb90dSTom Pothier 	}
397*074bb90dSTom Pothier 
398*074bb90dSTom Pothier 	/*
399*074bb90dSTom Pothier 	 * Determine if this node is a FRU
400*074bb90dSTom Pothier 	 */
401*074bb90dSTom Pothier 	if (!(flag & X86PI_ENUM_FRU)) {
402*074bb90dSTom Pothier 		/* This node is not a FRU.  Inherit from parent and return */
403*074bb90dSTom Pothier 		topo_node_fru_set(t_node, NULL, 0, &result);
404*074bb90dSTom Pothier 		return (0);
405*074bb90dSTom Pothier 	}
406*074bb90dSTom Pothier 
407*074bb90dSTom Pothier 	/*
408*074bb90dSTom Pothier 	 * This node is a FRU.  Create an FMRI.
409*074bb90dSTom Pothier 	 */
410*074bb90dSTom Pothier 	auth	= topo_mod_auth(mod, t_parent);
411*074bb90dSTom Pothier 	frufmri	= topo_mod_hcfmri(mod, t_parent, FM_HC_SCHEME_VERSION,
412*074bb90dSTom Pothier 	    hcfmri->hc_name, hcfmri->instance, NULL, auth,
413*074bb90dSTom Pothier 	    hcfmri->part_number, hcfmri->version, hcfmri->serial_number);
414*074bb90dSTom Pothier 	if (frufmri == NULL) {
415*074bb90dSTom Pothier 		topo_mod_dprintf(mod, "failed to create FRU: %s\n",
416*074bb90dSTom Pothier 		    topo_strerror(topo_mod_errno(mod)));
417*074bb90dSTom Pothier 	}
418*074bb90dSTom Pothier 	nvlist_free(auth);
419*074bb90dSTom Pothier 
420*074bb90dSTom Pothier 	/* Set the FRU, whether NULL or not */
421*074bb90dSTom Pothier 	result = topo_node_fru_set(t_node, frufmri, 0, &err);
422*074bb90dSTom Pothier 	if (result != 0)  {
423*074bb90dSTom Pothier 		topo_mod_seterrno(mod, err);
424*074bb90dSTom Pothier 	}
425*074bb90dSTom Pothier 	nvlist_free(frufmri);
426*074bb90dSTom Pothier 
427*074bb90dSTom Pothier 	return (result);
428*074bb90dSTom Pothier }
429*074bb90dSTom Pothier 
430*074bb90dSTom Pothier 
431*074bb90dSTom Pothier /*
432*074bb90dSTom Pothier  * Set the label for a topo node.
433*074bb90dSTom Pothier  */
434*074bb90dSTom Pothier int
435*074bb90dSTom Pothier x86pi_set_label(topo_mod_t *mod, const char *label, const char *name,
436*074bb90dSTom Pothier     tnode_t *t_node)
437*074bb90dSTom Pothier {
438*074bb90dSTom Pothier 	int	result;
439*074bb90dSTom Pothier 	int	err;
440*074bb90dSTom Pothier 
441*074bb90dSTom Pothier 	if (mod == NULL) {
442*074bb90dSTom Pothier 		return (-1);
443*074bb90dSTom Pothier 	}
444*074bb90dSTom Pothier 
445*074bb90dSTom Pothier 	/*
446*074bb90dSTom Pothier 	 * Set the label for this topology node.
447*074bb90dSTom Pothier 	 * Note that a NULL label will inherit the label from topology
448*074bb90dSTom Pothier 	 * node's parent.
449*074bb90dSTom Pothier 	 */
450*074bb90dSTom Pothier 	result = topo_node_label_set(t_node, (char *)label, &err);
451*074bb90dSTom Pothier 	if (result != 0) {
452*074bb90dSTom Pothier 		topo_mod_seterrno(mod, err);
453*074bb90dSTom Pothier 		topo_mod_dprintf(mod, "x86pi_set_label: failed with label %s "
454*074bb90dSTom Pothier 		    "on %s node: %s\n", (label == NULL ? "NULL" : label),
455*074bb90dSTom Pothier 		    name, topo_strerror(err));
456*074bb90dSTom Pothier 	}
457*074bb90dSTom Pothier 
458*074bb90dSTom Pothier 	return (result);
459*074bb90dSTom Pothier }
460*074bb90dSTom Pothier 
461*074bb90dSTom Pothier 
462*074bb90dSTom Pothier /*
463*074bb90dSTom Pothier  * Calculate the system information for a node.  Inherit the data if
464*074bb90dSTom Pothier  * possible, but always create an appropriate property group.
465*074bb90dSTom Pothier  */
466*074bb90dSTom Pothier int
467*074bb90dSTom Pothier x86pi_set_system(topo_mod_t *mod, tnode_t *t_node)
468*074bb90dSTom Pothier {
469*074bb90dSTom Pothier 	int		result;
470*074bb90dSTom Pothier 	int		err;
471*074bb90dSTom Pothier 	struct utsname	uts;
472*074bb90dSTom Pothier 	char		isa[MAXNAMELEN];
473*074bb90dSTom Pothier 
474*074bb90dSTom Pothier 	if (mod == NULL || t_node == NULL) {
475*074bb90dSTom Pothier 		return (-1);
476*074bb90dSTom Pothier 	}
477*074bb90dSTom Pothier 
478*074bb90dSTom Pothier 	result = topo_pgroup_create(t_node, &sys_pgroup, &err);
479*074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
480*074bb90dSTom Pothier 		/*
481*074bb90dSTom Pothier 		 * We failed to create the property group and it was not
482*074bb90dSTom Pothier 		 * already defined.  Set the err code and return failure.
483*074bb90dSTom Pothier 		 */
484*074bb90dSTom Pothier 		topo_mod_seterrno(mod, err);
485*074bb90dSTom Pothier 		return (-1);
486*074bb90dSTom Pothier 	}
487*074bb90dSTom Pothier 
488*074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA,
489*074bb90dSTom Pothier 	    &err);
490*074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
491*074bb90dSTom Pothier 		isa[0] = '\0';
492*074bb90dSTom Pothier 		result = sysinfo(SI_ARCHITECTURE, isa, sizeof (isa));
493*074bb90dSTom Pothier 		if (result == -1) {
494*074bb90dSTom Pothier 			/* Preserve the error and continue */
495*074bb90dSTom Pothier 			topo_mod_dprintf(mod, "x86pi_set_system: failed to "
496*074bb90dSTom Pothier 			    "read SI_ARCHITECTURE: %d\n", errno);
497*074bb90dSTom Pothier 		}
498*074bb90dSTom Pothier 		if (strnlen(isa, MAXNAMELEN) > 0) {
499*074bb90dSTom Pothier 			result = topo_prop_set_string(t_node,
500*074bb90dSTom Pothier 			    TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA,
501*074bb90dSTom Pothier 			    TOPO_PROP_IMMUTABLE, isa, &err);
502*074bb90dSTom Pothier 			if (result != 0) {
503*074bb90dSTom Pothier 				/* Preserve the error and continue */
504*074bb90dSTom Pothier 				topo_mod_seterrno(mod, err);
505*074bb90dSTom Pothier 				topo_mod_dprintf(mod,
506*074bb90dSTom Pothier 				    "x86pi_set_auth: failed to "
507*074bb90dSTom Pothier 				    "set property %s (%d) : %s\n",
508*074bb90dSTom Pothier 				    TOPO_PROP_ISA, err, topo_strerror(err));
509*074bb90dSTom Pothier 			}
510*074bb90dSTom Pothier 		}
511*074bb90dSTom Pothier 	}
512*074bb90dSTom Pothier 
513*074bb90dSTom Pothier 	result = topo_prop_inherit(t_node, TOPO_PGROUP_SYSTEM,
514*074bb90dSTom Pothier 	    TOPO_PROP_MACHINE, &err);
515*074bb90dSTom Pothier 	if (result != 0 && err != ETOPO_PROP_DEFD) {
516*074bb90dSTom Pothier 		result = uname(&uts);
517*074bb90dSTom Pothier 		if (result == -1) {
518*074bb90dSTom Pothier 			/* Preserve the error and continue */
519*074bb90dSTom Pothier 			topo_mod_seterrno(mod, errno);
520*074bb90dSTom Pothier 			topo_mod_dprintf(mod, "x86pi_set_system: failed to "
521*074bb90dSTom Pothier 			    "read uname: %d\n", errno);
522*074bb90dSTom Pothier 		}
523*074bb90dSTom Pothier 		if (strnlen(uts.machine, sizeof (uts.machine)) > 0) {
524*074bb90dSTom Pothier 			result = topo_prop_set_string(t_node,
525*074bb90dSTom Pothier 			    TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE,
526*074bb90dSTom Pothier 			    TOPO_PROP_IMMUTABLE, uts.machine, &err);
527*074bb90dSTom Pothier 			if (result != 0) {
528*074bb90dSTom Pothier 				/* Preserve the error and continue */
529*074bb90dSTom Pothier 				topo_mod_seterrno(mod, err);
530*074bb90dSTom Pothier 				topo_mod_dprintf(mod,
531*074bb90dSTom Pothier 				    "x86pi_set_auth: failed to "
532*074bb90dSTom Pothier 				    "set property %s (%d) : %s\n",
533*074bb90dSTom Pothier 				    TOPO_PROP_MACHINE, err, topo_strerror(err));
534*074bb90dSTom Pothier 			}
535*074bb90dSTom Pothier 		}
536*074bb90dSTom Pothier 	}
537*074bb90dSTom Pothier 
538*074bb90dSTom Pothier 	return (0);
539*074bb90dSTom Pothier }
540*074bb90dSTom Pothier 
541*074bb90dSTom Pothier /*
542*074bb90dSTom Pothier  * All the checks for compatibility are done within the kernel where the
543*074bb90dSTom Pothier  * ereport generators are. They'll determine first if there's a problem
544*074bb90dSTom Pothier  * and the topo enum will follow suit. The /dev/fm ioclt returns the value
545*074bb90dSTom Pothier  * of the x86gentopo_legacy kernel variable which determines if this platform
546*074bb90dSTom Pothier  * will provide an x86 generic topo or legacy topo enumeration.
547*074bb90dSTom Pothier  */
548*074bb90dSTom Pothier /* ARGSUSED */
549*074bb90dSTom Pothier int
550*074bb90dSTom Pothier x86pi_check_comp(topo_mod_t *mod, smbios_hdl_t *shp)
551*074bb90dSTom Pothier {
552*074bb90dSTom Pothier 	int rv;
553*074bb90dSTom Pothier 	int fd;
554*074bb90dSTom Pothier 	int32_t legacy;
555*074bb90dSTom Pothier 	nvlist_t *nvl = NULL;
556*074bb90dSTom Pothier 	fm_ioc_data_t fid;
557*074bb90dSTom Pothier 	char *ibuf = NULL, *obuf = NULL;
558*074bb90dSTom Pothier 	size_t insz = 0, outsz = 0;
559*074bb90dSTom Pothier 	char *f = "x86pi_check_comp";
560*074bb90dSTom Pothier 
561*074bb90dSTom Pothier 	/* open /dev/fm */
562*074bb90dSTom Pothier 	fd = open("/dev/fm", O_RDONLY);
563*074bb90dSTom Pothier 	if (fd < 0) {
564*074bb90dSTom Pothier 		topo_mod_dprintf(mod, "%s: failed to open /dev/fm.\n", f);
565*074bb90dSTom Pothier 		return (X86PI_NONE);
566*074bb90dSTom Pothier 	}
567*074bb90dSTom Pothier 
568*074bb90dSTom Pothier 	/* set up buffers and ioctl data structure */
569*074bb90dSTom Pothier 	outsz = FM_IOC_MAXBUFSZ;
570*074bb90dSTom Pothier 	obuf = topo_mod_alloc(mod, outsz);
571*074bb90dSTom Pothier 	if (obuf == NULL) {
572*074bb90dSTom Pothier 		perror("umem_alloc");
573*074bb90dSTom Pothier 		return (X86PI_NONE);
574*074bb90dSTom Pothier 	}
575*074bb90dSTom Pothier 
576*074bb90dSTom Pothier 	fid.fid_version = 1;
577*074bb90dSTom Pothier 	fid.fid_insz = insz;
578*074bb90dSTom Pothier 	fid.fid_inbuf = ibuf;
579*074bb90dSTom Pothier 	fid.fid_outsz = outsz;
580*074bb90dSTom Pothier 	fid.fid_outbuf = obuf;
581*074bb90dSTom Pothier 
582*074bb90dSTom Pothier 	/* send the ioctl to /dev/fm to retrieve legacy variable */
583*074bb90dSTom Pothier 	rv = ioctl(fd, FM_IOC_GENTOPO_LEGACY, &fid);
584*074bb90dSTom Pothier 	if (rv < 0) {
585*074bb90dSTom Pothier 		topo_mod_dprintf(mod, "%s: ioctl to /dev/fm failed", f);
586*074bb90dSTom Pothier 		perror("fm_ioctl");
587*074bb90dSTom Pothier 		(void) close(fd);
588*074bb90dSTom Pothier 		return (X86PI_NONE);
589*074bb90dSTom Pothier 	}
590*074bb90dSTom Pothier 	(void) close(fd);
591*074bb90dSTom Pothier 
592*074bb90dSTom Pothier 	(void) nvlist_unpack(fid.fid_outbuf, fid.fid_outsz, &nvl, 0);
593*074bb90dSTom Pothier 	(void) nvlist_lookup_int32(nvl, FM_GENTOPO_LEGACY, &legacy);
594*074bb90dSTom Pothier 
595*074bb90dSTom Pothier 	nvlist_free(nvl);
596*074bb90dSTom Pothier 	topo_mod_free(mod, obuf, outsz);
597*074bb90dSTom Pothier 
598*074bb90dSTom Pothier 	if (legacy == 1) {
599*074bb90dSTom Pothier 		/* legacy kernel variable set; will do the same */
600*074bb90dSTom Pothier 		return (X86PI_NONE);
601*074bb90dSTom Pothier 	}
602*074bb90dSTom Pothier 
603*074bb90dSTom Pothier 	/* legacy kernel variable not set; generic topo enum */
604*074bb90dSTom Pothier 	return (X86PI_FULL);
605*074bb90dSTom Pothier }
606*074bb90dSTom Pothier 
607*074bb90dSTom Pothier const char *
608*074bb90dSTom Pothier x86pi_cleanup_smbios_str(topo_mod_t *mod, const char *begin, int str_type)
609*074bb90dSTom Pothier {
610*074bb90dSTom Pothier 	char buf[MAXNAMELEN];
611*074bb90dSTom Pothier 	const char *end, *cp;
612*074bb90dSTom Pothier 	char *pp;
613*074bb90dSTom Pothier 	char c;
614*074bb90dSTom Pothier 	int i;
615*074bb90dSTom Pothier 
616*074bb90dSTom Pothier 	end = begin + strlen(begin);
617*074bb90dSTom Pothier 
618*074bb90dSTom Pothier 	while (begin < end && isspace(*begin))
619*074bb90dSTom Pothier 		begin++;
620*074bb90dSTom Pothier 	while (begin < end && isspace(*(end - 1)))
621*074bb90dSTom Pothier 		end--;
622*074bb90dSTom Pothier 
623*074bb90dSTom Pothier 	if (begin >= end)
624*074bb90dSTom Pothier 		return (NULL);
625*074bb90dSTom Pothier 
626*074bb90dSTom Pothier 	cp = begin;
627*074bb90dSTom Pothier 	for (i = 0; i < MAXNAMELEN - 1; i++) {
628*074bb90dSTom Pothier 		if (cp >= end)
629*074bb90dSTom Pothier 			break;
630*074bb90dSTom Pothier 		c = *cp;
631*074bb90dSTom Pothier 		if (str_type == LABEL) {
632*074bb90dSTom Pothier 			if (!isprint(c))
633*074bb90dSTom Pothier 				buf[i] = '-';
634*074bb90dSTom Pothier 			else
635*074bb90dSTom Pothier 				buf[i] = c;
636*074bb90dSTom Pothier 		} else {
637*074bb90dSTom Pothier 			if (c == ':' || c == '=' || c == '/' ||
638*074bb90dSTom Pothier 			    isspace(c) || !isprint(c))
639*074bb90dSTom Pothier 				buf[i] = '-';
640*074bb90dSTom Pothier 			else
641*074bb90dSTom Pothier 				buf[i] = c;
642*074bb90dSTom Pothier 		}
643*074bb90dSTom Pothier 		cp++;
644*074bb90dSTom Pothier 	}
645*074bb90dSTom Pothier 	buf[i] = 0;
646*074bb90dSTom Pothier 
647*074bb90dSTom Pothier 	pp = topo_mod_strdup(mod, buf);
648*074bb90dSTom Pothier 
649*074bb90dSTom Pothier 	if (str_type == LABEL)
650*074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)begin);
651*074bb90dSTom Pothier 
652*074bb90dSTom Pothier 	return (pp);
653*074bb90dSTom Pothier }
654