1*c5591576SRob Johnston /*
2*c5591576SRob Johnston  * This file and its contents are supplied under the terms of the
3*c5591576SRob Johnston  * Common Development and Distribution License ("CDDL"), version 1.0.
4*c5591576SRob Johnston  * You may only use this file in accordance with the terms of version
5*c5591576SRob Johnston  * 1.0 of the CDDL.
6*c5591576SRob Johnston  *
7*c5591576SRob Johnston  * A full copy of the text of the CDDL should have accompanied this
8*c5591576SRob Johnston  * source.  A copy of the CDDL is also available via the Internet at
9*c5591576SRob Johnston  * http://www.illumos.org/license/CDDL.
10*c5591576SRob Johnston  */
11*c5591576SRob Johnston 
12*c5591576SRob Johnston /*
13*c5591576SRob Johnston  * Copyright 2020 Joyent, Inc.
14*c5591576SRob Johnston  */
15*c5591576SRob Johnston 
16*c5591576SRob Johnston /*
17*c5591576SRob Johnston  * This file implements the following two routines for serializing and
18*c5591576SRob Johnston  * deserializing digraphs to/from XML, respectively:
19*c5591576SRob Johnston  *
20*c5591576SRob Johnston  * topo_digraph_serialize()
21*c5591576SRob Johnston  * topo_digraph_deserialize()
22*c5591576SRob Johnston  *
23*c5591576SRob Johnston  * Refer to the following file for the XML schema being used:
24*c5591576SRob Johnston  * usr/src/lib/fm/topo/maps/common/digraph-topology.dtd.1
25*c5591576SRob Johnston  */
26*c5591576SRob Johnston #include <time.h>
27*c5591576SRob Johnston #include <sys/utsname.h>
28*c5591576SRob Johnston #include <libxml/parser.h>
29*c5591576SRob Johnston #include <libtopo.h>
30*c5591576SRob Johnston 
31*c5591576SRob Johnston #include <topo_digraph.h>
32*c5591576SRob Johnston #include <topo_digraph_xml.h>
33*c5591576SRob Johnston 
34*c5591576SRob Johnston #define	__STDC_FORMAT_MACROS
35*c5591576SRob Johnston #include <inttypes.h>
36*c5591576SRob Johnston 
37*c5591576SRob Johnston extern int xmlattr_to_int(topo_mod_t *, xmlNodePtr, const char *, uint64_t *);
38*c5591576SRob Johnston static int serialize_nvpair(topo_hdl_t *thp, FILE *, uint_t, const char *,
39*c5591576SRob Johnston     nvpair_t *);
40*c5591576SRob Johnston 
41*c5591576SRob Johnston static void
tdg_xml_nvstring(FILE * fp,uint_t pad,const char * name,const char * value)42*c5591576SRob Johnston tdg_xml_nvstring(FILE *fp, uint_t pad, const char *name, const char *value)
43*c5591576SRob Johnston {
44*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%s' />\n", pad, "",
45*c5591576SRob Johnston 	    TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_STRING,
46*c5591576SRob Johnston 	    TDG_XML_VALUE, value);
47*c5591576SRob Johnston }
48*c5591576SRob Johnston 
49*c5591576SRob Johnston static void
tdg_xml_nvlist(FILE * fp,uint_t pad,const char * name)50*c5591576SRob Johnston tdg_xml_nvlist(FILE *fp, uint_t pad, const char *name)
51*c5591576SRob Johnston {
52*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s'>\n", pad, "",
53*c5591576SRob Johnston 	    TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_NVLIST);
54*c5591576SRob Johnston }
55*c5591576SRob Johnston 
56*c5591576SRob Johnston static void
tdg_xml_nvuint8(FILE * fp,uint_t pad,const char * name,const uint8_t value)57*c5591576SRob Johnston tdg_xml_nvuint8(FILE *fp, uint_t pad, const char *name, const uint8_t value)
58*c5591576SRob Johnston {
59*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%u' />\n", pad, "",
60*c5591576SRob Johnston 	    TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_UINT8,
61*c5591576SRob Johnston 	    TDG_XML_VALUE, value);
62*c5591576SRob Johnston }
63*c5591576SRob Johnston 
64*c5591576SRob Johnston static void
tdg_xml_nvint8(FILE * fp,uint_t pad,const char * name,const uint8_t value)65*c5591576SRob Johnston tdg_xml_nvint8(FILE *fp, uint_t pad, const char *name, const uint8_t value)
66*c5591576SRob Johnston {
67*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%d' />\n", pad, "",
68*c5591576SRob Johnston 	    TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_INT8,
69*c5591576SRob Johnston 	    TDG_XML_VALUE, value);
70*c5591576SRob Johnston }
71*c5591576SRob Johnston 
72*c5591576SRob Johnston static void
tdg_xml_nvuint16(FILE * fp,uint_t pad,const char * name,const uint8_t value)73*c5591576SRob Johnston tdg_xml_nvuint16(FILE *fp, uint_t pad, const char *name, const uint8_t value)
74*c5591576SRob Johnston {
75*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%u' />\n", pad, "",
76*c5591576SRob Johnston 	    TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_UINT16,
77*c5591576SRob Johnston 	    TDG_XML_VALUE, value);
78*c5591576SRob Johnston }
79*c5591576SRob Johnston 
80*c5591576SRob Johnston static void
tdg_xml_nvint16(FILE * fp,uint_t pad,const char * name,const uint8_t value)81*c5591576SRob Johnston tdg_xml_nvint16(FILE *fp, uint_t pad, const char *name, const uint8_t value)
82*c5591576SRob Johnston {
83*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%d' />\n", pad, "",
84*c5591576SRob Johnston 	    TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_INT16,
85*c5591576SRob Johnston 	    TDG_XML_VALUE, value);
86*c5591576SRob Johnston }
87*c5591576SRob Johnston 
88*c5591576SRob Johnston static void
tdg_xml_nvuint32(FILE * fp,uint_t pad,const char * name,const uint32_t value)89*c5591576SRob Johnston tdg_xml_nvuint32(FILE *fp, uint_t pad, const char *name, const uint32_t value)
90*c5591576SRob Johnston {
91*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%u' />\n", pad, "",
92*c5591576SRob Johnston 	    TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_UINT32,
93*c5591576SRob Johnston 	    TDG_XML_VALUE, value);
94*c5591576SRob Johnston }
95*c5591576SRob Johnston 
96*c5591576SRob Johnston static void
tdg_xml_nvint32(FILE * fp,uint_t pad,const char * name,const int32_t value)97*c5591576SRob Johnston tdg_xml_nvint32(FILE *fp, uint_t pad, const char *name, const int32_t value)
98*c5591576SRob Johnston {
99*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%d' />\n", pad, "",
100*c5591576SRob Johnston 	    TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_UINT32,
101*c5591576SRob Johnston 	    TDG_XML_VALUE, value);
102*c5591576SRob Johnston }
103*c5591576SRob Johnston 
104*c5591576SRob Johnston static void
tdg_xml_nvuint64(FILE * fp,uint_t pad,const char * name,const uint64_t value)105*c5591576SRob Johnston tdg_xml_nvuint64(FILE *fp, uint_t pad, const char *name, const uint64_t value)
106*c5591576SRob Johnston {
107*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='0x%" PRIx64 "' />\n",
108*c5591576SRob Johnston 	    pad, "", TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE,
109*c5591576SRob Johnston 	    TDG_XML_UINT64, TDG_XML_VALUE, value);
110*c5591576SRob Johnston }
111*c5591576SRob Johnston 
112*c5591576SRob Johnston static void
tdg_xml_nvint64(FILE * fp,uint_t pad,const char * name,const int64_t value)113*c5591576SRob Johnston tdg_xml_nvint64(FILE *fp, uint_t pad, const char *name, const int64_t value)
114*c5591576SRob Johnston {
115*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%" PRIi64 "' />\n", pad,
116*c5591576SRob Johnston 	    "", TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE,
117*c5591576SRob Johnston 	    TDG_XML_UINT64, TDG_XML_VALUE, value);
118*c5591576SRob Johnston }
119*c5591576SRob Johnston 
120*c5591576SRob Johnston static void
tdg_xml_nvdbl(FILE * fp,uint_t pad,const char * name,const double value)121*c5591576SRob Johnston tdg_xml_nvdbl(FILE *fp, uint_t pad, const char *name, const double value)
122*c5591576SRob Johnston {
123*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%lf' />\n", pad, ""
124*c5591576SRob Johnston 	    TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_UINT64,
125*c5591576SRob Johnston 	    TDG_XML_VALUE, value);
126*c5591576SRob Johnston }
127*c5591576SRob Johnston 
128*c5591576SRob Johnston static void
tdg_xml_nvarray(FILE * fp,uint_t pad,const char * name,const char * type)129*c5591576SRob Johnston tdg_xml_nvarray(FILE *fp, uint_t pad, const char *name, const char *type)
130*c5591576SRob Johnston {
131*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s'>\n", pad, "",
132*c5591576SRob Johnston 	    TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, type);
133*c5591576SRob Johnston }
134*c5591576SRob Johnston 
135*c5591576SRob Johnston static void
tdg_xml_nvint32arr(FILE * fp,uint_t pad,const char * name,int32_t * val,uint_t nelems)136*c5591576SRob Johnston tdg_xml_nvint32arr(FILE *fp, uint_t pad, const char *name, int32_t *val,
137*c5591576SRob Johnston     uint_t nelems)
138*c5591576SRob Johnston {
139*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s'>\n", pad, "",
140*c5591576SRob Johnston 	    TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE,
141*c5591576SRob Johnston 	    TDG_XML_INT32_ARR);
142*c5591576SRob Johnston 
143*c5591576SRob Johnston 	for (uint_t i = 0; i < nelems; i++) {
144*c5591576SRob Johnston 		(void) fprintf(fp, "%*s<%s %s='%d' />\n", (pad + 2), "",
145*c5591576SRob Johnston 		    TDG_XML_NVPAIR, TDG_XML_VALUE, val[i]);
146*c5591576SRob Johnston 	}
147*c5591576SRob Johnston 	(void) fprintf(fp, "%*s</%s>\n", pad, "", TDG_XML_NVPAIR);
148*c5591576SRob Johnston }
149*c5591576SRob Johnston 
150*c5591576SRob Johnston static void
tdg_xml_nvuint32arr(FILE * fp,uint_t pad,const char * name,uint32_t * val,uint_t nelems)151*c5591576SRob Johnston tdg_xml_nvuint32arr(FILE *fp, uint_t pad, const char *name, uint32_t *val,
152*c5591576SRob Johnston     uint_t nelems)
153*c5591576SRob Johnston {
154*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s'>\n", pad, "",
155*c5591576SRob Johnston 	    TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE,
156*c5591576SRob Johnston 	    TDG_XML_UINT32_ARR);
157*c5591576SRob Johnston 
158*c5591576SRob Johnston 	for (uint_t i = 0; i < nelems; i++) {
159*c5591576SRob Johnston 		(void) fprintf(fp, "%*s<%s %s='%d' />\n", (pad + 2), "",
160*c5591576SRob Johnston 		    TDG_XML_NVPAIR, TDG_XML_VALUE, val[i]);
161*c5591576SRob Johnston 	}
162*c5591576SRob Johnston 	(void) fprintf(fp, "%*s</%s>\n", pad, "", TDG_XML_NVPAIR);
163*c5591576SRob Johnston }
164*c5591576SRob Johnston 
165*c5591576SRob Johnston static void
tdg_xml_nvint64arr(FILE * fp,uint_t pad,const char * name,int64_t * val,uint_t nelems)166*c5591576SRob Johnston tdg_xml_nvint64arr(FILE *fp, uint_t pad, const char *name, int64_t *val,
167*c5591576SRob Johnston     uint_t nelems)
168*c5591576SRob Johnston {
169*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s'>\n", pad, "",
170*c5591576SRob Johnston 	    TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE,
171*c5591576SRob Johnston 	    TDG_XML_INT64_ARR);
172*c5591576SRob Johnston 
173*c5591576SRob Johnston 	for (uint_t i = 0; i < nelems; i++) {
174*c5591576SRob Johnston 		(void) fprintf(fp, "%*s<%s %s='%" PRIi64 "' />\n", (pad + 2),
175*c5591576SRob Johnston 		    "", TDG_XML_NVPAIR, TDG_XML_VALUE, val[i]);
176*c5591576SRob Johnston 	}
177*c5591576SRob Johnston 	(void) fprintf(fp, "%*s</%s>\n", pad, "", TDG_XML_NVPAIR);
178*c5591576SRob Johnston }
179*c5591576SRob Johnston 
180*c5591576SRob Johnston static void
tdg_xml_nvuint64arr(FILE * fp,uint_t pad,const char * name,uint64_t * val,uint_t nelems)181*c5591576SRob Johnston tdg_xml_nvuint64arr(FILE *fp, uint_t pad, const char *name, uint64_t *val,
182*c5591576SRob Johnston     uint_t nelems)
183*c5591576SRob Johnston {
184*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' %s='%s'>\n", pad, "",
185*c5591576SRob Johnston 	    TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE,
186*c5591576SRob Johnston 	    TDG_XML_UINT64_ARR);
187*c5591576SRob Johnston 
188*c5591576SRob Johnston 	for (uint_t i = 0; i < nelems; i++) {
189*c5591576SRob Johnston 		(void) fprintf(fp, "%*s<%s %s='0x%" PRIx64 "' />\n", (pad + 2),
190*c5591576SRob Johnston 		    "", TDG_XML_NVPAIR, TDG_XML_VALUE, val[i]);
191*c5591576SRob Johnston 	}
192*c5591576SRob Johnston 	(void) fprintf(fp, "%*s</%s>\n", pad, "", TDG_XML_NVPAIR);
193*c5591576SRob Johnston }
194*c5591576SRob Johnston 
195*c5591576SRob Johnston static int
serialize_nvpair_nvlist(topo_hdl_t * thp,FILE * fp,uint_t pad,const char * name,nvlist_t * nvl)196*c5591576SRob Johnston serialize_nvpair_nvlist(topo_hdl_t *thp, FILE *fp, uint_t pad,
197*c5591576SRob Johnston     const char *name, nvlist_t *nvl)
198*c5591576SRob Johnston {
199*c5591576SRob Johnston 	nvpair_t *elem = NULL;
200*c5591576SRob Johnston 
201*c5591576SRob Johnston 	tdg_xml_nvlist(fp, pad, name);
202*c5591576SRob Johnston 
203*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s>\n", pad, "", TDG_XML_NVLIST);
204*c5591576SRob Johnston 
205*c5591576SRob Johnston 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
206*c5591576SRob Johnston 		char *nvname = nvpair_name(elem);
207*c5591576SRob Johnston 
208*c5591576SRob Johnston 		if (serialize_nvpair(thp, fp, (pad + 2), nvname, elem) != 0) {
209*c5591576SRob Johnston 			/* errno set */
210*c5591576SRob Johnston 			return (-1);
211*c5591576SRob Johnston 		}
212*c5591576SRob Johnston 	}
213*c5591576SRob Johnston 
214*c5591576SRob Johnston 	(void) fprintf(fp, "%*s</%s>\n", pad, "", TDG_XML_NVLIST);
215*c5591576SRob Johnston 	(void) fprintf(fp, "%*s</%s> <!-- %s -->\n", pad, "", TDG_XML_NVPAIR,
216*c5591576SRob Johnston 	    name);
217*c5591576SRob Johnston 
218*c5591576SRob Johnston 	return (0);
219*c5591576SRob Johnston }
220*c5591576SRob Johnston 
221*c5591576SRob Johnston static int
serialize_nvpair(topo_hdl_t * thp,FILE * fp,uint_t pad,const char * pname,nvpair_t * nvp)222*c5591576SRob Johnston serialize_nvpair(topo_hdl_t *thp, FILE *fp, uint_t pad, const char *pname,
223*c5591576SRob Johnston     nvpair_t *nvp)
224*c5591576SRob Johnston {
225*c5591576SRob Johnston 	data_type_t type = nvpair_type(nvp);
226*c5591576SRob Johnston 
227*c5591576SRob Johnston 	switch (type) {
228*c5591576SRob Johnston 		case DATA_TYPE_INT8: {
229*c5591576SRob Johnston 			int8_t val;
230*c5591576SRob Johnston 
231*c5591576SRob Johnston 			if (nvpair_value_int8(nvp, &val) != 0)
232*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
233*c5591576SRob Johnston 
234*c5591576SRob Johnston 			tdg_xml_nvint8(fp, pad, pname, val);
235*c5591576SRob Johnston 			break;
236*c5591576SRob Johnston 		}
237*c5591576SRob Johnston 		case DATA_TYPE_UINT8: {
238*c5591576SRob Johnston 			uint8_t val;
239*c5591576SRob Johnston 
240*c5591576SRob Johnston 			if (nvpair_value_uint8(nvp, &val) != 0)
241*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
242*c5591576SRob Johnston 
243*c5591576SRob Johnston 			tdg_xml_nvuint8(fp, pad, pname, val);
244*c5591576SRob Johnston 			break;
245*c5591576SRob Johnston 		}
246*c5591576SRob Johnston 		case DATA_TYPE_INT16: {
247*c5591576SRob Johnston 			int16_t val;
248*c5591576SRob Johnston 
249*c5591576SRob Johnston 			if (nvpair_value_int16(nvp, &val) != 0)
250*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
251*c5591576SRob Johnston 
252*c5591576SRob Johnston 			tdg_xml_nvint16(fp, pad, pname, val);
253*c5591576SRob Johnston 			break;
254*c5591576SRob Johnston 		}
255*c5591576SRob Johnston 		case DATA_TYPE_UINT16: {
256*c5591576SRob Johnston 			uint16_t val;
257*c5591576SRob Johnston 
258*c5591576SRob Johnston 			if (nvpair_value_uint16(nvp, &val) != 0)
259*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
260*c5591576SRob Johnston 
261*c5591576SRob Johnston 			tdg_xml_nvuint16(fp, pad, pname, val);
262*c5591576SRob Johnston 			break;
263*c5591576SRob Johnston 		}
264*c5591576SRob Johnston 		case DATA_TYPE_INT32: {
265*c5591576SRob Johnston 			int32_t val;
266*c5591576SRob Johnston 
267*c5591576SRob Johnston 			if (nvpair_value_int32(nvp, &val) != 0)
268*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
269*c5591576SRob Johnston 
270*c5591576SRob Johnston 			tdg_xml_nvint32(fp, pad, pname, val);
271*c5591576SRob Johnston 			break;
272*c5591576SRob Johnston 		}
273*c5591576SRob Johnston 		case DATA_TYPE_UINT32: {
274*c5591576SRob Johnston 			uint32_t val;
275*c5591576SRob Johnston 
276*c5591576SRob Johnston 			if (nvpair_value_uint32(nvp, &val) != 0)
277*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
278*c5591576SRob Johnston 
279*c5591576SRob Johnston 			tdg_xml_nvuint32(fp, pad, pname, val);
280*c5591576SRob Johnston 			break;
281*c5591576SRob Johnston 		}
282*c5591576SRob Johnston 		case DATA_TYPE_INT64: {
283*c5591576SRob Johnston 			int64_t val;
284*c5591576SRob Johnston 
285*c5591576SRob Johnston 			if (nvpair_value_int64(nvp, &val) != 0)
286*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
287*c5591576SRob Johnston 
288*c5591576SRob Johnston 			tdg_xml_nvint64(fp, pad, pname, val);
289*c5591576SRob Johnston 			break;
290*c5591576SRob Johnston 		}
291*c5591576SRob Johnston 		case DATA_TYPE_UINT64: {
292*c5591576SRob Johnston 			uint64_t val;
293*c5591576SRob Johnston 
294*c5591576SRob Johnston 			if (nvpair_value_uint64(nvp, &val) != 0)
295*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
296*c5591576SRob Johnston 
297*c5591576SRob Johnston 			tdg_xml_nvuint64(fp, pad, pname, val);
298*c5591576SRob Johnston 			break;
299*c5591576SRob Johnston 		}
300*c5591576SRob Johnston 		case DATA_TYPE_DOUBLE: {
301*c5591576SRob Johnston 			double val;
302*c5591576SRob Johnston 
303*c5591576SRob Johnston 			if (nvpair_value_double(nvp, &val) != 0)
304*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
305*c5591576SRob Johnston 
306*c5591576SRob Johnston 			tdg_xml_nvdbl(fp, pad, pname, val);
307*c5591576SRob Johnston 			break;
308*c5591576SRob Johnston 		}
309*c5591576SRob Johnston 		case DATA_TYPE_STRING: {
310*c5591576SRob Johnston 			char *val;
311*c5591576SRob Johnston 
312*c5591576SRob Johnston 			if (nvpair_value_string(nvp, &val) != 0)
313*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
314*c5591576SRob Johnston 
315*c5591576SRob Johnston 			tdg_xml_nvstring(fp, pad, pname, val);
316*c5591576SRob Johnston 			break;
317*c5591576SRob Johnston 		}
318*c5591576SRob Johnston 		case DATA_TYPE_NVLIST: {
319*c5591576SRob Johnston 			nvlist_t *nvl;
320*c5591576SRob Johnston 
321*c5591576SRob Johnston 			if (nvpair_value_nvlist(nvp, &nvl) != 0)
322*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
323*c5591576SRob Johnston 
324*c5591576SRob Johnston 			if (serialize_nvpair_nvlist(thp, fp, pad + 2, pname,
325*c5591576SRob Johnston 			    nvl) != 0) {
326*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
327*c5591576SRob Johnston 			}
328*c5591576SRob Johnston 			break;
329*c5591576SRob Johnston 		}
330*c5591576SRob Johnston 		case DATA_TYPE_INT32_ARRAY: {
331*c5591576SRob Johnston 			uint_t nelems;
332*c5591576SRob Johnston 			int32_t *val;
333*c5591576SRob Johnston 
334*c5591576SRob Johnston 			if (nvpair_value_int32_array(nvp, &val, &nelems) != 0)
335*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
336*c5591576SRob Johnston 
337*c5591576SRob Johnston 			tdg_xml_nvint32arr(fp, pad + 2, pname, val, nelems);
338*c5591576SRob Johnston 
339*c5591576SRob Johnston 			break;
340*c5591576SRob Johnston 		}
341*c5591576SRob Johnston 		case DATA_TYPE_UINT32_ARRAY: {
342*c5591576SRob Johnston 			uint_t nelems;
343*c5591576SRob Johnston 			uint32_t *val;
344*c5591576SRob Johnston 
345*c5591576SRob Johnston 			if (nvpair_value_uint32_array(nvp, &val, &nelems) != 0)
346*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
347*c5591576SRob Johnston 
348*c5591576SRob Johnston 			tdg_xml_nvuint32arr(fp, pad + 2, pname,  val, nelems);
349*c5591576SRob Johnston 
350*c5591576SRob Johnston 			break;
351*c5591576SRob Johnston 		}
352*c5591576SRob Johnston 		case DATA_TYPE_INT64_ARRAY: {
353*c5591576SRob Johnston 			uint_t nelems;
354*c5591576SRob Johnston 			int64_t *val;
355*c5591576SRob Johnston 
356*c5591576SRob Johnston 			if (nvpair_value_int64_array(nvp, &val, &nelems) != 0)
357*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
358*c5591576SRob Johnston 
359*c5591576SRob Johnston 			tdg_xml_nvint64arr(fp, pad + 2, pname,  val, nelems);
360*c5591576SRob Johnston 
361*c5591576SRob Johnston 			break;
362*c5591576SRob Johnston 		}
363*c5591576SRob Johnston 		case DATA_TYPE_UINT64_ARRAY: {
364*c5591576SRob Johnston 			uint_t nelems;
365*c5591576SRob Johnston 			uint64_t *val;
366*c5591576SRob Johnston 
367*c5591576SRob Johnston 			if (nvpair_value_uint64_array(nvp, &val, &nelems) != 0)
368*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
369*c5591576SRob Johnston 
370*c5591576SRob Johnston 			tdg_xml_nvuint64arr(fp, pad + 2, pname,  val, nelems);
371*c5591576SRob Johnston 
372*c5591576SRob Johnston 			break;
373*c5591576SRob Johnston 		}
374*c5591576SRob Johnston 		case DATA_TYPE_STRING_ARRAY: {
375*c5591576SRob Johnston 			uint_t nelems;
376*c5591576SRob Johnston 			char **val;
377*c5591576SRob Johnston 
378*c5591576SRob Johnston 			if (nvpair_value_string_array(nvp, &val, &nelems) != 0)
379*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
380*c5591576SRob Johnston 
381*c5591576SRob Johnston 			tdg_xml_nvarray(fp, pad, pname, TDG_XML_STRING_ARR);
382*c5591576SRob Johnston 			for (uint_t i = 0; i < nelems; i++) {
383*c5591576SRob Johnston 				(void) fprintf(fp, "%*s<%s %s='%s' />\n",
384*c5591576SRob Johnston 				    (pad + 2), "", TDG_XML_NVPAIR,
385*c5591576SRob Johnston 				    TDG_XML_VALUE, val[i]);
386*c5591576SRob Johnston 			}
387*c5591576SRob Johnston 			(void) fprintf(fp, "%*s</%s>\n", (pad + 2), "",
388*c5591576SRob Johnston 			    TDG_XML_NVPAIR);
389*c5591576SRob Johnston 
390*c5591576SRob Johnston 			break;
391*c5591576SRob Johnston 		}
392*c5591576SRob Johnston 		case DATA_TYPE_NVLIST_ARRAY: {
393*c5591576SRob Johnston 			uint_t nelems;
394*c5591576SRob Johnston 			nvlist_t **val;
395*c5591576SRob Johnston 
396*c5591576SRob Johnston 			if (nvpair_value_nvlist_array(nvp, &val, &nelems) != 0)
397*c5591576SRob Johnston 				return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
398*c5591576SRob Johnston 
399*c5591576SRob Johnston 			tdg_xml_nvarray(fp, pad, pname, TDG_XML_NVLIST_ARR);
400*c5591576SRob Johnston 			for (uint_t i = 0; i < nelems; i++) {
401*c5591576SRob Johnston 				nvpair_t *elem = NULL;
402*c5591576SRob Johnston 
403*c5591576SRob Johnston 				(void) fprintf(fp, "%*s<%s>\n", (pad + 2), "",
404*c5591576SRob Johnston 				    TDG_XML_NVLIST);
405*c5591576SRob Johnston 
406*c5591576SRob Johnston 				while ((elem = nvlist_next_nvpair(val[i],
407*c5591576SRob Johnston 				    elem)) != NULL) {
408*c5591576SRob Johnston 					char *nvname = nvpair_name(elem);
409*c5591576SRob Johnston 
410*c5591576SRob Johnston 					if (serialize_nvpair(thp, fp,
411*c5591576SRob Johnston 					    (pad + 4), nvname, elem) != 0) {
412*c5591576SRob Johnston 						/* errno set */
413*c5591576SRob Johnston 						return (-1);
414*c5591576SRob Johnston 					}
415*c5591576SRob Johnston 				}
416*c5591576SRob Johnston 
417*c5591576SRob Johnston 				(void) fprintf(fp, "%*s</%s>\n", (pad + 2), "",
418*c5591576SRob Johnston 				    TDG_XML_NVLIST);
419*c5591576SRob Johnston 			}
420*c5591576SRob Johnston 			(void) fprintf(fp, "%*s</%s>\n", pad, "",
421*c5591576SRob Johnston 			    TDG_XML_NVPAIR);
422*c5591576SRob Johnston 
423*c5591576SRob Johnston 			break;
424*c5591576SRob Johnston 		}
425*c5591576SRob Johnston 		default:
426*c5591576SRob Johnston 			topo_dprintf(thp, TOPO_DBG_XML, "Invalid nvpair data "
427*c5591576SRob Johnston 			    "type: %d\n", type);
428*c5591576SRob Johnston 			(void) topo_hdl_seterrno(thp, ETOPO_MOD_XENUM);
429*c5591576SRob Johnston 			return (-1);
430*c5591576SRob Johnston 	}
431*c5591576SRob Johnston 	return (0);
432*c5591576SRob Johnston }
433*c5591576SRob Johnston 
434*c5591576SRob Johnston static int
serialize_edge(topo_hdl_t * thp,topo_edge_t * edge,boolean_t last_edge,void * arg)435*c5591576SRob Johnston serialize_edge(topo_hdl_t *thp, topo_edge_t *edge, boolean_t last_edge,
436*c5591576SRob Johnston     void *arg)
437*c5591576SRob Johnston {
438*c5591576SRob Johnston 	nvlist_t *fmri = NULL;
439*c5591576SRob Johnston 	char *fmristr;
440*c5591576SRob Johnston 	int err;
441*c5591576SRob Johnston 	tnode_t *tn;
442*c5591576SRob Johnston 	FILE *fp = (FILE *)arg;
443*c5591576SRob Johnston 
444*c5591576SRob Johnston 	tn = topo_vertex_node(edge->tve_vertex);
445*c5591576SRob Johnston 	if (topo_node_resource(tn, &fmri, &err) != 0 ||
446*c5591576SRob Johnston 	    topo_fmri_nvl2str(thp, fmri, &fmristr, &err) != 0) {
447*c5591576SRob Johnston 		/* errno set */
448*c5591576SRob Johnston 		nvlist_free(fmri);
449*c5591576SRob Johnston 		return (TOPO_WALK_ERR);
450*c5591576SRob Johnston 	}
451*c5591576SRob Johnston 	nvlist_free(fmri);
452*c5591576SRob Johnston 
453*c5591576SRob Johnston 	(void) fprintf(fp, "%*s<%s %s='%s' />\n", 4, "", TDG_XML_EDGE,
454*c5591576SRob Johnston 	    TDG_XML_FMRI, fmristr);
455*c5591576SRob Johnston 	topo_hdl_strfree(thp, fmristr);
456*c5591576SRob Johnston 
457*c5591576SRob Johnston 	return (TOPO_WALK_NEXT);
458*c5591576SRob Johnston }
459*c5591576SRob Johnston 
460*c5591576SRob Johnston /*
461*c5591576SRob Johnston  * Some node property values aren't available unless we go through the libtopo
462*c5591576SRob Johnston  * API's topo_prop_get_* routines. We do that here to make sure the nodes have
463*c5591576SRob Johnston  * all of their properties populated, then we vector off to type-specific
464*c5591576SRob Johnston  * XML serialization functions.
465*c5591576SRob Johnston  */
466*c5591576SRob Johnston static int
serialize_property(topo_hdl_t * thp,FILE * fp,uint_t pad,tnode_t * tn,topo_propval_t * pv,const char * pgname)467*c5591576SRob Johnston serialize_property(topo_hdl_t *thp, FILE *fp, uint_t pad, tnode_t *tn,
468*c5591576SRob Johnston     topo_propval_t *pv, const char *pgname)
469*c5591576SRob Johnston {
470*c5591576SRob Johnston 	topo_type_t type = pv->tp_type;
471*c5591576SRob Johnston 	const char *pname = pv->tp_name;
472*c5591576SRob Johnston 	int err;
473*c5591576SRob Johnston 	char *name = TDG_XML_PROP_VALUE;
474*c5591576SRob Johnston 
475*c5591576SRob Johnston 	switch (type) {
476*c5591576SRob Johnston 		case TOPO_TYPE_INT32: {
477*c5591576SRob Johnston 			int32_t val;
478*c5591576SRob Johnston 
479*c5591576SRob Johnston 			if (topo_prop_get_int32(tn, pgname, pname, &val,
480*c5591576SRob Johnston 			    &err) != 0)
481*c5591576SRob Johnston 				return (-1);
482*c5591576SRob Johnston 
483*c5591576SRob Johnston 			tdg_xml_nvint32(fp, pad, name, val);
484*c5591576SRob Johnston 			break;
485*c5591576SRob Johnston 		}
486*c5591576SRob Johnston 		case TOPO_TYPE_UINT32: {
487*c5591576SRob Johnston 			uint32_t val;
488*c5591576SRob Johnston 
489*c5591576SRob Johnston 			if (topo_prop_get_uint32(tn, pgname, pname, &val,
490*c5591576SRob Johnston 			    &err) != 0)
491*c5591576SRob Johnston 				return (-1);
492*c5591576SRob Johnston 
493*c5591576SRob Johnston 			tdg_xml_nvuint32(fp, pad, name, val);
494*c5591576SRob Johnston 			break;
495*c5591576SRob Johnston 		}
496*c5591576SRob Johnston 		case TOPO_TYPE_INT64: {
497*c5591576SRob Johnston 			int64_t val;
498*c5591576SRob Johnston 
499*c5591576SRob Johnston 			if (topo_prop_get_int64(tn, pgname, pname, &val,
500*c5591576SRob Johnston 			    &err) != 0)
501*c5591576SRob Johnston 				return (-1);
502*c5591576SRob Johnston 
503*c5591576SRob Johnston 			tdg_xml_nvint64(fp, pad, name, val);
504*c5591576SRob Johnston 			break;
505*c5591576SRob Johnston 		}
506*c5591576SRob Johnston 		case TOPO_TYPE_UINT64: {
507*c5591576SRob Johnston 			uint64_t val;
508*c5591576SRob Johnston 
509*c5591576SRob Johnston 			if (topo_prop_get_uint64(tn, pgname, pname, &val,
510*c5591576SRob Johnston 			    &err) != 0)
511*c5591576SRob Johnston 				return (-1);
512*c5591576SRob Johnston 
513*c5591576SRob Johnston 			tdg_xml_nvuint64(fp, pad, name, val);
514*c5591576SRob Johnston 			break;
515*c5591576SRob Johnston 		}
516*c5591576SRob Johnston 		case TOPO_TYPE_STRING: {
517*c5591576SRob Johnston 			char *val;
518*c5591576SRob Johnston 
519*c5591576SRob Johnston 			if (topo_prop_get_string(tn, pgname, pname, &val,
520*c5591576SRob Johnston 			    &err) != 0)
521*c5591576SRob Johnston 				return (-1);
522*c5591576SRob Johnston 
523*c5591576SRob Johnston 			tdg_xml_nvstring(fp, pad, name, val);
524*c5591576SRob Johnston 
525*c5591576SRob Johnston 			topo_hdl_strfree(thp, val);
526*c5591576SRob Johnston 			break;
527*c5591576SRob Johnston 		}
528*c5591576SRob Johnston 		case TOPO_TYPE_FMRI: {
529*c5591576SRob Johnston 			nvlist_t *nvl;
530*c5591576SRob Johnston 
531*c5591576SRob Johnston 			if (topo_prop_get_fmri(tn, pgname, pname, &nvl,
532*c5591576SRob Johnston 			    &err) != 0)
533*c5591576SRob Johnston 				return (-1);
534*c5591576SRob Johnston 
535*c5591576SRob Johnston 			if (serialize_nvpair_nvlist(thp, fp, pad + 2, name,
536*c5591576SRob Johnston 			    nvl) != 0) {
537*c5591576SRob Johnston 				nvlist_free(nvl);
538*c5591576SRob Johnston 				return (-1);
539*c5591576SRob Johnston 			}
540*c5591576SRob Johnston 
541*c5591576SRob Johnston 			nvlist_free(nvl);
542*c5591576SRob Johnston 			break;
543*c5591576SRob Johnston 		}
544*c5591576SRob Johnston 		case TOPO_TYPE_INT32_ARRAY: {
545*c5591576SRob Johnston 			uint_t nelems;
546*c5591576SRob Johnston 			int32_t *val;
547*c5591576SRob Johnston 
548*c5591576SRob Johnston 			if (topo_prop_get_int32_array(tn, pgname, pname, &val,
549*c5591576SRob Johnston 			    &nelems, &err) != 0)
550*c5591576SRob Johnston 				return (-1);
551*c5591576SRob Johnston 
552*c5591576SRob Johnston 			tdg_xml_nvint32arr(fp, pad, pname, val, nelems);
553*c5591576SRob Johnston 			topo_hdl_free(thp, val, (sizeof (int32_t) * nelems));
554*c5591576SRob Johnston 			break;
555*c5591576SRob Johnston 		}
556*c5591576SRob Johnston 		case TOPO_TYPE_UINT32_ARRAY: {
557*c5591576SRob Johnston 			uint_t nelems;
558*c5591576SRob Johnston 			uint32_t *val;
559*c5591576SRob Johnston 
560*c5591576SRob Johnston 			if (topo_prop_get_uint32_array(tn, pgname, pname, &val,
561*c5591576SRob Johnston 			    &nelems, &err) != 0)
562*c5591576SRob Johnston 				return (-1);
563*c5591576SRob Johnston 
564*c5591576SRob Johnston 			tdg_xml_nvuint32arr(fp, pad, pname,  val, nelems);
565*c5591576SRob Johnston 			topo_hdl_free(thp, val, (sizeof (uint32_t) * nelems));
566*c5591576SRob Johnston 			break;
567*c5591576SRob Johnston 		}
568*c5591576SRob Johnston 		case TOPO_TYPE_INT64_ARRAY: {
569*c5591576SRob Johnston 			uint_t nelems;
570*c5591576SRob Johnston 			int64_t *val;
571*c5591576SRob Johnston 
572*c5591576SRob Johnston 			if (topo_prop_get_int64_array(tn, pgname, pname, &val,
573*c5591576SRob Johnston 			    &nelems, &err) != 0)
574*c5591576SRob Johnston 				return (-1);
575*c5591576SRob Johnston 
576*c5591576SRob Johnston 			tdg_xml_nvint64arr(fp, pad, pname,  val, nelems);
577*c5591576SRob Johnston 			topo_hdl_free(thp, val, (sizeof (int64_t) * nelems));
578*c5591576SRob Johnston 			break;
579*c5591576SRob Johnston 		}
580*c5591576SRob Johnston 		case TOPO_TYPE_UINT64_ARRAY: {
581*c5591576SRob Johnston 			uint_t nelems;
582*c5591576SRob Johnston 			uint64_t *val;
583*c5591576SRob Johnston 
584*c5591576SRob Johnston 			if (topo_prop_get_uint64_array(tn, pgname, pname, &val,
585*c5591576SRob Johnston 			    &nelems, &err) != 0)
586*c5591576SRob Johnston 				return (-1);
587*c5591576SRob Johnston 
588*c5591576SRob Johnston 			tdg_xml_nvuint64arr(fp, pad, pname,  val, nelems);
589*c5591576SRob Johnston 			topo_hdl_free(thp, val, (sizeof (uint64_t) * nelems));
590*c5591576SRob Johnston 			break;
591*c5591576SRob Johnston 		}
592*c5591576SRob Johnston 		default:
593*c5591576SRob Johnston 			topo_dprintf(thp, TOPO_DBG_XML, "Invalid nvpair data "
594*c5591576SRob Johnston 			    "type: %d\n", type);
595*c5591576SRob Johnston 			(void) topo_hdl_seterrno(thp, ETOPO_MOD_XENUM);
596*c5591576SRob Johnston 			return (-1);
597*c5591576SRob Johnston 	}
598*c5591576SRob Johnston 	return (0);
599*c5591576SRob Johnston }
600*c5591576SRob Johnston 
601*c5591576SRob Johnston static int
serialize_pgroups(topo_hdl_t * thp,FILE * fp,tnode_t * tn)602*c5591576SRob Johnston serialize_pgroups(topo_hdl_t *thp, FILE *fp, tnode_t *tn)
603*c5591576SRob Johnston {
604*c5591576SRob Johnston 	topo_pgroup_t *pg;
605*c5591576SRob Johnston 	uint_t npgs = 0;
606*c5591576SRob Johnston 
607*c5591576SRob Johnston 	for (pg = topo_list_next(&tn->tn_pgroups); pg != NULL;
608*c5591576SRob Johnston 	    pg = topo_list_next(pg)) {
609*c5591576SRob Johnston 
610*c5591576SRob Johnston 		npgs++;
611*c5591576SRob Johnston 	}
612*c5591576SRob Johnston 
613*c5591576SRob Johnston 	tdg_xml_nvarray(fp, 2, TDG_XML_PGROUPS, TDG_XML_NVLIST_ARR);
614*c5591576SRob Johnston 
615*c5591576SRob Johnston 	for (pg = topo_list_next(&tn->tn_pgroups); pg != NULL;
616*c5591576SRob Johnston 	    pg = topo_list_next(pg)) {
617*c5591576SRob Johnston 
618*c5591576SRob Johnston 		topo_proplist_t *pvl;
619*c5591576SRob Johnston 		uint_t nprops = 0;
620*c5591576SRob Johnston 
621*c5591576SRob Johnston 		(void) fprintf(fp, "%*s<%s>\n", 4, "", TDG_XML_NVLIST);
622*c5591576SRob Johnston 		tdg_xml_nvstring(fp, 6, TOPO_PROP_GROUP_NAME,
623*c5591576SRob Johnston 		    pg->tpg_info->tpi_name);
624*c5591576SRob Johnston 
625*c5591576SRob Johnston 		for (pvl = topo_list_next(&pg->tpg_pvals); pvl != NULL;
626*c5591576SRob Johnston 		    pvl = topo_list_next(pvl))
627*c5591576SRob Johnston 			nprops++;
628*c5591576SRob Johnston 
629*c5591576SRob Johnston 		tdg_xml_nvarray(fp, 6, TDG_XML_PVALS, TDG_XML_NVLIST_ARR);
630*c5591576SRob Johnston 
631*c5591576SRob Johnston 		for (pvl = topo_list_next(&pg->tpg_pvals); pvl != NULL;
632*c5591576SRob Johnston 		    pvl = topo_list_next(pvl)) {
633*c5591576SRob Johnston 
634*c5591576SRob Johnston 			topo_propval_t *pv = pvl->tp_pval;
635*c5591576SRob Johnston 
636*c5591576SRob Johnston 			(void) fprintf(fp, "%*s<%s>\n", 8, "", TDG_XML_NVLIST);
637*c5591576SRob Johnston 			tdg_xml_nvstring(fp, 10, TDG_XML_PROP_NAME,
638*c5591576SRob Johnston 			    pv->tp_name);
639*c5591576SRob Johnston 			tdg_xml_nvuint32(fp, 10, TDG_XML_PROP_TYPE,
640*c5591576SRob Johnston 			    pv->tp_type);
641*c5591576SRob Johnston 
642*c5591576SRob Johnston 			if (serialize_property(thp, fp, 10, tn, pv,
643*c5591576SRob Johnston 			    pg->tpg_info->tpi_name) != 0) {
644*c5591576SRob Johnston 				/* errno set */
645*c5591576SRob Johnston 				return (-1);
646*c5591576SRob Johnston 			}
647*c5591576SRob Johnston 			(void) fprintf(fp, "%*s</%s>\n", 8, "",
648*c5591576SRob Johnston 			    TDG_XML_NVLIST);
649*c5591576SRob Johnston 		}
650*c5591576SRob Johnston 
651*c5591576SRob Johnston 		(void) fprintf(fp, "%*s</%s> <!-- %s -->\n", 6, "",
652*c5591576SRob Johnston 		    TDG_XML_NVPAIR, TDG_XML_PVALS);
653*c5591576SRob Johnston 		(void) fprintf(fp, "%*s</%s>\n", 4, "", TDG_XML_NVLIST);
654*c5591576SRob Johnston 	}
655*c5591576SRob Johnston 	(void) fprintf(fp, "%*s</%s> <!-- %s -->\n", 2, "", TDG_XML_NVPAIR,
656*c5591576SRob Johnston 	    TDG_XML_PGROUPS);
657*c5591576SRob Johnston 
658*c5591576SRob Johnston 	return (0);
659*c5591576SRob Johnston }
660*c5591576SRob Johnston 
661*c5591576SRob Johnston static int
serialize_vertex(topo_hdl_t * thp,topo_vertex_t * vtx,boolean_t last_vtx,void * arg)662*c5591576SRob Johnston serialize_vertex(topo_hdl_t *thp, topo_vertex_t *vtx, boolean_t last_vtx,
663*c5591576SRob Johnston     void *arg)
664*c5591576SRob Johnston {
665*c5591576SRob Johnston 	nvlist_t *fmri = NULL;
666*c5591576SRob Johnston 	char *fmristr;
667*c5591576SRob Johnston 	tnode_t *tn;
668*c5591576SRob Johnston 	int err;
669*c5591576SRob Johnston 	FILE *fp = (FILE *)arg;
670*c5591576SRob Johnston 
671*c5591576SRob Johnston 	tn = topo_vertex_node(vtx);
672*c5591576SRob Johnston 	if (topo_node_resource(tn, &fmri, &err) != 0 ||
673*c5591576SRob Johnston 	    topo_fmri_nvl2str(thp, fmri, &fmristr, &err) != 0) {
674*c5591576SRob Johnston 		/* errno set */
675*c5591576SRob Johnston 		nvlist_free(fmri);
676*c5591576SRob Johnston 		return (TOPO_WALK_ERR);
677*c5591576SRob Johnston 	}
678*c5591576SRob Johnston 	nvlist_free(fmri);
679*c5591576SRob Johnston 
680*c5591576SRob Johnston 	(void) fprintf(fp, "<%s %s='%s' %s='0x%" PRIx64 "' %s='%s'>\n",
681*c5591576SRob Johnston 	    TDG_XML_VERTEX, TDG_XML_NAME, topo_node_name(tn),
682*c5591576SRob Johnston 	    TDG_XML_INSTANCE, topo_node_instance(tn),
683*c5591576SRob Johnston 	    TDG_XML_FMRI, fmristr);
684*c5591576SRob Johnston 
685*c5591576SRob Johnston 	topo_hdl_strfree(thp, fmristr);
686*c5591576SRob Johnston 
687*c5591576SRob Johnston 	if (serialize_pgroups(thp, fp, tn) != 0) {
688*c5591576SRob Johnston 		/* errno set */
689*c5591576SRob Johnston 		return (TOPO_WALK_ERR);
690*c5591576SRob Johnston 	}
691*c5591576SRob Johnston 
692*c5591576SRob Johnston 	if (vtx->tvt_noutgoing != 0) {
693*c5591576SRob Johnston 		(void) fprintf(fp, "  <%s>\n", TDG_XML_OUTEDGES);
694*c5591576SRob Johnston 
695*c5591576SRob Johnston 		if (topo_edge_iter(thp, vtx, serialize_edge, fp) != 0) {
696*c5591576SRob Johnston 			topo_dprintf(thp, TOPO_DBG_XML, "failed to iterate "
697*c5591576SRob Johnston 			    "edges on %s=%" PRIx64 "\n", topo_node_name(tn),
698*c5591576SRob Johnston 			    topo_node_instance(tn));
699*c5591576SRob Johnston 			/* errno set */
700*c5591576SRob Johnston 			return (TOPO_WALK_ERR);
701*c5591576SRob Johnston 		}
702*c5591576SRob Johnston 		(void) fprintf(fp, "  </%s>\n", TDG_XML_OUTEDGES);
703*c5591576SRob Johnston 	}
704*c5591576SRob Johnston 	(void) fprintf(fp, "</%s>\n\n", TDG_XML_VERTEX);
705*c5591576SRob Johnston 
706*c5591576SRob Johnston 	return (TOPO_WALK_NEXT);
707*c5591576SRob Johnston }
708*c5591576SRob Johnston 
709*c5591576SRob Johnston /*
710*c5591576SRob Johnston  * This function takes a topo_digraph_t and serializes it to XML.
711*c5591576SRob Johnston  *
712*c5591576SRob Johnston  * The schema is described in detail in:
713*c5591576SRob Johnston  * usr/src/lib/fm/topo/maps/common/digraph-topology.dtd.1
714*c5591576SRob Johnston  *
715*c5591576SRob Johnston  * On success, this function writes the XML to the specified file and
716*c5591576SRob Johnston  * returns 0.
717*c5591576SRob Johnston  *
718*c5591576SRob Johnston  * On failure, this function returns -1.
719*c5591576SRob Johnston  */
720*c5591576SRob Johnston int
topo_digraph_serialize(topo_hdl_t * thp,topo_digraph_t * tdg,FILE * fp)721*c5591576SRob Johnston topo_digraph_serialize(topo_hdl_t *thp, topo_digraph_t *tdg, FILE *fp)
722*c5591576SRob Johnston {
723*c5591576SRob Johnston 	struct utsname uts = { 0 };
724*c5591576SRob Johnston 	time_t utc_time;
725*c5591576SRob Johnston 	char tstamp[64];
726*c5591576SRob Johnston 	int ret;
727*c5591576SRob Johnston 
728*c5591576SRob Johnston 	if ((ret =