PSARC 2008/428 Extending libnvpair for type double
authorrobj
Thu, 31 Jul 2008 17:35:39 -0700
changeset 7243 2f11e164daec
parent 7242 a5a434ddef57
child 7244 ebb575deece3
PSARC 2008/428 Extending libnvpair for type double PSARC 2008/463 Extending HC FMRI scheme to represent sensors/indicators 6579615 fmtopo -e has lots of memory leaks 6635159 libtopo: extend hc scheme to allow for representing sensors and indicators in the topology 6692392 fmtopo -x doesn't handle property methods properly 6718703 Need to extend libnvpair to support type double 6718712 libtopo: Need to implement facility provider module for IPMI 6722594 libtopo: the topo_prop_set_* interfaces need to learn to play well with propmethods 6727190 libtopo: add support for node properties of type double 6727459 libipmi: need interface to convert raw sensor readings to unit-based values 6727470 libipmi: need convenience routine to convert sensor unit defines to string 6729595 libtopo: add <set> case in fan and psu xml maps for SUN-FIRE-X4600-M2 6732318 fmd: small leak in sysevent modelling code
usr/src/cmd/fm/fmd/common/fmd_sysevent.c
usr/src/cmd/fm/fmtopo/common/fmtopo.c
usr/src/common/nvpair/nvpair.c
usr/src/lib/fm/topo/libtopo/Makefile.com
usr/src/lib/fm/topo/libtopo/common/hc.c
usr/src/lib/fm/topo/libtopo/common/libtopo.h
usr/src/lib/fm/topo/libtopo/common/mapfile-vers
usr/src/lib/fm/topo/libtopo/common/topo_2xml.c
usr/src/lib/fm/topo/libtopo/common/topo_error.h
usr/src/lib/fm/topo/libtopo/common/topo_fmri.c
usr/src/lib/fm/topo/libtopo/common/topo_method.c
usr/src/lib/fm/topo/libtopo/common/topo_method.h
usr/src/lib/fm/topo/libtopo/common/topo_mod.h
usr/src/lib/fm/topo/libtopo/common/topo_node.c
usr/src/lib/fm/topo/libtopo/common/topo_parse.h
usr/src/lib/fm/topo/libtopo/common/topo_prop.c
usr/src/lib/fm/topo/libtopo/common/topo_subr.c
usr/src/lib/fm/topo/libtopo/common/topo_subr.h
usr/src/lib/fm/topo/libtopo/common/topo_xml.c
usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4500/Sun-Fire-X4500-hc-topology.xmlgen
usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4540/Sun-Fire-X4540-hc-topology.xmlgen
usr/src/lib/fm/topo/maps/common/topology.dtd.1
usr/src/lib/fm/topo/maps/i86pc/chip-hc-topology.xml
usr/src/lib/fm/topo/maps/i86pc/fan-hc-topology.xmlgen
usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml
usr/src/lib/fm/topo/maps/i86pc/psu-hc-topology.xml
usr/src/lib/fm/topo/modules/common/Makefile
usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/Makefile
usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c
usr/src/lib/libipmi/Makefile.com
usr/src/lib/libipmi/common/ipmi_impl.h
usr/src/lib/libipmi/common/ipmi_sdr.c
usr/src/lib/libipmi/common/ipmi_util.c
usr/src/lib/libipmi/common/libipmi.h
usr/src/lib/libipmi/common/mapfile-vers
usr/src/lib/libipmi/common/mktables.sh
usr/src/lib/libnvpair/libnvpair.c
usr/src/lib/libnvpair/mapfile-vers
usr/src/pkgdefs/SUNWfmd/prototype_com
usr/src/uts/common/sys/fm/protocol.h
usr/src/uts/common/sys/nvpair.h
--- a/usr/src/cmd/fm/fmd/common/fmd_sysevent.c	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/cmd/fm/fmd/common/fmd_sysevent.c	Thu Jul 31 17:35:39 2008 -0700
@@ -119,8 +119,10 @@
 	(void) nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva);
 	(void) nvlist_add_string(nvl, FM_CLASS, fullclass);
 	(void) nvlist_add_uint8(nvl, FM_VERSION, FM_RSRC_VERSION);
-	if (sysevent_get_attr_list(sep, &attr) == 0)
+	if (sysevent_get_attr_list(sep, &attr) == 0) {
 		(void) nvlist_merge(nvl, attr, 0);
+		nvlist_free(attr);
+	}
 
 	/*
 	 * Dispatch the event.  Ideally, we'd like to use the same transport
--- a/usr/src/cmd/fm/fmtopo/common/fmtopo.c	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/cmd/fm/fmtopo/common/fmtopo.c	Thu Jul 31 17:35:39 2008 -0700
@@ -50,11 +50,12 @@
 
 static const char *opt_R = "/";
 static const char *opt_s = FM_FMRI_SCHEME_HC;
-static const char optstr[] = "bCdeP:pR:s:StVx";
+static const char optstr[] = "bCdeEP:pR:s:StVx";
 
 static int opt_b = 0;
 static int opt_d = 0;
 static int opt_e = 0;
+static int opt_E = 0;
 static int opt_p = 0;
 static int opt_S = 0;
 static int opt_t = 0;
@@ -76,7 +77,7 @@
 usage(FILE *fp)
 {
 	(void) fprintf(fp,
-	    "Usage: %s [-bCedpSVx] [-P group.property[=type:value]] "
+	    "Usage: %s [-bCeEdpSVx] [-P group.property[=type:value]] "
 	    "[-R root] [-s scheme] [fmri]\n", g_pname);
 
 	(void) fprintf(fp,
@@ -84,6 +85,7 @@
 	    "\t-C  dump core after completing execution\n"
 	    "\t-d  set debug mode for libtopo modules\n"
 	    "\t-e  display FMRIs as paths using esc/eft notation\n"
+	    "\t-E  enumerate sensor nodes\n"
 	    "\t-P  get/set specified properties\n"
 	    "\t-p  display of FMRI protocol properties\n"
 	    "\t-R  set root directory for libtopo plug-ins and other files\n"
@@ -196,6 +198,7 @@
 		(void) fprintf(stderr, "%s: failed to find %s for %s=%d\n",
 		    g_pname, FM_FMRI_HC_LIST, topo_node_name(node),
 		    topo_node_instance(node));
+		nvlist_free(fmri);
 		return;
 	}
 
@@ -210,6 +213,7 @@
 			(void) fprintf(stderr, "%s: failed to get "
 			    "name-instance for %s=%d\n", g_pname,
 			    topo_node_name(node), topo_node_instance(node));
+			nvlist_free(fmri);
 			return;
 		}
 
@@ -226,16 +230,17 @@
 		(void) snprintf(numbuf, sizeof (numbuf), "%u", ul);
 		(void) strlcat(buf, numbuf, sizeof (buf));
 	}
+	nvlist_free(fmri);
 
 	(void) printf("%s\n", buf);
 }
 
 static void
-print_prop_nameval(topo_hdl_t *thp, nvlist_t *nvl)
+print_prop_nameval(topo_hdl_t *thp, tnode_t *node, nvlist_t *nvl)
 {
 	int err;
 	topo_type_t type;
-	char *tstr, *propn, buf[48];
+	char *tstr, *propn, buf[48], *factype;
 	nvpair_t *pv_nvp;
 	int i;
 	uint_t nelem;
@@ -271,6 +276,7 @@
 		case TOPO_TYPE_UINT32: tstr = "uint32"; break;
 		case TOPO_TYPE_INT64: tstr = "int64"; break;
 		case TOPO_TYPE_UINT64: tstr = "uint64"; break;
+		case TOPO_TYPE_DOUBLE: tstr = "double"; break;
 		case TOPO_TYPE_STRING: tstr = "string"; break;
 		case TOPO_TYPE_FMRI: tstr = "fmri"; break;
 		case TOPO_TYPE_INT32_ARRAY: tstr = "int32[]"; break;
@@ -302,9 +308,65 @@
 			break;
 		}
 		case DATA_TYPE_UINT32: {
-			uint32_t val;
+			uint32_t val, type;
+			char val_str[49];
+			nvlist_t *fac, *rsrc = NULL;
+
 			(void) nvpair_value_uint32(pv_nvp, &val);
+			if (node == NULL || topo_node_flags(node) !=
+			    TOPO_NODE_FACILITY)
+				goto uint32_def;
+
+			if (topo_node_resource(node, &rsrc, &err) != 0)
+				goto uint32_def;
+
+			if (nvlist_lookup_nvlist(rsrc, "facility", &fac) != 0)
+				goto uint32_def;
+
+			if (nvlist_lookup_string(fac, FM_FMRI_FACILITY_TYPE,
+			    &factype) != 0)
+				goto uint32_def;
+
+			nvlist_free(rsrc);
+			rsrc = NULL;
+
+			/*
+			 * Special case code to do friendlier printing of
+			 * facility node properties
+			 */
+			if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) &&
+			    (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) {
+				topo_sensor_type_name(val, val_str, 48);
+				(void) printf(" 0x%x (%s)", val, val_str);
+				break;
+			} else if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) &&
+			    (strcmp(factype, TOPO_FAC_TYPE_INDICATOR) == 0)) {
+				topo_led_type_name(val, val_str, 48);
+				(void) printf(" 0x%x (%s)", val, val_str);
+				break;
+			} else if (strcmp(propn, TOPO_SENSOR_UNITS) == 0) {
+				topo_sensor_units_name(val, val_str, 48);
+				(void) printf(" 0x%x (%s)", val, val_str);
+				break;
+			} else if (strcmp(propn, TOPO_LED_MODE) == 0) {
+				topo_led_state_name(val, val_str, 48);
+				(void) printf(" 0x%x (%s)", val, val_str);
+				break;
+			} else if ((strcmp(propn, TOPO_SENSOR_STATE) == 0) &&
+			    (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) {
+				if (topo_prop_get_uint32(node,
+				    TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE,
+				    &type, &err) != 0) {
+					goto uint32_def;
+				}
+				topo_sensor_state_name(type, val, val_str, 48);
+				(void) printf(" 0x%x (%s)", val, val_str);
+				break;
+			}
+uint32_def:
 			(void) printf(" 0x%x", val);
+			if (rsrc != NULL)
+				nvlist_free(rsrc);
 			break;
 		}
 		case DATA_TYPE_INT64: {
@@ -319,6 +381,12 @@
 			(void) printf(" 0x%llx", (u_longlong_t)val);
 			break;
 		}
+		case DATA_TYPE_DOUBLE: {
+			double val;
+			(void) nvpair_value_double(pv_nvp, &val);
+			(void) printf(" %lf", (double)val);
+			break;
+		}
 		case DATA_TYPE_STRING: {
 			char *val;
 			(void) nvpair_value_string(pv_nvp, &val);
@@ -361,6 +429,16 @@
 			(void) printf("]");
 			break;
 		}
+		case DATA_TYPE_INT64_ARRAY: {
+			int64_t *val;
+
+			(void) nvpair_value_int64_array(pv_nvp, &val, &nelem);
+			(void) printf(" [ ");
+			for (i = 0; i < nelem; i++)
+				(void) printf("%lld ", val[i]);
+			(void) printf("]");
+			break;
+		}
 		case DATA_TYPE_STRING_ARRAY: {
 			char **val;
 
@@ -483,7 +561,7 @@
 			    == 0 && nvpair_type(pg_nvp) == DATA_TYPE_NVLIST) {
 				(void) nvpair_value_nvlist(pg_nvp, &pv_nv);
 				if ((match || all) && pg_done) {
-					print_prop_nameval(thp, pv_nv);
+					print_prop_nameval(thp, node, pv_nv);
 				}
 
 			}
@@ -649,7 +727,7 @@
 	}
 
 	print_pgroup(thp, node, pp->group, NULL, NULL, 0);
-	print_prop_nameval(thp, nvl);
+	print_prop_nameval(thp, node, nvl);
 	nvlist_free(nvl);
 
 	nvlist_free(f);
@@ -706,7 +784,7 @@
 			} else {
 				print_pgroup(thp, node, pp->group, NULL,
 				    NULL, 0);
-				print_prop_nameval(thp, nvl);
+				print_prop_nameval(thp, node, nvl);
 				nvlist_free(nvl);
 			}
 		} else {
@@ -721,7 +799,7 @@
 {
 	int err;
 	nvlist_t *nvl;
-	nvlist_t *rsrc;
+	nvlist_t *rsrc, *out;
 	char *s;
 
 	if (opt_e && strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0) {
@@ -752,6 +830,24 @@
 	topo_hdl_strfree(thp, s);
 	nvlist_free(rsrc);
 
+	/*
+	 * If the "-E" option was specified, we want to also enumerate any
+	 * available facility nodes.  To do that we check if the node supports
+	 * a facility enumerator method.  If it exists, then we invoke it to
+	 * enumerate the sensors for this node.
+	 */
+	if (opt_E) {
+		if (topo_method_supported(node, TOPO_METH_FAC_ENUM, 0))
+			if (topo_method_invoke(node, TOPO_METH_FAC_ENUM, 0,
+			    NULL, &out, &err) != 0) {
+				(void) fprintf(stderr,
+				    "topo_method_invoke failed (%s) on node "
+				    "%s=%d\n", topo_strerror(err),
+				    topo_node_name(node),
+				    topo_node_instance(node));
+			}
+	}
+
 	if (opt_V || opt_all) {
 		if ((nvl = topo_prop_getprops(node, &err)) == NULL) {
 			(void) fprintf(stderr, "%s: failed to get "
@@ -762,9 +858,8 @@
 			print_all_props(thp, node, nvl, ALL);
 			nvlist_free(nvl);
 		}
-	} else if (pcnt > 0) {
+	} else if (pcnt > 0)
 		print_props(thp, node);
-	}
 
 	printf("\n");
 
@@ -911,7 +1006,7 @@
 		if (strcmp(TOPO_PROP_VAL, nvpair_name(pnvp))
 		    == 0 && nvpair_type(pnvp) == DATA_TYPE_NVLIST) {
 			(void) nvpair_value_nvlist(pnvp, &pnvl);
-				print_prop_nameval(thp, pnvl);
+				print_prop_nameval(thp, NULL, pnvl);
 
 		}
 
@@ -951,7 +1046,8 @@
 					    pp->group, topo_strerror(err));
 					continue;
 				} else {
-					print_fmri_pgroup(thp, pp->group, pnvl);
+					print_fmri_pgroup(thp, pp->group,
+					    pnvl);
 					nvlist_free(pnvl);
 					continue;
 				}
@@ -965,7 +1061,7 @@
 				continue;
 			} else {
 				print_fmri_pgroup(thp, pp->group, pnvl);
-				print_prop_nameval(thp, pnvl);
+				print_prop_nameval(thp, NULL, pnvl);
 				nvlist_free(nvl);
 			}
 		} else {
@@ -1100,6 +1196,9 @@
 			case 'e':
 				opt_e++;
 				break;
+			case 'E':
+				opt_E++;
+				break;
 			case 'P':
 				pcnt++;
 				break;
--- a/usr/src/common/nvpair/nvpair.c	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/common/nvpair/nvpair.c	Thu Jul 31 17:35:39 2008 -0700
@@ -402,6 +402,9 @@
 	case DATA_TYPE_STRING:
 	case DATA_TYPE_HRTIME:
 	case DATA_TYPE_NVLIST:
+#if !defined(_KERNEL)
+	case DATA_TYPE_DOUBLE:
+#endif
 		if (nelem != 1)
 			return (EINVAL);
 		break;
@@ -740,6 +743,11 @@
 	case DATA_TYPE_UINT64:
 		value_sz = sizeof (uint64_t);
 		break;
+#if !defined(_KERNEL)
+	case DATA_TYPE_DOUBLE:
+		value_sz = sizeof (double);
+		break;
+#endif
 	case DATA_TYPE_STRING:
 		if (data == NULL)
 			value_sz = 0;
@@ -1024,6 +1032,14 @@
 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64, 1, &val));
 }
 
+#if !defined(_KERNEL)
+int
+nvlist_add_double(nvlist_t *nvl, const char *name, double val)
+{
+	return (nvlist_add_common(nvl, name, DATA_TYPE_DOUBLE, 1, &val));
+}
+#endif
+
 int
 nvlist_add_string(nvlist_t *nvl, const char *name, const char *val)
 {
@@ -1206,6 +1222,9 @@
 	case DATA_TYPE_INT64:
 	case DATA_TYPE_UINT64:
 	case DATA_TYPE_HRTIME:
+#if !defined(_KERNEL)
+	case DATA_TYPE_DOUBLE:
+#endif
 		if (data == NULL)
 			return (EINVAL);
 		bcopy(NVP_VALUE(nvp), data,
@@ -1342,6 +1361,14 @@
 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64, NULL, val));
 }
 
+#if !defined(_KERNEL)
+int
+nvlist_lookup_double(nvlist_t *nvl, const char *name, double *val)
+{
+	return (nvlist_lookup_common(nvl, name, DATA_TYPE_DOUBLE, NULL, val));
+}
+#endif
+
 int
 nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val)
 {
@@ -1476,6 +1503,9 @@
 		case DATA_TYPE_HRTIME:
 		case DATA_TYPE_STRING:
 		case DATA_TYPE_NVLIST:
+#if !defined(_KERNEL)
+		case DATA_TYPE_DOUBLE:
+#endif
 			val = va_arg(ap, void *);
 			ret = nvlist_lookup_common(nvl, name, type, NULL, val);
 			break;
@@ -1787,6 +1817,14 @@
 	return (nvpair_value_common(nvp, DATA_TYPE_UINT64, NULL, val));
 }
 
+#if !defined(_KERNEL)
+int
+nvpair_value_double(nvpair_t *nvp, double *val)
+{
+	return (nvpair_value_common(nvp, DATA_TYPE_DOUBLE, NULL, val));
+}
+#endif
+
 int
 nvpair_value_string(nvpair_t *nvp, char **val)
 {
@@ -2924,7 +2962,11 @@
 		 */
 		ret = xdr_longlong_t(xdr, (void *)buf);
 		break;
-
+#if !defined(_KERNEL)
+	case DATA_TYPE_DOUBLE:
+		ret = xdr_double(xdr, (void *)buf);
+		break;
+#endif
 	case DATA_TYPE_STRING:
 		ret = xdr_string(xdr, &buf, buflen - 1);
 		break;
@@ -3030,6 +3072,9 @@
 	case DATA_TYPE_INT64:
 	case DATA_TYPE_UINT64:
 	case DATA_TYPE_HRTIME:
+#if !defined(_KERNEL)
+	case DATA_TYPE_DOUBLE:
+#endif
 		nvp_sz += 8;
 		break;
 
--- a/usr/src/lib/fm/topo/libtopo/Makefile.com	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/Makefile.com	Thu Jul 31 17:35:39 2008 -0700
@@ -59,6 +59,7 @@
 	topo_snap.c \
 	topo_string.c \
 	topo_subr.c \
+	topo_tables.c \
 	topo_tree.c \
 	topo_xml.c
 
@@ -72,7 +73,7 @@
 
 SRCDIR =	../common
 
-CLEANFILES += ../common/topo_error.c
+CLEANFILES += $(SRCDIR)/topo_error.c $(SRCDIR)/topo_tables.c
 
 CPPFLAGS += -I../common -I/usr/include/libxml2 -I.
 CFLAGS += $(CCVERBOSE) $(C_BIGPICFLAGS)
@@ -113,5 +114,8 @@
 	sh ../common/mkerror.sh hdlerrors < ../common/libtopo.h >> $@
 	sh ../common/mkerror.sh moderrors < ../common/topo_mod.h >> $@
 
+$(SRCDIR)/topo_tables.c: $(SRCDIR)/mktables.sh $(SRCDIR)/libtopo.h
+	sh $(SRCDIR)/mktables.sh $(SRCDIR)/libtopo.h > $@
+
 include ../../../../Makefile.targ
 include ../../../Makefile.targ
--- a/usr/src/lib/fm/topo/libtopo/common/hc.c	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/hc.c	Thu Jul 31 17:35:39 2008 -0700
@@ -44,6 +44,7 @@
 #include <sys/utsname.h>
 
 #include <topo_method.h>
+#include <topo_module.h>
 #include <topo_subr.h>
 #include <topo_prop.h>
 #include <topo_tree.h>
@@ -70,6 +71,8 @@
     nvlist_t *, nvlist_t **);
 static int hc_fmri_pgrp_get(topo_mod_t *, tnode_t *, topo_version_t,
     nvlist_t *, nvlist_t **);
+static int hc_fmri_facility(topo_mod_t *, tnode_t *, topo_version_t,
+    nvlist_t *, nvlist_t **);
 
 static nvlist_t *hc_fmri_create(topo_mod_t *, nvlist_t *, int, const char *,
     topo_instance_t inst, const nvlist_t *, const char *, const char *,
@@ -98,6 +101,9 @@
 	{ TOPO_METH_PGRP_GET, TOPO_METH_PGRP_GET_DESC,
 	    TOPO_METH_PGRP_GET_VERSION, TOPO_STABILITY_INTERNAL,
 	    hc_fmri_pgrp_get },
+	{ TOPO_METH_FACILITY, TOPO_METH_FACILITY_DESC,
+	    TOPO_METH_FACILITY_VERSION, TOPO_STABILITY_INTERNAL,
+	    hc_fmri_facility },
 	{ NULL }
 };
 
@@ -325,8 +331,10 @@
 {
 	uint8_t v1, v2;
 	nvlist_t **hcp1, **hcp2;
+	nvlist_t *f1 = NULL, *f2 = NULL;
 	int err, i;
 	uint_t nhcp1, nhcp2;
+	char *f1str, *f2str;
 
 	if (nvlist_lookup_uint8(nv1, FM_VERSION, &v1) != 0 ||
 	    nvlist_lookup_uint8(nv2, FM_VERSION, &v2) != 0 ||
@@ -360,7 +368,28 @@
 		return (0);
 	}
 
-	return (1);
+	/*
+	 * Finally, check if the FMRI's represent a facility node.  If so, then
+	 * verify that the facilty type ("sensor"|"indicator") and facility
+	 * name match.
+	 */
+	(void) nvlist_lookup_nvlist(nv1, FM_FMRI_FACILITY, &f1);
+	(void) nvlist_lookup_nvlist(nv2, FM_FMRI_FACILITY, &f2);
+
+	if (f1 == NULL && f2 == NULL)
+		return (1);
+	else if (f1 == NULL || f2 == NULL)
+		return (0);
+
+	if (nvlist_lookup_string(f1, FM_FMRI_FACILITY_NAME, &f1str) == 0 &&
+	    nvlist_lookup_string(f2, FM_FMRI_FACILITY_NAME, &f2str) == 0 &&
+	    strcmp(f1str, f2str) == 0 &&
+	    nvlist_lookup_string(f1, FM_FMRI_FACILITY_TYPE, &f1str) == 0 &&
+	    nvlist_lookup_string(f2, FM_FMRI_FACILITY_TYPE, &f2str) == 0 &&
+	    strcmp(f1str, f2str) == 0) {
+		return (1);
+	}
+	return (0);
 }
 
 /*ARGSUSED*/
@@ -400,6 +429,7 @@
 {
 	nvlist_t **hcprs = NULL;
 	nvlist_t *anvl = NULL;
+	nvlist_t *fnvl;
 	uint8_t version;
 	ssize_t size = 0;
 	uint_t hcnprs;
@@ -412,6 +442,7 @@
 	char *part = NULL;
 	char *root = NULL;
 	char *rev = NULL;
+	char *fname = NULL, *ftype = NULL;
 	int more_auth = 0;
 	int err, i;
 
@@ -508,6 +539,22 @@
 		topo_fmristr_build(&size, buf, buflen, id, NULL, NULL);
 	}
 
+	/*
+	 * If the nvlist represents a facility node, then we append the
+	 * facility type and name to the end of the string representation using
+	 * the format below:
+	 *
+	 * ?<ftype>=<fname>
+	 */
+	if (nvlist_lookup_nvlist(nvl, FM_FMRI_FACILITY, &fnvl) == 0) {
+		if (nvlist_lookup_string(fnvl, FM_FMRI_FACILITY_NAME,
+		    &fname) != 0 || nvlist_lookup_string(fnvl,
+		    FM_FMRI_FACILITY_TYPE, &ftype) != 0)
+			return (0);
+		topo_fmristr_build(&size, buf, buflen, "?", NULL, NULL);
+		topo_fmristr_build(&size, buf, buflen, "=", ftype, fname);
+	}
+
 	return (size);
 }
 
@@ -707,17 +754,17 @@
 	return (pa);
 }
 
-void
+int
 make_hc_auth(topo_mod_t *mod, char *fmri, char **serial, char **part,
 char **rev, nvlist_t **auth)
 {
 	char *starti, *startn, *endi, *copy;
-	char *aname, *aid, *fs;
+	char *aname = NULL, *aid = NULL, *fs;
 	nvlist_t *na = NULL;
 	size_t len;
 
 	if ((copy = topo_mod_strdup(mod, fmri + 5)) == NULL)
-		return;
+		return (-1);
 
 	len = strlen(copy);
 
@@ -729,7 +776,7 @@
 
 	if (startn == NULL || fs == NULL) {
 		topo_mod_strfree(mod, copy);
-		return;
+		return (0);
 	}
 
 	/*
@@ -737,21 +784,21 @@
 	 * first slash
 	 */
 	if (startn > fs)
-		return;
+		goto hcabail;
 
 	do {
 		if (++startn >= copy + len)
 			break;
 
 		if ((starti = strchr(startn, '=')) == NULL)
-			break;
+			goto hcabail;
 
 		*starti = '\0';
 		if (++starti > copy + len)
-			break;
+			goto hcabail;
 
 		if ((aname = topo_mod_strdup(mod, startn)) == NULL)
-			break;
+			goto hcabail;
 
 		startn = endi = strchr(starti, ':');
 		if (endi == NULL)
@@ -759,10 +806,8 @@
 				break;
 
 		*endi = '\0';
-		if ((aid = topo_mod_strdup(mod, starti)) == NULL) {
-			topo_mod_strfree(mod, aname);
-			break;
-		}
+		if ((aid = topo_mod_strdup(mod, starti)) == NULL)
+			goto hcabail;
 
 		/*
 		 * Return possible serial, part and revision
@@ -786,12 +831,74 @@
 		}
 		topo_mod_strfree(mod, aname);
 		topo_mod_strfree(mod, aid);
+		aname = aid = NULL;
 
 	} while (startn != NULL);
 
 	*auth = na;
 
 	topo_mod_free(mod, copy, len + 1);
+	return (0);
+
+hcabail:
+	topo_mod_free(mod, copy, len + 1);
+	topo_mod_strfree(mod, aname);
+	topo_mod_strfree(mod, aid);
+	nvlist_free(na);
+	return (-1);
+}
+
+
+/*
+ * This function creates an nvlist to represent the facility portion of an
+ * hc-scheme node, given a string representation of the fmri.  This is called by
+ * hc_fmri_str2nvl.  If the string does not contain a facility component
+ * (e.g. ?<ftype>=<fname>) then it bails early and returns 0.
+ *
+ * On failure it returns -1 and sets the topo mod errno
+ */
+int
+make_facility(topo_mod_t *mod, char *str, nvlist_t **nvl)
+{
+	char *fac, *copy, *fname, *ftype;
+	nvlist_t *nf = NULL;
+	size_t len;
+
+	if ((fac = strchr(str, '?')) == NULL)
+		return (0);
+
+	++fac;
+	if ((copy = topo_mod_strdup(mod, fac)) == NULL)
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
+
+	fac = copy;
+	len = strlen(fac);
+
+	if ((fname = strchr(fac, '=')) == NULL) {
+		topo_mod_free(mod, copy, len + 1);
+		return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
+	}
+
+	fname[0] = '\0';
+	++fname;
+	ftype = fac;
+
+	if (topo_mod_nvalloc(mod, &nf, NV_UNIQUE_NAME) != 0) {
+		topo_mod_free(mod, copy, len + 1);
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
+	}
+
+	if (nvlist_add_string(nf, FM_FMRI_FACILITY_NAME, fname) != 0 ||
+	    nvlist_add_string(nf, FM_FMRI_FACILITY_TYPE, ftype) != 0) {
+		topo_mod_free(mod, copy, len + 1);
+		return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
+	}
+
+	topo_mod_free(mod, copy, len + 1);
+
+	*nvl = nf;
+
+	return (0);
 }
 
 /*ARGSUSED*/
@@ -802,6 +909,7 @@
 	nvlist_t **pa = NULL;
 	nvlist_t *nf = NULL;
 	nvlist_t *auth = NULL;
+	nvlist_t *fac = NULL;
 	char *str;
 	char *serial = NULL, *part = NULL, *rev = NULL;
 	int npairs;
@@ -820,7 +928,9 @@
 	if ((pa = make_hc_pairs(mod, str, &npairs)) == NULL)
 		return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
 
-	make_hc_auth(mod, str, &serial, &part, &rev, &auth);
+	if (make_hc_auth(mod, str, &serial, &part, &rev, &auth) < 0)
+		goto hcfmbail;
+
 	if ((nf = hc_base_fmri_create(mod, auth, part, rev, serial)) == NULL)
 		goto hcfmbail;
 	if ((e = nvlist_add_uint32(nf, FM_FMRI_HC_LIST_SZ, npairs)) == 0)
@@ -829,17 +939,26 @@
 		topo_mod_dprintf(mod, "construction of new hc nvl failed");
 		goto hcfmbail;
 	}
+
+	/*
+	 * Clean-up
+	 */
 	for (i = 0; i < npairs; i++)
 		nvlist_free(pa[i]);
 	topo_mod_free(mod, pa, npairs * sizeof (nvlist_t *));
-	if (serial != NULL)
-		topo_mod_strfree(mod, serial);
-	if (part != NULL)
-		topo_mod_strfree(mod, part);
-	if (rev != NULL)
-		topo_mod_strfree(mod, rev);
+	topo_mod_strfree(mod, serial);
+	topo_mod_strfree(mod, part);
+	topo_mod_strfree(mod, rev);
 	nvlist_free(auth);
 
+	if (make_facility(mod, str, &fac) == -1)
+		goto hcfmbail;
+
+	if (fac != NULL) {
+		if (nvlist_add_nvlist(nf, FM_FMRI_FACILITY, fac) != 0)
+			goto hcfmbail;
+	}
+
 	*out = nf;
 
 	return (0);
@@ -850,13 +969,12 @@
 	for (i = 0; i < npairs; i++)
 		nvlist_free(pa[i]);
 	topo_mod_free(mod, pa, npairs * sizeof (nvlist_t *));
-	if (serial != NULL)
-		topo_mod_strfree(mod, serial);
-	if (part != NULL)
-		topo_mod_strfree(mod, part);
-	if (rev != NULL)
-		topo_mod_strfree(mod, rev);
+
+	topo_mod_strfree(mod, serial);
+	topo_mod_strfree(mod, part);
+	topo_mod_strfree(mod, rev);
 	nvlist_free(auth);
+	nvlist_free(nf);
 	return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
 }
 
@@ -1053,6 +1171,7 @@
 	topo_walk_t *hcw_wp;
 	nvlist_t **hcw_list;
 	nvlist_t *hcw_fmri;
+	nvlist_t *hcw_fac;
 	uint_t hcw_index;
 	uint_t hcw_end;
 };
