xref: /illumos-gate/usr/src/lib/fm/topo/libtopo/common/topo_2xml.c (revision 3ced7af1ee4d7b1d1a3766385fdb7527a2abda93)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <strings.h>
31 #include <time.h>
32 #include <sys/types.h>
33 #include <sys/fm/protocol.h>
34 #include <sys/utsname.h>
35 
36 #include <topo_parse.h>
37 #include <topo_prop.h>
38 #include <topo_tree.h>
39 
40 #define	INT32BUFSZ	sizeof (UINT32_MAX) + 1
41 #define	INT64BUFSZ	sizeof (UINT64_MAX) + 1
42 #define	XML_VERSION	"1.0"
43 
44 static int txml_print_range(topo_hdl_t *, FILE *, tnode_t *, int);
45 
46 void
47 print_header(FILE *fp)
48 {
49 	char buf[32];
50 	time_t tod = time(NULL);
51 	struct utsname uts;
52 
53 	(void) fprintf(fp, "<?xml version=\"%s\"?>\n", XML_VERSION);
54 	(void) fprintf(fp, "<!DOCTYPE topology SYSTEM \"%s\">\n",
55 	    TOPO_DTD_PATH);
56 
57 	(void) uname(&uts);
58 	(void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod));
59 	(void) fprintf(fp, "<!--\n");
60 	(void) fprintf(fp, " This topology map file was generated on "
61 	    "%-15s for %s\n", buf, uts.nodename);
62 	(void) fprintf(fp, "<-->\n\n");
63 }
64 
65 void
66 begin_element(FILE *fp, const char *ename, ...)
67 {
68 	char *name, *value;
69 	va_list ap;
70 
71 	(void) fprintf(fp, "<%s ", ename);
72 	va_start(ap, ename);
73 	name = va_arg(ap, char *);
74 	while (name != NULL) {
75 		value = va_arg(ap, char *);
76 		(void) fprintf(fp, "%s='%s' ", name, value);
77 		name = va_arg(ap, char *);
78 	}
79 	(void) fprintf(fp, ">\n");
80 }
81 
82 void
83 begin_end_element(FILE *fp, const char *ename, ...)
84 {
85 	char *name, *value;
86 	va_list ap;
87 
88 	(void) fprintf(fp, "<%s ", ename);
89 	va_start(ap, ename);
90 	name = va_arg(ap, char *);
91 	while (name != NULL) {
92 		value = va_arg(ap, char *);
93 		(void) fprintf(fp, "%s='%s' ", name, value);
94 		name = va_arg(ap, char *);
95 	}
96 	(void) fprintf(fp, "/>\n");
97 }
98 
99 void
100 end_element(FILE *fp, const char *ename)
101 {
102 	(void) fprintf(fp, "</%s>\n", ename);
103 }
104 
105 static void
106 txml_print_prop(topo_hdl_t *thp, FILE *fp, topo_propval_t *pv)
107 {
108 	int err;
109 	char *fmri = NULL;
110 	char vbuf[INT64BUFSZ], tbuf[10], *pval, *aval;
111 	nvpair_t *nvp;
112 
113 	nvp = nvlist_next_nvpair(pv->tp_val, NULL);
114 	while (nvp && (strcmp(TOPO_PROP_VAL_VAL, nvpair_name(nvp)) != 0))
115 			nvp = nvlist_next_nvpair(pv->tp_val, nvp);
116 
117 	if (nvp == NULL)
118 		return;
119 
120 	switch (pv->tp_type) {
121 		case TOPO_TYPE_INT32: {
122 			int32_t val;
123 			(void) nvpair_value_int32(nvp, &val);
124 			(void) snprintf(vbuf, INT64BUFSZ, "%d", val);
125 			(void) snprintf(tbuf, 10, "%s", Int32);
126 			pval = vbuf;
127 			break;
128 		}
129 		case TOPO_TYPE_UINT32: {
130 			uint32_t val;
131 			(void) nvpair_value_uint32(nvp, &val);
132 			(void) snprintf(vbuf, INT64BUFSZ, "0x%x", val);
133 			(void) snprintf(tbuf, 10, "%s", UInt32);
134 			pval = vbuf;
135 			break;
136 		}
137 		case TOPO_TYPE_INT64: {
138 			int64_t val;
139 			(void) nvpair_value_int64(nvp, &val);
140 			(void) snprintf(vbuf, INT64BUFSZ, "%lld",
141 			    (longlong_t)val);
142 			(void) snprintf(tbuf, 10, "%s", Int64);
143 			pval = vbuf;
144 			break;
145 		}
146 		case TOPO_TYPE_UINT64: {
147 			uint64_t val;
148 			(void) nvpair_value_uint64(nvp, &val);
149 			(void) snprintf(vbuf, INT64BUFSZ, "0x%llx",
150 			    (u_longlong_t)val);
151 			(void) snprintf(tbuf, 10, "%s", UInt64);
152 			pval = vbuf;
153 			break;
154 		}
155 		case TOPO_TYPE_STRING: {
156 			(void) nvpair_value_string(nvp, &pval);
157 			(void) snprintf(tbuf, 10, "%s", String);
158 			break;
159 		}
160 		case TOPO_TYPE_FMRI: {
161 			nvlist_t *val;
162 
163 			(void) nvpair_value_nvlist(nvp, &val);
164 			if (topo_fmri_nvl2str(thp, val, &fmri, &err) == 0)
165 				pval = fmri;
166 			else
167 				return;
168 
169 			(void) snprintf(tbuf, 10, "%s", FMRI);
170 			break;
171 		}
172 		case TOPO_TYPE_UINT32_ARRAY: {
173 			uint32_t *val;
174 			uint_t nelem, i;
175 
176 			(void) nvpair_value_uint32_array(nvp, &val, &nelem);
177 
178 			if (nelem > 0) {
179 				aval = calloc((nelem*9-1), sizeof (uchar_t));
180 
181 				(void) sprintf(aval, "0x%x", val[0]);
182 				for (i = 1; i < nelem; i++) {
183 					(void) sprintf(vbuf, " 0x%x", val[i]);
184 					(void) strcat(aval, vbuf);
185 				}
186 				(void) snprintf(tbuf, 10, "%s", UInt32_Arr);
187 				pval = aval;
188 			}
189 			break;
190 		}
191 	}
192 
193 	begin_end_element(fp, Propval, Name, pv->tp_name, Type, tbuf,
194 	    Value, pval, NULL);
195 
196 	if (fmri != NULL)
197 		topo_hdl_strfree(thp, fmri);
198 
199 }
200 
201 static void
202 txml_print_pgroup(topo_hdl_t *thp, FILE *fp, topo_pgroup_t *pg)
203 {
204 	topo_ipgroup_info_t *pip = pg->tpg_info;
205 	topo_proplist_t *plp;
206 	const char *namestab, *datastab;
207 	char version[INT32BUFSZ];
208 
209 	namestab = topo_stability2name(pip->tpi_namestab);
210 	datastab = topo_stability2name(pip->tpi_datastab);
211 	(void) snprintf(version, INT32BUFSZ, "%d", pip->tpi_version);
212 	begin_element(fp, Propgrp, Name, pip->tpi_name, Namestab,
213 	    namestab, Datastab, datastab, Version, version, NULL);
214 	for (plp = topo_list_next(&pg->tpg_pvals); plp != NULL;
215 	    plp = topo_list_next(plp)) {
216 		txml_print_prop(thp, fp, plp->tp_pval);
217 	}
218 	end_element(fp, Propgrp);
219 }
220 
221 static void
222 txml_print_dependents(topo_hdl_t *thp, FILE *fp, tnode_t *node)
223 {
224 	if (topo_list_next(&node->tn_children) == NULL)
225 		return;
226 
227 	if (txml_print_range(thp, fp, node, 1) == 1)
228 		end_element(fp, Dependents);
229 }
230 
231 static void
232 txml_print_node(topo_hdl_t *thp, FILE *fp, tnode_t *node)
233 {
234 	char inst[INT32BUFSZ];
235 	topo_pgroup_t *pg;
236 
237 	(void) snprintf(inst, INT32BUFSZ, "%d", node->tn_instance);
238 	begin_element(fp, Node, Instance, inst, Static, True, NULL);
239 	for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
240 	    pg = topo_list_next(pg)) {
241 		txml_print_pgroup(thp, fp, pg);
242 	}
243 	txml_print_dependents(thp, fp, node);
244 	end_element(fp, Node);
245 
246 }
247 
248 static int
249 txml_print_range(topo_hdl_t *thp, FILE *fp, tnode_t *node, int dependent)
250 {
251 	int i, create = 0, ret = 0;
252 	topo_nodehash_t *nhp;
253 	char min[INT32BUFSZ], max[INT32BUFSZ];
254 
255 	for (nhp = topo_list_next(&node->tn_children); nhp != NULL;
256 	    nhp = topo_list_next(nhp)) {
257 		(void) snprintf(min, INT32BUFSZ, "%d", nhp->th_range.tr_min);
258 		(void) snprintf(max, INT32BUFSZ, "%d", nhp->th_range.tr_max);
259 
260 		/*
261 		 * Some enumerators create empty ranges: make sure there
262 		 * are real nodes before creating this range
263 		 */
264 		for (i = 0; i < nhp->th_arrlen; ++i) {
265 			if (nhp->th_nodearr[i] != NULL)
266 				++create;
267 		}
268 		if (!create)
269 			continue;
270 
271 		if (dependent) {
272 			begin_element(fp, Dependents, Grouping, Children, NULL);
273 			dependent = 0;
274 			ret = 1;
275 		}
276 		begin_element(fp, Range, Name, nhp->th_name, Min, min, Max,
277 		    max, NULL);
278 		for (i = 0; i < nhp->th_arrlen; ++i) {
279 			if (nhp->th_nodearr[i] != NULL)
280 				txml_print_node(thp, fp, nhp->th_nodearr[i]);
281 		}
282 		end_element(fp, Range);
283 	}
284 
285 	return (ret);
286 }
287 
288 static void
289 txml_print_topology(topo_hdl_t *thp, FILE *fp, char *scheme, tnode_t *node)
290 {
291 	char *name;
292 
293 	if (thp->th_product != NULL)
294 		name = thp->th_product;
295 	else
296 		name = thp->th_platform;
297 
298 	begin_element(fp, Topology, Name, name, Scheme, scheme,
299 	    NULL);
300 	(void) txml_print_range(thp, fp, node, 0);
301 	end_element(fp, Topology);
302 
303 }
304 
305 int
306 topo_xml_print(topo_hdl_t *thp,  FILE *fp, const char *scheme, int *err)
307 {
308 	ttree_t *tp;
309 
310 	print_header(fp);
311 	for (tp = topo_list_next(&thp->th_trees); tp != NULL;
312 	    tp = topo_list_next(tp)) {
313 		if (strcmp(scheme, tp->tt_scheme) == 0) {
314 			txml_print_topology(thp, fp, tp->tt_scheme,
315 			    tp->tt_root);
316 			return (0);
317 		}
318 	}
319 
320 	*err = EINVAL;
321 	return (-1);
322 }
323