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