@@ -1151,7 +1270,7 @@
 
 /*
  * Generic walker for the hc-scheme topo tree.  This function uses the
- * hierachical nature of the hc-scheme to step through efficiently through
+ * hierachical nature of the hc-scheme to efficiently step through
  * the topo hc tree.  Node lookups are done by topo_walk_byid() and
  * topo_walk_bysibling()  at each component level to avoid unnecessary
  * traversal of the tree.  hc_walker() never returns TOPO_WALK_NEXT, so
@@ -1164,13 +1283,27 @@
 	int i, err;
 	struct hc_walk *hwp = (struct hc_walk *)pdata;
 	char *name, *id;
+	char *fname, *ftype;
 	topo_instance_t inst;
 	boolean_t match;
 
 	i = hwp->hcw_index;
 	if (i > hwp->hcw_end) {
-		(void) topo_mod_seterrno(mod, ETOPO_PROP_NOENT);
-		return (TOPO_WALK_TERMINATE);
+		if (hwp->hcw_fac != NULL) {
+			if ((err = hwp->hcw_cb(mod, node, hwp->hcw_priv))
+			    != 0) {
+				(void) topo_mod_seterrno(mod, err);
+				topo_mod_dprintf(mod, "hc_walker: callback "
+				    "failed: %s\n ", topo_mod_errmsg(mod));
+				return (TOPO_WALK_ERR);
+			}
+			topo_mod_dprintf(mod, "hc_walker: callback "
+			    "complete: terminate walk\n");
+			return (TOPO_WALK_TERMINATE);
+		} else {
+			topo_mod_dprintf(mod, "hc_walker: node not found\n");
+			return (TOPO_WALK_TERMINATE);
+		}
 	}
 
 	err = nvlist_lookup_string(hwp->hcw_list[i], FM_FMRI_HC_NAME, &name);
@@ -1198,29 +1331,46 @@
 	topo_mod_dprintf(mod, "hc_walker: walking node:%s=%d for hc:"
 	    "%s=%d at %d, end at %d \n", topo_node_name(node),
 	    topo_node_instance(node), name, inst, i, hwp->hcw_end);
+
 	if (i == hwp->hcw_end) {
+
 		/*
-		 * We are at the end of the hc-list.  Verify that
-		 * the last node contains the name/instance we are looking for.
+		 * We are at the end of the hc-list.  Now, check for
+		 * a facility leaf and walk one more time.
 		 */
-		if (match) {
-			if ((err = hwp->hcw_cb(mod, node, hwp->hcw_priv))
-			    != 0) {
-				(void) topo_mod_seterrno(mod, err);
-				topo_mod_dprintf(mod, "hc_walker: callback "
-				    "failed: %s\n ", topo_mod_errmsg(mod));
+		if (hwp->hcw_fac != NULL) {
+			err = nvlist_lookup_string(hwp->hcw_fac,
+			    FM_FMRI_FACILITY_NAME, &fname);
+			err |= nvlist_lookup_string(hwp->hcw_fac,
+			    FM_FMRI_FACILITY_TYPE, &ftype);
+			if (err != 0) {
+				(void) topo_mod_seterrno(mod, EMOD_NVL_INVAL);
 				return (TOPO_WALK_ERR);
 			}
+			hwp->hcw_index++;
+			topo_mod_dprintf(mod, "hc_walker: walk to facility "
+			    "node:%s=%s\n", fname, ftype);
+			return (topo_walk_byid(hwp->hcw_wp, fname, 0));
+		}
+
+		/*
+		 * Otherwise, this is the node we're looking for.
+		 */
+		if ((err = hwp->hcw_cb(mod, node, hwp->hcw_priv)) != 0) {
+			(void) topo_mod_seterrno(mod, err);
+			topo_mod_dprintf(mod, "hc_walker: callback "
+			    "failed: %s\n ", topo_mod_errmsg(mod));
+			return (TOPO_WALK_ERR);
+		} else {
 			topo_mod_dprintf(mod, "hc_walker: callback "
 			    "complete: terminate walk\n");
 			return (TOPO_WALK_TERMINATE);
-		} else {
-			topo_mod_dprintf(mod, "hc_walker: %s=%d\n "
-			    "not found\n", name, inst);
-			return (TOPO_WALK_TERMINATE);
 		}
 	}
 
+	/*
+	 * Move on to the next component in the hc-list
+	 */
 	hwp->hcw_index = ++i;
 	err = nvlist_lookup_string(hwp->hcw_list[i], FM_FMRI_HC_NAME, &name);
 	err |= nvlist_lookup_string(hwp->hcw_list[i], FM_FMRI_HC_ID, &id);
@@ -1230,8 +1380,6 @@
 	}
 	inst = atoi(id);
 
-	topo_mod_dprintf(mod, "hc_walker: walk byid of %s=%d \n", name,
-	    inst);
 	return (topo_walk_byid(hwp->hcw_wp, name, inst));
 
 }
@@ -1240,7 +1388,7 @@
 hc_walk_init(topo_mod_t *mod, tnode_t *node, nvlist_t *rsrc,
     topo_mod_walk_cb_t cb, void *pdata)
 {
-	int err;
+	int err, ret;
 	uint_t sz;
 	struct hc_walk *hwp;
 	topo_walk_t *wp;
@@ -1252,10 +1400,24 @@
 
 	if (nvlist_lookup_nvlist_array(rsrc, FM_FMRI_HC_LIST, &hwp->hcw_list,
 	    &sz) != 0) {
+		topo_mod_dprintf(mod, "hc_walk_init: failed to lookup %s "
+		    "nvlist\n", FM_FMRI_HC_LIST);
 		topo_mod_free(mod, hwp, sizeof (struct hc_walk));
 		(void) topo_mod_seterrno(mod, EMOD_METHOD_INVAL);
 		return (NULL);
 	}
+	if ((ret = nvlist_lookup_nvlist(rsrc, FM_FMRI_FACILITY, &hwp->hcw_fac))
+	    != 0) {
+		if (ret != ENOENT) {
+			topo_mod_dprintf(mod, "hc_walk_init: unexpected error "
+			    "looking up %s nvlist", FM_FMRI_FACILITY);
+			topo_mod_free(mod, hwp, sizeof (struct hc_walk));
+			(void) topo_mod_seterrno(mod, EMOD_METHOD_INVAL);
+			return (NULL);
+		} else {
+			hwp->hcw_fac = NULL;
+		}
+	}
 
 	hwp->hcw_fmri = rsrc;
 	hwp->hcw_end = sz - 1;
@@ -1264,6 +1426,8 @@
 	hwp->hcw_cb = cb;
 	if ((wp = topo_mod_walk_init(mod, node, hc_walker, (void *)hwp, &err))
 	    == NULL) {
+		topo_mod_dprintf(mod, "hc_walk_init: topo_mod_walk_init failed "
+		    "(%s)\n", topo_strerror(err));
 		topo_mod_free(mod, hwp, sizeof (struct hc_walk));
 		(void) topo_mod_seterrno(mod, err);
 		return (NULL);
@@ -1615,3 +1779,122 @@
 
 	return (err);
 }
+
+struct fac_lookup {
+	const char *fl_fac_type;
+	uint32_t fl_fac_subtype;
+#ifdef _LP64
+	uint64_t fl_callback;
+	uint64_t fl_callback_args;
+#else
+	uint32_t fl_callback;
+	uint32_t fl_callback_args;
+#endif
+	nvlist_t *fl_rsrc;
+	nvlist_t *fl_fac_rsrc;
+};
+
+static int
+hc_fac_get(topo_mod_t *mod, tnode_t *node, void *pdata)
+{
+	struct fac_lookup *flp = (struct fac_lookup *)pdata;
+	topo_walk_cb_t cb = (topo_walk_cb_t)flp->fl_callback;
+	topo_faclist_t faclist, *tmp;
+	int err, ret = 0;
+
+	/*
+	 * Lookup the specified facility node.  Return with an error if we can't
+	 * find it.
+	 */
+	if (topo_node_facility(mod->tm_hdl, node, flp->fl_fac_type,
+	    flp->fl_fac_subtype, &faclist, &err) != 0) {
+		topo_mod_dprintf(mod, "hc_fac_get: topo_node_facility "
+		    "failed\n");
+		return (TOPO_WALK_ERR);
+	}
+
+	/*
+	 * Invoke user's callback for each facility node in the topo list,
+	 * passing in a pointer to the facility node
+	 */
+	for (tmp = topo_list_next(&faclist.tf_list); tmp != NULL;
+	    tmp = topo_list_next(tmp)) {
+
+		if ((err = cb(mod->tm_hdl, tmp->tf_node,
+		    (void *)flp->fl_callback_args)) != 0) {
+			(void) topo_mod_seterrno(mod, err);
+			topo_mod_dprintf(mod, "hc_fac_get: callback failed: "
+			    "%s\n ", topo_mod_errmsg(mod));
+			ret = TOPO_WALK_ERR;
+			break;
+		}
+	}
+
+	while ((tmp = topo_list_next(&faclist.tf_list)) != NULL) {
+		topo_list_delete(&faclist.tf_list, tmp);
+		topo_mod_free(mod, tmp, sizeof (topo_faclist_t));
+	}
+	return (ret);
+}
+
+static int
+hc_fmri_facility(topo_mod_t *mod, tnode_t *node, topo_version_t version,
+    nvlist_t *in, nvlist_t **out)
+{
+	int err = 0;
+	struct hc_walk *hwp;
+	struct fac_lookup *flp;
+
+	if (version > TOPO_METH_FACILITY_VERSION)
+		return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
+
+	if ((flp = topo_mod_alloc(mod, sizeof (struct fac_lookup))) == NULL)
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
+
+	/*
+	 * lookup arguments: hw resource, facility type, facility subtype,
+	 *  callback and callback args
+	 */
+	err = nvlist_lookup_nvlist(in, TOPO_PROP_RESOURCE, &flp->fl_rsrc);
+	err |= nvlist_lookup_string(in, FM_FMRI_FACILITY_TYPE,
+	    (char **)&flp->fl_fac_type);
+	err |= nvlist_lookup_uint32(in, "type", &flp->fl_fac_subtype);
+#ifdef _LP64
+	err |= nvlist_lookup_uint64(in, "callback", &flp->fl_callback);
+	err |= nvlist_lookup_uint64(in, "callback-args",
+	    &flp->fl_callback_args);
+#else
+	err |= nvlist_lookup_uint32(in, "callback", &flp->fl_callback);
+	err |= nvlist_lookup_uint32(in, "callback-args",
+	    &flp->fl_callback_args);
+#endif
+	if (err != 0) {
+		topo_mod_dprintf(mod, "hc_fmri_facility: failed to construct "
+		    "walker arg nvlist\n");
+		topo_mod_free(mod, flp, sizeof (struct fac_lookup));
+		return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
+	}
+
+	flp->fl_fac_rsrc = NULL;
+	if ((hwp = hc_walk_init(mod, node, flp->fl_rsrc, hc_fac_get,
+	    (void *)flp)) != NULL) {
+		if (topo_walk_step(hwp->hcw_wp, TOPO_WALK_CHILD) ==
+		    TOPO_WALK_ERR)
+			err = -1;
+		else
+			err = 0;
+		topo_walk_fini(hwp->hcw_wp);
+		topo_mod_free(mod, hwp, sizeof (struct hc_walk));
+	} else {
+		topo_mod_dprintf(mod, "hc_fmri_facility: failed to initialize "
+		    "hc walker\n");
+		err = -1;
+	}
+
+	if (flp->fl_fac_rsrc != NULL)
+		*out = flp->fl_fac_rsrc;
+
+	topo_mod_free(mod, flp, sizeof (struct fac_lookup));
+
+	return (err);
+}
--- a/usr/src/lib/fm/topo/libtopo/common/libtopo.h	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/libtopo.h	Thu Jul 31 17:35:39 2008 -0700
@@ -44,6 +44,16 @@
 typedef int32_t topo_instance_t;
 typedef uint32_t topo_version_t;
 
+typedef struct topo_list {
+	struct topo_list *l_prev;
+	struct topo_list *l_next;
+} topo_list_t;
+
+typedef struct topo_faclist {
+	topo_list_t	tf_list;
+	tnode_t		*tf_node;
+} topo_faclist_t;
+
 /*
  * The following functions, error codes and data structures are private
  * to libtopo snapshot consumers and enumerator modules.
@@ -91,6 +101,8 @@
 extern int topo_fmri_label(topo_hdl_t *, nvlist_t *, char **, int *);
 extern int topo_fmri_serial(topo_hdl_t *, nvlist_t *, char **, int *);
 extern int topo_fmri_compare(topo_hdl_t *, nvlist_t *, nvlist_t *, int *);
+extern int topo_fmri_facility(topo_hdl_t *, nvlist_t *, const char *,
+    uint32_t, topo_walk_cb_t, void *, int *);
 
 /*
  * Private utility functions for fmd
@@ -106,13 +118,30 @@
 extern topo_instance_t topo_node_instance(tnode_t *);
 extern tnode_t *topo_node_parent(tnode_t *);
 extern void *topo_node_private(tnode_t *);
+extern int topo_node_flags(tnode_t *);
 extern int topo_node_asru(tnode_t *, nvlist_t **, nvlist_t *, int *);
 extern int topo_node_fru(tnode_t *, nvlist_t **, nvlist_t *, int *);
 extern int topo_node_resource(tnode_t *, nvlist_t **, int *);
 extern int topo_node_label(tnode_t *, char **, int *);
 extern int topo_method_invoke(tnode_t *node, const char *, topo_version_t,
     nvlist_t *, nvlist_t **, int *);
+extern boolean_t topo_method_supported(tnode_t *, const char *,
+    topo_version_t);
+extern int topo_node_facility(topo_hdl_t *, tnode_t *, const char *,
+    uint32_t, topo_faclist_t *, int *);
 
+/*
+ * Node flags: denotes type of node
+ */
+#define	TOPO_NODE_DEFAULT	0
+#define	TOPO_NODE_FACILITY	1
+
+#define	TOPO_FAC_TYPE_SENSOR	"sensor"
+#define	TOPO_FAC_TYPE_INDICATOR	"indicator"
+
+/*
+ * Topo property get functions
+ */
 extern int topo_prop_get_int32(tnode_t *, const char *, const char *,
     int32_t *, int *);
 extern int topo_prop_get_uint32(tnode_t *, const char *, const char *,
@@ -121,6 +150,8 @@
     int64_t *, int *);
 extern int topo_prop_get_uint64(tnode_t *, const char *, const char *,
     uint64_t *, int *);
+extern int topo_prop_get_double(tnode_t *, const char *, const char *,
+    double *, int *);
 extern int topo_prop_get_string(tnode_t *, const char *, const char *,
     char **, int *);
 extern int topo_prop_get_fmri(tnode_t *, const char *, const char *,
@@ -138,6 +169,36 @@
 extern int topo_prop_get_fmri_array(tnode_t *, const char *, const char *,
     nvlist_t ***, uint_t *, int *);
 
+/*
+ * Topo property set functions
+ */
+extern int topo_prop_set_int32(tnode_t *, const char *, const char *, int,
+    int32_t, int *);
+extern int topo_prop_set_uint32(tnode_t *, const char *, const char *, int,
+    uint32_t, int *);
+extern int topo_prop_set_int64(tnode_t *, const char *, const char *,
+    int, int64_t, int *);
+extern int topo_prop_set_uint64(tnode_t *, const char *, const char *,
+    int, uint64_t, int *);
+extern int topo_prop_set_double(tnode_t *, const char *, const char *,
+    int, double, int *);
+extern int topo_prop_set_string(tnode_t *, const char *, const char *,
+    int, const char *, int *);
+extern int topo_prop_set_fmri(tnode_t *, const char *, const char *,
+    int, const nvlist_t *, int *);
+extern int topo_prop_set_int32_array(tnode_t *, const char *, const char *, int,
+    int32_t *, uint_t, int *);
+extern int topo_prop_set_uint32_array(tnode_t *, const char *, const char *,
+    int, uint32_t *, uint_t, int *);
+extern int topo_prop_set_int64_array(tnode_t *, const char *, const char *,
+    int, int64_t *, uint_t, int *);
+extern int topo_prop_set_uint64_array(tnode_t *, const char *, const char *,
+    int, uint64_t *, uint_t, int *);
+extern int topo_prop_set_string_array(tnode_t *, const char *, const char *,
+    int, const char **, uint_t, int *);
+extern int topo_prop_set_fmri_array(tnode_t *, const char *, const char *,
+    int, const nvlist_t **, uint_t, int *);
+
 #define	TOPO_PROP_IMMUTABLE	0
 #define	TOPO_PROP_MUTABLE	1
 
@@ -150,6 +211,8 @@
 #define	TOPO_PROP_PKG		"package"	/* software package FMRI */
 #define	TOPO_PROP_LABEL		"label"		/*  property LABEL */
 
+#define	TOPO_METH_FAC_ENUM	"fac_enum"
+
 /*
  * System property group
  */
@@ -270,7 +333,8 @@
 	TOPO_TYPE_INT64_ARRAY,	/* array of int64_t */
 	TOPO_TYPE_UINT64_ARRAY,	/* array of uint64_t */
 	TOPO_TYPE_STRING_ARRAY,	/* array of const char* */
-	TOPO_TYPE_FMRI_ARRAY	/* array of nvlist_t */
+	TOPO_TYPE_FMRI_ARRAY,	/* array of nvlist_t */
+	TOPO_TYPE_DOUBLE	/* double */
 } topo_type_t;
 
 extern nvlist_t *topo_prop_getprops(tnode_t *, int *err);
@@ -313,6 +377,590 @@
 extern int topo_hdl_nvdup(topo_hdl_t *, nvlist_t *, nvlist_t **);
 extern char *topo_hdl_strdup(topo_hdl_t *, const char *);
 
+/*
+ * Interfaces for converting sensor/indicator types, units, states, etc to
+ * a string
+ */
+void topo_sensor_type_name(uint32_t type, char *buf, size_t len);
+void topo_sensor_units_name(uint8_t type, char *buf, size_t len);
+void topo_led_type_name(uint8_t type, char *buf, size_t len);
+void topo_led_state_name(uint8_t type, char *buf, size_t len);
+void topo_sensor_state_name(uint32_t sensor_type, uint8_t state, char *buf,
+    size_t len);
+
+/*
+ * Defines for standard properties for sensors and indicators
+ */
+#define	TOPO_PGROUP_FACILITY	"facility"
+
+#define	TOPO_SENSOR_READING	"reading"
+#define	TOPO_SENSOR_STATE	"state"
+#define	TOPO_SENSOR_CLASS	"sensor-class"
+#define	TOPO_FACILITY_TYPE	"type"
+#define	TOPO_SENSOR_UNITS	"units"
+#define	TOPO_LED_MODE		"mode"
+
+/*
+ * Sensor Classes
+ *
+ * The "sensor-class" property in the "facility" propgroup on
+ * facility nodes of type "sensor" should be set to one of these
+ * two values.
+ *
+ * Threshold sensors provide an analog sensor reading via the
+ * "reading" property in the facility propgroup.  They will also
+ * provide one or more discrete states via the "state" property
+ * in the facility propgroup.
+ *
+ * Discrete sensors will not provide an analog reading by will
+ * provide one or more discrete states via the "state" property
+ * in the facility propgroup.
+ */
+#define	TOPO_SENSOR_CLASS_THRESHOLD	"threshold"
+#define	TOPO_SENSOR_CLASS_DISCRETE	"discrete"
+
+/*
+ * Sensor unit types.  We're using the unit types and corresponding
+ * codes described in the IPMI 2.0 spec as a reference as it seems to be a
+ * reasonably comprehensive list.  This also simplifies the IPMI provider code
+ * since the unit type codes will map exactly to what libtopo uses (so no
+ * conversion necessary).
+ */
+typedef enum topo_sensor_unit {
+	TOPO_SENSOR_UNITS_UNSPECIFIED = 0,
+	TOPO_SENSOR_UNITS_DEGREES_C,
+	TOPO_SENSOR_UNITS_DEGREES_F,
+	TOPO_SENSOR_UNITS_DEGREES_K,
+	TOPO_SENSOR_UNITS_VOLTS,
+	TOPO_SENSOR_UNITS_AMPS,
+	TOPO_SENSOR_UNITS_WATTS,
+	TOPO_SENSOR_UNITS_JOULES,
+	TOPO_SENSOR_UNITS_COULOMBS,
+	TOPO_SENSOR_UNITS_VA,
+	TOPO_SENSOR_UNITS_NITS,
+	TOPO_SENSOR_UNITS_LUMEN,
+	TOPO_SENSOR_UNITS_LUX,
+	TOPO_SENSOR_UNITS_CANDELA,
+	TOPO_SENSOR_UNITS_KPA,
+	TOPO_SENSOR_UNITS_PSI,
+
+	TOPO_SENSOR_UNITS_NEWTON,
+	TOPO_SENSOR_UNITS_CFM,
+	TOPO_SENSOR_UNITS_RPM,
+	TOPO_SENSOR_UNITS_HZ,
+	TOPO_SENSOR_UNITS_MICROSEC,
+	TOPO_SENSOR_UNITS_MILLISEC,
+	TOPO_SENSOR_UNITS_SECS,
+	TOPO_SENSOR_UNITS_MIN,
+	TOPO_SENSOR_UNITS_HOUR,
+	TOPO_SENSOR_UNITS_DAY,
+	TOPO_SENSOR_UNITS_WEEK,
+	TOPO_SENSOR_UNITS_MIL,
+	TOPO_SENSOR_UNITS_INCHES,
+	TOPO_SENSOR_UNITS_FEET,
+	TOPO_SENSOR_UNITS_CUB_INCH,
+	TOPO_SENSOR_UNITS_CUB_FEET,
+
+	TOPO_SENSOR_UNITS_MM,
+	TOPO_SENSOR_UNITS_CM,
+	TOPO_SENSOR_UNITS_METERS,
+	TOPO_SENSOR_UNITS_CUB_CM,
+	TOPO_SENSOR_UNITS_CUB_METER,
+	TOPO_SENSOR_UNITS_LITERS,
+	TOPO_SENSOR_UNITS_FLUID_OUNCE,
+	TOPO_SENSOR_UNITS_RADIANS,
+	TOPO_SENSOR_UNITS_STERADIANS,
+	TOPO_SENSOR_UNITS_REVOLUTIONS,
+	TOPO_SENSOR_UNITS_CYCLES,
+	TOPO_SENSOR_UNITS_GRAVITIES,
+	TOPO_SENSOR_UNITS_OUNCE,
+	TOPO_SENSOR_UNITS_POUND,
+	TOPO_SENSOR_UNITS_FOOT_POUND,
+	TOPO_SENSOR_UNITS_OZ_INCH,
+
+	TOPO_SENSOR_UNITS_GAUSS,
+	TOPO_SENSOR_UNITS_GILBERTS,
+	TOPO_SENSOR_UNITS_HENRY,
+	TOPO_SENSOR_UNITS_MILHENRY,
+	TOPO_SENSOR_UNITS_FARAD,
+	TOPO_SENSOR_UNITS_MICROFARAD,
+	TOPO_SENSOR_UNITS_OHMS,
+	TOPO_SENSOR_UNITS_SIEMENS,
+	TOPO_SENSOR_UNITS_MOLE,
+	TOPO_SENSOR_UNITS_BECQUEREL,
+	TOPO_SENSOR_UNITS_PPM,
+	TOPO_SENSOR_UNITS_RESERVED1,
+	TOPO_SENSOR_UNITS_DECIBELS,
+	TOPO_SENSOR_UNITS_DBA,
+	TOPO_SENSOR_UNITS_DBC,
+	TOPO_SENSOR_UNITS_GRAY,
+
+	TOPO_SENSOR_UNITS_SIEVERT,
+	TOPO_SENSOR_UNITS_COLOR_TEMP_K,
+	TOPO_SENSOR_UNITS_BIT,
+	TOPO_SENSOR_UNITS_KILOBIT,
+	TOPO_SENSOR_UNITS_MEGABIT,
+	TOPO_SENSOR_UNITS_GIGABIT,
+	TOPO_SENSOR_UNITS_BYTE,
+	TOPO_SENSOR_UNITS_KILOBYTE,
+	TOPO_SENSOR_UNITS_MEGABYTE,
+	TOPO_SENSOR_UNITS_GIGABYTE,
+	TOPO_SENSOR_UNITS_WORD,
+	TOPO_SENSOR_UNITS_DWORD,
+	TOPO_SENSOR_UNITS_QWORD,
+	TOPO_SENSOR_UNITS_MEMLINE,
+	TOPO_SENSOR_UNITS_HIT,
+	TOPO_SENSOR_UNITS_MISS,
+
+	TOPO_SENSOR_UNITS_RETRY,
+	TOPO_SENSOR_UNITS_RESET,
+	TOPO_SENSOR_UNITS_OVERFLOW,
+	TOPO_SENSOR_UNITS_UNDERRUN,
+	TOPO_SENSOR_UNITS_COLLISION,
+	TOPO_SENSOR_UNITS_PACKETS,
+	TOPO_SENSOR_UNITS_MESSAGES,
+	TOPO_SENSOR_UNITS_CHARACTERS,
+	TOPO_SENSOR_UNITS_ERROR,
+	TOPO_SENSOR_UNITS_CE,
+	TOPO_SENSOR_UNITS_UE,
+	TOPO_SENSOR_UNITS_FATAL_ERROR,
+	TOPO_SENSOR_UNITS_GRAMS
+} topo_sensor_unit_t;
+
+/*
+ * Sensor Types amd the associated sensor-type-specific states
+ *
+ * These are used to decode the type and state properties in the facility
+ * propgroup on facility nodes of type sensor.
+ *
+ * Again we're basically using the same defines as for IPMI as it's serves
+ * as a good starting point and simplifies the IPMI provider code.  Of course
+ * other facility providers will need to convert from their native codes
+ * to the topo code when they set the type and state properties.
+ */
+#define	TOPO_SENSOR_TYPE_RESERVED			0x0000
+#define	TOPO_SENSOR_TYPE_TEMP				0x0001
+#define	TOPO_SENSOR_TYPE_VOLTAGE			0x0002
+#define	TOPO_SENSOR_TYPE_CURRENT			0x0003
+#define	TOPO_SENSOR_TYPE_FAN				0x0004
+#define	TOPO_SENSOR_TYPE_PHYSICAL			0x0005
+
+#define	TOPO_SENSOR_STATE_PHYSICAL_GENERAL		0x0001
+#define	TOPO_SENSOR_STATE_PHYSICAL_BAY			0x0002
+#define	TOPO_SENSOR_STATE_PHYSICAL_CARD			0x0004
+#define	TOPO_SENSOR_STATE_PHYSICAL_PROCESSOR		0x0008
+#define	TOPO_SENSOR_STATE_PHYSICAL_LAN			0x0010
+#define	TOPO_SENSOR_STATE_PHYSICAL_DOCK			0x0020
+#define	TOPO_SENSOR_STATE_PHYSICAL_FAN			0x0040
+
+#define	TOPO_SENSOR_TYPE_PLATFORM			0x0006
+
+#define	TOPO_SENSOR_STATE_PLATFORM_SECURE		0x0001
+#define	TOPO_SENSOR_STATE_PLATFORM_USER_PASS		0x0002
+#define	TOPO_SENSOR_STATE_PLATFORM_SETUP_PASS		0x0004
+#define	TOPO_SENSOR_STATE_PLATFORM_NETWORK_PASS		0x0008
+#define	TOPO_SENSOR_STATE_PLATFORM_OTHER_PASS		0x0010
+#define	TOPO_SENSOR_STATE_PLATFORM_OUT_OF_BAND		0x0020
+
+#define	TOPO_SENSOR_TYPE_PROCESSOR			0x0007
+
+#define	TOPO_SENSOR_STATE_PROCESSOR_IERR		0x0001
+#define	TOPO_SENSOR_STATE_PROCESSOR_THERMAL		0x0002
+#define	TOPO_SENSOR_STATE_PROCESSOR_FRB1		0x0004
+#define	TOPO_SENSOR_STATE_PROCESSOR_FRB2		0x0008
+#define	TOPO_SENSOR_STATE_PROCESSOR_FRB3		0x0010
+#define	TOPO_SENSOR_STATE_PROCESSOR_CONFIG		0x0020
+#define	TOPO_SENSOR_STATE_PROCESSOR_SMBIOS		0x0040
+#define	TOPO_SENSOR_STATE_PROCESSOR_PRESENT		0x0080
+#define	TOPO_SENSOR_STATE_PROCESSOR_DISABLED		0x0100
+#define	TOPO_SENSOR_STATE_PROCESSOR_TERMINATOR		0x0200
+#define	TOPO_SENSOR_STATE_PROCESSOR_THROTTLED		0x0400
+
+#define	TOPO_SENSOR_TYPE_POWER_SUPPLY			0x0008
+
+#define	TOPO_SENSOR_STATE_POWER_SUPPLY_PRESENT		0x0001
+#define	TOPO_SENSOR_STATE_POWER_SUPPLY_FAILURE		0x0002
+#define	TOPO_SENSOR_STATE_POWER_SUPPLY_PREDFAIL		0x0004
+#define	TOPO_SENSOR_STATE_POWER_SUPPLY_INPUT_LOST	0x0008
+#define	TOPO_SENSOR_STATE_POWER_SUPPLY_INPUT_RANGE	0x0010
+#define	TOPO_SENSOR_STATE_POWER_SUPPLY_INPUT_RANGE_PRES	0x0020
+#define	TOPO_SENSOR_STATE_POWER_SUPPLY_CONFIG_ERR	0x0040
+
+#define	TOPO_SENSOR_TYPE_POWER_UNIT			0x0009
+
+#define	TOPO_SENSOR_STATE_POWER_UNIT_OFF		0x0001
+#define	TOPO_SENSOR_STATE_POWER_UNIT_CYCLE		0x0002
+#define	TOPO_SENSOR_STATE_POWER_UNIT_240_DOWN		0x0004
+#define	TOPO_SENSOR_STATE_POWER_UNIT_INTERLOCK_DOWN	0x0008
+#define	TOPO_SENSOR_STATE_POWER_UNIT_AC_LOST		0x0010
+#define	TOPO_SENSOR_STATE_POWER_UNIT_SOFT_FAILURE	0x0020
+#define	TOPO_SENSOR_STATE_POWER_UNIT_FAIL		0x0040
+#define	TOPO_SENSOR_STATE_POWER_UNIT_PREDFAIL		0x0080
+
+#define	TOPO_SENSOR_TYPE_COOLING			0x000A
+#define	TOPO_SENSOR_TYPE_OTHER				0x000B
+
+#define	TOPO_SENSOR_TYPE_MEMORY				0x000C
+
+#define	TOPO_SENSOR_STATE_MEMORY_CE			0x0001
+#define	TOPO_SENSOR_STATE_MEMORY_UE			0x0002
+#define	TOPO_SENSOR_STATE_MEMORY_PARITY			0x0004
+#define	TOPO_SENSOR_STATE_MEMORY_SCRUB_FAIL		0x0008
+#define	TOPO_SENSOR_STATE_MEMORY_DISABLED		0x0010
+#define	TOPO_SENSOR_STATE_MEMORY_CE_LOG_LIMIT		0x0020
+#define	TOPO_SENSOR_STATE_MEMORY_PRESENT		0x0040
+#define	TOPO_SENSOR_STATE_MEMORY_CONFIG_ERR		0x0080
+#define	TOPO_SENSOR_STATE_MEMORY_SPARE			0x0100
+#define	TOPO_SENSOR_STATE_MEMORY_THROTTLED		0x0200
+#define	TOPO_SENSOR_STATE_MEMORY_OVERTEMP		0x0400
+
+#define	TOPO_SENSOR_TYPE_BAY				0x000D
+
+#define	TOPO_SENSOR_STATE_BAY_PRESENT			0x0001
+#define	TOPO_SENSOR_STATE_BAY_FAULT			0x0002
+#define	TOPO_SENSOR_STATE_BAY_PREDFAIL			0x0004
+#define	TOPO_SENSOR_STATE_BAY_SPARE			0x0008
+#define	TOPO_SENSOR_STATE_BAY_CHECK			0x0010
+#define	TOPO_SENSOR_STATE_BAY_CRITICAL			0x0020
+#define	TOPO_SENSOR_STATE_BAY_FAILED			0x0040
+#define	TOPO_SENSOR_STATE_BAY_REBUILDING		0x0080
+#define	TOPO_SENSOR_STATE_BAY_ABORTED			0x0100
+
+#define	TOPO_SENSOR_TYPE_POST_RESIZE			0x000E
+
+#define	TOPO_SENSOR_TYPE_FIRMWARE			0x000F
+
+#define	TOPO_SENSOR_STATE_FIRMWARE_ERROR		0x0001
+#define	TOPO_SENSOR_STATE_FIRMWARE_HANG			0x0002
+#define	TOPO_SENSOR_STATE_FIRMWARE_PROGRESS		0x0004
+
+#define	TOPO_SENSOR_TYPE_EVENT_LOG			0x0010
+
+#define	TOPO_SENSOR_STATE_EVENT_LOG_CE			0x0001
+#define	TOPO_SENSOR_STATE_EVENT_LOG_TYPE		0x0002
+#define	TOPO_SENSOR_STATE_EVENT_LOG_RESET		0x0004
+#define	TOPO_SENSOR_STATE_EVENT_LOG_ALL			0x0008
+#define	TOPO_SENSOR_STATE_EVENT_LOG_FULL		0x0010
+#define	TOPO_SENSOR_STATE_EVENT_LOG_ALMOST_FULL		0x0020
+
+#define	TOPO_SENSOR_TYPE_WATCHDOG1			0x0011
+
+#define	TOPO_SENSOR_STATE_WATCHDOG_BIOS_RESET		0x0001
+#define	TOPO_SENSOR_STATE_WATCHDOG_OS_RESET		0x0002
+#define	TOPO_SENSOR_STATE_WATCHDOG_OS_SHUTDOWN		0x0004
+#define	TOPO_SENSOR_STATE_WATCHDOG_OS_PWR_DOWN		0x0008
+#define	TOPO_SENSOR_STATE_WATCHDOG_OS_PWR_CYCLE		0x0010
+#define	TOPO_SENSOR_STATE_WATCHDOG_OS_NMI_DIAG		0x0020
+#define	TOPO_SENSOR_STATE_WATCHDOG_EXPIRED		0x0040
+#define	TOPO_SENSOR_STATE_WATCHDOG_PRE_TIMEOUT_INT	0x0080
+
+#define	TOPO_SENSOR_TYPE_SYSTEM				0x0012
+
+#define	TOPO_SENSOR_STATE_SYSTEM_RECONF			0x0001
+#define	TOPO_SENSOR_STATE_SYSTEM_BOOT			0x0002
+#define	TOPO_SENSOR_STATE_SYSTEM_UNKNOWN_HW_FAILURE	0x0004
+#define	TOPO_SENSOR_STATE_SYSTEM_AUX_LOG_UPDATED	0x0008
+#define	TOPO_SENSOR_STATE_SYSTEM_PEF_ACTION		0x0010
+#define	TOPO_SENSOR_STATE_SYSTEM_TIMETAMP_CLOCKSYNC	0x0020
+
+#define	TOPO_SENSOR_TYPE_CRITICAL			0x0013
+
+#define	TOPO_SENSOR_STATE_CRITICAL_EXT_NMI		0x0001
+#define	TOPO_SENSOR_STATE_CRITICAL_BUS_TIMEOUT		0x0002
+#define	TOPO_SENSOR_STATE_CRITICAL_IO_NMI		0x0004
+#define	TOPO_SENSOR_STATE_CRITICAL_SW_NMI		0x0008
+#define	TOPO_SENSOR_STATE_CRITICAL_PCI_PERR		0x0010
+#define	TOPO_SENSOR_STATE_CRITICAL_PCI_SERR		0x0020
+#define	TOPO_SENSOR_STATE_CRITICAL_EISA_FAILSAFE	0x0040
+#define	TOPO_SENSOR_STATE_CRITICAL_BUS_CE		0x0080
+#define	TOPO_SENSOR_STATE_CRITICAL_BUS_UE		0x0100
+#define	TOPO_SENSOR_STATE_CRITICAL_FATAL_NMI		0x0200
+#define	TOPO_SENSOR_STATE_CRITICAL_BUS_FATAL_ERR	0x0400
+#define	TOPO_SENSOR_STATE_CRITICAL_BUS_DEGRADED		0x0800
+
+#define	TOPO_SENSOR_TYPE_BUTTON				0x0014
+
+#define	TOPO_SENSOR_STATE_BUTTON_PWR			0x0001
+#define	TOPO_SENSOR_STATE_BUTTON_SLEEP			0x0002
+#define	TOPO_SENSOR_STATE_BUTTON_RESET			0x0004
+#define	TOPO_SENSOR_STATE_BUTTON_FRU_LATCH		0x0008
+#define	TOPO_SENSOR_STATE_BUTTON_FRU_SERVICE		0x0010
+
+#define	TOPO_SENSOR_TYPE_MODULE				0x0015
+#define	TOPO_SENSOR_TYPE_MICROCONTROLLER		0x0016
+#define	TOPO_SENSOR_TYPE_CARD				0x0017
+#define	TOPO_SENSOR_TYPE_CHASSIS			0x0018
+
+#define	TOPO_SENSOR_TYPE_CHIPSET			0x0019
+
+#define	TOPO_SENSOR_STATE_CHIPSET_PWR_CTL_FAIL		0x0001
+
+#define	TOPO_SENSOR_TYPE_FRU				0x001A
+
+#define	TOPO_SENSOR_TYPE_CABLE				0x001B
+
+#define	TOPO_SENSOR_STATE_CABLE_CONNECTED		0x0001
+#define	TOPO_SENSOR_STATE_CABLE_CONFIG_ERR		0x0002
+
+#define	TOPO_SENSOR_TYPE_TERMINATOR			0x001C
+
+#define	TOPO_SENSOR_TYPE_BOOT_STATE			0x001D
+
+#define	TOPO_SENSOR_STATE_BOOT_STATE_BIOS_PWR_UP	0x0001
+#define	TOPO_SENSOR_STATE_BOOT_STATE_BIOS_HARD_RESET	0x0002
+#define	TOPO_SENSOR_STATE_BOOT_STATE_BIOS_WARM_RESET	0x0004
+#define	TOPO_SENSOR_STATE_BOOT_STATE_PXE_BOOT		0x0008
+#define	TOPO_SENSOR_STATE_BOOT_STATE_DIAG_BOOT		0x0010
+#define	TOPO_SENSOR_STATE_BOOT_STATE_OS_HARD_RESET	0x0020
+#define	TOPO_SENSOR_STATE_BOOT_STATE_OS_WARM_RESET	0x0040
+#define	TOPO_SENSOR_STATE_BOOT_STATE_SYS_RESTART	0x0080
+
+#define	TOPO_SENSOR_TYPE_BOOT_ERROR			0x001E
+
+#define	TOPO_SENSOR_STATE_BOOT_ERROR_NOMEDIA		0x0001
+#define	TOPO_SENSOR_STATE_BOOT_ERROR_NON_BOOTABLE_DISK	0x0002
+#define	TOPO_SENSOR_STATE_BOOT_ERROR_NO_PXE_SERVER	0x0004
+#define	TOPO_SENSOR_STATE_BOOT_ERROR_INV_BOOT_SECT	0x0008
+#define	TOPO_SENSOR_STATE_BOOT_ERROR_USR_SELECT_TIMEOUT	0x0010
+
+#define	TOPO_SENSOR_TYPE_BOOT_OS			0x001F
+
+#define	TOPO_SENSOR_STATE_BOOT_OS_A_DRV_BOOT_COMPLETE	0x0001
+#define	TOPO_SENSOR_STATE_BOOT_OS_C_DRV_BOOT_COMPLETE	0x0002
+#define	TOPO_SENSOR_STATE_BOOT_OS_PXE_BOOT_COMPLETE	0x0004
+#define	TOPO_SENSOR_STATE_BOOT_OS_DIAG_BOOT_COMPLETE	0x0008
+#define	TOPO_SENSOR_STATE_BOOT_OS_CDROM_BOOT_COMPLETE	0x0010
+#define	TOPO_SENSOR_STATE_BOOT_OS_ROM_BOOT_COMPLETE	0x0020
+#define	TOPO_SENSOR_STATE_BOOT_OS_UNSPEC_BOOT_COMPLETE	0x0040
+
+#define	TOPO_SENSOR_TYPE_OS_SHUTDOWN			0x0020
+
+#define	TOPO_SENSOR_STATE_OS_SHUTDOWN_LOADING		0x0001
+#define	TOPO_SENSOR_STATE_OS_SHUTDOWN_CRASH		0x0002
+#define	TOPO_SENSOR_STATE_OS_STOP_GRACEFUL		0x0004
+#define	TOPO_SENSOR_STATE_OS_SHUTDOWN_GRACEFUL		0x0008
+#define	TOPO_SENSOR_STATE_OS_SHUTDOWN_PEF		0x0010
+#define	TOPO_SENSOR_STATE_OS_SHUTDOWN_BMC		0x0020
+
+#define	TOPO_SENSOR_TYPE_SLOT				0x0021
+
+#define	TOPO_SENSOR_STATE_SLOT_FAULT_ASSERTED		0x0001
+#define	TOPO_SENSOR_STATE_SLOT_IDENTIFY_ASSERTED	0x0002
+#define	TOPO_SENSOR_STATE_SLOT_CONNECTED		0x0004
+#define	TOPO_SENSOR_STATE_SLOT_INSTALL_READY		0x0008
+#define	TOPO_SENSOR_STATE_SLOT_REMOVE_READY		0x0010
+#define	TOPO_SENSOR_STATE_SLOT_PWR_OFF			0x0020
+#define	TOPO_SENSOR_STATE_SLOT_REMOVED			0x0040
+#define	TOPO_SENSOR_STATE_SLOT_INTERLOCK_ASSERTED	0x0080
+#define	TOPO_SENSOR_STATE_SLOT_DISABLED			0x0100
+#define	TOPO_SENSOR_STATE_SLOT_SPARE_DEVICE		0x0200
+
+#define	TOPO_SENSOR_TYPE_ACPI				0x0022
+
+#define	TOPO_SENSOR_STATE_ACPI_PSTATE_S0_G0		0x0001
+#define	TOPO_SENSOR_STATE_ACPI_PSTATE_S1		0x0002
+#define	TOPO_SENSOR_STATE_ACPI_PSTATE_S2		0x0004
+#define	TOPO_SENSOR_STATE_ACPI_PSTATE_S3		0x0008
+#define	TOPO_SENSOR_STATE_ACPI_PSTATE_S4		0x0010
+#define	TOPO_SENSOR_STATE_ACPI_PSTATE_S5_G2_SOFT_OFF	0x0020
+#define	TOPO_SENSOR_STATE_ACPI_PSTATE_S4_S5_SOFT_OFF	0x0040
+#define	TOPO_SENSOR_STATE_ACPI_PSATTE_G3_MECH_OFF	0x0080
+#define	TOPO_SENSOR_STATE_ACPI_PSTATE_S1_S2_S3_SLEEP	0x0100
+#define	TOPO_SENSOR_STATE_ACPI_PSTATE_G1_SLEEP		0x0200
+#define	TOPO_SENSOR_STATE_ACPI_PSTATE_S5_OVERRIDE	0x0400
+#define	TOPO_SENSOR_STATE_ACPI_PSTATE_LEGACY_ON		0x0800
+#define	TOPO_SENSOR_STATE_ACPI_PSTATE_LEGACY_OFF	0x1000
+#define	TOPO_SENSOR_STATE_ACPI_PSTATE_UNKNOWN		0x2000
+
+#define	TOPO_SENSOR_TYPE_WATCHDOG2			0x0023
+
+#define	TOPO_SENSOR_STATE_WATCHDOG2_EXPIRED		0x0001
+#define	TOPO_SENSOR_STATE_WATCHDOG2_HARD_RESET		0x0002
+#define	TOPO_SENSOR_STATE_WATCHDOG2_PWR_DOWN		0x0004
+#define	TOPO_SENSOR_STATE_WATCHDOG2_PWR_CYCLE		0x0008
+#define	TOPO_SENSOR_STATE_WATCHDOG2_RESERVED1		0x0010
+#define	TOPO_SENSOR_STATE_WATCHDOG2_RESERVED2		0x0020
+#define	TOPO_SENSOR_STATE_WATCHDOG2_RESERVED3		0x0040
+#define	TOPO_SENSOR_STATE_WATCHDOG2_RESERVED4		0x0080
+#define	TOPO_SENSOR_STATE_WATCHDOG2_TIMEOUT_INT		0x0100
+
+#define	TOPO_SENSOR_TYPE_ALERT				0x0024
+
+#define	TOPO_SENSOR_STATE_ALERT_PLAT_PAGE		0x0001
+#define	TOPO_SENSOR_STATE_ALERT_PLAT_LAN_ALERT		0x0002
+#define	TOPO_SENSOR_STATE_ALERT_PLAT_EVT_TRAP		0x0004
+#define	TOPO_SENSOR_STATE_ALERT_PLAT_SNMP_TRAP		0x0008
+
+#define	TOPO_SENSOR_TYPE_PRESENCE			0x0025
+
+#define	TOPO_SENSOR_STATE_PRESENCE_PRESENT		0x0001
+#define	TOPO_SENSOR_STATE_PRESENCE_ABSENT		0x0002
+#define	TOPO_SENSOR_STATE_PRESENCE_DISABLED		0x0004
+
+#define	TOPO_SENSOR_TYPE_ASIC				0x0026
+
+#define	TOPO_SENSOR_TYPE_LAN				0x0027
+
+#define	TOPO_SENSOR_STATE_LAN_HEARTBEAT_LOST		0x0001
+#define	TOPO_SENSOR_STATE_LAN_HEARTBEAT			0x0002
+
+#define	TOPO_SENSOR_TYPE_HEALTH				0x0028
+
+#define	TOPO_SENSOR_STATE_HEALTH_SENSOR_ACC_DEGRADED	0x0001
+#define	TOPO_SENSOR_STATE_HEALTH_CNTLR_ACC_DEGRADED	0x0002
+#define	TOPO_SENSOR_STATE_HEALTH_CNTLR_OFFLINE		0x0004
+#define	TOPO_SENSOR_STATE_HEALTH_CNTLR_UNAVAIL		0x0008
+#define	TOPO_SENSOR_STATE_HEALTH_SENSOR_FAILURE		0x0010
+#define	TOPO_SENSOR_STATE_HEALTH_FRU_FAILURE		0x0020
+
+#define	TOPO_SENSOR_TYPE_BATTERY			0x0029
+
+#define	TOPO_SENSOR_STATE_BATTERY_LOW			0x0001
+#define	TOPO_SENSOR_STATE_BATTERY_FAILED		0x0002
+#define	TOPO_SENSOR_STATE_BATTERY_PRESENCE		0x0004
+
+#define	TOPO_SENSOR_TYPE_AUDIT				0x002A
+
+#define	TOPO_SENSOR_STATE_AUDIT_SESSION_ACTIVATED	0x0001
+#define	TOPO_SENSOR_STATE_AUDIT_SESSION_DEACTIVATED	0x0002
+
+#define	TOPO_SENSOR_TYPE_VERSION			0x002B
+
+#define	TOPO_SENSOR_STATE_VERSION_HW_CHANGE		0x0001
+#define	TOPO_SENSOR_STATE_VERSION_SW_CHANGE		0x0002
+#define	TOPO_SENSOR_STATE_VERSION_HW_INCOMPATIBLE	0x0004
+#define	TOPO_SENSOR_STATE_VERSION_SW_INCOMPATIBLE	0x0008
+#define	TOPO_SENSOR_STATE_VERSION_HW_INVAL		0x0010
+#define	TOPO_SENSOR_STATE_VERSION_SW_INVAL		0x0020
+#define	TOPO_SENSOR_STATE_VERSION_HW_CHANGE_SUCCESS	0x0040
+#define	TOPO_SENSOR_STATE_VERSION_SW_CHANGE_SUCCESS	0x0080
+
+#define	TOPO_SENSOR_TYPE_FRU_STATE			0x002C
+
+#define	TOPO_SENSOR_STATE_FRU_STATE_NOT_INSTALLED	0x0001
+#define	TOPO_SENSOR_STATE_FRU_STATE_INACTIVE		0x0002
+#define	TOPO_SENSOR_STATE_FRU_STATE_ACT_REQ		0x0004
+#define	TOPO_SENSOR_STATE_FRU_STATE_ACT_INPROGRESS	0x0008
+#define	TOPO_SENSOR_STATE_FRU_STATE_ACTIVE		0x0010
+#define	TOPO_SENSOR_STATE_FRU_STATE_DEACT_REQ		0x0020
+#define	TOPO_SENSOR_STATE_FRU_STATE_DEACT_INPROGRESS	0x0040
+#define	TOPO_SENSOR_STATE_FRU_STATE_COMM_LOST		0x0080
+
+/*
+ * We simplify the IPMI sensor type code defines by combining the generic
+ * and sensor-specific codes into a single range.  Because there's overlap
+ * between the two ranges we offset the generic type codes by 0x0100
+ * which allows ample room in the hole for future expansion of the table to
+ * accomodate either additions to the IPMI spec or to support new sensor types
+ * for alternate provider modules.
+ */
+#define	TOPO_SENSOR_TYPE_THRESHOLD_STATE	0x0101
+
+#define	TOPO_SENSOR_THRESH_LOWER_NONCRIT_GOING_LOW	0x0001
+#define	TOPO_SENSOR_THRESH_LOWER_NONCRIT_GOING_HIGH	0x0002
+#define	TOPO_SENSOR_THRESH_LOWER_CRIT_GOING_LOW		0x0004
+#define	TOPO_SENSOR_THRESH_LOWER_CRIT_GOING_HIGH	0x0008
+#define	TOPO_SENSOR_THRESH_LOWER_NONREC_GOING_LOW	0x0010
+#define	TOPO_SENSOR_THRESH_LOWER_NONREC_GOING_HIGH	0x0020
+#define	TOPO_SENSOR_THRESH_UPPER_NONCRIT_GOING_LOW	0x0040
+#define	TOPO_SENSOR_THRESH_UPPER_NONCRIT_GOING_HIGH	0x0080
+#define	TOPO_SENSOR_THRESH_UPPER_CRIT_GOING_LOW		0x0100
+#define	TOPO_SENSOR_THRESH_UPPER_CRIT_GOING_HIGH	0x0200
+#define	TOPO_SENSOR_THRESH_UPPER_NONREC_GOING_LOW	0x0400
+#define	TOPO_SENSOR_THRESH_UPPER_NONREC_GOING_HIGH	0x0800
+
+#define	TOPO_SENSOR_TYPE_GENERIC_USAGE			0x0102
+
+#define	TOPO_SENSOR_STATE_GENERIC_USAGE_IDLE		0x0001
+#define	TOPO_SENSOR_STATE_GENERIC_USAGE_ACTIVE		0x0002
+#define	TOPO_SENSOR_STATE_GENERIC_USAGE_BUSY		0x0004
+
+#define	TOPO_SENSOR_TYPE_GENERIC_STATE			0x0103
+
+#define	TOPO_SENSOR_STATE_GENERIC_STATE_DEASSERTED	0x0001
+#define	TOPO_SENSOR_STATE_GENERIC_STATE_ASSERTED	0x0002
+
+#define	TOPO_SENSOR_TYPE_GENERIC_PREDFAIL		0x0104
+
+#define	TOPO_SENSOR_STATE_GENERIC_PREDFAIL_DEASSERTED	0x0001
+#define	TOPO_SENSOR_STATE_GENERIC_PREDFAIL_ASSERTED	0x0002
+
+#define	TOPO_SENSOR_TYPE_GENERIC_LIMIT			0x0105
+
+#define	TOPO_SENSOR_STATE_GENERIC_LIMIT_NOT_EXCEEDED	0x0001
+#define	TOPO_SENSOR_STATE_GENERIC_LIMIT_EXCEEDED	0x0002
+
+#define	TOPO_SENSOR_TYPE_GENERIC_PERFORMANCE		0x0106
+
+#define	TOPO_SENSOR_STATE_GENERIC_PERFORMANCE_MET	0x0001
+#define	TOPO_SENSOR_STATE_GENERIC_PERFORMANCE_LAGS	0x0002
+
+#define	TOPO_SENSOR_TYPE_SEVERITY			0x0107
+
+#define	TOPO_SENSOR_STATE_SEVERITY_OK			0x0001
+#define	TOPO_SENSOR_STATE_SEVERITY_NONCRIT_GOING_HIGH	0x0002
+#define	TOPO_SENSOR_STATE_SEVERITY_CRIT_GOING_HIGH	0x0004
+#define	TOPO_SENSOR_STATE_SEVERITY_NONREC_GOING_HIGH	0x0008
+#define	TOPO_SENSOR_STATE_SEVERITY_NONCRIT_GOING_LOW	0x0010
+#define	TOPO_SENSOR_STATE_SEVERITY_CRIT_GOING_LOW	0x0020
+#define	TOPO_SENSOR_STATE_SEVERITY_NONREC_GOING_LOW	0x0020
+#define	TOPO_SENSOR_STATE_SEVERITY_MONITOR		0x0040
+#define	TOPO_SENSOR_STATE_SEVERITY_INFORMATIONAL	0x0080
+
+#define	TOPO_SENSOR_TYPE_GENERIC_PRESENCE		0x0108
+
+#define	TOPO_SENSOR_STATE_GENERIC_PRESENCE_DEASSERTED	0x0001
+#define	TOPO_SENSOR_STATE_GENERIC_PRESENCE_ASSERTED	0x0002
+
+#define	TOPO_SENSOR_TYPE_GENERIC_AVAILABILITY		0x0109
+
+#define	TOPO_SENSOR_STATE_GENERIC_AVAIL_DEASSERTED	0x0001
+#define	TOPO_SENSOR_STATE_GENERIC_AVAIL_ASSERTED	0x0002
+
+#define	TOPO_SENSOR_TYPE_GENERIC_STATUS			0x010A
+
+#define	TOPO_SENSOR_STATE_GENERIC_STATUS_RUNNING	0x0001
+#define	TOPO_SENSOR_STATE_GENERIC_STATUS_IN_TEST	0x0002
+#define	TOPO_SENSOR_STATE_GENERIC_STATUS_POWER_OFF	0x0004
+#define	TOPO_SENSOR_STATE_GENERIC_STATUS_ONLINE		0x0008
+#define	TOPO_SENSOR_STATE_GENERIC_STATUS_OFFLINE	0x0010
+#define	TOPO_SENSOR_STATE_GENERIC_STATUS_OFF_DUTY	0x0020
+#define	TOPO_SENSOR_STATE_GENERIC_STATUS_DEGRADED	0x0040
+#define	TOPO_SENSOR_STATE_GENERIC_STATUS_POWER_SAVE	0x0080
+#define	TOPO_SENSOR_STATE_GENERIC_STATUS_INSTALL_ERR	0x0100
+
+#define	TOPO_SENSOR_TYPE_GENERIC_REDUNDANCY		0x010B
+
+/*
+ * ACPI power state
+ */
+#define	TOPO_SENSOR_TYPE_GENERIC_ACPI			0x010C
+
+#define	TOPO_SENSOR_STATE_GENERIC_ACPI_D0		0x0001
+#define	TOPO_SENSOR_STATE_GENERIC_ACPI_D1		0x0002
+#define	TOPO_SENSOR_STATE_GENERIC_ACPI_D2		0x0004
+#define	TOPO_SENSOR_STATE_GENERIC_ACPI_D3		0x0008
+
+/*
+ * Indicator modes and types
+ */
+typedef enum topo_led_state {
+	TOPO_LED_STATE_OFF = 0,
+	TOPO_LED_STATE_ON
+} topo_led_state_t;
+
+/*
+ * This list is limited to the set of LED's that we're likely to manage through
+ * FMA.  Thus is does not include things like power or activity LED's
+ */
+typedef enum topo_led_type {
+	TOPO_LED_TYPE_SERVICE = 0,
+	TOPO_LED_TYPE_LOCATE,
+	TOPO_LED_TYPE_OK2RM,
+	TOPO_LED_TYPE_PRESENT
+} topo_led_type_t;
+
+
 #ifdef __cplusplus
 }
 #endif
