dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / fm / topo / libtopo / common / topo_2xml.c
blobfbd125462570a0d425898fccd1538a57c73464c3
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <stdio.h>
28 #include <strings.h>
29 #include <time.h>
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 */
40 #define INT64BUFSZ 20
41 #define XML_VERSION "1.0"
43 static int txml_print_range(topo_hdl_t *, FILE *, tnode_t *, int);
45 void
46 print_header(FILE *fp)
48 char buf[32];
49 time_t tod = time(NULL);
50 struct utsname uts;
52 (void) fprintf(fp, "<?xml version=\"%s\"?>\n", XML_VERSION);
53 (void) fprintf(fp, "<!DOCTYPE topology SYSTEM \"%s\">\n",
54 TOPO_DTD_PATH);
56 (void) uname(&uts);
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");
64 void
65 begin_element(FILE *fp, const char *ename, ...)
67 char *name, *value;
68 va_list ap;
70 (void) fprintf(fp, "<%s ", ename);
71 va_start(ap, 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");
81 void
82 begin_end_element(FILE *fp, const char *ename, ...)
84 char *name, *value;
85 va_list ap;
87 (void) fprintf(fp, "<%s ", ename);
88 va_start(ap, 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");
98 void
99 end_element(FILE *fp, const char *ename)
101 (void) fprintf(fp, "</%s>\n", ename);
104 static void
105 txml_print_prop(topo_hdl_t *thp, FILE *fp, tnode_t *node, const char *pgname,
106 topo_propval_t *pv)
108 int err;
109 char *fmri = NULL;
110 char vbuf[INT64BUFSZ], tbuf[32], *pval = NULL, *aval = NULL;
112 switch (pv->tp_type) {
113 case TOPO_TYPE_INT32: {
114 int32_t val;
115 if (topo_prop_get_int32(node, pgname, pv->tp_name, &val,
116 &err) == 0) {
117 (void) snprintf(vbuf, INT64BUFSZ, "%d", val);
118 (void) snprintf(tbuf, 10, "%s", Int32);
119 pval = vbuf;
120 } else
121 return;
122 break;
124 case TOPO_TYPE_UINT32: {
125 uint32_t val;
126 if (topo_prop_get_uint32(node, pgname, pv->tp_name,
127 &val, &err) == 0) {
128 (void) snprintf(vbuf, INT64BUFSZ, "0x%x", val);
129 (void) snprintf(tbuf, 10, "%s", UInt32);
130 pval = vbuf;
131 } else
132 return;
133 break;
135 case TOPO_TYPE_INT64: {
136 int64_t val;
137 if (topo_prop_get_int64(node, pgname, pv->tp_name, &val,
138 &err) == 0) {
139 (void) snprintf(vbuf, INT64BUFSZ, "0x%llx",
140 (longlong_t)val);
141 (void) snprintf(tbuf, 10, "%s", Int64);
142 pval = vbuf;
143 } else
144 return;
145 break;
147 case TOPO_TYPE_UINT64: {
148 uint64_t val;
149 if (topo_prop_get_uint64(node, pgname, pv->tp_name,
150 &val, &err) == 0) {
151 (void) snprintf(vbuf, INT64BUFSZ, "0x%llx",
152 (u_longlong_t)val);
153 (void) snprintf(tbuf, 10, "%s", UInt64);
154 pval = vbuf;
155 } else
156 return;
157 break;
159 case TOPO_TYPE_STRING: {
160 if (topo_prop_get_string(node, pgname, pv->tp_name,
161 &pval, &err) != 0)
162 return;
163 (void) snprintf(tbuf, 10, "%s", "string");
164 break;
166 case TOPO_TYPE_FMRI: {
167 nvlist_t *val;
169 if (topo_prop_get_fmri(node, pgname, pv->tp_name, &val,
170 &err) == 0) {
171 if (topo_fmri_nvl2str(thp, val, &fmri, &err)
172 == 0) {
173 nvlist_free(val);
174 pval = fmri;
175 } else {
176 nvlist_free(val);
177 return;
179 } else
180 return;
181 (void) snprintf(tbuf, 10, "%s", FMRI);
182 break;
184 case TOPO_TYPE_UINT32_ARRAY: {
185 uint32_t *val;
186 uint_t nelem, i;
187 if (topo_prop_get_uint32_array(node, pgname,
188 pv->tp_name, &val, &nelem, &err) != 0)
189 return;
191 if (nelem > 0) {
192 if ((aval = calloc((nelem * 9 - 1),
193 sizeof (uchar_t))) == NULL) {
195 topo_hdl_free(thp, val,
196 nelem * sizeof (uint32_t));
197 return;
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);
208 pval = aval;
210 break;
212 default:
213 return;
216 begin_end_element(fp, Propval, Name, pv->tp_name, Type, tbuf,
217 Value, pval, NULL);
219 if (pval != NULL && pv->tp_type == TOPO_TYPE_STRING)
220 topo_hdl_strfree(thp, pval);
222 if (fmri != NULL)
223 topo_hdl_strfree(thp, fmri);
225 free(aval);
228 static void
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);
248 static void
249 txml_print_dependents(topo_hdl_t *thp, FILE *fp, tnode_t *node)
251 if (topo_list_next(&node->tn_children) == NULL)
252 return;
254 if (txml_print_range(thp, fp, node, 1) == 1)
255 end_element(fp, Dependents);
258 static void
259 txml_print_node(topo_hdl_t *thp, FILE *fp, tnode_t *node)
261 char inst[INT32BUFSZ];
262 topo_pgroup_t *pg;
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);
275 static int
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)
293 ++create;
295 if (!create)
296 continue;
298 if (dependent) {
299 begin_element(fp, Dependents, Grouping, Children, NULL);
300 dependent = 0;
301 ret = 1;
303 begin_element(fp, Range, Name, nhp->th_name, Min, min, Max,
304 max, NULL);
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);
312 return (ret);
315 static void
316 txml_print_topology(topo_hdl_t *thp, FILE *fp, char *scheme, tnode_t *node)
318 char *name;
320 if (thp->th_product != NULL)
321 name = thp->th_product;
322 else
323 name = thp->th_platform;
325 begin_element(fp, Topology, Name, name, Scheme, scheme,
326 NULL);
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)
335 ttree_t *tp;
337 print_header(fp);
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,
342 tp->tt_root);
343 return (0);
347 *err = EINVAL;
348 return (-1);