10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51490Stimh * Common Development and Distribution License (the "License"). 61490Stimh * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211490Stimh 220Sstevel@tonic-gate /* 23*4436Sstephh * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 251490Stimh */ 261490Stimh 271490Stimh #pragma ident "%Z%%M% %I% %E% SMI" 281490Stimh 291490Stimh /* 300Sstevel@tonic-gate * config.c -- system configuration cache module 310Sstevel@tonic-gate * 320Sstevel@tonic-gate * this module caches the system configuration in a format useful 330Sstevel@tonic-gate * to eft. the information is loaded into this module by 340Sstevel@tonic-gate * config_snapshot() at the beginning of each FME. config_snapshot() 350Sstevel@tonic-gate * calls the platform-specific platform_config_snapshot() to get 360Sstevel@tonic-gate * the configuration information loaded up. 370Sstevel@tonic-gate */ 380Sstevel@tonic-gate 390Sstevel@tonic-gate #include <stdio.h> 400Sstevel@tonic-gate #include <stdlib.h> 410Sstevel@tonic-gate #include <ctype.h> 420Sstevel@tonic-gate #include <string.h> 430Sstevel@tonic-gate #include <strings.h> 443062Scindi #include <fm/topo_hc.h> 450Sstevel@tonic-gate #include "alloc.h" 460Sstevel@tonic-gate #include "out.h" 470Sstevel@tonic-gate #include "literals.h" 480Sstevel@tonic-gate #include "stable.h" 490Sstevel@tonic-gate #include "lut.h" 500Sstevel@tonic-gate #include "tree.h" 510Sstevel@tonic-gate #include "itree.h" 520Sstevel@tonic-gate #include "ipath.h" 530Sstevel@tonic-gate #include "ptree.h" 540Sstevel@tonic-gate #include "eval.h" 550Sstevel@tonic-gate #include "config.h" 560Sstevel@tonic-gate #include "fme.h" 570Sstevel@tonic-gate #include "platform.h" 580Sstevel@tonic-gate 590Sstevel@tonic-gate /* 600Sstevel@tonic-gate * private data structure for storing config. all access to 610Sstevel@tonic-gate * to this information happens using the config.h interfaces. 620Sstevel@tonic-gate */ 630Sstevel@tonic-gate struct config { 640Sstevel@tonic-gate struct config *next; 650Sstevel@tonic-gate struct config *child; 660Sstevel@tonic-gate struct config *parent; 670Sstevel@tonic-gate const char *s; 680Sstevel@tonic-gate int num; 690Sstevel@tonic-gate struct lut *props; 700Sstevel@tonic-gate }; 710Sstevel@tonic-gate 72*4436Sstephh static const char *config_lastcomp; 73*4436Sstephh 740Sstevel@tonic-gate /* 750Sstevel@tonic-gate * newcnode -- local function to allocate new config node 760Sstevel@tonic-gate */ 770Sstevel@tonic-gate static struct config * 780Sstevel@tonic-gate newcnode(const char *s, int num) 790Sstevel@tonic-gate { 800Sstevel@tonic-gate struct config *retval; 810Sstevel@tonic-gate 820Sstevel@tonic-gate retval = MALLOC(sizeof (struct config)); 830Sstevel@tonic-gate 840Sstevel@tonic-gate retval->s = s; 850Sstevel@tonic-gate retval->num = num; 860Sstevel@tonic-gate retval->next = NULL; 870Sstevel@tonic-gate retval->props = NULL; 880Sstevel@tonic-gate retval->child = retval->parent = NULL; 890Sstevel@tonic-gate 900Sstevel@tonic-gate return (retval); 910Sstevel@tonic-gate } 920Sstevel@tonic-gate 930Sstevel@tonic-gate /* 940Sstevel@tonic-gate * If we need to cache certain types of nodes for reverse look-up or 950Sstevel@tonic-gate * somesuch, do it here. Currently we need to cache nodes representing 960Sstevel@tonic-gate * cpus. 970Sstevel@tonic-gate */ 980Sstevel@tonic-gate static void 990Sstevel@tonic-gate config_node_cache(struct cfgdata *cdata, struct config *n) 1000Sstevel@tonic-gate { 1010Sstevel@tonic-gate if (n->s != stable("cpu")) 1020Sstevel@tonic-gate return; 1030Sstevel@tonic-gate cdata->cpucache = lut_add(cdata->cpucache, 1040Sstevel@tonic-gate (void *)n->num, (void *)n, NULL); 1050Sstevel@tonic-gate } 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate /* 1080Sstevel@tonic-gate * config_lookup -- lookup/add components in configuration cache 1090Sstevel@tonic-gate */ 1100Sstevel@tonic-gate struct config * 1110Sstevel@tonic-gate config_lookup(struct config *croot, char *path, int add) 1120Sstevel@tonic-gate { 1130Sstevel@tonic-gate char *pathbegin = path; 1140Sstevel@tonic-gate struct config *parent = croot; 1150Sstevel@tonic-gate struct config *cp; 1160Sstevel@tonic-gate struct config *lastcp; 1170Sstevel@tonic-gate struct config *newnode; 1180Sstevel@tonic-gate char *thiscom; /* this component */ 1190Sstevel@tonic-gate char *nextcom; /* next component */ 1200Sstevel@tonic-gate char svdigit; 1210Sstevel@tonic-gate int len; 1220Sstevel@tonic-gate int num; 1230Sstevel@tonic-gate const char *s; 1240Sstevel@tonic-gate int exists; 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate if (parent == NULL) 1270Sstevel@tonic-gate out(O_DIE, "uninitialized configuration"); 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate while (*path) { 1300Sstevel@tonic-gate if ((nextcom = strchr(path, '/')) != NULL) 1310Sstevel@tonic-gate *nextcom = '\0'; 1320Sstevel@tonic-gate if ((len = strlen(path)) == 0) 1330Sstevel@tonic-gate out(O_DIE, "config_lookup: zero length component"); 1340Sstevel@tonic-gate /* start at end of string and work backwards */ 1350Sstevel@tonic-gate thiscom = &path[len - 1]; 1360Sstevel@tonic-gate if (!isdigit(*thiscom)) 1370Sstevel@tonic-gate out(O_DIE, "config_lookup: " 1380Sstevel@tonic-gate "component \"%s\" has no number following it", 1390Sstevel@tonic-gate path); 1400Sstevel@tonic-gate while (thiscom > path && isdigit(*thiscom)) 1410Sstevel@tonic-gate thiscom--; 1420Sstevel@tonic-gate if (thiscom == path && isdigit(*thiscom)) 1430Sstevel@tonic-gate out(O_DIE, "config_lookup: " 1440Sstevel@tonic-gate "component \"%s\" has no name part", path); 1450Sstevel@tonic-gate thiscom++; /* move to first numeric character */ 1460Sstevel@tonic-gate num = atoi(thiscom); 1470Sstevel@tonic-gate svdigit = *thiscom; 1480Sstevel@tonic-gate *thiscom = '\0'; 1490Sstevel@tonic-gate s = stable(path); 150*4436Sstephh if (add) 151*4436Sstephh config_lastcomp = s; 1520Sstevel@tonic-gate *thiscom = svdigit; 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate if (nextcom != NULL) 1550Sstevel@tonic-gate *nextcom++ = '/'; 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate /* now we have s & num, figure out if it exists already */ 1580Sstevel@tonic-gate exists = 0; 1590Sstevel@tonic-gate lastcp = NULL; 1600Sstevel@tonic-gate for (cp = parent->child; cp; lastcp = cp, cp = cp->next) 1610Sstevel@tonic-gate if (cp->s == s && cp->num == num) { 1620Sstevel@tonic-gate exists = 1; 1630Sstevel@tonic-gate parent = cp; 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate if (!exists) { 1670Sstevel@tonic-gate /* creating new node */ 1680Sstevel@tonic-gate if (!add) { 1690Sstevel@tonic-gate /* 1700Sstevel@tonic-gate * indicate component not found by copying 1710Sstevel@tonic-gate * it to path (allows better error messages 1720Sstevel@tonic-gate * in the caller). 1730Sstevel@tonic-gate */ 1740Sstevel@tonic-gate (void) strcpy(pathbegin, s); 1750Sstevel@tonic-gate return (NULL); 1760Sstevel@tonic-gate } 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate newnode = newcnode(s, num); 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate if (lastcp) 1810Sstevel@tonic-gate lastcp->next = newnode; 1820Sstevel@tonic-gate else 1830Sstevel@tonic-gate parent->child = newnode; 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate newnode->parent = parent; 1860Sstevel@tonic-gate parent = newnode; 1870Sstevel@tonic-gate } 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate if (nextcom == NULL) 1900Sstevel@tonic-gate return (parent); /* all done */ 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate /* move on to next component */ 1930Sstevel@tonic-gate path = nextcom; 1940Sstevel@tonic-gate } 1950Sstevel@tonic-gate return (parent); 1960Sstevel@tonic-gate } 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate /* 1990Sstevel@tonic-gate * addconfigprop -- add a config prop to a config cache entry 2000Sstevel@tonic-gate */ 2010Sstevel@tonic-gate static void 2020Sstevel@tonic-gate addconfigprop(const char *lhs, struct node *rhs, void *arg) 2030Sstevel@tonic-gate { 2040Sstevel@tonic-gate struct config *cp = (struct config *)arg; 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate ASSERT(cp != NULL); 2070Sstevel@tonic-gate ASSERT(lhs != NULL); 2080Sstevel@tonic-gate ASSERT(rhs != NULL); 2090Sstevel@tonic-gate ASSERT(rhs->t == T_QUOTE); 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate config_setprop(cp, lhs, STRDUP(rhs->u.quote.s)); 2120Sstevel@tonic-gate } 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate /* 2150Sstevel@tonic-gate * addconfig -- add a config from parse tree to given configuration cache 2160Sstevel@tonic-gate */ 2170Sstevel@tonic-gate /*ARGSUSED*/ 2180Sstevel@tonic-gate static void 2190Sstevel@tonic-gate addconfig(struct node *lhs, struct node *rhs, void *arg) 2200Sstevel@tonic-gate { 2210Sstevel@tonic-gate struct config *parent = (struct config *)arg; 2220Sstevel@tonic-gate struct config *cp; 2230Sstevel@tonic-gate const char *s; 2240Sstevel@tonic-gate int num; 2250Sstevel@tonic-gate struct config *lastcp; 2260Sstevel@tonic-gate struct config *newnode; 2270Sstevel@tonic-gate int exists; 2280Sstevel@tonic-gate struct lut *lutp; 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate ASSERT(rhs->t == T_CONFIG); 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate lutp = rhs->u.stmt.lutp; 2330Sstevel@tonic-gate rhs = rhs->u.stmt.np; 2340Sstevel@tonic-gate while (rhs != NULL) { 2350Sstevel@tonic-gate ASSERT(rhs->t == T_NAME); 2360Sstevel@tonic-gate ASSERT(rhs->u.name.child->t == T_NUM); 2370Sstevel@tonic-gate s = rhs->u.name.s; 2380Sstevel@tonic-gate num = rhs->u.name.child->u.ull; 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate /* now we have s & num, figure out if it exists already */ 2410Sstevel@tonic-gate exists = 0; 2420Sstevel@tonic-gate lastcp = NULL; 2430Sstevel@tonic-gate for (cp = parent->child; cp; lastcp = cp, cp = cp->next) 2440Sstevel@tonic-gate if (cp->s == s && cp->num == num) { 2450Sstevel@tonic-gate exists = 1; 2460Sstevel@tonic-gate parent = cp; 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate if (!exists) { 2500Sstevel@tonic-gate /* creating new node */ 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate newnode = newcnode(s, num); 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate if (lastcp) 2550Sstevel@tonic-gate lastcp->next = newnode; 2560Sstevel@tonic-gate else 2570Sstevel@tonic-gate parent->child = newnode; 2580Sstevel@tonic-gate 259*4436Sstephh newnode->parent = parent; 2600Sstevel@tonic-gate parent = newnode; 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate /* move on to next component */ 2640Sstevel@tonic-gate rhs = rhs->u.name.next; 2650Sstevel@tonic-gate } 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate /* add configuration properties */ 2680Sstevel@tonic-gate lut_walk(lutp, (lut_cb)addconfigprop, (void *)parent); 2690Sstevel@tonic-gate } 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate /* 2720Sstevel@tonic-gate * config_cook -- convert raw config strings to eft internal representation 2730Sstevel@tonic-gate */ 2740Sstevel@tonic-gate void 2750Sstevel@tonic-gate config_cook(struct cfgdata *cdata) 2760Sstevel@tonic-gate { 2770Sstevel@tonic-gate struct config *newnode; 2780Sstevel@tonic-gate char *cfgstr, *equals; 2790Sstevel@tonic-gate const char *pn, *sv; 2800Sstevel@tonic-gate char *pv; 281*4436Sstephh const char *ptr; 282*4436Sstephh extern struct lut *Usedprops; 283*4436Sstephh extern struct lut *Usednames; 284*4436Sstephh 285*4436Sstephh cdata->cooked_refcnt++; 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate if (cdata->cooked != NULL) 2880Sstevel@tonic-gate return; 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate cdata->cooked = newcnode(NULL, 0); 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate if ((cfgstr = cdata->begin) == cdata->nextfree) { 2930Sstevel@tonic-gate out(O_ALTFP|O_VERB, "Platform provided no config data."); 2940Sstevel@tonic-gate goto eftcfgs; 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate 297*4436Sstephh /* 298*4436Sstephh * add the following properties to the "usedprops" table as they 299*4436Sstephh * are used internally by eft 300*4436Sstephh */ 301*4436Sstephh ptr = stable("module"); 302*4436Sstephh Usedprops = lut_add(Usedprops, (void *)ptr, (void *)ptr, NULL); 303*4436Sstephh ptr = stable("resource"); 304*4436Sstephh Usedprops = lut_add(Usedprops, (void *)ptr, (void *)ptr, NULL); 305*4436Sstephh ptr = stable("ASRU"); 306*4436Sstephh Usedprops = lut_add(Usedprops, (void *)ptr, (void *)ptr, NULL); 307*4436Sstephh ptr = stable("FRU"); 308*4436Sstephh Usedprops = lut_add(Usedprops, (void *)ptr, (void *)ptr, NULL); 309*4436Sstephh 3100Sstevel@tonic-gate out(O_ALTFP|O_VERB3, "Raw config data follows:"); 3110Sstevel@tonic-gate out(O_ALTFP|O_VERB3|O_NONL, 3120Sstevel@tonic-gate "nextfree is %p\n%p ", (void *)cdata->nextfree, (void *)cfgstr); 3130Sstevel@tonic-gate while (cfgstr < cdata->nextfree) { 3140Sstevel@tonic-gate if (!*cfgstr) 3150Sstevel@tonic-gate out(O_ALTFP|O_VERB3|O_NONL, "\n%p ", 3160Sstevel@tonic-gate (void *)(cfgstr + 1)); 3170Sstevel@tonic-gate else 3180Sstevel@tonic-gate out(O_ALTFP|O_VERB3|O_NONL, "%c", *cfgstr); 3190Sstevel@tonic-gate cfgstr++; 3200Sstevel@tonic-gate } 3210Sstevel@tonic-gate out(O_ALTFP|O_VERB3, NULL); 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate cfgstr = cdata->begin; 3240Sstevel@tonic-gate while (cfgstr < cdata->nextfree) { 3250Sstevel@tonic-gate while (*cfgstr == '/' && cfgstr < cdata->nextfree) { 3260Sstevel@tonic-gate out(O_ALTFP|O_VERB3, 3270Sstevel@tonic-gate "next string (%p) is %s", (void *)cfgstr, cfgstr); 3280Sstevel@tonic-gate /* skip the initial slash from libtopo */ 3290Sstevel@tonic-gate newnode = config_lookup(cdata->cooked, cfgstr + 1, 1); 3300Sstevel@tonic-gate /* 3310Sstevel@tonic-gate * Note we'll only cache nodes that have 3320Sstevel@tonic-gate * properties on them. Intermediate nodes 3330Sstevel@tonic-gate * will have been added to the config tree, 3340Sstevel@tonic-gate * but we don't have easy means of accessing 3350Sstevel@tonic-gate * them except if we climb the tree from this 3360Sstevel@tonic-gate * newnode to the root. 3370Sstevel@tonic-gate * 3380Sstevel@tonic-gate * Luckily, the nodes we care to cache 3390Sstevel@tonic-gate * (currently just cpus) always have some 3400Sstevel@tonic-gate * properties attached to them 3410Sstevel@tonic-gate * so we don't bother climbing the tree. 3420Sstevel@tonic-gate */ 3430Sstevel@tonic-gate config_node_cache(cdata, newnode); 3440Sstevel@tonic-gate cfgstr += strlen(cfgstr) + 1; 3450Sstevel@tonic-gate } 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate if (cfgstr >= cdata->nextfree) 3480Sstevel@tonic-gate break; 3490Sstevel@tonic-gate 3500Sstevel@tonic-gate out(O_ALTFP|O_VERB3, "next string (%p) is %s", (void *)cfgstr, 3510Sstevel@tonic-gate cfgstr); 3520Sstevel@tonic-gate if ((equals = strchr(cfgstr, '=')) == NULL) { 3530Sstevel@tonic-gate out(O_ALTFP|O_VERB3, "raw config data bad (%p); " 3540Sstevel@tonic-gate "property missing equals.\n", (void *)cfgstr); 3550Sstevel@tonic-gate break; 3560Sstevel@tonic-gate } 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate *equals = '\0'; 3590Sstevel@tonic-gate pn = stable(cfgstr); 3600Sstevel@tonic-gate 361*4436Sstephh /* 362*4436Sstephh * only actually add the props if the rules use them (saves 363*4436Sstephh * memory) 364*4436Sstephh */ 365*4436Sstephh if (lut_lookup(Usedprops, (void *)pn, NULL) != NULL && 366*4436Sstephh lut_lookup(Usednames, (void *)config_lastcomp, NULL) != 367*4436Sstephh NULL) { 368*4436Sstephh pv = STRDUP(equals + 1); 369*4436Sstephh out(O_ALTFP|O_VERB3, "add prop (%s) val %p", pn, 370*4436Sstephh (void *)pv); 371*4436Sstephh config_setprop(newnode, pn, pv); 372*4436Sstephh } 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate /* 3750Sstevel@tonic-gate * If this property is a device path, cache it for quick lookup 3760Sstevel@tonic-gate */ 3773062Scindi if (pn == stable(TOPO_IO_DEV)) { 378*4436Sstephh sv = stable(equals + 1); 3790Sstevel@tonic-gate out(O_ALTFP|O_VERB3, "caching %s\n", sv); 3800Sstevel@tonic-gate cdata->devcache = lut_add(cdata->devcache, 3810Sstevel@tonic-gate (void *)sv, (void *)newnode, NULL); 3820Sstevel@tonic-gate } 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate *equals = '='; 3850Sstevel@tonic-gate cfgstr += strlen(cfgstr) + 1; 3860Sstevel@tonic-gate } 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate eftcfgs: 3890Sstevel@tonic-gate /* now run through Configs table, adding to config cache */ 3900Sstevel@tonic-gate lut_walk(Configs, (lut_cb)addconfig, (void *)cdata->cooked); 3910Sstevel@tonic-gate } 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate /* 3940Sstevel@tonic-gate * config_snapshot -- gather a snapshot of the current configuration 3950Sstevel@tonic-gate */ 3960Sstevel@tonic-gate struct cfgdata * 3970Sstevel@tonic-gate config_snapshot(void) 3980Sstevel@tonic-gate { 3990Sstevel@tonic-gate struct cfgdata *rawcfg; 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate rawcfg = platform_config_snapshot(); 4020Sstevel@tonic-gate config_cook(rawcfg); 4030Sstevel@tonic-gate return (rawcfg); 4040Sstevel@tonic-gate } 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate /* 4070Sstevel@tonic-gate * prop_destructor -- free a prop value 4080Sstevel@tonic-gate */ 4090Sstevel@tonic-gate /*ARGSUSED*/ 4100Sstevel@tonic-gate static void 4110Sstevel@tonic-gate prop_destructor(void *left, void *right, void *arg) 4120Sstevel@tonic-gate { 4130Sstevel@tonic-gate FREE(right); 4140Sstevel@tonic-gate } 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate /* 4170Sstevel@tonic-gate * structconfig_free -- free a struct config pointer and all its relatives 4180Sstevel@tonic-gate */ 4190Sstevel@tonic-gate static void 4200Sstevel@tonic-gate structconfig_free(struct config *cp) 4210Sstevel@tonic-gate { 4220Sstevel@tonic-gate if (cp == NULL) 4230Sstevel@tonic-gate return; 4240Sstevel@tonic-gate 4250Sstevel@tonic-gate structconfig_free(cp->child); 4260Sstevel@tonic-gate structconfig_free(cp->next); 4270Sstevel@tonic-gate lut_free(cp->props, prop_destructor, NULL); 4280Sstevel@tonic-gate FREE(cp); 4290Sstevel@tonic-gate } 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate /* 4320Sstevel@tonic-gate * config_free -- free a configuration snapshot 4330Sstevel@tonic-gate */ 4340Sstevel@tonic-gate void 4350Sstevel@tonic-gate config_free(struct cfgdata *cp) 4360Sstevel@tonic-gate { 4370Sstevel@tonic-gate if (cp == NULL) 4380Sstevel@tonic-gate return; 4390Sstevel@tonic-gate 440*4436Sstephh if (--cp->cooked_refcnt == 0) { 441*4436Sstephh if (cp->cooked != NULL) 442*4436Sstephh structconfig_free(cp->cooked); 443*4436Sstephh cp->cooked = NULL; 444*4436Sstephh if (cp->devcache != NULL) 445*4436Sstephh lut_free(cp->devcache, NULL, NULL); 446*4436Sstephh cp->devcache = NULL; 447*4436Sstephh if (cp->cpucache != NULL) 448*4436Sstephh lut_free(cp->cpucache, NULL, NULL); 449*4436Sstephh cp->cpucache = NULL; 450*4436Sstephh } 4510Sstevel@tonic-gate 452*4436Sstephh if (--cp->raw_refcnt == 0) { 453*4436Sstephh if (cp->begin != NULL) 454*4436Sstephh FREE(cp->begin); 455*4436Sstephh FREE(cp); 456*4436Sstephh } 4570Sstevel@tonic-gate } 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate /* 4600Sstevel@tonic-gate * config_next -- get the "next" config node 4610Sstevel@tonic-gate */ 4620Sstevel@tonic-gate struct config * 4630Sstevel@tonic-gate config_next(struct config *cp) 4640Sstevel@tonic-gate { 4650Sstevel@tonic-gate ASSERT(cp != NULL); 4660Sstevel@tonic-gate 4670Sstevel@tonic-gate return ((struct config *)((struct config *)cp)->next); 4680Sstevel@tonic-gate } 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate /* 4720Sstevel@tonic-gate * config_child -- get the "child" of a config node 4730Sstevel@tonic-gate */ 4740Sstevel@tonic-gate struct config * 4750Sstevel@tonic-gate config_child(struct config *cp) 4760Sstevel@tonic-gate { 4770Sstevel@tonic-gate ASSERT(cp != NULL); 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate return ((struct config *)((struct config *)cp)->child); 4800Sstevel@tonic-gate } 4810Sstevel@tonic-gate 4820Sstevel@tonic-gate /* 483*4436Sstephh * config_parent -- get the "parent" of a config node 484*4436Sstephh */ 485*4436Sstephh struct config * 486*4436Sstephh config_parent(struct config *cp) 487*4436Sstephh { 488*4436Sstephh ASSERT(cp != NULL); 489*4436Sstephh 490*4436Sstephh return ((struct config *)((struct config *)cp)->parent); 491*4436Sstephh } 492*4436Sstephh 493*4436Sstephh /* 4940Sstevel@tonic-gate * config_setprop -- add a property to a config node 4950Sstevel@tonic-gate */ 4960Sstevel@tonic-gate void 4970Sstevel@tonic-gate config_setprop(struct config *cp, const char *propname, const char *propvalue) 4980Sstevel@tonic-gate { 4990Sstevel@tonic-gate const char *pn = stable(propname); 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate cp->props = lut_add(cp->props, (void *)pn, (void *)propvalue, NULL); 5020Sstevel@tonic-gate } 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate /* 5050Sstevel@tonic-gate * config_getprop -- lookup a config property 5060Sstevel@tonic-gate */ 5070Sstevel@tonic-gate const char * 5080Sstevel@tonic-gate config_getprop(struct config *cp, const char *propname) 5090Sstevel@tonic-gate { 5100Sstevel@tonic-gate return (lut_lookup(cp->props, (void *) stable(propname), NULL)); 5110Sstevel@tonic-gate } 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate /* 5140Sstevel@tonic-gate * config_getcompname -- get the component name of a config node 5150Sstevel@tonic-gate */ 5160Sstevel@tonic-gate void 5170Sstevel@tonic-gate config_getcompname(struct config *cp, char **name, int *inst) 5180Sstevel@tonic-gate { 5190Sstevel@tonic-gate ASSERT(cp != NULL); 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate if (name != NULL) 5220Sstevel@tonic-gate *name = (char *)cp->s; 5230Sstevel@tonic-gate if (inst != NULL) 5240Sstevel@tonic-gate *inst = cp->num; 5250Sstevel@tonic-gate } 5260Sstevel@tonic-gate 5270Sstevel@tonic-gate /* 5280Sstevel@tonic-gate * config_nodeize -- convert the config element represented by cp to struct 5290Sstevel@tonic-gate * node format 5300Sstevel@tonic-gate */ 5310Sstevel@tonic-gate static struct node * 5320Sstevel@tonic-gate config_nodeize(struct config *cp) 5330Sstevel@tonic-gate { 5340Sstevel@tonic-gate struct node *tmpn, *ptmpn; 5350Sstevel@tonic-gate struct node *numn; 5360Sstevel@tonic-gate const char *sname; 5370Sstevel@tonic-gate 5380Sstevel@tonic-gate if (cp == NULL || cp->s == NULL) 5390Sstevel@tonic-gate return (NULL); 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate sname = stable(cp->s); 5420Sstevel@tonic-gate numn = newnode(T_NUM, NULL, 0); 5430Sstevel@tonic-gate numn->u.ull = cp->num; 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate tmpn = tree_name_iterator(tree_name(sname, IT_VERTICAL, NULL, 0), numn); 5460Sstevel@tonic-gate if ((ptmpn = config_nodeize(cp->parent)) == NULL) 5470Sstevel@tonic-gate return (tmpn); 5480Sstevel@tonic-gate return (tree_name_append(ptmpn, tmpn)); 5490Sstevel@tonic-gate } 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate /*ARGSUSED*/ 5520Sstevel@tonic-gate static void 5530Sstevel@tonic-gate prtdevcache(void *lhs, void *rhs, void *arg) 5540Sstevel@tonic-gate { 5550Sstevel@tonic-gate out(O_ALTFP|O_VERB3, "%s -> %p", (char *)lhs, rhs); 5560Sstevel@tonic-gate } 5570Sstevel@tonic-gate 5580Sstevel@tonic-gate /*ARGSUSED*/ 5590Sstevel@tonic-gate static void 5600Sstevel@tonic-gate prtcpucache(void *lhs, void *rhs, void *arg) 5610Sstevel@tonic-gate { 5620Sstevel@tonic-gate out(O_ALTFP|O_VERB, "%u -> %p", (uint32_t)lhs, rhs); 5630Sstevel@tonic-gate } 5640Sstevel@tonic-gate 5650Sstevel@tonic-gate /* 5660Sstevel@tonic-gate * config_bydev_lookup -- look up the path in our DEVcache lut. If we find 5670Sstevel@tonic-gate * it return the config path, but as a struct node. 5680Sstevel@tonic-gate */ 5690Sstevel@tonic-gate struct node * 5700Sstevel@tonic-gate config_bydev_lookup(struct cfgdata *fromcfg, const char *path) 5710Sstevel@tonic-gate { 5720Sstevel@tonic-gate struct config *find; 5730Sstevel@tonic-gate struct node *np; 5740Sstevel@tonic-gate 5750Sstevel@tonic-gate out(O_ALTFP|O_VERB3, "Device path cache:"); 5760Sstevel@tonic-gate lut_walk(fromcfg->devcache, (lut_cb)prtdevcache, NULL); 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate if ((find = lut_lookup(fromcfg->devcache, 5790Sstevel@tonic-gate (void *) stable(path), NULL)) == NULL) 5800Sstevel@tonic-gate return (NULL); 5810Sstevel@tonic-gate 5820Sstevel@tonic-gate np = config_nodeize(find); 5830Sstevel@tonic-gate if (np != NULL) { 5840Sstevel@tonic-gate out(O_ALTFP|O_VERB, "Matching config entry:"); 5850Sstevel@tonic-gate ptree_name_iter(O_ALTFP|O_VERB|O_NONL, np); 5860Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 5870Sstevel@tonic-gate } 5880Sstevel@tonic-gate return (np); 5890Sstevel@tonic-gate } 5900Sstevel@tonic-gate 5910Sstevel@tonic-gate /* 5920Sstevel@tonic-gate * config_bycpuid_lookup -- look up the cpu id in our CPUcache lut. 5930Sstevel@tonic-gate * If we find it return the config path, but as a struct node. 5940Sstevel@tonic-gate */ 5950Sstevel@tonic-gate struct node * 5960Sstevel@tonic-gate config_bycpuid_lookup(struct cfgdata *fromcfg, uint32_t id) 5970Sstevel@tonic-gate { 5980Sstevel@tonic-gate struct config *find; 5990Sstevel@tonic-gate struct node *np; 6000Sstevel@tonic-gate 6010Sstevel@tonic-gate out(O_ALTFP|O_VERB, "Cpu cache:"); 6020Sstevel@tonic-gate lut_walk(fromcfg->cpucache, (lut_cb)prtcpucache, NULL); 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate if ((find = lut_lookup(fromcfg->cpucache, 6050Sstevel@tonic-gate (void *)id, NULL)) == NULL) 6060Sstevel@tonic-gate return (NULL); 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate np = config_nodeize(find); 6090Sstevel@tonic-gate if (np != NULL) { 6100Sstevel@tonic-gate out(O_ALTFP|O_VERB3, "Matching config entry:"); 6110Sstevel@tonic-gate ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, np); 6120Sstevel@tonic-gate out(O_ALTFP|O_VERB3, NULL); 6130Sstevel@tonic-gate } 6140Sstevel@tonic-gate return (np); 6150Sstevel@tonic-gate } 6160Sstevel@tonic-gate 6170Sstevel@tonic-gate /* 6180Sstevel@tonic-gate * printprop -- print prop associated with config node 6190Sstevel@tonic-gate */ 6200Sstevel@tonic-gate static void 6210Sstevel@tonic-gate printprop(const char *lhs, const char *rhs, void *arg) 6220Sstevel@tonic-gate { 6230Sstevel@tonic-gate int flags = (int)arg; 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate out(flags, "\t%s=%s", lhs, rhs); 6260Sstevel@tonic-gate } 6270Sstevel@tonic-gate 6280Sstevel@tonic-gate /* 6290Sstevel@tonic-gate * pconf -- internal printing function to recurse through the tree 6300Sstevel@tonic-gate */ 6310Sstevel@tonic-gate static void 6320Sstevel@tonic-gate pconf(int flags, struct config *cp, char *buf, int offset, int limit) 6330Sstevel@tonic-gate { 6340Sstevel@tonic-gate char *sep = "/"; 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate if (offset) 6370Sstevel@tonic-gate sep = "/"; 6380Sstevel@tonic-gate else 6390Sstevel@tonic-gate sep = ""; 6400Sstevel@tonic-gate (void) snprintf(&buf[offset], limit - offset, "%s%s%d", 6410Sstevel@tonic-gate sep, cp->s, cp->num); 6420Sstevel@tonic-gate if (cp->child == NULL) { 6430Sstevel@tonic-gate out(flags, "%s", buf); 6440Sstevel@tonic-gate lut_walk(cp->props, (lut_cb)printprop, (void *)flags); 6450Sstevel@tonic-gate } else 6460Sstevel@tonic-gate pconf(flags, cp->child, buf, strlen(buf), limit); 6470Sstevel@tonic-gate if (cp->next) 6480Sstevel@tonic-gate pconf(flags, cp->next, buf, offset, limit); 6490Sstevel@tonic-gate } 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate /* 6520Sstevel@tonic-gate * config_print -- spew the current configuration cache 6530Sstevel@tonic-gate */ 6540Sstevel@tonic-gate 6550Sstevel@tonic-gate #define MAXCONFLINE 4096 6560Sstevel@tonic-gate 6570Sstevel@tonic-gate void 6580Sstevel@tonic-gate config_print(int flags, struct config *croot) 6590Sstevel@tonic-gate { 6600Sstevel@tonic-gate char buf[MAXCONFLINE]; 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate if (croot == NULL) 6630Sstevel@tonic-gate out(flags, "empty configuration"); 6640Sstevel@tonic-gate else 6650Sstevel@tonic-gate pconf(flags, croot->child, buf, 0, MAXCONFLINE); 6660Sstevel@tonic-gate } 667