Home | History | Annotate | Download | only in eversholt
      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