Print this page
4018 mpt_sas: allow physical topology enumeration in libtopo
4019 mpt_sas: expose LED controls to libtopo
Reviewed by: Keith Wesolowski <keith.wesolowski@joyent.com>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Reviewed by: Albert Lee <trisk@nexenta.com>
Approved by: Albert Lee <trisk@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/fm/topo/libtopo/common/topo_xml.c
+++ new/usr/src/lib/fm/topo/libtopo/common/topo_xml.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright (c) 2013, Joyent, Inc. All rights reserved.
24 25 */
25 26
26 27 #include <libxml/parser.h>
27 28 #include <libxml/xinclude.h>
28 29 #include <sys/fm/protocol.h>
29 30 #include <assert.h>
30 31 #include <string.h>
31 32 #include <strings.h>
32 33 #include <ctype.h>
33 34 #include <errno.h>
34 35 #include <limits.h>
35 36 #include <fm/libtopo.h>
36 37 #include <unistd.h>
37 38 #include <sys/stat.h>
38 39 #include <fcntl.h>
39 40 #include <topo_file.h>
40 41 #include <topo_mod.h>
41 42 #include <topo_subr.h>
42 43 #include <topo_alloc.h>
43 44 #include <topo_parse.h>
44 45 #include <topo_error.h>
45 46
46 47 static tf_rdata_t *topo_xml_walk(topo_mod_t *, tf_info_t *, xmlNodePtr,
47 48 tnode_t *);
48 49 static tf_edata_t *enum_attributes_process(topo_mod_t *, xmlNodePtr);
49 50 static int enum_run(topo_mod_t *, tf_rdata_t *);
50 51 static int fac_enum_run(topo_mod_t *, tnode_t *, const char *);
51 52 static int fac_process(topo_mod_t *, xmlNodePtr, tf_rdata_t *, tnode_t *);
52 53 static int fac_enum_process(topo_mod_t *, xmlNodePtr, tnode_t *);
53 54 static int decorate_nodes(topo_mod_t *, tf_rdata_t *, xmlNodePtr, tnode_t *,
54 55 tf_pad_t **);
55 56
56 57
57 58 static void
58 59 strarr_free(topo_mod_t *mod, char **arr, uint_t nelems)
59 60 {
60 61 int i;
61 62
62 63 for (i = 0; i < nelems; i++)
63 64 topo_mod_strfree(mod, arr[i]);
64 65 topo_mod_free(mod, arr, (nelems * sizeof (char *)));
65 66 }
66 67
67 68 int
68 69 xmlattr_to_stab(topo_mod_t *mp, xmlNodePtr n, const char *stabname,
69 70 topo_stability_t *rs)
70 71 {
71 72 xmlChar *str;
72 73 int rv = 0;
73 74
74 75 if (n == NULL) {
75 76 /* If there is no Stability defined, we default to private */
76 77 *rs = TOPO_STABILITY_PRIVATE;
77 78 return (0);
78 79 }
79 80 if ((str = xmlGetProp(n, (xmlChar *)stabname)) == NULL) {
80 81 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
81 82 "attribute to stability:\n");
82 83 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
83 84 }
84 85
85 86 if (xmlStrcmp(str, (xmlChar *)Internal) == 0) {
86 87 *rs = TOPO_STABILITY_INTERNAL;
87 88 } else if (xmlStrcmp(str, (xmlChar *)Private) == 0) {
88 89 *rs = TOPO_STABILITY_PRIVATE;
89 90 } else if (xmlStrcmp(str, (xmlChar *)Obsolete) == 0) {
90 91 *rs = TOPO_STABILITY_OBSOLETE;
91 92 } else if (xmlStrcmp(str, (xmlChar *)External) == 0) {
92 93 *rs = TOPO_STABILITY_EXTERNAL;
93 94 } else if (xmlStrcmp(str, (xmlChar *)Unstable) == 0) {
94 95 *rs = TOPO_STABILITY_UNSTABLE;
95 96 } else if (xmlStrcmp(str, (xmlChar *)Evolving) == 0) {
96 97 *rs = TOPO_STABILITY_EVOLVING;
97 98 } else if (xmlStrcmp(str, (xmlChar *)Stable) == 0) {
98 99 *rs = TOPO_STABILITY_STABLE;
99 100 } else if (xmlStrcmp(str, (xmlChar *)Standard) == 0) {
100 101 *rs = TOPO_STABILITY_STANDARD;
101 102 } else {
102 103 xmlFree(str);
103 104 return (topo_mod_seterrno(mp, ETOPO_PRSR_BADSTAB));
104 105 }
105 106 xmlFree(str);
106 107 return (rv);
107 108 }
108 109
109 110 int
110 111 xmlattr_to_int(topo_mod_t *mp,
111 112 xmlNodePtr n, const char *propname, uint64_t *value)
112 113 {
113 114 xmlChar *str;
114 115 xmlChar *estr;
115 116
116 117 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xmlattr_to_int(propname=%s)\n",
117 118 propname);
118 119 if ((str = xmlGetProp(n, (xmlChar *)propname)) == NULL)
119 120 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
120 121 *value = strtoull((char *)str, (char **)&estr, 10);
121 122 if (estr == str) {
122 123 /* no conversion was done */
123 124 xmlFree(str);
124 125 return (topo_mod_seterrno(mp, ETOPO_PRSR_BADNUM));
125 126 }
126 127 xmlFree(str);
127 128 return (0);
128 129 }
129 130
130 131 static int
131 132 xmlattr_to_fmri(topo_mod_t *mp,
132 133 xmlNodePtr xn, const char *propname, nvlist_t **rnvl)
133 134 {
134 135 xmlChar *str;
135 136
136 137 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xmlattr_to_fmri(propname=%s)\n",
137 138 propname);
138 139 if ((str = xmlGetProp(xn, (xmlChar *)propname)) == NULL)
139 140 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
140 141 if (topo_mod_str2nvl(mp, (const char *)str, rnvl) < 0) {
141 142 xmlFree(str);
142 143 return (-1);
143 144 }
144 145 xmlFree(str);
145 146 return (0);
146 147 }
147 148
148 149 static topo_type_t
149 150 xmlattr_to_type(topo_mod_t *mp, xmlNodePtr xn, xmlChar *attr)
150 151 {
151 152 topo_type_t rv;
152 153 xmlChar *str;
153 154 if ((str = xmlGetProp(xn, (xmlChar *)attr)) == NULL) {
154 155 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "%s attribute missing",
155 156 attr);
156 157 (void) topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
157 158 return (TOPO_TYPE_INVALID);
158 159 }
159 160 if (xmlStrcmp(str, (xmlChar *)Int32) == 0) {
160 161 rv = TOPO_TYPE_INT32;
161 162 } else if (xmlStrcmp(str, (xmlChar *)UInt32) == 0) {
162 163 rv = TOPO_TYPE_UINT32;
163 164 } else if (xmlStrcmp(str, (xmlChar *)Int64) == 0) {
164 165 rv = TOPO_TYPE_INT64;
165 166 } else if (xmlStrcmp(str, (xmlChar *)UInt64) == 0) {
166 167 rv = TOPO_TYPE_UINT64;
167 168 } else if (xmlStrcmp(str, (xmlChar *)FMRI) == 0) {
168 169 rv = TOPO_TYPE_FMRI;
169 170 } else if (xmlStrcmp(str, (xmlChar *)String) == 0) {
170 171 rv = TOPO_TYPE_STRING;
171 172 } else if (xmlStrcmp(str, (xmlChar *)Int32_Arr) == 0) {
172 173 rv = TOPO_TYPE_INT32_ARRAY;
173 174 } else if (xmlStrcmp(str, (xmlChar *)UInt32_Arr) == 0) {
174 175 rv = TOPO_TYPE_UINT32_ARRAY;
175 176 } else if (xmlStrcmp(str, (xmlChar *)Int64_Arr) == 0) {
176 177 rv = TOPO_TYPE_INT64_ARRAY;
177 178 } else if (xmlStrcmp(str, (xmlChar *)UInt64_Arr) == 0) {
178 179 rv = TOPO_TYPE_UINT64_ARRAY;
179 180 } else if (xmlStrcmp(str, (xmlChar *)String_Arr) == 0) {
180 181 rv = TOPO_TYPE_STRING_ARRAY;
181 182 } else if (xmlStrcmp(str, (xmlChar *)FMRI_Arr) == 0) {
182 183 rv = TOPO_TYPE_FMRI_ARRAY;
183 184 } else {
184 185 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
185 186 "Unrecognized type attribute value '%s'.\n", str);
186 187 (void) topo_mod_seterrno(mp, ETOPO_PRSR_BADTYPE);
187 188 xmlFree(str);
188 189 return (TOPO_TYPE_INVALID);
189 190 }
190 191 xmlFree(str);
191 192 return (rv);
192 193 }
193 194
194 195 static int
195 196 xlate_common(topo_mod_t *mp, xmlNodePtr xn, topo_type_t ptype, nvlist_t *nvl,
196 197 const char *name)
197 198 {
198 199 int rv;
199 200 uint64_t ui;
200 201 uint_t i = 0, nelems = 0;
201 202 nvlist_t *fmri;
202 203 xmlChar *str;
203 204 char **strarrbuf;
204 205 void *arrbuf;
205 206 nvlist_t **nvlarrbuf;
206 207 xmlNodePtr cn;
207 208
208 209 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xlate_common(name=%s)\n", name);
209 210 switch (ptype) {
210 211 case TOPO_TYPE_INT32:
211 212 if (xmlattr_to_int(mp, xn, Value, &ui) < 0)
212 213 return (-1);
213 214 rv = nvlist_add_int32(nvl, name, (int32_t)ui);
214 215 break;
215 216 case TOPO_TYPE_UINT32:
216 217 if (xmlattr_to_int(mp, xn, Value, &ui) < 0)
217 218 return (-1);
218 219 rv = nvlist_add_uint32(nvl, name, (uint32_t)ui);
219 220 break;
220 221 case TOPO_TYPE_INT64:
221 222 if (xmlattr_to_int(mp, xn, Value, &ui) < 0)
222 223 return (-1);
223 224 rv = nvlist_add_int64(nvl, name, (int64_t)ui);
224 225 break;
225 226 case TOPO_TYPE_UINT64:
226 227 if (xmlattr_to_int(mp, xn, Value, &ui) < 0)
227 228 return (-1);
228 229 rv = nvlist_add_uint64(nvl, name, ui);
229 230 break;
230 231 case TOPO_TYPE_FMRI:
231 232 if (xmlattr_to_fmri(mp, xn, Value, &fmri) < 0)
232 233 return (-1);
233 234 rv = nvlist_add_nvlist(nvl, name, fmri);
234 235 nvlist_free(fmri);
235 236 break;
236 237 case TOPO_TYPE_STRING:
237 238 if ((str = xmlGetProp(xn, (xmlChar *)Value)) == NULL)
238 239 return (-1);
239 240 rv = nvlist_add_string(nvl, name, (char *)str);
240 241 xmlFree(str);
241 242 break;
242 243 case TOPO_TYPE_INT32_ARRAY:
243 244 case TOPO_TYPE_UINT32_ARRAY:
244 245 case TOPO_TYPE_INT64_ARRAY:
245 246 case TOPO_TYPE_UINT64_ARRAY:
246 247 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next)
247 248 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
248 249 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0))
249 250 nelems++;
250 251
251 252 if (nelems < 1) {
252 253 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "No <propitem> "
253 254 "or <argitem> elements found for array val");
254 255 return (-1);
255 256 }
256 257 if ((arrbuf = topo_mod_alloc(mp, (nelems * sizeof (uint64_t))))
257 258 == NULL)
258 259 return (topo_mod_seterrno(mp, ETOPO_NOMEM));
259 260 break;
260 261 case TOPO_TYPE_STRING_ARRAY:
261 262 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next)
262 263 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
263 264 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0))
264 265 nelems++;
265 266
266 267 if (nelems < 1) {
267 268 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "No <propitem> "
268 269 "or <argitem> elements found for array val");
269 270 return (-1);
270 271 }
271 272 if ((strarrbuf = topo_mod_alloc(mp, (nelems * sizeof (char *))))
272 273 == NULL)
273 274 return (topo_mod_seterrno(mp, ETOPO_NOMEM));
274 275 break;
275 276 case TOPO_TYPE_FMRI_ARRAY:
276 277 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next)
277 278 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
278 279 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0))
279 280 nelems++;
280 281
281 282 if (nelems < 1) {
282 283 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "No <propitem> "
283 284 "elements found for array prop");
284 285 return (-1);
285 286 }
286 287 if ((nvlarrbuf = topo_mod_alloc(mp, (nelems *
287 288 sizeof (nvlist_t *)))) == NULL)
288 289 return (topo_mod_seterrno(mp, ETOPO_NOMEM));
289 290 break;
290 291 default:
291 292 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
292 293 "Unrecognized type attribute (ptype = %d)\n", ptype);
293 294 return (topo_mod_seterrno(mp, ETOPO_PRSR_BADTYPE));
294 295 }
295 296
296 297 switch (ptype) {
297 298 case TOPO_TYPE_INT32_ARRAY:
298 299 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
299 300 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
300 301 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
301 302
302 303 if ((str = xmlGetProp(xn, (xmlChar *)Value))
303 304 == NULL)
304 305 return (-1);
305 306
306 307 ((int32_t *)arrbuf)[i++]
307 308 = atoi((const char *)str);
308 309 xmlFree(str);
309 310 }
310 311 }
311 312
312 313 rv = nvlist_add_int32_array(nvl, name, (int32_t *)arrbuf,
313 314 nelems);
314 315 free(arrbuf);
315 316 break;
316 317 case TOPO_TYPE_UINT32_ARRAY:
317 318 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
318 319 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
319 320 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
320 321
321 322 if ((str = xmlGetProp(xn, (xmlChar *)Value))
322 323 == NULL)
323 324 return (-1);
324 325
325 326 ((uint32_t *)arrbuf)[i++]
326 327 = atoi((const char *)str);
327 328 xmlFree(str);
328 329 }
329 330 }
330 331
331 332 rv = nvlist_add_uint32_array(nvl, name, (uint32_t *)arrbuf,
332 333 nelems);
333 334 free(arrbuf);
334 335 break;
335 336 case TOPO_TYPE_INT64_ARRAY:
336 337 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
337 338 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
338 339 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
339 340
340 341 if ((str = xmlGetProp(xn, (xmlChar *)Value))
341 342 == NULL)
342 343 return (-1);
343 344
344 345 ((int64_t *)arrbuf)[i++]
345 346 = atol((const char *)str);
346 347 xmlFree(str);
347 348 }
348 349 }
349 350
350 351 rv = nvlist_add_int64_array(nvl, name, (int64_t *)arrbuf,
351 352 nelems);
352 353 free(arrbuf);
353 354 break;
354 355 case TOPO_TYPE_UINT64_ARRAY:
355 356 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
356 357 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
357 358 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
358 359
359 360 if ((str = xmlGetProp(xn, (xmlChar *)Value))
360 361 == NULL)
361 362 return (-1);
362 363
363 364 ((uint64_t *)arrbuf)[i++]
364 365 = atol((const char *)str);
365 366 xmlFree(str);
366 367 }
367 368 }
368 369
369 370 rv = nvlist_add_uint64_array(nvl, name, arrbuf,
370 371 nelems);
371 372 free(arrbuf);
372 373 break;
373 374 case TOPO_TYPE_STRING_ARRAY:
374 375 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
375 376 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
376 377 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
377 378
378 379 if ((str = xmlGetProp(cn, (xmlChar *)Value))
379 380 == NULL)
380 381 return (-1);
381 382
382 383 strarrbuf[i++] =
383 384 topo_mod_strdup(mp, (const char *)str);
384 385 xmlFree(str);
385 386 }
386 387 }
387 388
388 389 rv = nvlist_add_string_array(nvl, name, strarrbuf, nelems);
389 390 strarr_free(mp, strarrbuf, nelems);
390 391 break;
391 392 case TOPO_TYPE_FMRI_ARRAY:
392 393 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
393 394 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
394 395 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
395 396
396 397 if ((str = xmlGetProp(xn, (xmlChar *)Value))
397 398 == NULL)
398 399 return (-1);
399 400
400 401 if (topo_mod_str2nvl(mp, (const char *)str,
401 402 &(nvlarrbuf[i++])) < 0) {
402 403 xmlFree(str);
403 404 return (-1);
404 405 }
405 406 xmlFree(str);
406 407 }
407 408 }
408 409
409 410 rv = nvlist_add_nvlist_array(nvl, name, nvlarrbuf,
410 411 nelems);
411 412 free(nvlarrbuf);
412 413 break;
413 414 }
414 415
415 416 if (rv != 0) {
416 417 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
417 418 "Nvlist construction failed.\n");
418 419 return (topo_mod_seterrno(mp, ETOPO_NOMEM));
419 420 } else
420 421 return (0);
421 422 }
422 423
423 424 static int
424 425 xmlprop_xlate(topo_mod_t *mp, xmlNodePtr xn, nvlist_t *nvl)
425 426 {
426 427 topo_type_t ptype;
427 428 xmlChar *str;
428 429
429 430 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xmlprop_xlate\n");
430 431 if ((str = xmlGetProp(xn, (xmlChar *)Immutable)) != NULL) {
431 432 if (xmlStrcmp(str, (xmlChar *)False) == 0)
432 433 (void) nvlist_add_boolean_value(nvl, INV_IMMUTE,
433 434 B_FALSE);
434 435 else
435 436 (void) nvlist_add_boolean_value(nvl, INV_IMMUTE,
436 437 B_TRUE);
437 438 xmlFree(str);
438 439 } else {
439 440 (void) nvlist_add_boolean_value(nvl, INV_IMMUTE, B_TRUE);
440 441 }
441 442
442 443 if ((ptype = xmlattr_to_type(mp, xn, (xmlChar *)Type))
443 444 == TOPO_TYPE_INVALID)
444 445 return (-1);
445 446
446 447 if (nvlist_add_int32(nvl, INV_PVALTYPE, ptype) != 0)
447 448 return (-1);
448 449
449 450 return (xlate_common(mp, xn, ptype, nvl, INV_PVAL));
450 451 }
451 452
452 453 static int
453 454 dependent_create(topo_mod_t *mp,
454 455 tf_info_t *xinfo, tf_pad_t *pad, xmlNodePtr dxn, tnode_t *ptn)
455 456 {
456 457 tf_rdata_t *rp, *pp, *np;
457 458 xmlChar *grptype;
458 459 int sibs = 0;
459 460
460 461 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "dependent_create\n");
461 462 if ((grptype = xmlGetProp(dxn, (xmlChar *)Grouping)) == NULL) {
462 463 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
463 464 "Dependents missing grouping attribute");
464 465 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
465 466 }
466 467
467 468 pp = NULL;
468 469 if (xmlStrcmp(grptype, (xmlChar *)Siblings) == 0) {
469 470 rp = pad->tpad_sibs;
470 471 sibs++;
471 472 } else if (xmlStrcmp(grptype, (xmlChar *)Children) == 0) {
472 473 rp = pad->tpad_child;
473 474 } else {
474 475 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
475 476 "Dependents have bogus grouping attribute");
476 477 xmlFree(grptype);
477 478 return (topo_mod_seterrno(mp, ETOPO_PRSR_BADGRP));
478 479 }
479 480 xmlFree(grptype);
480 481 /* Add processed dependents to the tail of the list */
481 482 while (rp != NULL) {
482 483 pp = rp;
483 484 rp = rp->rd_next;
484 485 }
485 486 if ((np = topo_xml_walk(mp, xinfo, dxn, ptn)) == NULL) {
486 487 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
487 488 "error within dependent .xml topology: "
488 489 "%s\n", topo_strerror(topo_mod_errno(mp)));
489 490 return (-1);
490 491 }
491 492 if (pp != NULL)
492 493 pp->rd_next = np;
493 494 else if (sibs == 1)
494 495 pad->tpad_sibs = np;
495 496 else
496 497 pad->tpad_child = np;
497 498 return (0);
498 499 }
499 500
500 501 static int
501 502 dependents_create(topo_mod_t *mp,
502 503 tf_info_t *xinfo, tf_pad_t *pad, xmlNodePtr pxn, tnode_t *ptn)
503 504 {
504 505 xmlNodePtr cn;
505 506
506 507 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "dependents_create\n");
507 508 for (cn = pxn->xmlChildrenNode; cn != NULL; cn = cn->next) {
508 509 if (xmlStrcmp(cn->name, (xmlChar *)Dependents) == 0) {
509 510 if (dependent_create(mp, xinfo, pad, cn, ptn) < 0)
510 511 return (-1);
511 512 }
512 513 }
513 514 return (0);
514 515 }
515 516
516 517 static int
517 518 prop_create(topo_mod_t *mp,
518 519 nvlist_t *pfmri, tnode_t *ptn, const char *gnm, const char *pnm,
519 520 topo_type_t ptype, int flag)
520 521 {
521 522 nvlist_t *fmri, **fmriarr;
522 523 uint32_t ui32, *ui32arr;
523 524 uint64_t ui64, *ui64arr;
524 525 int32_t i32, *i32arr;
525 526 int64_t i64, *i64arr;
526 527 uint_t nelem;
527 528 char *str, **strarr;
528 529 int err, e;
529 530
530 531 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "prop_create(pgrp = %s, "
531 532 "prop = %s)\n", gnm, pnm);
532 533 switch (ptype) {
533 534 case TOPO_TYPE_INT32:
534 535 e = nvlist_lookup_int32(pfmri, INV_PVAL, &i32);
535 536 break;
536 537 case TOPO_TYPE_UINT32:
537 538 e = nvlist_lookup_uint32(pfmri, INV_PVAL, &ui32);
538 539 break;
539 540 case TOPO_TYPE_INT64:
540 541 e = nvlist_lookup_int64(pfmri, INV_PVAL, &i64);
541 542 break;
542 543 case TOPO_TYPE_UINT64:
543 544 e = nvlist_lookup_uint64(pfmri, INV_PVAL, &ui64);
544 545 break;
545 546 case TOPO_TYPE_FMRI:
546 547 e = nvlist_lookup_nvlist(pfmri, INV_PVAL, &fmri);
547 548 break;
548 549 case TOPO_TYPE_STRING:
549 550 e = nvlist_lookup_string(pfmri, INV_PVAL, &str);
550 551 break;
551 552 case TOPO_TYPE_INT32_ARRAY:
552 553 e = nvlist_lookup_int32_array(pfmri, INV_PVAL, &i32arr, &nelem);
553 554 break;
554 555 case TOPO_TYPE_UINT32_ARRAY:
555 556 e = nvlist_lookup_uint32_array(pfmri, INV_PVAL, &ui32arr,
556 557 &nelem);
557 558 break;
558 559 case TOPO_TYPE_INT64_ARRAY:
559 560 e = nvlist_lookup_int64_array(pfmri, INV_PVAL, &i64arr,
560 561 &nelem);
561 562 break;
562 563 case TOPO_TYPE_UINT64_ARRAY:
563 564 e = nvlist_lookup_uint64_array(pfmri, INV_PVAL, &ui64arr,
564 565 &nelem);
565 566 break;
566 567 case TOPO_TYPE_STRING_ARRAY:
567 568 e = nvlist_lookup_string_array(pfmri, INV_PVAL, &strarr,
568 569 &nelem);
569 570 break;
570 571 case TOPO_TYPE_FMRI_ARRAY:
571 572 e = nvlist_lookup_nvlist_array(pfmri, INV_PVAL, &fmriarr,
572 573 &nelem);
573 574 break;
574 575 default:
575 576 e = ETOPO_PRSR_BADTYPE;
576 577 }
577 578 if (e != 0) {
578 579 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
579 580 "prop_create: prop value lookup failed.\n");
580 581 return (topo_mod_seterrno(mp, e));
581 582 }
582 583 switch (ptype) {
583 584 case TOPO_TYPE_INT32:
584 585 e = topo_prop_set_int32(ptn, gnm, pnm, flag, i32, &err);
585 586 break;
586 587 case TOPO_TYPE_UINT32:
587 588 e = topo_prop_set_uint32(ptn, gnm, pnm, flag, ui32, &err);
588 589 break;
589 590 case TOPO_TYPE_INT64:
590 591 e = topo_prop_set_int64(ptn, gnm, pnm, flag, i64, &err);
591 592 break;
592 593 case TOPO_TYPE_UINT64:
593 594 e = topo_prop_set_uint64(ptn, gnm, pnm, flag, ui64, &err);
594 595 break;
595 596 case TOPO_TYPE_FMRI:
596 597 e = topo_prop_set_fmri(ptn, gnm, pnm, flag, fmri, &err);
597 598 break;
598 599 case TOPO_TYPE_STRING:
599 600 e = topo_prop_set_string(ptn, gnm, pnm, flag, str, &err);
600 601 break;
601 602 case TOPO_TYPE_INT32_ARRAY:
602 603 e = topo_prop_set_int32_array(ptn, gnm, pnm, flag, i32arr,
603 604 nelem, &err);
604 605 break;
605 606 case TOPO_TYPE_UINT32_ARRAY:
606 607 e = topo_prop_set_uint32_array(ptn, gnm, pnm, flag, ui32arr,
607 608 nelem, &err);
608 609 break;
609 610 case TOPO_TYPE_INT64_ARRAY:
610 611 e = topo_prop_set_int64_array(ptn, gnm, pnm, flag, i64arr,
611 612 nelem, &err);
612 613 break;
613 614 case TOPO_TYPE_UINT64_ARRAY:
614 615 e = topo_prop_set_uint64_array(ptn, gnm, pnm, flag, ui64arr,
615 616 nelem, &err);
616 617 break;
617 618 case TOPO_TYPE_STRING_ARRAY:
618 619 e = topo_prop_set_string_array(ptn, gnm, pnm, flag,
619 620 (const char **)strarr, nelem, &err);
620 621 break;
621 622 case TOPO_TYPE_FMRI_ARRAY:
622 623 e = topo_prop_set_fmri_array(ptn, gnm, pnm, flag,
623 624 (const nvlist_t **)fmriarr, nelem, &err);
624 625 break;
625 626 }
626 627 if (e != 0 && err != ETOPO_PROP_DEFD) {
627 628
628 629 /*
629 630 * Some properties may have already been set
630 631 * in topo_node_bind() or topo_prop_inherit if we are
631 632 * enumerating from a static .xml file
632 633 */
633 634 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "prop set "
634 635 "failed %s/%s:%s\n", gnm, pnm, topo_strerror(err));
635 636 return (topo_mod_seterrno(mp, err));
636 637 }
637 638 return (0);
638 639 }
639 640
640 641 static int
641 642 props_create(topo_mod_t *mp,
642 643 tnode_t *ptn, const char *gnm, nvlist_t **props, int nprops)
643 644 {
644 645 topo_type_t ptype;
645 646 boolean_t pim;
646 647 char *pnm;
647 648 int32_t i32;
648 649 int flag;
649 650 int pn;
650 651 int e;
651 652
652 653 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "props_create(pgrp = %s)\n",
653 654 gnm);
654 655 for (pn = 0; pn < nprops; pn++) {
655 656 e = nvlist_lookup_string(props[pn], INV_PNAME, &pnm);
656 657 if (e != 0) {
657 658 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
658 659 "props create lookup (%s) failure: %s",
659 660 INV_PNAME, strerror(e));
660 661 return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
661 662 }
662 663 e = nvlist_lookup_boolean_value(props[pn], INV_IMMUTE, &pim);
663 664 if (e != 0) {
664 665 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
665 666 "props create lookup (%s) failure: %s",
666 667 INV_IMMUTE, strerror(e));
667 668 return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
668 669 }
669 670 flag = (pim == B_TRUE) ?
670 671 TOPO_PROP_IMMUTABLE : TOPO_PROP_MUTABLE;
671 672
672 673 e = nvlist_lookup_int32(props[pn], INV_PVALTYPE, &i32);
673 674 if (e != 0) {
674 675 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
675 676 "props create lookup (%s) failure: %s",
676 677 INV_PVALTYPE, strerror(e));
677 678 return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
678 679 }
679 680 ptype = (topo_type_t)i32;
680 681 if (prop_create(mp, props[pn], ptn, gnm, pnm, ptype, flag) < 0)
681 682 return (-1);
682 683 }
683 684 return (0);
684 685 }
685 686
686 687 static int
687 688 pgroups_create(topo_mod_t *mp, tf_pad_t *pad, tnode_t *ptn)
688 689 {
689 690 topo_pgroup_info_t pgi;
690 691 nvlist_t **props;
691 692 char *gnm;
692 693 char *nmstab, *dstab;
693 694 uint32_t rnprops, nprops;
694 695 uint32_t gv;
695 696 int pg;
696 697 int e;
697 698
698 699 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroups_create: %s=%d\n",
699 700 topo_node_name(ptn), topo_node_instance(ptn));
700 701 for (pg = 0; pg < pad->tpad_pgcnt; pg++) {
701 702 e = nvlist_lookup_string(pad->tpad_pgs[pg],
702 703 INV_PGRP_NAME, &gnm);
703 704 if (e != 0) {
704 705 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
705 706 "pad lookup (%s) failed (%s).\n",
706 707 INV_PGRP_NAME, strerror(errno));
707 708 return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
708 709 }
709 710 e = nvlist_lookup_string(pad->tpad_pgs[pg],
710 711 INV_PGRP_NMSTAB, &nmstab);
711 712 if (e != 0) {
712 713 if (e != ENOENT) {
713 714 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
714 715 "pad lookup (%s) "
715 716 "failed.\n", INV_PGRP_NMSTAB);
716 717 return (topo_mod_seterrno(mp,
717 718 ETOPO_PRSR_NVPROP));
718 719 } else {
719 720 nmstab = TOPO_STABSTR_PRIVATE;
720 721 }
721 722 }
722 723 e = nvlist_lookup_string(pad->tpad_pgs[pg],
723 724 INV_PGRP_DSTAB, &dstab);
724 725 if (e != 0) {
725 726 if (e != ENOENT) {
726 727 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
727 728 "pad lookup (%s) failed.\n",
728 729 INV_PGRP_DSTAB);
729 730 return (topo_mod_seterrno(mp,
730 731 ETOPO_PRSR_NVPROP));
731 732 } else {
732 733 dstab = TOPO_STABSTR_PRIVATE;
733 734 }
734 735 }
735 736 e = nvlist_lookup_uint32(pad->tpad_pgs[pg],
736 737 INV_PGRP_VER, &gv);
737 738 if (e != 0) {
738 739 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
739 740 "pad lookup (%s) failed.\n",
740 741 INV_PGRP_VER);
741 742 return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
742 743 }
743 744 pgi.tpi_name = gnm;
744 745 pgi.tpi_namestab = topo_name2stability(nmstab);
745 746 pgi.tpi_datastab = topo_name2stability(dstab);
746 747 pgi.tpi_version = gv;
747 748 if (topo_pgroup_create(ptn, &pgi, &e) != 0) {
748 749 if (e != ETOPO_PROP_DEFD) {
749 750 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
750 751 "pgroups create failure: %s\n",
751 752 topo_strerror(e));
752 753 return (-1);
753 754 }
754 755 }
755 756 e = nvlist_lookup_uint32(pad->tpad_pgs[pg],
756 757 INV_PGRP_NPROP, &rnprops);
757 758 /*
758 759 * The number of properties could be zero if the property
759 760 * group only contains propmethod declarations
760 761 */
761 762 if (rnprops > 0) {
762 763 e |= nvlist_lookup_nvlist_array(pad->tpad_pgs[pg],
763 764 INV_PGRP_ALLPROPS, &props, &nprops);
764 765 if (rnprops != nprops) {
765 766 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
766 767 "recorded number of props %d does not "
767 768 "match number of props recorded %d.\n",
768 769 rnprops, nprops);
769 770 }
770 771 if (props_create(mp, ptn, gnm, props, nprops) < 0)
771 772 return (-1);
772 773 }
773 774 }
774 775 return (0);
775 776 }
776 777
777 778 static nvlist_t *
778 779 pval_record(topo_mod_t *mp, xmlNodePtr xn)
779 780 {
780 781 nvlist_t *pnvl = NULL;
781 782 xmlChar *pname;
782 783
783 784 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pval_record\n");
784 785 if ((pname = xmlGetProp(xn, (xmlChar *)Name)) == NULL) {
785 786 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
786 787 "propval lacks a name\n");
787 788 (void) topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
788 789 return (NULL);
789 790 }
790 791 if (topo_mod_nvalloc(mp, &pnvl, NV_UNIQUE_NAME) < 0) {
791 792 xmlFree(pname);
792 793 return (NULL);
793 794 }
794 795 if (nvlist_add_string(pnvl, INV_PNAME, (char *)pname) < 0) {
795 796 xmlFree(pname);
796 797 nvlist_free(pnvl);
797 798 return (NULL);
798 799 }
799 800 xmlFree(pname);
800 801 /* FMXXX stability of the property name */
801 802
802 803 if (xmlprop_xlate(mp, xn, pnvl) < 0) {
803 804 nvlist_free(pnvl);
804 805 return (NULL);
805 806 }
806 807 return (pnvl);
807 808 }
808 809
809 810
810 811 struct propmeth_data {
811 812 const char *pg_name;
812 813 const char *prop_name;
813 814 topo_type_t prop_type;
814 815 const char *meth_name;
815 816 topo_version_t meth_ver;
816 817 nvlist_t *arg_nvl;
817 818 };
818 819
819 820 static int
820 821 register_method(topo_mod_t *mp, tnode_t *ptn, struct propmeth_data *meth)
821 822 {
822 823 int err;
823 824
824 825 if (topo_prop_method_version_register(ptn, meth->pg_name,
825 826 meth->prop_name, meth->prop_type, meth->meth_name, meth->meth_ver,
826 827 meth->arg_nvl, &err) != 0) {
827 828
828 829 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "failed to register "
829 830 "propmethod %s for property \"%s\" in propgrp %s on node "
830 831 "%s=%d (%s)\n",
831 832 meth->meth_name, meth->prop_name, meth->pg_name,
832 833 topo_node_name(ptn), topo_node_instance(ptn),
833 834 topo_strerror(err));
834 835 return (-1);
835 836 }
836 837 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
837 838 "registered method %s on %s=%d\n",
838 839 meth->meth_name, topo_node_name(ptn), topo_node_instance(ptn));
839 840
840 841 return (0);
841 842 }
842 843
843 844 static int
844 845 pmeth_record(topo_mod_t *mp, const char *pg_name, xmlNodePtr xn, tnode_t *tn,
845 846 const char *rname, const char *ppgrp_name)
846 847 {
847 848 nvlist_t *arg_nvl = NULL;
848 849 xmlNodePtr cn;
849 850 xmlChar *meth_name = NULL, *prop_name = NULL;
850 851 xmlChar *arg_name = NULL;
851 852 uint64_t meth_ver, is_mutable = 0, is_nonvolatile = 0;
852 853 topo_type_t prop_type;
853 854 struct propmeth_data meth;
854 855 int ret = 0, err;
855 856 topo_type_t ptype;
856 857 tnode_t *tmp;
857 858
858 859 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pmeth_record: %s=%d "
859 860 "(pgrp=%s)\n", topo_node_name(tn), topo_node_instance(tn), pg_name);
860 861
861 862 /*
862 863 * Get propmethod attribute values
863 864 */
864 865 if ((meth_name = xmlGetProp(xn, (xmlChar *)Name)) == NULL) {
865 866 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
866 867 "propmethod element lacks a name attribute\n");
867 868 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
868 869 }
869 870 if (xmlattr_to_int(mp, xn, Version, &meth_ver) < 0) {
870 871 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
871 872 "propmethod element lacks version attribute\n");
872 873 ret = topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
873 874 goto pmr_done;
874 875 }
875 876 /*
876 877 * The "mutable" and "nonvoltile" attributes are optional. If not
877 878 * specified we default to false (0)
878 879 */
879 880 (void) xmlattr_to_int(mp, xn, Mutable, &is_mutable);
880 881 (void) xmlattr_to_int(mp, xn, Nonvolatile, &is_nonvolatile);
881 882
882 883 if ((prop_name = xmlGetProp(xn, (xmlChar *)Propname)) == NULL) {
883 884 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
884 885 "propmethod element lacks propname attribute\n");
885 886 ret = topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
886 887 goto pmr_done;
887 888 }
888 889 if ((prop_type = xmlattr_to_type(mp, xn, (xmlChar *)Proptype))
889 890 == TOPO_TYPE_INVALID) {
890 891 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
891 892 "error decoding proptype attribute\n");
892 893 ret = topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
893 894 goto pmr_done;
894 895 }
895 896
896 897 /*
897 898 * Allocate method argument nvlist
898 899 */
899 900 if (topo_mod_nvalloc(mp, &arg_nvl, NV_UNIQUE_NAME) < 0) {
900 901 ret = topo_mod_seterrno(mp, ETOPO_NOMEM);
901 902 goto pmr_done;
902 903 }
903 904
904 905 /*
905 906 * Iterate through the argval nodes and build the argval nvlist
906 907 */
907 908 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
908 909 if (xmlStrcmp(cn->name, (xmlChar *)Argval) == 0) {
909 910 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
910 911 "found argval element\n");
911 912 if ((arg_name = xmlGetProp(cn, (xmlChar *)Name))
912 913 == NULL) {
913 914 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
914 915 "argval element lacks a name attribute\n");
915 916 ret = topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
916 917 goto pmr_done;
917 918 }
918 919 if ((ptype = xmlattr_to_type(mp, cn, (xmlChar *)Type))
919 920 == TOPO_TYPE_INVALID) {
920 921 ret = topo_mod_seterrno(mp, ETOPO_PRSR_BADTYPE);
921 922 xmlFree(arg_name);
922 923 break;
923 924 }
924 925 if (xlate_common(mp, cn, ptype, arg_nvl,
925 926 (const char *)arg_name) != 0) {
926 927 ret = topo_mod_seterrno(mp, ETOPO_PRSR_BADTYPE);
927 928 xmlFree(arg_name);
928 929 break;
929 930 }
930 931 }
931 932 if (arg_name) {
932 933 xmlFree(arg_name);
933 934 arg_name = NULL;
934 935 }
935 936 }
936 937
937 938 if (ret != 0)
938 939 goto pmr_done;
939 940
940 941 /*
941 942 * Register the prop method for all of the nodes in our range
942 943 */
943 944 meth.pg_name = (const char *)pg_name;
944 945 meth.prop_name = (const char *)prop_name;
945 946 meth.prop_type = prop_type;
946 947 meth.meth_name = (const char *)meth_name;
947 948 meth.meth_ver = meth_ver;
948 949 meth.arg_nvl = arg_nvl;
949 950
950 951 /*
951 952 * If the propgroup element is under a range element, we'll apply
952 953 * the method to all of the topo nodes at this level with the same
953 954 * range name.
954 955 *
955 956 * Otherwise, if the propgroup element is under a node element
956 957 * then we'll simply register the method for this node.
957 958 */
958 959 if (strcmp(ppgrp_name, Range) == 0) {
959 960 for (tmp = tn; tmp != NULL; tmp = topo_child_next(NULL, tmp)) {
960 961 if (strcmp(rname, topo_node_name(tmp)) == 0) {
961 962 if (register_method(mp, tmp, &meth) != 0) {
962 963 ret = topo_mod_seterrno(mp,
963 964 ETOPO_PRSR_REGMETH);
964 965 goto pmr_done;
965 966 }
966 967 if (is_mutable) {
967 968 if (topo_prop_setmutable(tmp,
968 969 meth.pg_name, meth.prop_name, &err)
969 970 != 0) {
970 971 ret = topo_mod_seterrno(mp,
971 972 ETOPO_PRSR_REGMETH);
972 973 goto pmr_done;
973 974 }
974 975 }
975 976 if (is_nonvolatile) {
976 977 if (topo_prop_setnonvolatile(tmp,
977 978 meth.pg_name, meth.prop_name, &err)
978 979 != 0) {
979 980 ret = topo_mod_seterrno(mp,
980 981 ETOPO_PRSR_REGMETH);
981 982 goto pmr_done;
982 983 }
983 984 }
984 985 }
985 986 }
986 987 } else {
987 988 if (register_method(mp, tn, &meth) != 0) {
988 989 ret = topo_mod_seterrno(mp, ETOPO_PRSR_REGMETH);
989 990 goto pmr_done;
990 991 }
991 992 if (is_mutable) {
992 993 if (topo_prop_setmutable(tn, meth.pg_name,
993 994 meth.prop_name, &err) != 0) {
994 995 ret = topo_mod_seterrno(mp,
995 996 ETOPO_PRSR_REGMETH);
996 997 goto pmr_done;
997 998 }
998 999 }
999 1000 if (is_nonvolatile) {
1000 1001 if (topo_prop_setnonvolatile(tn, meth.pg_name,
1001 1002 meth.prop_name, &err) != 0) {
1002 1003 ret = topo_mod_seterrno(mp,
1003 1004 ETOPO_PRSR_REGMETH);
1004 1005 goto pmr_done;
1005 1006 }
1006 1007 }
1007 1008 }
1008 1009
1009 1010 pmr_done:
1010 1011 if (meth_name)
1011 1012 xmlFree(meth_name);
1012 1013 if (prop_name)
1013 1014 xmlFree(prop_name);
1014 1015 if (arg_nvl)
1015 1016 nvlist_free(arg_nvl);
1016 1017 return (ret);
1017 1018 }
1018 1019
1019 1020
1020 1021 static int
1021 1022 pgroup_record(topo_mod_t *mp, xmlNodePtr pxn, tnode_t *tn, const char *rname,
1022 1023 tf_pad_t *rpad, int pi, const char *ppgrp_name)
1023 1024 {
1024 1025 topo_stability_t nmstab, dstab;
1025 1026 uint64_t ver;
1026 1027 xmlNodePtr cn;
1027 1028 xmlChar *name;
1028 1029 nvlist_t **apl = NULL;
1029 1030 nvlist_t *pgnvl = NULL;
1030 1031 int pcnt = 0;
1031 1032 int ai = 0;
1032 1033 int e;
1033 1034
1034 1035 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroup_record\n");
1035 1036 if ((name = xmlGetProp(pxn, (xmlChar *)Name)) == NULL) {
1036 1037 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1037 1038 "propgroup lacks a name\n");
1038 1039 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
1039 1040 }
1040 1041 if (xmlattr_to_int(mp, pxn, Version, &ver) < 0) {
1041 1042 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1042 1043 "propgroup lacks a version\n");
1043 1044 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
1044 1045 }
1045 1046 if (xmlattr_to_stab(mp, pxn, Namestab, &nmstab) < 0) {
1046 1047 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1047 1048 "propgroup lacks name-stability\n");
1048 1049 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
1049 1050 }
1050 1051 if (xmlattr_to_stab(mp, pxn, Datastab, &dstab) < 0) {
1051 1052 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1052 1053 "propgroup lacks data-stability\n");
1053 1054 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
1054 1055 }
1055 1056
1056 1057 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroup %s\n", (char *)name);
1057 1058 for (cn = pxn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1058 1059 if (xmlStrcmp(cn->name, (xmlChar *)Propval) == 0)
1059 1060 pcnt++;
1060 1061 }
1061 1062
1062 1063 if (topo_mod_nvalloc(mp, &pgnvl, NV_UNIQUE_NAME) < 0) {
1063 1064 xmlFree(name);
1064 1065 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1065 1066 "failed to allocate propgroup nvlist\n");
1066 1067 return (topo_mod_seterrno(mp, ETOPO_NOMEM));
1067 1068 }
1068 1069
1069 1070 e = nvlist_add_string(pgnvl, INV_PGRP_NAME, (char *)name);
1070 1071 e |= nvlist_add_uint32(pgnvl, INV_PGRP_NMSTAB, nmstab);
1071 1072 e |= nvlist_add_uint32(pgnvl, INV_PGRP_DSTAB, dstab);
1072 1073 e |= nvlist_add_uint32(pgnvl, INV_PGRP_VER, ver);
1073 1074 e |= nvlist_add_uint32(pgnvl, INV_PGRP_NPROP, pcnt);
1074 1075 if (pcnt > 0)
1075 1076 if (e != 0 ||
1076 1077 (apl = topo_mod_zalloc(mp, pcnt * sizeof (nvlist_t *)))
1077 1078 == NULL) {
1078 1079 xmlFree(name);
1079 1080 nvlist_free(pgnvl);
1080 1081 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1081 1082 "failed to allocate nvlist array for properties"
1082 1083 "(e=%d)\n", e);
1083 1084 return (topo_mod_seterrno(mp, ETOPO_NOMEM));
1084 1085 }
1085 1086 for (cn = pxn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1086 1087 if (xmlStrcmp(cn->name, (xmlChar *)Propval) == 0) {
1087 1088 if (ai < pcnt) {
1088 1089 if ((apl[ai] = pval_record(mp, cn)) == NULL)
1089 1090 break;
1090 1091 }
1091 1092 ai++;
1092 1093 } else if (xmlStrcmp(cn->name, (xmlChar *)Prop_meth) == 0) {
1093 1094 if (pmeth_record(mp, (const char *)name, cn, tn, rname,
1094 1095 ppgrp_name) < 0)
1095 1096 break;
1096 1097 }
1097 1098 }
1098 1099 xmlFree(name);
1099 1100 if (pcnt > 0) {
1100 1101 e |= (ai != pcnt);
1101 1102 e |= nvlist_add_nvlist_array(pgnvl, INV_PGRP_ALLPROPS, apl,
1102 1103 pcnt);
1103 1104 for (ai = 0; ai < pcnt; ai++)
1104 1105 if (apl[ai] != NULL)
1105 1106 nvlist_free(apl[ai]);
1106 1107 topo_mod_free(mp, apl, pcnt * sizeof (nvlist_t *));
1107 1108 if (e != 0) {
1108 1109 nvlist_free(pgnvl);
1109 1110 return (-1);
1110 1111 }
1111 1112 }
1112 1113 rpad->tpad_pgs[pi] = pgnvl;
1113 1114 return (0);
1114 1115 }
1115 1116
1116 1117 static int
1117 1118 pgroups_record(topo_mod_t *mp, xmlNodePtr pxn, tnode_t *tn, const char *rname,
1118 1119 tf_pad_t *rpad, const char *ppgrp)
1119 1120 {
1120 1121 xmlNodePtr cn;
1121 1122 int pi = 0;
1122 1123
1123 1124 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroups_record: pxn->name=%s\n",
1124 1125 pxn->name);
1125 1126 for (cn = pxn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1126 1127 if (xmlStrcmp(cn->name, (xmlChar *)Propgrp) == 0) {
1127 1128 if (pgroup_record(mp, cn, tn, rname, rpad, pi++, ppgrp)
1128 1129 < 0)
1129 1130 return (-1);
1130 1131 }
1131 1132 }
1132 1133 return (0);
1133 1134 }
1134 1135
1135 1136 /*
1136 1137 * psn: pointer to a "set" XML node
1137 1138 * key: string to search the set for
1138 1139 *
1139 1140 * returns: 1, if the set contains key
1140 1141 * 0, otherwise
1141 1142 */
1142 1143 static int
1143 1144 set_contains(topo_mod_t *mp, char *key, char *set)
1144 1145 {
1145 1146 char *prod;
1146 1147 int rv = 0;
1147 1148
1148 1149 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "set_contains(key = %s, "
1149 1150 "setlist = %s)\n", key, set);
1150 1151
1151 1152 prod = strtok((char *)set, "|");
1152 1153 if (prod && (strcmp(key, prod) == 0))
1153 1154 return (1);
1154 1155
1155 1156 while ((prod = strtok(NULL, "|")))
1156 1157 if (strcmp(key, prod) == 0)
1157 1158 return (1);
1158 1159
1159 1160 return (rv);
1160 1161 }
1161 1162
1162 1163
1163 1164 /*
1164 1165 * Process the property group and dependents xmlNode children of
1165 1166 * parent xmlNode pxn.
1166 1167 */
1167 1168 static int
1168 1169 pad_process(topo_mod_t *mp, tf_rdata_t *rd, xmlNodePtr pxn, tnode_t *ptn,
1169 1170 tf_pad_t **rpad)
1170 1171 {
1171 1172 xmlNodePtr cn, gcn, psn, ecn, target;
1172 1173 xmlNodePtr def_set = NULL;
1173 1174 tnode_t *ct;
1174 1175 tf_pad_t *new = *rpad;
1175 1176 tf_rdata_t tmp_rd;
1176 1177 int pgcnt = 0;
1177 1178 int dcnt = 0;
1178 1179 int ecnt = 0;
1179 1180 int joined_set = 0, inst;
1180 1181 xmlChar *set;
1181 1182 char *key;
1182 1183
1183 1184 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1184 1185 "pad_process beneath %s=%d\n", topo_node_name(ptn),
1185 1186 topo_node_instance(ptn));
1186 1187 if (new == NULL) {
1187 1188 for (cn = pxn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1188 1189 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1189 1190 "cn->name is %s \n", (char *)cn->name);
1190 1191 /*
1191 1192 * We're iterating through the XML children looking for
1192 1193 * four types of elements:
1193 1194 * 1) dependents elements
1194 1195 * 2) unconstrained pgroup elements
1195 1196 * 3) pgroup elements constrained by set elements
1196 1197 * 4) enum-method elements for the case that we want
1197 1198 * to post-process a statically defined node
1198 1199 */
1199 1200 if (xmlStrcmp(cn->name, (xmlChar *)Dependents) == 0)
1200 1201 dcnt++;
1201 1202 else if (xmlStrcmp(cn->name, (xmlChar *)Propgrp) == 0)
1202 1203 pgcnt++;
1203 1204 else if (xmlStrcmp(cn->name, (xmlChar *)Enum_meth)
1204 1205 == 0) {
1205 1206 ecn = cn;
1206 1207 ecnt++;
1207 1208 } else if (xmlStrcmp(cn->name, (xmlChar *)Set) == 0) {
1208 1209 if (joined_set)
1209 1210 continue;
1210 1211 set = xmlGetProp(cn, (xmlChar *)Setlist);
1211 1212
1212 1213 if (mp->tm_hdl->th_product)
1213 1214 key = mp->tm_hdl->th_product;
1214 1215 else
1215 1216 key = mp->tm_hdl->th_platform;
1216 1217
1217 1218 /*
1218 1219 * If it's the default set then we'll store
1219 1220 * a pointer to it so that if none of the other
1220 1221 * sets apply to our product we can fall
1221 1222 * back to this one.
1222 1223 */
1223 1224 if (strcmp((char *)set, "default") == 0)
1224 1225 def_set = cn;
1225 1226 else if (set_contains(mp, key, (char *)set)) {
1226 1227 psn = cn;
1227 1228 joined_set = 1;
1228 1229 for (gcn = cn->xmlChildrenNode;
1229 1230 gcn != NULL; gcn = gcn->next) {
1230 1231 if (xmlStrcmp(gcn->name,
1231 1232 (xmlChar *)Propgrp) == 0)
1232 1233 pgcnt++;
1233 1234 }
1234 1235 }
1235 1236 xmlFree(set);
1236 1237 }
1237 1238 }
1238 1239 /*
1239 1240 * If we haven't found a set that contains our product AND
1240 1241 * a default set exists, then we'll process it.
1241 1242 */
1242 1243 if (!joined_set && def_set) {
1243 1244 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1244 1245 "Falling back to default set\n");
1245 1246 joined_set = 1;
1246 1247 psn = def_set;
1247 1248 for (gcn = psn->xmlChildrenNode; gcn != NULL;
1248 1249 gcn = gcn->next) {
1249 1250 if (xmlStrcmp(gcn->name, (xmlChar *)Propgrp)
1250 1251 == 0)
1251 1252 pgcnt++;
1252 1253 }
1253 1254 }
1254 1255 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1255 1256 "pad_process: dcnt=%d, pgcnt=%d, ecnt=%d, joined_set=%d\n",
1256 1257 dcnt, pgcnt, ecnt, joined_set);
1257 1258 /*
1258 1259 * If an enum-method element was found, AND we're a child of a
1259 1260 * node element, then we invoke the enumerator so that it can do
1260 1261 * post-processing of the node.
1261 1262 */
1262 1263 if (ecnt && (strcmp((const char *)pxn->name, Node) == 0)) {
1263 1264 if ((tmp_rd.rd_einfo = enum_attributes_process(mp, ecn))
1264 1265 == NULL)
1265 1266 return (-1);
1266 1267 tmp_rd.rd_mod = mp;
1267 1268 tmp_rd.rd_name = rd->rd_name;
1268 1269 tmp_rd.rd_min = rd->rd_min;
1269 1270 tmp_rd.rd_max = rd->rd_max;
1270 1271 tmp_rd.rd_pn = ptn;
1271 1272 if (enum_run(mp, &tmp_rd) < 0) {
1272 1273 /*
1273 1274 * Note the failure but continue on
1274 1275 */
1275 1276 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1276 1277 "pad_process: enumeration failed.\n");
1277 1278 }
1278 1279 tf_edata_free(mp, tmp_rd.rd_einfo);
1279 1280 }
1280 1281 /*
1281 1282 * Here we allocate an element in an intermediate data structure
1282 1283 * which keeps track property groups and dependents of the range
1283 1284 * currently being processed.
1284 1285 *
1285 1286 * This structure is referenced in pgroups_record() to create
1286 1287 * the actual property groups in the topo tree
1287 1288 */
1288 1289 if ((new = tf_pad_new(mp, pgcnt, dcnt)) == NULL)
1289 1290 return (-1);
1290 1291
1291 1292 if (pgcnt > 0) {
1292 1293 new->tpad_pgs =
1293 1294 topo_mod_zalloc(mp, pgcnt * sizeof (nvlist_t *));
1294 1295 if (new->tpad_pgs == NULL) {
1295 1296 tf_pad_free(mp, new);
1296 1297 return (-1);
1297 1298 }
1298 1299 }
1299 1300 /*
1300 1301 * If the property groups are contained within a set
1301 1302 * then they will be one level lower in the XML tree.
1302 1303 */
1303 1304 if (joined_set)
1304 1305 target = psn;
1305 1306 else
1306 1307 target = pxn;
1307 1308
1308 1309 /*
1309 1310 * If there is no "node" element under the "range"
1310 1311 * element, then we need to attach the facility node to
1311 1312 * each node in this range.
1312 1313 *
1313 1314 * Otherwise we only attach it to the current node
1314 1315 */
1315 1316 if (xmlStrcmp(target->name, (xmlChar *)Range) == 0 ||
1316 1317 xmlStrcmp(target->name, (xmlChar *)Set) == 0) {
1317 1318 for (ct = topo_child_first(rd->rd_pn);
1318 1319 ct != NULL;
1319 1320 ct = topo_child_next(rd->rd_pn, ct)) {
1320 1321
1321 1322 if (strcmp(topo_node_name(ct),
1322 1323 rd->rd_name) != 0)
1323 1324 continue;
1324 1325
1325 1326 inst = topo_node_instance(ct);
1326 1327 if (inst < rd->rd_min || inst > rd->rd_max)
1327 1328 continue;
1328 1329
1329 1330 if (fac_enum_process(mp, target, ct) < 0)
1330 1331 return (-1);
1331 1332
1332 1333 if (fac_process(mp, target, rd, ct) < 0)
1333 1334 return (-1);
1334 1335 }
1335 1336 } else {
1336 1337 if (fac_enum_process(mp, target, ptn) < 0)
1337 1338 return (-1);
1338 1339 if (fac_process(mp, target, rd, ptn) < 0)
1339 1340 return (-1);
1340 1341 }
1341 1342 if (pgcnt > 0 && pgroups_record(mp, target, ptn, rd->rd_name,
1342 1343 new, (const char *)pxn->name) < 0) {
1343 1344 tf_pad_free(mp, new);
1344 1345 return (-1);
1345 1346 }
1346 1347 *rpad = new;
1347 1348 }
1348 1349
1349 1350 if (new->tpad_dcnt > 0)
1350 1351 if (dependents_create(mp, rd->rd_finfo, new, pxn, ptn) < 0)
1351 1352 return (-1);
1352 1353
1353 1354 if (new->tpad_pgcnt > 0)
1354 1355 if (pgroups_create(mp, new, ptn) < 0)
1355 1356 return (-1);
1356 1357
1357 1358 return (0);
1358 1359 }
1359 1360
1360 1361
1361 1362 static int
1362 1363 fac_enum_process(topo_mod_t *mp, xmlNodePtr pn, tnode_t *ptn)
1363 1364 {
1364 1365 xmlNodePtr cn;
1365 1366 xmlChar *fprov = NULL;
1366 1367 int rv = 0;
1367 1368
1368 1369 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
|
↓ open down ↓ |
1335 lines elided |
↑ open up ↑ |
1369 1370 "fac_enum_process() called for %s=%d\n", topo_node_name(ptn),
1370 1371 topo_node_instance(ptn));
1371 1372
1372 1373 for (cn = pn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1373 1374
1374 1375 if (xmlStrcmp(cn->name, (xmlChar *)"fac-enum") != 0)
1375 1376 continue;
1376 1377
1377 1378 if ((fprov = xmlGetProp(cn, (xmlChar *)Provider)) == NULL)
1378 1379 goto fenumdone;
1379 -
1380 - if (xmlStrcmp(fprov, (xmlChar *)"fac_prov_ipmi") != 0) {
1381 - topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1382 - "Invalid provider specified: %s\n", fprov);
1383 - goto fenumdone;
1384 - }
1385 -
1386 1380 /*
1387 - * Invoke enum entry point in fac provider which will cause the
1388 - * facility enumeration node method to be registered.
1381 + * Invoke enum entry point in facility provider which will
1382 + * cause the facility enumeration node method to be
1383 + * registered.
1389 1384 */
1390 1385 if (fac_enum_run(mp, ptn, (const char *)fprov) != 0) {
1391 1386 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1392 1387 "fac_enum_process: enum entry point failed!\n");
1393 1388 goto fenumdone;
1394 1389 }
1395 1390 xmlFree(fprov);
1396 1391 }
1397 1392 return (0);
1398 1393 fenumdone:
1399 1394 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "fac-enum processing failed\n");
1400 1395
1401 1396 if (fprov != NULL)
1402 1397 xmlFree(fprov);
1403 1398
1404 1399 return (rv);
1405 1400 }
1406 1401
1407 1402
1408 1403 static int
1409 1404 fac_process(topo_mod_t *mp, xmlNodePtr pn, tf_rdata_t *rd, tnode_t *ptn)
1410 1405 {
1411 1406 xmlNodePtr cn;
1412 1407 xmlChar *fname = NULL, *ftype = NULL, *provider = NULL;
1413 1408 tnode_t *ntn = NULL;
1414 1409 tf_idata_t *newi;
1415 1410 int err;
1416 1411 topo_pgroup_info_t pgi;
1417 1412
1418 1413 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1419 1414 "fac_process() called for %s=%d\n", topo_node_name(ptn),
1420 1415 topo_node_instance(ptn));
1421 1416
1422 1417 for (cn = pn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1423 1418
1424 1419 if (xmlStrcmp(cn->name, (xmlChar *)Facility) != 0)
1425 1420 continue;
1426 1421
1427 1422 if ((fname = xmlGetProp(cn, (xmlChar *)Name)) == NULL)
1428 1423 goto facdone;
1429 1424
1430 1425 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1431 1426 "processing facility node '%s'\n", fname);
1432 1427
|
↓ open down ↓ |
34 lines elided |
↑ open up ↑ |
1433 1428 if ((ftype = xmlGetProp(cn, (xmlChar *)Type)) == NULL)
1434 1429 goto facdone;
1435 1430
1436 1431 if ((provider = xmlGetProp(cn, (xmlChar *)Provider)) == NULL)
1437 1432 goto facdone;
1438 1433
1439 1434 if (xmlStrcmp(ftype, (xmlChar *)Sensor) != 0 &&
1440 1435 xmlStrcmp(ftype, (xmlChar *)Indicator) != 0)
1441 1436 goto facdone;
1442 1437
1443 - if (xmlStrcmp(provider, (xmlChar *)"fac_prov_ipmi") != 0) {
1444 - topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "fac_process: "
1445 - "Invalid provider attr value: %s\n", provider);
1446 - goto facdone;
1447 - }
1448 -
1449 1438 if ((ntn = topo_node_facbind(mp, ptn, (char *)fname,
1450 1439 (char *)ftype)) == NULL)
1451 1440 goto facdone;
1452 1441
1453 1442 pgi.tpi_name = TOPO_PGROUP_FACILITY;
1454 1443 pgi.tpi_namestab = TOPO_STABILITY_PRIVATE;
1455 1444 pgi.tpi_datastab = TOPO_STABILITY_PRIVATE;
1456 1445 pgi.tpi_version = 1;
1457 1446 if (topo_pgroup_create(ntn, &pgi, &err) != 0) {
1458 1447 if (err != ETOPO_PROP_DEFD) {
1459 1448 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1460 1449 "pgroups create failure: %s\n",
1461 1450 topo_strerror(err));
1462 1451 return (-1);
1463 1452 }
1464 1453 }
1465 1454 /*
1466 - * Invoke enum entry point in fac_prov_ipmi module, which will
1467 - * cause the provider methods to be registered on this node
1455 + * Invoke enum entry point in the facility provider module,
1456 + * which will cause the provider methods to be registered on
1457 + * this node
1468 1458 */
1469 1459 if (fac_enum_run(mp, ntn, (const char *)provider) != 0) {
1470 1460 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "fac_process: "
1471 1461 "enum entry point failed for provider %s!\n",
1472 1462 provider);
1473 1463 goto facdone;
1474 1464 }
1475 1465
1476 1466 if ((newi = tf_idata_new(mp, 0, ntn)) == NULL)
1477 1467 goto facdone;
1478 1468
1479 1469 if (tf_idata_insert(&rd->rd_instances, newi) < 0)
1480 1470 goto facdone;
1481 1471
1482 1472 if (pad_process(mp, rd, cn, ntn, &newi->ti_pad) < 0)
1483 1473 goto facdone;
1484 1474
1485 1475 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "done with "
1486 1476 "facility %s=%s.\n", ftype, fname);
1487 1477
1488 1478 xmlFree(ftype);
1489 1479 xmlFree(fname);
1490 1480 xmlFree(provider);
1491 1481 }
1492 1482
1493 1483 return (0);
1494 1484
1495 1485 facdone:
1496 1486 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "facility processing failed\n");
1497 1487
1498 1488 if (ftype != NULL)
1499 1489 xmlFree(ftype);
1500 1490 if (fname != NULL)
1501 1491 xmlFree(fname);
1502 1492 if (provider != NULL)
1503 1493 xmlFree(provider);
1504 1494 if (ntn != NULL)
1505 1495 topo_node_unbind(ntn);
1506 1496
1507 1497 return (0);
1508 1498 }
1509 1499
1510 1500 static int
1511 1501 node_process(topo_mod_t *mp, xmlNodePtr nn, tf_rdata_t *rd)
1512 1502 {
1513 1503 xmlChar *str;
1514 1504 topo_instance_t inst;
1515 1505 tf_idata_t *newi;
1516 1506 tnode_t *ntn;
1517 1507 uint64_t ui;
1518 1508 int rv = -1;
1519 1509 int s = 0;
1520 1510
1521 1511 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1522 1512 "node_process %s\n", rd->rd_name);
1523 1513
1524 1514 if (xmlattr_to_int(mp, nn, Instance, &ui) < 0)
1525 1515 goto nodedone;
1526 1516 inst = (topo_instance_t)ui;
1527 1517
1528 1518 if ((str = xmlGetProp(nn, (xmlChar *)Static)) != NULL) {
1529 1519 if (xmlStrcmp(str, (xmlChar *)True) == 0)
1530 1520 s = 1;
1531 1521 xmlFree(str);
1532 1522 }
1533 1523
1534 1524 if (s == 0) {
1535 1525 if (topo_mod_enumerate(rd->rd_mod, rd->rd_pn,
1536 1526 rd->rd_finfo->tf_scheme, rd->rd_name, inst, inst,
1537 1527 s == 1 ? &s : NULL) < 0)
1538 1528 goto nodedone;
1539 1529 }
1540 1530 ntn = topo_node_lookup(rd->rd_pn, rd->rd_name, inst);
1541 1531
1542 1532 if (ntn == NULL) {
1543 1533
1544 1534 /*
1545 1535 * If this is a static node declaration, we can
1546 1536 * ignore the lookup failure and continue
1547 1537 * processing. Otherwise, something
1548 1538 * went wrong during enumeration
1549 1539 */
1550 1540 if (s == 1)
1551 1541 rv = 0;
1552 1542 goto nodedone;
1553 1543 }
1554 1544 if ((newi = tf_idata_new(mp, inst, ntn)) == NULL) {
1555 1545 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1556 1546 "node_process: tf_idata_new failed.\n");
1557 1547 goto nodedone;
1558 1548 }
1559 1549 if (tf_idata_insert(&rd->rd_instances, newi) < 0) {
1560 1550 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1561 1551 "node_process: tf_idata_insert failed.\n");
1562 1552 goto nodedone;
1563 1553 }
1564 1554 if (pad_process(mp, rd, nn, ntn, &newi->ti_pad) < 0)
1565 1555 goto nodedone;
1566 1556 if (fac_process(mp, nn, rd, ntn) < 0)
1567 1557 goto nodedone;
1568 1558 rv = 0;
1569 1559 nodedone:
1570 1560 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "done with node %s.\n",
1571 1561 rd->rd_name);
1572 1562 return (rv);
1573 1563 }
1574 1564
1575 1565 static tf_edata_t *
1576 1566 enum_attributes_process(topo_mod_t *mp, xmlNodePtr en)
1577 1567 {
1578 1568 tf_edata_t *einfo;
1579 1569 uint64_t ui;
1580 1570
1581 1571 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "enum_attributes_process\n");
1582 1572 if ((einfo = topo_mod_zalloc(mp, sizeof (tf_edata_t))) == NULL) {
1583 1573 (void) topo_mod_seterrno(mp, ETOPO_NOMEM);
1584 1574 return (NULL);
1585 1575 }
1586 1576 einfo->te_name = (char *)xmlGetProp(en, (xmlChar *)Name);
1587 1577 if (einfo->te_name == NULL) {
1588 1578 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1589 1579 "Enumerator name attribute missing.\n");
1590 1580 (void) topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
1591 1581 goto enodedone;
1592 1582 }
1593 1583
1594 1584 /*
1595 1585 * Check for recursive enumeration
1596 1586 */
1597 1587 if (strcmp(einfo->te_name, mp->tm_name) == 0) {
1598 1588 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1599 1589 "Recursive enumeration detected for %s\n",
1600 1590 einfo->te_name);
1601 1591 (void) topo_mod_seterrno(mp, ETOPO_ENUM_RECURS);
1602 1592 goto enodedone;
1603 1593 }
1604 1594 if (xmlattr_to_int(mp, en, Version, &ui) < 0)
1605 1595 goto enodedone;
1606 1596 einfo->te_vers = (int)ui;
1607 1597
1608 1598 return (einfo);
1609 1599
1610 1600 enodedone:
1611 1601 if (einfo->te_name != NULL)
1612 1602 xmlFree(einfo->te_name);
1613 1603 topo_mod_free(mp, einfo, sizeof (tf_edata_t));
1614 1604 return (NULL);
1615 1605 }
1616 1606
1617 1607 static int
1618 1608 enum_run(topo_mod_t *mp, tf_rdata_t *rd)
1619 1609 {
1620 1610 topo_hdl_t *thp = mp->tm_hdl;
1621 1611 int e = -1;
1622 1612
1623 1613 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "enum_run\n");
1624 1614 /*
1625 1615 * Check if the enumerator module is already loaded.
1626 1616 * Module loading is single-threaded at this point so there's
1627 1617 * no need to worry about the module going away or bumping the
1628 1618 * ref count.
1629 1619 */
1630 1620 if ((rd->rd_mod = topo_mod_lookup(thp, rd->rd_einfo->te_name,
1631 1621 0)) == NULL) {
1632 1622 if ((rd->rd_mod = topo_mod_load(mp, rd->rd_einfo->te_name,
1633 1623 rd->rd_einfo->te_vers)) == NULL) {
1634 1624 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1635 1625 "enum_run: mod_load of %s failed: %s.\n",
1636 1626 rd->rd_einfo->te_name,
1637 1627 topo_strerror(topo_mod_errno(mp)));
1638 1628 (void) topo_hdl_seterrno(thp, topo_mod_errno(mp));
1639 1629 return (e);
1640 1630 }
1641 1631 }
1642 1632 /*
1643 1633 * We're live, so let's enumerate.
1644 1634 */
1645 1635 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "enumerate request. (%s)\n",
1646 1636 rd->rd_einfo->te_name);
1647 1637 e = topo_mod_enumerate(rd->rd_mod, rd->rd_pn, rd->rd_einfo->te_name,
1648 1638 rd->rd_name, rd->rd_min, rd->rd_max, NULL);
1649 1639 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "back from enumeration. %d\n",
1650 1640 e);
1651 1641 if (e != 0) {
1652 1642 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1653 1643 "Enumeration failed (%s)\n",
1654 1644 topo_strerror(topo_mod_errno(mp)));
1655 1645 (void) topo_hdl_seterrno(thp, EMOD_PARTIAL_ENUM);
1656 1646 return (topo_mod_seterrno(mp, EMOD_PARTIAL_ENUM));
1657 1647 }
1658 1648 return (e);
1659 1649 }
1660 1650
1661 1651 static int
1662 1652 fac_enum_run(topo_mod_t *mp, tnode_t *node, const char *name)
1663 1653 {
1664 1654 topo_hdl_t *thp = mp->tm_hdl;
1665 1655 topo_mod_t *fmod;
1666 1656 int e = -1;
1667 1657
1668 1658 topo_dprintf(thp, TOPO_DBG_XML, "fac_enum_run\n");
1669 1659 /*
1670 1660 * Check if the enumerator module is already loaded.
1671 1661 * Module loading is single-threaded at this point so there's
1672 1662 * no need to worry about the module going away or bumping the
1673 1663 * ref count.
1674 1664 */
1675 1665 if ((fmod = topo_mod_lookup(thp, name, 0)) == NULL) {
1676 1666 if ((fmod = topo_mod_load(mp, name, TOPO_VERSION)) == NULL) {
1677 1667 topo_dprintf(thp, TOPO_DBG_ERR,
1678 1668 "fac_enum_run: mod_load of %s failed: %s.\n",
1679 1669 name, topo_strerror(topo_mod_errno(mp)));
1680 1670 (void) topo_hdl_seterrno(thp, topo_mod_errno(mp));
1681 1671 return (e);
1682 1672 }
1683 1673 }
1684 1674 /*
1685 1675 * We're live, so let's enumerate.
1686 1676 */
1687 1677 topo_dprintf(thp, TOPO_DBG_XML, "fac enumerate request. (%s)\n", name);
1688 1678 e = topo_mod_enumerate(fmod, node, name, name, 0, 0, NULL);
1689 1679 topo_dprintf(thp, TOPO_DBG_XML, "back from enumeration. %d\n", e);
1690 1680 if (e != 0) {
1691 1681 topo_dprintf(thp, TOPO_DBG_ERR,
1692 1682 "Facility provider enumeration failed (%s)\n",
1693 1683 topo_strerror(topo_mod_errno(mp)));
1694 1684 (void) topo_hdl_seterrno(thp, EMOD_PARTIAL_ENUM);
1695 1685 return (topo_mod_seterrno(mp, EMOD_PARTIAL_ENUM));
1696 1686 }
1697 1687 return (e);
1698 1688 }
1699 1689
1700 1690 int
1701 1691 decorate_nodes(topo_mod_t *mp, tf_rdata_t *rd, xmlNodePtr pxn, tnode_t *ptn,
1702 1692 tf_pad_t **rpad)
1703 1693 {
1704 1694 tnode_t *ctn;
1705 1695
1706 1696 ctn = topo_child_first(ptn);
1707 1697 while (ctn != NULL) {
1708 1698 /* Only care about instances within the range */
1709 1699 if (strcmp(topo_node_name(ctn), rd->rd_name) != 0) {
1710 1700 ctn = topo_child_next(ptn, ctn);
1711 1701 continue;
1712 1702 }
1713 1703 if (pad_process(mp, rd, pxn, ctn, rpad) < 0)
1714 1704 return (-1);
1715 1705 if (decorate_nodes(mp, rd, pxn, ctn, rpad) < 0)
1716 1706 return (-1);
1717 1707 ctn = topo_child_next(ptn, ctn);
1718 1708 }
1719 1709 return (0);
1720 1710 }
1721 1711
1722 1712 int
1723 1713 topo_xml_range_process(topo_mod_t *mp, xmlNodePtr rn, tf_rdata_t *rd)
1724 1714 {
1725 1715 /*
1726 1716 * The range may have several children xmlNodes, that may
1727 1717 * represent the enumeration method, property groups,
1728 1718 * dependents, nodes or services.
1729 1719 */
1730 1720 xmlNodePtr cn, enum_node = NULL, pmap_node = NULL;
1731 1721 xmlChar *pmap_name;
1732 1722 tnode_t *ct;
1733 1723 int e, ccnt = 0;
1734 1724
1735 1725 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "topo_xml_range_process\n"
1736 1726 "process %s range beneath %s\n", rd->rd_name,
1737 1727 topo_node_name(rd->rd_pn));
1738 1728
1739 1729 e = topo_node_range_create(mp,
1740 1730 rd->rd_pn, rd->rd_name, rd->rd_min, rd->rd_max);
1741 1731 if (e != 0 && topo_mod_errno(mp) != EMOD_NODE_DUP) {
1742 1732 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1743 1733 "Range create failed due to %s.\n",
1744 1734 topo_strerror(topo_mod_errno(mp)));
1745 1735 return (-1);
1746 1736 }
1747 1737
1748 1738 /*
1749 1739 * Before we process any of the other child xmlNodes, we iterate through
1750 1740 * the children and looking for either enum-method or propmap elements.
1751 1741 */
1752 1742 for (cn = rn->xmlChildrenNode; cn != NULL; cn = cn->next)
1753 1743 if (xmlStrcmp(cn->name, (xmlChar *)Enum_meth) == 0)
1754 1744 enum_node = cn;
1755 1745 else if (xmlStrcmp(cn->name, (xmlChar *)Propmap) == 0)
1756 1746 pmap_node = cn;
1757 1747
1758 1748 /*
1759 1749 * If we found an enum-method element, process it first
1760 1750 */
1761 1751 if (enum_node != NULL) {
1762 1752 if ((rd->rd_einfo = enum_attributes_process(mp, enum_node))
1763 1753 == NULL)
1764 1754 return (-1);
1765 1755 if (enum_run(mp, rd) < 0) {
1766 1756 /*
1767 1757 * Note the failure but continue on
1768 1758 */
1769 1759 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1770 1760 "Enumeration failed.\n");
1771 1761 }
1772 1762 }
1773 1763
1774 1764 /*
1775 1765 * Next, check if a propmap element was found and if so, load it in
1776 1766 * and parse it.
1777 1767 */
1778 1768 if (pmap_node != NULL) {
1779 1769 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "found a propmap "
1780 1770 "element\n");
1781 1771 if ((pmap_name = xmlGetProp(pmap_node, (xmlChar *)Name))
1782 1772 == NULL) {
1783 1773 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1784 1774 "propmap element missing name attribute.\n");
1785 1775 } else {
1786 1776 if (topo_file_load(mp, rd->rd_pn,
1787 1777 (const char *)pmap_name,
1788 1778 rd->rd_finfo->tf_scheme, 1) < 0) {
1789 1779
1790 1780 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1791 1781 "topo_xml_range_process: topo_file_load"
1792 1782 "failed: %s.\n",
1793 1783 topo_strerror(topo_mod_errno(mp)));
1794 1784 }
1795 1785 xmlFree(pmap_name);
1796 1786 }
1797 1787 }
1798 1788
1799 1789 /* Now look for nodes, i.e., hard instances */
1800 1790 for (cn = rn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1801 1791 if (xmlStrcmp(cn->name, (xmlChar *)Node) == 0) {
1802 1792 if (node_process(mp, cn, rd) < 0) {
1803 1793 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1804 1794 "node processing failed: %s.\n",
1805 1795 topo_strerror(topo_mod_errno(mp)));
1806 1796 return (topo_mod_seterrno(mp,
1807 1797 EMOD_PARTIAL_ENUM));
1808 1798 }
1809 1799 ccnt++;
1810 1800 }
1811 1801 }
1812 1802
1813 1803 /*
1814 1804 * Finally, process the property groups and dependents
1815 1805 *
1816 1806 * If the TF_PROPMAP flag is set for the XML file we're currently
1817 1807 * processing, then this XML file was loaded via propmap. In that case
1818 1808 * we call a special routine to recursively apply the propgroup settings
1819 1809 * to all of nodes in this range
1820 1810 */
1821 1811 if (rd->rd_finfo->tf_flags & TF_PROPMAP)
1822 1812 (void) decorate_nodes(mp, rd, rn, rd->rd_pn, &rd->rd_pad);
1823 1813 else {
1824 1814 ct = topo_child_first(rd->rd_pn);
1825 1815 while (ct != NULL) {
1826 1816 /* Only care about instances within the range */
1827 1817 if (strcmp(topo_node_name(ct), rd->rd_name) != 0) {
1828 1818 ct = topo_child_next(rd->rd_pn, ct);
1829 1819 continue;
1830 1820 }
1831 1821 if (pad_process(mp, rd, rn, ct, &rd->rd_pad)
1832 1822 < 0)
1833 1823 return (-1);
1834 1824
1835 1825 if (fac_process(mp, rn, rd, ct) < 0)
1836 1826 return (-1);
1837 1827
1838 1828 ct = topo_child_next(rd->rd_pn, ct);
1839 1829 ccnt++;
1840 1830 }
1841 1831 }
1842 1832
1843 1833 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "topo_xml_range_process: end "
1844 1834 "range process %s\n", rd->rd_name);
1845 1835
1846 1836 return (0);
1847 1837 }
1848 1838
1849 1839 static tf_rdata_t *
1850 1840 topo_xml_walk(topo_mod_t *mp,
1851 1841 tf_info_t *xinfo, xmlNodePtr croot, tnode_t *troot)
1852 1842 {
1853 1843 xmlNodePtr curr, def_set = NULL;
1854 1844 tf_rdata_t *rr, *pr, *rdp;
1855 1845 xmlChar *set;
1856 1846 char *key;
1857 1847 int joined_set = 0;
1858 1848
1859 1849 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "topo_xml_walk\n");
1860 1850 rr = pr = NULL;
1861 1851 /*
1862 1852 * First iterate through all the XML nodes at this level to look for
1863 1853 * set nodes.
1864 1854 */
1865 1855 for (curr = croot->xmlChildrenNode; curr != NULL; curr = curr->next) {
1866 1856 if (curr->name == NULL) {
1867 1857 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1868 1858 "topo_xml_walk: Ignoring nameless xmlnode\n");
1869 1859 continue;
1870 1860 }
1871 1861 if (xmlStrcmp(curr->name, (xmlChar *)Set) == 0) {
1872 1862 if (joined_set)
1873 1863 continue;
1874 1864
1875 1865 set = xmlGetProp(curr, (xmlChar *)Setlist);
1876 1866
1877 1867 if (mp->tm_hdl->th_product)
1878 1868 key = mp->tm_hdl->th_product;
1879 1869 else
1880 1870 key = mp->tm_hdl->th_platform;
1881 1871
1882 1872 /*
1883 1873 * If it's the default set then we'll store
1884 1874 * a pointer to it so that if none of the other
1885 1875 * sets apply to our product we can fall
1886 1876 * back to this one.
1887 1877 */
1888 1878 if (strcmp((char *)set, "default") == 0)
1889 1879 def_set = curr;
1890 1880 else if (set_contains(mp, key, (char *)set)) {
1891 1881 joined_set = 1;
1892 1882 if ((rdp = topo_xml_walk(mp, xinfo, curr,
1893 1883 troot)) == NULL) {
1894 1884 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1895 1885 "topo_xml_walk: failed1\n");
1896 1886 } else {
1897 1887 if (pr == NULL) {
1898 1888 rr = pr = rdp;
1899 1889 } else {
1900 1890 pr->rd_next = rdp;
1901 1891 pr = rdp;
1902 1892 }
1903 1893 rr->rd_cnt++;
1904 1894 }
1905 1895 }
1906 1896 xmlFree(set);
1907 1897 }
1908 1898 }
1909 1899 /*
1910 1900 * If we haven't found a set that contains our product AND a default set
1911 1901 * exists, then we'll process it.
1912 1902 */
1913 1903 if (!joined_set && def_set) {
1914 1904 if ((rdp = topo_xml_walk(mp, xinfo, def_set, troot)) == NULL) {
1915 1905 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1916 1906 "topo_xml_walk: failed2\n");
1917 1907 }
1918 1908 if (pr == NULL) {
1919 1909 rr = pr = rdp;
1920 1910 } else {
1921 1911 pr->rd_next = rdp;
1922 1912 pr = rdp;
1923 1913 }
1924 1914 rr->rd_cnt++;
1925 1915 }
1926 1916 /*
1927 1917 * Now we're interested in children xmlNodes of croot tagged
1928 1918 * as 'ranges'. These define what topology nodes may exist, and need
1929 1919 * to be verified.
1930 1920 */
1931 1921 for (curr = croot->xmlChildrenNode; curr != NULL; curr = curr->next) {
1932 1922 if (curr->name == NULL) {
1933 1923 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1934 1924 "topo_xml_walk: Ignoring nameless xmlnode\n");
1935 1925 continue;
1936 1926 }
1937 1927 if (xmlStrcmp(curr->name, (xmlChar *)Range) != 0)
1938 1928 continue;
1939 1929 if ((rdp = tf_rdata_new(mp, xinfo, curr, troot)) == NULL) {
1940 1930 /*
1941 1931 * Range processing error, continue walk
1942 1932 */
1943 1933 continue;
1944 1934 }
1945 1935 if (pr == NULL) {
1946 1936 rr = pr = rdp;
1947 1937 } else {
1948 1938 pr->rd_next = rdp;
1949 1939 pr = rdp;
1950 1940 }
1951 1941 rr->rd_cnt++;
1952 1942 }
1953 1943
1954 1944 return (rr);
1955 1945 }
1956 1946
1957 1947 /*
1958 1948 * Convert parsed xml topology description into topology nodes
1959 1949 */
1960 1950 int
1961 1951 topo_xml_enum(topo_mod_t *tmp, tf_info_t *xinfo, tnode_t *troot)
1962 1952 {
1963 1953 xmlNodePtr xroot;
1964 1954
1965 1955 topo_dprintf(tmp->tm_hdl, TOPO_DBG_XML, "topo_xml_enum\n");
1966 1956
1967 1957 if ((xroot = xmlDocGetRootElement(xinfo->tf_xdoc)) == NULL) {
1968 1958 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
1969 1959 "Couldn't get root xmlNode.\n");
1970 1960 return (-1);
1971 1961 }
1972 1962 if ((xinfo->tf_rd = topo_xml_walk(tmp, xinfo, xroot, troot)) == NULL) {
1973 1963 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
1974 1964 "error within .xml topology: %s\n",
1975 1965 topo_strerror(topo_mod_errno(tmp)));
1976 1966 return (-1);
1977 1967 }
1978 1968 return (0);
1979 1969 }
1980 1970
1981 1971 /*
1982 1972 * Load an XML tree from filename and read it into a DOM parse tree.
1983 1973 */
1984 1974 static tf_info_t *
1985 1975 txml_file_parse(topo_mod_t *tmp,
1986 1976 int fd, const char *filenm, const char *escheme)
1987 1977 {
1988 1978 xmlValidCtxtPtr vcp;
1989 1979 xmlNodePtr cursor;
1990 1980 xmlDocPtr document;
1991 1981 xmlDtdPtr dtd = NULL;
1992 1982 xmlChar *scheme = NULL;
1993 1983 char *dtdpath = NULL;
1994 1984 int readflags = 0;
1995 1985 tf_info_t *r;
1996 1986 int e, validate = 0;
1997 1987
1998 1988 topo_dprintf(tmp->tm_hdl, TOPO_DBG_XML,
1999 1989 "txml_file_parse(filenm=%s, escheme=%s)\n", filenm, escheme);
2000 1990
2001 1991 /*
2002 1992 * Since topologies can XInclude other topologies, and libxml2
2003 1993 * doesn't do DTD-based validation with XInclude, by default
2004 1994 * we don't validate topology files. One can force
2005 1995 * validation, though, by creating a TOPOXML_VALIDATE
2006 1996 * environment variable and creating a TOPO_DTD environment
2007 1997 * variable with the path to the DTD against which to validate.
2008 1998 */
2009 1999 if (getenv("TOPOXML_VALIDATE") != NULL) {
2010 2000 dtdpath = getenv("TOPO_DTD");
2011 2001 if (dtdpath != NULL)
2012 2002 xmlLoadExtDtdDefaultValue = 0;
2013 2003 validate = 1;
2014 2004 }
2015 2005
2016 2006 /*
2017 2007 * Splat warnings and errors related to parsing the topology
2018 2008 * file if the TOPOXML_PERROR environment variable exists.
2019 2009 */
2020 2010 if (getenv("TOPOXML_PERROR") == NULL)
2021 2011 readflags = XML_PARSE_NOERROR | XML_PARSE_NOWARNING;
2022 2012
2023 2013 if ((document = xmlReadFd(fd, filenm, NULL, readflags)) == NULL) {
2024 2014 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2025 2015 "txml_file_parse: couldn't parse document.\n");
2026 2016 return (NULL);
2027 2017 }
2028 2018
2029 2019 /*
2030 2020 * Verify that this is a document type we understand.
2031 2021 */
2032 2022 if ((dtd = xmlGetIntSubset(document)) == NULL) {
2033 2023 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2034 2024 "document has no DTD.\n");
2035 2025 xmlFreeDoc(document);
2036 2026 return (NULL);
2037 2027 }
2038 2028
2039 2029 if (strcmp((const char *)dtd->SystemID, TOPO_DTD_PATH) != 0) {
2040 2030 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2041 2031 "document DTD unknown; bad topology file\n");
2042 2032 xmlFreeDoc(document);
2043 2033 return (NULL);
2044 2034 }
2045 2035
2046 2036 if ((cursor = xmlDocGetRootElement(document)) == NULL) {
2047 2037 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR, "document is empty.\n");
2048 2038 xmlFreeDoc(document);
2049 2039 return (NULL);
2050 2040 }
2051 2041
2052 2042 /*
2053 2043 * Make sure we're looking at a topology description in the
2054 2044 * expected scheme.
2055 2045 */
2056 2046 if (xmlStrcmp(cursor->name, (xmlChar *)Topology) != 0) {
2057 2047 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2058 2048 "document is not a topology description.\n");
2059 2049 xmlFreeDoc(document);
2060 2050 return (NULL);
2061 2051 }
2062 2052 if ((scheme = xmlGetProp(cursor, (xmlChar *)Scheme)) == NULL) {
2063 2053 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2064 2054 "topology lacks a scheme.\n");
2065 2055 (void) topo_mod_seterrno(tmp, ETOPO_PRSR_NOATTR);
2066 2056 xmlFreeDoc(document);
2067 2057 return (NULL);
2068 2058 }
2069 2059 if (xmlStrcmp(scheme, (xmlChar *)escheme) != 0) {
2070 2060 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2071 2061 "topology in unrecognized scheme, %s, expecting %s\n",
2072 2062 scheme, escheme);
2073 2063 (void) topo_mod_seterrno(tmp, ETOPO_PRSR_BADSCH);
2074 2064 xmlFree(scheme);
2075 2065 xmlFreeDoc(document);
2076 2066 return (NULL);
2077 2067 }
2078 2068
2079 2069 if (dtdpath != NULL) {
2080 2070 dtd = xmlParseDTD(NULL, (xmlChar *)dtdpath);
2081 2071 if (dtd == NULL) {
2082 2072 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2083 2073 "Could not parse DTD \"%s\".\n",
2084 2074 dtdpath);
2085 2075 xmlFree(scheme);
2086 2076 xmlFreeDoc(document);
2087 2077 return (NULL);
2088 2078 }
2089 2079
2090 2080 if (document->extSubset != NULL)
2091 2081 xmlFreeDtd(document->extSubset);
2092 2082
2093 2083 document->extSubset = dtd;
2094 2084 }
2095 2085
2096 2086 if (xmlXIncludeProcessFlags(document, XML_PARSE_XINCLUDE) == -1) {
2097 2087 xmlFree(scheme);
2098 2088 xmlFreeDoc(document);
2099 2089 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2100 2090 "couldn't handle XInclude statements in document\n");
2101 2091 return (NULL);
2102 2092 }
2103 2093
2104 2094 if (validate) {
2105 2095 if ((vcp = xmlNewValidCtxt()) == NULL) {
2106 2096 xmlFree(scheme);
2107 2097 xmlFreeDoc(document);
2108 2098 return (NULL);
2109 2099 }
2110 2100 vcp->warning = xmlParserValidityWarning;
2111 2101 vcp->error = xmlParserValidityError;
2112 2102
2113 2103 e = xmlValidateDocument(vcp, document);
2114 2104
2115 2105 xmlFreeValidCtxt(vcp);
2116 2106
2117 2107 if (e == 0)
2118 2108 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2119 2109 "Document is not valid.\n");
2120 2110 }
2121 2111
2122 2112 if ((r = tf_info_new(tmp, document, scheme)) == NULL) {
2123 2113 xmlFree(scheme);
2124 2114 xmlFreeDoc(document);
2125 2115 return (NULL);
2126 2116 }
2127 2117
2128 2118 xmlFree(scheme);
2129 2119 scheme = NULL;
2130 2120 return (r);
2131 2121 }
2132 2122
2133 2123 tf_info_t *
2134 2124 topo_xml_read(topo_mod_t *tmp, const char *path, const char *escheme)
2135 2125 {
2136 2126 int fd;
2137 2127 tf_info_t *tip;
2138 2128
2139 2129 if ((fd = open(path, O_RDONLY)) < 0) {
2140 2130 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2141 2131 "failed to open %s for reading\n", path);
2142 2132 return (NULL);
2143 2133 }
2144 2134 tip = txml_file_parse(tmp, fd, path, escheme);
2145 2135 (void) close(fd);
2146 2136 return (tip);
2147 2137 }
|
↓ open down ↓ |
670 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX