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