--- a/usr/src/lib/fm/topo/libtopo/common/mapfile-vers	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/mapfile-vers	Thu Jul 31 17:35:39 2008 -0700
@@ -34,6 +34,7 @@
 	topo_fmri_contains;
 	topo_fmri_create;
 	topo_fmri_expand;
+	topo_fmri_facility;
 	topo_fmri_fru;
 	topo_fmri_getpgrp;
 	topo_fmri_getprop;
@@ -55,10 +56,13 @@
 	topo_hdl_strdup;
 	topo_hdl_strfree;
 	topo_hdl_zalloc;
+	topo_led_state_name;
+	topo_led_type_name;
 	topo_list_append;
 	topo_list_delete;
 	topo_method_invoke;
 	topo_method_register;
+	topo_method_supported;
 	topo_method_unregister;
 	topo_method_unregister_all;
 	topo_mod_alloc;
@@ -98,6 +102,9 @@
 	topo_node_asru;
 	topo_node_asru_set;
 	topo_node_bind;
+	topo_node_facility;
+	topo_node_facbind;
+	topo_node_flags;
 	topo_node_fru;
 	topo_node_fru_set;
 	topo_node_getspecific;
@@ -121,6 +128,7 @@
 	topo_prop_get_string;
 	topo_prop_get_uint32;
 	topo_prop_get_uint64;
+	topo_prop_get_double;
 	topo_prop_get_int32_array;
 	topo_prop_get_uint32_array;
 	topo_prop_get_int64_array;
@@ -139,6 +147,7 @@
 	topo_prop_set_string;
 	topo_prop_set_uint32;
 	topo_prop_set_uint64;
+	topo_prop_set_double;
 	topo_prop_set_int32_array;
 	topo_prop_set_uint32_array;
 	topo_prop_set_int64_array;
@@ -146,7 +155,11 @@
 	topo_prop_set_string_array;
 	topo_prop_set_fmri_array;
 	topo_prop_setprop;
+	topo_prop_setmutable;
 	topo_name2stability;
+	topo_sensor_state_name;
+	topo_sensor_type_name;
+	topo_sensor_units_name;
 	topo_stability2name;
 	topo_snap_hold;
 	topo_snap_release;
--- a/usr/src/lib/fm/topo/libtopo/common/topo_2xml.c	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_2xml.c	Thu Jul 31 17:35:39 2008 -0700
@@ -38,7 +38,8 @@
 #include <topo_tree.h>
 
 #define	INT32BUFSZ	sizeof (UINT32_MAX) + 1
-#define	INT64BUFSZ	sizeof (UINT64_MAX) + 1
+/* 2 bytes for "0x" + 16 bytes for the hex value + 1 for sign + null */
+#define	INT64BUFSZ	20
 #define	XML_VERSION	"1.0"
 
 static int txml_print_range(topo_hdl_t *, FILE *, tnode_t *, int);
@@ -103,77 +104,88 @@
 }
 
 static void
-txml_print_prop(topo_hdl_t *thp, FILE *fp, topo_propval_t *pv)
+txml_print_prop(topo_hdl_t *thp, FILE *fp, tnode_t *node, const char *pgname,
+    topo_propval_t *pv)
 {
 	int err;
 	char *fmri = NULL;
-	char vbuf[INT64BUFSZ], tbuf[10], *pval, *aval;
-	nvpair_t *nvp;
-
-	nvp = nvlist_next_nvpair(pv->tp_val, NULL);
-	while (nvp && (strcmp(TOPO_PROP_VAL_VAL, nvpair_name(nvp)) != 0))
-			nvp = nvlist_next_nvpair(pv->tp_val, nvp);
-
-	if (nvp == NULL)
-		return;
+	char vbuf[INT64BUFSZ], tbuf[32], *pval = NULL, *aval;
 
 	switch (pv->tp_type) {
 		case TOPO_TYPE_INT32: {
 			int32_t val;
-			(void) nvpair_value_int32(nvp, &val);
-			(void) snprintf(vbuf, INT64BUFSZ, "%d", val);
-			(void) snprintf(tbuf, 10, "%s", Int32);
-			pval = vbuf;
+			if (topo_prop_get_int32(node, pgname, pv->tp_name, &val,
+			    &err) == 0) {
+				(void) snprintf(vbuf, INT64BUFSZ, "%d", val);
+				(void) snprintf(tbuf, 10, "%s", Int32);
+				pval = vbuf;
+			} else
+				return;
 			break;
 		}
 		case TOPO_TYPE_UINT32: {
 			uint32_t val;
-			(void) nvpair_value_uint32(nvp, &val);
-			(void) snprintf(vbuf, INT64BUFSZ, "0x%x", val);
-			(void) snprintf(tbuf, 10, "%s", UInt32);
-			pval = vbuf;
+			if (topo_prop_get_uint32(node, pgname, pv->tp_name,
+			    &val, &err) == 0) {
+				(void) snprintf(vbuf, INT64BUFSZ, "0x%x", val);
+				(void) snprintf(tbuf, 10, "%s", UInt32);
+				pval = vbuf;
+			} else
+				return;
 			break;
 		}
 		case TOPO_TYPE_INT64: {
 			int64_t val;
-			(void) nvpair_value_int64(nvp, &val);
-			(void) snprintf(vbuf, INT64BUFSZ, "%lld",
-			    (longlong_t)val);
-			(void) snprintf(tbuf, 10, "%s", Int64);
-			pval = vbuf;
+			if (topo_prop_get_int64(node, pgname, pv->tp_name, &val,
+			    &err) == 0) {
+				(void) snprintf(vbuf, INT64BUFSZ, "0x%llx",
+				    (longlong_t)val);
+				(void) snprintf(tbuf, 10, "%s", Int64);
+				pval = vbuf;
+			} else
+				return;
 			break;
 		}
 		case TOPO_TYPE_UINT64: {
 			uint64_t val;
-			(void) nvpair_value_uint64(nvp, &val);
-			(void) snprintf(vbuf, INT64BUFSZ, "0x%llx",
-			    (u_longlong_t)val);
-			(void) snprintf(tbuf, 10, "%s", UInt64);
-			pval = vbuf;
+			if (topo_prop_get_uint64(node, pgname, pv->tp_name,
+			    &val, &err) == 0) {
+				(void) snprintf(vbuf, INT64BUFSZ, "0x%llx",
+				    (u_longlong_t)val);
+				(void) snprintf(tbuf, 10, "%s", UInt64);
+				pval = vbuf;
+			} else
+				return;
 			break;
 		}
 		case TOPO_TYPE_STRING: {
-			(void) nvpair_value_string(nvp, &pval);
-			(void) snprintf(tbuf, 10, "%s", String);
+			if (topo_prop_get_string(node, pgname, pv->tp_name,
+			    &pval, &err) != 0)
+				return;
+			(void) snprintf(tbuf, 10, "%s", "string");
 			break;
 		}
 		case TOPO_TYPE_FMRI: {
 			nvlist_t *val;
 
-			(void) nvpair_value_nvlist(nvp, &val);
-			if (topo_fmri_nvl2str(thp, val, &fmri, &err) == 0)
-				pval = fmri;
-			else
+			if (topo_prop_get_fmri(node, pgname, pv->tp_name, &val,
+			    &err) == 0) {
+				if (topo_fmri_nvl2str(thp, val, &fmri, &err)
+				    == 0)
+					pval = fmri;
+				else
+					return;
+			} else
 				return;
-
 			(void) snprintf(tbuf, 10, "%s", FMRI);
 			break;
 		}
 		case TOPO_TYPE_UINT32_ARRAY: {
 			uint32_t *val;
 			uint_t nelem, i;
-
-			(void) nvpair_value_uint32_array(nvp, &val, &nelem);
+			if (topo_prop_get_uint32_array(node, pgname,
+			    pv->tp_name, &val, &nelem, &err) != 0)
+				return;
 
 			if (nelem > 0) {
 				aval = calloc((nelem*9-1), sizeof (uchar_t));
@@ -195,11 +207,10 @@
 
 	if (fmri != NULL)
 		topo_hdl_strfree(thp, fmri);
-
 }
 
 static void
-txml_print_pgroup(topo_hdl_t *thp, FILE *fp, topo_pgroup_t *pg)
+txml_print_pgroup(topo_hdl_t *thp, FILE *fp, tnode_t *node, topo_pgroup_t *pg)
 {
 	topo_ipgroup_info_t *pip = pg->tpg_info;
 	topo_proplist_t *plp;
@@ -213,7 +224,7 @@
 	    namestab, Datastab, datastab, Version, version, NULL);
 	for (plp = topo_list_next(&pg->tpg_pvals); plp != NULL;
 	    plp = topo_list_next(plp)) {
-		txml_print_prop(thp, fp, plp->tp_pval);
+		txml_print_prop(thp, fp, node, pip->tpi_name, plp->tp_pval);
 	}
 	end_element(fp, Propgrp);
 }
@@ -238,7 +249,7 @@
 	begin_element(fp, Node, Instance, inst, Static, True, NULL);
 	for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
 	    pg = topo_list_next(pg)) {
-		txml_print_pgroup(thp, fp, pg);
+		txml_print_pgroup(thp, fp, node, pg);
 	}
 	txml_print_dependents(thp, fp, node);
 	end_element(fp, Node);
--- a/usr/src/lib/fm/topo/libtopo/common/topo_error.h	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_error.h	Thu Jul 31 17:35:39 2008 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -64,13 +64,6 @@
     ETOPO_RTLD_NOMEM,	/* memory limit exceeded when opening shared library */
     ETOPO_BLTIN_NAME,	/* built-in plug-in name not found in definition list */
     ETOPO_BLTIN_INIT,	/* built-in plug-in does not define init function */
-    ETOPO_NODE_INVAL,	/* node opertation invalid argument */
-    ETOPO_NODE_LINKED,	/* node already linked */
-    ETOPO_NODE_BOUND,	/* node already bound */
-    ETOPO_NODE_DUP,	/* duplicate node */
-    ETOPO_NODE_RANGE,	/* invalid instance range */
-    ETOPO_NODE_NOENT,	/* node not found */
-    ETOPO_NODE_FMRI,	/* no fmri specified */
     ETOPO_VER_OLD,	/* plugin compiled using an obsolete topo ABI */
     ETOPO_VER_NEW,	/* plugin is compiled using a newer topo ABI */
     ETOPO_ENUM_PARTIAL,	/* partial enumeration completed for client */
@@ -93,6 +86,7 @@
     ETOPO_PRSR_REGMETH,	/* failed to register property method */
     ETOPO_WALK_EMPTY,	/* empty topology */
     ETOPO_WALK_NOTFOUND, /* scheme based topology not found */
+    ETOPO_FAC_NOENT,	/* no facility node of specified type found */
     ETOPO_END		/* end of custom errno list (to ease auto-merge) */
 } topo_errno_t;
 
