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  1414     cindi  * Common Development and Distribution License (the "License").
      6  1414     cindi  * 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     0    stevel /*
     22  6277  cy152378  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23     0    stevel  * Use is subject to license terms.
     24     0    stevel  *
     25     0    stevel  * platform.c -- interfaces to the platform's configuration information
     26     0    stevel  *
     27     0    stevel  * this platform.c allows eft to run on Solaris systems.
     28     0    stevel  */
     29     0    stevel 
     30     0    stevel #include <stdio.h>
     31     0    stevel #include <stdlib.h>
     32     0    stevel #include <string.h>
     33     0    stevel #include <strings.h>
     34     0    stevel #include <ctype.h>
     35     0    stevel #include <dirent.h>
     36     0    stevel #include <libnvpair.h>
     37     0    stevel #include <dlfcn.h>
     38     0    stevel #include <unistd.h>
     39     0    stevel #include <errno.h>
     40     0    stevel #include <stropts.h>
     41     0    stevel #include <sys/types.h>
     42   186   db35262 #include <sys/stat.h>
     43     0    stevel #include <sys/wait.h>
     44     0    stevel #include <sys/filio.h>
     45     0    stevel #include <sys/param.h>
     46     0    stevel #include <sys/fm/protocol.h>
     47     0    stevel #include <fm/fmd_api.h>
     48  3062     cindi #include <fm/fmd_fmri.h>
     49  1414     cindi #include <fm/libtopo.h>
     50  3062     cindi #include <fm/topo_hc.h>
     51     0    stevel #include "alloc.h"
     52     0    stevel #include "out.h"
     53     0    stevel #include "tree.h"
     54     0    stevel #include "itree.h"
     55     0    stevel #include "ipath.h"
     56     0    stevel #include "ptree.h"
     57     0    stevel #include "fme.h"
     58     0    stevel #include "stable.h"
     59     0    stevel #include "eval.h"
     60     0    stevel #include "config.h"
     61     0    stevel #include "platform.h"
     62     0    stevel 
     63     0    stevel extern fmd_hdl_t *Hdl;		/* handle from eft.c */
     64     0    stevel 
     65     0    stevel /*
     66  4436    stephh  * Lastcfg points to the last configuration snapshot we made.
     67     0    stevel  */
     68     0    stevel static struct cfgdata *Lastcfg;
     69  4436    stephh static fmd_hdl_t *Lasthdl;
     70  4436    stephh static fmd_case_t *Lastfmcase;
     71  4436    stephh static const char *lastcomp;
     72  4436    stephh static int in_getpath;
     73  4436    stephh extern struct lut *Usednames;
     74  4436    stephh int prune_raw_config = 0;
     75  4436    stephh 
     76  1414     cindi static topo_hdl_t *Eft_topo_hdl;
     77     0    stevel 
     78     0    stevel void *
     79     0    stevel topo_use_alloc(size_t bytes)
     80     0    stevel {
     81     0    stevel 	void *p = alloc_malloc(bytes, NULL, 0);
     82     0    stevel 
     83     0    stevel 	bzero(p, bytes);
     84     0    stevel 	return (p);
     85     0    stevel }
     86     0    stevel 
     87     0    stevel void
     88     0    stevel topo_use_free(void *p)
     89     0    stevel {
     90     0    stevel 	alloc_free(p, NULL, 0);
     91     0    stevel }
     92     0    stevel 
     93     0    stevel /*ARGSUSED*/
     94     0    stevel static void *
     95     0    stevel alloc_nv_alloc(nv_alloc_t *nva, size_t size)
     96     0    stevel {
     97     0    stevel 	return (alloc_malloc(size, NULL, 0));
     98     0    stevel }
     99     0    stevel 
    100     0    stevel /*ARGSUSED*/
    101     0    stevel static void
    102     0    stevel alloc_nv_free(nv_alloc_t *nva, void *p, size_t sz)
    103     0    stevel {
    104     0    stevel 	alloc_free(p, NULL, 0);
    105     0    stevel }
    106     0    stevel 
    107     0    stevel const nv_alloc_ops_t Eft_nv_alloc_ops = {
    108     0    stevel 	NULL,		/* nv_ao_init() */
    109     0    stevel 	NULL,		/* nv_ao_fini() */
    110     0    stevel 	alloc_nv_alloc,	/* nv_ao_alloc() */
    111     0    stevel 	alloc_nv_free,	/* nv_ao_free() */
    112     0    stevel 	NULL		/* nv_ao_reset() */
    113     0    stevel };
    114     0    stevel 
    115     0    stevel nv_alloc_t Eft_nv_hdl;
    116     0    stevel 
    117     0    stevel static char *Root;
    118     0    stevel static char *Mach;
    119     0    stevel static char *Plat;
    120  1414     cindi static char tmpbuf[MAXPATHLEN];
    121  1414     cindi static char numbuf[MAXPATHLEN];
    122     0    stevel 
    123     0    stevel /*
    124     0    stevel  * platform_globals -- set global variables based on sysinfo() calls
    125     0    stevel  */
    126     0    stevel static void
    127     0    stevel platform_globals()
    128     0    stevel {
    129     0    stevel 	Root = fmd_prop_get_string(Hdl, "fmd.rootdir");
    130     0    stevel 	Mach = fmd_prop_get_string(Hdl, "fmd.machine");
    131     0    stevel 	Plat = fmd_prop_get_string(Hdl, "fmd.platform");
    132     0    stevel }
    133     0    stevel 
    134     0    stevel static void
    135     0    stevel platform_free_globals()
    136     0    stevel {
    137     0    stevel 	fmd_prop_free_string(Hdl, Root);
    138     0    stevel 	fmd_prop_free_string(Hdl, Mach);
    139     0    stevel 	fmd_prop_free_string(Hdl, Plat);
    140     0    stevel }
    141     0    stevel 
    142     0    stevel /*
    143     0    stevel  * platform_init -- perform any platform-specific initialization
    144     0    stevel  */
    145     0    stevel void
    146     0    stevel platform_init(void)
    147     0    stevel {
    148  1414     cindi 	(void) nv_alloc_init(&Eft_nv_hdl, &Eft_nv_alloc_ops);
    149  4198  eschrock 	Eft_topo_hdl = fmd_hdl_topo_hold(Hdl, TOPO_VERSION);
    150  1414     cindi 	platform_globals();
    151     0    stevel 
    152  1414     cindi 	out(O_ALTFP, "platform_init() sucessful");
    153     0    stevel }
    154     0    stevel 
    155     0    stevel void
    156     0    stevel platform_fini(void)
    157     0    stevel {
    158     0    stevel 	if (Lastcfg != NULL) {
    159     0    stevel 		config_free(Lastcfg);
    160     0    stevel 		Lastcfg = NULL;
    161     0    stevel 	}
    162  4198  eschrock 	fmd_hdl_topo_rele(Hdl, Eft_topo_hdl);
    163     0    stevel 	platform_free_globals();
    164     0    stevel 	(void) nv_alloc_fini(&Eft_nv_hdl);
    165  1414     cindi 
    166  1414     cindi 	out(O_ALTFP, "platform_fini() sucessful");
    167     0    stevel }
    168     0    stevel 
    169     0    stevel /*
    170     0    stevel  * hc_fmri_nodeize -- convert hc-scheme FMRI to eft compatible format
    171     0    stevel  *
    172     0    stevel  * this is an internal platform.c helper routine
    173     0    stevel  */
    174     0    stevel static struct node *
    175     0    stevel hc_fmri_nodeize(nvlist_t *hcfmri)
    176     0    stevel {
    177     0    stevel 	struct node *pathtree = NULL;
    178     0    stevel 	struct node *tmpn;
    179     0    stevel 	nvlist_t **hc_prs;
    180     0    stevel 	uint_t hc_nprs;
    181     0    stevel 	const char *sname;
    182     0    stevel 	char *ename;
    183     0    stevel 	char *eid;
    184     0    stevel 	int e, r;
    185     0    stevel 
    186     0    stevel 	/*
    187     0    stevel 	 * What to do with/about hc-root?  Would we have any clue what
    188     0    stevel 	 * to do with it if it weren't /?  For now, we don't bother
    189     0    stevel 	 * even looking it up.
    190     0    stevel 	 */
    191     0    stevel 
    192     0    stevel 	/*
    193     0    stevel 	 * Get the hc-list of elements in the FMRI
    194     0    stevel 	 */
    195     0    stevel 	if (nvlist_lookup_nvlist_array(hcfmri, FM_FMRI_HC_LIST,
    196     0    stevel 	    &hc_prs, &hc_nprs) != 0) {
    197     0    stevel 		out(O_ALTFP, "XFILE: hc FMRI missing %s", FM_FMRI_HC_LIST);
    198     0    stevel 		return (NULL);
    199     0    stevel 	}
    200     0    stevel 
    201     0    stevel 	for (e = 0; e < hc_nprs; e++) {
    202     0    stevel 		ename = NULL;
    203     0    stevel 		eid = NULL;
    204     0    stevel 		r = nvlist_lookup_string(hc_prs[e], FM_FMRI_HC_NAME, &ename);
    205     0    stevel 		r |= nvlist_lookup_string(hc_prs[e], FM_FMRI_HC_ID, &eid);
    206     0    stevel 		if (r != 0) {
    207     0    stevel 			/* probably should bail */
    208     0    stevel 			continue;
    209     0    stevel 		}
    210     0    stevel 		sname = stable(ename);
    211     0    stevel 		tmpn = tree_name_iterator(
    212  4198  eschrock 		    tree_name(sname, IT_VERTICAL, NULL, 0),
    213  4198  eschrock 		    tree_num(eid, NULL, 0));
    214     0    stevel 
    215     0    stevel 		if (pathtree == NULL)
    216     0    stevel 			pathtree = tmpn;
    217     0    stevel 		else
    218     0    stevel 			(void) tree_name_append(pathtree, tmpn);
    219     0    stevel 	}
    220     0    stevel 
    221     0    stevel 	return (pathtree);
    222     0    stevel }
    223     0    stevel 
    224     0    stevel /*
    225     0    stevel  * platform_getpath -- extract eft-compatible path from ereport
    226     0    stevel  */
    227     0    stevel struct node *
    228     0    stevel platform_getpath(nvlist_t *nvl)
    229     0    stevel {
    230  6640       cth 	struct node	*ret;
    231  6640       cth 	nvlist_t	*dfmri;
    232  6640       cth 	char		*scheme;
    233  6640       cth 	char		*path;
    234  6640       cth 	char		*devid;
    235  6640       cth 	uint32_t	cpuid;
    236  6640       cth 	enum {DT_HC, DT_DEVID, DT_DEV, DT_CPU, DT_UNKNOWN} type = DT_UNKNOWN;
    237     0    stevel 
    238  6640       cth 	/* Find the detector */
    239     0    stevel 	if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &dfmri) != 0) {
    240     0    stevel 		out(O_ALTFP, "XFILE: ereport has no detector FMRI");
    241     0    stevel 		return (NULL);
    242     0    stevel 	}
    243     0    stevel 
    244  6640       cth 	/* get the scheme from the detector */
    245     0    stevel 	if (nvlist_lookup_string(dfmri, FM_FMRI_SCHEME, &scheme) != 0) {
    246     0    stevel 		out(O_ALTFP, "XFILE: detector FMRI missing scheme");
    247     0    stevel 		return (NULL);
    248     0    stevel 	}
    249     0    stevel 
    250  6640       cth 	/* based on scheme, determine type */
    251  6640       cth 	if (strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
    252  6640       cth 		/* already in hc scheme */
    253  6640       cth 		return (hc_fmri_nodeize(dfmri));
    254  6640       cth 	} else if (strcmp(scheme, FM_FMRI_SCHEME_DEV) == 0) {
    255  6640       cth 		/* devid takes precedence over path */
    256  6640       cth 		if (nvlist_lookup_string(dfmri,
    257  6640       cth 		    FM_FMRI_DEV_ID, &devid) == 0)
    258  6640       cth 			type = DT_DEVID;
    259  6640       cth 		else if (nvlist_lookup_string(dfmri,
    260  6640       cth 		    FM_FMRI_DEV_PATH, &path) == 0)
    261  6640       cth 			type = DT_DEV;
    262  6640       cth 		else {
    263  6640       cth 			out(O_ALTFP, "XFILE: detector FMRI missing %s or %s",
    264  6640       cth 			    FM_FMRI_DEV_ID, FM_FMRI_DEV_PATH);
    265     0    stevel 			return (NULL);
    266     0    stevel 		}
    267  7913   Stephen 	} else if (strcmp(scheme, FM_FMRI_SCHEME_CPU) == 0) {
    268  6640       cth 		if (nvlist_lookup_uint32(dfmri, FM_FMRI_CPU_ID, &cpuid) == 0)
    269  6640       cth 			type = DT_CPU;
    270  6640       cth 		else {
    271     0    stevel 			out(O_ALTFP, "XFILE: detector FMRI missing %s",
    272     0    stevel 			    FM_FMRI_CPU_ID);
    273     0    stevel 			return (NULL);
    274     0    stevel 		}
    275  6640       cth 	} else {
    276  6640       cth 		out(O_ALTFP, "XFILE: detector FMRI not recognized "
    277  6640       cth 		    "(scheme is %s, expect %s or %s or %s)",
    278  6640       cth 		    scheme, FM_FMRI_SCHEME_HC, FM_FMRI_SCHEME_DEV,
    279  6640       cth 		    FM_FMRI_SCHEME_CPU);
    280  6640       cth 		return (NULL);
    281     0    stevel 	}
    282     0    stevel 
    283  6640       cth 	out(O_ALTFP|O_VERB, "Received ereport in scheme %s", scheme);
    284  6640       cth 
    285  6640       cth 	/* take a config snapshot */
    286  6640       cth 	lut_free(Usednames, NULL, NULL);
    287  6640       cth 	Usednames = NULL;
    288  6640       cth 	in_getpath = 1;
    289  6640       cth 	if (config_snapshot() == NULL) {
    290  6640       cth 		out(O_ALTFP, "XFILE: cannot snapshot configuration");
    291  6640       cth 		in_getpath = 0;
    292  6640       cth 		return (NULL);
    293  6640       cth 	}
    294  6640       cth 
    295  6640       cth 	/* Look up the path, cpuid, or devid in the last config snapshot. */
    296  6640       cth 	switch (type) {
    297  6640       cth 	case DT_DEV:
    298  6640       cth 		if ((ret = config_bydev_lookup(Lastcfg, path)) == NULL)
    299  6640       cth 			out(O_ALTFP, "platform_getpath: no configuration node "
    300  6640       cth 			    "has device path matching \"%s\".", path);
    301  6640       cth 
    302  6640       cth 		break;
    303  6640       cth 
    304  6640       cth 	case DT_DEVID:
    305  6640       cth 		if ((ret = config_bydevid_lookup(Lastcfg, devid)) == NULL)
    306  6640       cth 			out(O_ALTFP, "platform_getpath: no configuration node "
    307  6640       cth 			    "has devid matching \"%s\".", devid);
    308  6640       cth 		break;
    309  6640       cth 
    310  6640       cth 	case DT_CPU:
    311  6640       cth 		if ((ret = config_bycpuid_lookup(Lastcfg, cpuid)) == NULL)
    312  6640       cth 			out(O_ALTFP, "platform_getpath: no configuration node "
    313  6640       cth 			    "has cpu-id matching %u.", cpuid);
    314  6640       cth 		break;
    315  6640       cth 	}
    316  6640       cth 
    317  6640       cth 	/* free the snapshot */
    318  6640       cth 	structconfig_free(Lastcfg->cooked);
    319  6640       cth 	config_free(Lastcfg);
    320  6640       cth 	in_getpath = 0;
    321  6640       cth 	return (ret);
    322     0    stevel }
    323     0    stevel 
    324     0    stevel /* Allocate space for raw config strings in chunks of this size */
    325     0    stevel #define	STRSBUFLEN	512
    326     0    stevel 
    327     0    stevel /*
    328     0    stevel  * cfgadjust -- Make sure the amount we want to add to the raw config string
    329     0    stevel  *		buffer will fit, and if not, increase the size of the buffer.
    330     0    stevel  */
    331     0    stevel static void
    332     0    stevel cfgadjust(struct cfgdata *rawdata, int addlen)
    333     0    stevel {
    334     0    stevel 	int curnext, newlen;
    335     0    stevel 
    336     0    stevel 	if (rawdata->nextfree + addlen >= rawdata->end) {
    337     0    stevel 		newlen = (((rawdata->nextfree - rawdata->begin + 1 + addlen)
    338     0    stevel 		    / STRSBUFLEN) + 1) * STRSBUFLEN;
    339     0    stevel 		curnext = rawdata->nextfree - rawdata->begin;
    340     0    stevel 		rawdata->begin = REALLOC(rawdata->begin, newlen);
    341     0    stevel 		rawdata->nextfree = rawdata->begin + curnext;
    342     0    stevel 		rawdata->end = rawdata->begin + newlen;
    343     0    stevel 	}
    344     0    stevel }
    345     0    stevel 
    346  1414     cindi static char *
    347  1414     cindi hc_path(tnode_t *node)
    348  1414     cindi {
    349  1414     cindi 	int i, err;
    350  1414     cindi 	char *name, *instance, *estr;
    351  1414     cindi 	nvlist_t *fmri, **hcl;
    352  1414     cindi 	ulong_t ul;
    353  1414     cindi 	uint_t nhc;
    354  1414     cindi 
    355  1414     cindi 	if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE,
    356  1414     cindi 	    &fmri, &err) < 0)
    357  1414     cindi 		return (NULL);
    358  1414     cindi 
    359  1414     cindi 	if (nvlist_lookup_nvlist_array(fmri, FM_FMRI_HC_LIST, &hcl, &nhc)
    360  1414     cindi 	    != 0) {
    361  1414     cindi 		nvlist_free(fmri);
    362  1414     cindi 		return (NULL);
    363  1414     cindi 	}
    364  1414     cindi 
    365  1414     cindi 	tmpbuf[0] = '\0';
    366  1414     cindi 	for (i = 0; i < nhc; ++i) {
    367  1414     cindi 		err = nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name);
    368  1414     cindi 		err |= nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &instance);
    369  1414     cindi 		if (err) {
    370  1414     cindi 			nvlist_free(fmri);
    371  1414     cindi 			return (NULL);
    372  1414     cindi 		}
    373  1414     cindi 
    374  1414     cindi 		ul = strtoul(instance, &estr, 10);
    375  1414     cindi 		/* conversion to number failed? */
    376  1414     cindi 		if (estr == instance) {
    377  1414     cindi 			nvlist_free(fmri);
    378  1414     cindi 			return (NULL);
    379  1414     cindi 		}
    380  1414     cindi 
    381  1414     cindi 		(void) strlcat(tmpbuf, "/", MAXPATHLEN);
    382  1414     cindi 		(void) strlcat(tmpbuf, name, MAXPATHLEN);
    383  6277  cy152378 		(void) snprintf(numbuf, MAXPATHLEN, "%lu", ul);
    384  1414     cindi 		(void) strlcat(tmpbuf, numbuf, MAXPATHLEN);
    385  4436    stephh 		lastcomp = stable(name);
    386  1414     cindi 	}
    387  1414     cindi 
    388  1414     cindi 	nvlist_free(fmri);
    389  1414     cindi 
    390  1414     cindi 	return (tmpbuf);
    391  1414     cindi }
    392  1414     cindi 
    393  1414     cindi static void
    394  1414     cindi add_prop_val(topo_hdl_t *thp, struct cfgdata *rawdata, char *propn,
    395  1414     cindi     nvpair_t *pv_nvp)
    396  1414     cindi {
    397  1414     cindi 	int addlen, err;
    398  1414     cindi 	char *propv, *fmristr = NULL;
    399  1414     cindi 	nvlist_t *fmri;
    400  4436    stephh 	uint32_t ui32;
    401  4436    stephh 	int64_t i64;
    402  4436    stephh 	int32_t i32;
    403  4436    stephh 	boolean_t bool;
    404  2869    gavinm 	uint64_t ui64;
    405  2869    gavinm 	char buf[32];	/* big enough for any 64-bit int */
    406  1414     cindi 
    407  1414     cindi 	/*
    408  3062     cindi 	 * malformed prop nvpair
    409  3062     cindi 	 */
    410  3062     cindi 	if (propn == NULL)
    411  3062     cindi 		return;
    412  3062     cindi 
    413  3062     cindi 	/*
    414  2869    gavinm 	 * We can only handle properties of string type
    415  1414     cindi 	 */
    416  2869    gavinm 	switch (nvpair_type(pv_nvp)) {
    417  2869    gavinm 	case DATA_TYPE_STRING:
    418  2869    gavinm 		(void) nvpair_value_string(pv_nvp, &propv);
    419  2869    gavinm 		break;
    420  2869    gavinm 
    421  2869    gavinm 	case DATA_TYPE_NVLIST:
    422  2869    gavinm 		/*
    423  2869    gavinm 		 * At least try to collect the protocol
    424  2869    gavinm 		 * properties
    425  2869    gavinm 		 */
    426  1414     cindi 		(void) nvpair_value_nvlist(pv_nvp, &fmri);
    427  1414     cindi 		if (topo_fmri_nvl2str(thp, fmri, &fmristr, &err) < 0) {
    428  1414     cindi 			out(O_ALTFP, "cfgcollect: failed to convert fmri to "
    429  1414     cindi 			    "string");
    430  1414     cindi 			return;
    431  1414     cindi 		} else {
    432  1414     cindi 			propv = fmristr;
    433  1414     cindi 		}
    434  2869    gavinm 		break;
    435  1414     cindi 
    436  2869    gavinm 	case DATA_TYPE_UINT64:
    437  2869    gavinm 		/*
    438  2869    gavinm 		 * Convert uint64 to hex strings
    439  2869    gavinm 		 */
    440  2869    gavinm 		(void) nvpair_value_uint64(pv_nvp, &ui64);
    441  2869    gavinm 		(void) snprintf(buf, sizeof (buf), "0x%llx", ui64);
    442  2869    gavinm 		propv = buf;
    443  2869    gavinm 		break;
    444  2869    gavinm 
    445  4436    stephh 	case DATA_TYPE_BOOLEAN_VALUE:
    446  4436    stephh 		/*
    447  4436    stephh 		 * Convert boolean_t to hex strings
    448  4436    stephh 		 */
    449  4436    stephh 		(void) nvpair_value_boolean_value(pv_nvp, &bool);
    450  4436    stephh 		(void) snprintf(buf, sizeof (buf), "0x%llx", (uint64_t)bool);
    451  4436    stephh 		propv = buf;
    452  4436    stephh 		break;
    453  4436    stephh 
    454  4436    stephh 	case DATA_TYPE_INT32:
    455  4436    stephh 		/*
    456  4436    stephh 		 * Convert int32 to hex strings
    457  4436    stephh 		 */
    458  4436    stephh 		(void) nvpair_value_int32(pv_nvp, &i32);
    459  4436    stephh 		(void) snprintf(buf, sizeof (buf), "0x%llx",
    460  4436    stephh 		    (uint64_t)(int64_t)i32);
    461  4436    stephh 		propv = buf;
    462  4436    stephh 		break;
    463  4436    stephh 
    464  4436    stephh 	case DATA_TYPE_INT64:
    465  4436    stephh 		/*
    466  4436    stephh 		 * Convert int64 to hex strings
    467  4436    stephh 		 */
    468  4436    stephh 		(void) nvpair_value_int64(pv_nvp, &i64);
    469  4436    stephh 		(void) snprintf(buf, sizeof (buf), "0x%llx", (uint64_t)i64);
    470  4436    stephh 		propv = buf;
    471  4436    stephh 		break;
    472  4436    stephh 
    473  4436    stephh 	case DATA_TYPE_UINT32:
    474  4436    stephh 		/*
    475  4436    stephh 		 * Convert uint32 to hex strings
    476  4436    stephh 		 */
    477  4436    stephh 		(void) nvpair_value_uint32(pv_nvp, &ui32);
    478  4436    stephh 		(void) snprintf(buf, sizeof (buf), "0x%llx", (uint64_t)ui32);
    479  4436    stephh 		propv = buf;
    480  4436    stephh 		break;
    481  4436    stephh 
    482  2869    gavinm 	default:
    483  3062     cindi 		out(O_ALTFP, "cfgcollect: failed to get property value for "
    484  3062     cindi 		    "%s", propn);
    485  1414     cindi 		return;
    486  1414     cindi 	}
    487  1414     cindi 
    488  1414     cindi 	/* = & NULL */
    489  1414     cindi 	addlen = strlen(propn) + strlen(propv) + 2;
    490  1414     cindi 	cfgadjust(rawdata, addlen);
    491  1414     cindi 	(void) snprintf(rawdata->nextfree,
    492  1414     cindi 	    rawdata->end - rawdata->nextfree, "%s=%s",
    493  1414     cindi 	    propn, propv);
    494  3062     cindi 	if (strcmp(propn, TOPO_PROP_RESOURCE) == 0)
    495  4436    stephh 		out(O_ALTFP|O_VERB3, "cfgcollect: %s", propv);
    496  3062     cindi 
    497  1414     cindi 	rawdata->nextfree += addlen;
    498  1414     cindi 
    499  1414     cindi 	if (fmristr != NULL)
    500  1414     cindi 		topo_hdl_strfree(thp, fmristr);
    501  1414     cindi }
    502  1414     cindi 
    503     0    stevel /*
    504     0    stevel  * cfgcollect -- Assemble raw configuration data in string form suitable
    505     0    stevel  *		 for checkpointing.
    506     0    stevel  */
    507  1414     cindi static int
    508  1414     cindi cfgcollect(topo_hdl_t *thp, tnode_t *node, void *arg)
    509     0    stevel {
    510     0    stevel 	struct cfgdata *rawdata = (struct cfgdata *)arg;
    511  3062     cindi 	int err, addlen;
    512  1414     cindi 	char *propn, *path = NULL;
    513  1414     cindi 	nvlist_t *p_nv, *pg_nv, *pv_nv;
    514  1414     cindi 	nvpair_t *nvp, *pg_nvp, *pv_nvp;
    515  7913   Stephen 
    516  7913   Stephen 	if (topo_node_flags(node) == TOPO_NODE_FACILITY)
    517  7913   Stephen 		return (TOPO_WALK_NEXT);
    518     0    stevel 
    519  1414     cindi 	path = hc_path(node);
    520  1414     cindi 	if (path == NULL)
    521  1414     cindi 		return (TOPO_WALK_ERR);
    522  1414     cindi 
    523     0    stevel 	addlen = strlen(path) + 1;
    524     0    stevel 
    525     0    stevel 	cfgadjust(rawdata, addlen);
    526     0    stevel 	(void) strcpy(rawdata->nextfree, path);
    527     0    stevel 	rawdata->nextfree += addlen;
    528  4436    stephh 
    529  4436    stephh 	/*
    530  4436    stephh 	 * If the prune_raw_config flag is set then we will only include in the
    531  4436    stephh 	 * raw config those nodes that are used by the rules remaining after
    532  4436    stephh 	 * prune_propagations() has been run - ie only those that could possibly
    533  4436    stephh 	 * be relevant to the incoming ereport given the current rules. This
    534  4436    stephh 	 * means that any other parts of the config will not get saved to the
    535  4436    stephh 	 * checkpoint file (even if they may theoretically be used if the
    536  4436    stephh 	 * rules are subsequently modified).
    537  4436    stephh 	 *
    538  4436    stephh 	 * For now prune_raw_config is 0 for Solaris, though it is expected to
    539  4436    stephh 	 * be set to 1 for fmsp.
    540  4436    stephh 	 *
    541  4436    stephh 	 * Note we only prune the raw config like this if we have been called
    542  4436    stephh 	 * from newfme(), not if we have been called when handling dev or cpu
    543  4436    stephh 	 * scheme ereports from platform_getpath(), as this is called before
    544  4436    stephh 	 * prune_propagations() - again this is not an issue on fmsp as the
    545  4436    stephh 	 * ereports are all in hc scheme.
    546  4436    stephh 	 */
    547  4436    stephh 	if (!in_getpath && prune_raw_config &&
    548  4436    stephh 	    lut_lookup(Usednames, (void *)lastcomp, NULL) == NULL)
    549  4436    stephh 		return (TOPO_WALK_NEXT);
    550     0    stevel 
    551  1414     cindi 	/*
    552  1414     cindi 	 * Collect properties
    553  1414     cindi 	 *
    554  1414     cindi 	 * eversholt should support alternate property types
    555  1414     cindi 	 * Better yet, topo properties could be represented as
    556  1414     cindi 	 * a packed nvlist
    557  1414     cindi 	 */
    558  3062     cindi 	p_nv = topo_prop_getprops(node, &err);
    559  1414     cindi 	for (nvp = nvlist_next_nvpair(p_nv, NULL); nvp != NULL;
    560  1414     cindi 	    nvp = nvlist_next_nvpair(p_nv, nvp)) {
    561  1414     cindi 		if (strcmp(TOPO_PROP_GROUP, nvpair_name(nvp)) != 0 ||
    562  1414     cindi 		    nvpair_type(nvp) != DATA_TYPE_NVLIST)
    563  1414     cindi 			continue;
    564  1414     cindi 
    565  1414     cindi 		(void) nvpair_value_nvlist(nvp, &pg_nv);
    566  1414     cindi 
    567  1414     cindi 		for (pg_nvp = nvlist_next_nvpair(pg_nv, NULL); pg_nvp != NULL;
    568  1414     cindi 		    pg_nvp = nvlist_next_nvpair(pg_nv, pg_nvp)) {
    569  1414     cindi 
    570  1414     cindi 			if (strcmp(TOPO_PROP_VAL, nvpair_name(pg_nvp)) != 0 ||
    571  1414     cindi 			    nvpair_type(pg_nvp) != DATA_TYPE_NVLIST)
    572  1414     cindi 				continue;
    573  1414     cindi 
    574  1414     cindi 			(void) nvpair_value_nvlist(pg_nvp, &pv_nv);
    575  1414     cindi 
    576  3062     cindi 			propn = NULL;
    577  1414     cindi 			for (pv_nvp = nvlist_next_nvpair(pv_nv, NULL);
    578  1414     cindi 			    pv_nvp != NULL;
    579  1414     cindi 			    pv_nvp = nvlist_next_nvpair(pv_nv, pv_nvp)) {
    580  1414     cindi 
    581  1414     cindi 				/* Get property name */
    582  3062     cindi 				if (strcmp(TOPO_PROP_VAL_NAME,
    583  3062     cindi 				    nvpair_name(pv_nvp)) == 0)
    584  3062     cindi 					(void) nvpair_value_string(pv_nvp,
    585  3062     cindi 					    &propn);
    586  1414     cindi 
    587  1414     cindi 				/*
    588  1414     cindi 				 * Get property value
    589  1414     cindi 				 */
    590  3062     cindi 				if (strcmp(TOPO_PROP_VAL_VAL,
    591  3062     cindi 				    nvpair_name(pv_nvp)) == 0)
    592  3062     cindi 					add_prop_val(thp, rawdata, propn,
    593  3062     cindi 					    pv_nvp);
    594  1414     cindi 			}
    595  1414     cindi 
    596  1414     cindi 		}
    597     0    stevel 	}
    598  1414     cindi 
    599  1414     cindi 	nvlist_free(p_nv);
    600  1414     cindi 
    601  1414     cindi 	return (TOPO_WALK_NEXT);
    602     0    stevel }
    603     0    stevel 
    604  4436    stephh void
    605  4436    stephh platform_restore_config(fmd_hdl_t *hdl, fmd_case_t *fmcase)
    606  4436    stephh {
    607  4436    stephh 	if (hdl == Lasthdl && fmcase == Lastfmcase) {
    608  4436    stephh 		size_t cfglen;
    609  4436    stephh 
    610  4436    stephh 		fmd_buf_read(Lasthdl, Lastfmcase, WOBUF_CFGLEN, (void *)&cfglen,
    611  4436    stephh 		    sizeof (size_t));
    612  4436    stephh 		Lastcfg->begin = MALLOC(cfglen);
    613  4436    stephh 		Lastcfg->end = Lastcfg->nextfree = Lastcfg->begin + cfglen;
    614  4436    stephh 		fmd_buf_read(Lasthdl, Lastfmcase, WOBUF_CFG, Lastcfg->begin,
    615  4436    stephh 		    cfglen);
    616  4436    stephh 		Lasthdl = NULL;
    617  4436    stephh 		Lastfmcase = NULL;
    618  4436    stephh 	}
    619  4436    stephh }
    620  4436    stephh 
    621  4436    stephh void
    622  4436    stephh platform_save_config(fmd_hdl_t *hdl, fmd_case_t *fmcase)
    623  4436    stephh {
    624  4436    stephh 	size_t cfglen;
    625  4436    stephh 
    626  4436    stephh 	/*
    627  4436    stephh 	 * Put the raw config into an fmd_buf. Then we can free it to
    628  4436    stephh 	 * save space.
    629  4436    stephh 	 */
    630  4436    stephh 	Lastfmcase = fmcase;
    631  4436    stephh 	Lasthdl = hdl;
    632  4436    stephh 	cfglen = Lastcfg->nextfree - Lastcfg->begin;
    633  4436    stephh 	fmd_buf_create(hdl, fmcase, WOBUF_CFGLEN, sizeof (cfglen));
    634  4436    stephh 	fmd_buf_write(hdl, fmcase, WOBUF_CFGLEN, (void *)&cfglen,
    635  4436    stephh 	    sizeof (cfglen));
    636  4436    stephh 	if (cfglen != 0) {
    637  4436    stephh 		fmd_buf_create(hdl, fmcase, WOBUF_CFG, cfglen);
    638  4436    stephh 		fmd_buf_write(hdl, fmcase, WOBUF_CFG, Lastcfg->begin, cfglen);
    639  4436    stephh 	}
    640  4436    stephh 	FREE(Lastcfg->begin);
    641  4436    stephh 	Lastcfg->begin = NULL;
    642  4436    stephh 	Lastcfg->end = NULL;
    643  4436    stephh 	Lastcfg->nextfree = NULL;
    644  4436    stephh }
    645  4436    stephh 
    646     0    stevel /*
    647     0    stevel  * platform_config_snapshot -- gather a snapshot of the current configuration
    648     0    stevel  */
    649     0    stevel struct cfgdata *
    650     0    stevel platform_config_snapshot(void)
    651     0    stevel {
    652  1414     cindi 	int err;
    653  1414     cindi 	topo_walk_t *twp;
    654  3062     cindi 	static uint64_t lastgen;
    655  3062     cindi 	uint64_t curgen;
    656     0    stevel 
    657     0    stevel 	/*
    658     0    stevel 	 * If the DR generation number has changed,
    659     0    stevel 	 * we need to grab a new snapshot, otherwise we
    660     0    stevel 	 * can simply point them at the last config.
    661     0    stevel 	 */
    662  4436    stephh 	if (prune_raw_config == 0 && (curgen = fmd_fmri_get_drgen()) <=
    663  4436    stephh 	    lastgen && Lastcfg != NULL) {
    664  4436    stephh 		Lastcfg->raw_refcnt++;
    665  4436    stephh 		/*
    666  4436    stephh 		 * if config has been backed away to an fmd_buf, restore it
    667  4436    stephh 		 */
    668  4436    stephh 		if (Lastcfg->begin == NULL)
    669  4436    stephh 			platform_restore_config(Lasthdl, Lastfmcase);
    670  3062     cindi 		return (Lastcfg);
    671  3062     cindi 	}
    672     0    stevel 
    673  3062     cindi 	lastgen = curgen;
    674     0    stevel 	/* we're getting a new config, so clean up the last one */
    675  4436    stephh 	if (Lastcfg != NULL) {
    676  4436    stephh 		if (--Lastcfg->raw_refcnt == 0) {
    677  4436    stephh 			if (Lastcfg->begin != NULL)
    678  4436    stephh 				FREE(Lastcfg->begin);
    679  4436    stephh 			FREE(Lastcfg);
    680  4436    stephh 		}
    681  4436    stephh 	}
    682     0    stevel 
    683     0    stevel 	Lastcfg = MALLOC(sizeof (struct cfgdata));
    684  4436    stephh 	Lastcfg->raw_refcnt = 2;	/* caller + Lastcfg */
    685     0    stevel 	Lastcfg->begin = Lastcfg->nextfree = Lastcfg->end = NULL;
    686     0    stevel 	Lastcfg->cooked = NULL;
    687     0    stevel 	Lastcfg->devcache = NULL;
    688  6640       cth 	Lastcfg->devidcache = NULL;
    689     0    stevel 	Lastcfg->cpucache = NULL;
    690     0    stevel 
    691  3062     cindi 
    692  4198  eschrock 	fmd_hdl_topo_rele(Hdl, Eft_topo_hdl);
    693  4198  eschrock 	Eft_topo_hdl = fmd_hdl_topo_hold(Hdl, TOPO_VERSION);
    694     0    stevel 
    695  1414     cindi 	if ((twp = topo_walk_init(Eft_topo_hdl, FM_FMRI_SCHEME_HC, cfgcollect,
    696  1414     cindi 	    Lastcfg, &err)) == NULL) {
    697  1414     cindi 		out(O_DIE, "platform_config_snapshot: NULL topology tree: %s",
    698  1414     cindi 		    topo_strerror(err));
    699  1414     cindi 	}
    700  1414     cindi 
    701  1414     cindi 	if (topo_walk_step(twp, TOPO_WALK_CHILD) == TOPO_WALK_ERR) {
    702  1414     cindi 		topo_walk_fini(twp);
    703  1414     cindi 		out(O_DIE, "platform_config_snapshot: error walking topology "
    704  1414     cindi 		    "tree");
    705  1414     cindi 	}
    706  1414     cindi 
    707  1414     cindi 	topo_walk_fini(twp);
    708  4436    stephh 	out(O_ALTFP|O_STAMP, "raw config complete");
    709  1414     cindi 
    710     0    stevel 
    711     0    stevel 	return (Lastcfg);
    712     0    stevel }
    713     0    stevel 
    714  1414     cindi static const char *
    715  1414     cindi cfgstrprop_lookup(struct config *croot, char *path, char *pname)
    716     0    stevel {
    717  1414     cindi 	struct config *cresource;
    718  1414     cindi 	const char *fmristr;
    719     0    stevel 
    720     0    stevel 	/*
    721  1414     cindi 	 * The first order of business is to find the resource in the
    722  1414     cindi 	 * config database so we can examine properties associated with
    723  1414     cindi 	 * that node.
    724     0    stevel 	 */
    725  1414     cindi 	if ((cresource = config_lookup(croot, path, 0)) == NULL) {
    726  1414     cindi 		out(O_ALTFP, "Cannot find config info for %s.", path);
    727     0    stevel 		return (NULL);
    728     0    stevel 	}
    729  1414     cindi 	if ((fmristr = config_getprop(cresource, pname)) == NULL) {
    730  1414     cindi 		out(O_ALTFP, "Cannot find %s property for %s resource "
    731  1414     cindi 		    "re-write", pname, path);
    732  1414     cindi 		return (NULL);
    733  1414     cindi 	}
    734  1414     cindi 	return (fmristr);
    735     0    stevel }
    736     0    stevel 
    737     0    stevel /*
    738  7197    stephh  * Get resource FMRI from libtopo
    739     0    stevel  */
    740     0    stevel /*ARGSUSED*/
    741     0    stevel void
    742     0    stevel platform_units_translate(int isdefect, struct config *croot,
    743     0    stevel     nvlist_t **dfltasru, nvlist_t **dfltfru, nvlist_t **dfltrsrc, char *path)
    744     0    stevel {
    745  7197    stephh 	const char *fmristr;
    746  7197    stephh 	nvlist_t *rsrc;
    747  7197    stephh 	int err;
    748     0    stevel 
    749  7197    stephh 	fmristr = cfgstrprop_lookup(croot, path, TOPO_PROP_RESOURCE);
    750  7197    stephh 	if (fmristr == NULL) {
    751  1414     cindi 		out(O_ALTFP, "Cannot rewrite resource for %s.", path);
    752     0    stevel 		return;
    753     0    stevel 	}
    754  7197    stephh 	if (topo_fmri_str2nvl(Eft_topo_hdl, fmristr, &rsrc, &err) < 0) {
    755  7197    stephh 		out(O_ALTFP, "Can not convert config info: %s",
    756  7197    stephh 		    topo_strerror(err));
    757  7197    stephh 		out(O_ALTFP, "Cannot rewrite resource for %s.", path);
    758  7197    stephh 		return;
    759     0    stevel 	}
    760  7197    stephh 	*dfltrsrc = rsrc;
    761     0    stevel }
    762     0    stevel 
    763     0    stevel /*
    764     0    stevel  * platform_get_files -- return names of all files we should load
    765     0    stevel  *
    766     0    stevel  * search directories in dirname[] for all files with names ending with the
    767     0    stevel  * substring fnstr.  dirname[] should be a NULL-terminated array.  fnstr
    768     0    stevel  * may be set to "*" to indicate all files in a directory.
    769     0    stevel  *
    770     0    stevel  * if nodups is non-zero, then the first file of a given name found is
    771     0    stevel  * the only file added to the list of names.  for example if nodups is
    772     0    stevel  * set and we're looking for .efts, and find a pci.eft in the dirname[0],
    773     0    stevel  * then no pci.eft found in any of the other dirname[] entries will be
    774     0    stevel  * included in the final list of names.
    775     0    stevel  *
    776     0    stevel  * this routine doesn't return NULL, even if no files are found (in that
    777     0    stevel  * case, a char ** is returned with the first element NULL).
    778     0    stevel  */
    779     0    stevel static char **
    780     0    stevel platform_get_files(const char *dirname[], const char *fnstr, int nodups)
    781     0    stevel {
    782     0    stevel 	DIR *dirp;
    783     0    stevel 	struct dirent *dp;
    784     0    stevel 	struct lut *foundnames = NULL;
    785     0    stevel 	char **files = NULL;	/* char * array of filenames found */
    786     0    stevel 	int nfiles = 0;		/* files found so far */
    787     0    stevel 	int slots = 0;		/* char * slots allocated in files */
    788     0    stevel 	size_t fnlen, d_namelen;
    789     0    stevel 	size_t totlen;
    790     0    stevel 	int i;
    791     0    stevel 	static char *nullav;
    792     0    stevel 
    793     0    stevel 	ASSERT(fnstr != NULL);
    794     0    stevel 	fnlen = strlen(fnstr);
    795     0    stevel 
    796     0    stevel 	for (i = 0; dirname[i] != NULL; i++) {
    797     0    stevel 		out(O_DEBUG, "Looking for %s files in %s", fnstr, dirname[i]);
    798     0    stevel 		if ((dirp = opendir(dirname[i])) == NULL) {
    799     0    stevel 			out(O_DEBUG|O_SYS,
    800     0    stevel 			    "platform_get_files: opendir failed for %s",
    801     0    stevel 			    dirname[i]);
    802     0    stevel 			continue;
    803     0    stevel 		}
    804     0    stevel 		while ((dp = readdir(dirp)) != NULL) {
    805     0    stevel 			if ((fnlen == 1 && *fnstr == '*') ||
    806     0    stevel 			    ((d_namelen = strlen(dp->d_name)) >= fnlen &&
    807     0    stevel 			    strncmp(dp->d_name + d_namelen - fnlen,
    808     0    stevel 			    fnstr, fnlen) == 0)) {
    809     0    stevel 
    810     0    stevel 				if (nodups != 0) {
    811     0    stevel 					const char *snm = stable(dp->d_name);
    812     0    stevel 
    813     0    stevel 					if (lut_lookup(foundnames,
    814     0    stevel 					    (void *)snm,
    815     0    stevel 					    NULL) != NULL) {
    816     0    stevel 						out(O_DEBUG,
    817     0    stevel 						    "platform_get_files: "
    818     0    stevel 						    "skipping repeated name "
    819     0    stevel 						    "%s/%s",
    820     0    stevel 						    dirname[i],
    821     0    stevel 						    snm);
    822     0    stevel 						continue;
    823     0    stevel 					}
    824     0    stevel 					foundnames = lut_add(foundnames,
    825     0    stevel 					    (void *)snm,
    826     0    stevel 					    (void *)snm,
    827     0    stevel 					    NULL);
    828     0    stevel 				}
    829     0    stevel 
    830     0    stevel 				if (nfiles > slots - 2) {
    831     0    stevel 					/* allocate ten more slots */
    832     0    stevel 					slots += 10;
    833     0    stevel 					files = (char **)REALLOC(files,
    834  4198  eschrock 					    slots * sizeof (char *));
    835     0    stevel 				}
    836     0    stevel 				/* prepend directory name and / */
    837     0    stevel 				totlen = strlen(dirname[i]) + 1;
    838     0    stevel 				totlen += strlen(dp->d_name) + 1;
    839     0    stevel 				files[nfiles] = MALLOC(totlen);
    840  1414     cindi 				out(O_DEBUG, "File %d: \"%s/%s\"", nfiles,
    841  1414     cindi 				    dirname[i], dp->d_name);
    842     0    stevel 				(void) snprintf(files[nfiles++], totlen,
    843     0    stevel 				    "%s/%s", dirname[i], dp->d_name);
    844     0    stevel 			}
    845     0    stevel 		}
    846     0    stevel 		(void) closedir(dirp);
    847     0    stevel 	}
    848     0    stevel 
    849     0    stevel 	if (foundnames != NULL)
    850     0    stevel 		lut_free(foundnames, NULL, NULL);
    851     0    stevel 
    852     0    stevel 	if (nfiles == 0)
    853     0    stevel 		return (&nullav);
    854     0    stevel 
    855     0    stevel 	files[nfiles] = NULL;
    856     0    stevel 	return (files);
    857     0    stevel }
    858     0    stevel 
    859     0    stevel /*
    860   186   db35262  * search for files in a standard set of directories
    861   186   db35262  */
    862   186   db35262 static char **
    863   186   db35262 platform_get_files_stddirs(char *fname, int nodups)
    864   186   db35262 {
    865   186   db35262 	const char *dirlist[4];
    866   186   db35262 	char **flist;
    867   186   db35262 	char *eftgendir, *eftmachdir, *eftplatdir;
    868   186   db35262 
    869   186   db35262 	eftgendir = MALLOC(MAXPATHLEN);
    870   186   db35262 	eftmachdir = MALLOC(MAXPATHLEN);
    871   186   db35262 	eftplatdir = MALLOC(MAXPATHLEN);
    872   186   db35262 
    873   186   db35262 	/* Generic files that apply to any machine */
    874   186   db35262 	(void) snprintf(eftgendir, MAXPATHLEN, "%s/usr/lib/fm/eft", Root);
    875   186   db35262 
    876   186   db35262 	(void) snprintf(eftmachdir,
    877   186   db35262 	    MAXPATHLEN, "%s/usr/platform/%s/lib/fm/eft", Root, Mach);
    878   186   db35262 
    879   186   db35262 	(void) snprintf(eftplatdir,
    880   186   db35262 	    MAXPATHLEN, "%s/usr/platform/%s/lib/fm/eft", Root, Plat);
    881   186   db35262 
    882   186   db35262 	dirlist[0] = eftplatdir;
    883   186   db35262 	dirlist[1] = eftmachdir;
    884   186   db35262 	dirlist[2] = eftgendir;
    885   186   db35262 	dirlist[3] = NULL;
    886   186   db35262 
    887   186   db35262 	flist = platform_get_files(dirlist, fname, nodups);
    888   186   db35262 
    889   186   db35262 	FREE(eftplatdir);
    890   186   db35262 	FREE(eftmachdir);
    891   186   db35262 	FREE(eftgendir);
    892   186   db35262 
    893   186   db35262 	return (flist);
    894   186   db35262 }
    895   186   db35262 
    896   186   db35262 /*
    897     0    stevel  * platform_run_poller -- execute a poller
    898     0    stevel  *
    899     0    stevel  * when eft needs to know if a polled ereport exists this routine
    900     0    stevel  * is called so the poller code may be run in a platform-specific way.
    901     0    stevel  * there's no return value from this routine -- either the polled ereport
    902     0    stevel  * is generated (and delivered *before* this routine returns) or not.
    903     0    stevel  * any errors, like "poller unknown" are considered platform-specific
    904     0    stevel  * should be handled here rather than passing an error back up.
    905     0    stevel  */
    906     0    stevel /*ARGSUSED*/
    907     0    stevel void
    908     0    stevel platform_run_poller(const char *poller)
    909     0    stevel {
    910     0    stevel }
    911     0    stevel 
    912     0    stevel /*
    913     0    stevel  * fork and execve path with argument array argv and environment array
    914     0    stevel  * envp.  data from stdout and stderr are placed in outbuf and errbuf,
    915     0    stevel  * respectively.
    916     0    stevel  *
    917     0    stevel  * see execve(2) for more descriptions for path, argv and envp.
    918     0    stevel  */
    919     0    stevel static int
    920     0    stevel forkandexecve(const char *path, char *const argv[], char *const envp[],
    921     0    stevel 	char *outbuf, size_t outbuflen, char *errbuf, size_t errbuflen)
    922     0    stevel {
    923     0    stevel 	pid_t pid;
    924     0    stevel 	int outpipe[2], errpipe[2];
    925     0    stevel 	int rt = 0;
    926     0    stevel 
    927     0    stevel 	/*
    928     0    stevel 	 * run the cmd and see if it failed.  this function is *not* a
    929     0    stevel 	 * generic command runner -- we depend on some knowledge we
    930     0    stevel 	 * have about the commands we run.  first of all, we expect
    931     0    stevel 	 * errors to spew something to stdout, and that something is
    932     0    stevel 	 * typically short enough to fit into a pipe so we can wait()
    933     0    stevel 	 * for the command to complete and then fetch the error text
    934     0    stevel 	 * from the pipe.
    935     0    stevel 	 */
    936     0    stevel 	if (pipe(outpipe) < 0)
    937     0    stevel 		if (strlcat(errbuf, ": pipe(outpipe) failed",
    938  4198  eschrock 		    errbuflen) >= errbuflen)
    939     0    stevel 			return (1);
    940     0    stevel 	if (pipe(errpipe) < 0)
    941     0    stevel 		if (strlcat(errbuf, ": pipe(errpipe) failed",
    942  4198  eschrock 		    errbuflen) >= errbuflen)
    943     0    stevel 			return (1);
    944     0    stevel 
    945  4198  eschrock 	if ((pid = fork()) < 0) {
    946     0    stevel 		rt = (int)strlcat(errbuf, ": fork() failed", errbuflen);
    947  4198  eschrock 	} else if (pid) {
    948     0    stevel 		int wstat, count;
    949     0    stevel 
    950     0    stevel 		/* parent */
    951     0    stevel 		(void) close(errpipe[1]);
    952     0    stevel 		(void) close(outpipe[1]);
    953     0    stevel 
    954     0    stevel 		/* PHASE2 need to guard against hang in child? */
    955     0    stevel 		if (waitpid(pid, &wstat, 0) < 0)
    956     0    stevel 			if (strlcat(errbuf, ": waitpid() failed",
    957  4198  eschrock 			    errbuflen) >= errbuflen)
    958     0    stevel 				return (1);
    959     0    stevel 
    960     0    stevel 		/* check for stderr contents */
    961     0    stevel 		if (ioctl(errpipe[0], FIONREAD, &count) >= 0 && count) {
    962     0    stevel 			if (read(errpipe[0], errbuf, errbuflen) <= 0) {
    963     0    stevel 				/*
    964     0    stevel 				 * read failed even though ioctl indicated
    965     0    stevel 				 * that nonzero bytes were available for
    966     0    stevel 				 * reading
    967     0    stevel 				 */
    968     0    stevel 				if (strlcat(errbuf, ": read(errpipe) failed",
    969  4198  eschrock 				    errbuflen) >= errbuflen)
    970     0    stevel 					return (1);
    971     0    stevel 			}
    972     0    stevel 			/*
    973     0    stevel 			 * handle case where errbuf is not properly
    974     0    stevel 			 * terminated
    975     0    stevel 			 */
    976     0    stevel 			if (count > errbuflen - 1)
    977     0    stevel 				count = errbuflen - 1;
    978     0    stevel 			if (errbuf[count - 1] != '\0' &&
    979     0    stevel 			    errbuf[count - 1] != '\n')
    980     0    stevel 				errbuf[count] = '\0';
    981     0    stevel 		} else if (WIFSIGNALED(wstat))
    982     0    stevel 			if (strlcat(errbuf, ": signaled",
    983  4198  eschrock 			    errbuflen) >= errbuflen)
    984     0    stevel 				return (1);
    985     0    stevel 		else if (WIFEXITED(wstat) && WEXITSTATUS(wstat))
    986     0    stevel 			if (strlcat(errbuf, ": abnormal exit",
    987  4198  eschrock 			    errbuflen) >= errbuflen)
    988     0    stevel 				return (1);
    989     0    stevel 
    990     0    stevel 		/* check for stdout contents */
    991     0    stevel 		if (ioctl(outpipe[0], FIONREAD, &count) >= 0 && count) {
    992     0    stevel 			if (read(outpipe[0], outbuf, outbuflen) <= 0) {
    993     0    stevel 				/*
    994     0    stevel 				 * read failed even though ioctl indicated
    995     0    stevel 				 * that nonzero bytes were available for
    996     0    stevel 				 * reading
    997     0    stevel 				 */
    998     0    stevel 				if (strlcat(errbuf, ": read(outpipe) failed",
    999  4198  eschrock 				    errbuflen) >= errbuflen)
   1000     0    stevel 					return (1);
   1001     0    stevel 			}
   1002     0    stevel 			/*
   1003     0    stevel 			 * handle case where outbuf is not properly
   1004     0    stevel 			 * terminated
   1005     0    stevel 			 */
   1006     0    stevel 			if (count > outbuflen - 1)
   1007     0    stevel 				count = outbuflen - 1;
   1008     0    stevel 			if (outbuf[count - 1] != '\0' &&
   1009     0    stevel 			    outbuf[count - 1] != '\n')
   1010     0    stevel 				outbuf[count] = '\0';
   1011     0    stevel 		}
   1012     0    stevel 
   1013     0    stevel 		(void) close(errpipe[0]);
   1014     0    stevel 		(void) close(outpipe[0]);
   1015     0    stevel 	} else {
   1016     0    stevel 		/* child */
   1017     0    stevel 		(void) dup2(errpipe[1], fileno(stderr));
   1018     0    stevel 		(void) close(errpipe[0]);
   1019     0    stevel 		(void) dup2(outpipe[1], fileno(stdout));
   1020     0    stevel 		(void) close(outpipe[0]);
   1021     0    stevel 
   1022     0    stevel 		if (execve(path, argv, envp))
   1023     0    stevel 			perror(path);
   1024     0    stevel 		_exit(1);
   1025     0    stevel 	}
   1026     0    stevel 
   1027     0    stevel 	return (rt);
   1028     0    stevel }
   1029     0    stevel 
   1030     0    stevel #define	MAXDIGITIDX	23
   1031     0    stevel 
   1032     0    stevel static int
   1033     0    stevel arglist2argv(struct node *np, struct lut **globals, struct config *croot,
   1034     0    stevel 	struct arrow *arrowp, char ***argv, int *argc, int *argvlen)
   1035     0    stevel {
   1036     0    stevel 	struct node *namep;
   1037     0    stevel 	char numbuf[MAXDIGITIDX + 1];
   1038     0    stevel 	char *numstr, *nullbyte;
   1039     0    stevel 	char *addthisarg = NULL;
   1040     0    stevel 
   1041     0    stevel 	if (np == NULL)
   1042     0    stevel 		return (0);
   1043     0    stevel 
   1044     0    stevel 	switch (np->t) {
   1045     0    stevel 	case T_QUOTE:
   1046     0    stevel 		addthisarg = STRDUP(np->u.func.s);
   1047     0    stevel 		break;
   1048     0    stevel 	case T_LIST:
   1049     0    stevel 		if (arglist2argv(np->u.expr.left, globals, croot, arrowp,
   1050  4198  eschrock 		    argv, argc, argvlen))
   1051     0    stevel 			return (1);
   1052     0    stevel 		/*
   1053     0    stevel 		 * only leftmost element of a list can provide the command
   1054     0    stevel 		 * name (after which *argc becomes 1)
   1055     0    stevel 		 */
   1056     0    stevel 		ASSERT(*argc > 0);
   1057     0    stevel 		if (arglist2argv(np->u.expr.right, globals, croot, arrowp,
   1058  4198  eschrock 		    argv, argc, argvlen))
   1059     0    stevel 			return (1);
   1060     0    stevel 		break;
   1061     0    stevel 	case T_FUNC:
   1062     0    stevel 	case T_GLOBID:
   1063     0    stevel 	case T_ASSIGN:
   1064     0    stevel 	case T_CONDIF:
   1065     0    stevel 	case T_CONDELSE:
   1066     0    stevel 	case T_EQ:
   1067     0    stevel 	case T_NE:
   1068     0    stevel 	case T_LT:
   1069     0    stevel 	case T_LE:
   1070     0    stevel 	case T_GT:
   1071     0    stevel 	case T_GE:
   1072     0    stevel 	case T_BITAND:
   1073     0    stevel 	case T_BITOR:
   1074     0    stevel 	case T_BITXOR:
   1075     0    stevel 	case T_BITNOT:
   1076     0    stevel 	case T_LSHIFT:
   1077     0    stevel 	case T_RSHIFT:
   1078     0    stevel 	case T_AND:
   1079     0    stevel 	case T_OR:
   1080     0    stevel 	case T_NOT:
   1081     0    stevel 	case T_ADD:
   1082     0    stevel 	case T_SUB:
   1083     0    stevel 	case T_MUL:
   1084     0    stevel 	case T_DIV:
   1085     0    stevel 	case T_MOD: {
   1086     0    stevel 		struct evalue value;
   1087     0    stevel 
   1088     0    stevel 		if (!eval_expr(np, NULL, NULL, globals, croot, arrowp,
   1089  4198  eschrock 		    0, &value))
   1090     0    stevel 			return (1);
   1091     0    stevel 
   1092     0    stevel 		switch (value.t) {
   1093     0    stevel 		case UINT64:
   1094     0    stevel 			numbuf[MAXDIGITIDX] = '\0';
   1095     0    stevel 			nullbyte = &numbuf[MAXDIGITIDX];
   1096     0    stevel 			numstr = ulltostr(value.v, nullbyte);
   1097     0    stevel 			addthisarg = STRDUP(numstr);
   1098     0    stevel 			break;
   1099     0    stevel 		case STRING:
   1100  1717  wesolows 			addthisarg = STRDUP((const char *)(uintptr_t)value.v);
   1101     0    stevel 			break;
   1102     0    stevel 		case NODEPTR :
   1103  1717  wesolows 			namep = (struct node *)(uintptr_t)value.v;
   1104     0    stevel 			addthisarg = ipath2str(NULL, ipath(namep));
   1105     0    stevel 			break;
   1106     0    stevel 		default:
   1107     0    stevel 			out(O_ERR,
   1108     0    stevel 			    "call: arglist2argv: unexpected result from"
   1109     0    stevel 			    " operation %s",
   1110     0    stevel 			    ptree_nodetype2str(np->t));
   1111     0    stevel 			return (1);
   1112     0    stevel 		}
   1113     0    stevel 		break;
   1114     0    stevel 	}
   1115     0    stevel 	case T_NUM:
   1116     0    stevel 	case T_TIMEVAL:
   1117     0    stevel 		numbuf[MAXDIGITIDX] = '\0';
   1118     0    stevel 		nullbyte = &numbuf[MAXDIGITIDX];
   1119     0    stevel 		numstr = ulltostr(np->u.ull, nullbyte);
   1120     0    stevel 		addthisarg = STRDUP(numstr);
   1121     0    stevel 		break;
   1122     0    stevel 	case T_NAME:
   1123     0    stevel 		addthisarg = ipath2str(NULL, ipath(np));
   1124     0    stevel 		break;
   1125     0    stevel 	case T_EVENT:
   1126     0    stevel 		addthisarg = ipath2str(np->u.event.ename->u.name.s,
   1127     0    stevel 		    ipath(np->u.event.epname));
   1128     0    stevel 		break;
   1129     0    stevel 	default:
   1130     0    stevel 		out(O_ERR, "call: arglist2argv: node type %s is unsupported",
   1131     0    stevel 		    ptree_nodetype2str(np->t));
   1132     0    stevel 		return (1);
   1133     0    stevel 		/*NOTREACHED*/
   1134     0    stevel 		break;
   1135     0    stevel 	}
   1136     0    stevel 
   1137     0    stevel 	if (*argc == 0 && addthisarg != NULL) {
   1138     0    stevel 		/*
   1139     0    stevel 		 * first argument added is the command name.
   1140     0    stevel 		 */
   1141     0    stevel 		char **files;
   1142     0    stevel 
   1143   186   db35262 		files = platform_get_files_stddirs(addthisarg, 0);
   1144     0    stevel 
   1145     0    stevel 		/* do not proceed if number of files found != 1 */
   1146     0    stevel 		if (files[0] == NULL)
   1147     0    stevel 			out(O_DIE, "call: function %s not found", addthisarg);
   1148     0    stevel 		if (files[1] != NULL)
   1149     0    stevel 			out(O_DIE, "call: multiple functions %s found",
   1150     0    stevel 			    addthisarg);
   1151     0    stevel 		FREE(addthisarg);
   1152     0    stevel 
   1153     0    stevel 		addthisarg = STRDUP(files[0]);
   1154     0    stevel 		FREE(files[0]);
   1155     0    stevel 		FREE(files);
   1156     0    stevel 	}
   1157     0    stevel 
   1158     0    stevel 	if (addthisarg != NULL) {
   1159     0    stevel 		if (*argc >= *argvlen - 2) {
   1160     0    stevel 			/*
   1161     0    stevel 			 * make sure argv is long enough so it has a
   1162     0    stevel 			 * terminating element set to NULL
   1163     0    stevel 			 */
   1164     0    stevel 			*argvlen += 10;
   1165     0    stevel 			*argv = (char **)REALLOC(*argv,
   1166  4198  eschrock 			    sizeof (char *) * *argvlen);
   1167     0    stevel 		}
   1168     0    stevel 		(*argv)[*argc] = addthisarg;
   1169     0    stevel 		(*argc)++;
   1170     0    stevel 		(*argv)[*argc] = NULL;
   1171     0    stevel 	}
   1172     0    stevel 
   1173     0    stevel 	return (0);
   1174     0    stevel }
   1175     0    stevel 
   1176     0    stevel static int
   1177     0    stevel generate_envp(struct arrow *arrowp, char ***envp, int *envc, int *envplen)
   1178     0    stevel {
   1179     0    stevel 	char *envnames[] = { "EFT_FROM_EVENT", "EFT_TO_EVENT",
   1180     0    stevel 			    "EFT_FILE", "EFT_LINE", NULL };
   1181     0    stevel 	char *envvalues[4];
   1182     0    stevel 	char *none = "(none)";
   1183     0    stevel 	size_t elen;
   1184     0    stevel 	int i;
   1185     0    stevel 
   1186     0    stevel 	*envc = 4;
   1187     0    stevel 
   1188     0    stevel 	/*
   1189     0    stevel 	 * make sure envp is long enough so it has a terminating element
   1190     0    stevel 	 * set to NULL
   1191     0    stevel 	 */
   1192     0    stevel 	*envplen = *envc + 1;
   1193     0    stevel 	*envp = (char **)MALLOC(sizeof (char *) * *envplen);
   1194     0    stevel 
   1195     0    stevel 	envvalues[0] = ipath2str(
   1196     0    stevel 	    arrowp->tail->myevent->enode->u.event.ename->u.name.s,
   1197     0    stevel 	    arrowp->tail->myevent->ipp);
   1198     0    stevel 	envvalues[1] = ipath2str(
   1199     0    stevel 	    arrowp->head->myevent->enode->u.event.ename->u.name.s,
   1200     0    stevel 	    arrowp->head->myevent->ipp);
   1201     0    stevel 
   1202     0    stevel 	if (arrowp->head->myevent->enode->file == NULL) {
   1203     0    stevel 		envvalues[2] = STRDUP(none);
   1204     0    stevel 		envvalues[3] = STRDUP(none);
   1205     0    stevel 	} else {
   1206     0    stevel 		envvalues[2] = STRDUP(arrowp->head->myevent->enode->file);
   1207     0    stevel 
   1208     0    stevel 		/* large enough for max int */
   1209     0    stevel 		envvalues[3] = MALLOC(sizeof (char) * 25);
   1210     0    stevel 		(void) snprintf(envvalues[3], sizeof (envvalues[3]), "%d",
   1211  4198  eschrock 		    arrowp->head->myevent->enode->line);
   1212     0    stevel 	}
   1213     0    stevel 
   1214     0    stevel 	for (i = 0; envnames[i] != NULL && i < *envc; i++) {
   1215     0    stevel 		elen = strlen(envnames[i]) + strlen(envvalues[i]) + 2;
   1216     0    stevel 		(*envp)[i] = MALLOC(elen);
   1217     0    stevel 		(void) snprintf((*envp)[i], elen, "%s=%s",
   1218     0    stevel 		    envnames[i], envvalues[i]);
   1219     0    stevel 		FREE(envvalues[i]);
   1220     0    stevel 	}
   1221     0    stevel 	(*envp)[*envc] = NULL;
   1222     0    stevel 
   1223     0    stevel 	return (0);
   1224     0    stevel }
   1225     0    stevel 
   1226     0    stevel /*
   1227     0    stevel  * platform_call -- call an external function
   1228     0    stevel  *
   1229     0    stevel  * evaluate a user-defined function and place result in valuep.  return 0
   1230     0    stevel  * if function evaluation was successful; 1 if otherwise.
   1231     0    stevel  */
   1232     0    stevel int
   1233     0    stevel platform_call(struct node *np, struct lut **globals, struct config *croot,
   1234     0    stevel 	struct arrow *arrowp, struct evalue *valuep)
   1235     0    stevel {
   1236     0    stevel 	/*
   1237     0    stevel 	 * use rather short buffers.  only the first string on outbuf[] is
   1238     0    stevel 	 * taken as output from the called function.  any message in
   1239     0    stevel 	 * errbuf[] is echoed out as an error message.
   1240     0    stevel 	 */
   1241     0    stevel 	char outbuf[256], errbuf[512];
   1242   186   db35262 	struct stat buf;
   1243     0    stevel 	char **argv, **envp;
   1244     0    stevel 	int argc, argvlen, envc, envplen;
   1245     0    stevel 	int i, ret;
   1246     0    stevel 
   1247     0    stevel 	/*
   1248     0    stevel 	 * np is the argument list.  the user-defined function is the first
   1249     0    stevel 	 * element of the list.
   1250     0    stevel 	 */
   1251     0    stevel 	ASSERT(np->t == T_LIST);
   1252     0    stevel 
   1253     0    stevel 	argv = NULL;
   1254     0    stevel 	argc = 0;
   1255     0    stevel 	argvlen = 0;
   1256     0    stevel 	if (arglist2argv(np, globals, croot, arrowp, &argv, &argc, &argvlen) ||
   1257     0    stevel 	    argc == 0)
   1258     0    stevel 		return (1);
   1259   186   db35262 
   1260   186   db35262 	/*
   1261   186   db35262 	 * make sure program has executable bit set
   1262   186   db35262 	 */
   1263   186   db35262 	if (stat(argv[0], &buf) == 0) {
   1264   186   db35262 		int exec_bit_set = 0;
   1265   186   db35262 
   1266   186   db35262 		if (buf.st_uid == geteuid() && buf.st_mode & S_IXUSR)
   1267   186   db35262 			exec_bit_set = 1;
   1268   186   db35262 		else if (buf.st_gid == getegid() && buf.st_mode & S_IXGRP)
   1269   186   db35262 			exec_bit_set = 1;
   1270   186   db35262 		else if (buf.st_mode & S_IXOTH)
   1271   186   db35262 			exec_bit_set = 1;
   1272   186   db35262 
   1273   186   db35262 		if (exec_bit_set == 0)
   1274   186   db35262 			out(O_DIE, "call: executable bit not set on %s",
   1275   186   db35262 			    argv[0]);
   1276   186   db35262 	} else {
   1277   186   db35262 		out(O_DIE, "call: failure in stat(), errno = %d\n", errno);
   1278   186   db35262 	}
   1279     0    stevel 
   1280     0    stevel 	envp = NULL;
   1281     0    stevel 	envc = 0;
   1282     0    stevel 	envplen = 0;
   1283     0    stevel 	if (generate_envp(arrowp, &envp, &envc, &envplen))
   1284     0    stevel 		return (1);
   1285     0    stevel 
   1286     0    stevel 	outbuf[0] = '\0';
   1287     0    stevel 	errbuf[0] = '\0';
   1288     0    stevel 
   1289     0    stevel 	ret = forkandexecve((const char *) argv[0], (char *const *) argv,
   1290  4198  eschrock 	    (char *const *) envp, outbuf, sizeof (outbuf),
   1291  4198  eschrock 	    errbuf, sizeof (errbuf));
   1292     0    stevel 
   1293     0    stevel 	for (i = 0; i < envc; i++)
   1294     0    stevel 		FREE(envp[i]);
   1295     0    stevel 	if (envp)
   1296     0    stevel 		FREE(envp);
   1297     0    stevel 
   1298     0    stevel 	if (ret) {
   1299     0    stevel 		outfl(O_OK, np->file, np->line,
   1300  4198  eschrock 		    "call: failure in fork + exec of %s", argv[0]);
   1301     0    stevel 	} else {
   1302  1414     cindi 		char *ptr;
   1303  1414     cindi 
   1304  1414     cindi 		/* chomp the result */
   1305  1414     cindi 		for (ptr = outbuf; *ptr; ptr++)
   1306  1414     cindi 			if (*ptr == '\n' || *ptr == '\r') {
   1307  1414     cindi 				*ptr = '\0';
   1308  1414     cindi 				break;
   1309  1414     cindi 			}
   1310  1414     cindi 		valuep->t = STRING;
   1311  1717  wesolows 		valuep->v = (uintptr_t)stable(outbuf);
   1312     0    stevel 	}
   1313     0    stevel 
   1314     0    stevel 	if (errbuf[0] != '\0') {
   1315     0    stevel 		ret = 1;
   1316     0    stevel 		outfl(O_OK, np->file, np->line,
   1317  4198  eschrock 		    "call: unexpected stderr output from %s: %s",
   1318  4198  eschrock 		    argv[0], errbuf);
   1319     0    stevel 	}
   1320     0    stevel 
   1321     0    stevel 	for (i = 0; i < argc; i++)
   1322     0    stevel 		FREE(argv[i]);
   1323     0    stevel 	FREE(argv);
   1324     0    stevel 
   1325     0    stevel 	return (ret);
   1326  1414     cindi }
   1327  1414     cindi 
   1328  1414     cindi /*
   1329  1414     cindi  * platform_confcall -- call a configuration database function
   1330  1414     cindi  *
   1331  1414     cindi  * returns result in *valuep, return 0 on success
   1332  1414     cindi  */
   1333  1414     cindi /*ARGSUSED*/
   1334  1414     cindi int
   1335  1414     cindi platform_confcall(struct node *np, struct lut **globals, struct config *croot,
   1336  1414     cindi 	struct arrow *arrowp, struct evalue *valuep)
   1337  1414     cindi {
   1338  7197    stephh 	outfl(O_ALTFP|O_VERB, np->file, np->line, "unknown confcall");
   1339  1414     cindi 	return (0);
   1340     0    stevel }
   1341     0    stevel 
   1342     0    stevel /*
   1343     0    stevel  * platform_get_eft_files -- return names of all eft files we should load
   1344     0    stevel  *
   1345     0    stevel  * this routine doesn't return NULL, even if no files are found (in that
   1346     0    stevel  * case, a char ** is returned with the first element NULL).
   1347     0    stevel  */
   1348     0    stevel char **
   1349     0    stevel platform_get_eft_files(void)
   1350     0    stevel {
   1351   186   db35262 	return (platform_get_files_stddirs(".eft", 1));
   1352     0    stevel }
   1353     0    stevel 
   1354     0    stevel void
   1355     0    stevel platform_free_eft_files(char **flist)
   1356     0    stevel {
   1357     0    stevel 	char **f;
   1358     0    stevel 
   1359     0    stevel 	if (flist == NULL || *flist == NULL)
   1360     0    stevel 		return;	/* no files were found so we're done */
   1361     0    stevel 
   1362     0    stevel 	f = flist;
   1363     0    stevel 	while (*f != NULL) {
   1364     0    stevel 		FREE(*f);
   1365     0    stevel 		f++;
   1366     0    stevel 	}
   1367     0    stevel 	FREE(flist);
   1368     0    stevel }
   1369     0    stevel 
   1370     0    stevel static nvlist_t *payloadnvp = NULL;
   1371     0    stevel 
   1372     0    stevel void
   1373     0    stevel platform_set_payloadnvp(nvlist_t *nvlp)
   1374     0    stevel {
   1375     0    stevel 	/*
   1376     0    stevel 	 * cannot replace a non-NULL payloadnvp with a non-NULL nvlp
   1377     0    stevel 	 */
   1378     0    stevel 	ASSERT(payloadnvp != NULL ? nvlp == NULL : 1);
   1379     0    stevel 	payloadnvp = nvlp;
   1380     0    stevel }
   1381     0    stevel 
   1382     0    stevel /*
   1383     0    stevel  * given array notation in inputstr such as "foo[1]" or "foo [ 1 ]" (spaces
   1384     0    stevel  * allowed), figure out the array name and index.  return 0 if successful,
   1385     0    stevel  * nonzero if otherwise.
   1386     0    stevel  */
   1387     0    stevel static int
   1388     0    stevel get_array_info(const char *inputstr, const char **name, unsigned int *index)
   1389     0    stevel {
   1390     0    stevel 	char *indexptr, *indexend, *dupname, *endname;
   1391     0    stevel 
   1392     0    stevel 	if (strchr(inputstr, '[') == NULL)
   1393     0    stevel 		return (1);
   1394     0    stevel 
   1395     0    stevel 	dupname = STRDUP(inputstr);
   1396     0    stevel 	indexptr = strchr(dupname, '[');
   1397     0    stevel 	indexend = strchr(dupname, ']');
   1398     0    stevel 
   1399     0    stevel 	/*
   1400     0    stevel 	 * return if array notation is not complete or if index is negative
   1401     0    stevel 	 */
   1402     0    stevel 	if (indexend == NULL || indexptr >= indexend ||
   1403     0    stevel 	    strchr(indexptr, '-') != NULL) {
   1404     0    stevel 		FREE(dupname);
   1405     0    stevel 		return (1);
   1406     0    stevel 	}
   1407     0    stevel 
   1408     0    stevel 	/*
   1409     0    stevel 	 * search past any spaces between the name string and '['
   1410     0    stevel 	 */
   1411     0    stevel 	endname = indexptr;
   1412     0    stevel 	while (isspace(*(endname - 1)) && dupname < endname)
   1413     0    stevel 		endname--;
   1414     0    stevel 	*endname = '\0';
   1415     0    stevel 	ASSERT(dupname < endname);
   1416     0    stevel 
   1417     0    stevel 	/*
   1418     0    stevel 	 * search until indexptr points to the first digit and indexend
   1419     0    stevel 	 * points to the last digit
   1420     0    stevel 	 */
   1421     0    stevel 	while (!isdigit(*indexptr) && indexptr < indexend)
   1422     0    stevel 		indexptr++;
   1423     0    stevel 	while (!isdigit(*indexend) && indexptr <= indexend)
   1424     0    stevel 		indexend--;
   1425     0    stevel 
   1426     0    stevel 	*(indexend + 1) = '\0';
   1427     0    stevel 	*index = (unsigned int)atoi(indexptr);
   1428     0    stevel 
   1429     0    stevel 	*name = stable(dupname);
   1430     0    stevel 	FREE(dupname);
   1431     0    stevel 
   1432     0    stevel 	return (0);
   1433     0    stevel }
   1434     0    stevel 
   1435  1414     cindi /*
   1436  1414     cindi  * platform_payloadprop -- fetch a payload value
   1437  1414     cindi  *
   1438  1414     cindi  * XXX this function should be replaced and eval_func() should be
   1439  1414     cindi  * XXX changed to use the more general platform_payloadprop_values().
   1440  1414     cindi  */
   1441     0    stevel int
   1442     0    stevel platform_payloadprop(struct node *np, struct evalue *valuep)
   1443     0    stevel {
   1444   186   db35262 	nvlist_t *basenvp;
   1445  1414     cindi 	nvlist_t *embnvp = NULL;
   1446     0    stevel 	nvpair_t *nvpair;
   1447   186   db35262 	const char *nameptr, *propstr, *lastnameptr;
   1448     0    stevel 	int not_array = 0;
   1449     0    stevel 	unsigned int index = 0;
   1450     0    stevel 	uint_t nelem;
   1451   186   db35262 	char *nvpname, *nameslist = NULL;
   1452  1414     cindi 	char *scheme = NULL;
   1453     0    stevel 
   1454     0    stevel 	ASSERT(np->t == T_QUOTE);
   1455     0    stevel 
   1456   186   db35262 	propstr = np->u.quote.s;
   1457     0    stevel 	if (payloadnvp == NULL) {
   1458  2869    gavinm 		out(O_ALTFP | O_VERB2, "platform_payloadprop: no nvp for %s",
   1459   186   db35262 		    propstr);
   1460     0    stevel 		return (1);
   1461     0    stevel 	}
   1462   186   db35262 	basenvp = payloadnvp;
   1463     0    stevel 
   1464   186   db35262 	/*
   1465   186   db35262 	 * first handle any embedded nvlists.  if propstr is "foo.bar[2]"
   1466   186   db35262 	 * then lastnameptr should end up being "bar[2]" with basenvp set
   1467   186   db35262 	 * to the nvlist for "foo".  (the search for "bar" within "foo"
   1468   186   db35262 	 * will be done later.)
   1469   186   db35262 	 */
   1470   186   db35262 	if (strchr(propstr, '.') != NULL) {
   1471   186   db35262 		nvlist_t **arraynvp;
   1472   186   db35262 		uint_t nelem;
   1473   186   db35262 		char *w;
   1474   186   db35262 		int ier;
   1475   186   db35262 
   1476   186   db35262 		nameslist = STRDUP(propstr);
   1477   186   db35262 		lastnameptr = strtok(nameslist, ".");
   1478   186   db35262 
   1479   186   db35262 		/*
   1480   186   db35262 		 * decompose nameslist into its component names while
   1481   186   db35262 		 * extracting the embedded nvlist
   1482   186   db35262 		 */
   1483   186   db35262 		while ((w = strtok(NULL, ".")) != NULL) {
   1484   186   db35262 			if (get_array_info(lastnameptr, &nameptr, &index)) {
   1485   186   db35262 				ier = nvlist_lookup_nvlist(basenvp,
   1486  4198  eschrock 				    lastnameptr, &basenvp);
   1487   186   db35262 			} else {
   1488   186   db35262 				/* handle array of nvlists */
   1489   186   db35262 				ier = nvlist_lookup_nvlist_array(basenvp,
   1490  4198  eschrock 				    nameptr, &arraynvp, &nelem);
   1491   186   db35262 				if (ier == 0) {
   1492   186   db35262 					if ((uint_t)index > nelem - 1)
   1493   186   db35262 						ier = 1;
   1494   186   db35262 					else
   1495   186   db35262 						basenvp = arraynvp[index];
   1496   186   db35262 				}
   1497   186   db35262 			}
   1498   186   db35262 
   1499   186   db35262 			if (ier) {
   1500   186   db35262 				out(O_ALTFP, "platform_payloadprop: "
   1501   186   db35262 				    " invalid list for %s (in %s)",
   1502   186   db35262 				    lastnameptr, propstr);
   1503   186   db35262 				FREE(nameslist);
   1504   186   db35262 				return (1);
   1505   186   db35262 			}
   1506   186   db35262 
   1507   186   db35262 			lastnameptr = w;
   1508   186   db35262 		}
   1509   186   db35262 	} else {
   1510   186   db35262 		lastnameptr = propstr;
   1511   186   db35262 	}
   1512   186   db35262 
   1513   186   db35262 	/* if property is an array reference, extract array name and index */
   1514   186   db35262 	not_array = get_array_info(lastnameptr, &nameptr, &index);
   1515   186   db35262 	if (not_array)
   1516   186   db35262 		nameptr = stable(lastnameptr);
   1517   186   db35262 
   1518   186   db35262 	if (nameslist != NULL)
   1519   186   db35262 		FREE(nameslist);
   1520     0    stevel 
   1521     0    stevel 	/* search for nvpair entry */
   1522     0    stevel 	nvpair = NULL;
   1523   186   db35262 	while ((nvpair = nvlist_next_nvpair(basenvp, nvpair)) != NULL) {
   1524     0    stevel 		nvpname = nvpair_name(nvpair);
   1525     0    stevel 		ASSERT(nvpname != NULL);
   1526     0    stevel 
   1527   186   db35262 		if (nameptr == stable(nvpname))
   1528     0    stevel 			break;
   1529     0    stevel 	}
   1530     0    stevel 
   1531     0    stevel 	if (nvpair == NULL) {
   1532   186   db35262 		out(O_ALTFP, "platform_payloadprop: no entry for %s", propstr);
   1533     0    stevel 		return (1);
   1534  1414     cindi 	} else if (valuep == NULL) {
   1535  1414     cindi 		/*
   1536  1414     cindi 		 * caller is interested in the existence of a property with
   1537  1414     cindi 		 * this name, regardless of type or value
   1538  1414     cindi 		 */
   1539  1414     cindi 		return (0);
   1540     0    stevel 	}
   1541  1414     cindi 
   1542  1414     cindi 	valuep->t = UNDEFINED;
   1543     0    stevel 
   1544     0    stevel 	/*
   1545     0    stevel 	 * get to this point if we found an entry.  figure out its data
   1546     0    stevel 	 * type and copy its value.
   1547     0    stevel 	 */
   1548  1414     cindi 	(void) nvpair_value_nvlist(nvpair, &embnvp);
   1549  1414     cindi 	if (nvlist_lookup_string(embnvp, FM_FMRI_SCHEME, &scheme) == 0) {
   1550  1414     cindi 		if (strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
   1551  1414     cindi 			valuep->t = NODEPTR;
   1552  1717  wesolows 			valuep->v = (uintptr_t)hc_fmri_nodeize(embnvp);
   1553  1414     cindi 			return (0);
   1554  1414     cindi 		}
   1555  1414     cindi 	}
   1556     0    stevel 	switch (nvpair_type(nvpair)) {
   1557     0    stevel 	case DATA_TYPE_BOOLEAN:
   1558     0    stevel 	case DATA_TYPE_BOOLEAN_VALUE: {
   1559     0    stevel 		boolean_t val;
   1560     0    stevel 		(void) nvpair_value_boolean_value(nvpair, &val);
   1561     0    stevel 		valuep->t = UINT64;
   1562     0    stevel 		valuep->v = (unsigned long long)val;
   1563     0    stevel 		break;
   1564     0    stevel 	}
   1565     0    stevel 	case DATA_TYPE_BYTE: {
   1566     0    stevel 		uchar_t val;
   1567     0    stevel 		(void) nvpair_value_byte(nvpair, &val);
   1568     0    stevel 		valuep->t = UINT64;
   1569     0    stevel 		valuep->v = (unsigned long long)val;
   1570     0    stevel 		break;
   1571     0    stevel 	}
   1572     0    stevel 	case DATA_TYPE_STRING: {
   1573     0    stevel 		char *val;
   1574     0    stevel 		valuep->t = STRING;
   1575     0    stevel 		(void) nvpair_value_string(nvpair, &val);
   1576  1717  wesolows 		valuep->v = (uintptr_t)stable(val);
   1577     0    stevel 		break;
   1578     0    stevel 	}
   1579     0    stevel 
   1580     0    stevel 	case DATA_TYPE_INT8: {
   1581     0    stevel 		int8_t val;
   1582     0    stevel 		(void) nvpair_value_int8(nvpair, &val);
   1583     0    stevel 		valuep->t = UINT64;
   1584     0    stevel 		valuep->v = (unsigned long long)val;
   1585     0    stevel 		break;
   1586     0    stevel 	}
   1587     0    stevel 	case DATA_TYPE_UINT8: {
   1588     0    stevel 		uint8_t val;
   1589     0    stevel 		(void) nvpair_value_uint8(nvpair, &val);
   1590     0    stevel 		valuep->t = UINT64;
   1591     0    stevel 		valuep->v = (unsigned long long)val;
   1592     0    stevel 		break;
   1593     0    stevel 	}
   1594     0    stevel 
   1595     0    stevel 	case DATA_TYPE_INT16: {
   1596     0    stevel 		int16_t val;
   1597     0    stevel 		(void) nvpair_value_int16(nvpair, &val);
   1598     0    stevel 		valuep->t = UINT64;
   1599     0    stevel 		valuep->v = (unsigned long long)val;
   1600     0    stevel 		break;
   1601     0    stevel 	}
   1602     0    stevel 	case DATA_TYPE_UINT16: {
   1603     0    stevel 		uint16_t val;
   1604     0    stevel 		(void) nvpair_value_uint16(nvpair, &val);
   1605     0    stevel 		valuep->t = UINT64;
   1606     0    stevel 		valuep->v = (unsigned long long)val;
   1607     0    stevel 		break;
   1608     0    stevel 	}
   1609     0    stevel 
   1610     0    stevel 	case DATA_TYPE_INT32: {
   1611     0    stevel 		int32_t val;
   1612     0    stevel 		(void) nvpair_value_int32(nvpair, &val);
   1613     0    stevel 		valuep->t = UINT64;
   1614     0    stevel 		valuep->v = (unsigned long long)val;
   1615     0    stevel 		break;
   1616     0    stevel 	}
   1617     0    stevel 	case DATA_TYPE_UINT32: {
   1618     0    stevel 		uint32_t val;
   1619     0    stevel 		(void) nvpair_value_uint32(nvpair, &val);
   1620     0    stevel 		valuep->t = UINT64;
   1621     0    stevel 		valuep->v = (unsigned long long)val;
   1622     0    stevel 		break;
   1623     0    stevel 	}
   1624     0    stevel 
   1625     0    stevel 	case DATA_TYPE_INT64: {
   1626     0    stevel 		int64_t val;
   1627     0    stevel 		(void) nvpair_value_int64(nvpair, &val);
   1628     0    stevel 		valuep->t = UINT64;
   1629     0    stevel 		valuep->v = (unsigned long long)val;
   1630     0    stevel 		break;
   1631     0    stevel 	}
   1632     0    stevel 	case DATA_TYPE_UINT64: {
   1633     0    stevel 		uint64_t val;
   1634     0    stevel 		(void) nvpair_value_uint64(nvpair, &val);
   1635     0    stevel 		valuep->t = UINT64;
   1636     0    stevel 		valuep->v = (unsigned long long)val;
   1637     0    stevel 		break;
   1638     0    stevel 	}
   1639     0    stevel 
   1640     0    stevel 	case DATA_TYPE_BOOLEAN_ARRAY: {
   1641     0    stevel 		boolean_t *val;
   1642     0    stevel 		(void) nvpair_value_boolean_array(nvpair, &val, &nelem);
   1643     0    stevel 		if (not_array == 1 || index >= nelem)
   1644     0    stevel 			goto invalid;
   1645     0    stevel 		valuep->t = UINT64;
   1646     0    stevel 		valuep->v = (unsigned long long)val[index];
   1647     0    stevel 		break;
   1648     0    stevel 	}
   1649     0    stevel 	case DATA_TYPE_BYTE_ARRAY: {
   1650     0    stevel 		uchar_t *val;
   1651     0    stevel 		(void) nvpair_value_byte_array(nvpair, &val, &nelem);
   1652     0    stevel 		if (not_array == 1 || index >= nelem)
   1653     0    stevel 			goto invalid;
   1654     0    stevel 		valuep->t = UINT64;
   1655     0    stevel 		valuep->v = (unsigned long long)val[index];
   1656     0    stevel 		break;
   1657     0    stevel 	}
   1658     0    stevel 	case DATA_TYPE_STRING_ARRAY: {
   1659     0    stevel 		char **val;
   1660     0    stevel 		(void) nvpair_value_string_array(nvpair, &val, &nelem);
   1661     0    stevel 		if (not_array == 1 || index >= nelem)
   1662     0    stevel 			goto invalid;
   1663     0    stevel 		valuep->t = STRING;
   1664  1717  wesolows 		valuep->v = (uintptr_t)stable(val[index]);
   1665     0    stevel 		break;
   1666     0    stevel 	}
   1667     0    stevel 
   1668     0    stevel 	case DATA_TYPE_INT8_ARRAY: {
   1669     0    stevel 		int8_t *val;
   1670     0    stevel 		(void) nvpair_value_int8_array(nvpair, &val, &nelem);
   1671     0    stevel 		if (not_array == 1 || index >= nelem)
   1672     0    stevel 			goto invalid;
   1673     0    stevel 		valuep->t = UINT64;
   1674     0    stevel 		valuep->v = (unsigned long long)val[index];
   1675     0    stevel 		break;
   1676     0    stevel 	}
   1677     0    stevel 	case DATA_TYPE_UINT8_ARRAY: {
   1678     0    stevel 		uint8_t *val;
   1679     0    stevel 		(void) nvpair_value_uint8_array(nvpair, &val, &nelem);
   1680     0    stevel 		if (not_array == 1 || index >= nelem)
   1681     0    stevel 			goto invalid;
   1682     0    stevel 		valuep->t = UINT64;
   1683     0    stevel 		valuep->v = (unsigned long long)val[index];
   1684     0    stevel 		break;
   1685     0    stevel 	}
   1686     0    stevel 	case DATA_TYPE_INT16_ARRAY: {
   1687     0    stevel 		int16_t *val;
   1688     0    stevel 		(void) nvpair_value_int16_array(nvpair, &val, &nelem);
   1689     0    stevel 		if (not_array == 1 || index >= nelem)
   1690     0    stevel 			goto invalid;
   1691     0    stevel 		valuep->t = UINT64;
   1692     0    stevel 		valuep->v = (unsigned long long)val[index];
   1693     0    stevel 		break;
   1694     0    stevel 	}
   1695     0    stevel 	case DATA_TYPE_UINT16_ARRAY: {
   1696     0    stevel 		uint16_t *val;
   1697     0    stevel 		(void) nvpair_value_uint16_array(nvpair, &val, &nelem);
   1698     0    stevel 		if (not_array == 1 || index >= nelem)
   1699     0    stevel 			goto invalid;
   1700     0    stevel 		valuep->t = UINT64;
   1701     0    stevel 		valuep->v = (unsigned long long)val[index];
   1702     0    stevel 		break;
   1703     0    stevel 	}
   1704     0    stevel 	case DATA_TYPE_INT32_ARRAY: {
   1705     0    stevel 		int32_t *val;
   1706     0    stevel 		(void) nvpair_value_int32_array(nvpair, &val, &nelem);
   1707     0    stevel 		if (not_array == 1 || index >= nelem)
   1708     0    stevel 			goto invalid;
   1709     0    stevel 		valuep->t = UINT64;
   1710     0    stevel 		valuep->v = (unsigned long long)val[index];
   1711     0    stevel 		break;
   1712     0    stevel 	}
   1713     0    stevel 	case DATA_TYPE_UINT32_ARRAY: {
   1714     0    stevel 		uint32_t *val;
   1715     0    stevel 		(void) nvpair_value_uint32_array(nvpair, &val, &nelem);
   1716     0    stevel 		if (not_array == 1 || index >= nelem)
   1717     0    stevel 			goto invalid;
   1718     0    stevel 		valuep->t = UINT64;
   1719     0    stevel 		valuep->v = (unsigned long long)val[index];
   1720     0    stevel 		break;
   1721     0    stevel 	}
   1722     0    stevel 	case DATA_TYPE_INT64_ARRAY: {
   1723     0    stevel 		int64_t *val;
   1724     0    stevel 		(void) nvpair_value_int64_array(nvpair, &val, &nelem);
   1725     0    stevel 		if (not_array == 1 || index >= nelem)
   1726     0    stevel 			goto invalid;
   1727     0    stevel 		valuep->t = UINT64;
   1728     0    stevel 		valuep->v = (unsigned long long)val[index];
   1729     0    stevel 		break;
   1730     0    stevel 	}
   1731     0    stevel 	case DATA_TYPE_UINT64_ARRAY: {
   1732     0    stevel 		uint64_t *val;
   1733     0    stevel 		(void) nvpair_value_uint64_array(nvpair, &val, &nelem);
   1734     0    stevel 		if (not_array == 1 || index >= nelem)
   1735     0    stevel 			goto invalid;
   1736     0    stevel 		valuep->t = UINT64;
   1737     0    stevel 		valuep->v = (unsigned long long)val[index];
   1738     0    stevel 		break;
   1739     0    stevel 	}
   1740     0    stevel 
   1741     0    stevel 	default :
   1742  1414     cindi 		out(O_ALTFP|O_VERB2,
   1743     0    stevel 		    "platform_payloadprop: unsupported data type for %s",
   1744   186   db35262 		    propstr);
   1745     0    stevel 		return (1);
   1746     0    stevel 	}
   1747     0    stevel 
   1748     0    stevel 	return (0);
   1749     0    stevel 
   1750     0    stevel invalid:
   1751  1414     cindi 	out(O_ALTFP|O_VERB2,
   1752  1414     cindi 	    "platform_payloadprop: invalid array reference for %s", propstr);
   1753     0    stevel 	return (1);
   1754     0    stevel }
   1755  1414     cindi 
   1756  1414     cindi /*ARGSUSED*/
   1757  1414     cindi int
   1758  1414     cindi platform_path_exists(nvlist_t *fmri)
   1759  1414     cindi {
   1760  1414     cindi 	return (fmd_nvl_fmri_present(Hdl, fmri));
   1761  1414     cindi }
   1762  1414     cindi 
   1763  1414     cindi struct evalue *
   1764  1414     cindi platform_payloadprop_values(const char *propstr, int *nvals)
   1765  1414     cindi {
   1766  1414     cindi 	struct evalue *retvals;
   1767  1414     cindi 	nvlist_t *basenvp;
   1768  1414     cindi 	nvpair_t *nvpair;
   1769  1414     cindi 	char *nvpname;
   1770  1414     cindi 
   1771  1414     cindi 	*nvals = 0;
   1772  1414     cindi 
   1773  1414     cindi 	if (payloadnvp == NULL)
   1774  1414     cindi 		return (NULL);
   1775  1414     cindi 
   1776  1414     cindi 	basenvp = payloadnvp;
   1777  1414     cindi 
   1778  1414     cindi 	/* search for nvpair entry */
   1779  1414     cindi 	nvpair = NULL;
   1780  1414     cindi 	while ((nvpair = nvlist_next_nvpair(basenvp, nvpair)) != NULL) {
   1781  1414     cindi 		nvpname = nvpair_name(nvpair);
   1782  1414     cindi 		ASSERT(nvpname != NULL);
   1783  1414     cindi 
   1784  1414     cindi 		if (strcmp(propstr, nvpname) == 0)
   1785  1414     cindi 			break;
   1786  1414     cindi 	}
   1787  1414     cindi 
   1788  1414     cindi 	if (nvpair == NULL)
   1789  1414     cindi 		return (NULL);	/* property not found */
   1790  1414     cindi 
   1791  1414     cindi 	switch (nvpair_type(nvpair)) {
   1792  1414     cindi 	case DATA_TYPE_NVLIST: {
   1793  1414     cindi 		nvlist_t *embnvp = NULL;
   1794  1414     cindi 		char *scheme = NULL;
   1795  1414     cindi 
   1796  1414     cindi 		(void) nvpair_value_nvlist(nvpair, &embnvp);
   1797  1414     cindi 		if (nvlist_lookup_string(embnvp, FM_FMRI_SCHEME,
   1798  1414     cindi 		    &scheme) == 0) {
   1799  1414     cindi 			if (strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
   1800  1414     cindi 				*nvals = 1;
   1801  1414     cindi 				retvals = MALLOC(sizeof (struct evalue));
   1802  1414     cindi 				retvals->t = NODEPTR;
   1803  1414     cindi 				retvals->v =
   1804  1717  wesolows 				    (uintptr_t)hc_fmri_nodeize(embnvp);
   1805  1414     cindi 				return (retvals);
   1806  1414     cindi 			}
   1807  1414     cindi 		}
   1808  1414     cindi 		return (NULL);
   1809  1414     cindi 	}
   1810  1414     cindi 	case DATA_TYPE_NVLIST_ARRAY: {
   1811  1414     cindi 		char *scheme = NULL;
   1812  1414     cindi 		nvlist_t **nvap;
   1813  1414     cindi 		uint_t nel;
   1814  1414     cindi 		int i;
   1815  1414     cindi 		int hccount;
   1816  1414     cindi 
   1817  1414     cindi 		/*
   1818  1414     cindi 		 * since we're only willing to handle hc fmri's, we
   1819  1414     cindi 		 * must count them first before allocating retvals.
   1820  1414     cindi 		 */
   1821  1414     cindi 		if (nvpair_value_nvlist_array(nvpair, &nvap, &nel) != 0)
   1822  1414     cindi 			return (NULL);
   1823  1414     cindi 
   1824  1414     cindi 		hccount = 0;
   1825  1414     cindi 		for (i = 0; i < nel; i++) {
   1826  1414     cindi 			if (nvlist_lookup_string(nvap[i], FM_FMRI_SCHEME,
   1827  1414     cindi 			    &scheme) == 0 &&
   1828  1414     cindi 			    strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
   1829  1414     cindi 				hccount++;
   1830  1414     cindi 			}
   1831  1414     cindi 		}
   1832  1414     cindi 
   1833  1414     cindi 		if (hccount == 0)
   1834  1414     cindi 			return (NULL);
   1835  1414     cindi 
   1836  1414     cindi 		*nvals = hccount;
   1837  1414     cindi 		retvals = MALLOC(sizeof (struct evalue) * hccount);
   1838  1414     cindi 
   1839  1414     cindi 		hccount = 0;
   1840  1414     cindi 		for (i = 0; i < nel; i++) {
   1841  1414     cindi 			if (nvlist_lookup_string(nvap[i], FM_FMRI_SCHEME,
   1842  1414     cindi 			    &scheme) == 0 &&
   1843  1414     cindi 			    strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
   1844  1414     cindi 				retvals[hccount].t = NODEPTR;
   1845  1717  wesolows 				retvals[hccount].v = (uintptr_t)
   1846  1414     cindi 				    hc_fmri_nodeize(nvap[i]);
   1847  1414     cindi 				hccount++;
   1848  1414     cindi 			}
   1849  1414     cindi 		}
   1850  1414     cindi 		return (retvals);
   1851  1414     cindi 	}
   1852  1414     cindi 	case DATA_TYPE_BOOLEAN:
   1853  1414     cindi 	case DATA_TYPE_BOOLEAN_VALUE: {
   1854  1414     cindi 		boolean_t val;
   1855  1414     cindi 
   1856  1414     cindi 		*nvals = 1;
   1857  1414     cindi 		retvals = MALLOC(sizeof (struct evalue));
   1858  1414     cindi 		(void) nvpair_value_boolean_value(nvpair, &val);
   1859  1414     cindi 		retvals->t = UINT64;
   1860  1414     cindi 		retvals->v = (unsigned long long)val;
   1861  1414     cindi 		return (retvals);
   1862  1414     cindi 	}
   1863  1414     cindi 	case DATA_TYPE_BYTE: {
   1864  1414     cindi 		uchar_t val;
   1865  1414     cindi 
   1866  1414     cindi 		*nvals = 1;
   1867  1414     cindi 		retvals = MALLOC(sizeof (struct evalue));
   1868  1414     cindi 		(void) nvpair_value_byte(nvpair, &val);
   1869  1414     cindi 		retvals->t = UINT64;
   1870  1414     cindi 		retvals->v = (unsigned long long)val;
   1871  1414     cindi 		return (retvals);
   1872  1414     cindi 	}
   1873  1414     cindi 	case DATA_TYPE_STRING: {
   1874  1414     cindi 		char *val;
   1875  1414     cindi 
   1876  1414     cindi 		*nvals = 1;
   1877  1414     cindi 		retvals = MALLOC(sizeof (struct evalue));
   1878  1414     cindi 		retvals->t = STRING;
   1879  1414     cindi 		(void) nvpair_value_string(nvpair, &val);
   1880  1717  wesolows 		retvals->v = (uintptr_t)stable(val);
   1881  1414     cindi 		return (retvals);
   1882  1414     cindi 	}
   1883  1414     cindi 
   1884  1414     cindi 	case DATA_TYPE_INT8: {
   1885  1414     cindi 		int8_t val;
   1886  1414     cindi 
   1887  1414     cindi 		*nvals = 1;
   1888  1414     cindi 		retvals = MALLOC(sizeof (struct evalue));
   1889  1414     cindi 		(void) nvpair_value_int8(nvpair, &val);
   1890  1414     cindi 		retvals->t = UINT64;
   1891  1414     cindi 		retvals->v = (unsigned long long)val;
   1892  1414     cindi 		return (retvals);
   1893  1414     cindi 	}
   1894  1414     cindi 	case DATA_TYPE_UINT8: {
   1895  1414     cindi 		uint8_t val;
   1896  1414     cindi 
   1897  1414     cindi 		*nvals = 1;
   1898  1414     cindi 		retvals = MALLOC(sizeof (struct evalue));
   1899  1414     cindi 		(void) nvpair_value_uint8(nvpair, &val);
   1900  1414     cindi 		retvals->t = UINT64;
   1901  1414     cindi 		retvals->v = (unsigned long long)val;
   1902  1414     cindi 		return (retvals);
   1903  1414     cindi 	}
   1904  1414     cindi 
   1905  1414     cindi 	case DATA_TYPE_INT16: {
   1906  1414     cindi 		int16_t val;
   1907  1414     cindi 
   1908  1414     cindi 		*nvals = 1;
   1909  1414     cindi 		retvals = MALLOC(sizeof (struct evalue));
   1910  1414     cindi 		(void) nvpair_value_int16(nvpair, &val);
   1911  1414     cindi 		retvals->t = UINT64;
   1912  1414     cindi 		retvals->v = (unsigned long long)val;
   1913  1414     cindi 		return (retvals);
   1914  1414     cindi 	}
   1915  1414     cindi 	case DATA_TYPE_UINT16: {
   1916  1414     cindi 		uint16_t val;
   1917  1414     cindi 
   1918  1414     cindi 		*nvals = 1;
   1919  1414     cindi 		retvals = MALLOC(sizeof (struct evalue));
   1920  1414     cindi 		(void) nvpair_value_uint16(nvpair, &val);
   1921  1414     cindi 		retvals->t = UINT64;
   1922  1414     cindi 		retvals->v = (unsigned long long)val;
   1923  1414     cindi 		return (retvals);
   1924  1414     cindi 	}
   1925  1414     cindi 
   1926  1414     cindi 	case DATA_TYPE_INT32: {
   1927  1414     cindi 		int32_t val;
   1928  1414     cindi 
   1929  1414     cindi 		*nvals = 1;
   1930  1414     cindi 		retvals = MALLOC(sizeof (struct evalue));
   1931  1414     cindi 		(void) nvpair_value_int32(nvpair, &val);
   1932  1414     cindi 		retvals->t = UINT64;
   1933  1414     cindi 		retvals->v = (unsigned long long)val;
   1934  1414     cindi 		return (retvals);
   1935  1414     cindi 	}
   1936  1414     cindi 	case DATA_TYPE_UINT32: {
   1937  1414     cindi 		uint32_t val;
   1938  1414     cindi 
   1939  1414     cindi 		*nvals = 1;
   1940  1414     cindi 		retvals = MALLOC(sizeof (struct evalue));
   1941  1414     cindi 		(void) nvpair_value_uint32(nvpair, &val);
   1942  1414     cindi 		retvals->t = UINT64;
   1943  1414     cindi 		retvals->v = (unsigned long long)val;
   1944  1414     cindi 		return (retvals);
   1945  1414     cindi 	}
   1946  1414     cindi 
   1947  1414     cindi 	case DATA_TYPE_INT64: {
   1948  1414     cindi 		int64_t val;
   1949  1414     cindi 
   1950  1414     cindi 		*nvals = 1;
   1951  1414     cindi 		retvals = MALLOC(sizeof (struct evalue));
   1952  1414     cindi 		(void) nvpair_value_int64(nvpair, &val);
   1953  1414     cindi 		retvals->t = UINT64;
   1954  1414     cindi 		retvals->v = (unsigned long long)val;
   1955  1414     cindi 		return (retvals);
   1956  1414     cindi 	}
   1957  1414     cindi 	case DATA_TYPE_UINT64: {
   1958  1414     cindi 		uint64_t val;
   1959  1414     cindi 
   1960  1414     cindi 		*nvals = 1;
   1961  1414     cindi 		retvals = MALLOC(sizeof (struct evalue));
   1962  1414     cindi 		(void) nvpair_value_uint64(nvpair, &val);
   1963  1414     cindi 		retvals->t = UINT64;
   1964  1414     cindi 		retvals->v = (unsigned long long)val;
   1965  1414     cindi 		return (retvals);
   1966  1414     cindi 	}
   1967  1414     cindi 
   1968  1414     cindi 	case DATA_TYPE_BOOLEAN_ARRAY: {
   1969  1414     cindi 		boolean_t *val;
   1970  1414     cindi 		uint_t nel;
   1971  1414     cindi 		int i;
   1972  1414     cindi 
   1973  1414     cindi 		(void) nvpair_value_boolean_array(nvpair, &val, &nel);
   1974  1414     cindi 		*nvals = nel;
   1975  1414     cindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
   1976  1414     cindi 		for (i = 0; i < nel; i++) {
   1977  1414     cindi 			retvals[i].t = UINT64;
   1978  1414     cindi 			retvals[i].v = (unsigned long long)val[i];
   1979  1414     cindi 		}
   1980  1414     cindi 		return (retvals);
   1981  1414     cindi 	}
   1982  1414     cindi 	case DATA_TYPE_BYTE_ARRAY: {
   1983  1414     cindi 		uchar_t *val;
   1984  1414     cindi 		uint_t nel;
   1985  1414     cindi 		int i;
   1986  1414     cindi 
   1987  1414     cindi 		(void) nvpair_value_byte_array(nvpair, &val, &nel);
   1988  1414     cindi 		*nvals = nel;
   1989  1414     cindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
   1990  1414     cindi 		for (i = 0; i < nel; i++) {
   1991  1414     cindi 			retvals[i].t = UINT64;
   1992  1414     cindi 			retvals[i].v = (unsigned long long)val[i];
   1993  1414     cindi 		}
   1994  1414     cindi 		return (retvals);
   1995  1414     cindi 	}
   1996  1414     cindi 	case DATA_TYPE_STRING_ARRAY: {
   1997  1414     cindi 		char **val;
   1998  1414     cindi 		uint_t nel;
   1999  1414     cindi 		int i;
   2000  1414     cindi 
   2001  1414     cindi 		(void) nvpair_value_string_array(nvpair, &val, &nel);
   2002  1414     cindi 		*nvals = nel;
   2003  1414     cindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
   2004  1414     cindi 		for (i = 0; i < nel; i++) {
   2005  1414     cindi 			retvals[i].t = STRING;
   2006  1717  wesolows 			retvals[i].v = (uintptr_t)stable(val[i]);
   2007  1414     cindi 		}
   2008  1414     cindi 		return (retvals);
   2009  1414     cindi 	}
   2010  1414     cindi 
   2011  1414     cindi 	case DATA_TYPE_INT8_ARRAY: {
   2012  1414     cindi 		int8_t *val;
   2013  1414     cindi 		uint_t nel;
   2014  1414     cindi 		int i;
   2015  1414     cindi 
   2016  1414     cindi 		(void) nvpair_value_int8_array(nvpair, &val, &nel);
   2017  1414     cindi 		*nvals = nel;
   2018  1414     cindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
   2019  1414     cindi 		for (i = 0; i < nel; i++) {
   2020  1414     cindi 			retvals[i].t = UINT64;
   2021  1414     cindi 			retvals[i].v = (unsigned long long)val[i];
   2022  1414     cindi 		}
   2023  1414     cindi 		return (retvals);
   2024  1414     cindi 	}
   2025  1414     cindi 	case DATA_TYPE_UINT8_ARRAY: {
   2026  1414     cindi 		uint8_t *val;
   2027  1414     cindi 		uint_t nel;
   2028  1414     cindi 		int i;
   2029  1414     cindi 
   2030  1414     cindi 		(void) nvpair_value_uint8_array(nvpair, &val, &nel);
   2031  1414     cindi 		*nvals = nel;
   2032  1414     cindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
   2033  1414     cindi 		for (i = 0; i < nel; i++) {
   2034  1414     cindi 			retvals[i].t = UINT64;
   2035  1414     cindi 			retvals[i].v = (unsigned long long)val[i];
   2036  1414     cindi 		}
   2037  1414     cindi 		return (retvals);
   2038  1414     cindi 	}
   2039  1414     cindi 	case DATA_TYPE_INT16_ARRAY: {
   2040  1414     cindi 		int16_t *val;
   2041  1414     cindi 		uint_t nel;
   2042  1414     cindi 		int i;
   2043  1414     cindi 
   2044  1414     cindi 		(void) nvpair_value_int16_array(nvpair, &val, &nel);
   2045  1414     cindi 		*nvals = nel;
   2046  1414     cindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
   2047  1414     cindi 		for (i = 0; i < nel; i++) {
   2048  1414     cindi 			retvals[i].t = UINT64;
   2049  1414     cindi 			retvals[i].v = (unsigned long long)val[i];
   2050  1414     cindi 		}
   2051  1414     cindi 		return (retvals);
   2052  1414     cindi 	}
   2053  1414     cindi 	case DATA_TYPE_UINT16_ARRAY: {
   2054  1414     cindi 		uint16_t *val;
   2055  1414     cindi 		uint_t nel;
   2056  1414     cindi 		int i;
   2057  1414     cindi 
   2058  1414     cindi 		(void) nvpair_value_uint16_array(nvpair, &val, &nel);
   2059  1414     cindi 		*nvals = nel;
   2060  1414     cindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
   2061  1414     cindi 		for (i = 0; i < nel; i++) {
   2062  1414     cindi 			retvals[i].t = UINT64;
   2063  1414     cindi 			retvals[i].v = (unsigned long long)val[i];
   2064  1414     cindi 		}
   2065  1414     cindi 		return (retvals);
   2066  1414     cindi 	}
   2067  1414     cindi 	case DATA_TYPE_INT32_ARRAY: {
   2068  1414     cindi 		int32_t *val;
   2069  1414     cindi 		uint_t nel;
   2070  1414     cindi 		int i;
   2071  1414     cindi 
   2072  1414     cindi 		(void) nvpair_value_int32_array(nvpair, &val, &nel);
   2073  1414     cindi 		*nvals = nel;
   2074  1414     cindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
   2075  1414     cindi 		for (i = 0; i < nel; i++) {
   2076  1414     cindi 			retvals[i].t = UINT64;
   2077  1414     cindi 			retvals[i].v = (unsigned long long)val[i];
   2078  1414     cindi 		}
   2079  1414     cindi 		return (retvals);
   2080  1414     cindi 	}
   2081  1414     cindi 	case DATA_TYPE_UINT32_ARRAY: {
   2082  1414     cindi 		uint32_t *val;
   2083  1414     cindi 		uint_t nel;
   2084  1414     cindi 		int i;
   2085  1414     cindi 
   2086  1414     cindi 		(void) nvpair_value_uint32_array(nvpair, &val, &nel);
   2087  1414     cindi 		*nvals = nel;
   2088  1414     cindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
   2089  1414     cindi 		for (i = 0; i < nel; i++) {
   2090  1414     cindi 			retvals[i].t = UINT64;
   2091  1414     cindi 			retvals[i].v = (unsigned long long)val[i];
   2092  1414     cindi 		}
   2093  1414     cindi 		return (retvals);
   2094  1414     cindi 	}
   2095  1414     cindi 	case DATA_TYPE_INT64_ARRAY: {
   2096  1414     cindi 		int64_t *val;
   2097  1414     cindi 		uint_t nel;
   2098  1414     cindi 		int i;
   2099  1414     cindi 
   2100  1414     cindi 		(void) nvpair_value_int64_array(nvpair, &val, &nel);
   2101  1414     cindi 		*nvals = nel;
   2102  1414     cindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
   2103  1414     cindi 		for (i = 0; i < nel; i++) {
   2104  1414     cindi 			retvals[i].t = UINT64;
   2105  1414     cindi 			retvals[i].v = (unsigned long long)val[i];
   2106  1414     cindi 		}
   2107  1414     cindi 		return (retvals);
   2108  1414     cindi 	}
   2109  1414     cindi 	case DATA_TYPE_UINT64_ARRAY: {
   2110  1414     cindi 		uint64_t *val;
   2111  1414     cindi 		uint_t nel;
   2112  1414     cindi 		int i;
   2113  1414     cindi 
   2114  1414     cindi 		(void) nvpair_value_uint64_array(nvpair, &val, &nel);
   2115  1414     cindi 		*nvals = nel;
   2116  1414     cindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
   2117  1414     cindi 		for (i = 0; i < nel; i++) {
   2118  1414     cindi 			retvals[i].t = UINT64;
   2119  1414     cindi 			retvals[i].v = (unsigned long long)val[i];
   2120  1414     cindi 		}
   2121  1414     cindi 		return (retvals);
   2122  1414     cindi 	}
   2123  1414     cindi 
   2124  1414     cindi 	}
   2125  1414     cindi 
   2126  1414     cindi 	return (NULL);
   2127  1414     cindi }
   2128  2120    gavinm 
   2129  2120    gavinm /*
   2130  2120    gavinm  * When a list.repaired event is seen the following is called for
   2131  2120    gavinm  * each fault in the associated fault list to convert the given FMRI
   2132  2120    gavinm  * to an instanced path.  Only hc scheme is supported.
   2133  2120    gavinm  */
   2134  2120    gavinm const struct ipath *
   2135  2120    gavinm platform_fault2ipath(nvlist_t *flt)
   2136  2120    gavinm {
   2137  2120    gavinm 	nvlist_t *rsrc;
   2138  2120    gavinm 	struct node *np;
   2139  2120    gavinm 	char *scheme;
   2140  3323     cindi 	const struct ipath *ip;
   2141  2120    gavinm 
   2142  2120    gavinm 	if (nvlist_lookup_nvlist(flt, FM_FAULT_RESOURCE, &rsrc) != 0) {
   2143  2120    gavinm 		out(O_ALTFP, "platform_fault2ipath: no resource member");
   2144  2120    gavinm 		return (NULL);
   2145  2120    gavinm 	} else if (nvlist_lookup_string(rsrc, FM_FMRI_SCHEME, &scheme) != 0) {
   2146  2120    gavinm 		out(O_ALTFP, "platform_fault2ipath: no scheme type for rsrc");
   2147  2120    gavinm 		return (NULL);
   2148  2120    gavinm 	}
   2149  2120    gavinm 
   2150  2120    gavinm 	if (strncmp(scheme, FM_FMRI_SCHEME_HC,
   2151  2120    gavinm 	    sizeof (FM_FMRI_SCHEME_HC) - 1) != 0) {
   2152  2120    gavinm 		out(O_ALTFP, "platform_fault2ipath: returning NULL for non-hc "
   2153  2120    gavinm 		"scheme %s", scheme);
   2154  2120    gavinm 		return (NULL);
   2155  2120    gavinm 	}
   2156  2120    gavinm 
   2157  2120    gavinm 	if ((np = hc_fmri_nodeize(rsrc)) == NULL)
   2158  2120    gavinm 		return (NULL);		/* nodeize will already have whinged */
   2159  2120    gavinm 
   2160  3323     cindi 	ip = ipath(np);
   2161  3323     cindi 	tree_free(np);
   2162  3323     cindi 	return (ip);
   2163  2120    gavinm }
   2164