1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1490 timh * Common Development and Distribution License (the "License"). 6 1490 timh * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 1490 timh 22 0 stevel /* 23 11202 Stephen * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 0 stevel * Use is subject to license terms. 25 1490 timh */ 26 1490 timh 27 1490 timh /* 28 0 stevel * config.c -- system configuration cache module 29 0 stevel * 30 0 stevel * this module caches the system configuration in a format useful 31 0 stevel * to eft. the information is loaded into this module by 32 0 stevel * config_snapshot() at the beginning of each FME. config_snapshot() 33 0 stevel * calls the platform-specific platform_config_snapshot() to get 34 0 stevel * the configuration information loaded up. 35 0 stevel */ 36 0 stevel 37 0 stevel #include <stdio.h> 38 0 stevel #include <stdlib.h> 39 0 stevel #include <ctype.h> 40 0 stevel #include <string.h> 41 0 stevel #include <strings.h> 42 3062 cindi #include <fm/topo_hc.h> 43 0 stevel #include "alloc.h" 44 0 stevel #include "out.h" 45 0 stevel #include "literals.h" 46 0 stevel #include "stable.h" 47 0 stevel #include "lut.h" 48 0 stevel #include "tree.h" 49 0 stevel #include "itree.h" 50 0 stevel #include "ipath.h" 51 0 stevel #include "ptree.h" 52 0 stevel #include "eval.h" 53 0 stevel #include "config.h" 54 5433 af #include "config_impl.h" 55 0 stevel #include "fme.h" 56 0 stevel #include "platform.h" 57 4436 stephh 58 4436 stephh static const char *config_lastcomp; 59 0 stevel 60 0 stevel /* 61 0 stevel * newcnode -- local function to allocate new config node 62 0 stevel */ 63 0 stevel static struct config * 64 0 stevel newcnode(const char *s, int num) 65 0 stevel { 66 0 stevel struct config *retval; 67 0 stevel 68 0 stevel retval = MALLOC(sizeof (struct config)); 69 0 stevel 70 0 stevel retval->s = s; 71 0 stevel retval->num = num; 72 0 stevel retval->next = NULL; 73 0 stevel retval->props = NULL; 74 0 stevel retval->child = retval->parent = NULL; 75 0 stevel 76 0 stevel return (retval); 77 0 stevel } 78 0 stevel 79 0 stevel /* 80 0 stevel * If we need to cache certain types of nodes for reverse look-up or 81 0 stevel * somesuch, do it here. Currently we need to cache nodes representing 82 0 stevel * cpus. 83 0 stevel */ 84 0 stevel static void 85 0 stevel config_node_cache(struct cfgdata *cdata, struct config *n) 86 0 stevel { 87 0 stevel if (n->s != stable("cpu")) 88 0 stevel return; 89 0 stevel cdata->cpucache = lut_add(cdata->cpucache, 90 0 stevel (void *)n->num, (void *)n, NULL); 91 0 stevel } 92 0 stevel 93 0 stevel /* 94 0 stevel * config_lookup -- lookup/add components in configuration cache 95 0 stevel */ 96 0 stevel struct config * 97 0 stevel config_lookup(struct config *croot, char *path, int add) 98 0 stevel { 99 0 stevel char *pathbegin = path; 100 0 stevel struct config *parent = croot; 101 0 stevel struct config *cp; 102 0 stevel struct config *lastcp; 103 0 stevel struct config *newnode; 104 0 stevel char *thiscom; /* this component */ 105 0 stevel char *nextcom; /* next component */ 106 0 stevel char svdigit; 107 0 stevel int len; 108 0 stevel int num; 109 0 stevel const char *s; 110 0 stevel int exists; 111 0 stevel 112 0 stevel if (parent == NULL) 113 0 stevel out(O_DIE, "uninitialized configuration"); 114 0 stevel 115 0 stevel while (*path) { 116 0 stevel if ((nextcom = strchr(path, '/')) != NULL) 117 0 stevel *nextcom = '\0'; 118 0 stevel if ((len = strlen(path)) == 0) 119 0 stevel out(O_DIE, "config_lookup: zero length component"); 120 0 stevel /* start at end of string and work backwards */ 121 0 stevel thiscom = &path[len - 1]; 122 0 stevel if (!isdigit(*thiscom)) 123 0 stevel out(O_DIE, "config_lookup: " 124 0 stevel "component \"%s\" has no number following it", 125 0 stevel path); 126 0 stevel while (thiscom > path && isdigit(*thiscom)) 127 0 stevel thiscom--; 128 0 stevel if (thiscom == path && isdigit(*thiscom)) 129 0 stevel out(O_DIE, "config_lookup: " 130 0 stevel "component \"%s\" has no name part", path); 131 0 stevel thiscom++; /* move to first numeric character */ 132 0 stevel num = atoi(thiscom); 133 0 stevel svdigit = *thiscom; 134 0 stevel *thiscom = '\0'; 135 0 stevel s = stable(path); 136 4436 stephh if (add) 137 4436 stephh config_lastcomp = s; 138 0 stevel *thiscom = svdigit; 139 0 stevel 140 0 stevel if (nextcom != NULL) 141 0 stevel *nextcom++ = '/'; 142 0 stevel 143 0 stevel /* now we have s & num, figure out if it exists already */ 144 0 stevel exists = 0; 145 0 stevel lastcp = NULL; 146 0 stevel for (cp = parent->child; cp; lastcp = cp, cp = cp->next) 147 0 stevel if (cp->s == s && cp->num == num) { 148 0 stevel exists = 1; 149 0 stevel parent = cp; 150 0 stevel } 151 0 stevel 152 0 stevel if (!exists) { 153 0 stevel /* creating new node */ 154 0 stevel if (!add) { 155 0 stevel /* 156 0 stevel * indicate component not found by copying 157 0 stevel * it to path (allows better error messages 158 0 stevel * in the caller). 159 0 stevel */ 160 0 stevel (void) strcpy(pathbegin, s); 161 0 stevel return (NULL); 162 0 stevel } 163 0 stevel 164 0 stevel newnode = newcnode(s, num); 165 0 stevel 166 0 stevel if (lastcp) 167 0 stevel lastcp->next = newnode; 168 0 stevel else 169 0 stevel parent->child = newnode; 170 0 stevel 171 0 stevel newnode->parent = parent; 172 0 stevel parent = newnode; 173 0 stevel } 174 0 stevel 175 0 stevel if (nextcom == NULL) 176 0 stevel return (parent); /* all done */ 177 0 stevel 178 0 stevel /* move on to next component */ 179 0 stevel path = nextcom; 180 0 stevel } 181 0 stevel return (parent); 182 0 stevel } 183 0 stevel 184 0 stevel /* 185 0 stevel * addconfigprop -- add a config prop to a config cache entry 186 0 stevel */ 187 0 stevel static void 188 0 stevel addconfigprop(const char *lhs, struct node *rhs, void *arg) 189 0 stevel { 190 0 stevel struct config *cp = (struct config *)arg; 191 0 stevel 192 0 stevel ASSERT(cp != NULL); 193 0 stevel ASSERT(lhs != NULL); 194 0 stevel ASSERT(rhs != NULL); 195 0 stevel ASSERT(rhs->t == T_QUOTE); 196 0 stevel 197 0 stevel config_setprop(cp, lhs, STRDUP(rhs->u.quote.s)); 198 0 stevel } 199 0 stevel 200 0 stevel /* 201 0 stevel * addconfig -- add a config from parse tree to given configuration cache 202 0 stevel */ 203 0 stevel /*ARGSUSED*/ 204 0 stevel static void 205 0 stevel addconfig(struct node *lhs, struct node *rhs, void *arg) 206 0 stevel { 207 0 stevel struct config *parent = (struct config *)arg; 208 0 stevel struct config *cp; 209 0 stevel const char *s; 210 0 stevel int num; 211 0 stevel struct config *lastcp; 212 0 stevel struct config *newnode; 213 0 stevel int exists; 214 0 stevel struct lut *lutp; 215 0 stevel 216 0 stevel ASSERT(rhs->t == T_CONFIG); 217 0 stevel 218 0 stevel lutp = rhs->u.stmt.lutp; 219 0 stevel rhs = rhs->u.stmt.np; 220 0 stevel while (rhs != NULL) { 221 0 stevel ASSERT(rhs->t == T_NAME); 222 0 stevel ASSERT(rhs->u.name.child->t == T_NUM); 223 0 stevel s = rhs->u.name.s; 224 0 stevel num = rhs->u.name.child->u.ull; 225 0 stevel 226 0 stevel /* now we have s & num, figure out if it exists already */ 227 0 stevel exists = 0; 228 0 stevel lastcp = NULL; 229 0 stevel for (cp = parent->child; cp; lastcp = cp, cp = cp->next) 230 0 stevel if (cp->s == s && cp->num == num) { 231 0 stevel exists = 1; 232 0 stevel parent = cp; 233 0 stevel } 234 0 stevel 235 0 stevel if (!exists) { 236 0 stevel /* creating new node */ 237 0 stevel 238 0 stevel newnode = newcnode(s, num); 239 0 stevel 240 0 stevel if (lastcp) 241 0 stevel lastcp->next = newnode; 242 0 stevel else 243 0 stevel parent->child = newnode; 244 0 stevel 245 4436 stephh newnode->parent = parent; 246 0 stevel parent = newnode; 247 0 stevel } 248 0 stevel 249 0 stevel /* move on to next component */ 250 0 stevel rhs = rhs->u.name.next; 251 0 stevel } 252 0 stevel 253 0 stevel /* add configuration properties */ 254 0 stevel lut_walk(lutp, (lut_cb)addconfigprop, (void *)parent); 255 0 stevel } 256 0 stevel 257 0 stevel /* 258 0 stevel * config_cook -- convert raw config strings to eft internal representation 259 0 stevel */ 260 0 stevel void 261 0 stevel config_cook(struct cfgdata *cdata) 262 0 stevel { 263 0 stevel struct config *newnode; 264 0 stevel char *cfgstr, *equals; 265 0 stevel const char *pn, *sv; 266 0 stevel char *pv; 267 4436 stephh const char *ptr; 268 4436 stephh extern struct lut *Usedprops; 269 4436 stephh extern struct lut *Usednames; 270 4436 stephh 271 0 stevel cdata->cooked = newcnode(NULL, 0); 272 0 stevel 273 0 stevel if ((cfgstr = cdata->begin) == cdata->nextfree) { 274 0 stevel out(O_ALTFP|O_VERB, "Platform provided no config data."); 275 0 stevel goto eftcfgs; 276 0 stevel } 277 4436 stephh 278 4436 stephh /* 279 4436 stephh * add the following properties to the "usedprops" table as they 280 4436 stephh * are used internally by eft 281 4436 stephh */ 282 4436 stephh ptr = stable("module"); 283 4436 stephh Usedprops = lut_add(Usedprops, (void *)ptr, (void *)ptr, NULL); 284 4436 stephh ptr = stable("resource"); 285 4436 stephh Usedprops = lut_add(Usedprops, (void *)ptr, (void *)ptr, NULL); 286 11202 Stephen ptr = stable("serial"); 287 11202 Stephen Usedprops = lut_add(Usedprops, (void *)ptr, (void *)ptr, NULL); 288 0 stevel 289 0 stevel out(O_ALTFP|O_VERB3, "Raw config data follows:"); 290 0 stevel out(O_ALTFP|O_VERB3|O_NONL, 291 0 stevel "nextfree is %p\n%p ", (void *)cdata->nextfree, (void *)cfgstr); 292 0 stevel while (cfgstr < cdata->nextfree) { 293 0 stevel if (!*cfgstr) 294 0 stevel out(O_ALTFP|O_VERB3|O_NONL, "\n%p ", 295 0 stevel (void *)(cfgstr + 1)); 296 0 stevel else 297 0 stevel out(O_ALTFP|O_VERB3|O_NONL, "%c", *cfgstr); 298 0 stevel cfgstr++; 299 0 stevel } 300 0 stevel out(O_ALTFP|O_VERB3, NULL); 301 0 stevel 302 0 stevel cfgstr = cdata->begin; 303 0 stevel while (cfgstr < cdata->nextfree) { 304 0 stevel while (*cfgstr == '/' && cfgstr < cdata->nextfree) { 305 0 stevel out(O_ALTFP|O_VERB3, 306 0 stevel "next string (%p) is %s", (void *)cfgstr, cfgstr); 307 0 stevel /* skip the initial slash from libtopo */ 308 0 stevel newnode = config_lookup(cdata->cooked, cfgstr + 1, 1); 309 0 stevel /* 310 0 stevel * Note we'll only cache nodes that have 311 0 stevel * properties on them. Intermediate nodes 312 0 stevel * will have been added to the config tree, 313 0 stevel * but we don't have easy means of accessing 314 0 stevel * them except if we climb the tree from this 315 0 stevel * newnode to the root. 316 0 stevel * 317 0 stevel * Luckily, the nodes we care to cache 318 0 stevel * (currently just cpus) always have some 319 0 stevel * properties attached to them 320 0 stevel * so we don't bother climbing the tree. 321 0 stevel */ 322 0 stevel config_node_cache(cdata, newnode); 323 0 stevel cfgstr += strlen(cfgstr) + 1; 324 0 stevel } 325 0 stevel 326 0 stevel if (cfgstr >= cdata->nextfree) 327 0 stevel break; 328 0 stevel 329 0 stevel out(O_ALTFP|O_VERB3, "next string (%p) is %s", (void *)cfgstr, 330 0 stevel cfgstr); 331 0 stevel if ((equals = strchr(cfgstr, '=')) == NULL) { 332 0 stevel out(O_ALTFP|O_VERB3, "raw config data bad (%p); " 333 0 stevel "property missing equals.\n", (void *)cfgstr); 334 0 stevel break; 335 0 stevel } 336 0 stevel 337 0 stevel *equals = '\0'; 338 0 stevel pn = stable(cfgstr); 339 0 stevel 340 4436 stephh /* 341 4436 stephh * only actually add the props if the rules use them (saves 342 4436 stephh * memory) 343 4436 stephh */ 344 5204 stephh if ((lut_lookup(Usedprops, (void *)pn, NULL) != NULL || 345 5204 stephh strncmp(pn, "serd_", 5) == 0) && lut_lookup(Usednames, 346 5204 stephh (void *)config_lastcomp, NULL) != NULL) { 347 4436 stephh pv = STRDUP(equals + 1); 348 4436 stephh out(O_ALTFP|O_VERB3, "add prop (%s) val %p", pn, 349 4436 stephh (void *)pv); 350 4436 stephh config_setprop(newnode, pn, pv); 351 4436 stephh } 352 0 stevel 353 0 stevel /* 354 6640 cth * If this property is a device path or devid, cache it 355 6640 cth * for quick lookup. 356 0 stevel */ 357 3062 cindi if (pn == stable(TOPO_IO_DEV)) { 358 4436 stephh sv = stable(equals + 1); 359 6640 cth out(O_ALTFP|O_VERB3, "caching dev %s\n", sv); 360 0 stevel cdata->devcache = lut_add(cdata->devcache, 361 6640 cth (void *)sv, (void *)newnode, NULL); 362 6640 cth } else if (pn == stable(TOPO_IO_DEVID)) { 363 6640 cth sv = stable(equals + 1); 364 6640 cth out(O_ALTFP|O_VERB3, "caching devid %s\n", sv); 365 6640 cth cdata->devidcache = lut_add(cdata->devidcache, 366 0 stevel (void *)sv, (void *)newnode, NULL); 367 0 stevel } 368 0 stevel 369 0 stevel *equals = '='; 370 0 stevel cfgstr += strlen(cfgstr) + 1; 371 0 stevel } 372 0 stevel 373 0 stevel eftcfgs: 374 0 stevel /* now run through Configs table, adding to config cache */ 375 0 stevel lut_walk(Configs, (lut_cb)addconfig, (void *)cdata->cooked); 376 0 stevel } 377 0 stevel 378 0 stevel /* 379 0 stevel * config_snapshot -- gather a snapshot of the current configuration 380 0 stevel */ 381 0 stevel struct cfgdata * 382 0 stevel config_snapshot(void) 383 0 stevel { 384 0 stevel struct cfgdata *rawcfg; 385 0 stevel 386 0 stevel rawcfg = platform_config_snapshot(); 387 0 stevel config_cook(rawcfg); 388 0 stevel return (rawcfg); 389 0 stevel } 390 0 stevel 391 0 stevel /* 392 0 stevel * prop_destructor -- free a prop value 393 0 stevel */ 394 0 stevel /*ARGSUSED*/ 395 0 stevel static void 396 0 stevel prop_destructor(void *left, void *right, void *arg) 397 0 stevel { 398 0 stevel FREE(right); 399 0 stevel } 400 0 stevel 401 0 stevel /* 402 0 stevel * structconfig_free -- free a struct config pointer and all its relatives 403 0 stevel */ 404 5204 stephh void 405 0 stevel structconfig_free(struct config *cp) 406 0 stevel { 407 0 stevel if (cp == NULL) 408 0 stevel return; 409 0 stevel 410 0 stevel structconfig_free(cp->child); 411 0 stevel structconfig_free(cp->next); 412 0 stevel lut_free(cp->props, prop_destructor, NULL); 413 0 stevel FREE(cp); 414 0 stevel } 415 0 stevel 416 0 stevel /* 417 0 stevel * config_free -- free a configuration snapshot 418 0 stevel */ 419 0 stevel void 420 0 stevel config_free(struct cfgdata *cp) 421 0 stevel { 422 0 stevel if (cp == NULL) 423 0 stevel return; 424 0 stevel 425 5204 stephh if (--cp->raw_refcnt == 0) { 426 4436 stephh if (cp->devcache != NULL) 427 4436 stephh lut_free(cp->devcache, NULL, NULL); 428 4436 stephh cp->devcache = NULL; 429 6640 cth if (cp->devidcache != NULL) 430 6640 cth lut_free(cp->devidcache, NULL, NULL); 431 6640 cth cp->devidcache = NULL; 432 4436 stephh if (cp->cpucache != NULL) 433 4436 stephh lut_free(cp->cpucache, NULL, NULL); 434 4436 stephh cp->cpucache = NULL; 435 4436 stephh if (cp->begin != NULL) 436 4436 stephh FREE(cp->begin); 437 4436 stephh FREE(cp); 438 4436 stephh } 439 0 stevel } 440 0 stevel 441 0 stevel /* 442 0 stevel * config_next -- get the "next" config node 443 0 stevel */ 444 0 stevel struct config * 445 0 stevel config_next(struct config *cp) 446 0 stevel { 447 0 stevel ASSERT(cp != NULL); 448 0 stevel 449 0 stevel return ((struct config *)((struct config *)cp)->next); 450 0 stevel } 451 0 stevel 452 0 stevel 453 0 stevel /* 454 0 stevel * config_child -- get the "child" of a config node 455 0 stevel */ 456 0 stevel struct config * 457 0 stevel config_child(struct config *cp) 458 0 stevel { 459 0 stevel ASSERT(cp != NULL); 460 0 stevel 461 0 stevel return ((struct config *)((struct config *)cp)->child); 462 4436 stephh } 463 4436 stephh 464 4436 stephh /* 465 4436 stephh * config_parent -- get the "parent" of a config node 466 4436 stephh */ 467 4436 stephh struct config * 468 4436 stephh config_parent(struct config *cp) 469 4436 stephh { 470 4436 stephh ASSERT(cp != NULL); 471 4436 stephh 472 4436 stephh return ((struct config *)((struct config *)cp)->parent); 473 0 stevel } 474 0 stevel 475 0 stevel /* 476 0 stevel * config_setprop -- add a property to a config node 477 0 stevel */ 478 0 stevel void 479 0 stevel config_setprop(struct config *cp, const char *propname, const char *propvalue) 480 0 stevel { 481 0 stevel const char *pn = stable(propname); 482 0 stevel 483 0 stevel cp->props = lut_add(cp->props, (void *)pn, (void *)propvalue, NULL); 484 0 stevel } 485 0 stevel 486 0 stevel /* 487 0 stevel * config_getprop -- lookup a config property 488 0 stevel */ 489 0 stevel const char * 490 0 stevel config_getprop(struct config *cp, const char *propname) 491 0 stevel { 492 0 stevel return (lut_lookup(cp->props, (void *) stable(propname), NULL)); 493 0 stevel } 494 0 stevel 495 0 stevel /* 496 0 stevel * config_getcompname -- get the component name of a config node 497 0 stevel */ 498 0 stevel void 499 0 stevel config_getcompname(struct config *cp, char **name, int *inst) 500 0 stevel { 501 0 stevel ASSERT(cp != NULL); 502 0 stevel 503 0 stevel if (name != NULL) 504 0 stevel *name = (char *)cp->s; 505 0 stevel if (inst != NULL) 506 0 stevel *inst = cp->num; 507 0 stevel } 508 0 stevel 509 0 stevel /* 510 0 stevel * config_nodeize -- convert the config element represented by cp to struct 511 0 stevel * node format 512 0 stevel */ 513 0 stevel static struct node * 514 0 stevel config_nodeize(struct config *cp) 515 0 stevel { 516 0 stevel struct node *tmpn, *ptmpn; 517 0 stevel struct node *numn; 518 0 stevel const char *sname; 519 0 stevel 520 0 stevel if (cp == NULL || cp->s == NULL) 521 0 stevel return (NULL); 522 0 stevel 523 0 stevel sname = stable(cp->s); 524 0 stevel numn = newnode(T_NUM, NULL, 0); 525 0 stevel numn->u.ull = cp->num; 526 0 stevel 527 0 stevel tmpn = tree_name_iterator(tree_name(sname, IT_VERTICAL, NULL, 0), numn); 528 0 stevel if ((ptmpn = config_nodeize(cp->parent)) == NULL) 529 0 stevel return (tmpn); 530 0 stevel return (tree_name_append(ptmpn, tmpn)); 531 0 stevel } 532 0 stevel 533 0 stevel /*ARGSUSED*/ 534 0 stevel static void 535 0 stevel prtdevcache(void *lhs, void *rhs, void *arg) 536 0 stevel { 537 0 stevel out(O_ALTFP|O_VERB3, "%s -> %p", (char *)lhs, rhs); 538 0 stevel } 539 0 stevel 540 0 stevel /*ARGSUSED*/ 541 0 stevel static void 542 6640 cth prtdevidcache(void *lhs, void *rhs, void *arg) 543 6640 cth { 544 6640 cth out(O_ALTFP|O_VERB3, "%s -> %p", (char *)lhs, rhs); 545 6640 cth } 546 6640 cth 547 6640 cth /*ARGSUSED*/ 548 6640 cth static void 549 0 stevel prtcpucache(void *lhs, void *rhs, void *arg) 550 0 stevel { 551 0 stevel out(O_ALTFP|O_VERB, "%u -> %p", (uint32_t)lhs, rhs); 552 0 stevel } 553 0 stevel 554 0 stevel /* 555 6640 cth * config_bydev_lookup -- look up the path in our devcache lut. If we find 556 0 stevel * it return the config path, but as a struct node. 557 0 stevel */ 558 0 stevel struct node * 559 0 stevel config_bydev_lookup(struct cfgdata *fromcfg, const char *path) 560 0 stevel { 561 0 stevel struct config *find; 562 0 stevel struct node *np; 563 0 stevel 564 0 stevel out(O_ALTFP|O_VERB3, "Device path cache:"); 565 0 stevel lut_walk(fromcfg->devcache, (lut_cb)prtdevcache, NULL); 566 0 stevel 567 0 stevel if ((find = lut_lookup(fromcfg->devcache, 568 0 stevel (void *) stable(path), NULL)) == NULL) 569 6640 cth return (NULL); 570 6640 cth 571 6640 cth np = config_nodeize(find); 572 6640 cth if (np != NULL) { 573 6640 cth out(O_ALTFP|O_VERB, "Matching config entry:"); 574 6640 cth ptree_name_iter(O_ALTFP|O_VERB|O_NONL, np); 575 6640 cth out(O_ALTFP|O_VERB, NULL); 576 6640 cth } 577 6640 cth return (np); 578 6640 cth } 579 6640 cth 580 6640 cth /* 581 6640 cth * config_bydevid_lookup -- look up the path in our DEVIDcache lut. 582 6640 cth * If we find it return the config path, but as a struct node. 583 6640 cth */ 584 6640 cth struct node * 585 6640 cth config_bydevid_lookup(struct cfgdata *fromcfg, const char *devid) 586 6640 cth { 587 6640 cth struct config *find; 588 6640 cth struct node *np; 589 6640 cth 590 6640 cth out(O_ALTFP|O_VERB3, "Device id cache:"); 591 6640 cth lut_walk(fromcfg->devcache, (lut_cb)prtdevidcache, NULL); 592 6640 cth 593 6640 cth if ((find = lut_lookup(fromcfg->devidcache, 594 6640 cth (void *) stable(devid), NULL)) == NULL) 595 0 stevel return (NULL); 596 0 stevel 597 0 stevel np = config_nodeize(find); 598 0 stevel if (np != NULL) { 599 0 stevel out(O_ALTFP|O_VERB, "Matching config entry:"); 600 0 stevel ptree_name_iter(O_ALTFP|O_VERB|O_NONL, np); 601 0 stevel out(O_ALTFP|O_VERB, NULL); 602 0 stevel } 603 0 stevel return (np); 604 0 stevel } 605 0 stevel 606 0 stevel /* 607 0 stevel * config_bycpuid_lookup -- look up the cpu id in our CPUcache lut. 608 0 stevel * If we find it return the config path, but as a struct node. 609 0 stevel */ 610 0 stevel struct node * 611 0 stevel config_bycpuid_lookup(struct cfgdata *fromcfg, uint32_t id) 612 0 stevel { 613 0 stevel struct config *find; 614 0 stevel struct node *np; 615 0 stevel 616 0 stevel out(O_ALTFP|O_VERB, "Cpu cache:"); 617 0 stevel lut_walk(fromcfg->cpucache, (lut_cb)prtcpucache, NULL); 618 0 stevel 619 0 stevel if ((find = lut_lookup(fromcfg->cpucache, 620 0 stevel (void *)id, NULL)) == NULL) 621 0 stevel return (NULL); 622 0 stevel 623 0 stevel np = config_nodeize(find); 624 0 stevel if (np != NULL) { 625 0 stevel out(O_ALTFP|O_VERB3, "Matching config entry:"); 626 0 stevel ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, np); 627 0 stevel out(O_ALTFP|O_VERB3, NULL); 628 0 stevel } 629 0 stevel return (np); 630 0 stevel } 631 0 stevel 632 0 stevel /* 633 0 stevel * printprop -- print prop associated with config node 634 0 stevel */ 635 0 stevel static void 636 0 stevel printprop(const char *lhs, const char *rhs, void *arg) 637 0 stevel { 638 0 stevel int flags = (int)arg; 639 0 stevel 640 0 stevel out(flags, "\t%s=%s", lhs, rhs); 641 0 stevel } 642 0 stevel 643 0 stevel /* 644 0 stevel * pconf -- internal printing function to recurse through the tree 645 0 stevel */ 646 0 stevel static void 647 0 stevel pconf(int flags, struct config *cp, char *buf, int offset, int limit) 648 0 stevel { 649 0 stevel char *sep = "/"; 650 0 stevel 651 0 stevel if (offset) 652 0 stevel sep = "/"; 653 0 stevel else 654 0 stevel sep = ""; 655 0 stevel (void) snprintf(&buf[offset], limit - offset, "%s%s%d", 656 0 stevel sep, cp->s, cp->num); 657 0 stevel if (cp->child == NULL) { 658 0 stevel out(flags, "%s", buf); 659 0 stevel lut_walk(cp->props, (lut_cb)printprop, (void *)flags); 660 0 stevel } else 661 0 stevel pconf(flags, cp->child, buf, strlen(buf), limit); 662 0 stevel if (cp->next) 663 0 stevel pconf(flags, cp->next, buf, offset, limit); 664 0 stevel } 665 0 stevel 666 0 stevel /* 667 0 stevel * config_print -- spew the current configuration cache 668 0 stevel */ 669 0 stevel 670 0 stevel #define MAXCONFLINE 4096 671 0 stevel 672 0 stevel void 673 0 stevel config_print(int flags, struct config *croot) 674 0 stevel { 675 0 stevel char buf[MAXCONFLINE]; 676 0 stevel 677 0 stevel if (croot == NULL) 678 0 stevel out(flags, "empty configuration"); 679 0 stevel else 680 0 stevel pconf(flags, croot->child, buf, 0, MAXCONFLINE); 681 0 stevel } 682