--- a/usr/src/lib/fm/topo/libtopo/common/topo_fmri.c	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_fmri.c	Thu Jul 31 17:35:39 2008 -0700
@@ -690,3 +690,49 @@
 
 	return (strcmp(ea, eb) == 0);
 }
+
+int
+topo_fmri_facility(topo_hdl_t *thp, nvlist_t *rsrc, const char *fac_type,
+    uint32_t fac_subtype, topo_walk_cb_t cb, void *cb_args, int *err)
+{
+	int rv;
+	nvlist_t *in = NULL, *out;
+	tnode_t *rnode;
+	char *scheme;
+
+	if (nvlist_lookup_string(rsrc, FM_FMRI_SCHEME, &scheme) != 0)
+		return (set_error(thp, ETOPO_FMRI_MALFORM, err,
+		    TOPO_METH_PROP_GET, in));
+
+	if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
+		return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
+		    TOPO_METH_PROP_GET, in));
+
+	if (topo_hdl_nvalloc(thp, &in, NV_UNIQUE_NAME) != 0)
+		return (set_error(thp, ETOPO_FMRI_NVL, err,
+		    TOPO_METH_PROP_GET, in));
+
+	rv = nvlist_add_nvlist(in, TOPO_PROP_RESOURCE, rsrc);
+	rv |= nvlist_add_string(in, FM_FMRI_FACILITY_TYPE, fac_type);
+	rv |= nvlist_add_uint32(in, "type", fac_subtype);
+#ifdef _LP64
+	rv |= nvlist_add_uint64(in, "callback", (uint64_t)cb);
+	rv |= nvlist_add_uint64(in, "callback-args", (uint64_t)cb_args);
+#else
+	rv |= nvlist_add_uint32(in, "callback", (uint32_t)cb);
+	rv |= nvlist_add_uint32(in, "callback-args", (uint32_t)cb_args);
+#endif
+	if (rv != 0)
+		return (set_error(thp, ETOPO_FMRI_NVL, err,
+		    TOPO_METH_PROP_GET, in));
+
+	rv = topo_method_invoke(rnode, TOPO_METH_FACILITY,
+	    TOPO_METH_FACILITY_VERSION, in, &out, err);
+
+	nvlist_free(in);
+
+	if (rv != 0)
+		return (-1); /* *err is set for us */
+
+	return (0);
+}
--- a/usr/src/lib/fm/topo/libtopo/common/topo_method.c	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_method.c	Thu Jul 31 17:35:39 2008 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -58,6 +58,29 @@
 	return (NULL);
 }
 
+/*
+ * Simple API to determine if the specified node supports a given topo method
+ * (specified by the method name and version).  Returns true if supported, false
+ * otherwise.
+ */
+boolean_t
+topo_method_supported(tnode_t *node, const char *name, topo_version_t vers)
+{
+	topo_imethod_t *mp;
+
+	topo_node_lock(node);
+	for (mp = topo_list_next(&node->tn_methods); mp != NULL;
+	    mp = topo_list_next(mp)) {
+		if ((strcmp(name, mp->tim_name) == 0) &&
+		    (vers == mp->tim_version)) {
+			topo_node_unlock(node);
+			return (B_TRUE);
+		}
+	}
+	topo_node_unlock(node);
+	return (B_FALSE);
+}
+
 static void
 topo_method_enter(topo_imethod_t *mp)
 {
--- a/usr/src/lib/fm/topo/libtopo/common/topo_method.h	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_method.h	Thu Jul 31 17:35:39 2008 -0700
@@ -67,6 +67,7 @@
 #define	TOPO_METH_PROP_GET		"topo_prop_get"
 #define	TOPO_METH_PGRP_GET		"topo_pgrp_get"
 #define	TOPO_METH_PROP_SET		"topo_prop_set"
+#define	TOPO_METH_FACILITY		"topo_facility"
 
 #define	TOPO_METH_FMRI_VERSION			0
 #define	TOPO_METH_FRU_COMPUTE_VERSION		0
@@ -77,6 +78,7 @@
 #define	TOPO_METH_PROP_GET_VERSION		0
 #define	TOPO_METH_PGRP_GET_VERSION		0
 #define	TOPO_METH_PROP_SET_VERSION		0
+#define	TOPO_METH_FACILITY_VERSION		0
 
 #define	TOPO_METH_ASRU_COMPUTE_DESC	"Dynamic ASRU constructor"
 #define	TOPO_METH_FRU_COMPUTE_DESC	"Dynamic FRU constructor"
@@ -87,6 +89,7 @@
 #define	TOPO_METH_PROP_GET_DESC		"get properties for FMRI"
 #define	TOPO_METH_PGRP_GET_DESC		"get property group for FMRI"
 #define	TOPO_METH_PROP_SET_DESC		"set properties for FMRI"
+#define	TOPO_METH_FACILITY_DESC		"get facility for FMRI"
 
 #define	TOPO_METH_COMPARE_RET		"contains-return"
 
--- a/usr/src/lib/fm/topo/libtopo/common/topo_mod.h	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_mod.h	Thu Jul 31 17:35:39 2008 -0700
@@ -96,7 +96,8 @@
 extern nvlist_t *topo_mod_pkgfmri(topo_mod_t *, int, const char *);
 extern int topo_mod_nvl2str(topo_mod_t *, nvlist_t *, char **);
 extern int topo_mod_str2nvl(topo_mod_t *, const char *,  nvlist_t **);
-
+extern int topo_prop_setmutable(tnode_t *node, const char *pgname,
+    const char *pname, int *err);
 /*
  * Snapshot walker support
  */
@@ -127,8 +128,8 @@
 #define	TOPO_METH_LABEL_DESC		"label constructor"
 #define	TOPO_METH_LABEL_VERSION0	0
 #define	TOPO_METH_LABEL_VERSION		TOPO_METH_LABEL_VERSION0
-#define	TOPO_METH_LABEL_ARG_NVL	"label-specific"
-#define	TOPO_METH_LABEL_RET_STR	"label-string"
+#define	TOPO_METH_LABEL_ARG_NVL		"label-specific"
+#define	TOPO_METH_LABEL_RET_STR		"label-string"
 
 #define	TOPO_METH_PRESENT		"topo_present"
 #define	TOPO_METH_PRESENT_DESC		"presence indicator"
@@ -167,6 +168,11 @@
 #define	TOPO_METH_DISK_STATUS_VERSION	0
 #define	TOPO_METH_DISK_STATUS_DESC	"Disk status"
 
+#define	TOPO_PROP_METH_DESC		"Dynamic Property method"
+
+#define	TOPO_METH_IPMI_ENTITY		"ipmi_entity"
+#define	TOPO_METH_FAC_ENUM_DESC		"Facility Enumerator"
+
 extern void *topo_mod_alloc(topo_mod_t *, size_t);
 extern void *topo_mod_zalloc(topo_mod_t *, size_t);
 extern void topo_mod_free(topo_mod_t *, void *, size_t);
@@ -189,6 +195,8 @@
 extern void topo_node_range_destroy(tnode_t *, const char *);
 extern tnode_t *topo_node_bind(topo_mod_t *, tnode_t *, const char *,
     topo_instance_t, nvlist_t *);
+extern tnode_t *topo_node_facbind(topo_mod_t *, tnode_t *, const char *,
+    const char *);
 extern void topo_node_unbind(tnode_t *);
 extern void topo_node_setspecific(tnode_t *, void *);
 extern void *topo_node_getspecific(tnode_t *);
@@ -199,33 +207,6 @@
 #define	TOPO_ASRU_COMPUTE	0x0001	/* Compute ASRU dynamically */
 #define	TOPO_FRU_COMPUTE	0x0002	/* Compute FRU dynamically */
 
-/*
- * Topo property set functions
- */
-extern int topo_prop_set_int32(tnode_t *, const char *, const char *, int,
-    int32_t, int *);
-extern int topo_prop_set_uint32(tnode_t *, const char *, const char *, int,
-    uint32_t, int *);
-extern int topo_prop_set_int64(tnode_t *, const char *, const char *,
-    int, int64_t, int *);
-extern int topo_prop_set_uint64(tnode_t *, const char *, const char *,
-    int, uint64_t, int *);
-extern int topo_prop_set_string(tnode_t *, const char *, const char *,
-    int, const char *, int *);
-extern int topo_prop_set_fmri(tnode_t *, const char *, const char *,
-    int, const nvlist_t *, int *);
-extern int topo_prop_set_int32_array(tnode_t *, const char *, const char *, int,
-    int32_t *, uint_t, int *);
-extern int topo_prop_set_uint32_array(tnode_t *, const char *, const char *,
-    int, uint32_t *, uint_t, int *);
-extern int topo_prop_set_int64_array(tnode_t *, const char *, const char *,
-    int, int64_t *, uint_t, int *);
-extern int topo_prop_set_uint64_array(tnode_t *, const char *, const char *,
-    int, uint64_t *, uint_t, int *);
-extern int topo_prop_set_string_array(tnode_t *, const char *, const char *,
-    int, const char **, uint_t, int *);
-extern int topo_prop_set_fmri_array(tnode_t *, const char *, const char *,
-    int, const nvlist_t **, uint_t, int *);
 extern int topo_prop_inherit(tnode_t *, const char *, const char *, int *);
 extern int topo_pgroup_create(tnode_t *, const topo_pgroup_info_t *, int *);
 
@@ -252,6 +233,10 @@
     EMOD_FMRI_NVL,		/* nvlist allocation failure for FMRI */
     EMOD_FMRI_VERSION,		/* invalid FMRI scheme version */
     EMOD_FMRI_MALFORM,		/* malformed FMRI */
+    EMOD_NODE_BOUND,		/* node already bound */
+    EMOD_NODE_DUP,		/* duplicate node */
+    EMOD_NODE_NOENT,		/* node not found */
+    EMOD_NODE_RANGE,		/* invalid node range */
     EMOD_VER_ABI,		/* registered with invalid ABI version */
     EMOD_VER_OLD,		/* attempt to load obsolete module */
     EMOD_VER_NEW,		/* attempt to load a newer module */
--- a/usr/src/lib/fm/topo/libtopo/common/topo_node.c	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_node.c	Thu Jul 31 17:35:39 2008 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -94,6 +94,13 @@
  *                           -----------
  *                           | tnode_t |
  *                           -----------
+ *
+ * Facility Nodes
+ *
+ * Facility nodes are always leaf nodes in the topology and represent a FMRI
+ * sensor or indicator facility for the path to which it is connected.
+ * Facility nodes are bound to the topology with topo_node_facbind() and
+ * unbound with topo_node_unbind().
  */
 
 #include <assert.h>
@@ -102,6 +109,7 @@
 #include <sys/fm/protocol.h>
 #include <topo_alloc.h>
 #include <topo_error.h>
+#include <topo_list.h>
 #include <topo_method.h>
 #include <topo_subr.h>
 #include <topo_tree.h>
@@ -248,6 +256,12 @@
 	return (node->tn_parent);
 }
 
+int
+topo_node_flags(tnode_t *node)
+{
+	return (node->tn_fflags);
+}
+
 void
 topo_node_setspecific(tnode_t *node, void *data)
 {
@@ -297,24 +311,24 @@
 	    nhp = topo_list_next(nhp)) {
 		if (strcmp(nhp->th_name, name) == 0)
 			return (node_create_seterror(mod, pnode, NULL,
-			    ETOPO_NODE_DUP));
+			    EMOD_NODE_DUP));
 	}
 
 	if (min < 0 || max < min)
 		return (node_create_seterror(mod, pnode, NULL,
-		    ETOPO_NODE_INVAL));
+		    EMOD_NODE_RANGE));
 
 	if ((nhp = topo_mod_zalloc(mod, sizeof (topo_nodehash_t))) == NULL)
-		return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM));
+		return (node_create_seterror(mod, pnode, nhp, EMOD_NOMEM));
 
 	if ((nhp->th_name = topo_mod_strdup(mod, name)) == NULL)
-		return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM));
+		return (node_create_seterror(mod, pnode, nhp, EMOD_NOMEM));
 
 	nhp->th_arrlen = max - min + 1;
 
 	if ((nhp->th_nodearr = topo_mod_zalloc(mod,
 	    nhp->th_arrlen * sizeof (tnode_t *))) == NULL)
-		return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM));
+		return (node_create_seterror(mod, pnode, nhp, EMOD_NOMEM));
 
 	nhp->th_range.tr_min = min;
 	nhp->th_range.tr_max = max;
@@ -442,12 +456,12 @@
 			if (inst > nhp->th_range.tr_max ||
 			    inst < nhp->th_range.tr_min)
 				return (node_bind_seterror(mod, pnode, NULL,
-				    ETOPO_NODE_INVAL));
+				    EMOD_NODE_RANGE));
 
 			h = topo_node_hash(nhp, inst);
 			if (nhp->th_nodearr[h] != NULL)
 				return (node_bind_seterror(mod, pnode, NULL,
-				    ETOPO_NODE_BOUND));
+				    EMOD_NODE_BOUND));
 			else
 				break;
 
@@ -455,10 +469,10 @@
 	}
 
 	if (nhp == NULL)
-		return (node_bind_seterror(mod, pnode, NULL, ETOPO_NODE_NOENT));
+		return (node_bind_seterror(mod, pnode, NULL, EMOD_NODE_NOENT));
 
 	if ((node = topo_mod_zalloc(mod, sizeof (tnode_t))) == NULL)
-		return (node_bind_seterror(mod, pnode, NULL, ETOPO_NOMEM));
+		return (node_bind_seterror(mod, pnode, NULL, EMOD_NOMEM));
 
 	(void) pthread_mutex_init(&node->tn_lock, NULL);
 
@@ -474,7 +488,7 @@
 	topo_mod_hold(mod);
 
 	if (fmri == NULL)
-		return (node_bind_seterror(mod, pnode, node, ETOPO_NODE_INVAL));
+		return (node_bind_seterror(mod, pnode, node, EMOD_NVL_INVAL));
 
 	if (topo_pgroup_create(node, &protocol_pgroup, &err) < 0)
 		return (node_bind_seterror(mod, pnode, node, err));
@@ -492,6 +506,7 @@
 	topo_node_hold(node);
 	nhp->th_nodearr[h] = node;
 	++pnode->tn_refs;
+
 	topo_node_unlock(pnode);
 
 	if (topo_pgroup_create(node, &auth_pgroup, &err) == 0) {
@@ -506,6 +521,227 @@
 	return (node);
 }
 
+tnode_t *
+topo_node_facbind(topo_mod_t *mod, tnode_t *pnode, const char *name,
+    const char *type)
+{
+	int h, err;
+	tnode_t *node;
+	topo_nodehash_t *nhp;
+	topo_instance_t inst = 0;
+	nvlist_t *pfmri, *fnvl;
+
+	/*
+	 * Create a single entry range for this facility
+	 */
+	if (topo_node_range_create(mod, pnode, name, 0, 0) < 0)
+		return (NULL);  /* mod errno set */
+
+	topo_node_lock(pnode);
+	for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL;
+	    nhp = topo_list_next(nhp)) {
+		if (strcmp(nhp->th_name, name) == 0) {
+
+			if (inst > nhp->th_range.tr_max ||
+			    inst < nhp->th_range.tr_min)
+				return (node_bind_seterror(mod, pnode, NULL,
+				    EMOD_NVL_INVAL));
+
+			h = topo_node_hash(nhp, inst);
+			if (nhp->th_nodearr[h] != NULL)
+				return (node_bind_seterror(mod, pnode, NULL,
+				    EMOD_NODE_BOUND));
+			else
+				break;
+
+		}
+	}
+
+	if (nhp == NULL)
+		return (node_bind_seterror(mod, pnode, NULL, EMOD_NODE_NOENT));
+
+	if ((node = topo_mod_zalloc(mod, sizeof (tnode_t))) == NULL)
+		return (node_bind_seterror(mod, pnode, NULL, EMOD_NOMEM));
+
+	(void) pthread_mutex_init(&node->tn_lock, NULL);
+
+	node->tn_enum = mod;
+	node->tn_hdl = mod->tm_hdl;
+	node->tn_parent = pnode;
+	node->tn_name = nhp->th_name;
+	node->tn_instance = inst;
+	node->tn_phash = nhp;
+	node->tn_refs = 0;
+	node->tn_fflags = TOPO_NODE_FACILITY;
+
+	/* Ref count module that bound this node */
+	topo_mod_hold(mod);
+
+	if (topo_pgroup_create(node, &protocol_pgroup, &err) < 0)
+		return (node_bind_seterror(mod, pnode, node, err));
+
+	if (topo_mod_nvalloc(mod, &fnvl, NV_UNIQUE_NAME) < 0)
+		return (node_bind_seterror(mod, pnode, node, EMOD_NOMEM));
+	if (nvlist_add_string(fnvl, FM_FMRI_FACILITY_NAME, name) != 0 ||
+	    nvlist_add_string(fnvl, FM_FMRI_FACILITY_TYPE, type) != 0) {
+		nvlist_free(fnvl);
+		return (node_bind_seterror(mod, pnode, node,  EMOD_FMRI_NVL));
+	}
+
+	if (topo_node_resource(pnode, &pfmri, &err) < 0) {
+		nvlist_free(fnvl);
+		return (node_bind_seterror(mod, pnode, node, err));
+	}
+
+	if (nvlist_add_nvlist(pfmri, FM_FMRI_FACILITY, fnvl) != 0) {
+		nvlist_free(fnvl);
+		nvlist_free(pfmri);
+		return (node_bind_seterror(mod, pnode, node,  EMOD_FMRI_NVL));
+	}
+
+	nvlist_free(fnvl);
+
+	if (topo_prop_set_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE,
+	    TOPO_PROP_IMMUTABLE, pfmri, &err) < 0) {
+		nvlist_free(pfmri);
+		return (node_bind_seterror(mod, pnode, node, err));
+	}
+
+	nvlist_free(pfmri);
+
+	topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC,
+	    "facility node bound %s=%s\n", type, node->tn_name);
+
+	node->tn_state |= TOPO_NODE_BOUND;
+
+	topo_node_hold(node);
+	nhp->th_nodearr[h] = node;
+	++pnode->tn_refs;
+
+	topo_node_unlock(pnode);
+
+	if (topo_pgroup_create(node, &auth_pgroup, &err) == 0) {
+		(void) topo_prop_inherit(node, FM_FMRI_AUTHORITY,
+		    FM_FMRI_AUTH_PRODUCT, &err);
+		(void) topo_prop_inherit(node, FM_FMRI_AUTHORITY,
+		    FM_FMRI_AUTH_CHASSIS, &err);
+		(void) topo_prop_inherit(node, FM_FMRI_AUTHORITY,
+		    FM_FMRI_AUTH_SERVER, &err);
+	}
+
+	return (node);
+}
+
+int
+topo_node_facility(topo_hdl_t *thp, tnode_t *node, const char *fac_type,
+    uint32_t fac_subtype, topo_faclist_t *faclist, int *errp)
+{
+	tnode_t *tmp;
+	nvlist_t *rsrc, *fac, *out;
+	char *tmp_factype;
+	uint32_t tmp_facsubtype;
+	boolean_t list_empty = 1;
+	topo_faclist_t *fac_ele;
+
+	/*
+	 * Some facility nodes will be statically enumerated in the xml maps.
+	 * Other may be enumerated on-demand.  We can check for/handle the
+	 * latter case by looking for a node method for doing facility
+	 * enumeration and invoking it, if found.
+	 *
+	 * If the TOPO_FACILITIES_BOUND flag is set on this node, then we've
+	 * already enumerated the facilties for this node (by a previous call
+	 * to topo_node_facility) so there's no need to invoke the enumeration
+	 * method.
+	 */
+	topo_node_lock(node);
+	if (!(node->tn_state & TOPO_FACILITIES_BOUND) &&
+	    topo_method_supported(node, TOPO_METH_FAC_ENUM, 0)) {
+
+		if (topo_method_invoke(node, TOPO_METH_FAC_ENUM, 0, NULL, &out,
+		    errp) != 0) {
+			topo_dprintf(thp, TOPO_DBG_ERR,
+			    "topo_method_invoke failed (%s) on node %s=%d\n",
+			    topo_strerror(*errp), topo_node_name(node),
+			    topo_node_instance(node));
+			topo_node_unlock(node);
+			return (-1);
+		} else
+			node->tn_state |= TOPO_FACILITIES_BOUND;
+	}
+
+	bzero(faclist, sizeof (topo_faclist_t));
+	for (tmp = topo_child_first(node); tmp != NULL;
+	    tmp = topo_child_next(node, tmp)) {
+
+		topo_node_hold(tmp);
+		/*
+		 * If it's not a facility node, move on
+		 */
+		if (topo_node_flags(tmp) != TOPO_NODE_FACILITY) {
+			topo_node_rele(tmp);
+			continue;
+		}
+
+		/*
+		 * Lookup whether the fac type is sensor or indicator and if
+		 * it's not the type we're looking for, move on
+		 */
+		if (topo_node_resource(tmp, &rsrc, errp) != 0) {
+			topo_dprintf(thp, TOPO_DBG_ERR,
+			    "Failed to get resource for node %s=%d (%s)\n",
+			    topo_node_name(node), topo_node_instance(node),
+			    topo_strerror(*errp));
+			topo_node_rele(tmp);
+			topo_node_unlock(node);
+			return (-1);
+		}
+		if ((nvlist_lookup_nvlist(rsrc, "facility", &fac) != 0) ||
+		    (nvlist_lookup_string(fac, FM_FMRI_FACILITY_TYPE,
+		    &tmp_factype) != 0)) {
+
+			topo_node_rele(tmp);
+			topo_node_unlock(node);
+			return (-1);
+		}
+		if (strcmp(fac_type, tmp_factype) != 0) {
+			topo_node_rele(tmp);
+			continue;
+		}
+
+		/*
+		 * Finally, look up the subtype, which is a property in the
+		 * facility propgroup.  If it's a match return a pointer to the
+		 * node.  Otherwise, move on.
+		 */
+		if (topo_prop_get_uint32(tmp, TOPO_PGROUP_FACILITY,
+		    TOPO_FACILITY_TYPE, &tmp_facsubtype, errp) != 0) {
+
+			topo_node_rele(tmp);
+			topo_node_unlock(node);
+			return (-1);
+		}
+		if (fac_subtype == tmp_facsubtype) {
+			if ((fac_ele = topo_mod_zalloc(tmp->tn_enum,
+			    sizeof (topo_faclist_t))) == NULL) {
+				*errp = ETOPO_NOMEM;
+				return (-1);
+			}
+			fac_ele->tf_node = tmp;
+			topo_list_append(&faclist->tf_list, fac_ele);
+			list_empty = 0;
+		}
+		topo_node_rele(tmp);
+	}
+	topo_node_unlock(node);
+
+	if (list_empty) {
+		*errp = ETOPO_FAC_NOENT;
+		return (-1);
+	}
+	return (0);
+}
+
 void
 topo_node_unbind(tnode_t *node)
 {
@@ -561,7 +797,7 @@
 	topo_node_hold(node);
 
 	if ((wp = topo_hdl_zalloc(thp, sizeof (topo_walk_t))) == NULL) {
-		*errp = ETOPO_NOMEM;
+		*errp = ETOPO_HDL_NOMEM;
 		topo_node_rele(node);
 		return (NULL);
 	}
--- a/usr/src/lib/fm/topo/libtopo/common/topo_parse.h	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_parse.h	Thu Jul 31 17:35:39 2008 -0700
@@ -95,6 +95,15 @@
 	tf_edata_t *rd_einfo;	/* enumerator information, if any */
 	struct tf_idata *rd_instances; /* hard instances */
 	tf_pad_t *rd_pad;	/* properties and dependents */
+	/*
+	 * true, if this range xml element contains any child xml
+	 * node elements.
+	 * We use this to determine whether or not we should apply
+	 * property map changes to all of the nodes in a given range
+	 * or just a specific node.
+	 *
+	 */
+	int contains_node_ele;
 } tf_rdata_t;
 
 /*
@@ -135,19 +144,25 @@
 #define	Argval "argval"
 #define	Children "children"
 #define	Dependents "dependents"
+#define	Facility	"facility"
 #define	FMRI "fmri"
 #define	Grouping "grouping"
 #define	Immutable "immutable"
+#define	Indicator	"indicator"
 #define	Instance "instance"
 #define	Int32 "int32"
 #define	Int64 "int64"
+#define	Ipmi	"ipmi"
+#define	Mutable "mutable"
 #define	Name "name"
 #define	Propname "propname"
 #define	Proptype "proptype"
+#define	Provider "provider"
 #define	Range "range"
 #define	Scheme "scheme"
 #define	Set "set"
 #define	Setlist "setlist"
+#define	Sensor	"sensor"
 #define	Siblings "siblings"
 #define	Static "static"
 #define	String "string"
--- a/usr/src/lib/fm/topo/libtopo/common/topo_prop.c	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_prop.c	Thu Jul 31 17:35:39 2008 -0700
@@ -234,6 +234,10 @@
 			ret = nvlist_lookup_uint64(pv->tp_val,
 			    TOPO_PROP_VAL_VAL, (uint64_t *)val);
 			break;
+		case TOPO_TYPE_DOUBLE:
+			ret = nvlist_lookup_double(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, (double *)val);
+			break;
 		case TOPO_TYPE_STRING: {
 			char *str;
 
@@ -419,6 +423,14 @@
 }
 
 int
+topo_prop_get_double(tnode_t *node, const char *pgname, const char *pname,
+    double *val, int *err)
+{
+	return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_DOUBLE,
+	    NULL, err));
+}
+
+int
 topo_prop_get_string(tnode_t *node, const char *pgname, const char *pname,
     char **val, int *err)
 {
@@ -557,7 +569,6 @@
 	int ret;
 	topo_hdl_t *thp = node->tn_hdl;
 	nvlist_t *nvl;
-	topo_propval_t *pv;
 
 	if (topo_hdl_nvalloc(thp, &nvl, NV_UNIQUE_NAME) < 0) {
 		*err = ETOPO_PROP_NVL;
@@ -583,6 +594,10 @@
 			ret |= nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL,
 			    *(uint64_t *)val);
 			break;
+		case TOPO_TYPE_DOUBLE:
+			ret |= nvlist_add_double(nvl, TOPO_PROP_VAL_VAL,
+			    *(double *)val);
+			break;
 		case TOPO_TYPE_STRING:
 			ret |= nvlist_add_string(nvl, TOPO_PROP_VAL_VAL,
 			    (char *)val);
@@ -631,16 +646,11 @@
 		}
 	}
 
-	topo_node_lock(node);
-	if ((pv = prop_create(node, pgname, pname, type, flag, err)) == NULL) {
+	if (topo_prop_setprop(node, pgname, nvl, flag, nvl, err) != 0) {
 		nvlist_free(nvl);
-		return (-1); /* unlocked and err set */
+		return (-1); /* err set */
 	}
-
-	pv->tp_val = nvl;
-
-	topo_node_unlock(node);
-
+	nvlist_free(nvl);
 	return (ret);
 }
 
@@ -677,6 +687,14 @@
 }
 
 int
+topo_prop_set_double(tnode_t *node, const char *pgname, const char *pname,
+    int flag, double val, int *err)
+{
+	return (topo_prop_set(node, pgname, pname, TOPO_TYPE_DOUBLE, flag,
+	    &val, 1, err));
+}
+
+int
 topo_prop_set_string(tnode_t *node, const char *pgname, const char *pname,
     int flag, const char *val, int *err)
 {
@@ -877,10 +895,18 @@
 	 * to allow the method to be registered.  This is to handle the case
 	 * where we specify an prop method in an xml map to override the value
 	 * that was set by the enumerator.
+	 *
+	 * By default, propmethod-backed properties are IMMUTABLE.  This is done
+	 * to simplify the programming model for modules that implement property
+	 * methods as most propmethods tend to only support get operations.
+	 * Enumerator modules can override this by calling topo_prop_setflags().
+	 * Propmethods that are registered via XML can be set as mutable via
+	 * the optional "mutable" attribute, which will result in the xml parser
+	 * calling topo_prop_setflags() after registering the propmethod.
 	 */
 	if ((pv = propval_get(pgroup_get(node, pgname), pname)) == NULL)
 		if ((pv = prop_create(node, pgname, pname, ptype,
-		    TOPO_PROP_MUTABLE, err)) == NULL) {
+		    TOPO_PROP_IMMUTABLE, err)) == NULL) {
 			/* node unlocked */
 			return (register_methoderror(node, pm, err, 0, *err));
 		}
@@ -982,6 +1008,35 @@
 	topo_node_unlock(node);
 }
 
+int
+topo_prop_setmutable(tnode_t *node, const char *pgname, const char *pname,
+    int *err)
+{
+	topo_propval_t *pv = NULL;
+
+	topo_node_lock(node);
+	if ((pv = propval_get(pgroup_get(node, pgname), pname)) == NULL) {
+		topo_node_unlock(node);
+		*err = ETOPO_PROP_NOENT;
+		return (-1);
+	}
+
+	/*
+	 * If the property is being inherited then we don't want to allow a
+	 * change from IMMUTABLE to MUTABLE.
+	 */
+	if (pv->tp_refs > 1) {
+		topo_node_unlock(node);
+		*err = ETOPO_PROP_DEFD;
+		return (-1);
+	}
+	pv->tp_flag = TOPO_PROP_MUTABLE;
+
+	topo_node_unlock(node);
+
+	return (0);
+}
+
 static int
 inherit_seterror(tnode_t *node, int *errp, int err)
 {
--- a/usr/src/lib/fm/topo/libtopo/common/topo_subr.c	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_subr.c	Thu Jul 31 17:35:39 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -351,3 +351,204 @@
 	pp = topo_hdl_strdup(thp, buf);
 	return (pp);
 }
