usr/src/lib/fm/topo/libtopo/common/topo_xml.c
changeset 7243 2f11e164daec
parent 7171 b35d9b69c7d3
child 7269 93f9bfecd57b
equal deleted inserted replaced
7242:a5a434ddef57 7243:2f11e164daec
    21 
    21 
    22 /*
    22 /*
    23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
    23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
    24  * Use is subject to license terms.
    24  * Use is subject to license terms.
    25  */
    25  */
    26 
       
    27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
    26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
    28 
    27 
    29 #include <libxml/parser.h>
    28 #include <libxml/parser.h>
    30 #include <libxml/xinclude.h>
    29 #include <libxml/xinclude.h>
    31 #include <sys/fm/protocol.h>
    30 #include <sys/fm/protocol.h>
    48 
    47 
    49 static tf_rdata_t *topo_xml_walk(topo_mod_t *, tf_info_t *, xmlNodePtr,
    48 static tf_rdata_t *topo_xml_walk(topo_mod_t *, tf_info_t *, xmlNodePtr,
    50     tnode_t *);
    49     tnode_t *);
    51 static tf_edata_t *enum_attributes_process(topo_mod_t *, xmlNodePtr);
    50 static tf_edata_t *enum_attributes_process(topo_mod_t *, xmlNodePtr);
    52 static int enum_run(topo_mod_t *, tf_rdata_t *);
    51 static int enum_run(topo_mod_t *, tf_rdata_t *);
       
    52 static int fac_enum_run(topo_mod_t *, tnode_t *, const char *);
       
    53 static int fac_process(topo_mod_t *, xmlNodePtr, tf_rdata_t *, tnode_t *);
       
    54 static int fac_enum_process(topo_mod_t *, xmlNodePtr, tnode_t *);
    53 static int decorate_nodes(topo_mod_t *, tf_rdata_t *, xmlNodePtr, tnode_t *,
    55 static int decorate_nodes(topo_mod_t *, tf_rdata_t *, xmlNodePtr, tnode_t *,
    54     tf_pad_t **);
    56     tf_pad_t **);
    55 
    57 
    56 
    58 
    57 int
    59 int
   101     xmlNodePtr n, const char *propname, uint64_t *value)
   103     xmlNodePtr n, const char *propname, uint64_t *value)
   102 {
   104 {
   103 	xmlChar *str;
   105 	xmlChar *str;
   104 	xmlChar *estr;
   106 	xmlChar *estr;
   105 
   107 
   106 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "attribute to int\n");
   108 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xmlattr_to_int(propname=%s)\n",
       
   109 	    propname);
   107 	if ((str = xmlGetProp(n, (xmlChar *)propname)) == NULL)
   110 	if ((str = xmlGetProp(n, (xmlChar *)propname)) == NULL)
   108 		return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
   111 		return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
   109 	*value = strtoull((char *)str, (char **)&estr, 10);
   112 	*value = strtoull((char *)str, (char **)&estr, 10);
   110 	if (estr == str) {
   113 	if (estr == str) {
   111 		/* no conversion was done */
   114 		/* no conversion was done */
   120 xmlattr_to_fmri(topo_mod_t *mp,
   123 xmlattr_to_fmri(topo_mod_t *mp,
   121     xmlNodePtr xn, const char *propname, nvlist_t **rnvl)
   124     xmlNodePtr xn, const char *propname, nvlist_t **rnvl)
   122 {
   125 {
   123 	xmlChar *str;
   126 	xmlChar *str;
   124 
   127 
   125 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "attribute to int\n");
   128 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xmlattr_to_fmri(propname=%s)\n",
       
   129 	    propname);
   126 	if ((str = xmlGetProp(xn, (xmlChar *)propname)) == NULL)
   130 	if ((str = xmlGetProp(xn, (xmlChar *)propname)) == NULL)
   127 		return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
   131 		return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
   128 	if (topo_mod_str2nvl(mp, (const char *)str, rnvl) < 0) {
   132 	if (topo_mod_str2nvl(mp, (const char *)str, rnvl) < 0) {
   129 		xmlFree(str);
   133 		xmlFree(str);
   130 		return (-1);
   134 		return (-1);
   174 	int rv;
   178 	int rv;
   175 	uint64_t ui;
   179 	uint64_t ui;
   176 	nvlist_t *fmri;
   180 	nvlist_t *fmri;
   177 	xmlChar *str;
   181 	xmlChar *str;
   178 
   182 
   179 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xlate_common\n");
   183 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xlate_common (name=%s)\n",
       
   184 	    name);
   180 	switch (ptype) {
   185 	switch (ptype) {
   181 	case TOPO_TYPE_INT32:
   186 	case TOPO_TYPE_INT32:
   182 		if (xmlattr_to_int(mp, xn, Value, &ui) < 0)
   187 		if (xmlattr_to_int(mp, xn, Value, &ui) < 0)
   183 			return (-1);
   188 			return (-1);
   184 		rv = nvlist_add_int32(nvl, name, (int32_t)ui);
   189 		rv = nvlist_add_int32(nvl, name, (int32_t)ui);
   327 	int32_t i32;
   332 	int32_t i32;
   328 	int64_t i64;
   333 	int64_t i64;
   329 	char *str;
   334 	char *str;
   330 	int err, e;
   335 	int err, e;
   331 
   336 
   332 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "prop_create(gnm = %s, "
   337 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "prop_create(pgrp = %s, "
   333 	    "pnm = %s)\n", gnm, pnm);
   338 	    "prop = %s)\n", gnm, pnm);
   334 	switch (ptype) {
   339 	switch (ptype) {
   335 	case TOPO_TYPE_INT32:
   340 	case TOPO_TYPE_INT32:
   336 		e = nvlist_lookup_int32(pfmri, INV_PVAL, &i32);
   341 		e = nvlist_lookup_int32(pfmri, INV_PVAL, &i32);
   337 		break;
   342 		break;
   338 	case TOPO_TYPE_UINT32:
   343 	case TOPO_TYPE_UINT32:
   402 	int32_t i32;
   407 	int32_t i32;
   403 	int flag;
   408 	int flag;
   404 	int pn;
   409 	int pn;
   405 	int e;
   410 	int e;
   406 
   411 
   407 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "props_create(gnm = %s)\n", gnm);
   412 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "props_create(pgrp = %s)\n",
       
   413 	    gnm);
   408 	for (pn = 0; pn < nprops; pn++) {
   414 	for (pn = 0; pn < nprops; pn++) {
   409 		e = nvlist_lookup_string(props[pn], INV_PNAME, &pnm);
   415 		e = nvlist_lookup_string(props[pn], INV_PNAME, &pnm);
   410 		if (e != 0) {
   416 		if (e != 0) {
   411 			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
   417 			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
   412 			    "props create lookup (%s) failure: %s",
   418 			    "props create lookup (%s) failure: %s",
   447 	uint32_t rnprops, nprops;
   453 	uint32_t rnprops, nprops;
   448 	uint32_t gv;
   454 	uint32_t gv;
   449 	int pg;
   455 	int pg;
   450 	int e;
   456 	int e;
   451 
   457 
   452 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroups_create\n");
   458 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroups_create: %s=%d\n",
       
   459 	    topo_node_name(ptn), topo_node_instance(ptn));
   453 	for (pg = 0; pg < pad->tpad_pgcnt; pg++) {
   460 	for (pg = 0; pg < pad->tpad_pgcnt; pg++) {
   454 		e = nvlist_lookup_string(pad->tpad_pgs[pg],
   461 		e = nvlist_lookup_string(pad->tpad_pgs[pg],
   455 		    INV_PGRP_NAME, &gnm);
   462 		    INV_PGRP_NAME, &gnm);
   456 		if (e != 0) {
   463 		if (e != 0) {
   457 			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
   464 			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
   599 {
   606 {
   600 	nvlist_t *arg_nvl = NULL;
   607 	nvlist_t *arg_nvl = NULL;
   601 	xmlNodePtr cn;
   608 	xmlNodePtr cn;
   602 	xmlChar *meth_name = NULL, *prop_name = NULL;
   609 	xmlChar *meth_name = NULL, *prop_name = NULL;
   603 	xmlChar *arg_name = NULL;
   610 	xmlChar *arg_name = NULL;
   604 	uint64_t meth_ver;
   611 	uint64_t meth_ver, is_mutable = 0;
   605 	topo_type_t prop_type;
   612 	topo_type_t prop_type;
   606 	struct propmeth_data meth;
   613 	struct propmeth_data meth;
   607 	int ret = 0;
   614 	int ret = 0, err;
   608 	topo_type_t ptype;
   615 	topo_type_t ptype;
   609 	tnode_t *tmp;
   616 	tnode_t *tmp;
   610 
   617 
   611 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pmeth_record\n");
   618 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pmeth_record: %s=%d "
       
   619 	    "(pgrp=%s)\n", topo_node_name(tn), topo_node_instance(tn), pg_name);
   612 
   620 
   613 	/*
   621 	/*
   614 	 * Get propmethod attribute values
   622 	 * Get propmethod attribute values
   615 	 */
   623 	 */
   616 	if ((meth_name = xmlGetProp(xn, (xmlChar *)Name)) == NULL) {
   624 	if ((meth_name = xmlGetProp(xn, (xmlChar *)Name)) == NULL) {
   622 		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
   630 		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
   623 		    "propmethod element lacks version attribute\n");
   631 		    "propmethod element lacks version attribute\n");
   624 		ret = topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
   632 		ret = topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
   625 		goto pmr_done;
   633 		goto pmr_done;
   626 	}
   634 	}
       
   635 	/*
       
   636 	 * The "mutable" attribute is optional.  If not specified we default to
       
   637 	 * false (0)
       
   638 	 */
       
   639 	(void) xmlattr_to_int(mp, xn, Mutable, &is_mutable);
       
   640 
   627 	if ((prop_name = xmlGetProp(xn, (xmlChar *)Propname)) == NULL) {
   641 	if ((prop_name = xmlGetProp(xn, (xmlChar *)Propname)) == NULL) {
   628 		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
   642 		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
   629 		    "propmethod element lacks propname attribute\n");
   643 		    "propmethod element lacks propname attribute\n");
   630 		ret = topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
   644 		ret = topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
   631 		goto pmr_done;
   645 		goto pmr_done;
   700 	 * Otherwise, if the propgroup element is under a node element
   714 	 * Otherwise, if the propgroup element is under a node element
   701 	 * then we'll simply register the method for this node.
   715 	 * then we'll simply register the method for this node.
   702 	 */
   716 	 */
   703 	if (strcmp(ppgrp_name, Range) == 0) {
   717 	if (strcmp(ppgrp_name, Range) == 0) {
   704 		for (tmp = tn; tmp != NULL; tmp = topo_child_next(NULL, tmp)) {
   718 		for (tmp = tn; tmp != NULL; tmp = topo_child_next(NULL, tmp)) {
   705 			if (strcmp(rname, topo_node_name(tmp)) == 0)
   719 			if (strcmp(rname, topo_node_name(tmp)) == 0) {
   706 				if (register_method(mp, tmp, &meth) != 0) {
   720 				if (register_method(mp, tmp, &meth) != 0) {
   707 					ret = topo_mod_seterrno(mp,
   721 					ret = topo_mod_seterrno(mp,
   708 					    ETOPO_PRSR_REGMETH);
   722 					    ETOPO_PRSR_REGMETH);
   709 					goto pmr_done;
   723 					goto pmr_done;
   710 				}
   724 				}
       
   725 				if (is_mutable) {
       
   726 					if (topo_prop_setmutable(tmp,
       
   727 					    meth.pg_name, meth.prop_name, &err)
       
   728 					    != 0) {
       
   729 						ret = topo_mod_seterrno(mp,
       
   730 						    ETOPO_PRSR_REGMETH);
       
   731 						goto pmr_done;
       
   732 					}
       
   733 				}
       
   734 			}
   711 		}
   735 		}
   712 	} else {
   736 	} else {
   713 		if (register_method(mp, tn, &meth) != 0) {
   737 		if (register_method(mp, tn, &meth) != 0) {
   714 			ret = topo_mod_seterrno(mp, ETOPO_PRSR_REGMETH);
   738 			ret = topo_mod_seterrno(mp, ETOPO_PRSR_REGMETH);
   715 			goto pmr_done;
   739 			goto pmr_done;
       
   740 		}
       
   741 		if (is_mutable) {
       
   742 			if (topo_prop_setmutable(tn, meth.pg_name,
       
   743 			    meth.prop_name, &err) != 0) {
       
   744 				ret = topo_mod_seterrno(mp,
       
   745 				    ETOPO_PRSR_REGMETH);
       
   746 				goto pmr_done;
       
   747 			}
   716 		}
   748 		}
   717 	}
   749 	}
   718 
   750 
   719 pmr_done:
   751 pmr_done:
   720 	if (meth_name)
   752 	if (meth_name)
   876  */
   908  */
   877 static int
   909 static int
   878 pad_process(topo_mod_t *mp, tf_rdata_t *rd, xmlNodePtr pxn, tnode_t *ptn,
   910 pad_process(topo_mod_t *mp, tf_rdata_t *rd, xmlNodePtr pxn, tnode_t *ptn,
   879     tf_pad_t **rpad)
   911     tf_pad_t **rpad)
   880 {
   912 {
   881 	xmlNodePtr cn, gcn, psn, ecn;
   913 	xmlNodePtr cn, gcn, psn, ecn, target;
   882 	xmlNodePtr def_set = NULL;
   914 	xmlNodePtr def_set = NULL;
       
   915 	tnode_t *ct;
   883 	tf_pad_t *new = *rpad;
   916 	tf_pad_t *new = *rpad;
   884 	tf_rdata_t tmp_rd;
   917 	tf_rdata_t tmp_rd;
   885 	int pgcnt = 0;
   918 	int pgcnt = 0;
   886 	int dcnt = 0;
   919 	int dcnt = 0;
   887 	int ecnt = 0;
   920 	int ecnt = 0;
  1006 			if (new->tpad_pgs == NULL) {
  1039 			if (new->tpad_pgs == NULL) {
  1007 				tf_pad_free(mp, new);
  1040 				tf_pad_free(mp, new);
  1008 				return (-1);
  1041 				return (-1);
  1009 			}
  1042 			}
  1010 
  1043 
  1011 			if (joined_set) {
  1044 			/*
  1012 				/*
  1045 			 * If the property groups are contained within a set
  1013 				 * If the property groups are contained within a
  1046 			 * then they will be one level lower in the XML tree.
  1014 				 * set then they will be one level lower in
  1047 			 */
  1015 				 * the XML tree.
  1048 			if (joined_set)
  1016 				 */
  1049 				target = psn;
  1017 				if (pgroups_record(mp, psn, ptn, rd->rd_name,
  1050 			else
  1018 				    new, (const char *)pxn->name) < 0) {
  1051 				target = pxn;
  1019 					tf_pad_free(mp, new);
  1052 
       
  1053 			/*
       
  1054 			 * If there is no "node" element under the "range"
       
  1055 			 * element, then we need to attach the facility node to
       
  1056 			 * each node in this range.
       
  1057 			 *
       
  1058 			 * Otherwise we only attach it to the current node
       
  1059 			 */
       
  1060 			if (!rd->contains_node_ele) {
       
  1061 				for (ct = topo_child_first(rd->rd_pn);
       
  1062 				    ct != NULL;
       
  1063 				    ct = topo_child_next(rd->rd_pn, ct)) {
       
  1064 
       
  1065 					if (strcmp(topo_node_name(ct),
       
  1066 					    rd->rd_name) != 0)
       
  1067 						continue;
       
  1068 
       
  1069 					if (fac_enum_process(mp, target,
       
  1070 					    ct) < 0)
       
  1071 						return (-1);
       
  1072 
       
  1073 					if (fac_process(mp, target, rd, ct) < 0)
       
  1074 						return (-1);
       
  1075 				}
       
  1076 			} else
       
  1077 				if (fac_enum_process(mp, target, ptn) < 0)
  1020 					return (-1);
  1078 					return (-1);
  1021 				}
  1079 				if (fac_process(mp, target, rd, ptn) < 0)
  1022 			} else {
       
  1023 				if (pgroups_record(mp, pxn, ptn, rd->rd_name,
       
  1024 				    new, (const char *)pxn->name) < 0) {
       
  1025 					tf_pad_free(mp, new);
       
  1026 					return (-1);
  1080 					return (-1);
  1027 				}
  1081 
       
  1082 			if (pgroups_record(mp, target, ptn, rd->rd_name,
       
  1083 			    new, (const char *)pxn->name) < 0) {
       
  1084 				tf_pad_free(mp, new);
       
  1085 				return (-1);
  1028 			}
  1086 			}
  1029 		}
  1087 		}
  1030 		*rpad = new;
  1088 		*rpad = new;
  1031 	}
  1089 	}
  1032 
  1090 
  1039 			return (-1);
  1097 			return (-1);
  1040 
  1098 
  1041 	return (0);
  1099 	return (0);
  1042 }
  1100 }
  1043 
  1101 
       
  1102 
       
  1103 static int
       
  1104 fac_enum_process(topo_mod_t *mp, xmlNodePtr pn, tnode_t *ptn)
       
  1105 {
       
  1106 	xmlNodePtr cn;
       
  1107 	xmlChar *fprov = NULL;
       
  1108 	int rv = 0;
       
  1109 
       
  1110 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
       
  1111 	    "fac_enum_process() called for %s=%d\n", topo_node_name(ptn),
       
  1112 	    topo_node_instance(ptn));
       
  1113 
       
  1114 	for (cn = pn->xmlChildrenNode; cn != NULL; cn = cn->next) {
       
  1115 
       
  1116 		if (xmlStrcmp(cn->name, (xmlChar *)"fac-enum") != 0)
       
  1117 			continue;
       
  1118 
       
  1119 		if ((fprov = xmlGetProp(cn, (xmlChar *)Provider)) == NULL)
       
  1120 			goto fenumdone;
       
  1121 
       
  1122 		if (xmlStrcmp(fprov, (xmlChar *)"fac_prov_ipmi") != 0) {
       
  1123 			topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
       
  1124 			    "Invalid provider specified: %s\n", fprov);
       
  1125 			goto fenumdone;
       
  1126 		}
       
  1127 
       
  1128 		/*
       
  1129 		 * Invoke enum entry point in fac provider which will cause the
       
  1130 		 * facility enumeration node method to be registered.
       
  1131 		 */
       
  1132 		if (fac_enum_run(mp, ptn, (const char *)fprov) != 0) {
       
  1133 			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
       
  1134 			    "fac_enum_process: enum entry point failed!\n");
       
  1135 			goto fenumdone;
       
  1136 		}
       
  1137 		xmlFree(fprov);
       
  1138 	}
       
  1139 	return (0);
       
  1140 fenumdone:
       
  1141 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "fac-enum processing failed\n");
       
  1142 
       
  1143 	if (fprov != NULL)
       
  1144 		xmlFree(fprov);
       
  1145 
       
  1146 	return (rv);
       
  1147 }
       
  1148 
       
  1149 
       
  1150 static int
       
  1151 fac_process(topo_mod_t *mp, xmlNodePtr pn, tf_rdata_t *rd, tnode_t *ptn)
       
  1152 {
       
  1153 	xmlNodePtr cn;
       
  1154 	xmlChar *fname = NULL, *ftype = NULL, *provider = NULL;
       
  1155 	tnode_t *ntn = NULL;
       
  1156 	tf_idata_t *newi;
       
  1157 	int err;
       
  1158 	topo_pgroup_info_t pgi;
       
  1159 
       
  1160 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
       
  1161 	    "fac_process() called\n");
       
  1162 
       
  1163 	for (cn = pn->xmlChildrenNode; cn != NULL; cn = cn->next) {
       
  1164 
       
  1165 		if (xmlStrcmp(cn->name, (xmlChar *)Facility) != 0)
       
  1166 			continue;
       
  1167 
       
  1168 		topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
       
  1169 		    "facility processing\n");
       
  1170 
       
  1171 		if ((fname = xmlGetProp(cn, (xmlChar *)Name)) == NULL)
       
  1172 			goto facdone;
       
  1173 
       
  1174 		if ((ftype = xmlGetProp(cn, (xmlChar *)Type)) == NULL)
       
  1175 			goto facdone;
       
  1176 
       
  1177 		if ((provider = xmlGetProp(cn, (xmlChar *)Provider)) == NULL)
       
  1178 			goto facdone;
       
  1179 
       
  1180 		if (xmlStrcmp(ftype, (xmlChar *)Sensor) != 0 &&
       
  1181 		    xmlStrcmp(ftype, (xmlChar *)Indicator) != 0)
       
  1182 			goto facdone;
       
  1183 
       
  1184 		if (xmlStrcmp(provider, (xmlChar *)"fac_prov_ipmi") != 0) {
       
  1185 			topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "fac_process: "
       
  1186 			    "Invalid provider attr value: %s\n", provider);
       
  1187 			goto facdone;
       
  1188 		}
       
  1189 
       
  1190 		if ((ntn = topo_node_facbind(mp, ptn, (char *)fname,
       
  1191 		    (char *)ftype)) == NULL)
       
  1192 			goto facdone;
       
  1193 
       
  1194 		pgi.tpi_name = TOPO_PGROUP_FACILITY;
       
  1195 		pgi.tpi_namestab = TOPO_STABILITY_PRIVATE;
       
  1196 		pgi.tpi_datastab = TOPO_STABILITY_PRIVATE;
       
  1197 		pgi.tpi_version = 1;
       
  1198 		if (topo_pgroup_create(ntn, &pgi, &err) != 0) {
       
  1199 			if (err != ETOPO_PROP_DEFD) {
       
  1200 				topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
       
  1201 				    "pgroups create failure: %s\n",
       
  1202 				    topo_strerror(err));
       
  1203 				return (-1);
       
  1204 			}
       
  1205 		}
       
  1206 		/*
       
  1207 		 * Invoke enum entry point in fac_prov_ipmi module, which will
       
  1208 		 * cause the provider methods to be registered on this node
       
  1209 		 */
       
  1210 		if (fac_enum_run(mp, ntn, (const char *)provider) != 0) {
       
  1211 			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "fac_process: "
       
  1212 			    "enum entry point failed for provider %s!\n",
       
  1213 			    provider);
       
  1214 			goto facdone;
       
  1215 		}
       
  1216 
       
  1217 		if ((newi = tf_idata_new(mp, 0, ntn)) == NULL)
       
  1218 			goto facdone;
       
  1219 
       
  1220 		if (tf_idata_insert(&rd->rd_instances, newi) < 0)
       
  1221 			goto facdone;
       
  1222 
       
  1223 		if (pad_process(mp, rd, cn, ntn, &newi->ti_pad) < 0)
       
  1224 			goto facdone;
       
  1225 
       
  1226 		topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "done with "
       
  1227 		    "facility %s=%s.\n", ftype, fname);
       
  1228 
       
  1229 		xmlFree(ftype);
       
  1230 		xmlFree(fname);
       
  1231 		xmlFree(provider);
       
  1232 	}
       
  1233 
       
  1234 	return (0);
       
  1235 
       
  1236 facdone:
       
  1237 	topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "facility processing failed\n");
       
  1238 
       
  1239 	if (ftype != NULL)
       
  1240 		xmlFree(ftype);
       
  1241 	if (fname != NULL)
       
  1242 		xmlFree(fname);
       
  1243 	if (provider != NULL)
       
  1244 		xmlFree(provider);
       
  1245 	if (ntn != NULL)
       
  1246 		topo_node_unbind(ntn);
       
  1247 
       
  1248 	return (0);
       
  1249 }
  1044 
  1250 
  1045 static int
  1251 static int
  1046 node_process(topo_mod_t *mp, xmlNodePtr nn, tf_rdata_t *rd)
  1252 node_process(topo_mod_t *mp, xmlNodePtr nn, tf_rdata_t *rd)
  1047 {
  1253 {
  1048 	xmlChar *str;
  1254 	xmlChar *str;
  1054 	int s = 0;
  1260 	int s = 0;
  1055 
  1261 
  1056 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
  1262 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
  1057 	    "node_process %s\n", rd->rd_name);
  1263 	    "node_process %s\n", rd->rd_name);
  1058 
  1264 
       
  1265 	rd->contains_node_ele = 1;
  1059 	if (xmlattr_to_int(mp, nn, Instance, &ui) < 0)
  1266 	if (xmlattr_to_int(mp, nn, Instance, &ui) < 0)
  1060 		goto nodedone;
  1267 		goto nodedone;
  1061 	inst = (topo_instance_t)ui;
  1268 	inst = (topo_instance_t)ui;
  1062 
  1269 
  1063 	if ((str = xmlGetProp(nn, (xmlChar *)Static)) != NULL) {
  1270 	if ((str = xmlGetProp(nn, (xmlChar *)Static)) != NULL) {
  1095 		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
  1302 		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
  1096 		    "node_process: tf_idata_insert failed.\n");
  1303 		    "node_process: tf_idata_insert failed.\n");
  1097 		goto nodedone;
  1304 		goto nodedone;
  1098 	}
  1305 	}
  1099 	if (pad_process(mp, rd, nn, ntn, &newi->ti_pad) < 0)
  1306 	if (pad_process(mp, rd, nn, ntn, &newi->ti_pad) < 0)
       
  1307 		goto nodedone;
       
  1308 	if (fac_process(mp, nn, rd, ntn) < 0)
  1100 		goto nodedone;
  1309 		goto nodedone;
  1101 	rv = 0;
  1310 	rv = 0;
  1102 nodedone:
  1311 nodedone:
  1103 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "done with node %s.\n",
  1312 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "done with node %s.\n",
  1104 	    rd->rd_name);
  1313 	    rd->rd_name);
  1189 		return (topo_mod_seterrno(mp, EMOD_PARTIAL_ENUM));
  1398 		return (topo_mod_seterrno(mp, EMOD_PARTIAL_ENUM));
  1190 	}
  1399 	}
  1191 	return (e);
  1400 	return (e);
  1192 }
  1401 }
  1193 
  1402 
       
  1403 static int
       
  1404 fac_enum_run(topo_mod_t *mp, tnode_t *node, const char *name)
       
  1405 {
       
  1406 	topo_hdl_t *thp = mp->tm_hdl;
       
  1407 	topo_mod_t *fmod;
       
  1408 	int e = -1;
       
  1409 
       
  1410 	topo_dprintf(thp, TOPO_DBG_XML, "fac_enum_run\n");
       
  1411 	/*
       
  1412 	 * Check if the enumerator module is already loaded.
       
  1413 	 * Module loading is single-threaded at this point so there's
       
  1414 	 * no need to worry about the module going away or bumping the
       
  1415 	 * ref count.
       
  1416 	 */
       
  1417 	if ((fmod = topo_mod_lookup(thp, name, 0)) == NULL) {
       
  1418 		if ((fmod = topo_mod_load(mp, name, TOPO_VERSION)) == NULL) {
       
  1419 			topo_dprintf(thp, TOPO_DBG_ERR,
       
  1420 			    "fac_enum_run: mod_load of %s failed: %s.\n",
       
  1421 			    name, topo_strerror(topo_mod_errno(mp)));
       
  1422 			(void) topo_hdl_seterrno(thp, topo_mod_errno(mp));
       
  1423 			return (e);
       
  1424 		}
       
  1425 	}
       
  1426 	/*
       
  1427 	 * We're live, so let's enumerate.
       
  1428 	 */
       
  1429 	topo_dprintf(thp, TOPO_DBG_XML, "fac enumerate request. (%s)\n", name);
       
  1430 	e = topo_mod_enumerate(fmod, node, name, name, 0, 0, NULL);
       
  1431 	topo_dprintf(thp, TOPO_DBG_XML, "back from enumeration. %d\n", e);
       
  1432 	if (e != 0) {
       
  1433 		topo_dprintf(thp, TOPO_DBG_ERR,
       
  1434 		    "Facility provider enumeration failed (%s)\n",
       
  1435 		    topo_strerror(topo_mod_errno(mp)));
       
  1436 		(void) topo_hdl_seterrno(thp, EMOD_PARTIAL_ENUM);
       
  1437 		return (topo_mod_seterrno(mp, EMOD_PARTIAL_ENUM));
       
  1438 	}
       
  1439 	return (e);
       
  1440 }
  1194 
  1441 
  1195 int
  1442 int
  1196 decorate_nodes(topo_mod_t *mp, tf_rdata_t *rd, xmlNodePtr pxn, tnode_t *ptn,
  1443 decorate_nodes(topo_mod_t *mp, tf_rdata_t *rd, xmlNodePtr pxn, tnode_t *ptn,
  1197     tf_pad_t **rpad)
  1444     tf_pad_t **rpad)
  1198 {
  1445 {
  1229 
  1476 
  1230 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "topo_xml_range_process\n"
  1477 	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "topo_xml_range_process\n"
  1231 	    "process %s range beneath %s\n", rd->rd_name,
  1478 	    "process %s range beneath %s\n", rd->rd_name,
  1232 	    topo_node_name(rd->rd_pn));
  1479 	    topo_node_name(rd->rd_pn));
  1233 
  1480 
       
  1481 	rd->contains_node_ele = 0;
  1234 	e = topo_node_range_create(mp,
  1482 	e = topo_node_range_create(mp,
  1235 	    rd->rd_pn, rd->rd_name, rd->rd_min, rd->rd_max);
  1483 	    rd->rd_pn, rd->rd_name, rd->rd_min, rd->rd_max);
  1236 	if (e != 0 && topo_mod_errno(mp) != ETOPO_NODE_DUP) {
  1484 	if (e != 0 && topo_mod_errno(mp) != EMOD_NODE_DUP) {
  1237 		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
  1485 		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
  1238 		    "Range create failed due to %s.\n",
  1486 		    "Range create failed due to %s.\n",
  1239 		    topo_strerror(topo_mod_errno(mp)));
  1487 		    topo_strerror(topo_mod_errno(mp)));
  1240 		return (-1);
  1488 		return (-1);
  1241 	}
  1489 	}
  1324 				continue;
  1572 				continue;
  1325 			}
  1573 			}
  1326 			if (pad_process(mp, rd, rn, ct, &rd->rd_pad)
  1574 			if (pad_process(mp, rd, rn, ct, &rd->rd_pad)
  1327 			    < 0)
  1575 			    < 0)
  1328 				return (-1);
  1576 				return (-1);
       
  1577 
       
  1578 			if (fac_process(mp, rn, rd, ct) < 0)
       
  1579 				return (-1);
       
  1580 
  1329 			ct = topo_child_next(rd->rd_pn, ct);
  1581 			ct = topo_child_next(rd->rd_pn, ct);
  1330 			ccnt++;
  1582 			ccnt++;
  1331 		}
  1583 		}
  1332 	}
  1584 	}
  1333 
  1585