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