+
+void
+topo_sensor_type_name(uint32_t type, char *buf, size_t len)
+{
+	topo_name_trans_t *ntp;
+
+	for (ntp = &topo_sensor_type_table[0]; ntp->int_name != NULL; ntp++) {
+		if (ntp->int_value == type) {
+			(void) strlcpy(buf, ntp->int_name, len);
+			return;
+		}
+	}
+
+	(void) snprintf(buf, len, "0x%02x", type);
+}
+
+void
+topo_sensor_units_name(uint8_t type, char *buf, size_t len)
+{
+	topo_name_trans_t *ntp;
+
+	for (ntp = &topo_units_type_table[0]; ntp->int_name != NULL; ntp++) {
+		if (ntp->int_value == type) {
+			(void) strlcpy(buf, ntp->int_name, len);
+			return;
+		}
+	}
+
+	(void) snprintf(buf, len, "0x%02x", type);
+}
+
+void
+topo_led_type_name(uint8_t type, char *buf, size_t len)
+{
+	topo_name_trans_t *ntp;
+
+	for (ntp = &topo_led_type_table[0]; ntp->int_name != NULL; ntp++) {
+		if (ntp->int_value == type) {
+			(void) strlcpy(buf, ntp->int_name, len);
+			return;
+		}
+	}
+
+	(void) snprintf(buf, len, "0x%02x", type);
+}
+
+void
+topo_led_state_name(uint8_t type, char *buf, size_t len)
+{
+	topo_name_trans_t *ntp;
+
+	for (ntp = &topo_led_states_table[0]; ntp->int_name != NULL; ntp++) {
+		if (ntp->int_value == type) {
+			(void) strlcpy(buf, ntp->int_name, len);
+			return;
+		}
+	}
+
+	(void) snprintf(buf, len, "0x%02x", type);
+}
+
+void
+topo_sensor_state_name(uint32_t sensor_type, uint8_t state, char *buf,
+size_t len)
+{
+	topo_name_trans_t *ntp;
+
+	switch (sensor_type) {
+		case TOPO_SENSOR_TYPE_PHYSICAL:
+			ntp = &topo_sensor_states_physical_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_PLATFORM:
+			ntp = &topo_sensor_states_platform_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_PROCESSOR:
+			ntp = &topo_sensor_states_processor_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_POWER_SUPPLY:
+			ntp = &topo_sensor_states_power_supply_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_POWER_UNIT:
+			ntp = &topo_sensor_states_power_unit_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_MEMORY:
+			ntp = &topo_sensor_states_memory_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_BAY:
+			ntp = &topo_sensor_states_bay_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_FIRMWARE:
+			ntp = &topo_sensor_states_firmware_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_EVENT_LOG:
+			ntp = &topo_sensor_states_event_log_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_WATCHDOG1:
+			ntp = &topo_sensor_states_watchdog1_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_SYSTEM:
+			ntp = &topo_sensor_states_system_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_CRITICAL:
+			ntp = &topo_sensor_states_critical_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_BUTTON:
+			ntp = &topo_sensor_states_button_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_CABLE:
+			ntp = &topo_sensor_states_cable_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_BOOT_STATE:
+			ntp = &topo_sensor_states_boot_state_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_BOOT_ERROR:
+			ntp = &topo_sensor_states_boot_error_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_BOOT_OS:
+			ntp = &topo_sensor_states_boot_os_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_OS_SHUTDOWN:
+			ntp = &topo_sensor_states_os_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_SLOT:
+			ntp = &topo_sensor_states_slot_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_ACPI:
+			ntp = &topo_sensor_states_acpi_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_WATCHDOG2:
+			ntp = &topo_sensor_states_watchdog2_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_ALERT:
+			ntp = &topo_sensor_states_alert_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_PRESENCE:
+			ntp = &topo_sensor_states_presence_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_LAN:
+			ntp = &topo_sensor_states_lan_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_HEALTH:
+			ntp = &topo_sensor_states_health_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_BATTERY:
+			ntp = &topo_sensor_states_battery_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_AUDIT:
+			ntp = &topo_sensor_states_audit_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_VERSION:
+			ntp = &topo_sensor_states_version_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_FRU_STATE:
+			ntp = &topo_sensor_states_fru_state_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_THRESHOLD_STATE:
+			ntp = &topo_sensor_states_thresh_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_GENERIC_USAGE:
+			ntp = &topo_sensor_states_generic_usage_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_GENERIC_STATE:
+			ntp = &topo_sensor_states_generic_state_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_GENERIC_PREDFAIL:
+			ntp = &topo_sensor_states_generic_predfail_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_GENERIC_LIMIT:
+			ntp = &topo_sensor_states_generic_limit_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_GENERIC_PERFORMANCE:
+			ntp = &topo_sensor_states_generic_perf_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_SEVERITY:
+			ntp = &topo_sensor_states_severity_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_GENERIC_PRESENCE:
+			ntp = &topo_sensor_states_generic_presence_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_GENERIC_AVAILABILITY:
+			ntp = &topo_sensor_states_generic_avail_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_GENERIC_STATUS:
+			ntp = &topo_sensor_states_generic_status_table[0];
+			break;
+		case TOPO_SENSOR_TYPE_GENERIC_ACPI:
+			ntp = &topo_sensor_states_generic_acpi_pwr_table[0];
+			break;
+		default:
+			(void) snprintf(buf, len, "0x%02x", state);
+			return;
+	}
+	for (; ntp->int_name != NULL; ntp++) {
+		if (ntp->int_value == state) {
+			(void) strlcpy(buf, ntp->int_name, len);
+			return;
+		}
+	}
+
+	(void) snprintf(buf, len, "0x%02x", state);
+}
--- a/usr/src/lib/fm/topo/libtopo/common/topo_subr.h	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_subr.h	Thu Jul 31 17:35:39 2008 -0700
@@ -65,6 +65,55 @@
 #define	TOPO_STABSTR_STANDARD	"Standard"	/* industry standard */
 #define	TOPO_STABSTR_UNKNOWN	"Unknown"	/* stability unknown */
 
+typedef struct topo_name_trans {
+	uint32_t	int_value;
+	const char	*int_name;
+} topo_name_trans_t;
+
+extern topo_name_trans_t topo_sensor_type_table[];
+extern topo_name_trans_t topo_units_type_table[];
+extern topo_name_trans_t topo_led_type_table[];
+extern topo_name_trans_t topo_led_states_table[];
+extern topo_name_trans_t topo_sensor_states_physical_table[];
+extern topo_name_trans_t topo_sensor_states_platform_table[];
+extern topo_name_trans_t topo_sensor_states_processor_table[];
+extern topo_name_trans_t topo_sensor_states_power_supply_table[];
+extern topo_name_trans_t topo_sensor_states_power_unit_table[];
+extern topo_name_trans_t topo_sensor_states_memory_table[];
+extern topo_name_trans_t topo_sensor_states_bay_table[];
+extern topo_name_trans_t topo_sensor_states_firmware_table[];
+extern topo_name_trans_t topo_sensor_states_event_log_table[];
+extern topo_name_trans_t topo_sensor_states_watchdog1_table[];
+extern topo_name_trans_t topo_sensor_states_system_table[];
+extern topo_name_trans_t topo_sensor_states_critical_table[];
+extern topo_name_trans_t topo_sensor_states_button_table[];
+extern topo_name_trans_t topo_sensor_states_cable_table[];
+extern topo_name_trans_t topo_sensor_states_boot_state_table[];
+extern topo_name_trans_t topo_sensor_states_boot_error_table[];
+extern topo_name_trans_t topo_sensor_states_boot_os_table[];
+extern topo_name_trans_t topo_sensor_states_os_table[];
+extern topo_name_trans_t topo_sensor_states_slot_table[];
+extern topo_name_trans_t topo_sensor_states_acpi_table[];
+extern topo_name_trans_t topo_sensor_states_watchdog2_table[];
+extern topo_name_trans_t topo_sensor_states_alert_table[];
+extern topo_name_trans_t topo_sensor_states_presence_table[];
+extern topo_name_trans_t topo_sensor_states_lan_table[];
+extern topo_name_trans_t topo_sensor_states_health_table[];
+extern topo_name_trans_t topo_sensor_states_battery_table[];
+extern topo_name_trans_t topo_sensor_states_audit_table[];
+extern topo_name_trans_t topo_sensor_states_version_table[];
+extern topo_name_trans_t topo_sensor_states_fru_state_table[];
+extern topo_name_trans_t topo_sensor_states_thresh_table[];
+extern topo_name_trans_t topo_sensor_states_generic_usage_table[];
+extern topo_name_trans_t topo_sensor_states_generic_state_table[];
+extern topo_name_trans_t topo_sensor_states_generic_predfail_table[];
+extern topo_name_trans_t topo_sensor_states_generic_limit_table[];
+extern topo_name_trans_t topo_sensor_states_generic_perf_table[];
+extern topo_name_trans_t topo_sensor_states_generic_presence_table[];
+extern topo_name_trans_t topo_sensor_states_severity_table[];
+extern topo_name_trans_t topo_sensor_states_generic_avail_table[];
+extern topo_name_trans_t topo_sensor_states_generic_status_table[];
+extern topo_name_trans_t topo_sensor_states_generic_acpi_pwr_table[];
 
 extern int topo_rw_read_held(pthread_rwlock_t *);
 extern int topo_rw_write_held(pthread_rwlock_t *);
--- a/usr/src/lib/fm/topo/libtopo/common/topo_xml.c	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_xml.c	Thu Jul 31 17:35:39 2008 -0700
@@ -23,7 +23,6 @@
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include <libxml/parser.h>
@@ -50,6 +49,9 @@
     tnode_t *);
 static tf_edata_t *enum_attributes_process(topo_mod_t *, xmlNodePtr);
 static int enum_run(topo_mod_t *, tf_rdata_t *);
+static int fac_enum_run(topo_mod_t *, tnode_t *, const char *);
+static int fac_process(topo_mod_t *, xmlNodePtr, tf_rdata_t *, tnode_t *);
+static int fac_enum_process(topo_mod_t *, xmlNodePtr, tnode_t *);
 static int decorate_nodes(topo_mod_t *, tf_rdata_t *, xmlNodePtr, tnode_t *,
     tf_pad_t **);
 
@@ -103,7 +105,8 @@
 	xmlChar *str;
 	xmlChar *estr;
 
-	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "attribute to int\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xmlattr_to_int(propname=%s)\n",
+	    propname);
 	if ((str = xmlGetProp(n, (xmlChar *)propname)) == NULL)
 		return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
 	*value = strtoull((char *)str, (char **)&estr, 10);
@@ -122,7 +125,8 @@
 {
 	xmlChar *str;
 
-	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "attribute to int\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xmlattr_to_fmri(propname=%s)\n",
+	    propname);
 	if ((str = xmlGetProp(xn, (xmlChar *)propname)) == NULL)
 		return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
 	if (topo_mod_str2nvl(mp, (const char *)str, rnvl) < 0) {
@@ -176,7 +180,8 @@
 	nvlist_t *fmri;
 	xmlChar *str;
 
-	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xlate_common\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xlate_common (name=%s)\n",
+	    name);
 	switch (ptype) {
 	case TOPO_TYPE_INT32:
 		if (xmlattr_to_int(mp, xn, Value, &ui) < 0)
@@ -329,8 +334,8 @@
 	char *str;
 	int err, e;
 
-	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "prop_create(gnm = %s, "
-	    "pnm = %s)\n", gnm, pnm);
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "prop_create(pgrp = %s, "
+	    "prop = %s)\n", gnm, pnm);
 	switch (ptype) {
 	case TOPO_TYPE_INT32:
 		e = nvlist_lookup_int32(pfmri, INV_PVAL, &i32);
@@ -404,7 +409,8 @@
 	int pn;
 	int e;
 
-	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "props_create(gnm = %s)\n", gnm);
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "props_create(pgrp = %s)\n",
+	    gnm);
 	for (pn = 0; pn < nprops; pn++) {
 		e = nvlist_lookup_string(props[pn], INV_PNAME, &pnm);
 		if (e != 0) {
@@ -449,7 +455,8 @@
 	int pg;
 	int e;
 
-	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroups_create\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroups_create: %s=%d\n",
+	    topo_node_name(ptn), topo_node_instance(ptn));
 	for (pg = 0; pg < pad->tpad_pgcnt; pg++) {
 		e = nvlist_lookup_string(pad->tpad_pgs[pg],
 		    INV_PGRP_NAME, &gnm);
@@ -601,14 +608,15 @@
 	xmlNodePtr cn;
 	xmlChar *meth_name = NULL, *prop_name = NULL;
 	xmlChar *arg_name = NULL;
-	uint64_t meth_ver;
+	uint64_t meth_ver, is_mutable = 0;
 	topo_type_t prop_type;
 	struct propmeth_data meth;
-	int ret = 0;
+	int ret = 0, err;
 	topo_type_t ptype;
 	tnode_t *tmp;
 
-	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pmeth_record\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pmeth_record: %s=%d "
+	    "(pgrp=%s)\n", topo_node_name(tn), topo_node_instance(tn), pg_name);
 
 	/*
 	 * Get propmethod attribute values
@@ -624,6 +632,12 @@
 		ret = topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
 		goto pmr_done;
 	}
+	/*
+	 * The "mutable" attribute is optional.  If not specified we default to
+	 * false (0)
+	 */
+	(void) xmlattr_to_int(mp, xn, Mutable, &is_mutable);
+
 	if ((prop_name = xmlGetProp(xn, (xmlChar *)Propname)) == NULL) {
 		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
 		    "propmethod element lacks propname attribute\n");
@@ -702,18 +716,36 @@
 	 */
 	if (strcmp(ppgrp_name, Range) == 0) {
 		for (tmp = tn; tmp != NULL; tmp = topo_child_next(NULL, tmp)) {
-			if (strcmp(rname, topo_node_name(tmp)) == 0)
+			if (strcmp(rname, topo_node_name(tmp)) == 0) {
 				if (register_method(mp, tmp, &meth) != 0) {
 					ret = topo_mod_seterrno(mp,
 					    ETOPO_PRSR_REGMETH);
 					goto pmr_done;
 				}
+				if (is_mutable) {
+					if (topo_prop_setmutable(tmp,
+					    meth.pg_name, meth.prop_name, &err)
+					    != 0) {
+						ret = topo_mod_seterrno(mp,
+						    ETOPO_PRSR_REGMETH);
+						goto pmr_done;
+					}
+				}
+			}
 		}
 	} else {
 		if (register_method(mp, tn, &meth) != 0) {
 			ret = topo_mod_seterrno(mp, ETOPO_PRSR_REGMETH);
 			goto pmr_done;
 		}
+		if (is_mutable) {
+			if (topo_prop_setmutable(tn, meth.pg_name,
+			    meth.prop_name, &err) != 0) {
+				ret = topo_mod_seterrno(mp,
+				    ETOPO_PRSR_REGMETH);
+				goto pmr_done;
+			}
+		}
 	}
 
 pmr_done:
@@ -878,8 +910,9 @@
 pad_process(topo_mod_t *mp, tf_rdata_t *rd, xmlNodePtr pxn, tnode_t *ptn,
     tf_pad_t **rpad)
 {
-	xmlNodePtr cn, gcn, psn, ecn;
+	xmlNodePtr cn, gcn, psn, ecn, target;
 	xmlNodePtr def_set = NULL;
+	tnode_t *ct;
 	tf_pad_t *new = *rpad;
 	tf_rdata_t tmp_rd;
 	int pgcnt = 0;
@@ -1008,23 +1041,48 @@
 				return (-1);
 			}
 
-			if (joined_set) {
-				/*
-				 * If the property groups are contained within a
-				 * set then they will be one level lower in
-				 * the XML tree.
-				 */
-				if (pgroups_record(mp, psn, ptn, rd->rd_name,
-				    new, (const char *)pxn->name) < 0) {
-					tf_pad_free(mp, new);
+			/*
+			 * If the property groups are contained within a set
+			 * then they will be one level lower in the XML tree.
+			 */
+			if (joined_set)
+				target = psn;
+			else
+				target = pxn;
+
+			/*
+			 * If there is no "node" element under the "range"
+			 * element, then we need to attach the facility node to
+			 * each node in this range.
+			 *
+			 * Otherwise we only attach it to the current node
+			 */
+			if (!rd->contains_node_ele) {
+				for (ct = topo_child_first(rd->rd_pn);
+				    ct != NULL;
+				    ct = topo_child_next(rd->rd_pn, ct)) {
+
+					if (strcmp(topo_node_name(ct),
+					    rd->rd_name) != 0)
+						continue;
+
+					if (fac_enum_process(mp, target,
+					    ct) < 0)
+						return (-1);
+
+					if (fac_process(mp, target, rd, ct) < 0)
+						return (-1);
+				}
+			} else
+				if (fac_enum_process(mp, target, ptn) < 0)
 					return (-1);
-				}
-			} else {
-				if (pgroups_record(mp, pxn, ptn, rd->rd_name,
-				    new, (const char *)pxn->name) < 0) {
-					tf_pad_free(mp, new);
+				if (fac_process(mp, target, rd, ptn) < 0)
 					return (-1);
-				}
+
+			if (pgroups_record(mp, target, ptn, rd->rd_name,
+			    new, (const char *)pxn->name) < 0) {
+				tf_pad_free(mp, new);
+				return (-1);
 			}
 		}
 		*rpad = new;
@@ -1043,6 +1101,154 @@
 
 
 static int
+fac_enum_process(topo_mod_t *mp, xmlNodePtr pn, tnode_t *ptn)
+{
+	xmlNodePtr cn;
+	xmlChar *fprov = NULL;
+	int rv = 0;
+
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
+	    "fac_enum_process() called for %s=%d\n", topo_node_name(ptn),
+	    topo_node_instance(ptn));
+
+	for (cn = pn->xmlChildrenNode; cn != NULL; cn = cn->next) {
+
+		if (xmlStrcmp(cn->name, (xmlChar *)"fac-enum") != 0)
+			continue;
+
+		if ((fprov = xmlGetProp(cn, (xmlChar *)Provider)) == NULL)
+			goto fenumdone;
+
+		if (xmlStrcmp(fprov, (xmlChar *)"fac_prov_ipmi") != 0) {
+			topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
+			    "Invalid provider specified: %s\n", fprov);
+			goto fenumdone;
+		}
+
+		/*
+		 * Invoke enum entry point in fac provider which will cause the
+		 * facility enumeration node method to be registered.
+		 */
+		if (fac_enum_run(mp, ptn, (const char *)fprov) != 0) {
+			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+			    "fac_enum_process: enum entry point failed!\n");
+			goto fenumdone;
+		}
+		xmlFree(fprov);
+	}
+	return (0);
+fenumdone:
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "fac-enum processing failed\n");
+
+	if (fprov != NULL)
+		xmlFree(fprov);
+
+	return (rv);
+}
+
+
+static int
+fac_process(topo_mod_t *mp, xmlNodePtr pn, tf_rdata_t *rd, tnode_t *ptn)
+{
+	xmlNodePtr cn;
+	xmlChar *fname = NULL, *ftype = NULL, *provider = NULL;
+	tnode_t *ntn = NULL;
+	tf_idata_t *newi;
+	int err;
+	topo_pgroup_info_t pgi;
+
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
+	    "fac_process() called\n");
+
+	for (cn = pn->xmlChildrenNode; cn != NULL; cn = cn->next) {
+
+		if (xmlStrcmp(cn->name, (xmlChar *)Facility) != 0)
+			continue;
+
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
+		    "facility processing\n");
+
+		if ((fname = xmlGetProp(cn, (xmlChar *)Name)) == NULL)
+			goto facdone;
+
+		if ((ftype = xmlGetProp(cn, (xmlChar *)Type)) == NULL)
+			goto facdone;
+
+		if ((provider = xmlGetProp(cn, (xmlChar *)Provider)) == NULL)
+			goto facdone;
+
+		if (xmlStrcmp(ftype, (xmlChar *)Sensor) != 0 &&
+		    xmlStrcmp(ftype, (xmlChar *)Indicator) != 0)
+			goto facdone;
+
+		if (xmlStrcmp(provider, (xmlChar *)"fac_prov_ipmi") != 0) {
+			topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "fac_process: "
+			    "Invalid provider attr value: %s\n", provider);
+			goto facdone;
+		}
+
+		if ((ntn = topo_node_facbind(mp, ptn, (char *)fname,
+		    (char *)ftype)) == NULL)
+			goto facdone;
+
+		pgi.tpi_name = TOPO_PGROUP_FACILITY;
+		pgi.tpi_namestab = TOPO_STABILITY_PRIVATE;
+		pgi.tpi_datastab = TOPO_STABILITY_PRIVATE;
+		pgi.tpi_version = 1;
+		if (topo_pgroup_create(ntn, &pgi, &err) != 0) {
+			if (err != ETOPO_PROP_DEFD) {
+				topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+				    "pgroups create failure: %s\n",
+				    topo_strerror(err));
+				return (-1);
+			}
+		}
+		/*
+		 * Invoke enum entry point in fac_prov_ipmi module, which will
+		 * cause the provider methods to be registered on this node
+		 */
+		if (fac_enum_run(mp, ntn, (const char *)provider) != 0) {
+			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "fac_process: "
+			    "enum entry point failed for provider %s!\n",
+			    provider);
+			goto facdone;
+		}
+
+		if ((newi = tf_idata_new(mp, 0, ntn)) == NULL)
+			goto facdone;
+
+		if (tf_idata_insert(&rd->rd_instances, newi) < 0)
+			goto facdone;
+
+		if (pad_process(mp, rd, cn, ntn, &newi->ti_pad) < 0)
+			goto facdone;
+
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "done with "
+		    "facility %s=%s.\n", ftype, fname);
+
+		xmlFree(ftype);
+		xmlFree(fname);
+		xmlFree(provider);
+	}
+
+	return (0);
+
+facdone:
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "facility processing failed\n");
+
+	if (ftype != NULL)
+		xmlFree(ftype);
+	if (fname != NULL)
+		xmlFree(fname);
+	if (provider != NULL)
+		xmlFree(provider);
+	if (ntn != NULL)
+		topo_node_unbind(ntn);
+
+	return (0);
+}
+
+static int
 node_process(topo_mod_t *mp, xmlNodePtr nn, tf_rdata_t *rd)
 {
 	xmlChar *str;
@@ -1056,6 +1262,7 @@
 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
 	    "node_process %s\n", rd->rd_name);
 
+	rd->contains_node_ele = 1;
 	if (xmlattr_to_int(mp, nn, Instance, &ui) < 0)
 		goto nodedone;
 	inst = (topo_instance_t)ui;
@@ -1098,6 +1305,8 @@
 	}
 	if (pad_process(mp, rd, nn, ntn, &newi->ti_pad) < 0)
 		goto nodedone;
+	if (fac_process(mp, nn, rd, ntn) < 0)
+		goto nodedone;
 	rv = 0;
 nodedone:
 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "done with node %s.\n",
@@ -1191,6 +1400,44 @@
 	return (e);
 }
 
+static int
+fac_enum_run(topo_mod_t *mp, tnode_t *node, const char *name)
+{
+	topo_hdl_t *thp = mp->tm_hdl;
+	topo_mod_t *fmod;
+	int e = -1;
+
+	topo_dprintf(thp, TOPO_DBG_XML, "fac_enum_run\n");
+	/*
+	 * Check if the enumerator module is already loaded.
+	 * Module loading is single-threaded at this point so there's
+	 * no need to worry about the module going away or bumping the
+	 * ref count.
+	 */
+	if ((fmod = topo_mod_lookup(thp, name, 0)) == NULL) {
+		if ((fmod = topo_mod_load(mp, name, TOPO_VERSION)) == NULL) {
+			topo_dprintf(thp, TOPO_DBG_ERR,
+			    "fac_enum_run: mod_load of %s failed: %s.\n",
+			    name, topo_strerror(topo_mod_errno(mp)));
+			(void) topo_hdl_seterrno(thp, topo_mod_errno(mp));
+			return (e);
+		}
+	}
+	/*
+	 * We're live, so let's enumerate.
+	 */
+	topo_dprintf(thp, TOPO_DBG_XML, "fac enumerate request. (%s)\n", name);
+	e = topo_mod_enumerate(fmod, node, name, name, 0, 0, NULL);
+	topo_dprintf(thp, TOPO_DBG_XML, "back from enumeration. %d\n", e);
+	if (e != 0) {
+		topo_dprintf(thp, TOPO_DBG_ERR,
+		    "Facility provider enumeration failed (%s)\n",
+		    topo_strerror(topo_mod_errno(mp)));
+		(void) topo_hdl_seterrno(thp, EMOD_PARTIAL_ENUM);
+		return (topo_mod_seterrno(mp, EMOD_PARTIAL_ENUM));
+	}
+	return (e);
+}
 
 int
 decorate_nodes(topo_mod_t *mp, tf_rdata_t *rd, xmlNodePtr pxn, tnode_t *ptn,
@@ -1231,9 +1478,10 @@
 	    "process %s range beneath %s\n", rd->rd_name,
 	    topo_node_name(rd->rd_pn));
 
+	rd->contains_node_ele = 0;
 	e = topo_node_range_create(mp,
 	    rd->rd_pn, rd->rd_name, rd->rd_min, rd->rd_max);
-	if (e != 0 && topo_mod_errno(mp) != ETOPO_NODE_DUP) {
+	if (e != 0 && topo_mod_errno(mp) != EMOD_NODE_DUP) {
 		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
 		    "Range create failed due to %s.\n",
 		    topo_strerror(topo_mod_errno(mp)));
@@ -1326,6 +1574,10 @@
 			if (pad_process(mp, rd, rn, ct, &rd->rd_pad)
 			    < 0)
 				return (-1);
+
+			if (fac_process(mp, rn, rd, ct) < 0)
+				return (-1);
+
 			ct = topo_child_next(rd->rd_pn, ct);
 			ccnt++;
 		}
--- a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4500/Sun-Fire-X4500-hc-topology.xmlgen	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4500/Sun-Fire-X4500-hc-topology.xmlgen	Thu Jul 31 17:35:39 2008 -0700
@@ -201,6 +201,103 @@
 printf OFILE "  <range name='bay' min='0' max='%d'>\n",
 		$sys_supported->{"num_bays"}-1;
 
+#
+# Statically define locate indicator
+#
+print OFILE "     <facility name='locate' type='indicator' ".
+    "provider='fac_prov_ipmi' >\n";
+print OFILE "           <propgroup name='facility' version='1' ".
+    "name-stability='Private' data-stability='Private' >\n";
+print OFILE "                <propval name='type' type='uint32' value='1' />\n";
+print OFILE "                <propmethod name='ipmi_entity' version='0' ".
+    "propname='entity_ref' proptype='string' >\n";
+print OFILE "                    <argval name='format' type='string' ".
+    "value='hdd%d.ok2rm.led' />\n";
+print OFILE "                    <argval name='offset' type='uint32' ".
+    "value='0' />\n";
+print OFILE "                    <argval name='nparams' type='uint32' ".
+    "value='1' />\n";
+print OFILE "                </propmethod>\n";
+print OFILE "                <propmethod name='thumper_locate_mode' ".
+    "version='0'\n";
+print OFILE "                   propname='mode' proptype='uint32' ".
+    "mutable='1' >\n";
+print OFILE "                </propmethod>\n";
+print OFILE "            </propgroup>\n";
+print OFILE "     </facility>\n";
+
+#
+# Statically define ok2rm indicator
+#
+print OFILE "     <facility name='ok2rm' type='indicator' ".
+    "provider='fac_prov_ipmi' >\n";
+print OFILE "           <propgroup name='facility' version='1' ".
+    "name-stability='Private' data-stability='Private' >\n";
+print OFILE "                <propval name='type' type='uint32' value='2' />\n";
+print OFILE "                <propmethod name='ipmi_entity' version='0' ".
+    "propname='entity_ref' proptype='string' >\n";
+print OFILE "                    <argval name='format' type='string' ".
+    "value='hdd%d.state' />\n";
+print OFILE "                    <argval name='offset' type='uint32' ".
+    "value='0' />\n";
+print OFILE "                    <argval name='nparams' type='uint32' ".
+    "value='1' />\n";
+print OFILE "                </propmethod>\n";
+print OFILE "                <propmethod name='thumper_indicator_mode' ".
+    "version='0'\n";
+print OFILE "                   propname='mode' proptype='uint32' ".
+    "mutable='1' >\n";
+print OFILE "                </propmethod>\n";
+print OFILE "            </propgroup>\n";
+print OFILE "     </facility>\n";
+
+#
+# Statically define service indicator
+#
+print OFILE "     <facility name='service' type='indicator' ".
+    "provider='fac_prov_ipmi' >\n";
+print OFILE "           <propgroup name='facility' version='1' ".
+    "name-stability='Private' data-stability='Private' >\n";
+print OFILE "                <propval name='type' type='uint32' value='0' />\n";
+print OFILE "                <propmethod name='ipmi_entity' version='0' ".
+    "propname='entity_ref' proptype='string' >\n";
+print OFILE "                    <argval name='format' type='string' ".
+    "value='hdd%d.state' />\n";
+print OFILE "                    <argval name='offset' type='uint32' ".
+    "value='0' />\n";
+print OFILE "                    <argval name='nparams' type='uint32' ".
+    "value='1' />\n";
+print OFILE "                </propmethod>\n";
+print OFILE "                <propmethod name='thumper_indicator_mode' ".
+    "version='0' propname='mode' proptype='uint32' mutable='1' >\n";
+print OFILE "                </propmethod>\n";
+print OFILE "            </propgroup>\n";
+print OFILE "     </facility>\n";
+
+
+#
+# Statically define present indicator
+#
+print OFILE "     <facility name='present' type='indicator' ".
+    "provider='fac_prov_ipmi' >\n";
+print OFILE "           <propgroup name='facility' version='1' ".
+    "name-stability='Private' data-stability='Private' >\n";
+print OFILE "                <propval name='type' type='uint32' value='3' />\n";
+print OFILE "                <propmethod name='ipmi_entity' version='0' ".
+    "propname='entity_ref' proptype='string' >\n";
+print OFILE "                    <argval name='format' type='string' ".
+    "value='hdd%d.state' />\n";
+print OFILE "                    <argval name='offset' type='uint32' ".
+    "value='0' />\n";
+print OFILE "                    <argval name='nparams' type='uint32' ".
+    "value='1' />\n";
+print OFILE "                </propmethod>\n";
+print OFILE "                <propmethod name='thumper_indicator_mode' ".
+    "version='0' propname='mode' proptype='uint32' mutable='1' >\n";
+print OFILE "                </propmethod>\n";
+print OFILE "            </propgroup>\n";
+print OFILE "     </facility>\n";
+
 calc_nodes(0);
 
 printf OFILE "    <dependents grouping='children'>\n";
--- a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4540/Sun-Fire-X4540-hc-topology.xmlgen	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4540/Sun-Fire-X4540-hc-topology.xmlgen	Thu Jul 31 17:35:39 2008 -0700
@@ -200,6 +200,102 @@
 printf OFILE "  <range name='bay' min='0' max='%d'>\n",
 		$sys_supported->{"num_bays"}-1;
 
