xref: /illumos-gate/usr/src/lib/fm/topo/libtopo/common/topo_2xml.c (revision c839f7d5515cd80a9c4f32cc29aa002e8ebc5dbb)
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 2007 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;
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 	}
173 
174 	begin_end_element(fp, Propval, Name, pv->tp_name, Type, tbuf,
175 	    Value, pval, NULL);
176 
177 	if (fmri != NULL)
178 		topo_hdl_strfree(thp, fmri);
179 
180 }
181 
182 static void
183 txml_print_pgroup(topo_hdl_t *thp, FILE *fp, topo_pgroup_t *pg)
184 {
185 	topo_ipgroup_info_t *pip = pg->tpg_info;
186 	topo_proplist_t *plp;
187 	const char *namestab, *datastab;
188 	char version[INT32BUFSZ];
189 
190 	namestab = topo_stability2name(pip->tpi_namestab);
191 	datastab = topo_stability2name(pip->tpi_datastab);
192 	(void) snprintf(version, INT32BUFSZ, "%d", pip->tpi_version);
193 	begin_element(fp, Propgrp, Name, pip->tpi_name, Namestab,
194 	    namestab, Datastab, datastab, Version, version, NULL);
195 	for (plp = topo_list_next(&pg->tpg_pvals); plp != NULL;
196 	    plp = topo_list_next(plp)) {
197 		txml_print_prop(thp, fp, plp->tp_pval);
198 	}
199 	end_element(fp, Propgrp);
200 }
201 
202 static void
203 txml_print_dependents(topo_hdl_t *thp, FILE *fp, tnode_t *node)
204 {
205 	if (topo_list_next(&node->tn_children) == NULL)
206 		return;
207 
208 	if (txml_print_range(thp, fp, node, 1) == 1)
209 		end_element(fp, Dependents);
210 }
211 
212 static void
213 txml_print_node(topo_hdl_t *thp, FILE *fp, tnode_t *node)
214 {
215 	char inst[INT32BUFSZ];
216 	topo_pgroup_t *pg;
217 
218 	(void) snprintf(inst, INT32BUFSZ, "%d", node->tn_instance);
219 	begin_element(fp, Node, Instance, inst, Static, True, NULL);
220 	for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
221 	    pg = topo_list_next(pg)) {
222 		txml_print_pgroup(thp, fp, pg);
223 	}
224 	txml_print_dependents(thp, fp, node);
225 	end_element(fp, Node);
226 
227 }
228 
229 static int
230 txml_print_range(topo_hdl_t *thp, FILE *fp, tnode_t *node, int dependent)
231 {
232 	int i, create = 0, ret = 0;
233 	topo_nodehash_t *nhp;
234 	char min[INT32BUFSZ], max[INT32BUFSZ];
235 
236 	for (nhp = topo_list_next(&node->tn_children); nhp != NULL;
237 	    nhp = topo_list_next(nhp)) {
238 		(void) snprintf(min, INT32BUFSZ, "%d", nhp->th_range.tr_min);
239 		(void) snprintf(max, INT32BUFSZ, "%d", nhp->th_range.tr_max);
240 
241 		/*
242 		 * Some enumerators create empty ranges: make sure there
243 		 * are real nodes before creating this range
244 		 */
245 		for (i = 0; i < nhp->th_arrlen; ++i) {
246 			if (nhp->th_nodearr[i] != NULL)
247 				++create;
248 		}
249 		if (!create)
250 			continue;
251 
252 		if (dependent) {
253 			begin_element(fp, Dependents, Grouping, Children, NULL);
254 			dependent = 0;
255 			ret = 1;
256 		}
257 		begin_element(fp, Range, Name, nhp->th_name, Min, min, Max,
258 		    max, NULL);
259 		for (i = 0; i < nhp->th_arrlen; ++i) {
260 			if (nhp->th_nodearr[i] != NULL)
261 				txml_print_node(thp, fp, nhp->th_nodearr[i]);
262 		}
263 		end_element(fp, Range);
264 	}
265 
266 	return (ret);
267 }
268 
269 static void
270 txml_print_topology(topo_hdl_t *thp, FILE *fp, char *scheme, tnode_t *node)
271 {
272 	begin_element(fp, Topology, Name, thp->th_product, Scheme, scheme,
273 	    NULL);
274 	(void) txml_print_range(thp, fp, node, 0);
275 	end_element(fp, Topology);
276 
277 }
278 
279 int
280 topo_xml_print(topo_hdl_t *thp,  FILE *fp, const char *scheme, int *err)
281 {
282 	ttree_t *tp;
283 
284 	print_header(fp);
285 	for (tp = topo_list_next(&thp->th_trees); tp != NULL;
286 	    tp = topo_list_next(tp)) {
287 		if (strcmp(scheme, tp->tt_scheme) == 0) {
288 			txml_print_topology(thp, fp, tp->tt_scheme,
289 			    tp->tt_root);
290 			return (0);
291 		}
292 	}
293 
294 	*err = EINVAL;
295 	return (-1);
296 }
297