xref: /illumos-gate/usr/src/cmd/fm/fmtopo/common/fmtopo.c (revision 7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fe)
1*7aec1d6eScindi /*
2*7aec1d6eScindi  * CDDL HEADER START
3*7aec1d6eScindi  *
4*7aec1d6eScindi  * The contents of this file are subject to the terms of the
5*7aec1d6eScindi  * Common Development and Distribution License (the "License").
6*7aec1d6eScindi  * You may not use this file except in compliance with the License.
7*7aec1d6eScindi  *
8*7aec1d6eScindi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7aec1d6eScindi  * or http://www.opensolaris.org/os/licensing.
10*7aec1d6eScindi  * See the License for the specific language governing permissions
11*7aec1d6eScindi  * and limitations under the License.
12*7aec1d6eScindi  *
13*7aec1d6eScindi  * When distributing Covered Code, include this CDDL HEADER in each
14*7aec1d6eScindi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7aec1d6eScindi  * If applicable, add the following below this CDDL HEADER, with the
16*7aec1d6eScindi  * fields enclosed by brackets "[]" replaced with your own identifying
17*7aec1d6eScindi  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7aec1d6eScindi  *
19*7aec1d6eScindi  * CDDL HEADER END
20*7aec1d6eScindi  */
21*7aec1d6eScindi 
22*7aec1d6eScindi /*
23*7aec1d6eScindi  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*7aec1d6eScindi  * Use is subject to license terms.
25*7aec1d6eScindi  */
26*7aec1d6eScindi 
27*7aec1d6eScindi #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7aec1d6eScindi 
29*7aec1d6eScindi #include <sys/fm/protocol.h>
30*7aec1d6eScindi #include <fm/libtopo.h>
31*7aec1d6eScindi #include <limits.h>
32*7aec1d6eScindi #include <strings.h>
33*7aec1d6eScindi #include <stdio.h>
34*7aec1d6eScindi #include <errno.h>
35*7aec1d6eScindi 
36*7aec1d6eScindi #define	FMTOPO_EXIT_SUCCESS	0
37*7aec1d6eScindi #define	FMTOPO_EXIT_ERROR	1
38*7aec1d6eScindi #define	FMTOPO_EXIT_USAGE	2
39*7aec1d6eScindi 
40*7aec1d6eScindi static const char *g_pname;
41*7aec1d6eScindi 
42*7aec1d6eScindi static const char *opt_R = "/";
43*7aec1d6eScindi static const char *opt_s = FM_FMRI_SCHEME_HC;
44*7aec1d6eScindi 
45*7aec1d6eScindi static int opt_e;
46*7aec1d6eScindi static int opt_d;
47*7aec1d6eScindi static int opt_v;
48*7aec1d6eScindi static int opt_V;
49*7aec1d6eScindi 
50*7aec1d6eScindi static int
51*7aec1d6eScindi usage(FILE *fp)
52*7aec1d6eScindi {
53*7aec1d6eScindi 	(void) fprintf(fp,
54*7aec1d6eScindi 	    "Usage: %s [-Cdev] [-R root] [-s scheme]\n", g_pname);
55*7aec1d6eScindi 
56*7aec1d6eScindi 	(void) fprintf(fp,
57*7aec1d6eScindi 	    "\t-C  dump core after completing execution\n"
58*7aec1d6eScindi 	    "\t-d  set debug mode for libtopo\n"
59*7aec1d6eScindi 	    "\t-e  display nodes as paths using esc/eft notation\n"
60*7aec1d6eScindi 	    "\t-R  set root directory for libtopo plug-ins and other files\n"
61*7aec1d6eScindi 	    "\t-s  display topology for the specified FMRI scheme\n"
62*7aec1d6eScindi 	    "\t-v  set verbose mode (display node ASRU, FRU and label)\n"
63*7aec1d6eScindi 	    "\t-V  set verbose mode (display node properties)\n");
64*7aec1d6eScindi 
65*7aec1d6eScindi 	return (FMTOPO_EXIT_USAGE);
66*7aec1d6eScindi }
67*7aec1d6eScindi 
68*7aec1d6eScindi static void
69*7aec1d6eScindi print_fmri(topo_hdl_t *thp, tnode_t *node)
70*7aec1d6eScindi {
71*7aec1d6eScindi 	int err;
72*7aec1d6eScindi 	char *name;
73*7aec1d6eScindi 	nvlist_t *fmri;
74*7aec1d6eScindi 
75*7aec1d6eScindi 	if (topo_node_resource(node, &fmri, &err) < 0) {
76*7aec1d6eScindi 		(void) fprintf(stderr, "%s: failed to get fmri for %s=%d: %s\n",
77*7aec1d6eScindi 		    g_pname, topo_node_name(node),
78*7aec1d6eScindi 		    topo_node_instance(node), topo_strerror(err));
79*7aec1d6eScindi 		return;
80*7aec1d6eScindi 	}
81*7aec1d6eScindi 
82*7aec1d6eScindi 	if (topo_fmri_nvl2str(thp, fmri, &name, &err) < 0) {
83*7aec1d6eScindi 		(void) fprintf(stderr, "%s: failed to convert fmri for %s=%d "
84*7aec1d6eScindi 		    "to a string: %s\n", g_pname, topo_node_name(node),
85*7aec1d6eScindi 		    topo_node_instance(node), topo_strerror(err));
86*7aec1d6eScindi 		nvlist_free(fmri);
87*7aec1d6eScindi 		return;
88*7aec1d6eScindi 	}
89*7aec1d6eScindi 
90*7aec1d6eScindi 	(void) printf("%s\n", name);
91*7aec1d6eScindi 
92*7aec1d6eScindi 	if (opt_v) {
93*7aec1d6eScindi 		char *aname = NULL, *fname = NULL, *lname = NULL;
94*7aec1d6eScindi 		nvlist_t *asru = NULL;
95*7aec1d6eScindi 		nvlist_t *fru = NULL;
96*7aec1d6eScindi 
97*7aec1d6eScindi 		if (topo_node_asru(node, &asru, NULL, &err) == 0)
98*7aec1d6eScindi 		    (void) topo_fmri_nvl2str(thp, asru, &aname, &err);
99*7aec1d6eScindi 		if (topo_node_fru(node, &fru, NULL, &err) == 0)
100*7aec1d6eScindi 		    (void) topo_fmri_nvl2str(thp, fru, &fname, &err);
101*7aec1d6eScindi 		(void) topo_node_label(node, &lname, &err);
102*7aec1d6eScindi 		if (aname != NULL) {
103*7aec1d6eScindi 			nvlist_free(asru);
104*7aec1d6eScindi 			(void) printf("\tASRU: %s\n", aname);
105*7aec1d6eScindi 			topo_hdl_strfree(thp, aname);
106*7aec1d6eScindi 		} else {
107*7aec1d6eScindi 			(void) printf("\tASRU: -\n");
108*7aec1d6eScindi 		}
109*7aec1d6eScindi 		if (fname != NULL) {
110*7aec1d6eScindi 			nvlist_free(fru);
111*7aec1d6eScindi 			(void) printf("\tFRU: %s\n", fname);
112*7aec1d6eScindi 			topo_hdl_strfree(thp, fname);
113*7aec1d6eScindi 		} else {
114*7aec1d6eScindi 			(void) printf("\tFRU: -\n");
115*7aec1d6eScindi 		}
116*7aec1d6eScindi 		if (lname != NULL) {
117*7aec1d6eScindi 			(void) printf("\tLabel: %s\n", lname);
118*7aec1d6eScindi 			topo_hdl_strfree(thp, lname);
119*7aec1d6eScindi 		} else {
120*7aec1d6eScindi 			(void) printf("\tLabel: -\n");
121*7aec1d6eScindi 		}
122*7aec1d6eScindi 	}
123*7aec1d6eScindi 
124*7aec1d6eScindi 	nvlist_free(fmri);
125*7aec1d6eScindi 
126*7aec1d6eScindi 	if (opt_d) {
127*7aec1d6eScindi 		fmri = NULL;
128*7aec1d6eScindi 
129*7aec1d6eScindi 		if (topo_fmri_str2nvl(thp, name, &fmri, &err) < 0) {
130*7aec1d6eScindi 			(void) fprintf(stderr, "%s: failed to convert "
131*7aec1d6eScindi 			    "alternate fmri for %s=%d: %s\n", g_pname,
132*7aec1d6eScindi 			    topo_node_name(node), topo_node_instance(node),
133*7aec1d6eScindi 			    topo_strerror(err));
134*7aec1d6eScindi 		} else {
135*7aec1d6eScindi 			nvlist_print(stderr, fmri);
136*7aec1d6eScindi 			nvlist_free(fmri);
137*7aec1d6eScindi 		}
138*7aec1d6eScindi 	}
139*7aec1d6eScindi 
140*7aec1d6eScindi 	topo_hdl_strfree(thp, name);
141*7aec1d6eScindi }
142*7aec1d6eScindi 
143*7aec1d6eScindi static void
144*7aec1d6eScindi print_everstyle(tnode_t *node)
145*7aec1d6eScindi {
146*7aec1d6eScindi 	char buf[PATH_MAX], numbuf[64];
147*7aec1d6eScindi 	nvlist_t *fmri, **hcl;
148*7aec1d6eScindi 	int i, err;
149*7aec1d6eScindi 	uint_t n;
150*7aec1d6eScindi 
151*7aec1d6eScindi 	if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL,
152*7aec1d6eScindi 	    TOPO_PROP_RESOURCE, &fmri, &err) < 0) {
153*7aec1d6eScindi 		(void) fprintf(stderr, "%s: failed to get fmri for %s=%d: %s\n",
154*7aec1d6eScindi 		    g_pname, topo_node_name(node),
155*7aec1d6eScindi 		    topo_node_instance(node), topo_strerror(err));
156*7aec1d6eScindi 		return;
157*7aec1d6eScindi 	}
158*7aec1d6eScindi 
159*7aec1d6eScindi 	if (nvlist_lookup_nvlist_array(fmri, FM_FMRI_HC_LIST, &hcl, &n) != 0) {
160*7aec1d6eScindi 		(void) fprintf(stderr, "%s: failed to find %s for %s=%d\n",
161*7aec1d6eScindi 		    g_pname, FM_FMRI_HC_LIST, topo_node_name(node),
162*7aec1d6eScindi 		    topo_node_instance(node));
163*7aec1d6eScindi 		return;
164*7aec1d6eScindi 	}
165*7aec1d6eScindi 
166*7aec1d6eScindi 	buf[0] = '\0';
167*7aec1d6eScindi 
168*7aec1d6eScindi 	for (i = 0; i < n; i++) {
169*7aec1d6eScindi 		char *name, *inst, *estr;
170*7aec1d6eScindi 		ulong_t ul;
171*7aec1d6eScindi 
172*7aec1d6eScindi 		if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name) != 0 ||
173*7aec1d6eScindi 		    nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &inst) != 0) {
174*7aec1d6eScindi 			(void) fprintf(stderr, "%s: failed to get "
175*7aec1d6eScindi 			    "name-instance for %s=%d\n", g_pname,
176*7aec1d6eScindi 			    topo_node_name(node), topo_node_instance(node));
177*7aec1d6eScindi 			return;
178*7aec1d6eScindi 		}
179*7aec1d6eScindi 
180*7aec1d6eScindi 		errno = 0;
181*7aec1d6eScindi 		ul = strtoul(inst, &estr, 10);
182*7aec1d6eScindi 
183*7aec1d6eScindi 		if (errno != 0 || estr == inst) {
184*7aec1d6eScindi 			(void) fprintf(stderr, "%s: instance %s does not "
185*7aec1d6eScindi 			    "convert to an unsigned integer\n", g_pname, inst);
186*7aec1d6eScindi 		}
187*7aec1d6eScindi 
188*7aec1d6eScindi 		(void) strlcat(buf, "/", sizeof (buf));
189*7aec1d6eScindi 		(void) strlcat(buf, name, sizeof (buf));
190*7aec1d6eScindi 		(void) snprintf(numbuf, sizeof (numbuf), "%u", ul);
191*7aec1d6eScindi 		(void) strlcat(buf, numbuf, sizeof (buf));
192*7aec1d6eScindi 	}
193*7aec1d6eScindi 
194*7aec1d6eScindi 	(void) printf("%s\n", buf);
195*7aec1d6eScindi }
196*7aec1d6eScindi 
197*7aec1d6eScindi /*ARGSUSED*/
198*7aec1d6eScindi static int
199*7aec1d6eScindi print_tnode(topo_hdl_t *thp, tnode_t *node, void *arg)
200*7aec1d6eScindi {
201*7aec1d6eScindi 	if (opt_e && strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0)
202*7aec1d6eScindi 		print_everstyle(node);
203*7aec1d6eScindi 	else
204*7aec1d6eScindi 		print_fmri(thp, node);
205*7aec1d6eScindi 
206*7aec1d6eScindi 	if (opt_V) {
207*7aec1d6eScindi 		nvlist_t *nvl = topo_prop_get_all(thp, node);
208*7aec1d6eScindi 
209*7aec1d6eScindi 		if (nvl == NULL) {
210*7aec1d6eScindi 			(void) fprintf(stderr, "%s: failed to get properties "
211*7aec1d6eScindi 			    "for %s=%d\n", g_pname, topo_node_name(node),
212*7aec1d6eScindi 			    topo_node_instance(node));
213*7aec1d6eScindi 		} else {
214*7aec1d6eScindi 			nvlist_print(stdout, nvl);
215*7aec1d6eScindi 			nvlist_free(nvl);
216*7aec1d6eScindi 		}
217*7aec1d6eScindi 	}
218*7aec1d6eScindi 
219*7aec1d6eScindi 	return (TOPO_WALK_NEXT);
220*7aec1d6eScindi }
221*7aec1d6eScindi 
222*7aec1d6eScindi int
223*7aec1d6eScindi main(int argc, char *argv[])
224*7aec1d6eScindi {
225*7aec1d6eScindi 	topo_hdl_t *thp;
226*7aec1d6eScindi 	topo_walk_t *twp;
227*7aec1d6eScindi 	char *uuid;
228*7aec1d6eScindi 	int c, err;
229*7aec1d6eScindi 
230*7aec1d6eScindi 	g_pname = argv[0];
231*7aec1d6eScindi 
232*7aec1d6eScindi 	while (optind < argc) {
233*7aec1d6eScindi 		while ((c = getopt(argc, argv, "aCdeR:s:vV")) != -1) {
234*7aec1d6eScindi 			switch (c) {
235*7aec1d6eScindi 			case 'C':
236*7aec1d6eScindi 				atexit(abort);
237*7aec1d6eScindi 				break;
238*7aec1d6eScindi 			case 'd':
239*7aec1d6eScindi 				opt_d++;
240*7aec1d6eScindi 				break;
241*7aec1d6eScindi 			case 'e':
242*7aec1d6eScindi 				opt_e++;
243*7aec1d6eScindi 				break;
244*7aec1d6eScindi 			case 'v':
245*7aec1d6eScindi 				opt_v++;
246*7aec1d6eScindi 				break;
247*7aec1d6eScindi 			case 'V':
248*7aec1d6eScindi 				opt_V++;
249*7aec1d6eScindi 				break;
250*7aec1d6eScindi 			case 'R':
251*7aec1d6eScindi 				opt_R = optarg;
252*7aec1d6eScindi 				break;
253*7aec1d6eScindi 			case 's':
254*7aec1d6eScindi 				opt_s = optarg;
255*7aec1d6eScindi 				break;
256*7aec1d6eScindi 			default:
257*7aec1d6eScindi 				return (usage(stderr));
258*7aec1d6eScindi 			}
259*7aec1d6eScindi 		}
260*7aec1d6eScindi 
261*7aec1d6eScindi 		if (optind < argc) {
262*7aec1d6eScindi 			(void) fprintf(stderr, "%s: illegal argument -- %s\n",
263*7aec1d6eScindi 			    g_pname, argv[optind]);
264*7aec1d6eScindi 			return (FMTOPO_EXIT_USAGE);
265*7aec1d6eScindi 		}
266*7aec1d6eScindi 	}
267*7aec1d6eScindi 
268*7aec1d6eScindi 	if ((thp = topo_open(TOPO_VERSION, opt_R, &err)) == NULL) {
269*7aec1d6eScindi 		(void) fprintf(stderr, "%s: failed to open topology tree: %s\n",
270*7aec1d6eScindi 		    g_pname, topo_strerror(err));
271*7aec1d6eScindi 		return (FMTOPO_EXIT_ERROR);
272*7aec1d6eScindi 	}
273*7aec1d6eScindi 
274*7aec1d6eScindi 	if (opt_d)
275*7aec1d6eScindi 		topo_debug_set(thp, TOPO_DBG_ALL, "stderr");
276*7aec1d6eScindi 
277*7aec1d6eScindi 	if ((uuid = topo_snap_hold(thp, NULL, &err)) == NULL) {
278*7aec1d6eScindi 		(void) fprintf(stderr, "%s: failed to snapshot topology: %s\n",
279*7aec1d6eScindi 		    g_pname, topo_strerror(err));
280*7aec1d6eScindi 		topo_close(thp);
281*7aec1d6eScindi 		return (FMTOPO_EXIT_ERROR);
282*7aec1d6eScindi 	}
283*7aec1d6eScindi 
284*7aec1d6eScindi 	if ((twp = topo_walk_init(thp, opt_s, print_tnode, NULL, &err))
285*7aec1d6eScindi 	    == NULL) {
286*7aec1d6eScindi 		(void) fprintf(stderr, "%s: failed to walk %s topology:"
287*7aec1d6eScindi 		    " %s\n", g_pname, opt_s, topo_strerror(err));
288*7aec1d6eScindi 
289*7aec1d6eScindi 		topo_hdl_strfree(thp, uuid);
290*7aec1d6eScindi 		topo_close(thp);
291*7aec1d6eScindi 
292*7aec1d6eScindi 		return (err ? FMTOPO_EXIT_ERROR : FMTOPO_EXIT_SUCCESS);
293*7aec1d6eScindi 	}
294*7aec1d6eScindi 
295*7aec1d6eScindi 	if (!opt_e)
296*7aec1d6eScindi 		(void) printf("Topology Snapshot %s\n", uuid);
297*7aec1d6eScindi 
298*7aec1d6eScindi 	topo_hdl_strfree(thp, uuid);
299*7aec1d6eScindi 
300*7aec1d6eScindi 	if (topo_walk_step(twp, TOPO_WALK_CHILD) == TOPO_WALK_ERR) {
301*7aec1d6eScindi 		(void) fprintf(stderr, "%s: failed to walk topology\n",
302*7aec1d6eScindi 		    g_pname);
303*7aec1d6eScindi 		topo_close(thp);
304*7aec1d6eScindi 		return (FMTOPO_EXIT_ERROR);
305*7aec1d6eScindi 	}
306*7aec1d6eScindi 
307*7aec1d6eScindi 	if (opt_d)
308*7aec1d6eScindi 		(void) printf("--------------------\n");
309*7aec1d6eScindi 
310*7aec1d6eScindi 	topo_walk_fini(twp);
311*7aec1d6eScindi 	topo_snap_release(thp);
312*7aec1d6eScindi 	topo_close(thp);
313*7aec1d6eScindi 
314*7aec1d6eScindi 	return (FMTOPO_EXIT_SUCCESS);
315*7aec1d6eScindi }
316