+#
+# Statically define locate indicator
+#
+print OFILE "     <facility name='locate' type='indicator' ".
+    "provider='fac_prov_ipmi' >\n";
+print OFILE "           <propgroup name='facility' version='1' ".
+    "name-stability='Private' data-stability='Private' >\n";
+print OFILE "                <propval name='type' type='uint32' value='1' />\n";
+print OFILE "                <propmethod name='ipmi_entity' version='0' ".
+    "propname='entity_ref' proptype='string' >\n";
+print OFILE "                    <argval name='format' type='string' ".
+    "value='hdd%d.ok2rm.led' />\n";
+print OFILE "                    <argval name='offset' type='uint32' ".
+    "value='0' />\n";
+print OFILE "                    <argval name='nparams' type='uint32' ".
+    "value='1' />\n";
+print OFILE "                </propmethod>\n";
+print OFILE "                <propmethod name='thumper_locate_mode' ".
+    "version='0'\n";
+print OFILE "                   propname='mode' proptype='uint32' ".
+    "mutable='1' >\n";
+print OFILE "                </propmethod>\n";
+print OFILE "            </propgroup>\n";
+print OFILE "     </facility>\n";
+
+#
+# Statically define ok2rm indicator
+#
+print OFILE "     <facility name='ok2rm' type='indicator' ".
+    "provider='fac_prov_ipmi' >\n";
+print OFILE "           <propgroup name='facility' version='1' ".
+    "name-stability='Private' data-stability='Private' >\n";
+print OFILE "                <propval name='type' type='uint32' value='2' />\n";
+print OFILE "                <propmethod name='ipmi_entity' version='0' ".
+    "propname='entity_ref' proptype='string' >\n";
+print OFILE "                    <argval name='format' type='string' ".
+    "value='hdd%d.state' />\n";
+print OFILE "			 <argval name='offset' type='uint32' ".
+    "value='0' />\n";
+print OFILE "                    <argval name='nparams' type='uint32' ".
+    "value='1' />\n";
+print OFILE "			</propmethod>\n";
+print OFILE "			<propmethod name='thumper_indicator_mode' ".
+    "version='0'\n";
+print OFILE "			propname='mode' proptype='uint32' ".
+    "mutable='1' >\n";
+print OFILE "			</propmethod>\n";
+print OFILE "		 </propgroup>\n";
+print OFILE "	  </facility>\n";
+
+#
+# Statically define service indicator
+#
+print OFILE "	  <facility name='service' type='indicator' ".
+    "provider='fac_prov_ipmi' >\n";
+print OFILE "		<propgroup name='facility' version='1' ".
+    "name-stability='Private' data-stability='Private' >\n";
+print OFILE "			<propval name='type' type='uint32' value='0' />\n";
+print OFILE "			<propmethod name='ipmi_entity' version='0' ".
+    "propname='entity_ref' proptype='string' >\n";
+print OFILE "			 <argval name='format' type='string' ".
+    "value='hdd%d.state' />\n";
+print OFILE "			 <argval name='offset' type='uint32' ".
+    "value='0' />\n";
+print OFILE "                    <argval name='nparams' type='uint32' ".
+    "value='1' />\n";
+print OFILE "			</propmethod>\n";
+print OFILE "			<propmethod name='thumper_indicator_mode' ".
+    "version='0' propname='mode' proptype='uint32' mutable='1' >\n";
+print OFILE "			</propmethod>\n";
+print OFILE "		 </propgroup>\n";
+print OFILE "	  </facility>\n";
+
+#
+# Statically define present indicator
+#
+print OFILE "	  <facility name='present' type='indicator' ".
+    "provider='fac_prov_ipmi' >\n";
+print OFILE "		<propgroup name='facility' version='1' ".
+    "name-stability='Private' data-stability='Private' >\n";
+print OFILE "			<propval name='type' type='uint32' value='3' />\n";
+print OFILE "			<propmethod name='ipmi_entity' version='0' ".
+    "propname='entity_ref' proptype='string' >\n";
+print OFILE "			 <argval name='format' type='string' ".
+    "value='hdd%d.state' />\n";
+print OFILE "			 <argval name='offset' type='uint32' ".
+    "value='0' />\n";
+print OFILE "                    <argval name='nparams' type='uint32' ".
+    "value='1' />\n";
+print OFILE "			</propmethod>\n";
+print OFILE "			<propmethod name='thumper_indicator_mode' ".
+    "version='0' propname='mode' proptype='uint32' mutable='1' >\n";
+print OFILE "			</propmethod>\n";
+print OFILE "		 </propgroup>\n";
+print OFILE "	  </facility>\n";
+
 calc_nodes(0);
 
 printf OFILE "    <dependents grouping='children'>\n";
--- a/usr/src/lib/fm/topo/maps/common/topology.dtd.1	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/maps/common/topology.dtd.1	Thu Jul 31 17:35:39 2008 -0700
@@ -125,7 +125,7 @@
 -->
 
 <!ELEMENT set
-	 ( range*, propgroup* ) >
+	 ( range*, fac-enum?, propgroup*, facility* ) >
 
 <!ATTLIST set
 	type	( product ) #REQUIRED
@@ -177,6 +177,7 @@
       		version		Version of the method API
       		propname	Name of the property to create
 		proptype	Type of the property to create
+		mutable         optional: default is false (0)
 -->
 
 <!ELEMENT propmethod
@@ -186,7 +187,8 @@
 	name		CDATA #REQUIRED
 	version		CDATA #REQUIRED
 	propname	CDATA #REQUIRED
-	proptype	CDATA #REQUIRED>
+	proptype	CDATA #REQUIRED
+	mutable		(0|1) "0" >
 
 <!--
   enum-method
@@ -221,7 +223,7 @@
 -->
 
 <!ELEMENT node
-	( propgroup*, dependents*, set*, enum-method* ) >
+	( fac-enum?, facility*, propgroup*, set*, enum-method*, dependents? ) >
 
 <!ATTLIST node
 	instance	CDATA #REQUIRED >
@@ -259,7 +261,8 @@
 -->
 
 <!ELEMENT range
-	( enum-method?, propmap?, node*, propgroup*, set*, dependents* ) >
+	( enum-method?, propmap?, fac-enum?, facility*, node*, propgroup*, set*,
+	    dependents* ) >
 
 <!ATTLIST range
 	name		CDATA #REQUIRED
@@ -267,6 +270,47 @@
 	max		CDATA #REQUIRED >
 
 <!--
+  facility
+
+    This element identifies a single facility node instance
+
+    Its attributes are
+
+	name	The name of the facility node
+
+	type	The type of facility node: either "sensor" or "indicator"
+
+	provider	The name of the facility provider module that
+	                implements the methods for this node or range
+-->
+
+<!ELEMENT facility
+	( propgroup* ) >
+
+<!ATTLIST facility
+	name		CDATA #REQUIRED
+	type		(sensor | indicator) #REQUIRED
+	provider	CDATA #REQUIRED >
+
+<!--
+  fac-enum
+
+    This element identifies a facility provider module that
+    implements a facility enumeration method for the enclosing
+    node or range.
+
+    Its attributes are
+
+	provider	The name of the facility provider module that
+	                implements the facility enumerator method for
+			the parent node or range
+-->
+
+<!ELEMENT fac-enum EMPTY >
+
+<!ATTLIST fac-enum provider CDATA #REQUIRED >
+
+<!--
   topology
 
 	This is the root-level for the scheme-specific topology
--- a/usr/src/lib/fm/topo/maps/i86pc/chip-hc-topology.xml	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/maps/i86pc/chip-hc-topology.xml	Thu Jul 31 17:35:39 2008 -0700
@@ -31,7 +31,7 @@
     <range name='chip' min='0' max='100'>
 
         <set type='product'
-	    setlist='Sun-Fire-V20z|Sun-Fire-V40z|W1100z-2100z|Sun-Ultra-20-Workstation|Ultra20-M2|Sun-Ultra-40-M2-Workstation'>
+	    setlist='Sun-Fire(TM)-X2100|W1100z-2100z|Sun-Ultra-20-Workstation|Ultra20-M2|Sun-Ultra-40-M2-Workstation'>
 	    
             <propgroup name='protocol' version='1'
                 name-stability='Private' data-stability='Private' >
@@ -48,7 +48,7 @@
 
         </set> 
         <set type='product'
-	    setlist='Sun-Fire(TM)-X2100|Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4200E|Sun-Fire-X4500|X2100-M2|Sun-Fire-X4140|Sun-Fire-X4240|Sun-Fire-X4440'>
+	    setlist='Sun-Fire-V20z|Sun-Fire-V40z'>
 	    
             <propgroup name='protocol' version='1'
                 name-stability='Private' data-stability='Private' >
@@ -62,14 +62,191 @@
                 </propmethod>
 
             </propgroup>
+            <propgroup name='ipmi' version='1'
+               name-stability='Private' data-stability='Private' >
+                 <propmethod name='ipmi_entity' version='0'
+		            propname='entity_ref' proptype='string' >
+              
+                    <argval name='format' type='string' value='cpu%d.vpd' />
+                    <argval name='offset' type='uint32' value='0' />
+                    <argval name='nparams' type='uint32' value='1' />
 
+                </propmethod>
+            </propgroup>
+
+        </set> 
+        <set type='product'
+	    setlist='X2100-M2|Sun-Blade-X8440-Server-Module'>
+            <propgroup name='protocol' version='1'
+                name-stability='Private' data-stability='Private' >
+
+                <propmethod name='simple_chip_label' version='0'
+		            propname='label' proptype='string' >
+              
+                    <argval name='format' type='string' value='CPU %d' />
+                    <argval name='offset' type='uint32' value='0' />
+
+                </propmethod>
+
+            </propgroup>
+            <propgroup name='ipmi' version='1'
+               name-stability='Private' data-stability='Private' >
+                 <propmethod name='ipmi_entity' version='0'
+		            propname='entity_ref' proptype='string' >
+              
+                    <argval name='format' type='string' value='p%d.fru' />
+                    <argval name='offset' type='uint32' value='0' />
+                    <argval name='nparams' type='uint32' value='1' />
+
+                </propmethod>
+            </propgroup>
+        </set> 
+
+        <set type='product'
+	    setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4200E|Sun-Fire-X4140|Sun-Fire-X4240|Sun-Fire-X4440'>
+	    <fac-enum provider='fac_prov_ipmi' />
+	    <!--
+	       chip FRU label
+	    -->
+            <propgroup name='protocol' version='1'
+                name-stability='Private' data-stability='Private' >
+
+                <propmethod name='simple_chip_label' version='0'
+		            propname='label' proptype='string' >
+              
+                    <argval name='format' type='string' value='CPU %d' />
+                    <argval name='offset' type='uint32' value='0' />
+
+                </propmethod>
+
+            </propgroup>
+            <propgroup name='ipmi' version='1'
+               name-stability='Private' data-stability='Private' >
+                 <propmethod name='ipmi_entity' version='0'
+		            propname='entity_ref' proptype='string' >
+              
+                    <argval name='format' type='string' value='p%d.fru' />
+                    <argval name='offset' type='uint32' value='0' />
+                    <argval name='nparams' type='uint32' value='1' />
+
+                </propmethod>
+            </propgroup>
+	    <!--
+	       chip service LED
+	    -->
+            <facility name='service' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+                    <propval name='type' type='uint32' value='0' />
+                    <propmethod name='ipmi_entity' version='0' propname='entity_ref' proptype='string' >
+                        <argval name='format' type='string' value='p%d.led' />
+                        <argval name='offset' type='uint32' value='0' />
+                        <argval name='nparams' type='uint32' value='1' />
+                    </propmethod>
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1'>
+                    </propmethod>
+                </propgroup>
+            </facility>
+        </set> 
+        <set type='product' setlist='Sun-Fire-X4500'>
+            <fac-enum provider='fac_prov_ipmi' />
+            <!--
+               chip FRU label
+            -->
+            <propgroup name='protocol' version='1'
+                name-stability='Private' data-stability='Private' >
+
+                <propmethod name='simple_chip_label' version='0'
+                            propname='label' proptype='string' >
+
+                    <argval name='format' type='string' value='CPU %d' />
+                    <argval name='offset' type='uint32' value='0' />
+
+                </propmethod>
+
+            </propgroup>
+            <propgroup name='ipmi' version='1'
+               name-stability='Private' data-stability='Private' >
+                 <propmethod name='ipmi_entity' version='0'
+                            propname='entity_ref' proptype='string' >
+
+                    <argval name='format' type='string' value='p%d.fru' />
+                    <argval name='offset' type='uint32' value='0' />
+                    <argval name='nparams' type='uint32' value='1' />
+
+                </propmethod>
+	    </propgroup>
+            <!--
+               chip service LED
+            -->
+            <facility name='service' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+                    <propval name='type' type='uint32' value='0' />
+                    <propmethod name='ipmi_entity' version='0' propname='entity_ref' proptype='string' >
+                        <argval name='format' type='string' value='p%d.fail.led' />
+                        <argval name='offset' type='uint32' value='0' />
+                        <argval name='nparams' type='uint32' value='1' />
+                    </propmethod>
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+            </facility>
+        </set>
+ 
+        <set type='product' setlist='Sun-Fire-X4540'>
+	    <fac-enum provider='fac_prov_ipmi' />
+	    <!--
+	       chip FRU label
+	    -->
+            <propgroup name='protocol' version='1'
+                name-stability='Private' data-stability='Private' >
+
+                <propmethod name='simple_chip_label' version='0'
+		            propname='label' proptype='string' >
+              
+                    <argval name='format' type='string' value='CPU %d' />
+                    <argval name='offset' type='uint32' value='0' />
+
+                </propmethod>
+
+            </propgroup>
+            <propgroup name='ipmi' version='1'
+               name-stability='Private' data-stability='Private' >
+                 <propmethod name='ipmi_entity' version='0'
+		            propname='entity_ref' proptype='string' >
+              
+                    <argval name='format' type='string' value='p%d.fru' />
+                    <argval name='offset' type='uint32' value='0' />
+                    <argval name='nparams' type='uint32' value='1' />
+
+                </propmethod>
+            </propgroup>
+	    <!--
+	       chip service LED
+	    -->
+            <facility name='service' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+                    <propval name='type' type='uint32' value='0' />
+                    <propmethod name='ipmi_entity' version='0' propname='entity_ref' proptype='string' >
+                        <argval name='format' type='string' value='p%d.led' />
+                        <argval name='offset' type='uint32' value='0' />
+                        <argval name='nparams' type='uint32' value='1' />
+                    </propmethod>
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+            </facility>
         </set> 
         <set type='product'
 	    setlist='Sun-Fire-X4100-M2|Sun-Fire-X4200-M2'>
-	    
+	    <fac-enum provider='fac_prov_ipmi' />
+	    <!--
+	       chip FRU label
+	    -->
             <propgroup name='protocol' version='1'
                 name-stability='Private' data-stability='Private' >
-
                 <propmethod name='simple_chip_label' version='0'
 		            propname='label' proptype='string' >
               
@@ -79,11 +256,41 @@
                 </propmethod>
 
             </propgroup>
+            <propgroup name='ipmi' version='1'
+               name-stability='Private' data-stability='Private' >
+                 <propmethod name='ipmi_entity' version='0'
+		            propname='entity_ref' proptype='string' >
+              
+                    <argval name='format' type='string' value='p%d.fru' />
+                    <argval name='offset' type='uint32' value='0' />
+                    <argval name='nparams' type='uint32' value='1' />
 
+                </propmethod>
+            </propgroup>
+	    <!--
+	       chip service LED
+	    -->
+            <facility name='service' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+                    <propval name='type' type='uint32' value='0' />
+                    <propmethod name='ipmi_entity' version='0' propname='entity_ref' proptype='string' >
+                        <argval name='format' type='string' value='p%d.led' />
+                        <argval name='offset' type='uint32' value='0' />
+                        <argval name='nparams' type='uint32' value='1' />
+                    </propmethod>
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+            </facility>
         </set> 
         <set type='product'
 	    setlist='Sun-Fire-X4600|Sun-Fire-X4600-M2'>
 	    
+	    <fac-enum provider='fac_prov_ipmi' />
+	    <!--
+	       chip FRU label
+	    -->
             <propgroup name='protocol' version='1'
                 name-stability='Private' data-stability='Private' >
 
@@ -95,7 +302,34 @@
                 </propmethod>
 
             </propgroup>
+            <propgroup name='ipmi' version='1'
+               name-stability='Private' data-stability='Private' >
+                 <propmethod name='ipmi_entity' version='0'
+		            propname='entity_ref' proptype='string' >
+              
+                    <argval name='format' type='string' value='p%d.fru' />
+                    <argval name='offset' type='uint32' value='0' />
+                    <argval name='nparams' type='uint32' value='1' />
 
+                </propmethod>
+            </propgroup>
+	    <!--
+	       chip service LED
+	    -->
+            <facility name='service' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+                    <propval name='type' type='uint32' value='0' />
+                    <propmethod name='ipmi_entity' version='0' propname='entity_ref' proptype='string' >
+                        <argval name='format' type='string' value='p%d.led' />
+                        <argval name='offset' type='uint32' value='0' />
+                        <argval name='nparams' type='uint32' value='1' />
+                    </propmethod>
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+            </facility>
+ 
         </set> 
         <set type='product'
 	    setlist='Sun-Blade-X8420-Server-Module|Sun-Blade-X8440-Server-Module|SUN-BLADE-X8440-SERVER-MODULE'>
@@ -212,8 +446,62 @@
 
                     </propgroup>
                 </set>
-                <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4200E|Sun-Fire-X4500'>
+                <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4200E'>
 		    
+		    <fac-enum provider='fac_prov_ipmi' />
+                    <propgroup name='protocol' version='1'
+                               name-stability='Private'
+			       data-stability='Private' >
+
+                        <propmethod name='simple_dimm_label_mp' version='0'
+			            propname='label' proptype='string' >
+              
+                            <argval name='format' type='string'
+			        value='CPU %d DIMM %d' />
+                            <argval name='offset' type='uint32' value='0' />
+                            <argval name='order' type='string'
+			        value='forward' />
+                            <argval name='dimms_per_chip' type='uint32'
+			        value='4' />
+
+                        </propmethod>
+                        <propmethod name='get_dimm_serial' version='0'
+			            propname='serial' proptype='string' >
+              
+                            <argval name='format' type='string'
+			        value='p%d.d%d.fru' />
+                            <argval name='offset' type='uint32' value='0' />
+
+                        </propmethod>
+                    </propgroup>
+                    <propgroup name='ipmi' version='1'
+                    	name-stability='Private' data-stability='Private' >
+			
+                         <propmethod name='dimm_ipmi_entity' version='0'
+		            propname='entity_ref' proptype='string' >
+              
+                            <argval name='format' type='string' 
+			        value='p%d.d%d.fru' />
+                            <argval name='offset' type='uint32' value='0' />
+
+                        </propmethod>
+                    </propgroup>
+                    <facility name='service' type='indicator' provider='fac_prov_ipmi' >
+                        <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+                          <propval name='type' type='uint32' value='0' />
+                          <propmethod name='dimm_ipmi_entity' version='0' propname='entity_ref' proptype='string' >
+                            <argval name='format' type='string' value='p%d.d%d.led' />
+                            <argval name='offset' type='uint32' value='0' />
+                          </propmethod>
+                          <propmethod name='ipmi_indicator_mode' version='0'
+                             propname='mode' proptype='uint32' mutable='1' >
+                          </propmethod>
+                       </propgroup>
+                    </facility>
+                </set>
+                <set type='product' setlist='Sun-Fire-X4500'>
+		    
+		    <fac-enum provider='fac_prov_ipmi' />
                     <propgroup name='protocol' version='1'
                                name-stability='Private'
 			       data-stability='Private' >
@@ -238,12 +526,35 @@
                             <argval name='offset' type='uint32' value='0' />
 
                         </propmethod>
+                    </propgroup>
+                    <propgroup name='ipmi' version='1'
+                    	name-stability='Private' data-stability='Private' >
+			
+                         <propmethod name='dimm_ipmi_entity' version='0'
+		            propname='entity_ref' proptype='string' >
+              
+                            <argval name='format' type='string' 
+			        value='p%d.d%d.fru' />
+                            <argval name='offset' type='uint32' value='0' />
 
+                        </propmethod>
                     </propgroup>
-
+                    <facility name='service' type='indicator' provider='fac_prov_ipmi' >
+                        <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+                          <propval name='type' type='uint32' value='0' />
+                          <propmethod name='dimm_ipmi_entity' version='0' propname='entity_ref' proptype='string' >
+                            <argval name='format' type='string' value='p%d.d%d.fail.led' />
+                            <argval name='offset' type='uint32' value='0' />
+                          </propmethod>
+                          <propmethod name='ipmi_indicator_mode' version='0'
+                             propname='mode' proptype='uint32' mutable='1' >
+                          </propmethod>
+                       </propgroup>
+                    </facility>
                 </set>
                 <set type='product' setlist='Sun-Fire-X4100-M2|Sun-Fire-X4200-M2'>
 		    
+		    <fac-enum provider='fac_prov_ipmi' />
                     <propgroup name='protocol' version='1'
                                name-stability='Private'
 			       data-stability='Private' >
@@ -265,10 +576,37 @@
                         </propmethod>
 
                     </propgroup>
+                    <propgroup name='ipmi' version='1'
+                    	name-stability='Private' data-stability='Private' >
+			
+                         <propmethod name='dimm_ipmi_entity' version='0'
+		            propname='entity_ref' proptype='string' >
+              
+                            <argval name='format' type='string' 
+			        value='p%d.d%d.fru' />
+                            <argval name='offset' type='uint32' value='0' />
 
+                        </propmethod>
+                    </propgroup>
+		    <!--
+		      DIMM service LED
+		    -->
+                    <facility name='service' type='indicator' provider='fac_prov_ipmi' >
+                        <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+                          <propval name='type' type='uint32' value='0' />
+                          <propmethod name='dimm_ipmi_entity' version='0' propname='entity_ref' proptype='string' >
+                            <argval name='format' type='string' value='p%d.d%d.led' />
+                            <argval name='offset' type='uint32' value='0' />
+                          </propmethod>
+                          <propmethod name='ipmi_indicator_mode' version='0'
+                             propname='mode' proptype='uint32' mutable='1' >
+                          </propmethod>
+                       </propgroup>
+                    </facility>
                 </set>
                 <set type='product' setlist='Sun-Fire-X4600|Sun-Fire-X4600-M2'>
 		    
+		    <fac-enum provider='fac_prov_ipmi' />
                     <propgroup name='protocol' version='1'
                                name-stability='Private'
 			       data-stability='Private' >
@@ -291,6 +629,33 @@
                         </propmethod>
 
                     </propgroup>
+                    <propgroup name='ipmi' version='1'
+                    	name-stability='Private' data-stability='Private' >
+			
+                         <propmethod name='dimm_ipmi_entity' version='0'
+		            propname='entity_ref' proptype='string' >
+              
+                            <argval name='format' type='string' 
+			        value='p%d.d%d.fru' />
+                            <argval name='offset' type='uint32' value='0' />
+
+                        </propmethod>
+                    </propgroup>
+		    <!--
+		      DIMM service LED
+		    -->
+                    <facility name='service' type='indicator' provider='fac_prov_ipmi' >
+                        <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+                          <propval name='type' type='uint32' value='0' />
+                          <propmethod name='dimm_ipmi_entity' version='0' propname='entity_ref' proptype='string' >
+                            <argval name='format' type='string' value='p%d.d%d.led' />
+                            <argval name='offset' type='uint32' value='0' />
+                          </propmethod>
+                          <propmethod name='ipmi_indicator_mode' version='0'
+                             propname='mode' proptype='uint32' mutable='1' >
+                          </propmethod>
+                       </propgroup>
+                    </facility>
 
                 </set>
                 <set type='product'
--- a/usr/src/lib/fm/topo/maps/i86pc/fan-hc-topology.xmlgen	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/maps/i86pc/fan-hc-topology.xmlgen	Thu Jul 31 17:35:39 2008 -0700
@@ -54,9 +54,13 @@
 		count => 2,
 		fru => "self"
 	    }, {
+	        fac_enum => 1,
+		provider => "fac_prov_ipmi",
 		count => 3,
 		label => "FT %d FM %d",
 		entity_ref => "ft%d.fm%d.led",
+		entity_ref_nparams => 2,
+		fm_service_indctr => "ft%d.fm%d.led",
 		fru => "self"
 	    }
 	]
@@ -72,12 +76,21 @@
 	set => "Sun-Fire-X4500|Sun-Fire-X4540",
 	topology => [
 	    {
+	        fac_enum => 0,
+		provider => "fac_prov_ipmi",
 		label => "FT %d",
 		count => 5,
 		fru => "self",
 		entity_ref => "ft%d.prsnt",
+		entity_ref_nparams => 1,
+		fm_service_indctr => "ft%d.service.led",
+		fm_ok2rm_indctr => "ft%d.ok2rm.led",
 	    }, {
+	        fac_enum => 1,
+		provider => "fac_prov_ipmi",
 		count => 2,
+		entity_ref => "ft%d.f%d.speed",
+		entity_ref_nparams => 2,
 		fru => "parent"
 	    }
 	]
@@ -86,8 +99,10 @@
     #
     # Fan Module/Fan topology for all G1N/G2N platforms.
     #
-    # These systems have 6 fan modules, with each fan module containing 2 fans.
-    # The FRU's for the individual fans are the containing fan module.
+    # There are two fan boards, which are FRU's.  Each fan board has
+    # 3 fan modules for a total of 6 fan modules, with each fan module
+    # containing 2 fans.  The FRU's for the individual fans are the
+    # containing fan module.
     #
     # Unfortunately, the IPMI topology on these systems is rather broken, and
     # all the SDRs that should be separate entities in fact refer to the same
@@ -99,19 +114,47 @@
 	topology => [
 	    {
 		count => 2,
-		label => "FT %d",
+		label => "FANBD%d",
 		fru => "self"
 	    }, {
-		label => "FT %d FM %d",
+		fac_enum => 1,
+		provider => "fac_prov_ipmi",
+		label => "FANBD%d FM%d",
 		count => 3,
 		fru => "self",
 		entity_present => "fb%d.fm%d.prsnt",
+		entity_ref => "fb%d.fm%d.prsnt",
+		entity_ref_nparams => 2,
+		fm_service_indctr_ => "fb%d.fm%d.led",
 	    }, {
 		count => 2,
 		fru => "parent"
 	    }
 
 	]
+    },
+
+    #
+    # Fan Module/Fan topology for G4F platforms.
+    #
+    # These systems have 4 fan assemblies with a single fan per assembly.
+    # Each fan assembly is a FRU.  The fan assemblies have a service LED
+    # but no other indicators.
+    #
+    {
+	set => "Sun-Fire-X4600-M2",
+	topology => [
+	    {
+	        fac_enum => 1,
+		provider => "fac_prov_ipmi",
+		count => 4,
+		label => "FT %d",
+		fru => "self",
+		entity_ref => "ft%d.fm0.prsnt",
+		entity_ref_nparams => 1,
+		fm_service_indctr => "ft%d.fm0.led"
+	    }	
+	]
     }
 );
 
@@ -143,6 +186,69 @@
 
 		$indent += 2;
 
+		# Facility enumerator
+		if ($level->{fac_enum}) {
+			printf(OFILE "%*s<fac-enum provider='",
+			    $indent, "");
+			printf(OFILE $level->{provider}, @indices);
+			printf(OFILE "' />\n");
+		}
+
+		# Facility nodes for service and ok2rm LED's
+		if ($level->{fm_service_indctr}) {
+			printf(OFILE "%*s<facility name='service' type='indicator' ".
+			    "provider='fac_prov_ipmi' >\n", $indent+2, "");
+			printf(OFILE "%*s<propgroup name='facility' version='1' ".
+			    "name-stability='Private' data-stability='Private' >\n",
+			    $indent+4, "");
+			printf(OFILE "%*s<propval name='type' type='uint32' ".
+			    "value='1' />\n", $indent+6, "");
+			printf(OFILE "%*s<propmethod name='ipmi_entity' version='0' ".
+			    "propname='entity_ref' proptype='string' >\n",
+			    $indent+6, "");
+			printf(OFILE "%*s<argval name='format' type='string' ".
+			    "value='%s' />\n", $indent+8, "",
+			    $level->{fm_service_indctr});
+			printf(OFILE "%*s<argval name='offset' type='uint32' ".
+			    "value='0' />\n", $indent+8, "");
+			printf(OFILE "%*s<argval name='nparams' type='uint32' ".
+			    "value='%d' />\n", $indent+8, "",
+			    $level->{entity_ref_nparams});
+			printf(OFILE "%*s</propmethod>\n", $indent+6, "");
+			printf(OFILE "%*s<propmethod name='ipmi_indicator_mode' ".
+			    "version='0' propname='mode' proptype='uint32' ".
+			    "mutable='1' >\n", $indent+6, "");
+			printf(OFILE "%*s</propmethod>\n", $indent+6, "");
+			printf(OFILE "%*s</propgroup>\n", $indent+4, "");
+			printf(OFILE "%*s</facility>\n", $indent+2, "");
+		}
+		if ($level->{fm_ok2rm_indctr}) {
+			printf(OFILE "%*s<facility name='ok2rm' type='indicator' ".
+			    "provider='fac_prov_ipmi' >\n", $indent+2, "");
+			printf(OFILE "%*s<propgroup name='facility' version='1' ".
+			    "name-stability='Private' data-stability='Private' >\n",
+			    $indent+4, "");
+			printf(OFILE "%*s<propval name='type' type='uint32' ".
+			    "value='2' />\n", $indent+6, "");
+			printf(OFILE "%*s<propmethod name='ipmi_entity' version='0' ".
+			    "propname='entity_ref' proptype='string' >\n",
+			    $indent+6, "");
+			printf(OFILE "%*s<argval name='format' type='string' ".
+			    "value='%s' />\n", $indent+8, "",
+			    $level->{fm_ok2rm_indctr});
+			printf(OFILE "%*s<argval name='offset' type='uint32' ".
+			    "value='0' />\n", $indent+8, "");
+			printf(OFILE "%*s<argval name='nparams' type='uint32' ".
+			    "value='%d' />\n", $indent+8, "",
+			    $level->{entity_ref_nparams});
+			printf(OFILE "%*s</propmethod>\n", $indent+6, "");
+			printf(OFILE "%*s<propmethod name='ipmi_indicator_mode' ".
+			    "version='0' propname='mode' proptype='uint32' mutable='1' >\n",
+			    $indent+6, "");
+			printf(OFILE "%*s</propmethod>\n", $indent+6, "");
+			printf(OFILE "%*s</propgroup>\n", $indent+4, "");
+			printf(OFILE "%*s</facility>\n", $indent+2, "");
+		}
 		# Protocol properties (label, fmri)
 		printf(OFILE "%*s<propgroup name='protocol' version='1' " .
 		    "name-stability='Private' data-stability='Private'>\n",
@@ -169,7 +275,7 @@
 		printf(OFILE "%*s</propgroup>\n", $indent, "");
 
 		#
-		# Entity reference (if any)
+		# Entity references (if any)
 		#
 		if ($level->{entity_ref} || $level->{entity_present}) {
 			my $name = $level->{entity_ref} ? "entity_ref" :
@@ -185,6 +291,13 @@
 			printf(OFILE "%*s</propgroup>\n", $indent, "");
 		}
 
+		#
+		# Post-process IPMI enumerator method
+		#
+		if ($level->{provider}) {
+			printf(OFILE "%*s<enum-method name='ipmi' version='1' ".
+			    "/>\n", $indent, "");
+		}
 
 		#
 		# Children (if any)
@@ -196,12 +309,6 @@
 			printf(OFILE "%*s</dependents>\n", $indent, "");
 		}
 
-		#
-		# Post-process IPMI enumerator method
-		#
-		printf(OFILE "%*s<enum-method name='ipmi' version='1' />\n",
-		   $indent, "");
-
 		$indent -= 2;
 
 		printf(OFILE "%*s</node>\n", $indent, "");
--- a/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml	Thu Jul 31 17:35:39 2008 -0700
@@ -30,10 +30,24 @@
 
   <range name='motherboard' min='0' max='0'>
     <node instance='0'>
-      <propgroup name='protocol' version='1'
-          name-stability='Private' data-stability='Private' >
-          <propval name='label' type='string' value='MB' />
-      </propgroup>
+      <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4240|Sun-Fire-X4440|Sun-Fire-X4500|Sun-Fire-X4540|Sun-Fire-X4600-M2'>
+        <fac-enum provider='fac_prov_ipmi' />
+        <propgroup name='protocol' version='1'
+            name-stability='Private' data-stability='Private' >
+            <propval name='label' type='string' value='MB' />
+        </propgroup>
+        <propgroup name='ipmi' version='1'
+            name-stability='Private' data-stability='Private' >
+            <propval name='entity_ref' type='string' value='mb.fru' />
+        </propgroup>
+
+      </set>
+      <set type='product' setlist='default'>
+        <propgroup name='protocol' version='1'
+            name-stability='Private' data-stability='Private' >
+            <propval name='label' type='string' value='MB' />
+        </propgroup>
+      </set>
     </node>
  
     <dependents grouping='children'>
@@ -50,8 +64,152 @@
 
   <range name='chassis' min='0' max='0'>
     <node instance='0'>
