xref: /onnv-gate/usr/src/cmd/fm/fmtopo/common/fmtopo.c (revision 12967:ab9ae749152f)
11414Scindi /*
21414Scindi  * CDDL HEADER START
31414Scindi  *
41414Scindi  * The contents of this file are subject to the terms of the
51414Scindi  * Common Development and Distribution License (the "License").
61414Scindi  * You may not use this file except in compliance with the License.
71414Scindi  *
81414Scindi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91414Scindi  * or http://www.opensolaris.org/os/licensing.
101414Scindi  * See the License for the specific language governing permissions
111414Scindi  * and limitations under the License.
121414Scindi  *
131414Scindi  * When distributing Covered Code, include this CDDL HEADER in each
141414Scindi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151414Scindi  * If applicable, add the following below this CDDL HEADER, with the
161414Scindi  * fields enclosed by brackets "[]" replaced with your own identifying
171414Scindi  * information: Portions Copyright [yyyy] [name of copyright owner]
181414Scindi  *
191414Scindi  * CDDL HEADER END
201414Scindi  */
211414Scindi 
221414Scindi /*
23*12967Sgavin.maltby@oracle.com  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
241414Scindi  */
251414Scindi 
261414Scindi 
271414Scindi #include <sys/fm/protocol.h>
281414Scindi #include <fm/libtopo.h>
293062Scindi #include <ctype.h>
304087Scindi #include <fnmatch.h>
311414Scindi #include <limits.h>
321414Scindi #include <strings.h>
331414Scindi #include <stdio.h>
341414Scindi #include <errno.h>
354087Scindi #include <umem.h>
36*12967Sgavin.maltby@oracle.com #include <zone.h>
373062Scindi #include <sys/param.h>
381414Scindi 
391414Scindi #define	FMTOPO_EXIT_SUCCESS	0
401414Scindi #define	FMTOPO_EXIT_ERROR	1
411414Scindi #define	FMTOPO_EXIT_USAGE	2
421414Scindi 
433062Scindi #define	STDERR	"stderr"
443062Scindi #define	DOTS	"..."
453062Scindi #define	ALL	"all"
463062Scindi 
471414Scindi static const char *g_pname;
484087Scindi static const char *g_fmri = NULL;
491414Scindi 
501414Scindi static const char *opt_R = "/";
511414Scindi static const char *opt_s = FM_FMRI_SCHEME_HC;
529501SRobert.Johnston@Sun.COM static const char optstr[] = "bCdem:P:pR:s:StVx";
539501SRobert.Johnston@Sun.COM static const char *opt_m;
541414Scindi 
556341Scy152378 static int opt_b = 0;
566341Scy152378 static int opt_d = 0;
573062Scindi static int opt_e = 0;
583062Scindi static int opt_p = 0;
594087Scindi static int opt_S = 0;
604087Scindi static int opt_t = 0;
616341Scy152378 static int opt_V = 0;
623062Scindi static int opt_x = 0;
634087Scindi static int opt_all = 0;
644087Scindi 
654087Scindi struct prop_args {
664087Scindi 	const char *group;
674087Scindi 	const char *prop;
684087Scindi 	const char *type;
694087Scindi 	const char *value;
704087Scindi };
714087Scindi 
724087Scindi static struct prop_args **pargs = NULL;
734087Scindi static int pcnt = 0;
741414Scindi 
751414Scindi static int
usage(FILE * fp)761414Scindi usage(FILE *fp)
771414Scindi {
781414Scindi 	(void) fprintf(fp,
797585SRobert.Johnston@Sun.COM 	    "Usage: %s [-bCedpSVx] [-P group.property[=type:value]] "
809501SRobert.Johnston@Sun.COM 	    "[-R root] [-m method] [-s scheme] [fmri]\n", g_pname);
811414Scindi 
821414Scindi 	(void) fprintf(fp,
836341Scy152378 	    "\t-b  walk in sibling-first order (default is child-first)\n"
841414Scindi 	    "\t-C  dump core after completing execution\n"
853062Scindi 	    "\t-d  set debug mode for libtopo modules\n"
863062Scindi 	    "\t-e  display FMRIs as paths using esc/eft notation\n"
879501SRobert.Johnston@Sun.COM 	    "\t-m  execute given method\n"
884087Scindi 	    "\t-P  get/set specified properties\n"
893062Scindi 	    "\t-p  display of FMRI protocol properties\n"
901414Scindi 	    "\t-R  set root directory for libtopo plug-ins and other files\n"
911414Scindi 	    "\t-s  display topology for the specified FMRI scheme\n"
924087Scindi 	    "\t-S  display FMRI status (present/usable)\n"
933062Scindi 	    "\t-V  set verbose mode\n"
943062Scindi 	    "\t-x  display a xml formatted topology\n");
951414Scindi 
961414Scindi 	return (FMTOPO_EXIT_USAGE);
971414Scindi }
981414Scindi 
994087Scindi static topo_type_t
str2type(const char * tstr)1004087Scindi str2type(const char *tstr)
1011414Scindi {
1024087Scindi 	topo_type_t type;
1034087Scindi 
1044087Scindi 	if (tstr == NULL)
1054087Scindi 		return (TOPO_TYPE_INVALID);
1061414Scindi 
1074087Scindi 	if (strcmp(tstr, "int32") == 0)
1084087Scindi 		type = TOPO_TYPE_INT32;
1094087Scindi 	else if (strcmp(tstr, "uint32") == 0)
1104087Scindi 		type = TOPO_TYPE_UINT32;
1114087Scindi 	else if (strcmp(tstr, "int64") == 0)
1124087Scindi 		type = TOPO_TYPE_INT64;
1134087Scindi 	else if (strcmp(tstr, "uint64") == 0)
1144087Scindi 		type = TOPO_TYPE_UINT64;
1154087Scindi 	else if (strcmp(tstr, "string") == 0)
1164087Scindi 		type = TOPO_TYPE_STRING;
1174087Scindi 	else if (strcmp(tstr, "fmri") == 0)
1184087Scindi 		type = TOPO_TYPE_FMRI;
1194087Scindi 	else {
1204087Scindi 		type = TOPO_TYPE_INVALID;
1211414Scindi 	}
1221414Scindi 
1234087Scindi 	return (type);
1244087Scindi }
1251414Scindi 
1264087Scindi static void
print_node(topo_hdl_t * thp,tnode_t * node,nvlist_t * nvl,const char * fmri)1274087Scindi print_node(topo_hdl_t *thp, tnode_t *node, nvlist_t *nvl, const char *fmri)
1284087Scindi {
1294087Scindi 	int err, ret;
1301414Scindi 
1314087Scindi 	(void) printf("%s\n", (char *)fmri);
1324087Scindi 
1334087Scindi 	if (opt_p && !(pcnt > 0 || opt_V || opt_all)) {
1341414Scindi 		char *aname = NULL, *fname = NULL, *lname = NULL;
1351414Scindi 		nvlist_t *asru = NULL;
1361414Scindi 		nvlist_t *fru = NULL;
1371414Scindi 
1381414Scindi 		if (topo_node_asru(node, &asru, NULL, &err) == 0)
1394328Scindi 			(void) topo_fmri_nvl2str(thp, asru, &aname, &err);
1401414Scindi 		if (topo_node_fru(node, &fru, NULL, &err) == 0)
1414328Scindi 			(void) topo_fmri_nvl2str(thp, fru, &fname, &err);
1421414Scindi 		(void) topo_node_label(node, &lname, &err);
1431414Scindi 		if (aname != NULL) {
1441414Scindi 			nvlist_free(asru);
1451414Scindi 			(void) printf("\tASRU: %s\n", aname);
1461414Scindi 			topo_hdl_strfree(thp, aname);
1471414Scindi 		} else {
1481414Scindi 			(void) printf("\tASRU: -\n");
1491414Scindi 		}
1501414Scindi 		if (fname != NULL) {
1511414Scindi 			nvlist_free(fru);
1521414Scindi 			(void) printf("\tFRU: %s\n", fname);
1531414Scindi 			topo_hdl_strfree(thp, fname);
1541414Scindi 		} else {
1551414Scindi 			(void) printf("\tFRU: -\n");
1561414Scindi 		}
1571414Scindi 		if (lname != NULL) {
1581414Scindi 			(void) printf("\tLabel: %s\n", lname);
1591414Scindi 			topo_hdl_strfree(thp, lname);
1601414Scindi 		} else {
1611414Scindi 			(void) printf("\tLabel: -\n");
1621414Scindi 		}
1631414Scindi 	}
1641414Scindi 
1654087Scindi 	if (opt_S) {
1664087Scindi 		if ((ret = topo_fmri_present(thp, nvl, &err)) < 0)
1674087Scindi 			(void) printf("\tPresent: -\n");
1684087Scindi 		else
1694087Scindi 			(void) printf("\tPresent: %s\n",
1704087Scindi 			    ret ? "true" : "false");
1714087Scindi 
1724087Scindi 		if ((ret = topo_fmri_unusable(thp, nvl, &err)) < 0)
1734087Scindi 			(void) printf("\tUnusable: -\n");
1744087Scindi 		else
1754087Scindi 			(void) printf("\tUnusable: %s\n",
1764087Scindi 			    ret ? "true" : "false");
1774087Scindi 	}
1781414Scindi }
1791414Scindi 
1801414Scindi static void
print_everstyle(tnode_t * node)1811414Scindi print_everstyle(tnode_t *node)
1821414Scindi {
1831414Scindi 	char buf[PATH_MAX], numbuf[64];
1841414Scindi 	nvlist_t *fmri, **hcl;
1851414Scindi 	int i, err;
1861414Scindi 	uint_t n;
1871414Scindi 
1881414Scindi 	if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL,
1891414Scindi 	    TOPO_PROP_RESOURCE, &fmri, &err) < 0) {
1901414Scindi 		(void) fprintf(stderr, "%s: failed to get fmri for %s=%d: %s\n",
1911414Scindi 		    g_pname, topo_node_name(node),
1921414Scindi 		    topo_node_instance(node), topo_strerror(err));
1931414Scindi 		return;
1941414Scindi 	}
1951414Scindi 
1961414Scindi 	if (nvlist_lookup_nvlist_array(fmri, FM_FMRI_HC_LIST, &hcl, &n) != 0) {
1971414Scindi 		(void) fprintf(stderr, "%s: failed to find %s for %s=%d\n",
1981414Scindi 		    g_pname, FM_FMRI_HC_LIST, topo_node_name(node),
1991414Scindi 		    topo_node_instance(node));
2007243Srobj 		nvlist_free(fmri);
2011414Scindi 		return;
2021414Scindi 	}
2031414Scindi 
2041414Scindi 	buf[0] = '\0';
2051414Scindi 
2061414Scindi 	for (i = 0; i < n; i++) {
2071414Scindi 		char *name, *inst, *estr;
2081414Scindi 		ulong_t ul;
2091414Scindi 
2101414Scindi 		if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name) != 0 ||
2111414Scindi 		    nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &inst) != 0) {
2121414Scindi 			(void) fprintf(stderr, "%s: failed to get "
2131414Scindi 			    "name-instance for %s=%d\n", g_pname,
2141414Scindi 			    topo_node_name(node), topo_node_instance(node));
2157243Srobj 			nvlist_free(fmri);
2161414Scindi 			return;
2171414Scindi 		}
2181414Scindi 
2191414Scindi 		errno = 0;
2201414Scindi 		ul = strtoul(inst, &estr, 10);
2211414Scindi 
2221414Scindi 		if (errno != 0 || estr == inst) {
2231414Scindi 			(void) fprintf(stderr, "%s: instance %s does not "
2241414Scindi 			    "convert to an unsigned integer\n", g_pname, inst);
2251414Scindi 		}
2261414Scindi 
2271414Scindi 		(void) strlcat(buf, "/", sizeof (buf));
2281414Scindi 		(void) strlcat(buf, name, sizeof (buf));
2291414Scindi 		(void) snprintf(numbuf, sizeof (numbuf), "%u", ul);
2301414Scindi 		(void) strlcat(buf, numbuf, sizeof (buf));
2311414Scindi 	}
2327243Srobj 	nvlist_free(fmri);
2331414Scindi 
2341414Scindi 	(void) printf("%s\n", buf);
2351414Scindi }
2361414Scindi 
2373062Scindi static void
print_prop_nameval(topo_hdl_t * thp,tnode_t * node,nvlist_t * nvl)2387243Srobj print_prop_nameval(topo_hdl_t *thp, tnode_t *node, nvlist_t *nvl)
2393062Scindi {
2403062Scindi 	int err;
2413062Scindi 	topo_type_t type;
2427243Srobj 	char *tstr, *propn, buf[48], *factype;
2433062Scindi 	nvpair_t *pv_nvp;
2443323Scindi 	int i;
2453323Scindi 	uint_t nelem;
2463062Scindi 
2473062Scindi 	if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL)
2483062Scindi 		return;
2493062Scindi 
2503062Scindi 	/* Print property name */
2513062Scindi 	if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL ||
2523062Scindi 	    nvpair_name(pv_nvp) == NULL ||
2533062Scindi 	    strcmp(TOPO_PROP_VAL_NAME, nvpair_name(pv_nvp)) != 0) {
2543062Scindi 		(void) fprintf(stderr, "%s: malformed property name\n",
2553062Scindi 		    g_pname);
2563062Scindi 		return;
2573062Scindi 	} else {
2584328Scindi 		(void) nvpair_value_string(pv_nvp, &propn);
2593062Scindi 	}
2603062Scindi 
2613062Scindi 	if ((pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL ||
2623062Scindi 	    nvpair_name(pv_nvp) == NULL ||
2633062Scindi 	    strcmp(nvpair_name(pv_nvp), TOPO_PROP_VAL_TYPE) != 0 ||
2644087Scindi 	    nvpair_type(pv_nvp) != DATA_TYPE_UINT32)  {
2653062Scindi 		(void) fprintf(stderr, "%s: malformed property type for %s\n",
2663062Scindi 		    g_pname, propn);
2673062Scindi 		return;
2683062Scindi 	} else {
2694087Scindi 		(void) nvpair_value_uint32(pv_nvp, (uint32_t *)&type);
2703062Scindi 	}
2713062Scindi 
2723062Scindi 	switch (type) {
2733062Scindi 		case TOPO_TYPE_BOOLEAN: tstr = "boolean"; break;
2743062Scindi 		case TOPO_TYPE_INT32: tstr = "int32"; break;
2753062Scindi 		case TOPO_TYPE_UINT32: tstr = "uint32"; break;
2763062Scindi 		case TOPO_TYPE_INT64: tstr = "int64"; break;
2773062Scindi 		case TOPO_TYPE_UINT64: tstr = "uint64"; break;
2787243Srobj 		case TOPO_TYPE_DOUBLE: tstr = "double"; break;
2793062Scindi 		case TOPO_TYPE_STRING: tstr = "string"; break;
2803062Scindi 		case TOPO_TYPE_FMRI: tstr = "fmri"; break;
2813062Scindi 		case TOPO_TYPE_INT32_ARRAY: tstr = "int32[]"; break;
2823062Scindi 		case TOPO_TYPE_UINT32_ARRAY: tstr = "uint32[]"; break;
2833062Scindi 		case TOPO_TYPE_INT64_ARRAY: tstr = "int64[]"; break;
2843062Scindi 		case TOPO_TYPE_UINT64_ARRAY: tstr = "uint64[]"; break;
2853062Scindi 		case TOPO_TYPE_STRING_ARRAY: tstr = "string[]"; break;
2863062Scindi 		case TOPO_TYPE_FMRI_ARRAY: tstr = "fmri[]"; break;
2873062Scindi 		default: tstr = "unknown type";
2883062Scindi 	}
2893062Scindi 
29011050SRobert.Johnston@Sun.COM 	(void) printf("    %-17s %-8s ", propn, tstr);
2913062Scindi 
2923062Scindi 	/*
2933062Scindi 	 * Get property value
2943062Scindi 	 */
2953062Scindi 	if (nvpair_name(pv_nvp) == NULL ||
2963062Scindi 	    (pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL) {
2973062Scindi 		(void) fprintf(stderr, "%s: malformed property value\n",
2983062Scindi 		    g_pname);
2993062Scindi 		return;
3003062Scindi 	}
3013062Scindi 
3023062Scindi 	switch (nvpair_type(pv_nvp)) {
3033062Scindi 		case DATA_TYPE_INT32: {
3043062Scindi 			int32_t val;
3053062Scindi 			(void) nvpair_value_int32(pv_nvp, &val);
3063062Scindi 			(void) printf(" %d", val);
3073062Scindi 			break;
3083062Scindi 		}
3093062Scindi 		case DATA_TYPE_UINT32: {
3107243Srobj 			uint32_t val, type;
3117243Srobj 			char val_str[49];
3127243Srobj 			nvlist_t *fac, *rsrc = NULL;
3137243Srobj 
3143062Scindi 			(void) nvpair_value_uint32(pv_nvp, &val);
3157243Srobj 			if (node == NULL || topo_node_flags(node) !=
3167243Srobj 			    TOPO_NODE_FACILITY)
3177243Srobj 				goto uint32_def;
3187243Srobj 
3197243Srobj 			if (topo_node_resource(node, &rsrc, &err) != 0)
3207243Srobj 				goto uint32_def;
3217243Srobj 
3227243Srobj 			if (nvlist_lookup_nvlist(rsrc, "facility", &fac) != 0)
3237243Srobj 				goto uint32_def;
3247243Srobj 
3257243Srobj 			if (nvlist_lookup_string(fac, FM_FMRI_FACILITY_TYPE,
3267243Srobj 			    &factype) != 0)
3277243Srobj 				goto uint32_def;
3287243Srobj 
3297243Srobj 			nvlist_free(rsrc);
3307243Srobj 			rsrc = NULL;
3317243Srobj 
3327243Srobj 			/*
3337243Srobj 			 * Special case code to do friendlier printing of
3347243Srobj 			 * facility node properties
3357243Srobj 			 */
3367243Srobj 			if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) &&
3377243Srobj 			    (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) {
3387243Srobj 				topo_sensor_type_name(val, val_str, 48);
3397243Srobj 				(void) printf(" 0x%x (%s)", val, val_str);
3407243Srobj 				break;
3417243Srobj 			} else if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) &&
3427243Srobj 			    (strcmp(factype, TOPO_FAC_TYPE_INDICATOR) == 0)) {
3437243Srobj 				topo_led_type_name(val, val_str, 48);
3447243Srobj 				(void) printf(" 0x%x (%s)", val, val_str);
3457243Srobj 				break;
3467243Srobj 			} else if (strcmp(propn, TOPO_SENSOR_UNITS) == 0) {
3477243Srobj 				topo_sensor_units_name(val, val_str, 48);
3487243Srobj 				(void) printf(" 0x%x (%s)", val, val_str);
3497243Srobj 				break;
3507243Srobj 			} else if (strcmp(propn, TOPO_LED_MODE) == 0) {
3517243Srobj 				topo_led_state_name(val, val_str, 48);
3527243Srobj 				(void) printf(" 0x%x (%s)", val, val_str);
3537243Srobj 				break;
3547243Srobj 			} else if ((strcmp(propn, TOPO_SENSOR_STATE) == 0) &&
3557243Srobj 			    (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) {
3567243Srobj 				if (topo_prop_get_uint32(node,
3577243Srobj 				    TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE,
3587243Srobj 				    &type, &err) != 0) {
3597243Srobj 					goto uint32_def;
3607243Srobj 				}
3617243Srobj 				topo_sensor_state_name(type, val, val_str, 48);
3627243Srobj 				(void) printf(" 0x%x (%s)", val, val_str);
3637243Srobj 				break;
3647243Srobj 			}
3657243Srobj uint32_def:
3663062Scindi 			(void) printf(" 0x%x", val);
3677243Srobj 			if (rsrc != NULL)
3687243Srobj 				nvlist_free(rsrc);
3693062Scindi 			break;
3703062Scindi 		}
3713062Scindi 		case DATA_TYPE_INT64: {
3723062Scindi 			int64_t val;
3733062Scindi 			(void) nvpair_value_int64(pv_nvp, &val);
3743062Scindi 			(void) printf(" %lld", (longlong_t)val);
3753062Scindi 			break;
3763062Scindi 		}
3773062Scindi 		case DATA_TYPE_UINT64: {
3783062Scindi 			uint64_t val;
3793062Scindi 			(void) nvpair_value_uint64(pv_nvp, &val);
3803062Scindi 			(void) printf(" 0x%llx", (u_longlong_t)val);
3813062Scindi 			break;
3823062Scindi 		}
3837243Srobj 		case DATA_TYPE_DOUBLE: {
3847243Srobj 			double val;
3857243Srobj 			(void) nvpair_value_double(pv_nvp, &val);
3867243Srobj 			(void) printf(" %lf", (double)val);
3877243Srobj 			break;
3887243Srobj 		}
3893062Scindi 		case DATA_TYPE_STRING: {
3903062Scindi 			char *val;
3913062Scindi 			(void) nvpair_value_string(pv_nvp, &val);
3923062Scindi 			if (!opt_V && strlen(val) > 48) {
3933062Scindi 				(void) snprintf(buf, 48, "%s...", val);
3943062Scindi 				(void) printf(" %s", buf);
3953062Scindi 			} else {
3963062Scindi 				(void) printf(" %s", val);
3973062Scindi 			}
3983062Scindi 			break;
3993062Scindi 		}
4003062Scindi 		case DATA_TYPE_NVLIST: {
4013062Scindi 			nvlist_t *val;
4023062Scindi 			char *fmri;
4033062Scindi 			(void) nvpair_value_nvlist(pv_nvp, &val);
4043062Scindi 			if (topo_fmri_nvl2str(thp, val, &fmri, &err) != 0) {
4053062Scindi 				if (opt_V)
4063062Scindi 					nvlist_print(stdout, nvl);
4073062Scindi 				break;
4083062Scindi 			}
4093062Scindi 
4103062Scindi 			if (!opt_V && strlen(fmri) > 48) {
4113062Scindi 				(void) snprintf(buf, 48, "%s", fmri);
4123062Scindi 				(void) snprintf(&buf[45], 4, "%s", DOTS);
4133062Scindi 				(void) printf(" %s", buf);
4143062Scindi 			} else {
4153062Scindi 				(void) printf(" %s", fmri);
4163062Scindi 			}
4173062Scindi 
4183062Scindi 			topo_hdl_strfree(thp, fmri);
4193062Scindi 			break;
4203062Scindi 		}
42110234SRobert.Johnston@Sun.COM 		case DATA_TYPE_INT32_ARRAY: {
42210234SRobert.Johnston@Sun.COM 			int32_t *val;
42310234SRobert.Johnston@Sun.COM 
42410234SRobert.Johnston@Sun.COM 			(void) nvpair_value_int32_array(pv_nvp, &val, &nelem);
42510234SRobert.Johnston@Sun.COM 			(void) printf(" [ ");
42610234SRobert.Johnston@Sun.COM 			for (i = 0; i < nelem; i++)
42710234SRobert.Johnston@Sun.COM 				(void) printf("%d ", val[i]);
42810234SRobert.Johnston@Sun.COM 			(void) printf("]");
42910234SRobert.Johnston@Sun.COM 			break;
43010234SRobert.Johnston@Sun.COM 		}
4313323Scindi 		case DATA_TYPE_UINT32_ARRAY: {
4323323Scindi 			uint32_t *val;
4333323Scindi 
4343323Scindi 			(void) nvpair_value_uint32_array(pv_nvp, &val, &nelem);
4353323Scindi 			(void) printf(" [ ");
4363323Scindi 			for (i = 0; i < nelem; i++)
4373323Scindi 				(void) printf("%u ", val[i]);
4383323Scindi 			(void) printf("]");
4393323Scindi 			break;
4403323Scindi 		}
4417243Srobj 		case DATA_TYPE_INT64_ARRAY: {
4427243Srobj 			int64_t *val;
4437243Srobj 
4447243Srobj 			(void) nvpair_value_int64_array(pv_nvp, &val, &nelem);
4457243Srobj 			(void) printf(" [ ");
4467243Srobj 			for (i = 0; i < nelem; i++)
4477243Srobj 				(void) printf("%lld ", val[i]);
4487243Srobj 			(void) printf("]");
4497243Srobj 			break;
4507243Srobj 		}
45110234SRobert.Johnston@Sun.COM 		case DATA_TYPE_UINT64_ARRAY: {
45210234SRobert.Johnston@Sun.COM 			uint64_t *val;
45310234SRobert.Johnston@Sun.COM 
45410234SRobert.Johnston@Sun.COM 			(void) nvpair_value_uint64_array(pv_nvp, &val, &nelem);
45510234SRobert.Johnston@Sun.COM 			(void) printf(" [ ");
45610234SRobert.Johnston@Sun.COM 			for (i = 0; i < nelem; i++)
45710234SRobert.Johnston@Sun.COM 				(void) printf("%llu ", val[i]);
45810234SRobert.Johnston@Sun.COM 			(void) printf("]");
45910234SRobert.Johnston@Sun.COM 			break;
46010234SRobert.Johnston@Sun.COM 		}
4616640Scth 		case DATA_TYPE_STRING_ARRAY: {
4626640Scth 			char **val;
4636640Scth 
4646640Scth 			(void) nvpair_value_string_array(pv_nvp, &val, &nelem);
4656640Scth 			(void) printf(" [ ");
4666640Scth 			for (i = 0; i < nelem; i++)
46710234SRobert.Johnston@Sun.COM 				(void) printf("\"%s\" ", val[i]);
4686640Scth 			(void) printf("]");
4696640Scth 			break;
4706640Scth 		}
4713062Scindi 		default:
4723062Scindi 			(void) fprintf(stderr, " unknown data type (%d)",
4733062Scindi 			    nvpair_type(pv_nvp));
4743062Scindi 			break;
4753062Scindi 		}
4763062Scindi 		(void) printf("\n");
4773062Scindi }
4783062Scindi 
4793062Scindi static void
print_pgroup(topo_hdl_t * thp,tnode_t * node,const char * pgn,char * dstab,char * nstab,int32_t version)4804087Scindi print_pgroup(topo_hdl_t *thp, tnode_t *node, const char *pgn, char *dstab,
4814087Scindi     char *nstab, int32_t version)
4823062Scindi {
4834087Scindi 	int err;
4843062Scindi 	char buf[30];
4854087Scindi 	topo_pgroup_info_t *pgi = NULL;
4863062Scindi 
4874087Scindi 	if (pgn == NULL)
4883062Scindi 		return;
4893062Scindi 
4904087Scindi 	if (node != NULL && (dstab == NULL || nstab == NULL || version == -1)) {
4914087Scindi 		if ((pgi = topo_pgroup_info(node, pgn, &err)) != NULL) {
4924087Scindi 			dstab = (char *)topo_stability2name(pgi->tpi_datastab);
4934087Scindi 			nstab = (char *)topo_stability2name(pgi->tpi_namestab);
4944087Scindi 			version = pgi->tpi_version;
4954087Scindi 		}
4964087Scindi 	}
4974087Scindi 
4984087Scindi 	if (dstab == NULL || nstab == NULL || version == -1) {
49911050SRobert.Johnston@Sun.COM 		(void) printf("  group: %-30s version: - stability: -/-\n",
50011050SRobert.Johnston@Sun.COM 		    pgn);
5014087Scindi 	} else if (!opt_V && strlen(pgn) > 30) {
5023062Scindi 		(void) snprintf(buf, 26, "%s", pgn);
5033062Scindi 		(void) snprintf(&buf[27], 4, "%s", DOTS);
50411050SRobert.Johnston@Sun.COM 		(void) printf("  group: %-30s version: %-3d stability: %s/%s\n",
5053062Scindi 		    buf, version, nstab, dstab);
5063062Scindi 	} else {
50711050SRobert.Johnston@Sun.COM 		(void) printf("  group: %-30s version: %-3d stability: %s/%s\n",
5083062Scindi 		    pgn, version, nstab, dstab);
5093062Scindi 	}
5103062Scindi 
5114087Scindi 	if (pgi != NULL) {
5124087Scindi 		topo_hdl_strfree(thp, (char *)pgi->tpi_name);
5134087Scindi 		topo_hdl_free(thp, pgi, sizeof (topo_pgroup_info_t));
5143062Scindi 	}
5153062Scindi }
5163062Scindi 
5173062Scindi static void
print_all_props(topo_hdl_t * thp,tnode_t * node,nvlist_t * p_nv,const char * group)5184087Scindi print_all_props(topo_hdl_t *thp, tnode_t *node, nvlist_t *p_nv,
5194087Scindi     const char *group)
5203062Scindi {
5213062Scindi 	char *pgn = NULL, *dstab = NULL, *nstab = NULL;
5224087Scindi 	int32_t version;
5233062Scindi 	nvlist_t *pg_nv, *pv_nv;
5243062Scindi 	nvpair_t *nvp, *pg_nvp;
5254087Scindi 	int pg_done, match, all = strcmp(group, ALL) == 0;
5263062Scindi 
5273062Scindi 	for (nvp = nvlist_next_nvpair(p_nv, NULL); nvp != NULL;
5283062Scindi 	    nvp = nvlist_next_nvpair(p_nv, nvp)) {
5293062Scindi 		if (strcmp(TOPO_PROP_GROUP, nvpair_name(nvp)) != 0 ||
5303062Scindi 		    nvpair_type(nvp) != DATA_TYPE_NVLIST)
5313062Scindi 			continue;
5323062Scindi 
5334087Scindi 		nstab = NULL;
5344087Scindi 		dstab = NULL;
5354087Scindi 		version = -1;
5364087Scindi 		pg_done = match = 0;
5373062Scindi 		(void) nvpair_value_nvlist(nvp, &pg_nv);
5383062Scindi 		for (pg_nvp = nvlist_next_nvpair(pg_nv, NULL); pg_nvp != NULL;
5393062Scindi 		    pg_nvp = nvlist_next_nvpair(pg_nv, pg_nvp)) {
5403062Scindi 			/*
5413062Scindi 			 * Print property group name and stability levels
5423062Scindi 			 */
5433062Scindi 			if (strcmp(TOPO_PROP_GROUP_NAME, nvpair_name(pg_nvp))
5443062Scindi 			    == 0 && nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
5453062Scindi 				(void) nvpair_value_string(pg_nvp, &pgn);
5464087Scindi 				match = strcmp(group, pgn) == 0;
5474087Scindi 				continue;
5484087Scindi 			}
5493062Scindi 
5504087Scindi 			if (strcmp(TOPO_PROP_GROUP_NSTAB,
5513062Scindi 			    nvpair_name(pg_nvp)) == 0 &&
5523062Scindi 			    nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
5533062Scindi 				(void) nvpair_value_string(pg_nvp, &nstab);
5544087Scindi 				continue;
5554087Scindi 			}
5564087Scindi 
5574087Scindi 			if (strcmp(TOPO_PROP_GROUP_DSTAB,
5583062Scindi 			    nvpair_name(pg_nvp)) == 0 &&
5593062Scindi 			    nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
5603062Scindi 				(void) nvpair_value_string(pg_nvp, &dstab);
5614087Scindi 				continue;
5624087Scindi 			}
5634087Scindi 
5644087Scindi 			if (strcmp(TOPO_PROP_GROUP_VERSION,
5653062Scindi 			    nvpair_name(pg_nvp)) == 0 &&
5663062Scindi 			    nvpair_type(pg_nvp) == DATA_TYPE_INT32) {
5673062Scindi 				(void) nvpair_value_int32(pg_nvp, &version);
5684087Scindi 				continue;
5694087Scindi 			}
5704087Scindi 
5714087Scindi 			if ((match || all) && !pg_done) {
5724087Scindi 				print_pgroup(thp, node, pgn, dstab, nstab,
5734087Scindi 				    version);
5744087Scindi 				pg_done++;
5754087Scindi 			}
5764087Scindi 
5774087Scindi 			/*
5784087Scindi 			 * Print property group and property name-value pair
5794087Scindi 			 */
5804087Scindi 			if (strcmp(TOPO_PROP_VAL, nvpair_name(pg_nvp))
5814087Scindi 			    == 0 && nvpair_type(pg_nvp) == DATA_TYPE_NVLIST) {
5824087Scindi 				(void) nvpair_value_nvlist(pg_nvp, &pv_nv);
5834087Scindi 				if ((match || all) && pg_done) {
5847243Srobj 					print_prop_nameval(thp, node, pv_nv);
5854087Scindi 				}
5864087Scindi 
5873062Scindi 			}
5883062Scindi 
5894087Scindi 		}
5904087Scindi 		if (match && !all)
5914087Scindi 			return;
5924087Scindi 	}
5934087Scindi }
5944087Scindi 
5954087Scindi static void
set_prop(topo_hdl_t * thp,tnode_t * node,nvlist_t * fmri,struct prop_args * pp)5964087Scindi set_prop(topo_hdl_t *thp, tnode_t *node, nvlist_t *fmri, struct prop_args *pp)
5974087Scindi {
5984087Scindi 	int ret, err = 0;
5994087Scindi 	topo_type_t type;
6004087Scindi 	nvlist_t *nvl, *f = NULL;
6014087Scindi 	char *end;
6024087Scindi 
6034087Scindi 	if (pp->prop == NULL || pp->type == NULL || pp->value == NULL)
6044087Scindi 		return;
6054087Scindi 
6064087Scindi 	if ((type = str2type(pp->type)) == TOPO_TYPE_INVALID) {
6074087Scindi 		(void) fprintf(stderr, "%s: invalid property type %s for %s\n",
6084087Scindi 		    g_pname, pp->type, pp->prop);
6094087Scindi 		return;
6104087Scindi 	}
6114087Scindi 
6124087Scindi 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
6134087Scindi 		(void) fprintf(stderr, "%s: nvlist allocation failed for "
6144087Scindi 		    "%s=%s:%s\n", g_pname, pp->prop, pp->type, pp->value);
6154087Scindi 		return;
6164087Scindi 	}
6174087Scindi 	ret = nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, pp->prop);
6184087Scindi 	ret |= nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, type);
6194087Scindi 	if (ret != 0) {
6204087Scindi 		(void) fprintf(stderr, "%s: invalid property type %s for %s\n",
6214087Scindi 		    g_pname, pp->type, pp->prop);
6224087Scindi 		nvlist_free(nvl);
6234087Scindi 		return;
6244087Scindi 	}
6254087Scindi 
6264087Scindi 	errno = 0;
6274087Scindi 	switch (type) {
6284087Scindi 		case TOPO_TYPE_INT32:
6294087Scindi 		{
6304087Scindi 			int32_t val;
6314087Scindi 
6324087Scindi 			val = strtol(pp->value, &end, 0);
6334087Scindi 			if (errno == ERANGE) {
6344087Scindi 				ret = -1;
6354087Scindi 				break;
6364087Scindi 			}
6374087Scindi 			ret = nvlist_add_int32(nvl, TOPO_PROP_VAL_VAL, val);
6384087Scindi 			break;
6394087Scindi 		}
6404087Scindi 		case TOPO_TYPE_UINT32:
6414087Scindi 		{
6424087Scindi 			uint32_t val;
6434087Scindi 
6444087Scindi 			val = strtoul(pp->value, &end, 0);
6454087Scindi 			if (errno == ERANGE) {
6464087Scindi 				ret = -1;
6474087Scindi 				break;
6484087Scindi 			}
6494087Scindi 			ret = nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, val);
6504087Scindi 			break;
6514087Scindi 		}
6524087Scindi 		case TOPO_TYPE_INT64:
6534087Scindi 		{
6544087Scindi 			int64_t val;
6554087Scindi 
6564087Scindi 			val = strtoll(pp->value, &end, 0);
6574087Scindi 			if (errno == ERANGE) {
6584087Scindi 				ret = -1;
6594087Scindi 				break;
6604087Scindi 			}
6614087Scindi 			ret = nvlist_add_int64(nvl, TOPO_PROP_VAL_VAL, val);
6624087Scindi 			break;
6634087Scindi 		}
6644087Scindi 		case TOPO_TYPE_UINT64:
6654087Scindi 		{
6664087Scindi 			uint64_t val;
6674087Scindi 
6684087Scindi 			val = strtoull(pp->value, &end, 0);
6694087Scindi 			if (errno == ERANGE) {
6704087Scindi 				ret = -1;
6714087Scindi 				break;
6724087Scindi 			}
6734087Scindi 			ret = nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL, val);
6744087Scindi 			break;
6754087Scindi 		}
6764087Scindi 		case TOPO_TYPE_STRING:
6774087Scindi 		{
6784087Scindi 			ret = nvlist_add_string(nvl, TOPO_PROP_VAL_VAL,
6794087Scindi 			    pp->value);
6804087Scindi 			break;
6814087Scindi 		}
6824087Scindi 		case TOPO_TYPE_FMRI:
6834087Scindi 		{
6844087Scindi 			if ((ret = topo_fmri_str2nvl(thp, pp->value, &f, &err))
6854087Scindi 			    < 0)
6864087Scindi 				break;
6874087Scindi 
6884087Scindi 			if ((ret = nvlist_add_nvlist(nvl, TOPO_PROP_VAL_VAL,
6894087Scindi 			    f)) != 0)
6904087Scindi 				err = ETOPO_PROP_NVL;
6914087Scindi 			break;
6924087Scindi 		}
6934087Scindi 		default:
6944087Scindi 			ret = -1;
6954087Scindi 	}
6964087Scindi 
6974087Scindi 	if (ret != 0) {
6984087Scindi 		(void) fprintf(stderr, "%s: unable to set property value for "
6994087Scindi 		    "%s: %s\n", g_pname, pp->prop,  topo_strerror(err));
7004087Scindi 		nvlist_free(nvl);
7014087Scindi 		return;
7024087Scindi 	}
7034087Scindi 
7044087Scindi 	if (node != NULL) {
7054087Scindi 		if (topo_prop_setprop(node, pp->group, nvl, TOPO_PROP_MUTABLE,
7064087Scindi 		    f, &ret) < 0) {
7074087Scindi 			(void) fprintf(stderr, "%s: unable to set property "
7084087Scindi 			    "value for " "%s=%s:%s: %s\n", g_pname, pp->prop,
7094087Scindi 			    pp->type, pp->value, topo_strerror(ret));
7104087Scindi 			nvlist_free(nvl);
7114087Scindi 			nvlist_free(f);
7124087Scindi 			return;
7134087Scindi 		}
7144087Scindi 	} else {
7154087Scindi 		if (topo_fmri_setprop(thp, fmri,  pp->group, nvl,
7164087Scindi 		    TOPO_PROP_MUTABLE, f, &ret) < 0) {
7174087Scindi 			(void) fprintf(stderr, "%s: unable to set property "
7184087Scindi 			    "value for " "%s=%s:%s: %s\n", g_pname, pp->prop,
7194087Scindi 			    pp->type, pp->value, topo_strerror(ret));
7204087Scindi 			nvlist_free(nvl);
7214087Scindi 			nvlist_free(f);
7224087Scindi 			return;
7234087Scindi 		}
7244087Scindi 	}
7254087Scindi 
7264087Scindi 	nvlist_free(nvl);
7274087Scindi 
7284087Scindi 	/*
7294087Scindi 	 * Now, get the property back for printing
7304087Scindi 	 */
7314087Scindi 	if (node != NULL) {
7324087Scindi 		if (topo_prop_getprop(node, pp->group, pp->prop, f, &nvl,
7334087Scindi 		    &err) < 0) {
7344087Scindi 			(void) fprintf(stderr, "%s: failed to get %s.%s: %s\n",
7354087Scindi 			    g_pname, pp->group, pp->prop, topo_strerror(err));
7364087Scindi 			nvlist_free(f);
7374087Scindi 			return;
7384087Scindi 		}
7394087Scindi 	} else {
7404087Scindi 		if (topo_fmri_getprop(thp, fmri, pp->group, pp->prop,
7414087Scindi 		    f, &nvl, &err) < 0) {
7424087Scindi 			(void) fprintf(stderr, "%s: failed to get %s.%s: %s\n",
7434087Scindi 			    g_pname, pp->group, pp->prop, topo_strerror(err));
7444087Scindi 			nvlist_free(f);
7454087Scindi 			return;
7464087Scindi 		}
7474087Scindi 	}
7484087Scindi 
7494087Scindi 	print_pgroup(thp, node, pp->group, NULL, NULL, 0);
7507243Srobj 	print_prop_nameval(thp, node, nvl);
7514087Scindi 	nvlist_free(nvl);
7524087Scindi 
7534087Scindi 	nvlist_free(f);
7544087Scindi }
7554087Scindi 
7564087Scindi static void
print_props(topo_hdl_t * thp,tnode_t * node)7574087Scindi print_props(topo_hdl_t *thp, tnode_t *node)
7584087Scindi {
7594087Scindi 	int i, err;
7604087Scindi 	nvlist_t *nvl;
7614087Scindi 	struct prop_args *pp;
7624087Scindi 
7634087Scindi 	if (pcnt == 0)
7644087Scindi 		return;
7654087Scindi 
7664087Scindi 	for (i = 0; i < pcnt; ++i) {
7674087Scindi 		pp = pargs[i];
7684087Scindi 
7694087Scindi 		if (pp->group == NULL)
7704087Scindi 			continue;
7714087Scindi 
7724087Scindi 		/*
7734087Scindi 		 * If we have a valid value, this is a request to
7744087Scindi 		 * set a property.  Otherwise, just print the property
7754087Scindi 		 * group and any specified properties.
7764087Scindi 		 */
7774087Scindi 		if (pp->value == NULL) {
7784087Scindi 			if (pp->prop == NULL) {
7794087Scindi 
7804087Scindi 				/*
7814087Scindi 				 * Print all properties in this group
7824087Scindi 				 */
7834087Scindi 				if ((nvl = topo_prop_getprops(node, &err))
7844087Scindi 				    == NULL) {
7854087Scindi 					(void) fprintf(stderr, "%s: failed to "
7864087Scindi 					    "get %s: %s\n", g_pname,
7874087Scindi 					    pp->group,
7884087Scindi 					    topo_strerror(err));
7894087Scindi 					continue;
7903062Scindi 				} else {
7914087Scindi 					print_all_props(thp, node, nvl,
7924087Scindi 					    pp->group);
7934087Scindi 					nvlist_free(nvl);
7943062Scindi 					continue;
7953062Scindi 				}
7963062Scindi 			}
7974087Scindi 			if (topo_prop_getprop(node, pp->group, pp->prop,
7984087Scindi 			    NULL, &nvl, &err) < 0) {
7994087Scindi 				(void) fprintf(stderr, "%s: failed to get "
8004087Scindi 				    "%s.%s: %s\n", g_pname,
8014087Scindi 				    pp->group, pp->prop,
8024087Scindi 				    topo_strerror(err));
8034087Scindi 				continue;
8044087Scindi 			} else {
8054087Scindi 				print_pgroup(thp, node, pp->group, NULL,
8064087Scindi 				    NULL, 0);
8077243Srobj 				print_prop_nameval(thp, node, nvl);
8084087Scindi 				nvlist_free(nvl);
8094087Scindi 			}
8104087Scindi 		} else {
8114087Scindi 			set_prop(thp, node, NULL, pp);
8123062Scindi 		}
8133062Scindi 	}
8143062Scindi }
8153062Scindi 
8161414Scindi /*ARGSUSED*/
8171414Scindi static int
walk_node(topo_hdl_t * thp,tnode_t * node,void * arg)8184087Scindi walk_node(topo_hdl_t *thp, tnode_t *node, void *arg)
8191414Scindi {
8203062Scindi 	int err;
8213062Scindi 	nvlist_t *nvl;
8229501SRobert.Johnston@Sun.COM 	nvlist_t *rsrc, *out;
8234087Scindi 	char *s;
8243062Scindi 
8253062Scindi 	if (opt_e && strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0) {
8261414Scindi 		print_everstyle(node);
8273062Scindi 		return (TOPO_WALK_NEXT);
8283062Scindi 	}
8291414Scindi 
8304087Scindi 	if (topo_node_resource(node, &rsrc, &err) < 0) {
8314087Scindi 		(void) fprintf(stderr, "%s: failed to get resource: "
8324087Scindi 		    "%s", g_pname, topo_strerror(err));
8334087Scindi 		return (TOPO_WALK_NEXT);
8344087Scindi 	}
8354087Scindi 	if (topo_fmri_nvl2str(thp, rsrc, &s, &err) < 0) {
8364087Scindi 		(void) fprintf(stderr, "%s: failed to convert "
8374087Scindi 		    "resource to FMRI string: %s", g_pname,
8384087Scindi 		    topo_strerror(err));
8394087Scindi 		nvlist_free(rsrc);
8404087Scindi 		return (TOPO_WALK_NEXT);
8414087Scindi 	}
8421414Scindi 
8434087Scindi 	if (g_fmri != NULL && fnmatch(g_fmri, s, 0) != 0) {
8449501SRobert.Johnston@Sun.COM 		nvlist_free(rsrc);
8459501SRobert.Johnston@Sun.COM 		topo_hdl_strfree(thp, s);
8469501SRobert.Johnston@Sun.COM 		return (TOPO_WALK_NEXT);
8474087Scindi 	}
8484087Scindi 
8494087Scindi 	print_node(thp, node, rsrc, s);
8504087Scindi 	topo_hdl_strfree(thp, s);
8514087Scindi 	nvlist_free(rsrc);
8524087Scindi 
8539501SRobert.Johnston@Sun.COM 	if (opt_m != NULL) {
8549501SRobert.Johnston@Sun.COM 		if (topo_method_invoke(node, opt_m, 0, NULL, &out, &err) == 0) {
8559501SRobert.Johnston@Sun.COM 			nvlist_print(stdout, out);
8569501SRobert.Johnston@Sun.COM 			nvlist_free(out);
8579501SRobert.Johnston@Sun.COM 		} else if (err != ETOPO_METHOD_NOTSUP)
8589501SRobert.Johnston@Sun.COM 			(void) fprintf(stderr, "%s: method failed unexpectedly "
8599501SRobert.Johnston@Sun.COM 			    "on %s=%d (%s)\n", g_pname, topo_node_name(node),
8609501SRobert.Johnston@Sun.COM 			    topo_node_instance(node), topo_strerror(err));
8619501SRobert.Johnston@Sun.COM 	}
8629501SRobert.Johnston@Sun.COM 
8634087Scindi 	if (opt_V || opt_all) {
8643062Scindi 		if ((nvl = topo_prop_getprops(node, &err)) == NULL) {
8653062Scindi 			(void) fprintf(stderr, "%s: failed to get "
8663062Scindi 			    "properties for %s=%d: %s\n", g_pname,
8673062Scindi 			    topo_node_name(node), topo_node_instance(node),
8683062Scindi 			    topo_strerror(err));
8691414Scindi 		} else {
8704087Scindi 			print_all_props(thp, node, nvl, ALL);
8711414Scindi 			nvlist_free(nvl);
8721414Scindi 		}
8737243Srobj 	} else if (pcnt > 0)
8744087Scindi 		print_props(thp, node);
8751414Scindi 
87611050SRobert.Johnston@Sun.COM 	(void) printf("\n");
8773062Scindi 
8781414Scindi 	return (TOPO_WALK_NEXT);
8791414Scindi }
8801414Scindi 
8814087Scindi static void
get_pargs(int argc,char * argv[])8824087Scindi get_pargs(int argc, char *argv[])
8831414Scindi {
8844087Scindi 	struct prop_args *pp;
8854087Scindi 	char c, *s, *p;
8864087Scindi 	int i = 0;
8871414Scindi 
8884087Scindi 	if ((pargs = malloc(sizeof (struct prop_args *) * pcnt)) == NULL) {
8894087Scindi 		(void) fprintf(stderr, "%s: failed to allocate property "
8904087Scindi 		    "arguments\n", g_pname);
8914087Scindi 		return;
8924087Scindi 	}
8934087Scindi 
8944087Scindi 	for (optind = 1; (c = getopt(argc, argv, optstr)) != EOF; ) {
8954087Scindi 		if (c == 'P') {
8964087Scindi 
8974087Scindi 			if (strcmp(optarg, ALL) == 0) {
8984087Scindi 				opt_all++;
8993062Scindi 				break;
9004087Scindi 			}
9014087Scindi 
9024087Scindi 			if ((pp = pargs[i] = malloc(sizeof (struct prop_args)))
9034087Scindi 			    == NULL) {
9044087Scindi 				(void) fprintf(stderr, "%s: failed to "
9054087Scindi 				    "allocate propertyarguments\n", g_pname);
9064087Scindi 				return;
9074087Scindi 			}
9084087Scindi 			++i;
9094087Scindi 			pp->group = NULL;
9104087Scindi 			pp->prop = NULL;
9114087Scindi 			pp->type = NULL;
9124087Scindi 			pp->value = NULL;
9134087Scindi 
9144087Scindi 			p = optarg;
9154087Scindi 			if ((s = strchr(p, '.')) != NULL) {
9164087Scindi 				*s++ = '\0'; /* strike out delimiter */
9174087Scindi 				pp->group = p;
9184087Scindi 				p = s;
9194087Scindi 				if ((s = strchr(p, '=')) != NULL) {
9204087Scindi 					*s++ = '\0'; /* strike out delimiter */
9214087Scindi 					pp->prop = p;
9224087Scindi 					p = s;
9234087Scindi 					if ((s = strchr(p, ':')) != NULL) {
9244087Scindi 						*s++ = '\0';
9254087Scindi 						pp->type = p;
9264087Scindi 						pp->value = s;
9274087Scindi 					} else {
9284087Scindi 						(void) fprintf(stderr, "%s: "
9294087Scindi 						    "property type not "
9304087Scindi 						    "specified for assignment "
9314087Scindi 						    " of %s.%s\n", g_pname,
9324087Scindi 						    pp->group, pp->prop);
9334087Scindi 						break;
9344087Scindi 					}
9354087Scindi 				} else {
9364087Scindi 					pp->prop = p;
9374087Scindi 				}
9384087Scindi 			} else {
9394087Scindi 				pp->group = p;
9404087Scindi 			}
9414087Scindi 			if (i >= pcnt)
9421414Scindi 				break;
9431414Scindi 		}
9441414Scindi 	}
9451414Scindi 
9464087Scindi 	if (opt_all > 0) {
9474087Scindi 		int j;
9481414Scindi 
9494087Scindi 		for (j = 0; j < i; ++j)
9504087Scindi 			free(pargs[i]);
9514087Scindi 		free(pargs);
9524087Scindi 		pargs = NULL;
9531414Scindi 	}
9544087Scindi }
9553062Scindi 
9564087Scindi static int
walk_topo(topo_hdl_t * thp,char * uuid)9574087Scindi walk_topo(topo_hdl_t *thp, char *uuid)
9584087Scindi {
9594087Scindi 	int err;
9604087Scindi 	topo_walk_t *twp;
9616341Scy152378 	int flag;
9623062Scindi 
963*12967Sgavin.maltby@oracle.com 	if (getzoneid() != GLOBAL_ZONEID &&
964*12967Sgavin.maltby@oracle.com 	    strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0) {
965*12967Sgavin.maltby@oracle.com 		return (0);
966*12967Sgavin.maltby@oracle.com 	}
967*12967Sgavin.maltby@oracle.com 
9684087Scindi 	if ((twp = topo_walk_init(thp, opt_s, walk_node, NULL, &err))
9691414Scindi 	    == NULL) {
9701414Scindi 		(void) fprintf(stderr, "%s: failed to walk %s topology:"
9711414Scindi 		    " %s\n", g_pname, opt_s, topo_strerror(err));
9721414Scindi 
9734087Scindi 		return (-1);
9741414Scindi 	}
9751414Scindi 
9763062Scindi 	/*
9773062Scindi 	 * Print standard header
9783062Scindi 	 */
9793062Scindi 	if (!opt_e) {
9803062Scindi 		char buf[32];
9813062Scindi 		time_t tod = time(NULL);
9823062Scindi 
98311050SRobert.Johnston@Sun.COM 		(void) printf("TIME                 UUID\n");
9843062Scindi 		(void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod));
9853062Scindi 		(void) printf("%-15s %-32s\n", buf, uuid);
9863062Scindi 		(void) printf("\n");
9873062Scindi 	}
9881414Scindi 
9896341Scy152378 	flag = opt_b != 0 ? TOPO_WALK_SIBLING : TOPO_WALK_CHILD;
9906341Scy152378 
9916341Scy152378 	if (topo_walk_step(twp, flag) == TOPO_WALK_ERR) {
9921414Scindi 		(void) fprintf(stderr, "%s: failed to walk topology\n",
9931414Scindi 		    g_pname);
9942027Ssethg 		topo_walk_fini(twp);
9954087Scindi 		return (-1);
9961414Scindi 	}
9971414Scindi 
9981414Scindi 	topo_walk_fini(twp);
9994087Scindi 
10004087Scindi 	return (0);
10014087Scindi }
10024087Scindi 
10034087Scindi static void
print_fmri_pgroup(topo_hdl_t * thp,const char * pgn,nvlist_t * nvl)10044087Scindi print_fmri_pgroup(topo_hdl_t *thp, const char *pgn, nvlist_t *nvl)
10054087Scindi {
10064087Scindi 	char *dstab = NULL, *nstab = NULL;
10074087Scindi 	int32_t version = -1;
10084087Scindi 	nvlist_t *pnvl;
10094087Scindi 	nvpair_t *pnvp;
10104087Scindi 
10114087Scindi 	(void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_NSTAB, &nstab);
10124087Scindi 	(void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_DSTAB, &dstab);
10134087Scindi 	(void) nvlist_lookup_int32(nvl, TOPO_PROP_GROUP_VERSION, &version);
10144087Scindi 
10154087Scindi 	print_pgroup(thp, NULL, pgn, dstab, nstab, version);
10164087Scindi 
10174087Scindi 	for (pnvp = nvlist_next_nvpair(nvl, NULL); pnvp != NULL;
10184087Scindi 	    pnvp = nvlist_next_nvpair(nvl, pnvp)) {
10194087Scindi 
10204087Scindi 		/*
10214087Scindi 		 * Print property group and property name-value pair
10224087Scindi 		 */
10234087Scindi 		if (strcmp(TOPO_PROP_VAL, nvpair_name(pnvp))
10244087Scindi 		    == 0 && nvpair_type(pnvp) == DATA_TYPE_NVLIST) {
10254087Scindi 			(void) nvpair_value_nvlist(pnvp, &pnvl);
10267243Srobj 				print_prop_nameval(thp, NULL, pnvl);
10274087Scindi 
10284087Scindi 		}
10294087Scindi 
10304087Scindi 	}
10314087Scindi }
10324087Scindi 
10334087Scindi static void
print_fmri_props(topo_hdl_t * thp,nvlist_t * nvl)10344087Scindi print_fmri_props(topo_hdl_t *thp, nvlist_t *nvl)
10354087Scindi {
10364087Scindi 	int i, err;
10374087Scindi 	struct prop_args *pp;
10384087Scindi 	nvlist_t *pnvl;
10394087Scindi 
10404087Scindi 	for (i = 0; i < pcnt; ++i) {
10414087Scindi 		pp = pargs[i];
10424087Scindi 
10434087Scindi 		if (pp->group == NULL)
10444087Scindi 			continue;
10454087Scindi 
10464087Scindi 		pnvl = NULL;
10474087Scindi 
10484087Scindi 		/*
10494087Scindi 		 * If we have a valid value, this is a request to
10504087Scindi 		 * set a property.  Otherwise, just print the property
10514087Scindi 		 * group and any specified properties.
10524087Scindi 		 */
10534087Scindi 		if (pp->value == NULL) {
10544087Scindi 			if (pp->prop == NULL) {
10554087Scindi 
10564087Scindi 				/*
10574087Scindi 				 * Print all properties in this group
10584087Scindi 				 */
10594087Scindi 				if (topo_fmri_getpgrp(thp, nvl, pp->group,
10604087Scindi 				    &pnvl, &err) < 0) {
10614087Scindi 					(void) fprintf(stderr, "%s: failed to "
10624087Scindi 					    "get group %s: %s\n", g_pname,
10634087Scindi 					    pp->group, topo_strerror(err));
10644087Scindi 					continue;
10654087Scindi 				} else {
10667243Srobj 					print_fmri_pgroup(thp, pp->group,
10677243Srobj 					    pnvl);
10684087Scindi 					nvlist_free(pnvl);
10694087Scindi 					continue;
10704087Scindi 				}
10714087Scindi 			}
10724087Scindi 			if (topo_fmri_getprop(thp, nvl, pp->group, pp->prop,
10734087Scindi 			    NULL, &pnvl, &err) < 0) {
10744087Scindi 				(void) fprintf(stderr, "%s: failed to get "
10754087Scindi 				    "%s.%s: %s\n", g_pname,
10764087Scindi 				    pp->group, pp->prop,
10774087Scindi 				    topo_strerror(err));
10784087Scindi 				continue;
10794087Scindi 			} else {
10804087Scindi 				print_fmri_pgroup(thp, pp->group, pnvl);
10817243Srobj 				print_prop_nameval(thp, NULL, pnvl);
10824087Scindi 				nvlist_free(nvl);
10834087Scindi 			}
10844087Scindi 		} else {
10854087Scindi 			set_prop(thp, NULL, nvl, pp);
10864087Scindi 		}
10874087Scindi 	}
10884087Scindi }
10894087Scindi 
10904087Scindi void
print_fmri(topo_hdl_t * thp,char * uuid)10914087Scindi print_fmri(topo_hdl_t *thp, char *uuid)
10924087Scindi {
10934087Scindi 	int ret, err;
10944087Scindi 	nvlist_t *nvl;
10954087Scindi 	char buf[32];
10964087Scindi 	time_t tod = time(NULL);
10974087Scindi 
10984087Scindi 	if (topo_fmri_str2nvl(thp, g_fmri, &nvl, &err) < 0) {
10994087Scindi 		(void) fprintf(stderr, "%s: failed to convert %s to nvlist: "
11004087Scindi 		    "%s\n", g_pname, g_fmri, topo_strerror(err));
11014087Scindi 		return;
11024087Scindi 	}
11034087Scindi 
110411050SRobert.Johnston@Sun.COM 	(void) printf("TIME                 UUID\n");
11054087Scindi 	(void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod));
11064087Scindi 	(void) printf("%-15s %-32s\n", buf, uuid);
11074087Scindi 	(void) printf("\n");
11084087Scindi 
11094087Scindi 	(void) printf("%s\n", (char *)g_fmri);
11104087Scindi 
11114087Scindi 	if (opt_p && !(pcnt > 0 || opt_V || opt_all)) {
11124087Scindi 		char *aname = NULL, *fname = NULL, *lname = NULL;
11134087Scindi 		nvlist_t *asru = NULL;
11144087Scindi 		nvlist_t *fru = NULL;
11154087Scindi 
11164087Scindi 		if (topo_fmri_asru(thp, nvl, &asru, &err) == 0)
11174328Scindi 			(void) topo_fmri_nvl2str(thp, asru, &aname, &err);
11184087Scindi 		if (topo_fmri_fru(thp, nvl, &fru, &err) == 0)
11194328Scindi 			(void) topo_fmri_nvl2str(thp, fru, &fname, &err);
11204087Scindi 		(void) topo_fmri_label(thp, nvl, &lname, &err);
11214087Scindi 
11224087Scindi 		nvlist_free(fru);
11234087Scindi 		nvlist_free(asru);
11244087Scindi 
11254087Scindi 		if (aname != NULL) {
11264087Scindi 			(void) printf("\tASRU: %s\n", aname);
11274087Scindi 			topo_hdl_strfree(thp, aname);
11284087Scindi 		} else {
11294087Scindi 			(void) printf("\tASRU: -\n");
11304087Scindi 		}
11314087Scindi 		if (fname != NULL) {
11324087Scindi 			(void) printf("\tFRU: %s\n", fname);
11334087Scindi 			topo_hdl_strfree(thp, fname);
11344087Scindi 		} else {
11354087Scindi 			(void) printf("\tFRU: -\n");
11364087Scindi 		}
11374087Scindi 		if (lname != NULL) {
11384087Scindi 			(void) printf("\tLabel: %s\n", lname);
11394087Scindi 			topo_hdl_strfree(thp, lname);
11404087Scindi 		} else {
11414087Scindi 			(void) printf("\tLabel: -\n");
11424087Scindi 		}
11434087Scindi 	}
11444087Scindi 
11454087Scindi 	if (opt_S) {
11464087Scindi 		if (topo_fmri_str2nvl(thp, g_fmri, &nvl, &err) < 0) {
11474087Scindi 			(void) printf("\tPresent: -\n");
11484087Scindi 			(void) printf("\tUnusable: -\n");
11494087Scindi 			return;
11504087Scindi 		}
11514087Scindi 
11524087Scindi 		if ((ret = topo_fmri_present(thp, nvl, &err)) < 0)
11534087Scindi 			(void) printf("\tPresent: -\n");
11544087Scindi 		else
11554087Scindi 			(void) printf("\tPresent: %s\n",
11564087Scindi 			    ret ? "true" : "false");
11574087Scindi 
11584087Scindi 		if ((ret = topo_fmri_unusable(thp, nvl, &err)) < 0)
11594087Scindi 			(void) printf("\tUnusable: -\n");
11604087Scindi 		else
11614087Scindi 			(void) printf("\tUnusable: %s\n",
11624087Scindi 			    ret ? "true" : "false");
11634087Scindi 
11644087Scindi 		nvlist_free(nvl);
11654087Scindi 	}
11664087Scindi 
11675068Srobj 	if (pargs && pcnt > 0)
11684087Scindi 		print_fmri_props(thp, nvl);
11694087Scindi }
11704087Scindi 
11714087Scindi int
fmtopo_exit(topo_hdl_t * thp,char * uuid,int err)11724087Scindi fmtopo_exit(topo_hdl_t *thp, char *uuid, int err)
11734087Scindi {
11744087Scindi 	if (uuid != NULL)
11754087Scindi 		topo_hdl_strfree(thp, uuid);
11764087Scindi 
11774087Scindi 	if (thp != NULL) {
11784087Scindi 		topo_snap_release(thp);
11794087Scindi 		topo_close(thp);
11804087Scindi 	}
11814087Scindi 
11824087Scindi 	if (pargs) {
11834087Scindi 		int i;
11844087Scindi 		for (i = 0; i < pcnt; ++i)
11854087Scindi 			free(pargs[i]);
11864087Scindi 		free(pargs);
11874087Scindi 	}
11884087Scindi 
11894087Scindi 	return (err);
11904087Scindi }
11914087Scindi 
11924087Scindi int
main(int argc,char * argv[])11934087Scindi main(int argc, char *argv[])
11944087Scindi {
11954087Scindi 	topo_hdl_t *thp = NULL;
11964087Scindi 	char *uuid = NULL;
11974087Scindi 	int c, err = 0;
11984087Scindi 
11994087Scindi 	g_pname = argv[0];
12004087Scindi 
12014087Scindi 	while (optind < argc) {
12024087Scindi 		while ((c = getopt(argc, argv, optstr)) != -1) {
12034087Scindi 			switch (c) {
12046341Scy152378 			case 'b':
12056341Scy152378 				opt_b++;
12066341Scy152378 				break;
12074087Scindi 			case 'C':
120811050SRobert.Johnston@Sun.COM 				(void) atexit(abort);
12094087Scindi 				break;
12104087Scindi 			case 'd':
12114087Scindi 				opt_d++;
12124087Scindi 				break;
12134087Scindi 			case 'e':
12144087Scindi 				opt_e++;
12154087Scindi 				break;
12169501SRobert.Johnston@Sun.COM 			case 'm':
12179501SRobert.Johnston@Sun.COM 				opt_m = optarg;
12189501SRobert.Johnston@Sun.COM 				break;
12194087Scindi 			case 'P':
12204087Scindi 				pcnt++;
12214087Scindi 				break;
12224087Scindi 			case 'p':
12234087Scindi 				opt_p++;
12244087Scindi 				break;
12254087Scindi 			case 'V':
12264087Scindi 				opt_V++;
12274087Scindi 				break;
12284087Scindi 			case 'R':
12294087Scindi 				opt_R = optarg;
12304087Scindi 				break;
12314087Scindi 			case 's':
12324087Scindi 				opt_s = optarg;
12334087Scindi 				break;
12344087Scindi 			case 'S':
12354087Scindi 				opt_S++;
12364087Scindi 				break;
12374087Scindi 			case 't':
12384087Scindi 				opt_t++;
12394087Scindi 				break;
12404087Scindi 			case 'x':
12414087Scindi 				opt_x++;
12424087Scindi 				break;
12434087Scindi 			default:
12444087Scindi 				return (usage(stderr));
12454087Scindi 			}
12464087Scindi 		}
12474087Scindi 
12484087Scindi 		if (optind < argc) {
12494087Scindi 			if (g_fmri != NULL) {
12504087Scindi 				(void) fprintf(stderr, "%s: illegal argument "
12514087Scindi 				    "-- %s\n", g_pname, argv[optind]);
12524087Scindi 				return (FMTOPO_EXIT_USAGE);
12534087Scindi 			} else {
12544087Scindi 				g_fmri = argv[optind++];
12554087Scindi 			}
12564087Scindi 		}
12574087Scindi 	}
12584087Scindi 
12594087Scindi 	if (pcnt > 0)
12604087Scindi 		get_pargs(argc, argv);
12614087Scindi 
12624087Scindi 	if ((thp = topo_open(TOPO_VERSION, opt_R, &err)) == NULL) {
12634087Scindi 		(void) fprintf(stderr, "%s: failed to open topology tree: %s\n",
12644087Scindi 		    g_pname, topo_strerror(err));
12654087Scindi 		return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR));
12664087Scindi 	}
12674087Scindi 
12684087Scindi 	if (opt_d)
12694087Scindi 		topo_debug_set(thp, "module", "stderr");
12704087Scindi 
12714087Scindi 	if ((uuid = topo_snap_hold(thp, NULL, &err)) == NULL) {
12724087Scindi 		(void) fprintf(stderr, "%s: failed to snapshot topology: %s\n",
12734087Scindi 		    g_pname, topo_strerror(err));
12744087Scindi 		return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR));
12754087Scindi 	} else if (err != 0) {
1276*12967Sgavin.maltby@oracle.com 		(void) fprintf(stderr, "%s: topology snapshot incomplete%s\n",
1277*12967Sgavin.maltby@oracle.com 		    g_pname, getzoneid() != GLOBAL_ZONEID &&
1278*12967Sgavin.maltby@oracle.com 		    strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0 ?
1279*12967Sgavin.maltby@oracle.com 		    " (" FM_FMRI_SCHEME_HC " scheme does not enumerate "
1280*12967Sgavin.maltby@oracle.com 		    "in a non-global zone)": "");
12814087Scindi 	}
12824087Scindi 
12836341Scy152378 	if (opt_x) {
12846341Scy152378 		if (opt_b) {
12856341Scy152378 			(void) fprintf(stderr,
12866341Scy152378 			    "%s: -b and -x cannot be specified together\n",
12876341Scy152378 			    g_pname);
12886341Scy152378 			return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_USAGE));
12896341Scy152378 		}
12904087Scindi 
12914087Scindi 		err = 0;
12924087Scindi 		if (topo_xml_print(thp, stdout, opt_s, &err) < 0)
12934087Scindi 			(void) fprintf(stderr, "%s: failed to print xml "
12944087Scindi 			    "formatted topology:%s",  g_pname,
12954087Scindi 			    topo_strerror(err));
12964087Scindi 
12974087Scindi 		return (fmtopo_exit(thp, uuid, err ? FMTOPO_EXIT_ERROR :
12984087Scindi 		    FMTOPO_EXIT_SUCCESS));
12994087Scindi 	}
13004087Scindi 
13014087Scindi 	if (opt_t || walk_topo(thp, uuid) < 0) {
13024087Scindi 		if (g_fmri != NULL)
13034087Scindi 			/*
13044087Scindi 			 * Try getting some useful information
13054087Scindi 			 */
13064087Scindi 			print_fmri(thp, uuid);
13074087Scindi 
13084087Scindi 		return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR));
13094087Scindi 	}
13104087Scindi 
13114328Scindi 	return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_SUCCESS));
13121414Scindi }
1313