17aec1d6eScindi /* 27aec1d6eScindi * CDDL HEADER START 37aec1d6eScindi * 47aec1d6eScindi * The contents of this file are subject to the terms of the 57aec1d6eScindi * Common Development and Distribution License (the "License"). 67aec1d6eScindi * You may not use this file except in compliance with the License. 77aec1d6eScindi * 87aec1d6eScindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97aec1d6eScindi * or http://www.opensolaris.org/os/licensing. 107aec1d6eScindi * See the License for the specific language governing permissions 117aec1d6eScindi * and limitations under the License. 127aec1d6eScindi * 137aec1d6eScindi * When distributing Covered Code, include this CDDL HEADER in each 147aec1d6eScindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157aec1d6eScindi * If applicable, add the following below this CDDL HEADER, with the 167aec1d6eScindi * fields enclosed by brackets "[]" replaced with your own identifying 177aec1d6eScindi * information: Portions Copyright [yyyy] [name of copyright owner] 187aec1d6eScindi * 197aec1d6eScindi * CDDL HEADER END 207aec1d6eScindi */ 217aec1d6eScindi 227aec1d6eScindi /* 23f6e214c7SGavin Maltby * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 24*1410cb93SJoshua M. Clulow * Copyright (c) 2013, Joyent, Inc. All rights reserved. 257aec1d6eScindi */ 267aec1d6eScindi 277aec1d6eScindi 287aec1d6eScindi #include <sys/fm/protocol.h> 297aec1d6eScindi #include <fm/libtopo.h> 300eb822a1Scindi #include <ctype.h> 31c40d7343Scindi #include <fnmatch.h> 327aec1d6eScindi #include <limits.h> 337aec1d6eScindi #include <strings.h> 347aec1d6eScindi #include <stdio.h> 357aec1d6eScindi #include <errno.h> 36c40d7343Scindi #include <umem.h> 37f6e214c7SGavin Maltby #include <zone.h> 380eb822a1Scindi #include <sys/param.h> 397aec1d6eScindi 407aec1d6eScindi #define FMTOPO_EXIT_SUCCESS 0 417aec1d6eScindi #define FMTOPO_EXIT_ERROR 1 427aec1d6eScindi #define FMTOPO_EXIT_USAGE 2 437aec1d6eScindi 440eb822a1Scindi #define STDERR "stderr" 450eb822a1Scindi #define DOTS "..." 460eb822a1Scindi #define ALL "all" 470eb822a1Scindi 487aec1d6eScindi static const char *g_pname; 49c40d7343Scindi static const char *g_fmri = NULL; 507aec1d6eScindi 517aec1d6eScindi static const char *opt_R = "/"; 527aec1d6eScindi static const char *opt_s = FM_FMRI_SCHEME_HC; 53b6955755SRobert Johnston static const char optstr[] = "bCdem:P:pR:s:StVx"; 54b6955755SRobert Johnston static const char *opt_m; 557aec1d6eScindi 5678432d5eScy152378 static int opt_b = 0; 570eb822a1Scindi static int opt_d = 0; 5878432d5eScy152378 static int opt_e = 0; 590eb822a1Scindi static int opt_p = 0; 60c40d7343Scindi static int opt_S = 0; 61c40d7343Scindi static int opt_t = 0; 6278432d5eScy152378 static int opt_V = 0; 630eb822a1Scindi static int opt_x = 0; 64c40d7343Scindi static int opt_all = 0; 65c40d7343Scindi 66c40d7343Scindi struct prop_args { 67c40d7343Scindi const char *group; 68c40d7343Scindi const char *prop; 69c40d7343Scindi const char *type; 70c40d7343Scindi const char *value; 71c40d7343Scindi }; 72c40d7343Scindi 73c40d7343Scindi static struct prop_args **pargs = NULL; 74c40d7343Scindi static int pcnt = 0; 757aec1d6eScindi 767aec1d6eScindi static int 777aec1d6eScindi usage(FILE *fp) 787aec1d6eScindi { 797aec1d6eScindi (void) fprintf(fp, 80a38fc4eaSRobert Johnston "Usage: %s [-bCedpSVx] [-P group.property[=type:value]] " 81b6955755SRobert Johnston "[-R root] [-m method] [-s scheme] [fmri]\n", g_pname); 827aec1d6eScindi 837aec1d6eScindi (void) fprintf(fp, 8478432d5eScy152378 "\t-b walk in sibling-first order (default is child-first)\n" 857aec1d6eScindi "\t-C dump core after completing execution\n" 860eb822a1Scindi "\t-d set debug mode for libtopo modules\n" 870eb822a1Scindi "\t-e display FMRIs as paths using esc/eft notation\n" 88b6955755SRobert Johnston "\t-m execute given method\n" 89c40d7343Scindi "\t-P get/set specified properties\n" 900eb822a1Scindi "\t-p display of FMRI protocol properties\n" 917aec1d6eScindi "\t-R set root directory for libtopo plug-ins and other files\n" 927aec1d6eScindi "\t-s display topology for the specified FMRI scheme\n" 93c40d7343Scindi "\t-S display FMRI status (present/usable)\n" 940eb822a1Scindi "\t-V set verbose mode\n" 950eb822a1Scindi "\t-x display a xml formatted topology\n"); 967aec1d6eScindi 977aec1d6eScindi return (FMTOPO_EXIT_USAGE); 987aec1d6eScindi } 997aec1d6eScindi 100c40d7343Scindi static topo_type_t 101c40d7343Scindi str2type(const char *tstr) 1027aec1d6eScindi { 103c40d7343Scindi topo_type_t type; 1047aec1d6eScindi 105c40d7343Scindi if (tstr == NULL) 106c40d7343Scindi return (TOPO_TYPE_INVALID); 107c40d7343Scindi 108c40d7343Scindi if (strcmp(tstr, "int32") == 0) 109c40d7343Scindi type = TOPO_TYPE_INT32; 110c40d7343Scindi else if (strcmp(tstr, "uint32") == 0) 111c40d7343Scindi type = TOPO_TYPE_UINT32; 112c40d7343Scindi else if (strcmp(tstr, "int64") == 0) 113c40d7343Scindi type = TOPO_TYPE_INT64; 114c40d7343Scindi else if (strcmp(tstr, "uint64") == 0) 115c40d7343Scindi type = TOPO_TYPE_UINT64; 116c40d7343Scindi else if (strcmp(tstr, "string") == 0) 117c40d7343Scindi type = TOPO_TYPE_STRING; 118c40d7343Scindi else if (strcmp(tstr, "fmri") == 0) 119c40d7343Scindi type = TOPO_TYPE_FMRI; 120c40d7343Scindi else { 121c40d7343Scindi type = TOPO_TYPE_INVALID; 1227aec1d6eScindi } 1237aec1d6eScindi 124c40d7343Scindi return (type); 1257aec1d6eScindi } 1267aec1d6eScindi 127c40d7343Scindi static void 128c40d7343Scindi print_node(topo_hdl_t *thp, tnode_t *node, nvlist_t *nvl, const char *fmri) 129c40d7343Scindi { 130c40d7343Scindi int err, ret; 1317aec1d6eScindi 132c40d7343Scindi (void) printf("%s\n", (char *)fmri); 133c40d7343Scindi 134c40d7343Scindi if (opt_p && !(pcnt > 0 || opt_V || opt_all)) { 1357aec1d6eScindi char *aname = NULL, *fname = NULL, *lname = NULL; 1367aec1d6eScindi nvlist_t *asru = NULL; 1377aec1d6eScindi nvlist_t *fru = NULL; 1387aec1d6eScindi 1397aec1d6eScindi if (topo_node_asru(node, &asru, NULL, &err) == 0) 1407aec1d6eScindi (void) topo_fmri_nvl2str(thp, asru, &aname, &err); 1417aec1d6eScindi if (topo_node_fru(node, &fru, NULL, &err) == 0) 1427aec1d6eScindi (void) topo_fmri_nvl2str(thp, fru, &fname, &err); 1437aec1d6eScindi (void) topo_node_label(node, &lname, &err); 1447aec1d6eScindi if (aname != NULL) { 1457aec1d6eScindi nvlist_free(asru); 1467aec1d6eScindi (void) printf("\tASRU: %s\n", aname); 1477aec1d6eScindi topo_hdl_strfree(thp, aname); 1487aec1d6eScindi } else { 1497aec1d6eScindi (void) printf("\tASRU: -\n"); 1507aec1d6eScindi } 1517aec1d6eScindi if (fname != NULL) { 1527aec1d6eScindi nvlist_free(fru); 1537aec1d6eScindi (void) printf("\tFRU: %s\n", fname); 1547aec1d6eScindi topo_hdl_strfree(thp, fname); 1557aec1d6eScindi } else { 1567aec1d6eScindi (void) printf("\tFRU: -\n"); 1577aec1d6eScindi } 1587aec1d6eScindi if (lname != NULL) { 1597aec1d6eScindi (void) printf("\tLabel: %s\n", lname); 1607aec1d6eScindi topo_hdl_strfree(thp, lname); 1617aec1d6eScindi } else { 1627aec1d6eScindi (void) printf("\tLabel: -\n"); 1637aec1d6eScindi } 1647aec1d6eScindi } 1657aec1d6eScindi 166c40d7343Scindi if (opt_S) { 167c40d7343Scindi if ((ret = topo_fmri_present(thp, nvl, &err)) < 0) 168c40d7343Scindi (void) printf("\tPresent: -\n"); 169c40d7343Scindi else 170c40d7343Scindi (void) printf("\tPresent: %s\n", 171c40d7343Scindi ret ? "true" : "false"); 172c40d7343Scindi 173c40d7343Scindi if ((ret = topo_fmri_unusable(thp, nvl, &err)) < 0) 174c40d7343Scindi (void) printf("\tUnusable: -\n"); 175c40d7343Scindi else 176c40d7343Scindi (void) printf("\tUnusable: %s\n", 177c40d7343Scindi ret ? "true" : "false"); 178c40d7343Scindi } 1797aec1d6eScindi } 1807aec1d6eScindi 1817aec1d6eScindi static void 1827aec1d6eScindi print_everstyle(tnode_t *node) 1837aec1d6eScindi { 1847aec1d6eScindi char buf[PATH_MAX], numbuf[64]; 1857aec1d6eScindi nvlist_t *fmri, **hcl; 1867aec1d6eScindi int i, err; 1877aec1d6eScindi uint_t n; 1887aec1d6eScindi 1897aec1d6eScindi if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, 1907aec1d6eScindi TOPO_PROP_RESOURCE, &fmri, &err) < 0) { 1917aec1d6eScindi (void) fprintf(stderr, "%s: failed to get fmri for %s=%d: %s\n", 1927aec1d6eScindi g_pname, topo_node_name(node), 1937aec1d6eScindi topo_node_instance(node), topo_strerror(err)); 1947aec1d6eScindi return; 1957aec1d6eScindi } 1967aec1d6eScindi 1977aec1d6eScindi if (nvlist_lookup_nvlist_array(fmri, FM_FMRI_HC_LIST, &hcl, &n) != 0) { 1987aec1d6eScindi (void) fprintf(stderr, "%s: failed to find %s for %s=%d\n", 1997aec1d6eScindi g_pname, FM_FMRI_HC_LIST, topo_node_name(node), 2007aec1d6eScindi topo_node_instance(node)); 201825ba0f2Srobj nvlist_free(fmri); 2027aec1d6eScindi return; 2037aec1d6eScindi } 2047aec1d6eScindi 2057aec1d6eScindi buf[0] = '\0'; 2067aec1d6eScindi 2077aec1d6eScindi for (i = 0; i < n; i++) { 2087aec1d6eScindi char *name, *inst, *estr; 2097aec1d6eScindi ulong_t ul; 2107aec1d6eScindi 2117aec1d6eScindi if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name) != 0 || 2127aec1d6eScindi nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &inst) != 0) { 2137aec1d6eScindi (void) fprintf(stderr, "%s: failed to get " 2147aec1d6eScindi "name-instance for %s=%d\n", g_pname, 2157aec1d6eScindi topo_node_name(node), topo_node_instance(node)); 216825ba0f2Srobj nvlist_free(fmri); 2177aec1d6eScindi return; 2187aec1d6eScindi } 2197aec1d6eScindi 2207aec1d6eScindi errno = 0; 2217aec1d6eScindi ul = strtoul(inst, &estr, 10); 2227aec1d6eScindi 2237aec1d6eScindi if (errno != 0 || estr == inst) { 2247aec1d6eScindi (void) fprintf(stderr, "%s: instance %s does not " 2257aec1d6eScindi "convert to an unsigned integer\n", g_pname, inst); 2267aec1d6eScindi } 2277aec1d6eScindi 2287aec1d6eScindi (void) strlcat(buf, "/", sizeof (buf)); 2297aec1d6eScindi (void) strlcat(buf, name, sizeof (buf)); 2307aec1d6eScindi (void) snprintf(numbuf, sizeof (numbuf), "%u", ul); 2317aec1d6eScindi (void) strlcat(buf, numbuf, sizeof (buf)); 2327aec1d6eScindi } 233825ba0f2Srobj nvlist_free(fmri); 2347aec1d6eScindi 2357aec1d6eScindi (void) printf("%s\n", buf); 2367aec1d6eScindi } 2377aec1d6eScindi 2380eb822a1Scindi static void 239825ba0f2Srobj print_prop_nameval(topo_hdl_t *thp, tnode_t *node, nvlist_t *nvl) 2400eb822a1Scindi { 2410eb822a1Scindi int err; 2420eb822a1Scindi topo_type_t type; 243825ba0f2Srobj char *tstr, *propn, buf[48], *factype; 2440eb822a1Scindi nvpair_t *pv_nvp; 2459dd0f810Scindi int i; 2469dd0f810Scindi uint_t nelem; 2470eb822a1Scindi 2480eb822a1Scindi if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL) 2490eb822a1Scindi return; 2500eb822a1Scindi 2510eb822a1Scindi /* Print property name */ 2520eb822a1Scindi if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL || 2530eb822a1Scindi nvpair_name(pv_nvp) == NULL || 2540eb822a1Scindi strcmp(TOPO_PROP_VAL_NAME, nvpair_name(pv_nvp)) != 0) { 2550eb822a1Scindi (void) fprintf(stderr, "%s: malformed property name\n", 2560eb822a1Scindi g_pname); 2570eb822a1Scindi return; 2580eb822a1Scindi } else { 2590eb822a1Scindi (void) nvpair_value_string(pv_nvp, &propn); 2600eb822a1Scindi } 2610eb822a1Scindi 2620eb822a1Scindi if ((pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL || 2630eb822a1Scindi nvpair_name(pv_nvp) == NULL || 2640eb822a1Scindi strcmp(nvpair_name(pv_nvp), TOPO_PROP_VAL_TYPE) != 0 || 265c40d7343Scindi nvpair_type(pv_nvp) != DATA_TYPE_UINT32) { 2660eb822a1Scindi (void) fprintf(stderr, "%s: malformed property type for %s\n", 2670eb822a1Scindi g_pname, propn); 2680eb822a1Scindi return; 2690eb822a1Scindi } else { 270c40d7343Scindi (void) nvpair_value_uint32(pv_nvp, (uint32_t *)&type); 2710eb822a1Scindi } 2720eb822a1Scindi 2730eb822a1Scindi switch (type) { 2740eb822a1Scindi case TOPO_TYPE_BOOLEAN: tstr = "boolean"; break; 2750eb822a1Scindi case TOPO_TYPE_INT32: tstr = "int32"; break; 2760eb822a1Scindi case TOPO_TYPE_UINT32: tstr = "uint32"; break; 2770eb822a1Scindi case TOPO_TYPE_INT64: tstr = "int64"; break; 2780eb822a1Scindi case TOPO_TYPE_UINT64: tstr = "uint64"; break; 279825ba0f2Srobj case TOPO_TYPE_DOUBLE: tstr = "double"; break; 2800eb822a1Scindi case TOPO_TYPE_STRING: tstr = "string"; break; 2810eb822a1Scindi case TOPO_TYPE_FMRI: tstr = "fmri"; break; 2820eb822a1Scindi case TOPO_TYPE_INT32_ARRAY: tstr = "int32[]"; break; 2830eb822a1Scindi case TOPO_TYPE_UINT32_ARRAY: tstr = "uint32[]"; break; 2840eb822a1Scindi case TOPO_TYPE_INT64_ARRAY: tstr = "int64[]"; break; 2850eb822a1Scindi case TOPO_TYPE_UINT64_ARRAY: tstr = "uint64[]"; break; 2860eb822a1Scindi case TOPO_TYPE_STRING_ARRAY: tstr = "string[]"; break; 2870eb822a1Scindi case TOPO_TYPE_FMRI_ARRAY: tstr = "fmri[]"; break; 2880eb822a1Scindi default: tstr = "unknown type"; 2890eb822a1Scindi } 2900eb822a1Scindi 291888e0559SRobert Johnston (void) printf(" %-17s %-8s ", propn, tstr); 2920eb822a1Scindi 2930eb822a1Scindi /* 2940eb822a1Scindi * Get property value 2950eb822a1Scindi */ 2960eb822a1Scindi if (nvpair_name(pv_nvp) == NULL || 2970eb822a1Scindi (pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL) { 2980eb822a1Scindi (void) fprintf(stderr, "%s: malformed property value\n", 2990eb822a1Scindi g_pname); 3000eb822a1Scindi return; 3010eb822a1Scindi } 3020eb822a1Scindi 3030eb822a1Scindi switch (nvpair_type(pv_nvp)) { 3040eb822a1Scindi case DATA_TYPE_INT32: { 3050eb822a1Scindi int32_t val; 3060eb822a1Scindi (void) nvpair_value_int32(pv_nvp, &val); 3070eb822a1Scindi (void) printf(" %d", val); 3080eb822a1Scindi break; 3090eb822a1Scindi } 3100eb822a1Scindi case DATA_TYPE_UINT32: { 311825ba0f2Srobj uint32_t val, type; 312825ba0f2Srobj char val_str[49]; 313825ba0f2Srobj nvlist_t *fac, *rsrc = NULL; 314825ba0f2Srobj 3150eb822a1Scindi (void) nvpair_value_uint32(pv_nvp, &val); 316825ba0f2Srobj if (node == NULL || topo_node_flags(node) != 317825ba0f2Srobj TOPO_NODE_FACILITY) 318825ba0f2Srobj goto uint32_def; 319825ba0f2Srobj 320825ba0f2Srobj if (topo_node_resource(node, &rsrc, &err) != 0) 321825ba0f2Srobj goto uint32_def; 322825ba0f2Srobj 323825ba0f2Srobj if (nvlist_lookup_nvlist(rsrc, "facility", &fac) != 0) 324825ba0f2Srobj goto uint32_def; 325825ba0f2Srobj 326825ba0f2Srobj if (nvlist_lookup_string(fac, FM_FMRI_FACILITY_TYPE, 327825ba0f2Srobj &factype) != 0) 328825ba0f2Srobj goto uint32_def; 329825ba0f2Srobj 330825ba0f2Srobj nvlist_free(rsrc); 331825ba0f2Srobj rsrc = NULL; 332825ba0f2Srobj 333825ba0f2Srobj /* 334825ba0f2Srobj * Special case code to do friendlier printing of 335825ba0f2Srobj * facility node properties 336825ba0f2Srobj */ 337825ba0f2Srobj if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) && 338825ba0f2Srobj (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) { 339825ba0f2Srobj topo_sensor_type_name(val, val_str, 48); 340825ba0f2Srobj (void) printf(" 0x%x (%s)", val, val_str); 341825ba0f2Srobj break; 342825ba0f2Srobj } else if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) && 343825ba0f2Srobj (strcmp(factype, TOPO_FAC_TYPE_INDICATOR) == 0)) { 344825ba0f2Srobj topo_led_type_name(val, val_str, 48); 345825ba0f2Srobj (void) printf(" 0x%x (%s)", val, val_str); 346825ba0f2Srobj break; 347825ba0f2Srobj } else if (strcmp(propn, TOPO_SENSOR_UNITS) == 0) { 348825ba0f2Srobj topo_sensor_units_name(val, val_str, 48); 349825ba0f2Srobj (void) printf(" 0x%x (%s)", val, val_str); 350825ba0f2Srobj break; 351825ba0f2Srobj } else if (strcmp(propn, TOPO_LED_MODE) == 0) { 352825ba0f2Srobj topo_led_state_name(val, val_str, 48); 353825ba0f2Srobj (void) printf(" 0x%x (%s)", val, val_str); 354825ba0f2Srobj break; 355825ba0f2Srobj } else if ((strcmp(propn, TOPO_SENSOR_STATE) == 0) && 356825ba0f2Srobj (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) { 357825ba0f2Srobj if (topo_prop_get_uint32(node, 358825ba0f2Srobj TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE, 359825ba0f2Srobj &type, &err) != 0) { 360825ba0f2Srobj goto uint32_def; 361825ba0f2Srobj } 362825ba0f2Srobj topo_sensor_state_name(type, val, val_str, 48); 363825ba0f2Srobj (void) printf(" 0x%x (%s)", val, val_str); 364825ba0f2Srobj break; 365825ba0f2Srobj } 366825ba0f2Srobj uint32_def: 3670eb822a1Scindi (void) printf(" 0x%x", val); 368825ba0f2Srobj nvlist_free(rsrc); 3690eb822a1Scindi break; 3700eb822a1Scindi } 3710eb822a1Scindi case DATA_TYPE_INT64: { 3720eb822a1Scindi int64_t val; 3730eb822a1Scindi (void) nvpair_value_int64(pv_nvp, &val); 3740eb822a1Scindi (void) printf(" %lld", (longlong_t)val); 3750eb822a1Scindi break; 3760eb822a1Scindi } 3770eb822a1Scindi case DATA_TYPE_UINT64: { 3780eb822a1Scindi uint64_t val; 3790eb822a1Scindi (void) nvpair_value_uint64(pv_nvp, &val); 3800eb822a1Scindi (void) printf(" 0x%llx", (u_longlong_t)val); 3810eb822a1Scindi break; 3820eb822a1Scindi } 383825ba0f2Srobj case DATA_TYPE_DOUBLE: { 384825ba0f2Srobj double val; 385825ba0f2Srobj (void) nvpair_value_double(pv_nvp, &val); 386825ba0f2Srobj (void) printf(" %lf", (double)val); 387825ba0f2Srobj break; 388825ba0f2Srobj } 3890eb822a1Scindi case DATA_TYPE_STRING: { 3900eb822a1Scindi char *val; 3910eb822a1Scindi (void) nvpair_value_string(pv_nvp, &val); 3920eb822a1Scindi if (!opt_V && strlen(val) > 48) { 3930eb822a1Scindi (void) snprintf(buf, 48, "%s...", val); 3940eb822a1Scindi (void) printf(" %s", buf); 3950eb822a1Scindi } else { 3960eb822a1Scindi (void) printf(" %s", val); 3970eb822a1Scindi } 3980eb822a1Scindi break; 3990eb822a1Scindi } 4000eb822a1Scindi case DATA_TYPE_NVLIST: { 4010eb822a1Scindi nvlist_t *val; 4020eb822a1Scindi char *fmri; 4030eb822a1Scindi (void) nvpair_value_nvlist(pv_nvp, &val); 4040eb822a1Scindi if (topo_fmri_nvl2str(thp, val, &fmri, &err) != 0) { 4050eb822a1Scindi if (opt_V) 4060eb822a1Scindi nvlist_print(stdout, nvl); 4070eb822a1Scindi break; 4080eb822a1Scindi } 4090eb822a1Scindi 4100eb822a1Scindi if (!opt_V && strlen(fmri) > 48) { 4110eb822a1Scindi (void) snprintf(buf, 48, "%s", fmri); 4120eb822a1Scindi (void) snprintf(&buf[45], 4, "%s", DOTS); 4130eb822a1Scindi (void) printf(" %s", buf); 4140eb822a1Scindi } else { 4150eb822a1Scindi (void) printf(" %s", fmri); 4160eb822a1Scindi } 4170eb822a1Scindi 4180eb822a1Scindi topo_hdl_strfree(thp, fmri); 4190eb822a1Scindi break; 4200eb822a1Scindi } 42188045cffSRobert Johnston case DATA_TYPE_INT32_ARRAY: { 42288045cffSRobert Johnston int32_t *val; 42388045cffSRobert Johnston 42488045cffSRobert Johnston (void) nvpair_value_int32_array(pv_nvp, &val, &nelem); 42588045cffSRobert Johnston (void) printf(" [ "); 42688045cffSRobert Johnston for (i = 0; i < nelem; i++) 42788045cffSRobert Johnston (void) printf("%d ", val[i]); 42888045cffSRobert Johnston (void) printf("]"); 42988045cffSRobert Johnston break; 43088045cffSRobert Johnston } 4319dd0f810Scindi case DATA_TYPE_UINT32_ARRAY: { 4329dd0f810Scindi uint32_t *val; 4339dd0f810Scindi 4349dd0f810Scindi (void) nvpair_value_uint32_array(pv_nvp, &val, &nelem); 4359dd0f810Scindi (void) printf(" [ "); 4369dd0f810Scindi for (i = 0; i < nelem; i++) 4379dd0f810Scindi (void) printf("%u ", val[i]); 4389dd0f810Scindi (void) printf("]"); 4399dd0f810Scindi break; 4409dd0f810Scindi } 441825ba0f2Srobj case DATA_TYPE_INT64_ARRAY: { 442825ba0f2Srobj int64_t *val; 443825ba0f2Srobj 444825ba0f2Srobj (void) nvpair_value_int64_array(pv_nvp, &val, &nelem); 445825ba0f2Srobj (void) printf(" [ "); 446825ba0f2Srobj for (i = 0; i < nelem; i++) 447825ba0f2Srobj (void) printf("%lld ", val[i]); 448825ba0f2Srobj (void) printf("]"); 449825ba0f2Srobj break; 450825ba0f2Srobj } 45188045cffSRobert Johnston case DATA_TYPE_UINT64_ARRAY: { 45288045cffSRobert Johnston uint64_t *val; 45388045cffSRobert Johnston 45488045cffSRobert Johnston (void) nvpair_value_uint64_array(pv_nvp, &val, &nelem); 45588045cffSRobert Johnston (void) printf(" [ "); 45688045cffSRobert Johnston for (i = 0; i < nelem; i++) 45788045cffSRobert Johnston (void) printf("%llu ", val[i]); 45888045cffSRobert Johnston (void) printf("]"); 45988045cffSRobert Johnston break; 46088045cffSRobert Johnston } 461602ca9eaScth case DATA_TYPE_STRING_ARRAY: { 462602ca9eaScth char **val; 463602ca9eaScth 464602ca9eaScth (void) nvpair_value_string_array(pv_nvp, &val, &nelem); 465602ca9eaScth (void) printf(" [ "); 466602ca9eaScth for (i = 0; i < nelem; i++) 46788045cffSRobert Johnston (void) printf("\"%s\" ", val[i]); 468602ca9eaScth (void) printf("]"); 469602ca9eaScth break; 470602ca9eaScth } 4710eb822a1Scindi default: 4720eb822a1Scindi (void) fprintf(stderr, " unknown data type (%d)", 4730eb822a1Scindi nvpair_type(pv_nvp)); 4740eb822a1Scindi break; 4750eb822a1Scindi } 4760eb822a1Scindi (void) printf("\n"); 4770eb822a1Scindi } 4780eb822a1Scindi 4790eb822a1Scindi static void 480c40d7343Scindi print_pgroup(topo_hdl_t *thp, tnode_t *node, const char *pgn, char *dstab, 481c40d7343Scindi char *nstab, int32_t version) 4820eb822a1Scindi { 483c40d7343Scindi int err; 4840eb822a1Scindi char buf[30]; 485c40d7343Scindi topo_pgroup_info_t *pgi = NULL; 4860eb822a1Scindi 487c40d7343Scindi if (pgn == NULL) 4880eb822a1Scindi return; 4890eb822a1Scindi 490c40d7343Scindi if (node != NULL && (dstab == NULL || nstab == NULL || version == -1)) { 491c40d7343Scindi if ((pgi = topo_pgroup_info(node, pgn, &err)) != NULL) { 492c40d7343Scindi dstab = (char *)topo_stability2name(pgi->tpi_datastab); 493c40d7343Scindi nstab = (char *)topo_stability2name(pgi->tpi_namestab); 494c40d7343Scindi version = pgi->tpi_version; 495c40d7343Scindi } 496c40d7343Scindi } 497c40d7343Scindi 498c40d7343Scindi if (dstab == NULL || nstab == NULL || version == -1) { 499888e0559SRobert Johnston (void) printf(" group: %-30s version: - stability: -/-\n", 500888e0559SRobert Johnston pgn); 501c40d7343Scindi } else if (!opt_V && strlen(pgn) > 30) { 5020eb822a1Scindi (void) snprintf(buf, 26, "%s", pgn); 5030eb822a1Scindi (void) snprintf(&buf[27], 4, "%s", DOTS); 504888e0559SRobert Johnston (void) printf(" group: %-30s version: %-3d stability: %s/%s\n", 5050eb822a1Scindi buf, version, nstab, dstab); 5060eb822a1Scindi } else { 507888e0559SRobert Johnston (void) printf(" group: %-30s version: %-3d stability: %s/%s\n", 5080eb822a1Scindi pgn, version, nstab, dstab); 5090eb822a1Scindi } 510c40d7343Scindi 511c40d7343Scindi if (pgi != NULL) { 512c40d7343Scindi topo_hdl_strfree(thp, (char *)pgi->tpi_name); 513c40d7343Scindi topo_hdl_free(thp, pgi, sizeof (topo_pgroup_info_t)); 5140eb822a1Scindi } 5150eb822a1Scindi } 5160eb822a1Scindi 5170eb822a1Scindi static void 518c40d7343Scindi print_all_props(topo_hdl_t *thp, tnode_t *node, nvlist_t *p_nv, 519c40d7343Scindi const char *group) 5200eb822a1Scindi { 5210eb822a1Scindi char *pgn = NULL, *dstab = NULL, *nstab = NULL; 522c40d7343Scindi int32_t version; 5230eb822a1Scindi nvlist_t *pg_nv, *pv_nv; 5240eb822a1Scindi nvpair_t *nvp, *pg_nvp; 525c40d7343Scindi int pg_done, match, all = strcmp(group, ALL) == 0; 5260eb822a1Scindi 5270eb822a1Scindi for (nvp = nvlist_next_nvpair(p_nv, NULL); nvp != NULL; 5280eb822a1Scindi nvp = nvlist_next_nvpair(p_nv, nvp)) { 5290eb822a1Scindi if (strcmp(TOPO_PROP_GROUP, nvpair_name(nvp)) != 0 || 5300eb822a1Scindi nvpair_type(nvp) != DATA_TYPE_NVLIST) 5310eb822a1Scindi continue; 5320eb822a1Scindi 533c40d7343Scindi nstab = NULL; 534c40d7343Scindi dstab = NULL; 535c40d7343Scindi version = -1; 536c40d7343Scindi pg_done = match = 0; 5370eb822a1Scindi (void) nvpair_value_nvlist(nvp, &pg_nv); 5380eb822a1Scindi for (pg_nvp = nvlist_next_nvpair(pg_nv, NULL); pg_nvp != NULL; 5390eb822a1Scindi pg_nvp = nvlist_next_nvpair(pg_nv, pg_nvp)) { 5400eb822a1Scindi /* 5410eb822a1Scindi * Print property group name and stability levels 5420eb822a1Scindi */ 5430eb822a1Scindi if (strcmp(TOPO_PROP_GROUP_NAME, nvpair_name(pg_nvp)) 5440eb822a1Scindi == 0 && nvpair_type(pg_nvp) == DATA_TYPE_STRING) { 5450eb822a1Scindi (void) nvpair_value_string(pg_nvp, &pgn); 546c40d7343Scindi match = strcmp(group, pgn) == 0; 547c40d7343Scindi continue; 548c40d7343Scindi } 5490eb822a1Scindi 550c40d7343Scindi if (strcmp(TOPO_PROP_GROUP_NSTAB, 5510eb822a1Scindi nvpair_name(pg_nvp)) == 0 && 5520eb822a1Scindi nvpair_type(pg_nvp) == DATA_TYPE_STRING) { 5530eb822a1Scindi (void) nvpair_value_string(pg_nvp, &nstab); 554c40d7343Scindi continue; 555c40d7343Scindi } 556c40d7343Scindi 557c40d7343Scindi if (strcmp(TOPO_PROP_GROUP_DSTAB, 5580eb822a1Scindi nvpair_name(pg_nvp)) == 0 && 5590eb822a1Scindi nvpair_type(pg_nvp) == DATA_TYPE_STRING) { 5600eb822a1Scindi (void) nvpair_value_string(pg_nvp, &dstab); 561c40d7343Scindi continue; 562c40d7343Scindi } 563c40d7343Scindi 564c40d7343Scindi if (strcmp(TOPO_PROP_GROUP_VERSION, 5650eb822a1Scindi nvpair_name(pg_nvp)) == 0 && 5660eb822a1Scindi nvpair_type(pg_nvp) == DATA_TYPE_INT32) { 5670eb822a1Scindi (void) nvpair_value_int32(pg_nvp, &version); 5680eb822a1Scindi continue; 5690eb822a1Scindi } 570c40d7343Scindi 571c40d7343Scindi if ((match || all) && !pg_done) { 572c40d7343Scindi print_pgroup(thp, node, pgn, dstab, nstab, 573c40d7343Scindi version); 574c40d7343Scindi pg_done++; 575c40d7343Scindi } 576c40d7343Scindi 5770eb822a1Scindi /* 578c40d7343Scindi * Print property group and property name-value pair 5790eb822a1Scindi */ 580c40d7343Scindi if (strcmp(TOPO_PROP_VAL, nvpair_name(pg_nvp)) 5810eb822a1Scindi == 0 && nvpair_type(pg_nvp) == DATA_TYPE_NVLIST) { 5820eb822a1Scindi (void) nvpair_value_nvlist(pg_nvp, &pv_nv); 583c40d7343Scindi if ((match || all) && pg_done) { 584825ba0f2Srobj print_prop_nameval(thp, node, pv_nv); 585c40d7343Scindi } 5860eb822a1Scindi 5870eb822a1Scindi } 588c40d7343Scindi 5890eb822a1Scindi } 590c40d7343Scindi if (match && !all) 591c40d7343Scindi return; 592c40d7343Scindi } 593c40d7343Scindi } 594c40d7343Scindi 595c40d7343Scindi static void 596c40d7343Scindi set_prop(topo_hdl_t *thp, tnode_t *node, nvlist_t *fmri, struct prop_args *pp) 597c40d7343Scindi { 598c40d7343Scindi int ret, err = 0; 599c40d7343Scindi topo_type_t type; 600*1410cb93SJoshua M. Clulow nvlist_t *nvl = NULL; 601c40d7343Scindi char *end; 602c40d7343Scindi 603c40d7343Scindi if (pp->prop == NULL || pp->type == NULL || pp->value == NULL) 604*1410cb93SJoshua M. Clulow goto out; 605c40d7343Scindi 606c40d7343Scindi if ((type = str2type(pp->type)) == TOPO_TYPE_INVALID) { 607c40d7343Scindi (void) fprintf(stderr, "%s: invalid property type %s for %s\n", 608c40d7343Scindi g_pname, pp->type, pp->prop); 609*1410cb93SJoshua M. Clulow goto out; 610c40d7343Scindi } 611c40d7343Scindi 612c40d7343Scindi if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { 613c40d7343Scindi (void) fprintf(stderr, "%s: nvlist allocation failed for " 614c40d7343Scindi "%s=%s:%s\n", g_pname, pp->prop, pp->type, pp->value); 615*1410cb93SJoshua M. Clulow goto out; 616c40d7343Scindi } 617c40d7343Scindi ret = nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, pp->prop); 618c40d7343Scindi ret |= nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, type); 619c40d7343Scindi if (ret != 0) { 620c40d7343Scindi (void) fprintf(stderr, "%s: invalid property type %s for %s\n", 621c40d7343Scindi g_pname, pp->type, pp->prop); 622*1410cb93SJoshua M. Clulow goto out; 623c40d7343Scindi } 624c40d7343Scindi 625c40d7343Scindi errno = 0; 626c40d7343Scindi switch (type) { 627c40d7343Scindi case TOPO_TYPE_INT32: 628c40d7343Scindi { 629c40d7343Scindi int32_t val; 630c40d7343Scindi 631c40d7343Scindi val = strtol(pp->value, &end, 0); 632c40d7343Scindi if (errno == ERANGE) { 633c40d7343Scindi ret = -1; 634c40d7343Scindi break; 635c40d7343Scindi } 636c40d7343Scindi ret = nvlist_add_int32(nvl, TOPO_PROP_VAL_VAL, val); 637c40d7343Scindi break; 638c40d7343Scindi } 639c40d7343Scindi case TOPO_TYPE_UINT32: 640c40d7343Scindi { 641c40d7343Scindi uint32_t val; 642c40d7343Scindi 643c40d7343Scindi val = strtoul(pp->value, &end, 0); 644c40d7343Scindi if (errno == ERANGE) { 645c40d7343Scindi ret = -1; 646c40d7343Scindi break; 647c40d7343Scindi } 648c40d7343Scindi ret = nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, val); 649c40d7343Scindi break; 650c40d7343Scindi } 651c40d7343Scindi case TOPO_TYPE_INT64: 652c40d7343Scindi { 653c40d7343Scindi int64_t val; 654c40d7343Scindi 655c40d7343Scindi val = strtoll(pp->value, &end, 0); 656c40d7343Scindi if (errno == ERANGE) { 657c40d7343Scindi ret = -1; 658c40d7343Scindi break; 659c40d7343Scindi } 660c40d7343Scindi ret = nvlist_add_int64(nvl, TOPO_PROP_VAL_VAL, val); 661c40d7343Scindi break; 662c40d7343Scindi } 663c40d7343Scindi case TOPO_TYPE_UINT64: 664c40d7343Scindi { 665c40d7343Scindi uint64_t val; 666c40d7343Scindi 667c40d7343Scindi val = strtoull(pp->value, &end, 0); 668c40d7343Scindi if (errno == ERANGE) { 669c40d7343Scindi ret = -1; 670c40d7343Scindi break; 671c40d7343Scindi } 672c40d7343Scindi ret = nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL, val); 673c40d7343Scindi break; 674c40d7343Scindi } 675c40d7343Scindi case TOPO_TYPE_STRING: 676c40d7343Scindi { 677c40d7343Scindi ret = nvlist_add_string(nvl, TOPO_PROP_VAL_VAL, 678c40d7343Scindi pp->value); 679c40d7343Scindi break; 680c40d7343Scindi } 681c40d7343Scindi case TOPO_TYPE_FMRI: 682c40d7343Scindi { 683*1410cb93SJoshua M. Clulow nvlist_t *val = NULL; 684*1410cb93SJoshua M. Clulow 685*1410cb93SJoshua M. Clulow if ((ret = topo_fmri_str2nvl(thp, pp->value, &val, 686*1410cb93SJoshua M. Clulow &err)) < 0) 687c40d7343Scindi break; 688c40d7343Scindi 689c40d7343Scindi if ((ret = nvlist_add_nvlist(nvl, TOPO_PROP_VAL_VAL, 690*1410cb93SJoshua M. Clulow val)) != 0) 691c40d7343Scindi err = ETOPO_PROP_NVL; 692*1410cb93SJoshua M. Clulow 693*1410cb93SJoshua M. Clulow nvlist_free(val); 694c40d7343Scindi break; 695c40d7343Scindi } 696c40d7343Scindi default: 697c40d7343Scindi ret = -1; 698c40d7343Scindi } 699c40d7343Scindi 700c40d7343Scindi if (ret != 0) { 701c40d7343Scindi (void) fprintf(stderr, "%s: unable to set property value for " 702c40d7343Scindi "%s: %s\n", g_pname, pp->prop, topo_strerror(err)); 703*1410cb93SJoshua M. Clulow goto out; 704c40d7343Scindi } 705c40d7343Scindi 706c40d7343Scindi if (node != NULL) { 707*1410cb93SJoshua M. Clulow if ((ret = topo_prop_setprop(node, pp->group, nvl, 708*1410cb93SJoshua M. Clulow TOPO_PROP_MUTABLE, nvl, &err)) < 0) { 709c40d7343Scindi (void) fprintf(stderr, "%s: unable to set property " 710c40d7343Scindi "value for " "%s=%s:%s: %s\n", g_pname, pp->prop, 711*1410cb93SJoshua M. Clulow pp->type, pp->value, topo_strerror(err)); 712*1410cb93SJoshua M. Clulow goto out; 713c40d7343Scindi } 714c40d7343Scindi } else { 715*1410cb93SJoshua M. Clulow if ((ret = topo_fmri_setprop(thp, fmri, pp->group, nvl, 716*1410cb93SJoshua M. Clulow TOPO_PROP_MUTABLE, nvl, &err)) < 0) { 717c40d7343Scindi (void) fprintf(stderr, "%s: unable to set property " 718c40d7343Scindi "value for " "%s=%s:%s: %s\n", g_pname, pp->prop, 719*1410cb93SJoshua M. Clulow pp->type, pp->value, topo_strerror(err)); 720*1410cb93SJoshua M. Clulow goto out; 721c40d7343Scindi } 722c40d7343Scindi } 723c40d7343Scindi 724c40d7343Scindi nvlist_free(nvl); 725*1410cb93SJoshua M. Clulow nvl = NULL; 726c40d7343Scindi 727c40d7343Scindi /* 728c40d7343Scindi * Now, get the property back for printing 729c40d7343Scindi */ 730c40d7343Scindi if (node != NULL) { 731*1410cb93SJoshua M. Clulow if ((ret = topo_prop_getprop(node, pp->group, pp->prop, NULL, 732*1410cb93SJoshua M. Clulow &nvl, &err)) < 0) { 733c40d7343Scindi (void) fprintf(stderr, "%s: failed to get %s.%s: %s\n", 734c40d7343Scindi g_pname, pp->group, pp->prop, topo_strerror(err)); 735*1410cb93SJoshua M. Clulow goto out; 736c40d7343Scindi } 737c40d7343Scindi } else { 738*1410cb93SJoshua M. Clulow if ((ret = topo_fmri_getprop(thp, fmri, pp->group, pp->prop, 739*1410cb93SJoshua M. Clulow NULL, &nvl, &err)) < 0) { 740c40d7343Scindi (void) fprintf(stderr, "%s: failed to get %s.%s: %s\n", 741c40d7343Scindi g_pname, pp->group, pp->prop, topo_strerror(err)); 742*1410cb93SJoshua M. Clulow goto out; 743c40d7343Scindi } 744c40d7343Scindi } 745c40d7343Scindi 746c40d7343Scindi print_pgroup(thp, node, pp->group, NULL, NULL, 0); 747825ba0f2Srobj print_prop_nameval(thp, node, nvl); 748c40d7343Scindi 749*1410cb93SJoshua M. Clulow out: 750*1410cb93SJoshua M. Clulow nvlist_free(nvl); 751c40d7343Scindi } 752c40d7343Scindi 753c40d7343Scindi static void 754c40d7343Scindi print_props(topo_hdl_t *thp, tnode_t *node) 755c40d7343Scindi { 756c40d7343Scindi int i, err; 757c40d7343Scindi nvlist_t *nvl; 758c40d7343Scindi struct prop_args *pp; 759c40d7343Scindi 760c40d7343Scindi if (pcnt == 0) 761c40d7343Scindi return; 762c40d7343Scindi 763c40d7343Scindi for (i = 0; i < pcnt; ++i) { 764c40d7343Scindi pp = pargs[i]; 765c40d7343Scindi 766c40d7343Scindi if (pp->group == NULL) 767c40d7343Scindi continue; 768c40d7343Scindi 769c40d7343Scindi /* 770c40d7343Scindi * If we have a valid value, this is a request to 771c40d7343Scindi * set a property. Otherwise, just print the property 772c40d7343Scindi * group and any specified properties. 773c40d7343Scindi */ 774c40d7343Scindi if (pp->value == NULL) { 775c40d7343Scindi if (pp->prop == NULL) { 776c40d7343Scindi 777c40d7343Scindi /* 778c40d7343Scindi * Print all properties in this group 779c40d7343Scindi */ 780c40d7343Scindi if ((nvl = topo_prop_getprops(node, &err)) 781c40d7343Scindi == NULL) { 782c40d7343Scindi (void) fprintf(stderr, "%s: failed to " 783c40d7343Scindi "get %s: %s\n", g_pname, 784c40d7343Scindi pp->group, 785c40d7343Scindi topo_strerror(err)); 786c40d7343Scindi continue; 787c40d7343Scindi } else { 788c40d7343Scindi print_all_props(thp, node, nvl, 789c40d7343Scindi pp->group); 790c40d7343Scindi nvlist_free(nvl); 791c40d7343Scindi continue; 792c40d7343Scindi } 793c40d7343Scindi } 794c40d7343Scindi if (topo_prop_getprop(node, pp->group, pp->prop, 795c40d7343Scindi NULL, &nvl, &err) < 0) { 796c40d7343Scindi (void) fprintf(stderr, "%s: failed to get " 797c40d7343Scindi "%s.%s: %s\n", g_pname, 798c40d7343Scindi pp->group, pp->prop, 799c40d7343Scindi topo_strerror(err)); 800c40d7343Scindi continue; 801c40d7343Scindi } else { 802c40d7343Scindi print_pgroup(thp, node, pp->group, NULL, 803c40d7343Scindi NULL, 0); 804825ba0f2Srobj print_prop_nameval(thp, node, nvl); 805c40d7343Scindi nvlist_free(nvl); 806c40d7343Scindi } 807c40d7343Scindi } else { 808c40d7343Scindi set_prop(thp, node, NULL, pp); 809c40d7343Scindi } 8100eb822a1Scindi } 8110eb822a1Scindi } 8120eb822a1Scindi 8137aec1d6eScindi /*ARGSUSED*/ 8147aec1d6eScindi static int 815c40d7343Scindi walk_node(topo_hdl_t *thp, tnode_t *node, void *arg) 8167aec1d6eScindi { 8170eb822a1Scindi int err; 8180eb822a1Scindi nvlist_t *nvl; 819b6955755SRobert Johnston nvlist_t *rsrc, *out; 820c40d7343Scindi char *s; 8210eb822a1Scindi 8220eb822a1Scindi if (opt_e && strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0) { 8237aec1d6eScindi print_everstyle(node); 8240eb822a1Scindi return (TOPO_WALK_NEXT); 8250eb822a1Scindi } 8260eb822a1Scindi 827c40d7343Scindi if (topo_node_resource(node, &rsrc, &err) < 0) { 828c40d7343Scindi (void) fprintf(stderr, "%s: failed to get resource: " 829c40d7343Scindi "%s", g_pname, topo_strerror(err)); 830c40d7343Scindi return (TOPO_WALK_NEXT); 831c40d7343Scindi } 832c40d7343Scindi if (topo_fmri_nvl2str(thp, rsrc, &s, &err) < 0) { 833c40d7343Scindi (void) fprintf(stderr, "%s: failed to convert " 834c40d7343Scindi "resource to FMRI string: %s", g_pname, 835c40d7343Scindi topo_strerror(err)); 836c40d7343Scindi nvlist_free(rsrc); 837c40d7343Scindi return (TOPO_WALK_NEXT); 838c40d7343Scindi } 8397aec1d6eScindi 840c40d7343Scindi if (g_fmri != NULL && fnmatch(g_fmri, s, 0) != 0) { 841c40d7343Scindi nvlist_free(rsrc); 842c40d7343Scindi topo_hdl_strfree(thp, s); 843c40d7343Scindi return (TOPO_WALK_NEXT); 844c40d7343Scindi } 845c40d7343Scindi 846c40d7343Scindi print_node(thp, node, rsrc, s); 847c40d7343Scindi topo_hdl_strfree(thp, s); 848c40d7343Scindi nvlist_free(rsrc); 849c40d7343Scindi 850b6955755SRobert Johnston if (opt_m != NULL) { 851b6955755SRobert Johnston if (topo_method_invoke(node, opt_m, 0, NULL, &out, &err) == 0) { 852b6955755SRobert Johnston nvlist_print(stdout, out); 853b6955755SRobert Johnston nvlist_free(out); 854b6955755SRobert Johnston } else if (err != ETOPO_METHOD_NOTSUP) 855b6955755SRobert Johnston (void) fprintf(stderr, "%s: method failed unexpectedly " 856b6955755SRobert Johnston "on %s=%d (%s)\n", g_pname, topo_node_name(node), 857b6955755SRobert Johnston topo_node_instance(node), topo_strerror(err)); 858b6955755SRobert Johnston } 859b6955755SRobert Johnston 860c40d7343Scindi if (opt_V || opt_all) { 8610eb822a1Scindi if ((nvl = topo_prop_getprops(node, &err)) == NULL) { 8620eb822a1Scindi (void) fprintf(stderr, "%s: failed to get " 8630eb822a1Scindi "properties for %s=%d: %s\n", g_pname, 8640eb822a1Scindi topo_node_name(node), topo_node_instance(node), 8650eb822a1Scindi topo_strerror(err)); 8667aec1d6eScindi } else { 867c40d7343Scindi print_all_props(thp, node, nvl, ALL); 8687aec1d6eScindi nvlist_free(nvl); 8697aec1d6eScindi } 870825ba0f2Srobj } else if (pcnt > 0) 871c40d7343Scindi print_props(thp, node); 8727aec1d6eScindi 873888e0559SRobert Johnston (void) printf("\n"); 8740eb822a1Scindi 8757aec1d6eScindi return (TOPO_WALK_NEXT); 8767aec1d6eScindi } 8777aec1d6eScindi 878c40d7343Scindi static void 879c40d7343Scindi get_pargs(int argc, char *argv[]) 8807aec1d6eScindi { 881c40d7343Scindi struct prop_args *pp; 882c40d7343Scindi char c, *s, *p; 883c40d7343Scindi int i = 0; 884c40d7343Scindi 885c40d7343Scindi if ((pargs = malloc(sizeof (struct prop_args *) * pcnt)) == NULL) { 886c40d7343Scindi (void) fprintf(stderr, "%s: failed to allocate property " 887c40d7343Scindi "arguments\n", g_pname); 888c40d7343Scindi return; 889c40d7343Scindi } 890c40d7343Scindi 891c40d7343Scindi for (optind = 1; (c = getopt(argc, argv, optstr)) != EOF; ) { 892c40d7343Scindi if (c == 'P') { 893c40d7343Scindi 894c40d7343Scindi if (strcmp(optarg, ALL) == 0) { 895c40d7343Scindi opt_all++; 896c40d7343Scindi break; 897c40d7343Scindi } 898c40d7343Scindi 899c40d7343Scindi if ((pp = pargs[i] = malloc(sizeof (struct prop_args))) 900c40d7343Scindi == NULL) { 901c40d7343Scindi (void) fprintf(stderr, "%s: failed to " 902c40d7343Scindi "allocate propertyarguments\n", g_pname); 903c40d7343Scindi return; 904c40d7343Scindi } 905c40d7343Scindi ++i; 906c40d7343Scindi pp->group = NULL; 907c40d7343Scindi pp->prop = NULL; 908c40d7343Scindi pp->type = NULL; 909c40d7343Scindi pp->value = NULL; 910c40d7343Scindi 911c40d7343Scindi p = optarg; 912c40d7343Scindi if ((s = strchr(p, '.')) != NULL) { 913c40d7343Scindi *s++ = '\0'; /* strike out delimiter */ 914c40d7343Scindi pp->group = p; 915c40d7343Scindi p = s; 916c40d7343Scindi if ((s = strchr(p, '=')) != NULL) { 917c40d7343Scindi *s++ = '\0'; /* strike out delimiter */ 918c40d7343Scindi pp->prop = p; 919c40d7343Scindi p = s; 920c40d7343Scindi if ((s = strchr(p, ':')) != NULL) { 921c40d7343Scindi *s++ = '\0'; 922c40d7343Scindi pp->type = p; 923c40d7343Scindi pp->value = s; 924c40d7343Scindi } else { 925c40d7343Scindi (void) fprintf(stderr, "%s: " 926c40d7343Scindi "property type not " 927c40d7343Scindi "specified for assignment " 928c40d7343Scindi " of %s.%s\n", g_pname, 929c40d7343Scindi pp->group, pp->prop); 930c40d7343Scindi break; 931c40d7343Scindi } 932c40d7343Scindi } else { 933c40d7343Scindi pp->prop = p; 934c40d7343Scindi } 935c40d7343Scindi } else { 936c40d7343Scindi pp->group = p; 937c40d7343Scindi } 938c40d7343Scindi if (i >= pcnt) 939c40d7343Scindi break; 940c40d7343Scindi } 941c40d7343Scindi } 942c40d7343Scindi 943c40d7343Scindi if (opt_all > 0) { 944c40d7343Scindi int j; 945c40d7343Scindi 946c40d7343Scindi for (j = 0; j < i; ++j) 947c40d7343Scindi free(pargs[i]); 948c40d7343Scindi free(pargs); 949c40d7343Scindi pargs = NULL; 950c40d7343Scindi } 951c40d7343Scindi } 952c40d7343Scindi 953c40d7343Scindi static int 954c40d7343Scindi walk_topo(topo_hdl_t *thp, char *uuid) 955c40d7343Scindi { 956c40d7343Scindi int err; 9577aec1d6eScindi topo_walk_t *twp; 95878432d5eScy152378 int flag; 9597aec1d6eScindi 960f6e214c7SGavin Maltby if (getzoneid() != GLOBAL_ZONEID && 961f6e214c7SGavin Maltby strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0) { 962f6e214c7SGavin Maltby return (0); 963f6e214c7SGavin Maltby } 964f6e214c7SGavin Maltby 965c40d7343Scindi if ((twp = topo_walk_init(thp, opt_s, walk_node, NULL, &err)) 9667aec1d6eScindi == NULL) { 9677aec1d6eScindi (void) fprintf(stderr, "%s: failed to walk %s topology:" 9687aec1d6eScindi " %s\n", g_pname, opt_s, topo_strerror(err)); 9697aec1d6eScindi 970c40d7343Scindi return (-1); 9717aec1d6eScindi } 9727aec1d6eScindi 9730eb822a1Scindi /* 9740eb822a1Scindi * Print standard header 9750eb822a1Scindi */ 9760eb822a1Scindi if (!opt_e) { 9770eb822a1Scindi char buf[32]; 9780eb822a1Scindi time_t tod = time(NULL); 9790eb822a1Scindi 980888e0559SRobert Johnston (void) printf("TIME UUID\n"); 9810eb822a1Scindi (void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod)); 9820eb822a1Scindi (void) printf("%-15s %-32s\n", buf, uuid); 9830eb822a1Scindi (void) printf("\n"); 9840eb822a1Scindi } 9857aec1d6eScindi 98678432d5eScy152378 flag = opt_b != 0 ? TOPO_WALK_SIBLING : TOPO_WALK_CHILD; 98778432d5eScy152378 98878432d5eScy152378 if (topo_walk_step(twp, flag) == TOPO_WALK_ERR) { 9897aec1d6eScindi (void) fprintf(stderr, "%s: failed to walk topology\n", 9907aec1d6eScindi g_pname); 991724365f7Ssethg topo_walk_fini(twp); 992c40d7343Scindi return (-1); 9937aec1d6eScindi } 9947aec1d6eScindi 9957aec1d6eScindi topo_walk_fini(twp); 996c40d7343Scindi 997c40d7343Scindi return (0); 998c40d7343Scindi } 999c40d7343Scindi 1000c40d7343Scindi static void 1001c40d7343Scindi print_fmri_pgroup(topo_hdl_t *thp, const char *pgn, nvlist_t *nvl) 1002c40d7343Scindi { 1003c40d7343Scindi char *dstab = NULL, *nstab = NULL; 1004c40d7343Scindi int32_t version = -1; 1005c40d7343Scindi nvlist_t *pnvl; 1006c40d7343Scindi nvpair_t *pnvp; 1007c40d7343Scindi 1008c40d7343Scindi (void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_NSTAB, &nstab); 1009c40d7343Scindi (void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_DSTAB, &dstab); 1010c40d7343Scindi (void) nvlist_lookup_int32(nvl, TOPO_PROP_GROUP_VERSION, &version); 1011c40d7343Scindi 1012c40d7343Scindi print_pgroup(thp, NULL, pgn, dstab, nstab, version); 1013c40d7343Scindi 1014c40d7343Scindi for (pnvp = nvlist_next_nvpair(nvl, NULL); pnvp != NULL; 1015c40d7343Scindi pnvp = nvlist_next_nvpair(nvl, pnvp)) { 1016c40d7343Scindi 1017c40d7343Scindi /* 1018c40d7343Scindi * Print property group and property name-value pair 1019c40d7343Scindi */ 1020c40d7343Scindi if (strcmp(TOPO_PROP_VAL, nvpair_name(pnvp)) 1021c40d7343Scindi == 0 && nvpair_type(pnvp) == DATA_TYPE_NVLIST) { 1022c40d7343Scindi (void) nvpair_value_nvlist(pnvp, &pnvl); 1023825ba0f2Srobj print_prop_nameval(thp, NULL, pnvl); 1024c40d7343Scindi 1025c40d7343Scindi } 1026c40d7343Scindi 1027c40d7343Scindi } 1028c40d7343Scindi } 1029c40d7343Scindi 1030c40d7343Scindi static void 1031c40d7343Scindi print_fmri_props(topo_hdl_t *thp, nvlist_t *nvl) 1032c40d7343Scindi { 1033c40d7343Scindi int i, err; 1034c40d7343Scindi struct prop_args *pp; 1035c40d7343Scindi nvlist_t *pnvl; 1036c40d7343Scindi 1037c40d7343Scindi for (i = 0; i < pcnt; ++i) { 1038c40d7343Scindi pp = pargs[i]; 1039c40d7343Scindi 1040c40d7343Scindi if (pp->group == NULL) 1041c40d7343Scindi continue; 1042c40d7343Scindi 1043c40d7343Scindi pnvl = NULL; 1044c40d7343Scindi 1045c40d7343Scindi /* 1046c40d7343Scindi * If we have a valid value, this is a request to 1047c40d7343Scindi * set a property. Otherwise, just print the property 1048c40d7343Scindi * group and any specified properties. 1049c40d7343Scindi */ 1050c40d7343Scindi if (pp->value == NULL) { 1051c40d7343Scindi if (pp->prop == NULL) { 1052c40d7343Scindi 1053c40d7343Scindi /* 1054c40d7343Scindi * Print all properties in this group 1055c40d7343Scindi */ 1056c40d7343Scindi if (topo_fmri_getpgrp(thp, nvl, pp->group, 1057c40d7343Scindi &pnvl, &err) < 0) { 1058c40d7343Scindi (void) fprintf(stderr, "%s: failed to " 1059c40d7343Scindi "get group %s: %s\n", g_pname, 1060c40d7343Scindi pp->group, topo_strerror(err)); 1061c40d7343Scindi continue; 1062c40d7343Scindi } else { 1063825ba0f2Srobj print_fmri_pgroup(thp, pp->group, 1064825ba0f2Srobj pnvl); 1065c40d7343Scindi nvlist_free(pnvl); 1066c40d7343Scindi continue; 1067c40d7343Scindi } 1068c40d7343Scindi } 1069c40d7343Scindi if (topo_fmri_getprop(thp, nvl, pp->group, pp->prop, 1070c40d7343Scindi NULL, &pnvl, &err) < 0) { 1071c40d7343Scindi (void) fprintf(stderr, "%s: failed to get " 1072c40d7343Scindi "%s.%s: %s\n", g_pname, 1073c40d7343Scindi pp->group, pp->prop, 1074c40d7343Scindi topo_strerror(err)); 1075c40d7343Scindi continue; 1076c40d7343Scindi } else { 1077c40d7343Scindi print_fmri_pgroup(thp, pp->group, pnvl); 1078825ba0f2Srobj print_prop_nameval(thp, NULL, pnvl); 1079c40d7343Scindi nvlist_free(nvl); 1080c40d7343Scindi } 1081c40d7343Scindi } else { 1082c40d7343Scindi set_prop(thp, NULL, nvl, pp); 1083c40d7343Scindi } 1084c40d7343Scindi } 1085c40d7343Scindi } 1086c40d7343Scindi 1087c40d7343Scindi void 1088c40d7343Scindi print_fmri(topo_hdl_t *thp, char *uuid) 1089c40d7343Scindi { 1090c40d7343Scindi int ret, err; 1091c40d7343Scindi nvlist_t *nvl; 1092c40d7343Scindi char buf[32]; 1093c40d7343Scindi time_t tod = time(NULL); 1094c40d7343Scindi 1095c40d7343Scindi if (topo_fmri_str2nvl(thp, g_fmri, &nvl, &err) < 0) { 1096c40d7343Scindi (void) fprintf(stderr, "%s: failed to convert %s to nvlist: " 1097c40d7343Scindi "%s\n", g_pname, g_fmri, topo_strerror(err)); 1098c40d7343Scindi return; 1099c40d7343Scindi } 1100c40d7343Scindi 1101888e0559SRobert Johnston (void) printf("TIME UUID\n"); 1102c40d7343Scindi (void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod)); 1103c40d7343Scindi (void) printf("%-15s %-32s\n", buf, uuid); 1104c40d7343Scindi (void) printf("\n"); 1105c40d7343Scindi 1106c40d7343Scindi (void) printf("%s\n", (char *)g_fmri); 1107c40d7343Scindi 1108c40d7343Scindi if (opt_p && !(pcnt > 0 || opt_V || opt_all)) { 1109c40d7343Scindi char *aname = NULL, *fname = NULL, *lname = NULL; 1110c40d7343Scindi nvlist_t *asru = NULL; 1111c40d7343Scindi nvlist_t *fru = NULL; 1112c40d7343Scindi 1113c40d7343Scindi if (topo_fmri_asru(thp, nvl, &asru, &err) == 0) 1114c40d7343Scindi (void) topo_fmri_nvl2str(thp, asru, &aname, &err); 1115c40d7343Scindi if (topo_fmri_fru(thp, nvl, &fru, &err) == 0) 1116c40d7343Scindi (void) topo_fmri_nvl2str(thp, fru, &fname, &err); 1117c40d7343Scindi (void) topo_fmri_label(thp, nvl, &lname, &err); 1118c40d7343Scindi 1119c40d7343Scindi nvlist_free(fru); 1120c40d7343Scindi nvlist_free(asru); 1121c40d7343Scindi 1122c40d7343Scindi if (aname != NULL) { 1123c40d7343Scindi (void) printf("\tASRU: %s\n", aname); 1124c40d7343Scindi topo_hdl_strfree(thp, aname); 1125c40d7343Scindi } else { 1126c40d7343Scindi (void) printf("\tASRU: -\n"); 1127c40d7343Scindi } 1128c40d7343Scindi if (fname != NULL) { 1129c40d7343Scindi (void) printf("\tFRU: %s\n", fname); 1130c40d7343Scindi topo_hdl_strfree(thp, fname); 1131c40d7343Scindi } else { 1132c40d7343Scindi (void) printf("\tFRU: -\n"); 1133c40d7343Scindi } 1134c40d7343Scindi if (lname != NULL) { 1135c40d7343Scindi (void) printf("\tLabel: %s\n", lname); 1136c40d7343Scindi topo_hdl_strfree(thp, lname); 1137c40d7343Scindi } else { 1138c40d7343Scindi (void) printf("\tLabel: -\n"); 1139c40d7343Scindi } 1140c40d7343Scindi } 1141c40d7343Scindi 1142c40d7343Scindi if (opt_S) { 1143c40d7343Scindi if (topo_fmri_str2nvl(thp, g_fmri, &nvl, &err) < 0) { 1144c40d7343Scindi (void) printf("\tPresent: -\n"); 1145c40d7343Scindi (void) printf("\tUnusable: -\n"); 1146c40d7343Scindi return; 1147c40d7343Scindi } 1148c40d7343Scindi 1149c40d7343Scindi if ((ret = topo_fmri_present(thp, nvl, &err)) < 0) 1150c40d7343Scindi (void) printf("\tPresent: -\n"); 1151c40d7343Scindi else 1152c40d7343Scindi (void) printf("\tPresent: %s\n", 1153c40d7343Scindi ret ? "true" : "false"); 1154c40d7343Scindi 1155c40d7343Scindi if ((ret = topo_fmri_unusable(thp, nvl, &err)) < 0) 1156c40d7343Scindi (void) printf("\tUnusable: -\n"); 1157c40d7343Scindi else 1158c40d7343Scindi (void) printf("\tUnusable: %s\n", 1159c40d7343Scindi ret ? "true" : "false"); 1160c40d7343Scindi 1161c40d7343Scindi nvlist_free(nvl); 1162c40d7343Scindi } 1163c40d7343Scindi 11644557a2a1Srobj if (pargs && pcnt > 0) 1165c40d7343Scindi print_fmri_props(thp, nvl); 1166c40d7343Scindi } 1167c40d7343Scindi 1168c40d7343Scindi int 1169c40d7343Scindi fmtopo_exit(topo_hdl_t *thp, char *uuid, int err) 1170c40d7343Scindi { 1171c40d7343Scindi if (uuid != NULL) 1172c40d7343Scindi topo_hdl_strfree(thp, uuid); 1173c40d7343Scindi 1174c40d7343Scindi if (thp != NULL) { 11757aec1d6eScindi topo_snap_release(thp); 11767aec1d6eScindi topo_close(thp); 1177c40d7343Scindi } 1178c40d7343Scindi 1179c40d7343Scindi if (pargs) { 1180c40d7343Scindi int i; 1181c40d7343Scindi for (i = 0; i < pcnt; ++i) 1182c40d7343Scindi free(pargs[i]); 1183c40d7343Scindi free(pargs); 1184c40d7343Scindi } 1185c40d7343Scindi 1186c40d7343Scindi return (err); 1187c40d7343Scindi } 1188c40d7343Scindi 1189c40d7343Scindi int 1190c40d7343Scindi main(int argc, char *argv[]) 1191c40d7343Scindi { 1192c40d7343Scindi topo_hdl_t *thp = NULL; 1193c40d7343Scindi char *uuid = NULL; 1194c40d7343Scindi int c, err = 0; 1195c40d7343Scindi 1196c40d7343Scindi g_pname = argv[0]; 1197c40d7343Scindi 1198c40d7343Scindi while (optind < argc) { 1199c40d7343Scindi while ((c = getopt(argc, argv, optstr)) != -1) { 1200c40d7343Scindi switch (c) { 120178432d5eScy152378 case 'b': 120278432d5eScy152378 opt_b++; 120378432d5eScy152378 break; 1204c40d7343Scindi case 'C': 1205888e0559SRobert Johnston (void) atexit(abort); 1206c40d7343Scindi break; 1207c40d7343Scindi case 'd': 1208c40d7343Scindi opt_d++; 1209c40d7343Scindi break; 1210c40d7343Scindi case 'e': 1211c40d7343Scindi opt_e++; 1212c40d7343Scindi break; 1213b6955755SRobert Johnston case 'm': 1214b6955755SRobert Johnston opt_m = optarg; 1215b6955755SRobert Johnston break; 1216c40d7343Scindi case 'P': 1217c40d7343Scindi pcnt++; 1218c40d7343Scindi break; 1219c40d7343Scindi case 'p': 1220c40d7343Scindi opt_p++; 1221c40d7343Scindi break; 1222c40d7343Scindi case 'V': 1223c40d7343Scindi opt_V++; 1224c40d7343Scindi break; 1225c40d7343Scindi case 'R': 1226c40d7343Scindi opt_R = optarg; 1227c40d7343Scindi break; 1228c40d7343Scindi case 's': 1229c40d7343Scindi opt_s = optarg; 1230c40d7343Scindi break; 1231c40d7343Scindi case 'S': 1232c40d7343Scindi opt_S++; 1233c40d7343Scindi break; 1234c40d7343Scindi case 't': 1235c40d7343Scindi opt_t++; 1236c40d7343Scindi break; 1237c40d7343Scindi case 'x': 1238c40d7343Scindi opt_x++; 1239c40d7343Scindi break; 1240c40d7343Scindi default: 1241c40d7343Scindi return (usage(stderr)); 1242c40d7343Scindi } 1243c40d7343Scindi } 1244c40d7343Scindi 1245c40d7343Scindi if (optind < argc) { 1246c40d7343Scindi if (g_fmri != NULL) { 1247c40d7343Scindi (void) fprintf(stderr, "%s: illegal argument " 1248c40d7343Scindi "-- %s\n", g_pname, argv[optind]); 1249c40d7343Scindi return (FMTOPO_EXIT_USAGE); 1250c40d7343Scindi } else { 1251c40d7343Scindi g_fmri = argv[optind++]; 1252c40d7343Scindi } 1253c40d7343Scindi } 1254c40d7343Scindi } 1255c40d7343Scindi 1256c40d7343Scindi if (pcnt > 0) 1257c40d7343Scindi get_pargs(argc, argv); 1258c40d7343Scindi 1259c40d7343Scindi if ((thp = topo_open(TOPO_VERSION, opt_R, &err)) == NULL) { 1260c40d7343Scindi (void) fprintf(stderr, "%s: failed to open topology tree: %s\n", 1261c40d7343Scindi g_pname, topo_strerror(err)); 1262c40d7343Scindi return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR)); 1263c40d7343Scindi } 1264c40d7343Scindi 1265c40d7343Scindi if (opt_d) 1266c40d7343Scindi topo_debug_set(thp, "module", "stderr"); 1267c40d7343Scindi 1268c40d7343Scindi if ((uuid = topo_snap_hold(thp, NULL, &err)) == NULL) { 1269c40d7343Scindi (void) fprintf(stderr, "%s: failed to snapshot topology: %s\n", 1270c40d7343Scindi g_pname, topo_strerror(err)); 1271c40d7343Scindi return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR)); 1272c40d7343Scindi } else if (err != 0) { 1273f6e214c7SGavin Maltby (void) fprintf(stderr, "%s: topology snapshot incomplete%s\n", 1274f6e214c7SGavin Maltby g_pname, getzoneid() != GLOBAL_ZONEID && 1275f6e214c7SGavin Maltby strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0 ? 1276f6e214c7SGavin Maltby " (" FM_FMRI_SCHEME_HC " scheme does not enumerate " 1277f6e214c7SGavin Maltby "in a non-global zone)": ""); 1278c40d7343Scindi } 1279c40d7343Scindi 1280c40d7343Scindi if (opt_x) { 128178432d5eScy152378 if (opt_b) { 128278432d5eScy152378 (void) fprintf(stderr, 128378432d5eScy152378 "%s: -b and -x cannot be specified together\n", 128478432d5eScy152378 g_pname); 128578432d5eScy152378 return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_USAGE)); 128678432d5eScy152378 } 128778432d5eScy152378 1288c40d7343Scindi err = 0; 1289c40d7343Scindi if (topo_xml_print(thp, stdout, opt_s, &err) < 0) 1290c40d7343Scindi (void) fprintf(stderr, "%s: failed to print xml " 1291c40d7343Scindi "formatted topology:%s", g_pname, 1292c40d7343Scindi topo_strerror(err)); 1293c40d7343Scindi 1294c40d7343Scindi return (fmtopo_exit(thp, uuid, err ? FMTOPO_EXIT_ERROR : 1295c40d7343Scindi FMTOPO_EXIT_SUCCESS)); 1296c40d7343Scindi } 1297c40d7343Scindi 1298c40d7343Scindi if (opt_t || walk_topo(thp, uuid) < 0) { 1299c40d7343Scindi if (g_fmri != NULL) 1300c40d7343Scindi /* 1301c40d7343Scindi * Try getting some useful information 1302c40d7343Scindi */ 1303c40d7343Scindi print_fmri(thp, uuid); 1304c40d7343Scindi 1305c40d7343Scindi return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR)); 1306c40d7343Scindi } 1307c40d7343Scindi 130812cc75c8Scindi return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_SUCCESS)); 13097aec1d6eScindi } 1310