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