+        <set type='product' setlist='Sun-Fire-X4240|Sun-Fire-X4440'>
+          <fac-enum provider='fac_prov_ipmi' />
+          <propgroup name='ipmi' version='1'
+              name-stability='Private' data-stability='Private' >
+             <propval name='entity_ref' type='string' value='sys.intsw' />
+          </propgroup>
+        </set>
+        <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2'>
+          <fac-enum provider='fac_prov_ipmi' />
+          <propgroup name='ipmi' version='1'
+              name-stability='Private' data-stability='Private' >
+             <propval name='entity_ref' type='string' value='sys.intsw' />
+          </propgroup>
+	  <!--
+	  	chassis locate and service LED's for Galaxy 1/2
+	  -->
+          <facility name='fp.locate.led' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+		    <propval name='entity_ref' type='string' value='fp.locate.led' />
+                    <propval name='type' type='uint32' value='1' />
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+          </facility>
+          <facility name='bp.locate.led' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+		    <propval name='entity_ref' type='string' value='bp.locate.led' />
+                    <propval name='type' type='uint32' value='1' />
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+          </facility>
+          <facility name='fp.alert.led' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+		    <propval name='entity_ref' type='string' value='fp.alert.led' />
+                    <propval name='type' type='uint32' value='0' />
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+          </facility>
+          <facility name='bp.alert.led' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+		    <propval name='entity_ref' type='string' value='bp.alert.led' />
+                    <propval name='type' type='uint32' value='0' />
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+          </facility>
+        </set>
+        <set type='product' setlist='Sun-Fire-X4500|Sun-Fire-X4540'>
+          <fac-enum provider='fac_prov_ipmi' />
+          <propgroup name='ipmi' version='1'
+              name-stability='Private' data-stability='Private' >
+             <propval name='entity_ref' type='string' value='sys.intsw' />
+          </propgroup>
+	  <!--
+	  	chassis locate and service LED's for X4500/X4540
+	  -->
+          <facility name='fp.locate.led' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+		    <propval name='entity_ref' type='string' value='fp.locate.led' />
+                    <propval name='type' type='uint32' value='1' />
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+          </facility>
+          <facility name='bp.locate.led' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+		    <propval name='entity_ref' type='string' value='bp.locate.led' />
+                    <propval name='type' type='uint32' value='1' />
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+          </facility>
+          <facility name='fp.alert.led' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+		    <propval name='entity_ref' type='string' value='fp.alert.led' />
+                    <propval name='type' type='uint32' value='0' />
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+          </facility>
+          <facility name='bp.alert.led' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+		    <propval name='entity_ref' type='string' value='bp.alert.led' />
+                    <propval name='type' type='uint32' value='0' />
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+          </facility>
+          <facility name='sys.top_svc.led' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+		    <propval name='entity_ref' type='string' value='sys.top_svc.led' />
+                    <propval name='type' type='uint32' value='0' />
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+          </facility>
+          <facility name='sys.rear_svc.led' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+		    <propval name='entity_ref' type='string' value='sys.rear_svc.led' />
+                    <propval name='type' type='uint32' value='0' />
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+          </facility>
+        </set>
+        <set type='product' setlist='Sun-Fire-X4600-M2'>
+          <fac-enum provider='fac_prov_ipmi' />
+          <propgroup name='ipmi' version='1'
+              name-stability='Private' data-stability='Private' >
+             <propval name='entity_ref' type='string' value='sys.intsw' />
+          </propgroup>
+	  <!--
+	  	chassis locate and service LED's for X4600M2
+	  -->
+          <facility name='sys.locate.led' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+		    <propval name='entity_ref' type='string' value='sys.locate.led' />
+                    <propval name='type' type='uint32' value='1' />
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+          </facility>
+          <facility name='sys.alert.led' type='indicator' provider='fac_prov_ipmi' >
+                <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+		    <propval name='entity_ref' type='string' value='sys.alert.led' />
+                    <propval name='type' type='uint32' value='0' />
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+                </propgroup>
+          </facility>
+        </set>
     </node>
-    
     <dependents grouping='children'>
     
     <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4240|Sun-Fire-X4440'>
@@ -73,6 +231,16 @@
        </range>
     </set>
       
+   <set type='product' setlist='Sun-Fire-X4600-M2'>
+       <range name='psu' min='0' max='100'>
+          <enum-method name='ipmi' version='1' />
+          <propmap name='psu' />
+       </range>
+       <range name='fan' min='0' max='3'>
+          <propmap name='fan' />
+       </range>
+    </set>
+
     <set type='product' setlist='default'>
        <range name='psu' min='0' max='100'>
    	  <enum-method name='ipmi' version='1' />
--- a/usr/src/lib/fm/topo/maps/i86pc/psu-hc-topology.xml	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/maps/i86pc/psu-hc-topology.xml	Thu Jul 31 17:35:39 2008 -0700
@@ -36,6 +36,7 @@
   <set type='product' setlist='Sun-Fire-X4500|Sun-Fire-X4540'>
     <range name='psu' min='0' max='100'>
 	<node instance='0'>
+	  <fac-enum provider='fac_prov_ipmi' />
 	  <propgroup name='protocol' version='1'
 	       name-stability='Private' data-stability='Private' >
                     <propval name='label' type='string' value='PS0' />
@@ -52,6 +53,7 @@
 	  <enum-method name='ipmi' version='1' />
         </node>
 	<node instance='1'>
+	  <fac-enum provider='fac_prov_ipmi' />
 	  <propgroup name='protocol' version='1'
 	       name-stability='Private' data-stability='Private' >
                     <propval name='label' type='string' value='PS1' />
@@ -69,8 +71,18 @@
         </node>
     </range>
   </set>
-  <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4240|Sun-Fire-X4440'>
+  <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4240|Sun-Fire-X4440|Sun-Fire-X4600-M2'>
     <range name='psu' min='0' max='100'>
+        <fac-enum provider='fac_prov_ipmi' />
+        <facility name='sys.psfail.led' type='indicator' provider='fac_prov_ipmi' >
+              <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' >
+		    <propval name='entity_ref' type='string' value='sys.psfail.led' />
+                    <propval name='type' type='uint32' value='0' />
+                    <propmethod name='ipmi_indicator_mode' version='0'
+                       propname='mode' proptype='uint32' mutable='1' >
+                    </propmethod>
+              </propgroup>
+        </facility>
         <propgroup name='protocol' version='1'
             name-stability='Private' data-stability='Private' >
 
@@ -82,6 +94,18 @@
 
                 </propmethod>
         </propgroup>
+        <propgroup name='ipmi' version='1'
+            name-stability='Private' data-stability='Private' >
+
+                 <propmethod name='ipmi_entity' version='0'
+		            propname='entity_ref' proptype='string' >
+              
+                    <argval name='format' type='string' value='ps%d.prsnt' />
+                    <argval name='offset' type='uint32' value='0' />
+		    <argval name='nparams' type='uint32' value='1' />
+
+                </propmethod>
+        </propgroup>
     </range>
   </set>
 </topology>
--- a/usr/src/lib/fm/topo/modules/common/Makefile	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/fm/topo/modules/common/Makefile	Thu Jul 31 17:35:39 2008 -0700
@@ -27,6 +27,7 @@
 
 SUBDIRS =		\
 	disk		\
+	fac_prov_ipmi	\
 	ipmi		\
 	ses		\
 	xfp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/Makefile	Thu Jul 31 17:35:39 2008 -0700
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+MODULE = fac_prov_ipmi
+CLASS = common
+
+MODULESRCS = fac_prov_ipmi.c
+
+include ../../Makefile.plugin
+
+LDLIBS += -lipmi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c	Thu Jul 31 17:35:39 2008 -0700
@@ -0,0 +1,1095 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <limits.h>
+#include <alloca.h>
+#include <errno.h>
+#include <libnvpair.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/fm/protocol.h>
+#include <fm/libtopo.h>
+#include <fm/topo_mod.h>
+#include <libipmi.h>
+
+#define	BUFSZ	128
+#define	TOPO_PGROUP_IPMI	"ipmi"
+
+#define	THUMPER_PRESENT_LED_MASK	0x01
+#define	THUMPER_SERVICE_LED_MASK	0x02
+#define	THUMPER_OK2RM_LED_MASK		0x08
+
+/*
+ * The largest possible SDR ID length is 2^5+1
+ */
+#define	MAX_ID_LEN	33
+
+#define	TOPO_METH_IPMI_READING_VERSION		0
+#define	TOPO_METH_IPMI_STATE_VERSION		0
+#define	TOPO_METH_IPMI_MODE_VERSION		0
+#define	TOPO_METH_THUMPER_LOCATE_VERSION	0
+#define	TOPO_METH_THUMPER_MODE_VERSION		0
+#define	TOPO_METH_IPMI_ENTITY_VERSION		0
+#define	TOPO_METH_DIMM_IPMI_ENTITY_VERSION	0
+
+static int fac_prov_ipmi_enum(topo_mod_t *, tnode_t *, const char *,
+    topo_instance_t, topo_instance_t, void *, void *);
+
+/*
+ * IPMI facility provider methods
+ */
+static int ipmi_sensor_enum(topo_mod_t *, tnode_t *, topo_version_t,
+    nvlist_t *, nvlist_t **);
+static int ipmi_entity(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
+    nvlist_t **);
+static int dimm_ipmi_entity(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
+    nvlist_t **);
+static int ipmi_sensor_reading(topo_mod_t *, tnode_t *, topo_version_t,
+    nvlist_t *, nvlist_t **);
+static int ipmi_sensor_state(topo_mod_t *, tnode_t *, topo_version_t,
+    nvlist_t *, nvlist_t **);
+static int ipmi_indicator_mode(topo_mod_t *, tnode_t *, topo_version_t,
+    nvlist_t *, nvlist_t **);
+static int thumper_locate_mode(topo_mod_t *, tnode_t *, topo_version_t,
+    nvlist_t *, nvlist_t **);
+static int thumper_indicator_mode(topo_mod_t *, tnode_t *, topo_version_t,
+    nvlist_t *, nvlist_t **);
+
+const topo_modops_t ipmi_ops = { fac_prov_ipmi_enum, NULL };
+
+const topo_modinfo_t ipmi_info =
+	{ "IPMI facility provider", FM_FMRI_SCHEME_HC, TOPO_VERSION,
+	&ipmi_ops };
+
+static const topo_method_t ipmi_node_methods[] = {
+	{ TOPO_METH_FAC_ENUM, TOPO_METH_FAC_ENUM_DESC, 0,
+	    TOPO_STABILITY_INTERNAL, ipmi_sensor_enum },
+	{ TOPO_METH_IPMI_ENTITY, TOPO_PROP_METH_DESC,
+	    TOPO_METH_IPMI_ENTITY_VERSION,
+	    TOPO_STABILITY_INTERNAL, ipmi_entity },
+	{ "dimm_ipmi_entity", TOPO_PROP_METH_DESC,
+	    TOPO_METH_DIMM_IPMI_ENTITY_VERSION,
+	    TOPO_STABILITY_INTERNAL, dimm_ipmi_entity },
+	{ NULL }
+};
+
+static const topo_method_t ipmi_fac_methods[] = {
+	{ "ipmi_sensor_reading", TOPO_PROP_METH_DESC,
+	    TOPO_METH_IPMI_READING_VERSION,
+	    TOPO_STABILITY_INTERNAL, ipmi_sensor_reading },
+	{ "ipmi_sensor_state", TOPO_PROP_METH_DESC,
+	    TOPO_METH_IPMI_STATE_VERSION,
+	    TOPO_STABILITY_INTERNAL, ipmi_sensor_state },
+	{ "ipmi_indicator_mode", TOPO_PROP_METH_DESC,
+	    TOPO_METH_IPMI_MODE_VERSION,
+	    TOPO_STABILITY_INTERNAL, ipmi_indicator_mode },
+	{ "thumper_locate_mode", TOPO_PROP_METH_DESC,
+	    TOPO_METH_THUMPER_LOCATE_VERSION,
+	    TOPO_STABILITY_INTERNAL, thumper_locate_mode },
+	{ "thumper_indicator_mode", TOPO_PROP_METH_DESC,
+	    TOPO_METH_THUMPER_MODE_VERSION,
+	    TOPO_STABILITY_INTERNAL, thumper_indicator_mode },
+	{ TOPO_METH_IPMI_ENTITY, TOPO_PROP_METH_DESC,
+	    TOPO_METH_IPMI_ENTITY_VERSION,
+	    TOPO_STABILITY_INTERNAL, ipmi_entity },
+	{ "dimm_ipmi_entity", TOPO_PROP_METH_DESC,
+	    TOPO_METH_DIMM_IPMI_ENTITY_VERSION,
+	    TOPO_STABILITY_INTERNAL, dimm_ipmi_entity },
+	{ NULL }
+};
+
+struct entity_info {
+	uint32_t ei_id;
+	uint32_t ei_inst;
+	topo_mod_t *ei_mod;
+	tnode_t *ei_node;
+};
+
+struct sensor_data {
+	char sd_entity_ref[MAX_ID_LEN];
+	uint8_t sd_units;
+	uint32_t sd_stype;
+	uint32_t sd_rtype;
+	char *sd_class;
+};
+
+/*ARGSUSED*/
+int
+_topo_init(topo_mod_t *mod, topo_version_t version)
+{
+	if (getenv("TOPOFACIPMIDEBUG") != NULL)
+		topo_mod_setdebug(mod);
+
+	return (topo_mod_register(mod, &ipmi_info, TOPO_VERSION));
+}
+
+void
+_topo_fini(topo_mod_t *mod)
+{
+	topo_mod_unregister(mod);
+}
+
+static char *
+get_fmtstr(topo_mod_t *mod, nvlist_t *in)
+{
+	char *fmtstr;
+	nvlist_t *args;
+
+	if (nvlist_lookup_nvlist(in, TOPO_PROP_ARGS, &args) != 0) {
+		topo_mod_dprintf(mod, "Failed to lookup 'args' list (%s)\n",
+		    strerror(errno));
+		(void) topo_mod_seterrno(mod, EMOD_NVL_INVAL);
+		return (NULL);
+	}
+	if (nvlist_lookup_string(args, "format", &fmtstr) != 0) {
+		topo_mod_dprintf(mod, "Failed to lookup 'format' arg (%s)\n",
+		    strerror(errno));
+		(void) topo_mod_seterrno(mod, EMOD_NVL_INVAL);
+		return (NULL);
+	}
+	return (fmtstr);
+}
+
+/*ARGSUSED*/
+static int
+ipmi_sensor_state(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+    nvlist_t *in, nvlist_t **out)
+{
+	char *entity_ref;
+	ipmi_sdr_t *sdr = NULL;
+	ipmi_sensor_reading_t *reading;
+	ipmi_handle_t *hdl;
+	int err;
+	uint8_t sensor_num;
+	ipmi_sdr_full_sensor_t *fsensor;
+	ipmi_sdr_compact_sensor_t *csensor;
+	nvlist_t *nvl;
+
+	if (vers > TOPO_METH_IPMI_STATE_VERSION)
+		return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
+
+	if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref",
+	    &entity_ref, &err) != 0) {
+		topo_mod_dprintf(mod, "Failed to lookup entity_ref property "
+		    "(%s)", topo_strerror(err));
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+
+	if ((hdl = topo_mod_ipmi(mod)) == NULL) {
+		topo_mod_dprintf(mod, "Failed to get IPMI handle\n");
+		topo_mod_strfree(mod, entity_ref);
+		return (-1);
+	}
+
+	if ((sdr = ipmi_sdr_lookup(hdl, entity_ref)) == NULL) {
+		topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n",
+		    entity_ref, ipmi_errmsg(hdl));
+		topo_mod_strfree(mod, entity_ref);
+		return (-1);
+	}
+
+	switch (sdr->is_type) {
+		case IPMI_SDR_TYPE_FULL_SENSOR:
+			fsensor = (ipmi_sdr_full_sensor_t *)sdr->is_record;
+			sensor_num = fsensor->is_fs_number;
+			break;
+		case IPMI_SDR_TYPE_COMPACT_SENSOR:
+			csensor = (ipmi_sdr_compact_sensor_t *)sdr->is_record;
+			sensor_num = csensor->is_cs_number;
+			break;
+		default:
+			topo_mod_dprintf(mod, "%s does not refer to a full or "
+			    "compact SDR\n", entity_ref);
+			topo_mod_strfree(mod, entity_ref);
+			return (-1);
+	}
+	if ((reading = ipmi_get_sensor_reading(hdl, sensor_num))
+	    == NULL) {
+		topo_mod_dprintf(mod, "Failed to get sensor reading for sensor "
+		    "%s, sensor_num=%d (%s)\n", entity_ref, sensor_num,
+		    ipmi_errmsg(hdl));
+		topo_mod_strfree(mod, entity_ref);
+		return (-1);
+	}
+	topo_mod_strfree(mod, entity_ref);
+
+	if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 ||
+	    nvlist_add_string(nvl, TOPO_PROP_VAL_NAME,
+	    TOPO_SENSOR_STATE) != 0 ||
+	    nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 ||
+	    nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, reading->isr_state)
+	    != 0) {
+		topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n");
+		nvlist_free(nvl);
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
+	}
+	*out = nvl;
+
+	return (0);
+}
+
+/*ARGSUSED*/
+static int
+ipmi_sensor_reading(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+    nvlist_t *in, nvlist_t **out)
+{
+	char *entity_ref, reading_str[BUFSZ];
+	int err = 0;
+	ipmi_sdr_full_sensor_t *sensor;
+	ipmi_sensor_reading_t  *reading;
+	double conv_reading;
+	ipmi_handle_t *hdl;
+	nvlist_t *nvl;
+
+	if (vers > TOPO_METH_IPMI_READING_VERSION)
+		return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
+
+	if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref",
+	    &entity_ref, &err) != 0) {
+		topo_mod_dprintf(mod, "Failed to lookup entity_ref property "
+		    "(%s)", topo_strerror(err));
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+
+	if ((hdl = topo_mod_ipmi(mod)) == NULL) {
+		topo_mod_dprintf(mod, "Failed to get IPMI handle\n");
+		topo_mod_strfree(mod, entity_ref);
+		return (-1);
+	}
+
+	if ((sensor = ipmi_sdr_lookup_full_sensor(hdl, entity_ref))
+	    == NULL) {
+		topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n",
+		    entity_ref, ipmi_errmsg(hdl));
+		topo_mod_strfree(mod, entity_ref);
+		return (-1);
+	}
+
+	if ((reading = ipmi_get_sensor_reading(hdl, sensor->is_fs_number))
+	    == NULL) {
+		topo_mod_dprintf(mod, "Failed to get sensor reading for sensor "
+		    "%s, sensor_num=%d (%s)\n", entity_ref,
+		    sensor->is_fs_number, ipmi_errmsg(hdl));
+		topo_mod_strfree(mod, entity_ref);
+		return (-1);
+	}
+	if (ipmi_sdr_conv_reading(sensor, reading->isr_reading, &conv_reading)
+	    != 0) {
+		topo_mod_dprintf(mod, "Failed to convert sensor reading for "
+		    "sensor %s (%s)\n", entity_ref, ipmi_errmsg(hdl));
+		topo_mod_strfree(mod, entity_ref);
+		return (-1);
+	}
+	topo_mod_strfree(mod, entity_ref);
+
+	(void) snprintf(reading_str, BUFSZ, "%f", conv_reading);
+	if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 ||
+	    nvlist_add_string(nvl, TOPO_PROP_VAL_NAME,
+	    TOPO_SENSOR_READING) != 0 ||
+	    nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_DOUBLE) != 0 ||
+	    nvlist_add_double(nvl, TOPO_PROP_VAL_VAL, conv_reading) != 0) {
+		topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n");
+		nvlist_free(nvl);
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
+	}
+	*out = nvl;
+
+	return (0);
+}
+
+static int
+ipmi_indicator_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+    nvlist_t *in, nvlist_t **out)
+{
+	char *entity_ref;
+	ipmi_sdr_generic_locator_t *gdl = NULL;
+	ipmi_handle_t *hdl;
+	int err, ret;
+	uint8_t ledmode;
+	uint32_t mode_in;
+	nvlist_t *pargs, *nvl;
+
+	if (vers > TOPO_METH_IPMI_MODE_VERSION)
+		return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
+
+	/*
+	 * Get an IPMI handle and then lookup the generic device locator sensor
+	 * data record referenced by the entity_ref prop val
+	 */
+	if ((hdl = topo_mod_ipmi(mod)) == NULL) {
+		topo_mod_dprintf(mod, "Failed to get IPMI handle\n");
+		return (-1);
+	}
+
+	if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref",
+	    &entity_ref, &err) != 0) {
+		topo_mod_dprintf(mod, "Failed to lookup entity_ref property "
+		    "(%s)", topo_strerror(err));
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+
+	if ((gdl = ipmi_sdr_lookup_generic(hdl, entity_ref))
+	    == NULL) {
+		topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n",
+		    entity_ref, ipmi_errmsg(hdl));
+		topo_mod_strfree(mod, entity_ref);
+		return (-1);
+	}
+
+	/*
+	 * Now look for a private argument list to figure out whether we're
+	 * doing a get or a set operation, and then do it.
+	 */
+	if ((nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0) &&
+	    nvlist_exists(pargs, TOPO_PROP_VAL_VAL)) {
+		/*
+		 * Set the LED mode
+		 */
+		if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL,
+		    &mode_in)) != 0) {
+			topo_mod_dprintf(mod, "Failed to lookup %s nvpair "
+			    "(%s)\n", TOPO_PROP_VAL_VAL, strerror(ret));
+			topo_mod_strfree(mod, entity_ref);
+			return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+		}
+		if (mode_in != TOPO_LED_STATE_OFF &&
+		    mode_in != TOPO_LED_STATE_ON) {
+			topo_mod_dprintf(mod, "Invalid property value: %d\n",
+			    mode_in);
+			topo_mod_strfree(mod, entity_ref);
+			return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+		}
+		ledmode = (uint8_t)mode_in;
+		topo_mod_dprintf(mod, "Setting LED mode to %s\n",
+		    ledmode ? "ON" : "OFF");
+		if (ipmi_sunoem_led_set(hdl, gdl, ledmode) < 0) {
+			topo_mod_dprintf(mod, "Failed to set LED mode for %s "
+			    "(%s)\n", entity_ref, ipmi_errmsg(hdl));
+			topo_mod_strfree(mod, entity_ref);
+			return (-1);
+		}
+	} else {
+		/*
+		 * Get the LED mode
+		 */
+		topo_mod_dprintf(mod, "Getting LED mode\n");
+		if (ipmi_sunoem_led_get(hdl, gdl, &ledmode) < 0) {
+			topo_mod_dprintf(mod, "Failed to get LED mode for %s "
+			    "(%s)\n", entity_ref, ipmi_errmsg(hdl));
+			topo_mod_strfree(mod, entity_ref);
+			return (-1);
+		}
+	}
+	topo_mod_strfree(mod, entity_ref);
+
+	if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 ||
+	    nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 ||
+	    nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 ||
+	    nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) {
+		topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n");
+		nvlist_free(nvl);
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
+	}
+	*out = nvl;
+
+	return (0);
+}
+
+/*
+ * On thumper platforms these is no seperate locate LED for the drive bays.
+ * Therefore we simulate a locate LED by blinking the ok2rm LED.
+ */
+static int
+thumper_locate_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+    nvlist_t *in, nvlist_t **out)
+{
+	char *entity_ref;
+	ipmi_sdr_generic_locator_t *gdl = NULL;
+	ipmi_handle_t *hdl;
+	int err, ret;
+	uint8_t ledmode;
+	uint32_t mode_in;
+	nvlist_t *pargs, *nvl;
+
+	if (vers > TOPO_METH_THUMPER_LOCATE_VERSION)
+		return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
+
+	/*
+	 * Get an IPMI handle and then lookup the generic device locator sensor
+	 * data record referenced by the entity_ref prop val
+	 */
+	if ((hdl = topo_mod_ipmi(mod)) == NULL) {
+		topo_mod_dprintf(mod, "Failed to get IPMI handle\n");
+		return (-1);
+	}
+
+	if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref",
+	    &entity_ref, &err) != 0) {
+		topo_mod_dprintf(mod, "Failed to lookup entity_ref property "
+		    "(%s)", topo_strerror(err));
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+
+	if ((gdl = ipmi_sdr_lookup_generic(hdl, entity_ref))
+	    == NULL) {
+		topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n",
+		    entity_ref, ipmi_errmsg(hdl));
+		topo_mod_strfree(mod, entity_ref);
+		return (-1);
+	}
+
+	/*
+	 * Now look for a private argument list to figure out whether we're
+	 * doing a get or a set operation, and then do it.
+	 */
+	if ((nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0) &&
+	    nvlist_exists(pargs, TOPO_PROP_VAL_VAL)) {
+		/*
+		 * Set the LED mode
+		 */
+		if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL,
+		    &mode_in)) != 0) {
+			topo_mod_dprintf(mod, "Failed to lookup %s nvpair "
+			    "(%s)\n", TOPO_PROP_VAL_VAL, strerror(ret));
+			topo_mod_strfree(mod, entity_ref);
+			return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+		}
+		if (mode_in != TOPO_LED_STATE_OFF &&
+		    mode_in != TOPO_LED_STATE_ON) {
+			topo_mod_dprintf(mod, "Invalid property value: %d\n",
+			    mode_in);
+			topo_mod_strfree(mod, entity_ref);
+			return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+		}
+		if (mode_in == TOPO_LED_STATE_ON)
+			ledmode = IPMI_SUNOEM_LED_MODE_FAST;
+		else
+			ledmode = (uint8_t)mode_in;
+		if (ipmi_sunoem_led_set(hdl, gdl, ledmode) < 0) {
+			topo_mod_dprintf(mod, "Failed to set LED mode for %s "
+			    "(%s)\n", entity_ref, ipmi_errmsg(hdl));
+			topo_mod_strfree(mod, entity_ref);
+			return (-1);
+		}
+	} else {
+		/*
+		 * Get the LED mode
+		 */
+		if (ipmi_sunoem_led_get(hdl, gdl, &ledmode) < 0) {
+			topo_mod_dprintf(mod, "Failed to get LED mode for %s "
+			    "(%s)\n", entity_ref, ipmi_errmsg(hdl));
+			topo_mod_strfree(mod, entity_ref);
+			return (-1);
+		}
+	}
+	topo_mod_strfree(mod, entity_ref);
+
+	if (ledmode == IPMI_SUNOEM_LED_MODE_FAST)
+		ledmode = TOPO_LED_STATE_ON;
+	else
+		ledmode = TOPO_LED_STATE_OFF;
+
+	if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 ||
+	    nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 ||
+	    nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 ||
+	    nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) {
+		topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n");
+		nvlist_free(nvl);
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
+	}
+	*out = nvl;
+
+	return (0);
+}
+
+
+/*
+ * This is a method for the "mode" property that is specific for the drive bay
+ * LED's on thumper platforms.  On thumper, the drive bay LED's are manipulated
+ * by asserting the right state bits in the hdd#.state compact SDR.
+ */
+static int
+thumper_indicator_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+    nvlist_t *in, nvlist_t **out)
+{
+	char *entity_ref;
+	ipmi_sdr_compact_sensor_t *cs = NULL;
+	ipmi_handle_t *hdl;
+	int err, ret;
+	uint32_t mask, type, ledmode;
+	nvlist_t *pargs, *nvl;
+
+	if (vers > TOPO_METH_THUMPER_MODE_VERSION)
+		return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
+
+	/*
+	 * Figure out which sensor state mask to use based on the indicator
+	 * node's type prop val
+	 */
+	if (topo_prop_get_uint32(node, TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE,
+	    &type, &err) != 0) {
+		topo_mod_dprintf(mod, "Failed to lookup %s property "
+		    "(%s)", TOPO_FACILITY_TYPE, topo_strerror(err));
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+	switch (type) {
+	case (TOPO_LED_TYPE_SERVICE):
+		mask = THUMPER_SERVICE_LED_MASK;
+		break;
+	case (TOPO_LED_TYPE_PRESENT):
+		mask = THUMPER_PRESENT_LED_MASK;
+		break;
+	case (TOPO_LED_TYPE_OK2RM):
+		mask = THUMPER_OK2RM_LED_MASK;
+		break;
+	default:
+		topo_mod_dprintf(mod, "Invalid LED type: 0x%x\n", type);
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+
+	/*
+	 * Get an IPMI handle and then lookup the compact sensor data record
+	 * referenced by the entity_ref prop val
+	 */
+	if ((hdl = topo_mod_ipmi(mod)) == NULL) {
+		topo_mod_dprintf(mod, "Failed to get IPMI handle\n");
+		return (-1);
+	}
+
+	if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref",
+	    &entity_ref, &err) != 0) {
+		topo_mod_dprintf(mod, "Failed to lookup entity_ref property "
+		    "(%s)", topo_strerror(err));
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+
+	if ((cs = ipmi_sdr_lookup_compact_sensor(hdl, entity_ref))
+	    == NULL) {
+		topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n",
+		    entity_ref, ipmi_errmsg(hdl));
+		topo_mod_strfree(mod, entity_ref);
+		return (-1);
+	}
+
+	/*
+	 * Now lookup the propmethod argument list and figure out whether we're
+	 * doing a get or a set operation, and then do it.
+	 */
+	if ((nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0) &&
+	    nvlist_exists(pargs, TOPO_PROP_VAL_VAL)) {
+		/*
+		 * Set the LED mode
+		 */
+		ipmi_set_sensor_reading_t sr_out;
+
+		if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL,
+		    &ledmode)) != 0) {
+			topo_mod_dprintf(mod, "Failed to lookup %s nvpair "
+			    "(%s)\n", TOPO_PROP_VAL_VAL, strerror(ret));
+			topo_mod_strfree(mod, entity_ref);
+			return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+		}
+
+		if (ledmode == TOPO_LED_STATE_OFF) {
+			sr_out.iss_deassert_state = mask;
+			sr_out.iss_deassrt_op = IPMI_SENSOR_OP_SET;
+		} else if (ledmode == TOPO_LED_STATE_ON) {
+			sr_out.iss_assert_state = mask;
+			sr_out.iss_assert_op = IPMI_SENSOR_OP_SET;
+		} else {
+			topo_mod_dprintf(mod, "Invalid LED mode: %d 0x%x\n",
+			    ledmode);
+			topo_mod_strfree(mod, entity_ref);
+			return (-1);
+		}
+		sr_out.iss_id = cs->is_cs_number;
+		topo_mod_dprintf(mod, "Setting LED mode (mask = 0x%x)\n", mask);
+		if (ipmi_set_sensor_reading(hdl, &sr_out) != 0) {
+			topo_mod_dprintf(mod, "Failed to set sensor reading "
+			    "for sensor %s (%s)\n", entity_ref,
+			    ipmi_errmsg(hdl));
+			topo_mod_strfree(mod, entity_ref);
+			return (-1);
+		}
+	} else {
+		/*
+		 * Get the LED mode
+		 */
+		ipmi_sensor_reading_t *sr_in;
+
+		topo_mod_dprintf(mod, "Getting LED mode\n");
+		if ((sr_in = ipmi_get_sensor_reading(hdl, cs->is_cs_number))
+		    == NULL) {
+			topo_mod_dprintf(mod, "Failed to get sensor reading "
+			    "for sensor %s (sensor num: %d) (error: %s)\n",
+			    entity_ref, cs->is_cs_number, ipmi_errmsg(hdl));
+			topo_mod_strfree(mod, entity_ref);
+			return (-1);
+		}
+		if (sr_in->isr_state & (uint16_t)mask)
+			ledmode = TOPO_LED_STATE_ON;
+		else
+			ledmode = TOPO_LED_STATE_OFF;
+	}
+	topo_mod_strfree(mod, entity_ref);
+
+	if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 ||
+	    nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 ||
+	    nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 ||
+	    nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) {
+		topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n");
+		nvlist_free(nvl);
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
+	}
+	*out = nvl;
+	return (0);
+}
+
+static int
+make_sensor_node(topo_mod_t *mod, tnode_t *pnode, struct sensor_data *sd)
+{
+	int err, ret;
+	tnode_t *fnode;
+	char *ftype = "sensor";
+	topo_pgroup_info_t pgi;
+	nvlist_t *arg_nvl = NULL;
+
+	if ((fnode = topo_node_facbind(mod, pnode, sd->sd_entity_ref,
+	    ftype)) == NULL) {
+		topo_mod_dprintf(mod, "Failed to bind facility node: %s\n",
+		    sd->sd_entity_ref);
+		/* topo errno set */
+		return (-1);
+	}
+
+	pgi.tpi_name = TOPO_PGROUP_FACILITY;
+	pgi.tpi_namestab = TOPO_STABILITY_PRIVATE;
+	pgi.tpi_datastab = TOPO_STABILITY_PRIVATE;
+	pgi.tpi_version = 1;
+	if (topo_pgroup_create(fnode, &pgi, &err) != 0) {
+		if (err != ETOPO_PROP_DEFD) {
+			topo_mod_dprintf(mod,  "pgroups create failure: %s\n",
+			    topo_strerror(err));
+			topo_node_unbind(fnode);
+			return (-1);
+		}
+	}
+	if (topo_method_register(mod, fnode, ipmi_fac_methods) < 0) {
+		topo_mod_dprintf(mod, "make_fac_node: "
+		    "failed to register facility methods");
+		topo_node_unbind(fnode);
+		return (-1);
+	}
+	/*
+	 * For both threshold and discrete sensors we set up a propmethod for
+	 * getting the sensor state and properties to hold the entity ref,
+	 * sensor class and sensor type.
+	 *
+	 * Additionally, for analog sensors we set up a property method for
+	 * getting the converted sensor reading and property for the base
+	 * unit type
+	 */
+	if (topo_prop_set_string(fnode, TOPO_PGROUP_FACILITY, "entity_ref",
+	    TOPO_PROP_IMMUTABLE, sd->sd_entity_ref, &err) != 0) {
+		topo_mod_dprintf(mod, "Failed to set entity_ref property on "
+		    "node: %s=%d (%s)\n", topo_node_name(fnode),
+		    topo_node_instance(fnode), topo_strerror(err));
+		return (-1);
+	}
+	if (topo_prop_set_string(fnode, TOPO_PGROUP_FACILITY, TOPO_SENSOR_CLASS,
+	    TOPO_PROP_IMMUTABLE, sd->sd_class, &err) != 0) {
+		topo_mod_dprintf(mod, "Failed to set %s property on node: "
+		    "%s=%d (%s)\n", TOPO_SENSOR_CLASS, topo_node_name(fnode),
+		    topo_node_instance(fnode), topo_strerror(err));
+		return (-1);
+	}
+	if (topo_prop_set_uint32(fnode, TOPO_PGROUP_FACILITY,
+	    TOPO_FACILITY_TYPE, TOPO_PROP_IMMUTABLE, sd->sd_stype, &err) != 0) {
+		topo_mod_dprintf(mod, "Failed to set %s property on node: "
+		    "%s=%d (%s)\n", TOPO_FACILITY_TYPE, topo_node_name(fnode),
+		    topo_node_instance(fnode), topo_strerror(err));
+		return (-1);
+	}
+	if (topo_mod_nvalloc(mod, &arg_nvl, NV_UNIQUE_NAME) < 0) {
+		topo_node_unbind(fnode);
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
+	}
+
+	if ((ret = nvlist_add_string(arg_nvl, "ipmi_entity", sd->sd_entity_ref))
+	    != 0) {
+		topo_mod_dprintf(mod, "Failed build arg nvlist (%s)\n",
+		    strerror(ret));
+		nvlist_free(arg_nvl);
+		return (-1);
+	}
+
+	if (topo_prop_method_register(fnode, TOPO_PGROUP_FACILITY,
+	    TOPO_SENSOR_STATE, TOPO_TYPE_UINT32, "ipmi_sensor_state", arg_nvl,
+	    &err) != 0) {
+		topo_mod_dprintf(mod, "Failed to register %s propmeth on fac "
+		    "node %s (%s)\n", TOPO_SENSOR_STATE, topo_node_name(fnode),
+		    topo_strerror(err));
+		nvlist_free(arg_nvl);
+		return (-1);
+	}
+
+	if (strcmp(sd->sd_class, TOPO_SENSOR_CLASS_THRESHOLD) == 0) {
+		if (topo_prop_method_register(fnode, TOPO_PGROUP_FACILITY,
+		    TOPO_SENSOR_READING, TOPO_TYPE_DOUBLE,
+		    "ipmi_sensor_reading", arg_nvl, &err) != 0) {
+			topo_mod_dprintf(mod, "Failed to register %s propmeth "
+			    "on fac node %s (%s)\n", TOPO_SENSOR_READING,
+			    topo_node_name(fnode), topo_strerror(err));
+			nvlist_free(arg_nvl);
+			return (-1);
+		}
+		if (topo_prop_set_uint32(fnode, TOPO_PGROUP_FACILITY,
+		    TOPO_SENSOR_UNITS, TOPO_PROP_IMMUTABLE, sd->sd_units, &err)
+		    != 0) {
+			topo_mod_dprintf(mod, "Failed to set units property on "
+			    "node: %s (%s)\n", topo_node_name(fnode),
+			    topo_strerror(err));
+			nvlist_free(arg_nvl);
+			return (-1);
+		}
+	}
+	nvlist_free(arg_nvl);
+	return (0);
+}
+
+/* ARGSUSED */
+static int
+sdr_callback(ipmi_handle_t *hdl, const char *id, ipmi_sdr_t *sdr, void *data)
+{
+	uint8_t sensor_entity, sensor_inst;
+	int sensor_idlen;
+	ipmi_sdr_full_sensor_t *f_sensor = NULL;
+	ipmi_sdr_compact_sensor_t *c_sensor = NULL;
+	struct sensor_data sd;
+	struct entity_info *ei = (struct entity_info *)data;
+
+	switch (sdr->is_type) {
+		case IPMI_SDR_TYPE_FULL_SENSOR:
+			f_sensor =
+			    (ipmi_sdr_full_sensor_t *)sdr->is_record;
+			sensor_entity = f_sensor->is_fs_entity_id;
+			sensor_inst = f_sensor->is_fs_entity_instance;
+			sensor_idlen = f_sensor->is_fs_idlen;
+			(void) strncpy(sd.sd_entity_ref,
+			    f_sensor->is_fs_idstring,
+			    f_sensor->is_fs_idlen);
+			sd.sd_entity_ref[sensor_idlen] = '\0';
+			sd.sd_class = TOPO_SENSOR_CLASS_THRESHOLD;
+			sd.sd_units = f_sensor->is_fs_unit2;
+			sd.sd_stype = f_sensor->is_fs_type;
+			sd.sd_rtype = f_sensor->is_fs_reading_type;
+			break;
+		case IPMI_SDR_TYPE_COMPACT_SENSOR:
+			c_sensor =
+			    (ipmi_sdr_compact_sensor_t *)sdr->is_record;
+			sensor_entity = c_sensor->is_cs_entity_id;
+			sensor_inst = c_sensor->is_cs_entity_instance;
+			sensor_idlen = c_sensor->is_cs_idlen;
+			(void) strncpy(sd.sd_entity_ref,
+			    c_sensor->is_cs_idstring,
+			    sensor_idlen);
+			sd.sd_entity_ref[sensor_idlen] = '\0';
+			sd.sd_class = TOPO_SENSOR_CLASS_DISCRETE;
+			sd.sd_units = c_sensor->is_cs_unit2;
+			sd.sd_stype = c_sensor->is_cs_type;
+			sd.sd_rtype = c_sensor->is_cs_reading_type;
+			break;
+		default:
+			return (0);
+	}
+	/*
+	 * We offset the threshold and generic sensor reading types by 0x100
+	 */
+	if (sd.sd_rtype >= 0x1 && sd.sd_rtype <= 0xc)
+		sd.sd_stype = sd.sd_rtype + 0x100;
+
+	if ((sensor_entity == ei->ei_id) && (sensor_inst == ei->ei_inst))
+		if (make_sensor_node(ei->ei_mod, ei->ei_node, &sd) != 0) {
+			topo_mod_dprintf(ei->ei_mod, "Failed to create sensor "
+			    "node for %s\n", sd.sd_entity_ref);
+			if (topo_mod_errno(ei->ei_mod) != EMOD_NODE_DUP)
+				return (-1);
+		}
+	return (0);
+}
+
+/* ARGSUSED */
+static int
+ipmi_sensor_enum(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+    nvlist_t *in, nvlist_t **out)
+{
+	char *entity_ref;
+	int err;
+	struct entity_info ei;
+	ipmi_sdr_t *ref_sdr;
+	ipmi_handle_t *hdl;
+	ipmi_sdr_full_sensor_t *fsensor;
+	ipmi_sdr_compact_sensor_t *csensor;
+	ipmi_sdr_fru_locator_t *floc;
+	ipmi_sdr_generic_locator_t *gloc;
+
+	if ((hdl = topo_mod_ipmi(mod)) == NULL) {
+		topo_mod_dprintf(mod, "Failed to get IPMI handle\n");
+		return (-1);
+	}
+
+	/*
+	 * Use the entity ref to lookup the SDR, which will have the entity ID
+	 * and instance.
+	 */
+	if (topo_prop_get_string(node, TOPO_PGROUP_IPMI,
+	    "entity_ref", &entity_ref, &err) != 0) {
+		topo_mod_dprintf(mod, "Failed to lookup entity_ref "
+		    "property (%s)\n", topo_strerror(err));
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+
+	topo_mod_dprintf(mod, "Looking up SDR for %s ...\n",
+	    entity_ref);
+	if ((ref_sdr = ipmi_sdr_lookup(hdl, entity_ref)) == NULL) {
+		topo_mod_dprintf(mod, "Failed to lookup SDR (%s)\n",
+		    ipmi_errmsg(hdl));
+		topo_mod_strfree(mod, entity_ref);
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+	topo_mod_strfree(mod, entity_ref);
+
+	switch (ref_sdr->is_type) {
+		case IPMI_SDR_TYPE_FULL_SENSOR:
+			fsensor = (ipmi_sdr_full_sensor_t *)ref_sdr->is_record;
+			ei.ei_id = fsensor->is_fs_entity_id;
+			ei.ei_inst = fsensor->is_fs_entity_instance;
+			break;
+		case IPMI_SDR_TYPE_COMPACT_SENSOR:
+			csensor
+			    = (ipmi_sdr_compact_sensor_t *)ref_sdr->is_record;
+			ei.ei_id = csensor->is_cs_entity_id;
+			ei.ei_inst = csensor->is_cs_entity_instance;
+			break;
+		case IPMI_SDR_TYPE_FRU_LOCATOR:
+			floc = (ipmi_sdr_fru_locator_t *)ref_sdr->is_record;
+			ei.ei_id = floc->is_fl_entity;
+			ei.ei_inst = floc->is_fl_instance;
+			break;
+		case IPMI_SDR_TYPE_GENERIC_LOCATOR:
+			gloc = (ipmi_sdr_generic_locator_t *)ref_sdr->is_record;
+			ei.ei_id = gloc->is_gl_entity;
+			ei.ei_inst = gloc->is_gl_instance;
+			break;
+		default:
+			topo_mod_dprintf(mod, "Failed to determine entity id "
+			    "and instance\n", ipmi_errmsg(hdl));
+			return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+	topo_mod_dprintf(mod, "Entity ID = 0x%x, Entity Instance = 0x%x\n",
+	    ei.ei_id, ei.ei_inst);
+
+	ei.ei_node = node;
+	ei.ei_mod = mod;
+
+	/*
+	 * Now iterate through all of the full and compact sensor data records
+	 * and create a sensor facility node for each record that matches our
+	 * entity ID and instance
+	 */
+	if (ipmi_sdr_iter(hdl, sdr_callback, &ei) != 0) {
+		topo_mod_dprintf(mod, "ipmi_sdr_iter() failed\n");
+		return (-1);
+	}
+	return (0);
+}
+
+static int
+ipmi_entity(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+    nvlist_t *in, nvlist_t **out)
+{
+	char *fmtstr, buf[BUFSZ];
+	tnode_t *refnode;
+	int ret, inst1, inst2;
+	uint32_t offset, nparams;
+	nvlist_t *args, *nvl;
+
+	if (vers > TOPO_METH_IPMI_ENTITY_VERSION)
+		return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
+
+	if ((ret = nvlist_lookup_nvlist(in, TOPO_PROP_ARGS, &args)) != 0) {
+		topo_mod_dprintf(mod, "Failed to lookup 'args' list (%s)\n",
+		    strerror(ret));
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+	if ((ret = nvlist_lookup_uint32(args, "offset", &offset)) != 0) {
+		topo_mod_dprintf(mod, "Failed to lookup 'offset' arg (%s)\n",
+		    strerror(ret));
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+	if ((ret = nvlist_lookup_uint32(args, "nparams", &nparams)) != 0) {
+		topo_mod_dprintf(mod, "Failed to lookup 'nparams' arg (%s)\n",
+		    strerror(ret));
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+
+	if ((fmtstr = get_fmtstr(mod, in)) == NULL) {
+		topo_mod_dprintf(mod, "Failed to retrieve 'format' arg\n");
+		/* topo errno already set */
+		return (-1);
+	}
+
+	if (topo_node_flags(node) & TOPO_NODE_FACILITY)
+		refnode = topo_node_parent(node);
+	else
+		refnode = node;
+
+	switch (nparams) {
+	case 1:
+		/* LINTED: E_SEC_PRINTF_VAR_FMT */
+		(void) snprintf(buf, BUFSZ, fmtstr,
+		    (topo_node_instance(refnode) + offset));
+		break;
+	case 2:
+		inst1 = topo_node_instance(topo_node_parent(refnode)) + offset;
+		inst2 = topo_node_instance(refnode) + offset;
+		/* LINTED: E_SEC_PRINTF_VAR_FMT */
+		(void) snprintf(buf, BUFSZ, fmtstr, inst1, inst2);
+		break;
+	default:
+		topo_mod_dprintf(mod, "Invalid 'nparams' argval (%d)\n",
+		    nparams);
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+
+	if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 ||
+	    nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, "entity_ref") != 0 ||
+	    nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_STRING) != 0 ||
+	    nvlist_add_string(nvl, TOPO_PROP_VAL_VAL, buf) != 0) {
+		topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n");
+		nvlist_free(nvl);
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
+	}
+	*out = nvl;
+
+	return (0);
+}
+
+/* ARGSUSED */
+static int
+dimm_ipmi_entity(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+    nvlist_t *in, nvlist_t **out)
+{
+	char *fmtstr, buf[BUFSZ];
+	tnode_t *chip, *dimm;
+	int ret;
+	uint32_t offset;
+	nvlist_t *args, *nvl;
+
+	if ((ret = nvlist_lookup_nvlist(in, TOPO_PROP_ARGS, &args)) != 0) {
+		topo_mod_dprintf(mod, "Failed to lookup 'args' list (%s)\n",
+		    strerror(ret));
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+	if ((ret = nvlist_lookup_uint32(args, "offset", &offset)) != 0) {
+		topo_mod_dprintf(mod, "Failed to lookup 'offset' arg (%s)\n",
+		    strerror(ret));
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+
+	if ((fmtstr = get_fmtstr(mod, in)) == NULL) {
+		topo_mod_dprintf(mod, "Failed to retrieve 'format' arg\n");
+		/* topo errno already set */
+		return (-1);
+	}
+
+	if (topo_node_flags(node) & TOPO_NODE_FACILITY)
+		dimm = topo_node_parent(node);
+	else
+		dimm = node;
+
+	chip = topo_node_parent(topo_node_parent(dimm));
+
+	/* LINTED: E_SEC_PRINTF_VAR_FMT */
+	(void) snprintf(buf, BUFSZ, fmtstr, topo_node_instance(chip),
+	    (topo_node_instance(dimm) + offset));
+
+	if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 ||
+	    nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, "entity_ref") != 0 ||
+	    nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_STRING) != 0 ||
+	    nvlist_add_string(nvl, TOPO_PROP_VAL_VAL, buf) != 0) {
+		topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n");
+		nvlist_free(nvl);
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
+	}
+	*out = nvl;
+
+	return (0);
+}
+
+/*ARGSUSED*/
+static int
+fac_prov_ipmi_enum(topo_mod_t *mod, tnode_t *rnode, const char *name,
+    topo_instance_t min, topo_instance_t max, void *arg, void *unused)
+{
+	topo_pgroup_info_t pgi;
+	int err;
+
+	if (topo_node_flags(rnode) == TOPO_NODE_DEFAULT) {
+		pgi.tpi_name = TOPO_PGROUP_IPMI;
+		pgi.tpi_namestab = TOPO_STABILITY_PRIVATE;
+		pgi.tpi_datastab = TOPO_STABILITY_PRIVATE;
+		pgi.tpi_version = 1;
+		if (topo_pgroup_create(rnode, &pgi, &err) != 0) {
+			if (err != ETOPO_PROP_DEFD) {
+				topo_mod_dprintf(mod,
+				    "pgroups create failure: %s\n",
+				    topo_strerror(err));
+				return (-1);
+			}
+		}
+		if (topo_method_register(mod, rnode, ipmi_node_methods) != 0) {
+			topo_mod_dprintf(mod, "fac_prov_ipmi_enum: "
+			    "topo_method_register() failed: %s",
+			    topo_mod_errmsg(mod));
+			return (-1);
+		}
+	} else {
+		if (topo_method_register(mod, rnode, ipmi_fac_methods) != 0) {
+			topo_mod_dprintf(mod, "fac_prov_ipmi_enum: "
+			    "topo_method_register() failed: %s",
+			    topo_mod_errmsg(mod));
+			return (-1);
+		}
+	}
+	return (0);
+}
--- a/usr/src/lib/libipmi/Makefile.com	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/libipmi/Makefile.com	Thu Jul 31 17:35:39 2008 -0700
@@ -52,7 +52,7 @@
 
 CLEANFILES +=	$(SRCDIR)/ipmi_tables.c	
 INCS +=		-I$(SRCDIR)
-LDLIBS +=	-lc
+LDLIBS +=	-lc -lm
 CPPFLAGS +=	$(INCS)
 
 $(LINTLIB) := SRCS=	$(SRCDIR)/$(LINTSRC)
--- a/usr/src/lib/libipmi/common/ipmi_impl.h	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/libipmi/common/ipmi_impl.h	Thu Jul 31 17:35:39 2008 -0700
@@ -120,6 +120,7 @@
 extern ipmi_name_trans_t ipmi_reading_type_table[];
 extern ipmi_name_trans_t ipmi_errno_table[];
 extern ipmi_name_trans_t ipmi_threshold_state_table[];
+extern ipmi_name_trans_t ipmi_units_type_table[];
 extern ipmi_sensor_trans_t ipmi_reading_state_table[];
 extern ipmi_sensor_trans_t ipmi_specific_state_table[];
 
--- a/usr/src/lib/libipmi/common/ipmi_sdr.c	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/libipmi/common/ipmi_sdr.c	Thu Jul 31 17:35:39 2008 -0700
@@ -30,9 +30,57 @@
 #include <stddef.h>
 #include <string.h>
 #include <strings.h>
+#include <math.h>
 
 #include "ipmi_impl.h"
 
+/*
+ * This macros are used by ipmi_sdr_conv_reading.  They were taken verbatim from
+ * the source for ipmitool (v1.88)
+ */
+#define	tos32(val, bits)	((val & ((1<<((bits)-1)))) ? (-((val) & \
+				(1<<((bits)-1))) | (val)) : (val))
+
+#define	__TO_TOL(mtol)	(uint16_t)(BSWAP_16(mtol) & 0x3f)
+
+#define	__TO_M(mtol)	(int16_t)(tos32((((BSWAP_16(mtol) & 0xff00) >> 8) | \
+				((BSWAP_16(mtol) & 0xc0) << 2)), 10))
+
+#define	__TO_B(bacc)	(int32_t)(tos32((((BSWAP_32(bacc) & \
+				0xff000000) >> 24) | \
+				((BSWAP_32(bacc) & 0xc00000) >> 14)), 10))
+
+#define	__TO_ACC(bacc)	(uint32_t)(((BSWAP_32(bacc) & 0x3f0000) >> 16) | \
+				((BSWAP_32(bacc) & 0xf000) >> 6))
+
+#define	__TO_ACC_EXP(bacc)	(uint32_t)((BSWAP_32(bacc) & 0xc00) >> 10)
+#define	__TO_R_EXP(bacc)	(int32_t)(tos32(((BSWAP_32(bacc) & 0xf0) >> 4),\
+				4))
+#define	__TO_B_EXP(bacc)	(int32_t)(tos32((BSWAP_32(bacc) & 0xf), 4))
+
+#define	SDR_SENSOR_L_LINEAR	0x00
+#define	SDR_SENSOR_L_LN		0x01
+#define	SDR_SENSOR_L_LOG10	0x02
+#define	SDR_SENSOR_L_LOG2	0x03
+#define	SDR_SENSOR_L_E		0x04
+#define	SDR_SENSOR_L_EXP10	0x05
+#define	SDR_SENSOR_L_EXP2	0x06
+#define	SDR_SENSOR_L_1_X	0x07
+#define	SDR_SENSOR_L_SQR	0x08
+#define	SDR_SENSOR_L_CUBE	0x09
+#define	SDR_SENSOR_L_SQRT	0x0a
+#define	SDR_SENSOR_L_CUBERT	0x0b
+#define	SDR_SENSOR_L_NONLINEAR	0x70
+
+/*
+ * Analog sensor reading data formats
+ *
+ * See Section 43.1
+ */
+#define	IPMI_DATA_FMT_UNSIGNED	0
+#define	IPMI_DATA_FMT_ONESCOMP	1
+#define	IPMI_DATA_FMT_TWOSCOMP	2
+
 typedef struct ipmi_sdr_cache_ent {
 	char				*isc_name;
 	struct ipmi_sdr			*isc_sdr;
@@ -530,3 +578,79 @@
 	return (ipmi_sdr_lookup_common(ihp, idstr,
 	    IPMI_SDR_TYPE_FULL_SENSOR));
 }
