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 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
30 #include <sys/types.h>
31 #include <sys/fm/protocol.h>
32 #include <sys/utsname.h>
34 #include <topo_parse.h>
35 #include <topo_prop.h>
36 #include <topo_tree.h>
38 #define INT32BUFSZ sizeof (UINT32_MAX) + 1
39 /* 2 bytes for "0x" + 16 bytes for the hex value + 1 for sign + null */
41 #define XML_VERSION "1.0"
43 static int txml_print_range(topo_hdl_t
*, FILE *, tnode_t
*, int);
46 print_header(FILE *fp
)
49 time_t tod
= time(NULL
);
52 (void) fprintf(fp
, "<?xml version=\"%s\"?>\n", XML_VERSION
);
53 (void) fprintf(fp
, "<!DOCTYPE topology SYSTEM \"%s\">\n",
57 (void) strftime(buf
, sizeof (buf
), "%b %d %T", localtime(&tod
));
58 (void) fprintf(fp
, "<!--\n");
59 (void) fprintf(fp
, " This topology map file was generated on "
60 "%-15s for %s\n", buf
, uts
.nodename
);
61 (void) fprintf(fp
, "<-->\n\n");
65 begin_element(FILE *fp
, const char *ename
, ...)
70 (void) fprintf(fp
, "<%s ", ename
);
72 name
= va_arg(ap
, char *);
73 while (name
!= NULL
) {
74 value
= va_arg(ap
, char *);
75 (void) fprintf(fp
, "%s='%s' ", name
, value
);
76 name
= va_arg(ap
, char *);
78 (void) fprintf(fp
, ">\n");
82 begin_end_element(FILE *fp
, const char *ename
, ...)
87 (void) fprintf(fp
, "<%s ", ename
);
89 name
= va_arg(ap
, char *);
90 while (name
!= NULL
) {
91 value
= va_arg(ap
, char *);
92 (void) fprintf(fp
, "%s='%s' ", name
, value
);
93 name
= va_arg(ap
, char *);
95 (void) fprintf(fp
, "/>\n");
99 end_element(FILE *fp
, const char *ename
)
101 (void) fprintf(fp
, "</%s>\n", ename
);
105 txml_print_prop(topo_hdl_t
*thp
, FILE *fp
, tnode_t
*node
, const char *pgname
,
110 char vbuf
[INT64BUFSZ
], tbuf
[32], *pval
= NULL
, *aval
= NULL
;
112 switch (pv
->tp_type
) {
113 case TOPO_TYPE_INT32
: {
115 if (topo_prop_get_int32(node
, pgname
, pv
->tp_name
, &val
,
117 (void) snprintf(vbuf
, INT64BUFSZ
, "%d", val
);
118 (void) snprintf(tbuf
, 10, "%s", Int32
);
124 case TOPO_TYPE_UINT32
: {
126 if (topo_prop_get_uint32(node
, pgname
, pv
->tp_name
,
128 (void) snprintf(vbuf
, INT64BUFSZ
, "0x%x", val
);
129 (void) snprintf(tbuf
, 10, "%s", UInt32
);
135 case TOPO_TYPE_INT64
: {
137 if (topo_prop_get_int64(node
, pgname
, pv
->tp_name
, &val
,
139 (void) snprintf(vbuf
, INT64BUFSZ
, "0x%llx",
141 (void) snprintf(tbuf
, 10, "%s", Int64
);
147 case TOPO_TYPE_UINT64
: {
149 if (topo_prop_get_uint64(node
, pgname
, pv
->tp_name
,
151 (void) snprintf(vbuf
, INT64BUFSZ
, "0x%llx",
153 (void) snprintf(tbuf
, 10, "%s", UInt64
);
159 case TOPO_TYPE_STRING
: {
160 if (topo_prop_get_string(node
, pgname
, pv
->tp_name
,
163 (void) snprintf(tbuf
, 10, "%s", "string");
166 case TOPO_TYPE_FMRI
: {
169 if (topo_prop_get_fmri(node
, pgname
, pv
->tp_name
, &val
,
171 if (topo_fmri_nvl2str(thp
, val
, &fmri
, &err
)
181 (void) snprintf(tbuf
, 10, "%s", FMRI
);
184 case TOPO_TYPE_UINT32_ARRAY
: {
187 if (topo_prop_get_uint32_array(node
, pgname
,
188 pv
->tp_name
, &val
, &nelem
, &err
) != 0)
192 if ((aval
= calloc((nelem
* 9 - 1),
193 sizeof (uchar_t
))) == NULL
) {
195 topo_hdl_free(thp
, val
,
196 nelem
* sizeof (uint32_t));
200 (void) sprintf(aval
, "0x%x", val
[0]);
201 for (i
= 1; i
< nelem
; i
++) {
202 (void) sprintf(vbuf
, " 0x%x", val
[i
]);
203 (void) strcat(aval
, vbuf
);
205 topo_hdl_free(thp
, val
,
206 nelem
* sizeof (uint32_t));
207 (void) snprintf(tbuf
, 10, "%s", UInt32_Arr
);
216 begin_end_element(fp
, Propval
, Name
, pv
->tp_name
, Type
, tbuf
,
219 if (pval
!= NULL
&& pv
->tp_type
== TOPO_TYPE_STRING
)
220 topo_hdl_strfree(thp
, pval
);
223 topo_hdl_strfree(thp
, fmri
);
229 txml_print_pgroup(topo_hdl_t
*thp
, FILE *fp
, tnode_t
*node
, topo_pgroup_t
*pg
)
231 topo_ipgroup_info_t
*pip
= pg
->tpg_info
;
232 topo_proplist_t
*plp
;
233 const char *namestab
, *datastab
;
234 char version
[INT32BUFSZ
];
236 namestab
= topo_stability2name(pip
->tpi_namestab
);
237 datastab
= topo_stability2name(pip
->tpi_datastab
);
238 (void) snprintf(version
, INT32BUFSZ
, "%d", pip
->tpi_version
);
239 begin_element(fp
, Propgrp
, Name
, pip
->tpi_name
, Namestab
,
240 namestab
, Datastab
, datastab
, Version
, version
, NULL
);
241 for (plp
= topo_list_next(&pg
->tpg_pvals
); plp
!= NULL
;
242 plp
= topo_list_next(plp
)) {
243 txml_print_prop(thp
, fp
, node
, pip
->tpi_name
, plp
->tp_pval
);
245 end_element(fp
, Propgrp
);
249 txml_print_dependents(topo_hdl_t
*thp
, FILE *fp
, tnode_t
*node
)
251 if (topo_list_next(&node
->tn_children
) == NULL
)
254 if (txml_print_range(thp
, fp
, node
, 1) == 1)
255 end_element(fp
, Dependents
);
259 txml_print_node(topo_hdl_t
*thp
, FILE *fp
, tnode_t
*node
)
261 char inst
[INT32BUFSZ
];
264 (void) snprintf(inst
, INT32BUFSZ
, "%d", node
->tn_instance
);
265 begin_element(fp
, Node
, Instance
, inst
, Static
, True
, NULL
);
266 for (pg
= topo_list_next(&node
->tn_pgroups
); pg
!= NULL
;
267 pg
= topo_list_next(pg
)) {
268 txml_print_pgroup(thp
, fp
, node
, pg
);
270 txml_print_dependents(thp
, fp
, node
);
271 end_element(fp
, Node
);
276 txml_print_range(topo_hdl_t
*thp
, FILE *fp
, tnode_t
*node
, int dependent
)
278 int i
, create
= 0, ret
= 0;
279 topo_nodehash_t
*nhp
;
280 char min
[INT32BUFSZ
], max
[INT32BUFSZ
];
282 for (nhp
= topo_list_next(&node
->tn_children
); nhp
!= NULL
;
283 nhp
= topo_list_next(nhp
)) {
284 (void) snprintf(min
, INT32BUFSZ
, "%d", nhp
->th_range
.tr_min
);
285 (void) snprintf(max
, INT32BUFSZ
, "%d", nhp
->th_range
.tr_max
);
288 * Some enumerators create empty ranges: make sure there
289 * are real nodes before creating this range
291 for (i
= 0; i
< nhp
->th_arrlen
; ++i
) {
292 if (nhp
->th_nodearr
[i
] != NULL
)
299 begin_element(fp
, Dependents
, Grouping
, Children
, NULL
);
303 begin_element(fp
, Range
, Name
, nhp
->th_name
, Min
, min
, Max
,
305 for (i
= 0; i
< nhp
->th_arrlen
; ++i
) {
306 if (nhp
->th_nodearr
[i
] != NULL
)
307 txml_print_node(thp
, fp
, nhp
->th_nodearr
[i
]);
309 end_element(fp
, Range
);
316 txml_print_topology(topo_hdl_t
*thp
, FILE *fp
, char *scheme
, tnode_t
*node
)
320 if (thp
->th_product
!= NULL
)
321 name
= thp
->th_product
;
323 name
= thp
->th_platform
;
325 begin_element(fp
, Topology
, Name
, name
, Scheme
, scheme
,
327 (void) txml_print_range(thp
, fp
, node
, 0);
328 end_element(fp
, Topology
);
333 topo_xml_print(topo_hdl_t
*thp
, FILE *fp
, const char *scheme
, int *err
)
338 for (tp
= topo_list_next(&thp
->th_trees
); tp
!= NULL
;
339 tp
= topo_list_next(tp
)) {
340 if (strcmp(scheme
, tp
->tt_scheme
) == 0) {
341 txml_print_topology(thp
, fp
, tp
->tt_scheme
,