4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
27 #include <libxml/parser.h>
28 #include <libxml/xinclude.h>
29 #include <sys/fm/protocol.h>
36 #include <fm/libtopo.h>
40 #include <topo_file.h>
42 #include <topo_subr.h>
43 #include <topo_alloc.h>
44 #include <topo_parse.h>
45 #include <topo_error.h>
47 static tf_rdata_t
*topo_xml_walk(topo_mod_t
*, tf_info_t
*, xmlNodePtr
,
49 static tf_edata_t
*enum_attributes_process(topo_mod_t
*, xmlNodePtr
);
50 static int enum_run(topo_mod_t
*, tf_rdata_t
*);
51 static int fac_enum_run(topo_mod_t
*, tnode_t
*, const char *);
52 static int fac_process(topo_mod_t
*, xmlNodePtr
, tf_rdata_t
*, tnode_t
*);
53 static int fac_enum_process(topo_mod_t
*, xmlNodePtr
, tnode_t
*);
54 static int decorate_nodes(topo_mod_t
*, tf_rdata_t
*, xmlNodePtr
, tnode_t
*,
59 strarr_free(topo_mod_t
*mod
, char **arr
, uint_t nelems
)
63 for (i
= 0; i
< nelems
; i
++)
64 topo_mod_strfree(mod
, arr
[i
]);
65 topo_mod_free(mod
, arr
, (nelems
* sizeof (char *)));
69 xmlattr_to_stab(topo_mod_t
*mp
, xmlNodePtr n
, const char *stabname
,
76 /* If there is no Stability defined, we default to private */
77 *rs
= TOPO_STABILITY_PRIVATE
;
80 if ((str
= xmlGetProp(n
, (xmlChar
*)stabname
)) == NULL
) {
81 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
82 "attribute to stability:\n");
83 return (topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
));
86 if (xmlStrcmp(str
, (xmlChar
*)Internal
) == 0) {
87 *rs
= TOPO_STABILITY_INTERNAL
;
88 } else if (xmlStrcmp(str
, (xmlChar
*)Private
) == 0) {
89 *rs
= TOPO_STABILITY_PRIVATE
;
90 } else if (xmlStrcmp(str
, (xmlChar
*)Obsolete
) == 0) {
91 *rs
= TOPO_STABILITY_OBSOLETE
;
92 } else if (xmlStrcmp(str
, (xmlChar
*)External
) == 0) {
93 *rs
= TOPO_STABILITY_EXTERNAL
;
94 } else if (xmlStrcmp(str
, (xmlChar
*)Unstable
) == 0) {
95 *rs
= TOPO_STABILITY_UNSTABLE
;
96 } else if (xmlStrcmp(str
, (xmlChar
*)Evolving
) == 0) {
97 *rs
= TOPO_STABILITY_EVOLVING
;
98 } else if (xmlStrcmp(str
, (xmlChar
*)Stable
) == 0) {
99 *rs
= TOPO_STABILITY_STABLE
;
100 } else if (xmlStrcmp(str
, (xmlChar
*)Standard
) == 0) {
101 *rs
= TOPO_STABILITY_STANDARD
;
104 return (topo_mod_seterrno(mp
, ETOPO_PRSR_BADSTAB
));
111 xmlattr_to_int(topo_mod_t
*mp
,
112 xmlNodePtr n
, const char *propname
, uint64_t *value
)
117 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "xmlattr_to_int(propname=%s)\n",
119 if ((str
= xmlGetProp(n
, (xmlChar
*)propname
)) == NULL
)
120 return (topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
));
121 *value
= strtoull((char *)str
, (char **)&estr
, 10);
123 /* no conversion was done */
125 return (topo_mod_seterrno(mp
, ETOPO_PRSR_BADNUM
));
132 xmlattr_to_fmri(topo_mod_t
*mp
,
133 xmlNodePtr xn
, const char *propname
, nvlist_t
**rnvl
)
137 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "xmlattr_to_fmri(propname=%s)\n",
139 if ((str
= xmlGetProp(xn
, (xmlChar
*)propname
)) == NULL
)
140 return (topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
));
141 if (topo_mod_str2nvl(mp
, (const char *)str
, rnvl
) < 0) {
150 xmlattr_to_type(topo_mod_t
*mp
, xmlNodePtr xn
, xmlChar
*attr
)
154 if ((str
= xmlGetProp(xn
, (xmlChar
*)attr
)) == NULL
) {
155 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
, "%s attribute missing",
157 (void) topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
);
158 return (TOPO_TYPE_INVALID
);
160 if (xmlStrcmp(str
, (xmlChar
*)Int32
) == 0) {
161 rv
= TOPO_TYPE_INT32
;
162 } else if (xmlStrcmp(str
, (xmlChar
*)UInt32
) == 0) {
163 rv
= TOPO_TYPE_UINT32
;
164 } else if (xmlStrcmp(str
, (xmlChar
*)Int64
) == 0) {
165 rv
= TOPO_TYPE_INT64
;
166 } else if (xmlStrcmp(str
, (xmlChar
*)UInt64
) == 0) {
167 rv
= TOPO_TYPE_UINT64
;
168 } else if (xmlStrcmp(str
, (xmlChar
*)FMRI
) == 0) {
170 } else if (xmlStrcmp(str
, (xmlChar
*)String
) == 0) {
171 rv
= TOPO_TYPE_STRING
;
172 } else if (xmlStrcmp(str
, (xmlChar
*)Int32_Arr
) == 0) {
173 rv
= TOPO_TYPE_INT32_ARRAY
;
174 } else if (xmlStrcmp(str
, (xmlChar
*)UInt32_Arr
) == 0) {
175 rv
= TOPO_TYPE_UINT32_ARRAY
;
176 } else if (xmlStrcmp(str
, (xmlChar
*)Int64_Arr
) == 0) {
177 rv
= TOPO_TYPE_INT64_ARRAY
;
178 } else if (xmlStrcmp(str
, (xmlChar
*)UInt64_Arr
) == 0) {
179 rv
= TOPO_TYPE_UINT64_ARRAY
;
180 } else if (xmlStrcmp(str
, (xmlChar
*)String_Arr
) == 0) {
181 rv
= TOPO_TYPE_STRING_ARRAY
;
182 } else if (xmlStrcmp(str
, (xmlChar
*)FMRI_Arr
) == 0) {
183 rv
= TOPO_TYPE_FMRI_ARRAY
;
185 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
186 "Unrecognized type attribute value '%s'.\n", str
);
187 (void) topo_mod_seterrno(mp
, ETOPO_PRSR_BADTYPE
);
189 return (TOPO_TYPE_INVALID
);
196 xlate_common(topo_mod_t
*mp
, xmlNodePtr xn
, topo_type_t ptype
, nvlist_t
*nvl
,
201 uint_t i
= 0, nelems
= 0;
206 nvlist_t
**nvlarrbuf
;
209 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "xlate_common(name=%s)\n", name
);
211 case TOPO_TYPE_INT32
:
212 if (xmlattr_to_int(mp
, xn
, Value
, &ui
) < 0)
214 rv
= nvlist_add_int32(nvl
, name
, (int32_t)ui
);
216 case TOPO_TYPE_UINT32
:
217 if (xmlattr_to_int(mp
, xn
, Value
, &ui
) < 0)
219 rv
= nvlist_add_uint32(nvl
, name
, (uint32_t)ui
);
221 case TOPO_TYPE_INT64
:
222 if (xmlattr_to_int(mp
, xn
, Value
, &ui
) < 0)
224 rv
= nvlist_add_int64(nvl
, name
, (int64_t)ui
);
226 case TOPO_TYPE_UINT64
:
227 if (xmlattr_to_int(mp
, xn
, Value
, &ui
) < 0)
229 rv
= nvlist_add_uint64(nvl
, name
, ui
);
232 if (xmlattr_to_fmri(mp
, xn
, Value
, &fmri
) < 0)
234 rv
= nvlist_add_nvlist(nvl
, name
, fmri
);
237 case TOPO_TYPE_STRING
:
238 if ((str
= xmlGetProp(xn
, (xmlChar
*)Value
)) == NULL
)
240 rv
= nvlist_add_string(nvl
, name
, (char *)str
);
243 case TOPO_TYPE_INT32_ARRAY
:
244 case TOPO_TYPE_UINT32_ARRAY
:
245 case TOPO_TYPE_INT64_ARRAY
:
246 case TOPO_TYPE_UINT64_ARRAY
:
247 case TOPO_TYPE_STRING_ARRAY
:
248 case TOPO_TYPE_FMRI_ARRAY
:
249 for (cn
= xn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
)
250 if ((xmlStrcmp(cn
->name
, (xmlChar
*)Propitem
) == 0) ||
251 (xmlStrcmp(cn
->name
, (xmlChar
*)Argitem
) == 0))
255 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
, "No <propitem> "
256 "or <argitem> elements found for array val");
261 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
262 "Unrecognized type attribute (ptype = %d)\n", ptype
);
263 return (topo_mod_seterrno(mp
, ETOPO_PRSR_BADTYPE
));
267 case TOPO_TYPE_INT32_ARRAY
:
268 if ((arrbuf
= topo_mod_alloc(mp
, (nelems
* sizeof (int32_t))))
270 return (topo_mod_seterrno(mp
, ETOPO_NOMEM
));
271 for (cn
= xn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
272 if ((xmlStrcmp(cn
->name
, (xmlChar
*)Propitem
) == 0) ||
273 (xmlStrcmp(cn
->name
, (xmlChar
*)Argitem
) == 0)) {
275 if ((str
= xmlGetProp(cn
, (xmlChar
*)Value
))
279 ((int32_t *)arrbuf
)[i
++]
280 = atoi((const char *)str
);
285 rv
= nvlist_add_int32_array(nvl
, name
, (int32_t *)arrbuf
,
287 topo_mod_free(mp
, arrbuf
, (nelems
* sizeof (int32_t)));
289 case TOPO_TYPE_UINT32_ARRAY
:
290 if ((arrbuf
= topo_mod_alloc(mp
, (nelems
* sizeof (uint32_t))))
292 return (topo_mod_seterrno(mp
, ETOPO_NOMEM
));
293 for (cn
= xn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
294 if ((xmlStrcmp(cn
->name
, (xmlChar
*)Propitem
) == 0) ||
295 (xmlStrcmp(cn
->name
, (xmlChar
*)Argitem
) == 0)) {
297 if ((str
= xmlGetProp(cn
, (xmlChar
*)Value
))
301 ((uint32_t *)arrbuf
)[i
++]
302 = atoi((const char *)str
);
307 rv
= nvlist_add_uint32_array(nvl
, name
, (uint32_t *)arrbuf
,
309 topo_mod_free(mp
, arrbuf
, (nelems
* sizeof (uint32_t)));
311 case TOPO_TYPE_INT64_ARRAY
:
312 if ((arrbuf
= topo_mod_alloc(mp
, (nelems
* sizeof (int64_t))))
314 return (topo_mod_seterrno(mp
, ETOPO_NOMEM
));
315 for (cn
= xn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
316 if ((xmlStrcmp(cn
->name
, (xmlChar
*)Propitem
) == 0) ||
317 (xmlStrcmp(cn
->name
, (xmlChar
*)Argitem
) == 0)) {
319 if ((str
= xmlGetProp(cn
, (xmlChar
*)Value
))
323 ((int64_t *)arrbuf
)[i
++]
324 = atol((const char *)str
);
329 rv
= nvlist_add_int64_array(nvl
, name
, (int64_t *)arrbuf
,
331 topo_mod_free(mp
, arrbuf
, (nelems
* sizeof (int64_t)));
333 case TOPO_TYPE_UINT64_ARRAY
:
334 if ((arrbuf
= topo_mod_alloc(mp
, (nelems
* sizeof (uint64_t))))
336 return (topo_mod_seterrno(mp
, ETOPO_NOMEM
));
337 for (cn
= xn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
338 if ((xmlStrcmp(cn
->name
, (xmlChar
*)Propitem
) == 0) ||
339 (xmlStrcmp(cn
->name
, (xmlChar
*)Argitem
) == 0)) {
341 if ((str
= xmlGetProp(cn
, (xmlChar
*)Value
))
345 ((uint64_t *)arrbuf
)[i
++]
346 = atol((const char *)str
);
351 rv
= nvlist_add_uint64_array(nvl
, name
, arrbuf
,
353 topo_mod_free(mp
, arrbuf
, (nelems
* sizeof (uint64_t)));
355 case TOPO_TYPE_STRING_ARRAY
:
356 if ((strarrbuf
= topo_mod_alloc(mp
, (nelems
* sizeof (char *))))
358 return (topo_mod_seterrno(mp
, ETOPO_NOMEM
));
359 for (cn
= xn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
360 if ((xmlStrcmp(cn
->name
, (xmlChar
*)Propitem
) == 0) ||
361 (xmlStrcmp(cn
->name
, (xmlChar
*)Argitem
) == 0)) {
363 if ((str
= xmlGetProp(cn
, (xmlChar
*)Value
))
368 topo_mod_strdup(mp
, (const char *)str
);
373 rv
= nvlist_add_string_array(nvl
, name
, strarrbuf
, nelems
);
374 strarr_free(mp
, strarrbuf
, nelems
);
376 case TOPO_TYPE_FMRI_ARRAY
:
377 if ((nvlarrbuf
= topo_mod_alloc(mp
, (nelems
*
378 sizeof (nvlist_t
*)))) == NULL
)
379 return (topo_mod_seterrno(mp
, ETOPO_NOMEM
));
380 for (cn
= xn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
381 if ((xmlStrcmp(cn
->name
, (xmlChar
*)Propitem
) == 0) ||
382 (xmlStrcmp(cn
->name
, (xmlChar
*)Argitem
) == 0)) {
384 if ((str
= xmlGetProp(cn
, (xmlChar
*)Value
))
388 if (topo_mod_str2nvl(mp
, (const char *)str
,
389 &(nvlarrbuf
[i
++])) < 0) {
397 rv
= nvlist_add_nvlist_array(nvl
, name
, nvlarrbuf
,
399 topo_mod_free(mp
, nvlarrbuf
, (nelems
* sizeof (nvlist_t
*)));
404 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
405 "Nvlist construction failed.\n");
406 return (topo_mod_seterrno(mp
, ETOPO_NOMEM
));
412 xmlprop_xlate(topo_mod_t
*mp
, xmlNodePtr xn
, nvlist_t
*nvl
)
417 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "xmlprop_xlate\n");
418 if ((str
= xmlGetProp(xn
, (xmlChar
*)Immutable
)) != NULL
) {
419 if (xmlStrcmp(str
, (xmlChar
*)False
) == 0)
420 (void) nvlist_add_boolean_value(nvl
, INV_IMMUTE
,
423 (void) nvlist_add_boolean_value(nvl
, INV_IMMUTE
,
427 (void) nvlist_add_boolean_value(nvl
, INV_IMMUTE
, B_TRUE
);
430 if ((ptype
= xmlattr_to_type(mp
, xn
, (xmlChar
*)Type
))
431 == TOPO_TYPE_INVALID
)
434 if (nvlist_add_int32(nvl
, INV_PVALTYPE
, ptype
) != 0)
437 return (xlate_common(mp
, xn
, ptype
, nvl
, INV_PVAL
));
441 dependent_create(topo_mod_t
*mp
,
442 tf_info_t
*xinfo
, tf_pad_t
*pad
, xmlNodePtr dxn
, tnode_t
*ptn
)
444 tf_rdata_t
*rp
, *pp
, *np
;
448 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "dependent_create\n");
449 if ((grptype
= xmlGetProp(dxn
, (xmlChar
*)Grouping
)) == NULL
) {
450 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
451 "Dependents missing grouping attribute");
452 return (topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
));
456 if (xmlStrcmp(grptype
, (xmlChar
*)Siblings
) == 0) {
459 } else if (xmlStrcmp(grptype
, (xmlChar
*)Children
) == 0) {
460 rp
= pad
->tpad_child
;
462 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
463 "Dependents have bogus grouping attribute");
465 return (topo_mod_seterrno(mp
, ETOPO_PRSR_BADGRP
));
468 /* Add processed dependents to the tail of the list */
473 if ((np
= topo_xml_walk(mp
, xinfo
, dxn
, ptn
)) == NULL
) {
474 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
475 "error within dependent .xml topology: "
476 "%s\n", topo_strerror(topo_mod_errno(mp
)));
484 pad
->tpad_child
= np
;
489 dependents_create(topo_mod_t
*mp
,
490 tf_info_t
*xinfo
, tf_pad_t
*pad
, xmlNodePtr pxn
, tnode_t
*ptn
)
494 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "dependents_create\n");
495 for (cn
= pxn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
496 if (xmlStrcmp(cn
->name
, (xmlChar
*)Dependents
) == 0) {
497 if (dependent_create(mp
, xinfo
, pad
, cn
, ptn
) < 0)
505 prop_create(topo_mod_t
*mp
,
506 nvlist_t
*pfmri
, tnode_t
*ptn
, const char *gnm
, const char *pnm
,
507 topo_type_t ptype
, int flag
)
509 nvlist_t
*fmri
, **fmriarr
;
510 uint32_t ui32
, *ui32arr
;
511 uint64_t ui64
, *ui64arr
;
512 int32_t i32
, *i32arr
;
513 int64_t i64
, *i64arr
;
518 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "prop_create(pgrp = %s, "
519 "prop = %s)\n", gnm
, pnm
);
521 case TOPO_TYPE_INT32
:
522 e
= nvlist_lookup_int32(pfmri
, INV_PVAL
, &i32
);
524 case TOPO_TYPE_UINT32
:
525 e
= nvlist_lookup_uint32(pfmri
, INV_PVAL
, &ui32
);
527 case TOPO_TYPE_INT64
:
528 e
= nvlist_lookup_int64(pfmri
, INV_PVAL
, &i64
);
530 case TOPO_TYPE_UINT64
:
531 e
= nvlist_lookup_uint64(pfmri
, INV_PVAL
, &ui64
);
534 e
= nvlist_lookup_nvlist(pfmri
, INV_PVAL
, &fmri
);
536 case TOPO_TYPE_STRING
:
537 e
= nvlist_lookup_string(pfmri
, INV_PVAL
, &str
);
539 case TOPO_TYPE_INT32_ARRAY
:
540 e
= nvlist_lookup_int32_array(pfmri
, INV_PVAL
, &i32arr
, &nelem
);
542 case TOPO_TYPE_UINT32_ARRAY
:
543 e
= nvlist_lookup_uint32_array(pfmri
, INV_PVAL
, &ui32arr
,
546 case TOPO_TYPE_INT64_ARRAY
:
547 e
= nvlist_lookup_int64_array(pfmri
, INV_PVAL
, &i64arr
,
550 case TOPO_TYPE_UINT64_ARRAY
:
551 e
= nvlist_lookup_uint64_array(pfmri
, INV_PVAL
, &ui64arr
,
554 case TOPO_TYPE_STRING_ARRAY
:
555 e
= nvlist_lookup_string_array(pfmri
, INV_PVAL
, &strarr
,
558 case TOPO_TYPE_FMRI_ARRAY
:
559 e
= nvlist_lookup_nvlist_array(pfmri
, INV_PVAL
, &fmriarr
,
563 e
= ETOPO_PRSR_BADTYPE
;
566 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
567 "prop_create: prop value lookup failed.\n");
568 return (topo_mod_seterrno(mp
, e
));
571 case TOPO_TYPE_INT32
:
572 e
= topo_prop_set_int32(ptn
, gnm
, pnm
, flag
, i32
, &err
);
574 case TOPO_TYPE_UINT32
:
575 e
= topo_prop_set_uint32(ptn
, gnm
, pnm
, flag
, ui32
, &err
);
577 case TOPO_TYPE_INT64
:
578 e
= topo_prop_set_int64(ptn
, gnm
, pnm
, flag
, i64
, &err
);
580 case TOPO_TYPE_UINT64
:
581 e
= topo_prop_set_uint64(ptn
, gnm
, pnm
, flag
, ui64
, &err
);
584 e
= topo_prop_set_fmri(ptn
, gnm
, pnm
, flag
, fmri
, &err
);
586 case TOPO_TYPE_STRING
:
587 e
= topo_prop_set_string(ptn
, gnm
, pnm
, flag
, str
, &err
);
589 case TOPO_TYPE_INT32_ARRAY
:
590 e
= topo_prop_set_int32_array(ptn
, gnm
, pnm
, flag
, i32arr
,
593 case TOPO_TYPE_UINT32_ARRAY
:
594 e
= topo_prop_set_uint32_array(ptn
, gnm
, pnm
, flag
, ui32arr
,
597 case TOPO_TYPE_INT64_ARRAY
:
598 e
= topo_prop_set_int64_array(ptn
, gnm
, pnm
, flag
, i64arr
,
601 case TOPO_TYPE_UINT64_ARRAY
:
602 e
= topo_prop_set_uint64_array(ptn
, gnm
, pnm
, flag
, ui64arr
,
605 case TOPO_TYPE_STRING_ARRAY
:
606 e
= topo_prop_set_string_array(ptn
, gnm
, pnm
, flag
,
607 (const char **)strarr
, nelem
, &err
);
609 case TOPO_TYPE_FMRI_ARRAY
:
610 e
= topo_prop_set_fmri_array(ptn
, gnm
, pnm
, flag
,
611 (const nvlist_t
**)fmriarr
, nelem
, &err
);
614 if (e
!= 0 && err
!= ETOPO_PROP_DEFD
) {
617 * Some properties may have already been set
618 * in topo_node_bind() or topo_prop_inherit if we are
619 * enumerating from a static .xml file
621 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
, "prop set "
622 "failed %s/%s:%s\n", gnm
, pnm
, topo_strerror(err
));
623 return (topo_mod_seterrno(mp
, err
));
629 props_create(topo_mod_t
*mp
,
630 tnode_t
*ptn
, const char *gnm
, nvlist_t
**props
, int nprops
)
640 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "props_create(pgrp = %s)\n",
642 for (pn
= 0; pn
< nprops
; pn
++) {
643 e
= nvlist_lookup_string(props
[pn
], INV_PNAME
, &pnm
);
645 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
646 "props create lookup (%s) failure: %s",
647 INV_PNAME
, strerror(e
));
648 return (topo_mod_seterrno(mp
, ETOPO_PRSR_NVPROP
));
650 e
= nvlist_lookup_boolean_value(props
[pn
], INV_IMMUTE
, &pim
);
652 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
653 "props create lookup (%s) failure: %s",
654 INV_IMMUTE
, strerror(e
));
655 return (topo_mod_seterrno(mp
, ETOPO_PRSR_NVPROP
));
657 flag
= (pim
== B_TRUE
) ?
658 TOPO_PROP_IMMUTABLE
: TOPO_PROP_MUTABLE
;
660 e
= nvlist_lookup_int32(props
[pn
], INV_PVALTYPE
, &i32
);
662 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
663 "props create lookup (%s) failure: %s",
664 INV_PVALTYPE
, strerror(e
));
665 return (topo_mod_seterrno(mp
, ETOPO_PRSR_NVPROP
));
667 ptype
= (topo_type_t
)i32
;
668 if (prop_create(mp
, props
[pn
], ptn
, gnm
, pnm
, ptype
, flag
) < 0)
675 pgroups_create(topo_mod_t
*mp
, tf_pad_t
*pad
, tnode_t
*ptn
)
677 topo_pgroup_info_t pgi
;
680 char *nmstab
, *dstab
;
681 uint32_t rnprops
, nprops
;
686 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "pgroups_create: %s=%d\n",
687 topo_node_name(ptn
), topo_node_instance(ptn
));
688 for (pg
= 0; pg
< pad
->tpad_pgcnt
; pg
++) {
689 e
= nvlist_lookup_string(pad
->tpad_pgs
[pg
],
690 INV_PGRP_NAME
, &gnm
);
692 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
693 "pad lookup (%s) failed (%s).\n",
694 INV_PGRP_NAME
, strerror(errno
));
695 return (topo_mod_seterrno(mp
, ETOPO_PRSR_NVPROP
));
697 e
= nvlist_lookup_string(pad
->tpad_pgs
[pg
],
698 INV_PGRP_NMSTAB
, &nmstab
);
701 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
703 "failed.\n", INV_PGRP_NMSTAB
);
704 return (topo_mod_seterrno(mp
,
707 nmstab
= TOPO_STABSTR_PRIVATE
;
710 e
= nvlist_lookup_string(pad
->tpad_pgs
[pg
],
711 INV_PGRP_DSTAB
, &dstab
);
714 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
715 "pad lookup (%s) failed.\n",
717 return (topo_mod_seterrno(mp
,
720 dstab
= TOPO_STABSTR_PRIVATE
;
723 e
= nvlist_lookup_uint32(pad
->tpad_pgs
[pg
],
726 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
727 "pad lookup (%s) failed.\n",
729 return (topo_mod_seterrno(mp
, ETOPO_PRSR_NVPROP
));
732 pgi
.tpi_namestab
= topo_name2stability(nmstab
);
733 pgi
.tpi_datastab
= topo_name2stability(dstab
);
734 pgi
.tpi_version
= gv
;
735 if (topo_pgroup_create(ptn
, &pgi
, &e
) != 0) {
736 if (e
!= ETOPO_PROP_DEFD
) {
737 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
738 "pgroups create failure: %s\n",
743 e
= nvlist_lookup_uint32(pad
->tpad_pgs
[pg
],
744 INV_PGRP_NPROP
, &rnprops
);
746 * The number of properties could be zero if the property
747 * group only contains propmethod declarations
750 e
|= nvlist_lookup_nvlist_array(pad
->tpad_pgs
[pg
],
751 INV_PGRP_ALLPROPS
, &props
, &nprops
);
752 if (rnprops
!= nprops
) {
753 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
754 "recorded number of props %d does not "
755 "match number of props recorded %d.\n",
758 if (props_create(mp
, ptn
, gnm
, props
, nprops
) < 0)
766 pval_record(topo_mod_t
*mp
, xmlNodePtr xn
)
768 nvlist_t
*pnvl
= NULL
;
771 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "pval_record\n");
772 if ((pname
= xmlGetProp(xn
, (xmlChar
*)Name
)) == NULL
) {
773 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
774 "propval lacks a name\n");
775 (void) topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
);
778 if (topo_mod_nvalloc(mp
, &pnvl
, NV_UNIQUE_NAME
) < 0) {
782 if (nvlist_add_string(pnvl
, INV_PNAME
, (char *)pname
) < 0) {
788 /* FMXXX stability of the property name */
790 if (xmlprop_xlate(mp
, xn
, pnvl
) < 0) {
798 struct propmeth_data
{
800 const char *prop_name
;
801 topo_type_t prop_type
;
802 const char *meth_name
;
803 topo_version_t meth_ver
;
808 register_method(topo_mod_t
*mp
, tnode_t
*ptn
, struct propmeth_data
*meth
)
812 if (topo_prop_method_version_register(ptn
, meth
->pg_name
,
813 meth
->prop_name
, meth
->prop_type
, meth
->meth_name
, meth
->meth_ver
,
814 meth
->arg_nvl
, &err
) != 0) {
816 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
, "failed to register "
817 "propmethod %s for property \"%s\" in propgrp %s on node "
819 meth
->meth_name
, meth
->prop_name
, meth
->pg_name
,
820 topo_node_name(ptn
), topo_node_instance(ptn
),
824 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
825 "registered method %s on %s=%d\n",
826 meth
->meth_name
, topo_node_name(ptn
), topo_node_instance(ptn
));
832 pmeth_record(topo_mod_t
*mp
, const char *pg_name
, xmlNodePtr xn
, tnode_t
*tn
,
833 const char *rname
, const char *ppgrp_name
)
835 nvlist_t
*arg_nvl
= NULL
;
837 xmlChar
*meth_name
= NULL
, *prop_name
= NULL
;
838 xmlChar
*arg_name
= NULL
;
839 uint64_t meth_ver
, is_mutable
= 0, is_nonvolatile
= 0;
840 topo_type_t prop_type
;
841 struct propmeth_data meth
;
846 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "pmeth_record: %s=%d "
847 "(pgrp=%s)\n", topo_node_name(tn
), topo_node_instance(tn
), pg_name
);
850 * Get propmethod attribute values
852 if ((meth_name
= xmlGetProp(xn
, (xmlChar
*)Name
)) == NULL
) {
853 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
854 "propmethod element lacks a name attribute\n");
855 return (topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
));
857 if (xmlattr_to_int(mp
, xn
, Version
, &meth_ver
) < 0) {
858 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
859 "propmethod element lacks version attribute\n");
860 ret
= topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
);
864 * The "mutable" and "nonvoltile" attributes are optional. If not
865 * specified we default to false (0)
867 (void) xmlattr_to_int(mp
, xn
, Mutable
, &is_mutable
);
868 (void) xmlattr_to_int(mp
, xn
, Nonvolatile
, &is_nonvolatile
);
870 if ((prop_name
= xmlGetProp(xn
, (xmlChar
*)Propname
)) == NULL
) {
871 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
872 "propmethod element lacks propname attribute\n");
873 ret
= topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
);
876 if ((prop_type
= xmlattr_to_type(mp
, xn
, (xmlChar
*)Proptype
))
877 == TOPO_TYPE_INVALID
) {
878 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
879 "error decoding proptype attribute\n");
880 ret
= topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
);
885 * Allocate method argument nvlist
887 if (topo_mod_nvalloc(mp
, &arg_nvl
, NV_UNIQUE_NAME
) < 0) {
888 ret
= topo_mod_seterrno(mp
, ETOPO_NOMEM
);
893 * Iterate through the argval nodes and build the argval nvlist
895 for (cn
= xn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
896 if (xmlStrcmp(cn
->name
, (xmlChar
*)Argval
) == 0) {
897 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
898 "found argval element\n");
899 if ((arg_name
= xmlGetProp(cn
, (xmlChar
*)Name
))
901 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
902 "argval element lacks a name attribute\n");
903 ret
= topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
);
906 if ((ptype
= xmlattr_to_type(mp
, cn
, (xmlChar
*)Type
))
907 == TOPO_TYPE_INVALID
) {
908 ret
= topo_mod_seterrno(mp
, ETOPO_PRSR_BADTYPE
);
912 if (xlate_common(mp
, cn
, ptype
, arg_nvl
,
913 (const char *)arg_name
) != 0) {
914 ret
= topo_mod_seterrno(mp
, ETOPO_PRSR_BADTYPE
);
929 * Register the prop method for all of the nodes in our range
931 meth
.pg_name
= (const char *)pg_name
;
932 meth
.prop_name
= (const char *)prop_name
;
933 meth
.prop_type
= prop_type
;
934 meth
.meth_name
= (const char *)meth_name
;
935 meth
.meth_ver
= meth_ver
;
936 meth
.arg_nvl
= arg_nvl
;
939 * If the propgroup element is under a range element, we'll apply
940 * the method to all of the topo nodes at this level with the same
943 * Otherwise, if the propgroup element is under a node element
944 * then we'll simply register the method for this node.
946 if (strcmp(ppgrp_name
, Range
) == 0) {
947 for (tmp
= tn
; tmp
!= NULL
; tmp
= topo_child_next(NULL
, tmp
)) {
948 if (strcmp(rname
, topo_node_name(tmp
)) == 0) {
949 if (register_method(mp
, tmp
, &meth
) != 0) {
950 ret
= topo_mod_seterrno(mp
,
955 if (topo_prop_setmutable(tmp
,
956 meth
.pg_name
, meth
.prop_name
, &err
)
958 ret
= topo_mod_seterrno(mp
,
963 if (is_nonvolatile
) {
964 if (topo_prop_setnonvolatile(tmp
,
965 meth
.pg_name
, meth
.prop_name
, &err
)
967 ret
= topo_mod_seterrno(mp
,
975 if (register_method(mp
, tn
, &meth
) != 0) {
976 ret
= topo_mod_seterrno(mp
, ETOPO_PRSR_REGMETH
);
980 if (topo_prop_setmutable(tn
, meth
.pg_name
,
981 meth
.prop_name
, &err
) != 0) {
982 ret
= topo_mod_seterrno(mp
,
987 if (is_nonvolatile
) {
988 if (topo_prop_setnonvolatile(tn
, meth
.pg_name
,
989 meth
.prop_name
, &err
) != 0) {
990 ret
= topo_mod_seterrno(mp
,
1002 nvlist_free(arg_nvl
);
1008 pgroup_record(topo_mod_t
*mp
, xmlNodePtr pxn
, tnode_t
*tn
, const char *rname
,
1009 tf_pad_t
*rpad
, int pi
, const char *ppgrp_name
)
1011 topo_stability_t nmstab
, dstab
;
1015 nvlist_t
**apl
= NULL
;
1016 nvlist_t
*pgnvl
= NULL
;
1021 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "pgroup_record\n");
1022 if ((name
= xmlGetProp(pxn
, (xmlChar
*)Name
)) == NULL
) {
1023 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1024 "propgroup lacks a name\n");
1025 return (topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
));
1027 if (xmlattr_to_int(mp
, pxn
, Version
, &ver
) < 0) {
1028 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1029 "propgroup lacks a version\n");
1030 return (topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
));
1032 if (xmlattr_to_stab(mp
, pxn
, Namestab
, &nmstab
) < 0) {
1033 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1034 "propgroup lacks name-stability\n");
1035 return (topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
));
1037 if (xmlattr_to_stab(mp
, pxn
, Datastab
, &dstab
) < 0) {
1038 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1039 "propgroup lacks data-stability\n");
1040 return (topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
));
1043 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "pgroup %s\n", (char *)name
);
1044 for (cn
= pxn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
1045 if (xmlStrcmp(cn
->name
, (xmlChar
*)Propval
) == 0)
1049 if (topo_mod_nvalloc(mp
, &pgnvl
, NV_UNIQUE_NAME
) < 0) {
1051 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1052 "failed to allocate propgroup nvlist\n");
1053 return (topo_mod_seterrno(mp
, ETOPO_NOMEM
));
1056 e
= nvlist_add_string(pgnvl
, INV_PGRP_NAME
, (char *)name
);
1057 e
|= nvlist_add_uint32(pgnvl
, INV_PGRP_NMSTAB
, nmstab
);
1058 e
|= nvlist_add_uint32(pgnvl
, INV_PGRP_DSTAB
, dstab
);
1059 e
|= nvlist_add_uint32(pgnvl
, INV_PGRP_VER
, ver
);
1060 e
|= nvlist_add_uint32(pgnvl
, INV_PGRP_NPROP
, pcnt
);
1063 (apl
= topo_mod_zalloc(mp
, pcnt
* sizeof (nvlist_t
*)))
1067 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1068 "failed to allocate nvlist array for properties"
1070 return (topo_mod_seterrno(mp
, ETOPO_NOMEM
));
1072 for (cn
= pxn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
1073 if (xmlStrcmp(cn
->name
, (xmlChar
*)Propval
) == 0) {
1075 if ((apl
[ai
] = pval_record(mp
, cn
)) == NULL
)
1079 } else if (xmlStrcmp(cn
->name
, (xmlChar
*)Prop_meth
) == 0) {
1080 if (pmeth_record(mp
, (const char *)name
, cn
, tn
, rname
,
1088 e
|= nvlist_add_nvlist_array(pgnvl
, INV_PGRP_ALLPROPS
, apl
,
1090 for (ai
= 0; ai
< pcnt
; ai
++)
1091 nvlist_free(apl
[ai
]);
1092 topo_mod_free(mp
, apl
, pcnt
* sizeof (nvlist_t
*));
1098 rpad
->tpad_pgs
[pi
] = pgnvl
;
1103 pgroups_record(topo_mod_t
*mp
, xmlNodePtr pxn
, tnode_t
*tn
, const char *rname
,
1104 tf_pad_t
*rpad
, const char *ppgrp
)
1109 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "pgroups_record: pxn->name=%s\n",
1111 for (cn
= pxn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
1112 if (xmlStrcmp(cn
->name
, (xmlChar
*)Propgrp
) == 0) {
1113 if (pgroup_record(mp
, cn
, tn
, rname
, rpad
, pi
++, ppgrp
)
1122 * psn: pointer to a "set" XML node
1123 * key: string to search the set for
1125 * returns: 1, if the set contains key
1129 set_contains(topo_mod_t
*mp
, char *key
, char *set
)
1134 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "set_contains(key = %s, "
1135 "setlist = %s)\n", key
, set
);
1137 prod
= strtok((char *)set
, "|");
1138 if (prod
&& (strcmp(key
, prod
) == 0))
1141 while ((prod
= strtok(NULL
, "|")))
1142 if (strcmp(key
, prod
) == 0)
1150 * Process the property group and dependents xmlNode children of
1151 * parent xmlNode pxn.
1154 pad_process(topo_mod_t
*mp
, tf_rdata_t
*rd
, xmlNodePtr pxn
, tnode_t
*ptn
,
1157 xmlNodePtr cn
, gcn
, psn
, ecn
, target
;
1158 xmlNodePtr def_set
= NULL
;
1160 tf_pad_t
*new = *rpad
;
1165 int joined_set
= 0, inst
;
1169 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
1170 "pad_process beneath %s=%d\n", topo_node_name(ptn
),
1171 topo_node_instance(ptn
));
1173 for (cn
= pxn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
1174 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
1175 "cn->name is %s \n", (char *)cn
->name
);
1177 * We're iterating through the XML children looking for
1178 * four types of elements:
1179 * 1) dependents elements
1180 * 2) unconstrained pgroup elements
1181 * 3) pgroup elements constrained by set elements
1182 * 4) enum-method elements for the case that we want
1183 * to post-process a statically defined node
1185 if (xmlStrcmp(cn
->name
, (xmlChar
*)Dependents
) == 0)
1187 else if (xmlStrcmp(cn
->name
, (xmlChar
*)Propgrp
) == 0)
1189 else if (xmlStrcmp(cn
->name
, (xmlChar
*)Enum_meth
)
1193 } else if (xmlStrcmp(cn
->name
, (xmlChar
*)Set
) == 0) {
1196 set
= xmlGetProp(cn
, (xmlChar
*)Setlist
);
1198 if (mp
->tm_hdl
->th_product
)
1199 key
= mp
->tm_hdl
->th_product
;
1201 key
= mp
->tm_hdl
->th_platform
;
1204 * If it's the default set then we'll store
1205 * a pointer to it so that if none of the other
1206 * sets apply to our product we can fall
1209 if (strcmp((char *)set
, "default") == 0)
1211 else if (set_contains(mp
, key
, (char *)set
)) {
1214 for (gcn
= cn
->xmlChildrenNode
;
1215 gcn
!= NULL
; gcn
= gcn
->next
) {
1216 if (xmlStrcmp(gcn
->name
,
1217 (xmlChar
*)Propgrp
) == 0)
1225 * If we haven't found a set that contains our product AND
1226 * a default set exists, then we'll process it.
1228 if (!joined_set
&& def_set
) {
1229 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
1230 "Falling back to default set\n");
1233 for (gcn
= psn
->xmlChildrenNode
; gcn
!= NULL
;
1235 if (xmlStrcmp(gcn
->name
, (xmlChar
*)Propgrp
)
1240 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
1241 "pad_process: dcnt=%d, pgcnt=%d, ecnt=%d, joined_set=%d\n",
1242 dcnt
, pgcnt
, ecnt
, joined_set
);
1244 * If an enum-method element was found, AND we're a child of a
1245 * node element, then we invoke the enumerator so that it can do
1246 * post-processing of the node.
1248 if (ecnt
&& (strcmp((const char *)pxn
->name
, Node
) == 0)) {
1249 if ((tmp_rd
.rd_einfo
= enum_attributes_process(mp
, ecn
))
1253 tmp_rd
.rd_name
= rd
->rd_name
;
1254 tmp_rd
.rd_min
= rd
->rd_min
;
1255 tmp_rd
.rd_max
= rd
->rd_max
;
1257 if (enum_run(mp
, &tmp_rd
) < 0) {
1259 * Note the failure but continue on
1261 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1262 "pad_process: enumeration failed.\n");
1264 tf_edata_free(mp
, tmp_rd
.rd_einfo
);
1267 * Here we allocate an element in an intermediate data structure
1268 * which keeps track property groups and dependents of the range
1269 * currently being processed.
1271 * This structure is referenced in pgroups_record() to create
1272 * the actual property groups in the topo tree
1274 if ((new = tf_pad_new(mp
, pgcnt
, dcnt
)) == NULL
)
1279 topo_mod_zalloc(mp
, pgcnt
* sizeof (nvlist_t
*));
1280 if (new->tpad_pgs
== NULL
) {
1281 tf_pad_free(mp
, new);
1286 * If the property groups are contained within a set
1287 * then they will be one level lower in the XML tree.
1295 * If there is no "node" element under the "range"
1296 * element, then we need to attach the facility node to
1297 * each node in this range.
1299 * Otherwise we only attach it to the current node
1301 if (xmlStrcmp(target
->name
, (xmlChar
*)Range
) == 0 ||
1302 xmlStrcmp(target
->name
, (xmlChar
*)Set
) == 0) {
1303 for (ct
= topo_child_first(rd
->rd_pn
);
1305 ct
= topo_child_next(rd
->rd_pn
, ct
)) {
1307 if (strcmp(topo_node_name(ct
),
1311 inst
= topo_node_instance(ct
);
1312 if (inst
< rd
->rd_min
|| inst
> rd
->rd_max
)
1315 if (fac_enum_process(mp
, target
, ct
) < 0)
1318 if (fac_process(mp
, target
, rd
, ct
) < 0)
1322 if (fac_enum_process(mp
, target
, ptn
) < 0)
1324 if (fac_process(mp
, target
, rd
, ptn
) < 0)
1327 if (pgcnt
> 0 && pgroups_record(mp
, target
, ptn
, rd
->rd_name
,
1328 new, (const char *)pxn
->name
) < 0) {
1329 tf_pad_free(mp
, new);
1335 if (new->tpad_dcnt
> 0)
1336 if (dependents_create(mp
, rd
->rd_finfo
, new, pxn
, ptn
) < 0)
1339 if (new->tpad_pgcnt
> 0)
1340 if (pgroups_create(mp
, new, ptn
) < 0)
1348 fac_enum_process(topo_mod_t
*mp
, xmlNodePtr pn
, tnode_t
*ptn
)
1351 xmlChar
*fprov
= NULL
;
1354 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
1355 "fac_enum_process() called for %s=%d\n", topo_node_name(ptn
),
1356 topo_node_instance(ptn
));
1358 for (cn
= pn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
1360 if (xmlStrcmp(cn
->name
, (xmlChar
*)"fac-enum") != 0)
1363 if ((fprov
= xmlGetProp(cn
, (xmlChar
*)Provider
)) == NULL
)
1366 * Invoke enum entry point in facility provider which will
1367 * cause the facility enumeration node method to be
1370 if (fac_enum_run(mp
, ptn
, (const char *)fprov
) != 0) {
1371 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1372 "fac_enum_process: enum entry point failed!\n");
1379 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "fac-enum processing failed\n");
1389 fac_process(topo_mod_t
*mp
, xmlNodePtr pn
, tf_rdata_t
*rd
, tnode_t
*ptn
)
1392 xmlChar
*fname
= NULL
, *ftype
= NULL
, *provider
= NULL
;
1393 tnode_t
*ntn
= NULL
;
1396 topo_pgroup_info_t pgi
;
1398 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
1399 "fac_process() called for %s=%d\n", topo_node_name(ptn
),
1400 topo_node_instance(ptn
));
1402 for (cn
= pn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
1404 if (xmlStrcmp(cn
->name
, (xmlChar
*)Facility
) != 0)
1407 if ((fname
= xmlGetProp(cn
, (xmlChar
*)Name
)) == NULL
)
1410 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
1411 "processing facility node '%s'\n", fname
);
1413 if ((ftype
= xmlGetProp(cn
, (xmlChar
*)Type
)) == NULL
)
1416 if ((provider
= xmlGetProp(cn
, (xmlChar
*)Provider
)) == NULL
)
1419 if (xmlStrcmp(ftype
, (xmlChar
*)Sensor
) != 0 &&
1420 xmlStrcmp(ftype
, (xmlChar
*)Indicator
) != 0)
1423 if ((ntn
= topo_node_facbind(mp
, ptn
, (char *)fname
,
1424 (char *)ftype
)) == NULL
)
1427 pgi
.tpi_name
= TOPO_PGROUP_FACILITY
;
1428 pgi
.tpi_namestab
= TOPO_STABILITY_PRIVATE
;
1429 pgi
.tpi_datastab
= TOPO_STABILITY_PRIVATE
;
1430 pgi
.tpi_version
= 1;
1431 if (topo_pgroup_create(ntn
, &pgi
, &err
) != 0) {
1432 if (err
!= ETOPO_PROP_DEFD
) {
1433 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1434 "pgroups create failure: %s\n",
1435 topo_strerror(err
));
1440 * Invoke enum entry point in the facility provider module,
1441 * which will cause the provider methods to be registered on
1444 if (fac_enum_run(mp
, ntn
, (const char *)provider
) != 0) {
1445 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
, "fac_process: "
1446 "enum entry point failed for provider %s!\n",
1451 if ((newi
= tf_idata_new(mp
, 0, ntn
)) == NULL
)
1454 if (tf_idata_insert(&rd
->rd_instances
, newi
) < 0)
1457 if (pad_process(mp
, rd
, cn
, ntn
, &newi
->ti_pad
) < 0)
1460 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "done with "
1461 "facility %s=%s.\n", ftype
, fname
);
1471 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
, "facility processing failed\n");
1477 if (provider
!= NULL
)
1480 topo_node_unbind(ntn
);
1486 node_process(topo_mod_t
*mp
, xmlNodePtr nn
, tf_rdata_t
*rd
)
1489 topo_instance_t inst
;
1496 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
1497 "node_process %s\n", rd
->rd_name
);
1499 if (xmlattr_to_int(mp
, nn
, Instance
, &ui
) < 0)
1501 inst
= (topo_instance_t
)ui
;
1503 if ((str
= xmlGetProp(nn
, (xmlChar
*)Static
)) != NULL
) {
1504 if (xmlStrcmp(str
, (xmlChar
*)True
) == 0)
1510 if (topo_mod_enumerate(rd
->rd_mod
, rd
->rd_pn
,
1511 rd
->rd_finfo
->tf_scheme
, rd
->rd_name
, inst
, inst
,
1512 s
== 1 ? &s
: NULL
) < 0)
1515 ntn
= topo_node_lookup(rd
->rd_pn
, rd
->rd_name
, inst
);
1520 * If this is a static node declaration, we can
1521 * ignore the lookup failure and continue
1522 * processing. Otherwise, something
1523 * went wrong during enumeration
1529 if ((newi
= tf_idata_new(mp
, inst
, ntn
)) == NULL
) {
1530 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1531 "node_process: tf_idata_new failed.\n");
1534 if (tf_idata_insert(&rd
->rd_instances
, newi
) < 0) {
1535 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1536 "node_process: tf_idata_insert failed.\n");
1539 if (pad_process(mp
, rd
, nn
, ntn
, &newi
->ti_pad
) < 0)
1541 if (fac_process(mp
, nn
, rd
, ntn
) < 0)
1545 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "done with node %s.\n",
1551 enum_attributes_process(topo_mod_t
*mp
, xmlNodePtr en
)
1556 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "enum_attributes_process\n");
1557 if ((einfo
= topo_mod_zalloc(mp
, sizeof (tf_edata_t
))) == NULL
) {
1558 (void) topo_mod_seterrno(mp
, ETOPO_NOMEM
);
1561 einfo
->te_name
= (char *)xmlGetProp(en
, (xmlChar
*)Name
);
1562 if (einfo
->te_name
== NULL
) {
1563 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1564 "Enumerator name attribute missing.\n");
1565 (void) topo_mod_seterrno(mp
, ETOPO_PRSR_NOATTR
);
1570 * Check for recursive enumeration
1572 if (strcmp(einfo
->te_name
, mp
->tm_name
) == 0) {
1573 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1574 "Recursive enumeration detected for %s\n",
1576 (void) topo_mod_seterrno(mp
, ETOPO_ENUM_RECURS
);
1579 if (xmlattr_to_int(mp
, en
, Version
, &ui
) < 0)
1581 einfo
->te_vers
= (int)ui
;
1586 if (einfo
->te_name
!= NULL
)
1587 xmlFree(einfo
->te_name
);
1588 topo_mod_free(mp
, einfo
, sizeof (tf_edata_t
));
1593 enum_run(topo_mod_t
*mp
, tf_rdata_t
*rd
)
1595 topo_hdl_t
*thp
= mp
->tm_hdl
;
1598 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "enum_run\n");
1600 * Check if the enumerator module is already loaded.
1601 * Module loading is single-threaded at this point so there's
1602 * no need to worry about the module going away or bumping the
1605 if ((rd
->rd_mod
= topo_mod_lookup(thp
, rd
->rd_einfo
->te_name
,
1607 if ((rd
->rd_mod
= topo_mod_load(mp
, rd
->rd_einfo
->te_name
,
1608 rd
->rd_einfo
->te_vers
)) == NULL
) {
1609 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1610 "enum_run: mod_load of %s failed: %s.\n",
1611 rd
->rd_einfo
->te_name
,
1612 topo_strerror(topo_mod_errno(mp
)));
1613 (void) topo_hdl_seterrno(thp
, topo_mod_errno(mp
));
1618 * We're live, so let's enumerate.
1620 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "enumerate request. (%s)\n",
1621 rd
->rd_einfo
->te_name
);
1622 e
= topo_mod_enumerate(rd
->rd_mod
, rd
->rd_pn
, rd
->rd_einfo
->te_name
,
1623 rd
->rd_name
, rd
->rd_min
, rd
->rd_max
, NULL
);
1624 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "back from enumeration. %d\n",
1627 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1628 "Enumeration failed (%s)\n",
1629 topo_strerror(topo_mod_errno(mp
)));
1630 (void) topo_hdl_seterrno(thp
, EMOD_PARTIAL_ENUM
);
1631 return (topo_mod_seterrno(mp
, EMOD_PARTIAL_ENUM
));
1637 fac_enum_run(topo_mod_t
*mp
, tnode_t
*node
, const char *name
)
1639 topo_hdl_t
*thp
= mp
->tm_hdl
;
1643 topo_dprintf(thp
, TOPO_DBG_XML
, "fac_enum_run\n");
1645 * Check if the enumerator module is already loaded.
1646 * Module loading is single-threaded at this point so there's
1647 * no need to worry about the module going away or bumping the
1650 if ((fmod
= topo_mod_lookup(thp
, name
, 0)) == NULL
) {
1651 if ((fmod
= topo_mod_load(mp
, name
, TOPO_VERSION
)) == NULL
) {
1652 topo_dprintf(thp
, TOPO_DBG_ERR
,
1653 "fac_enum_run: mod_load of %s failed: %s.\n",
1654 name
, topo_strerror(topo_mod_errno(mp
)));
1655 (void) topo_hdl_seterrno(thp
, topo_mod_errno(mp
));
1660 * We're live, so let's enumerate.
1662 topo_dprintf(thp
, TOPO_DBG_XML
, "fac enumerate request. (%s)\n", name
);
1663 e
= topo_mod_enumerate(fmod
, node
, name
, name
, 0, 0, NULL
);
1664 topo_dprintf(thp
, TOPO_DBG_XML
, "back from enumeration. %d\n", e
);
1666 topo_dprintf(thp
, TOPO_DBG_ERR
,
1667 "Facility provider enumeration failed (%s)\n",
1668 topo_strerror(topo_mod_errno(mp
)));
1669 (void) topo_hdl_seterrno(thp
, EMOD_PARTIAL_ENUM
);
1670 return (topo_mod_seterrno(mp
, EMOD_PARTIAL_ENUM
));
1676 decorate_nodes(topo_mod_t
*mp
, tf_rdata_t
*rd
, xmlNodePtr pxn
, tnode_t
*ptn
,
1681 ctn
= topo_child_first(ptn
);
1682 while (ctn
!= NULL
) {
1683 /* Only care about instances within the range */
1684 if (strcmp(topo_node_name(ctn
), rd
->rd_name
) != 0) {
1685 ctn
= topo_child_next(ptn
, ctn
);
1688 if (pad_process(mp
, rd
, pxn
, ctn
, rpad
) < 0)
1690 if (decorate_nodes(mp
, rd
, pxn
, ctn
, rpad
) < 0)
1692 ctn
= topo_child_next(ptn
, ctn
);
1698 topo_xml_range_process(topo_mod_t
*mp
, xmlNodePtr rn
, tf_rdata_t
*rd
)
1701 * The range may have several children xmlNodes, that may
1702 * represent the enumeration method, property groups,
1703 * dependents, nodes or services.
1705 xmlNodePtr cn
, enum_node
= NULL
, pmap_node
= NULL
;
1710 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "topo_xml_range_process\n"
1711 "process %s range beneath %s\n", rd
->rd_name
,
1712 topo_node_name(rd
->rd_pn
));
1714 e
= topo_node_range_create(mp
,
1715 rd
->rd_pn
, rd
->rd_name
, rd
->rd_min
, rd
->rd_max
);
1716 if (e
!= 0 && topo_mod_errno(mp
) != EMOD_NODE_DUP
) {
1717 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1718 "Range create failed due to %s.\n",
1719 topo_strerror(topo_mod_errno(mp
)));
1724 * Before we process any of the other child xmlNodes, we iterate through
1725 * the children and looking for either enum-method or propmap elements.
1727 for (cn
= rn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
)
1728 if (xmlStrcmp(cn
->name
, (xmlChar
*)Enum_meth
) == 0)
1730 else if (xmlStrcmp(cn
->name
, (xmlChar
*)Propmap
) == 0)
1734 * If we found an enum-method element, process it first
1736 if (enum_node
!= NULL
) {
1737 if ((rd
->rd_einfo
= enum_attributes_process(mp
, enum_node
))
1740 if (enum_run(mp
, rd
) < 0) {
1742 * Note the failure but continue on
1744 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1745 "Enumeration failed.\n");
1750 * Next, check if a propmap element was found and if so, load it in
1753 if (pmap_node
!= NULL
) {
1754 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "found a propmap "
1756 if ((pmap_name
= xmlGetProp(pmap_node
, (xmlChar
*)Name
))
1758 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1759 "propmap element missing name attribute.\n");
1761 if (topo_file_load(mp
, rd
->rd_pn
,
1762 (const char *)pmap_name
,
1763 rd
->rd_finfo
->tf_scheme
, 1) < 0) {
1765 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1766 "topo_xml_range_process: topo_file_load"
1768 topo_strerror(topo_mod_errno(mp
)));
1774 /* Now look for nodes, i.e., hard instances */
1775 for (cn
= rn
->xmlChildrenNode
; cn
!= NULL
; cn
= cn
->next
) {
1776 if (xmlStrcmp(cn
->name
, (xmlChar
*)Node
) == 0) {
1777 if (node_process(mp
, cn
, rd
) < 0) {
1778 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_ERR
,
1779 "node processing failed: %s.\n",
1780 topo_strerror(topo_mod_errno(mp
)));
1781 return (topo_mod_seterrno(mp
,
1782 EMOD_PARTIAL_ENUM
));
1789 * Finally, process the property groups and dependents
1791 * If the TF_PROPMAP flag is set for the XML file we're currently
1792 * processing, then this XML file was loaded via propmap. In that case
1793 * we call a special routine to recursively apply the propgroup settings
1794 * to all of nodes in this range
1796 if (rd
->rd_finfo
->tf_flags
& TF_PROPMAP
)
1797 (void) decorate_nodes(mp
, rd
, rn
, rd
->rd_pn
, &rd
->rd_pad
);
1799 ct
= topo_child_first(rd
->rd_pn
);
1800 while (ct
!= NULL
) {
1801 /* Only care about instances within the range */
1802 if (strcmp(topo_node_name(ct
), rd
->rd_name
) != 0) {
1803 ct
= topo_child_next(rd
->rd_pn
, ct
);
1806 if (pad_process(mp
, rd
, rn
, ct
, &rd
->rd_pad
)
1810 if (fac_process(mp
, rn
, rd
, ct
) < 0)
1813 ct
= topo_child_next(rd
->rd_pn
, ct
);
1818 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "topo_xml_range_process: end "
1819 "range process %s\n", rd
->rd_name
);
1825 topo_xml_walk(topo_mod_t
*mp
,
1826 tf_info_t
*xinfo
, xmlNodePtr croot
, tnode_t
*troot
)
1828 xmlNodePtr curr
, def_set
= NULL
;
1829 tf_rdata_t
*rr
, *pr
, *rdp
;
1834 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
, "topo_xml_walk\n");
1837 * First iterate through all the XML nodes at this level to look for
1840 for (curr
= croot
->xmlChildrenNode
; curr
!= NULL
; curr
= curr
->next
) {
1841 if (curr
->name
== NULL
) {
1842 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
1843 "topo_xml_walk: Ignoring nameless xmlnode\n");
1846 if (xmlStrcmp(curr
->name
, (xmlChar
*)Set
) == 0) {
1850 set
= xmlGetProp(curr
, (xmlChar
*)Setlist
);
1852 if (mp
->tm_hdl
->th_product
)
1853 key
= mp
->tm_hdl
->th_product
;
1855 key
= mp
->tm_hdl
->th_platform
;
1858 * If it's the default set then we'll store
1859 * a pointer to it so that if none of the other
1860 * sets apply to our product we can fall
1863 if (strcmp((char *)set
, "default") == 0)
1865 else if (set_contains(mp
, key
, (char *)set
)) {
1867 if ((rdp
= topo_xml_walk(mp
, xinfo
, curr
,
1869 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
1870 "topo_xml_walk: failed1\n");
1885 * If we haven't found a set that contains our product AND a default set
1886 * exists, then we'll process it.
1888 if (!joined_set
&& def_set
) {
1889 if ((rdp
= topo_xml_walk(mp
, xinfo
, def_set
, troot
)) == NULL
) {
1890 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
1891 "topo_xml_walk: failed2\n");
1902 * Now we're interested in children xmlNodes of croot tagged
1903 * as 'ranges'. These define what topology nodes may exist, and need
1906 for (curr
= croot
->xmlChildrenNode
; curr
!= NULL
; curr
= curr
->next
) {
1907 if (curr
->name
== NULL
) {
1908 topo_dprintf(mp
->tm_hdl
, TOPO_DBG_XML
,
1909 "topo_xml_walk: Ignoring nameless xmlnode\n");
1912 if (xmlStrcmp(curr
->name
, (xmlChar
*)Range
) != 0)
1914 if ((rdp
= tf_rdata_new(mp
, xinfo
, curr
, troot
)) == NULL
) {
1916 * Range processing error, continue walk
1933 * Convert parsed xml topology description into topology nodes
1936 topo_xml_enum(topo_mod_t
*tmp
, tf_info_t
*xinfo
, tnode_t
*troot
)
1940 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_XML
, "topo_xml_enum\n");
1942 if ((xroot
= xmlDocGetRootElement(xinfo
->tf_xdoc
)) == NULL
) {
1943 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_ERR
,
1944 "Couldn't get root xmlNode.\n");
1947 if ((xinfo
->tf_rd
= topo_xml_walk(tmp
, xinfo
, xroot
, troot
)) == NULL
) {
1948 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_ERR
,
1949 "error within .xml topology: %s\n",
1950 topo_strerror(topo_mod_errno(tmp
)));
1957 * Load an XML tree from filename and read it into a DOM parse tree.
1960 txml_file_parse(topo_mod_t
*tmp
,
1961 int fd
, const char *filenm
, const char *escheme
)
1963 xmlValidCtxtPtr vcp
;
1966 xmlDtdPtr dtd
= NULL
;
1967 xmlChar
*scheme
= NULL
;
1968 char *dtdpath
= NULL
;
1971 int e
, validate
= 0;
1973 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_XML
,
1974 "txml_file_parse(filenm=%s, escheme=%s)\n", filenm
, escheme
);
1977 * Since topologies can XInclude other topologies, and libxml2
1978 * doesn't do DTD-based validation with XInclude, by default
1979 * we don't validate topology files. One can force
1980 * validation, though, by creating a TOPOXML_VALIDATE
1981 * environment variable and creating a TOPO_DTD environment
1982 * variable with the path to the DTD against which to validate.
1984 if (getenv("TOPOXML_VALIDATE") != NULL
) {
1985 dtdpath
= getenv("TOPO_DTD");
1986 if (dtdpath
!= NULL
)
1987 xmlLoadExtDtdDefaultValue
= 0;
1992 * Splat warnings and errors related to parsing the topology
1993 * file if the TOPOXML_PERROR environment variable exists.
1995 if (getenv("TOPOXML_PERROR") == NULL
)
1996 readflags
= XML_PARSE_NOERROR
| XML_PARSE_NOWARNING
;
1998 if ((document
= xmlReadFd(fd
, filenm
, NULL
, readflags
)) == NULL
) {
1999 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_ERR
,
2000 "txml_file_parse: couldn't parse document.\n");
2005 * Verify that this is a document type we understand.
2007 if ((dtd
= xmlGetIntSubset(document
)) == NULL
) {
2008 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_ERR
,
2009 "document has no DTD.\n");
2010 xmlFreeDoc(document
);
2014 if (strcmp((const char *)dtd
->SystemID
, TOPO_DTD_PATH
) != 0) {
2015 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_ERR
,
2016 "document DTD unknown; bad topology file\n");
2017 xmlFreeDoc(document
);
2021 if ((cursor
= xmlDocGetRootElement(document
)) == NULL
) {
2022 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_ERR
, "document is empty.\n");
2023 xmlFreeDoc(document
);
2028 * Make sure we're looking at a topology description in the
2031 if (xmlStrcmp(cursor
->name
, (xmlChar
*)Topology
) != 0) {
2032 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_ERR
,
2033 "document is not a topology description.\n");
2034 xmlFreeDoc(document
);
2037 if ((scheme
= xmlGetProp(cursor
, (xmlChar
*)Scheme
)) == NULL
) {
2038 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_ERR
,
2039 "topology lacks a scheme.\n");
2040 (void) topo_mod_seterrno(tmp
, ETOPO_PRSR_NOATTR
);
2041 xmlFreeDoc(document
);
2044 if (xmlStrcmp(scheme
, (xmlChar
*)escheme
) != 0) {
2045 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_ERR
,
2046 "topology in unrecognized scheme, %s, expecting %s\n",
2048 (void) topo_mod_seterrno(tmp
, ETOPO_PRSR_BADSCH
);
2050 xmlFreeDoc(document
);
2054 if (dtdpath
!= NULL
) {
2055 dtd
= xmlParseDTD(NULL
, (xmlChar
*)dtdpath
);
2057 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_ERR
,
2058 "Could not parse DTD \"%s\".\n",
2061 xmlFreeDoc(document
);
2065 if (document
->extSubset
!= NULL
)
2066 xmlFreeDtd(document
->extSubset
);
2068 document
->extSubset
= dtd
;
2071 if (xmlXIncludeProcessFlags(document
, XML_PARSE_XINCLUDE
) == -1) {
2073 xmlFreeDoc(document
);
2074 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_ERR
,
2075 "couldn't handle XInclude statements in document\n");
2080 if ((vcp
= xmlNewValidCtxt()) == NULL
) {
2082 xmlFreeDoc(document
);
2085 vcp
->warning
= xmlParserValidityWarning
;
2086 vcp
->error
= xmlParserValidityError
;
2088 e
= xmlValidateDocument(vcp
, document
);
2090 xmlFreeValidCtxt(vcp
);
2093 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_ERR
,
2094 "Document is not valid.\n");
2097 if ((r
= tf_info_new(tmp
, document
, scheme
)) == NULL
) {
2099 xmlFreeDoc(document
);
2109 topo_xml_read(topo_mod_t
*tmp
, const char *path
, const char *escheme
)
2114 if ((fd
= open(path
, O_RDONLY
)) < 0) {
2115 topo_dprintf(tmp
->tm_hdl
, TOPO_DBG_ERR
,
2116 "failed to open %s for reading\n", path
);
2119 tip
= txml_file_parse(tmp
, fd
, path
, escheme
);