+
+/*
+ * Mostly taken from ipmitool source v1.88
+ *
+ * This function converts the raw sensor reading returned by
+ * ipmi_get_sensor_reading to a unit-based value of type double.
+ */
+int
+ipmi_sdr_conv_reading(ipmi_sdr_full_sensor_t *sensor, uint8_t val,
+    double *result)
+{
+	int m, b, k1, k2;
+
+	m = __TO_M(sensor->is_fs_mtol);
+	b = __TO_B(sensor->is_fs_bacc);
+	k1 = __TO_B_EXP(sensor->is_fs_bacc);
+	k2 = __TO_R_EXP(sensor->is_fs_bacc);
+
+	switch (sensor->is_fs_analog_fmt) {
+	case IPMI_DATA_FMT_UNSIGNED:
+		*result = (double)(((m * val) +
+		    (b * pow(10, k1))) * pow(10, k2));
+		break;
+	case IPMI_DATA_FMT_ONESCOMP:
+		if (val & 0x80)
+			val++;
+		/* FALLTHRU */
+	case IPMI_DATA_FMT_TWOSCOMP:
+		*result = (double)(((m * (int8_t)val) +
+		    (b * pow(10, k1))) * pow(10, k2));
+		break;
+	default:
+		/* This sensor does not return a numeric reading */
+		return (-1);
+	}
+
+	switch (sensor->is_fs_sensor_linear_type) {
+	case SDR_SENSOR_L_LN:
+		*result = log(*result);
+		break;
+	case SDR_SENSOR_L_LOG10:
+		*result = log10(*result);
+		break;
+	case SDR_SENSOR_L_LOG2:
+		*result = (double)(log(*result) / log(2.0));
+		break;
+	case SDR_SENSOR_L_E:
+		*result = exp(*result);
+		break;
+	case SDR_SENSOR_L_EXP10:
+		*result = pow(10.0, *result);
+		break;
+	case SDR_SENSOR_L_EXP2:
+		*result = pow(2.0, *result);
+		break;
+	case SDR_SENSOR_L_1_X:
+		*result = pow(*result, -1.0);	/* 1/x w/o exception */
+		break;
+	case SDR_SENSOR_L_SQR:
+		*result = pow(*result, 2.0);
+		break;
+	case SDR_SENSOR_L_CUBE:
+		*result = pow(*result, 3.0);
+		break;
+	case SDR_SENSOR_L_SQRT:
+		*result = sqrt(*result);
+		break;
+	case SDR_SENSOR_L_CUBERT:
+		*result = cbrt(*result);
+		break;
+	case SDR_SENSOR_L_LINEAR:
+	default:
+		break;
+	}
+	return (0);
+}
--- a/usr/src/lib/libipmi/common/ipmi_util.c	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/libipmi/common/ipmi_util.c	Thu Jul 31 17:35:39 2008 -0700
@@ -169,6 +169,21 @@
 }
 
 void
+ipmi_sensor_units_name(uint8_t type, char *buf, size_t len)
+{
+	ipmi_name_trans_t *ntp;
+
+	for (ntp = &ipmi_units_type_table[0]; ntp->int_name != NULL; ntp++) {
+		if (ntp->int_value == type) {
+			(void) strlcpy(buf, ntp->int_name, len);
+			return;
+		}
+	}
+
+	(void) snprintf(buf, len, "0x%02x", type);
+}
+
+void
 ipmi_sensor_reading_name(uint8_t sensor_type, uint8_t reading_type,
     char *buf, size_t len)
 {
--- a/usr/src/lib/libipmi/common/libipmi.h	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/libipmi/common/libipmi.h	Thu Jul 31 17:35:39 2008 -0700
@@ -1426,7 +1426,8 @@
 #define	IPMI_SENSOR_THRESHOLD_UPPER_NONRECOV		0x0020
 
 extern ipmi_sensor_reading_t *ipmi_get_sensor_reading(ipmi_handle_t *, uint8_t);
-
+extern int ipmi_sdr_conv_reading(ipmi_sdr_full_sensor_t *, uint8_t,
+    double *);
 /*
  * Set Sensor Reading.  See section 35.14.
  */
@@ -1517,6 +1518,7 @@
  */
 void ipmi_entity_name(uint8_t, char *, size_t);
 void ipmi_sensor_type_name(uint8_t, char *, size_t);
+void ipmi_sensor_units_name(uint8_t, char *, size_t);
 void ipmi_sensor_reading_name(uint8_t, uint8_t, char *, size_t);
 
 /*
--- a/usr/src/lib/libipmi/common/mapfile-vers	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/libipmi/common/mapfile-vers	Thu Jul 31 17:35:39 2008 -0700
@@ -46,6 +46,7 @@
 	ipmi_get_sensor_reading;
 	ipmi_open;
 	ipmi_sdr_changed;
+	ipmi_sdr_conv_reading;
 	ipmi_sdr_get;
 	ipmi_sdr_iter;
 	ipmi_sdr_lookup;
@@ -62,6 +63,7 @@
 	ipmi_sel_set_utc_offset;
 	ipmi_sensor_reading_name;
 	ipmi_sensor_type_name;
+	ipmi_sensor_units_name;
 	ipmi_send;
 	ipmi_set_sensor_reading;
 	ipmi_sunoem_led_get;
--- a/usr/src/lib/libipmi/common/mktables.sh	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/libipmi/common/mktables.sh	Thu Jul 31 17:35:39 2008 -0700
@@ -107,3 +107,17 @@
 
 echo "\t{ 0, NULL }
 };"
+
+#
+# Units
+#
+echo "\nipmi_name_trans_t ipmi_units_type_table[] = {"
+
+pattern="#define	IPMI_UNITS_\([A-Z0-9_]*\).*\$"
+replace="	{ IPMI_UNITS_\1, \"\1\" },"
+
+cat $libipmi_h | sed -n "s/$pattern/$replace/p" || exit 1
+
+echo "\t{ 0, NULL }
+};"
+
--- a/usr/src/lib/libnvpair/libnvpair.c	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/libnvpair/libnvpair.c	Thu Jul 31 17:35:39 2008 -0700
@@ -138,6 +138,12 @@
 			(void) fprintf(fp, " 0x%llx", (u_longlong_t)val);
 			break;
 		}
+		case DATA_TYPE_DOUBLE: {
+			double val;
+			(void) nvpair_value_double(nvp, &val);
+			(void) fprintf(fp, " 0x%llf", val);
+			break;
+		}
 		case DATA_TYPE_STRING: {
 			char *val;
 			(void) nvpair_value_string(nvp, &val);
@@ -583,6 +589,7 @@
 	case DATA_TYPE_NVLIST:
 	case DATA_TYPE_NVLIST_ARRAY:
 	case DATA_TYPE_BOOLEAN:
+	case DATA_TYPE_DOUBLE:
 	case DATA_TYPE_UNKNOWN:
 	default:
 		/*
--- a/usr/src/lib/libnvpair/mapfile-vers	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/lib/libnvpair/mapfile-vers	Thu Jul 31 17:35:39 2008 -0700
@@ -25,6 +25,13 @@
 # ident	"%Z%%M%	%I%	%E% SMI"
 #
 
+SUNW_1.4 {
+    global:
+	nvlist_add_double;
+	nvlist_lookup_double;
+	nvpair_value_double;
+} SUNW_1.3;
+
 SUNW_1.3 {
     global:
 	nvlist_exists;
--- a/usr/src/pkgdefs/SUNWfmd/prototype_com	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/pkgdefs/SUNWfmd/prototype_com	Thu Jul 31 17:35:39 2008 -0700
@@ -136,6 +136,7 @@
 f none usr/lib/fm/topo/maps/xfp-hc-topology.xml 444 root bin
 d none usr/lib/fm/topo/plugins 755 root bin
 f none usr/lib/fm/topo/plugins/disk.so 555 root bin
+f none usr/lib/fm/topo/plugins/fac_prov_ipmi.so 555 root bin
 f none usr/lib/fm/topo/plugins/ipmi.so 555 root bin
 f none usr/lib/fm/topo/plugins/ses.so 555 root bin
 f none usr/lib/fm/topo/plugins/xfp.so 555 root bin
--- a/usr/src/uts/common/sys/fm/protocol.h	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/uts/common/sys/fm/protocol.h	Thu Jul 31 17:35:39 2008 -0700
@@ -153,6 +153,7 @@
 #define	FM_FMRI_AUTHORITY		"authority"
 #define	FM_FMRI_SCHEME			"scheme"
 #define	FM_FMRI_SVC_AUTHORITY		"svc-authority"
+#define	FM_FMRI_FACILITY		"facility"
 
 /* FMRI authority-type member names */
 #define	FM_FMRI_AUTH_CHASSIS		"chassis-id"
@@ -206,6 +207,10 @@
 #define	FM_FMRI_HC_LIST			"hc-list"
 #define	FM_FMRI_HC_SPECIFIC		"hc-specific"
 
+/* facility member names */
+#define	FM_FMRI_FACILITY_NAME		"facility-name"
+#define	FM_FMRI_FACILITY_TYPE		"facility-type"
+
 /* hc-list version and member names */
 #define	FM_FMRI_HC_NAME			"hc-name"
 #define	FM_FMRI_HC_ID			"hc-id"
--- a/usr/src/uts/common/sys/nvpair.h	Thu Jul 31 15:42:10 2008 -0700
+++ b/usr/src/uts/common/sys/nvpair.h	Thu Jul 31 17:35:39 2008 -0700
@@ -67,7 +67,12 @@
 	DATA_TYPE_UINT8,
 	DATA_TYPE_BOOLEAN_ARRAY,
 	DATA_TYPE_INT8_ARRAY,
+#if !defined(_KERNEL)
+	DATA_TYPE_UINT8_ARRAY,
+	DATA_TYPE_DOUBLE
+#else
 	DATA_TYPE_UINT8_ARRAY
+#endif
 } data_type_t;
 
 typedef struct nvpair {
@@ -188,6 +193,9 @@
 int nvlist_add_string_array(nvlist_t *, const char *, char *const *, uint_t);
 int nvlist_add_nvlist_array(nvlist_t *, const char *, nvlist_t **, uint_t);
 int nvlist_add_hrtime(nvlist_t *, const char *, hrtime_t);
+#if !defined(_KERNEL)
+int nvlist_add_double(nvlist_t *, const char *, double);
+#endif
 
 int nvlist_remove(nvlist_t *, const char *, data_type_t);
 int nvlist_remove_all(nvlist_t *, const char *);
@@ -221,6 +229,9 @@
     nvlist_t ***, uint_t *);
 int nvlist_lookup_hrtime(nvlist_t *, const char *, hrtime_t *);
 int nvlist_lookup_pairs(nvlist_t *, int, ...);
+#if !defined(_KERNEL)
+int nvlist_lookup_double(nvlist_t *, const char *, double *);
+#endif
 
 int nvlist_lookup_nvpair(nvlist_t *, const char *, nvpair_t **);
 int nvlist_lookup_nvpair_embedded_index(nvlist_t *, const char *, nvpair_t **,
@@ -257,6 +268,9 @@
 int nvpair_value_string_array(nvpair_t *, char ***, uint_t *);
 int nvpair_value_nvlist_array(nvpair_t *, nvlist_t ***, uint_t *);
 int nvpair_value_hrtime(nvpair_t *, hrtime_t *);
+#if !defined(_KERNEL)
+int nvpair_value_double(nvpair_t *, double *);
+#endif
 
 #ifdef	__cplusplus
 }