17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57aec1d6eScindi  * Common Development and Distribution License (the "License").
67aec1d6eScindi  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*837416c3Scy152378  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  *
257c478bd9Sstevel@tonic-gate  * platform.c -- interfaces to the platform's configuration information
267c478bd9Sstevel@tonic-gate  *
277c478bd9Sstevel@tonic-gate  * this platform.c allows eft to run on Solaris systems.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <stdio.h>
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <string.h>
357c478bd9Sstevel@tonic-gate #include <strings.h>
367c478bd9Sstevel@tonic-gate #include <ctype.h>
377c478bd9Sstevel@tonic-gate #include <dirent.h>
387c478bd9Sstevel@tonic-gate #include <libnvpair.h>
397c478bd9Sstevel@tonic-gate #include <dlfcn.h>
407c478bd9Sstevel@tonic-gate #include <unistd.h>
417c478bd9Sstevel@tonic-gate #include <errno.h>
427c478bd9Sstevel@tonic-gate #include <stropts.h>
437c478bd9Sstevel@tonic-gate #include <sys/types.h>
443e8d8e18Sdb35262 #include <sys/stat.h>
457c478bd9Sstevel@tonic-gate #include <sys/wait.h>
467c478bd9Sstevel@tonic-gate #include <sys/filio.h>
477c478bd9Sstevel@tonic-gate #include <sys/param.h>
487c478bd9Sstevel@tonic-gate #include <sys/fm/protocol.h>
497c478bd9Sstevel@tonic-gate #include <fm/fmd_api.h>
500eb822a1Scindi #include <fm/fmd_fmri.h>
517aec1d6eScindi #include <fm/libtopo.h>
520eb822a1Scindi #include <fm/topo_hc.h>
537c478bd9Sstevel@tonic-gate #include "alloc.h"
547c478bd9Sstevel@tonic-gate #include "out.h"
557c478bd9Sstevel@tonic-gate #include "tree.h"
567c478bd9Sstevel@tonic-gate #include "itree.h"
577c478bd9Sstevel@tonic-gate #include "ipath.h"
587c478bd9Sstevel@tonic-gate #include "ptree.h"
597c478bd9Sstevel@tonic-gate #include "fme.h"
607c478bd9Sstevel@tonic-gate #include "stable.h"
617c478bd9Sstevel@tonic-gate #include "eval.h"
627c478bd9Sstevel@tonic-gate #include "config.h"
637c478bd9Sstevel@tonic-gate #include "platform.h"
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate extern fmd_hdl_t *Hdl;		/* handle from eft.c */
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /*
68b5016cbbSstephh  * Lastcfg points to the last configuration snapshot we made.
697c478bd9Sstevel@tonic-gate  */
707c478bd9Sstevel@tonic-gate static struct cfgdata *Lastcfg;
71b5016cbbSstephh static fmd_hdl_t *Lasthdl;
72b5016cbbSstephh static fmd_case_t *Lastfmcase;
73b5016cbbSstephh static const char *lastcomp;
74b5016cbbSstephh static int in_getpath;
75b5016cbbSstephh extern struct lut *Usednames;
76b5016cbbSstephh int prune_raw_config = 0;
777c478bd9Sstevel@tonic-gate 
78b5016cbbSstephh static topo_hdl_t *Eft_topo_hdl;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate void *
817c478bd9Sstevel@tonic-gate topo_use_alloc(size_t bytes)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 	void *p = alloc_malloc(bytes, NULL, 0);
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 	bzero(p, bytes);
867c478bd9Sstevel@tonic-gate 	return (p);
877c478bd9Sstevel@tonic-gate }
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate void
907c478bd9Sstevel@tonic-gate topo_use_free(void *p)
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate 	alloc_free(p, NULL, 0);
937c478bd9Sstevel@tonic-gate }
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /*ARGSUSED*/
967c478bd9Sstevel@tonic-gate static void *
977c478bd9Sstevel@tonic-gate alloc_nv_alloc(nv_alloc_t *nva, size_t size)
987c478bd9Sstevel@tonic-gate {
997c478bd9Sstevel@tonic-gate 	return (alloc_malloc(size, NULL, 0));
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1037c478bd9Sstevel@tonic-gate static void
1047c478bd9Sstevel@tonic-gate alloc_nv_free(nv_alloc_t *nva, void *p, size_t sz)
1057c478bd9Sstevel@tonic-gate {
1067c478bd9Sstevel@tonic-gate 	alloc_free(p, NULL, 0);
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate const nv_alloc_ops_t Eft_nv_alloc_ops = {
1107c478bd9Sstevel@tonic-gate 	NULL,		/* nv_ao_init() */
1117c478bd9Sstevel@tonic-gate 	NULL,		/* nv_ao_fini() */
1127c478bd9Sstevel@tonic-gate 	alloc_nv_alloc,	/* nv_ao_alloc() */
1137c478bd9Sstevel@tonic-gate 	alloc_nv_free,	/* nv_ao_free() */
1147c478bd9Sstevel@tonic-gate 	NULL		/* nv_ao_reset() */
1157c478bd9Sstevel@tonic-gate };
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate nv_alloc_t Eft_nv_hdl;
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate static char *Root;
1207c478bd9Sstevel@tonic-gate static char *Mach;
1217c478bd9Sstevel@tonic-gate static char *Plat;
1227aec1d6eScindi static char tmpbuf[MAXPATHLEN];
1237aec1d6eScindi static char numbuf[MAXPATHLEN];
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate  * platform_globals -- set global variables based on sysinfo() calls
1277c478bd9Sstevel@tonic-gate  */
1287c478bd9Sstevel@tonic-gate static void
1297c478bd9Sstevel@tonic-gate platform_globals()
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate 	Root = fmd_prop_get_string(Hdl, "fmd.rootdir");
1327c478bd9Sstevel@tonic-gate 	Mach = fmd_prop_get_string(Hdl, "fmd.machine");
1337c478bd9Sstevel@tonic-gate 	Plat = fmd_prop_get_string(Hdl, "fmd.platform");
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate static void
1377c478bd9Sstevel@tonic-gate platform_free_globals()
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate 	fmd_prop_free_string(Hdl, Root);
1407c478bd9Sstevel@tonic-gate 	fmd_prop_free_string(Hdl, Mach);
1417c478bd9Sstevel@tonic-gate 	fmd_prop_free_string(Hdl, Plat);
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate /*
1457c478bd9Sstevel@tonic-gate  * platform_init -- perform any platform-specific initialization
1467c478bd9Sstevel@tonic-gate  */
1477c478bd9Sstevel@tonic-gate void
1487c478bd9Sstevel@tonic-gate platform_init(void)
1497c478bd9Sstevel@tonic-gate {
1507c478bd9Sstevel@tonic-gate 	(void) nv_alloc_init(&Eft_nv_hdl, &Eft_nv_alloc_ops);
15124db4641Seschrock 	Eft_topo_hdl = fmd_hdl_topo_hold(Hdl, TOPO_VERSION);
1527c478bd9Sstevel@tonic-gate 	platform_globals();
1537aec1d6eScindi 
1547aec1d6eScindi 	out(O_ALTFP, "platform_init() sucessful");
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate void
1587c478bd9Sstevel@tonic-gate platform_fini(void)
1597c478bd9Sstevel@tonic-gate {
1607c478bd9Sstevel@tonic-gate 	if (Lastcfg != NULL) {
1617c478bd9Sstevel@tonic-gate 		config_free(Lastcfg);
1627c478bd9Sstevel@tonic-gate 		Lastcfg = NULL;
1637c478bd9Sstevel@tonic-gate 	}
16424db4641Seschrock 	fmd_hdl_topo_rele(Hdl, Eft_topo_hdl);
1657c478bd9Sstevel@tonic-gate 	platform_free_globals();
1667c478bd9Sstevel@tonic-gate 	(void) nv_alloc_fini(&Eft_nv_hdl);
1677aec1d6eScindi 
1687aec1d6eScindi 	out(O_ALTFP, "platform_fini() sucessful");
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate  * hc_fmri_nodeize -- convert hc-scheme FMRI to eft compatible format
1737c478bd9Sstevel@tonic-gate  *
1747c478bd9Sstevel@tonic-gate  * this is an internal platform.c helper routine
1757c478bd9Sstevel@tonic-gate  */
1767c478bd9Sstevel@tonic-gate static struct node *
1777c478bd9Sstevel@tonic-gate hc_fmri_nodeize(nvlist_t *hcfmri)
1787c478bd9Sstevel@tonic-gate {
1797c478bd9Sstevel@tonic-gate 	struct node *pathtree = NULL;
1807c478bd9Sstevel@tonic-gate 	struct node *tmpn;
1817c478bd9Sstevel@tonic-gate 	nvlist_t **hc_prs;
1827c478bd9Sstevel@tonic-gate 	uint_t hc_nprs;
1837c478bd9Sstevel@tonic-gate 	const char *sname;
1847c478bd9Sstevel@tonic-gate 	char *ename;
1857c478bd9Sstevel@tonic-gate 	char *eid;
1867c478bd9Sstevel@tonic-gate 	int e, r;
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	/*
1897c478bd9Sstevel@tonic-gate 	 * What to do with/about hc-root?  Would we have any clue what
1907c478bd9Sstevel@tonic-gate 	 * to do with it if it weren't /?  For now, we don't bother
1917c478bd9Sstevel@tonic-gate 	 * even looking it up.
1927c478bd9Sstevel@tonic-gate 	 */
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	/*
1957c478bd9Sstevel@tonic-gate 	 * Get the hc-list of elements in the FMRI
1967c478bd9Sstevel@tonic-gate 	 */
1977c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_nvlist_array(hcfmri, FM_FMRI_HC_LIST,
1987c478bd9Sstevel@tonic-gate 	    &hc_prs, &hc_nprs) != 0) {
1997c478bd9Sstevel@tonic-gate 		out(O_ALTFP, "XFILE: hc FMRI missing %s", FM_FMRI_HC_LIST);
2007c478bd9Sstevel@tonic-gate 		return (NULL);
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	for (e = 0; e < hc_nprs; e++) {
2047c478bd9Sstevel@tonic-gate 		ename = NULL;
2057c478bd9Sstevel@tonic-gate 		eid = NULL;
2067c478bd9Sstevel@tonic-gate 		r = nvlist_lookup_string(hc_prs[e], FM_FMRI_HC_NAME, &ename);
2077c478bd9Sstevel@tonic-gate 		r |= nvlist_lookup_string(hc_prs[e], FM_FMRI_HC_ID, &eid);
2087c478bd9Sstevel@tonic-gate 		if (r != 0) {
2097c478bd9Sstevel@tonic-gate 			/* probably should bail */
2107c478bd9Sstevel@tonic-gate 			continue;
2117c478bd9Sstevel@tonic-gate 		}
2127c478bd9Sstevel@tonic-gate 		sname = stable(ename);
2137c478bd9Sstevel@tonic-gate 		tmpn = tree_name_iterator(
2147c478bd9Sstevel@tonic-gate 		    tree_name(sname, IT_VERTICAL, NULL, 0),
2157c478bd9Sstevel@tonic-gate 		    tree_num(eid, NULL, 0));
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 		if (pathtree == NULL)
2187c478bd9Sstevel@tonic-gate 			pathtree = tmpn;
2197c478bd9Sstevel@tonic-gate 		else
2207c478bd9Sstevel@tonic-gate 			(void) tree_name_append(pathtree, tmpn);
2217c478bd9Sstevel@tonic-gate 	}
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	return (pathtree);
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate /*
2277c478bd9Sstevel@tonic-gate  * platform_getpath -- extract eft-compatible path from ereport
2287c478bd9Sstevel@tonic-gate  */
2297c478bd9Sstevel@tonic-gate struct node *
2307c478bd9Sstevel@tonic-gate platform_getpath(nvlist_t *nvl)
2317c478bd9Sstevel@tonic-gate {
2327c478bd9Sstevel@tonic-gate 	struct node *ret;
2337c478bd9Sstevel@tonic-gate 	nvlist_t *dfmri = NULL;
2347c478bd9Sstevel@tonic-gate 	char *scheme = NULL;
2357c478bd9Sstevel@tonic-gate 	char *path = NULL;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	/*
2387c478bd9Sstevel@tonic-gate 	 * For now we assume the "path" part of the error report is
2397c478bd9Sstevel@tonic-gate 	 * the detector FMRI
2407c478bd9Sstevel@tonic-gate 	 */
2417c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &dfmri) != 0) {
2427c478bd9Sstevel@tonic-gate 		out(O_ALTFP, "XFILE: ereport has no detector FMRI");
2437c478bd9Sstevel@tonic-gate 		return (NULL);
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_string(dfmri, FM_FMRI_SCHEME, &scheme) != 0) {
2477c478bd9Sstevel@tonic-gate 		out(O_ALTFP, "XFILE: detector FMRI missing scheme");
2487c478bd9Sstevel@tonic-gate 		return (NULL);
2497c478bd9Sstevel@tonic-gate 	}
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	if (strcmp(scheme, FM_FMRI_SCHEME_HC) != 0) {
2527c478bd9Sstevel@tonic-gate 		/*
2537c478bd9Sstevel@tonic-gate 		 *  later, if FM_FMRI_SCHEME_DEV or FM_FMRI_SCHEME_CPU
2547c478bd9Sstevel@tonic-gate 		 *  we can look and perform a reverse translation into
2557c478bd9Sstevel@tonic-gate 		 *  an hc node
2567c478bd9Sstevel@tonic-gate 		 */
2577c478bd9Sstevel@tonic-gate 		uint32_t id;
2587c478bd9Sstevel@tonic-gate 		int isdev = 0;
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 		out(O_ALTFP|O_VERB, "Received ereport in scheme %s", scheme);
2617c478bd9Sstevel@tonic-gate 		if (strcmp(scheme, FM_FMRI_SCHEME_DEV) == 0) {
2627c478bd9Sstevel@tonic-gate 			isdev = 1;
2637c478bd9Sstevel@tonic-gate 		} else if (strcmp(scheme, FM_FMRI_SCHEME_CPU) != 0) {
2647c478bd9Sstevel@tonic-gate 			out(O_ALTFP, "XFILE: detector FMRI not recognized "
2657c478bd9Sstevel@tonic-gate 			    "(scheme is %s, expect %s or %s or %s)",
2667c478bd9Sstevel@tonic-gate 			    scheme, FM_FMRI_SCHEME_HC, FM_FMRI_SCHEME_DEV,
2677c478bd9Sstevel@tonic-gate 			    FM_FMRI_SCHEME_CPU);
2687c478bd9Sstevel@tonic-gate 			return (NULL);
2697c478bd9Sstevel@tonic-gate 		}
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 		if (isdev == 1 &&
2727c478bd9Sstevel@tonic-gate 		    nvlist_lookup_string(dfmri, FM_FMRI_DEV_PATH, &path) != 0) {
2737c478bd9Sstevel@tonic-gate 			out(O_ALTFP, "XFILE: detector FMRI missing %s",
2747c478bd9Sstevel@tonic-gate 			    FM_FMRI_DEV_PATH);
2757c478bd9Sstevel@tonic-gate 			return (NULL);
2767c478bd9Sstevel@tonic-gate 		} else if (isdev == 0 &&
2777c478bd9Sstevel@tonic-gate 		    nvlist_lookup_uint32(dfmri, FM_FMRI_CPU_ID, &id) != 0) {
2787c478bd9Sstevel@tonic-gate 			out(O_ALTFP, "XFILE: detector FMRI missing %s",
2797c478bd9Sstevel@tonic-gate 			    FM_FMRI_CPU_ID);
2807c478bd9Sstevel@tonic-gate 			return (NULL);
2817c478bd9Sstevel@tonic-gate 		}
2827c478bd9Sstevel@tonic-gate 
283b5016cbbSstephh 		lut_free(Usednames, NULL, NULL);
284b5016cbbSstephh 		Usednames = NULL;
285b5016cbbSstephh 		in_getpath = 1;
286b5016cbbSstephh 		if (config_snapshot() == NULL) {
2877c478bd9Sstevel@tonic-gate 			out(O_ALTFP,
2887c478bd9Sstevel@tonic-gate 			    "XFILE: cannot snapshot configuration");
289b5016cbbSstephh 			in_getpath = 0;
2907c478bd9Sstevel@tonic-gate 			return (NULL);
2917c478bd9Sstevel@tonic-gate 		}
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 		/*
2947c478bd9Sstevel@tonic-gate 		 * Look up the path or cpu id in the last config snapshot.
2957c478bd9Sstevel@tonic-gate 		 */
2967c478bd9Sstevel@tonic-gate 		if (isdev == 1 &&
2977c478bd9Sstevel@tonic-gate 		    (ret = config_bydev_lookup(Lastcfg, path)) == NULL)
2987c478bd9Sstevel@tonic-gate 			out(O_ALTFP, "XFILE: no configuration node has "
2997c478bd9Sstevel@tonic-gate 			    "device path matching %s.", path);
3007c478bd9Sstevel@tonic-gate 		else if (isdev == 0 &&
3017c478bd9Sstevel@tonic-gate 		    (ret = config_bycpuid_lookup(Lastcfg, id)) == NULL)
3027c478bd9Sstevel@tonic-gate 			out(O_ALTFP, "XFILE: no configuration node has "
3037c478bd9Sstevel@tonic-gate 			    "cpu-id matching %u.", id);
3047c478bd9Sstevel@tonic-gate 
305e5ba14ffSstephh 		structconfig_free(Lastcfg->cooked);
306b5016cbbSstephh 		config_free(Lastcfg);
307b5016cbbSstephh 		in_getpath = 0;
3087c478bd9Sstevel@tonic-gate 		return (ret);
3097c478bd9Sstevel@tonic-gate 	}
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	return (hc_fmri_nodeize(dfmri));
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate /* Allocate space for raw config strings in chunks of this size */
3157c478bd9Sstevel@tonic-gate #define	STRSBUFLEN	512
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate /*
3187c478bd9Sstevel@tonic-gate  * cfgadjust -- Make sure the amount we want to add to the raw config string
3197c478bd9Sstevel@tonic-gate  *		buffer will fit, and if not, increase the size of the buffer.
3207c478bd9Sstevel@tonic-gate  */
3217c478bd9Sstevel@tonic-gate static void
3227c478bd9Sstevel@tonic-gate cfgadjust(struct cfgdata *rawdata, int addlen)
3237c478bd9Sstevel@tonic-gate {
3247c478bd9Sstevel@tonic-gate 	int curnext, newlen;
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	if (rawdata->nextfree + addlen >= rawdata->end) {
3277c478bd9Sstevel@tonic-gate 		newlen = (((rawdata->nextfree - rawdata->begin + 1 + addlen)
3287c478bd9Sstevel@tonic-gate 		    / STRSBUFLEN) + 1) * STRSBUFLEN;
3297c478bd9Sstevel@tonic-gate 		curnext = rawdata->nextfree - rawdata->begin;
3307c478bd9Sstevel@tonic-gate 		rawdata->begin = REALLOC(rawdata->begin, newlen);
3317c478bd9Sstevel@tonic-gate 		rawdata->nextfree = rawdata->begin + curnext;
3327c478bd9Sstevel@tonic-gate 		rawdata->end = rawdata->begin + newlen;
3337c478bd9Sstevel@tonic-gate 	}
3347c478bd9Sstevel@tonic-gate }
3357c478bd9Sstevel@tonic-gate 
3367aec1d6eScindi static char *
3377aec1d6eScindi hc_path(tnode_t *node)
3387aec1d6eScindi {
3397aec1d6eScindi 	int i, err;
3407aec1d6eScindi 	char *name, *instance, *estr;
3417aec1d6eScindi 	nvlist_t *fmri, **hcl;
3427aec1d6eScindi 	ulong_t ul;
3437aec1d6eScindi 	uint_t nhc;
3447aec1d6eScindi 
3457aec1d6eScindi 	if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE,
3467aec1d6eScindi 	    &fmri, &err) < 0)
3477aec1d6eScindi 		return (NULL);
3487aec1d6eScindi 
3497aec1d6eScindi 	if (nvlist_lookup_nvlist_array(fmri, FM_FMRI_HC_LIST, &hcl, &nhc)
3507aec1d6eScindi 	    != 0) {
3517aec1d6eScindi 		nvlist_free(fmri);
3527aec1d6eScindi 		return (NULL);
3537aec1d6eScindi 	}
3547aec1d6eScindi 
3557aec1d6eScindi 	tmpbuf[0] = '\0';
3567aec1d6eScindi 	for (i = 0; i < nhc; ++i) {
3577aec1d6eScindi 		err = nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name);
3587aec1d6eScindi 		err |= nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &instance);
3597aec1d6eScindi 		if (err) {
3607aec1d6eScindi 			nvlist_free(fmri);
3617aec1d6eScindi 			return (NULL);
3627aec1d6eScindi 		}
3637aec1d6eScindi 
3647aec1d6eScindi 		ul = strtoul(instance, &estr, 10);
3657aec1d6eScindi 		/* conversion to number failed? */
3667aec1d6eScindi 		if (estr == instance) {
3677aec1d6eScindi 			nvlist_free(fmri);
3687aec1d6eScindi 			return (NULL);
3697aec1d6eScindi 		}
3707aec1d6eScindi 
3717aec1d6eScindi 		(void) strlcat(tmpbuf, "/", MAXPATHLEN);
3727aec1d6eScindi 		(void) strlcat(tmpbuf, name, MAXPATHLEN);
373*837416c3Scy152378 		(void) snprintf(numbuf, MAXPATHLEN, "%lu", ul);
3747aec1d6eScindi 		(void) strlcat(tmpbuf, numbuf, MAXPATHLEN);
375b5016cbbSstephh 		lastcomp = stable(name);
3767aec1d6eScindi 	}
3777aec1d6eScindi 
3787aec1d6eScindi 	nvlist_free(fmri);
3797aec1d6eScindi 
3807aec1d6eScindi 	return (tmpbuf);
3817aec1d6eScindi }
3827aec1d6eScindi 
3837aec1d6eScindi static void
3847aec1d6eScindi add_prop_val(topo_hdl_t *thp, struct cfgdata *rawdata, char *propn,
3857aec1d6eScindi     nvpair_t *pv_nvp)
3867aec1d6eScindi {
3877aec1d6eScindi 	int addlen, err;
3887aec1d6eScindi 	char *propv, *fmristr = NULL;
3897aec1d6eScindi 	nvlist_t *fmri;
390b5016cbbSstephh 	uint32_t ui32;
391b5016cbbSstephh 	int64_t i64;
392b5016cbbSstephh 	int32_t i32;
393b5016cbbSstephh 	boolean_t bool;
3948a40a695Sgavinm 	uint64_t ui64;
3958a40a695Sgavinm 	char buf[32];	/* big enough for any 64-bit int */
3967aec1d6eScindi 
3977aec1d6eScindi 	/*
3980eb822a1Scindi 	 * malformed prop nvpair
3990eb822a1Scindi 	 */
4000eb822a1Scindi 	if (propn == NULL)
4010eb822a1Scindi 		return;
4020eb822a1Scindi 
4030eb822a1Scindi 	/*
4048a40a695Sgavinm 	 * We can only handle properties of string type
4058a40a695Sgavinm 	 */
4068a40a695Sgavinm 	switch (nvpair_type(pv_nvp)) {
4078a40a695Sgavinm 	case DATA_TYPE_STRING:
4088a40a695Sgavinm 		(void) nvpair_value_string(pv_nvp, &propv);
4098a40a695Sgavinm 		break;
4108a40a695Sgavinm 
4118a40a695Sgavinm 	case DATA_TYPE_NVLIST:
4128a40a695Sgavinm 		/*
4137aec1d6eScindi 		 * At least try to collect the protocol
4147aec1d6eScindi 		 * properties
4157aec1d6eScindi 		 */
4167aec1d6eScindi 		(void) nvpair_value_nvlist(pv_nvp, &fmri);
4177aec1d6eScindi 		if (topo_fmri_nvl2str(thp, fmri, &fmristr, &err) < 0) {
4187aec1d6eScindi 			out(O_ALTFP, "cfgcollect: failed to convert fmri to "
4197aec1d6eScindi 			    "string");
4207aec1d6eScindi 			return;
4217aec1d6eScindi 		} else {
4227aec1d6eScindi 			propv = fmristr;
4237aec1d6eScindi 		}
4248a40a695Sgavinm 		break;
4257aec1d6eScindi 
4268a40a695Sgavinm 	case DATA_TYPE_UINT64:
4278a40a695Sgavinm 		/*
4288a40a695Sgavinm 		 * Convert uint64 to hex strings
4298a40a695Sgavinm 		 */
4308a40a695Sgavinm 		(void) nvpair_value_uint64(pv_nvp, &ui64);
4318a40a695Sgavinm 		(void) snprintf(buf, sizeof (buf), "0x%llx", ui64);
4328a40a695Sgavinm 		propv = buf;
4338a40a695Sgavinm 		break;
4348a40a695Sgavinm 
435b5016cbbSstephh 	case DATA_TYPE_BOOLEAN_VALUE:
436b5016cbbSstephh 		/*
437b5016cbbSstephh 		 * Convert boolean_t to hex strings
438b5016cbbSstephh 		 */
439b5016cbbSstephh 		(void) nvpair_value_boolean_value(pv_nvp, &bool);
440b5016cbbSstephh 		(void) snprintf(buf, sizeof (buf), "0x%llx", (uint64_t)bool);
441b5016cbbSstephh 		propv = buf;
442b5016cbbSstephh 		break;
443b5016cbbSstephh 
444b5016cbbSstephh 	case DATA_TYPE_INT32:
445b5016cbbSstephh 		/*
446b5016cbbSstephh 		 * Convert int32 to hex strings
447b5016cbbSstephh 		 */
448b5016cbbSstephh 		(void) nvpair_value_int32(pv_nvp, &i32);
449b5016cbbSstephh 		(void) snprintf(buf, sizeof (buf), "0x%llx",
450b5016cbbSstephh 		    (uint64_t)(int64_t)i32);
451b5016cbbSstephh 		propv = buf;
452b5016cbbSstephh 		break;
453b5016cbbSstephh 
454b5016cbbSstephh 	case DATA_TYPE_INT64:
455b5016cbbSstephh 		/*
456b5016cbbSstephh 		 * Convert int64 to hex strings
457b5016cbbSstephh 		 */
458b5016cbbSstephh 		(void) nvpair_value_int64(pv_nvp, &i64);
459b5016cbbSstephh 		(void) snprintf(buf, sizeof (buf), "0x%llx", (uint64_t)i64);
460b5016cbbSstephh 		propv = buf;
461b5016cbbSstephh 		break;
462b5016cbbSstephh 
463b5016cbbSstephh 	case DATA_TYPE_UINT32:
464b5016cbbSstephh 		/*
465b5016cbbSstephh 		 * Convert uint32 to hex strings
466b5016cbbSstephh 		 */
467b5016cbbSstephh 		(void) nvpair_value_uint32(pv_nvp, &ui32);
468b5016cbbSstephh 		(void) snprintf(buf, sizeof (buf), "0x%llx", (uint64_t)ui32);
469b5016cbbSstephh 		propv = buf;
470b5016cbbSstephh 		break;
471b5016cbbSstephh 
4728a40a695Sgavinm 	default:
4730eb822a1Scindi 		out(O_ALTFP, "cfgcollect: failed to get property value for "
4740eb822a1Scindi 		    "%s", propn);
4757aec1d6eScindi 		return;
4767aec1d6eScindi 	}
4777aec1d6eScindi 
4787aec1d6eScindi 	/* = & NULL */
4797aec1d6eScindi 	addlen = strlen(propn) + strlen(propv) + 2;
4807aec1d6eScindi 	cfgadjust(rawdata, addlen);
4817aec1d6eScindi 	(void) snprintf(rawdata->nextfree,
4827aec1d6eScindi 	    rawdata->end - rawdata->nextfree, "%s=%s",
4837aec1d6eScindi 	    propn, propv);
4840eb822a1Scindi 	if (strcmp(propn, TOPO_PROP_RESOURCE) == 0)
485b5016cbbSstephh 		out(O_ALTFP|O_VERB3, "cfgcollect: %s", propv);
4860eb822a1Scindi 
4877aec1d6eScindi 	rawdata->nextfree += addlen;
4887aec1d6eScindi 
4897aec1d6eScindi 	if (fmristr != NULL)
4907aec1d6eScindi 		topo_hdl_strfree(thp, fmristr);
4917aec1d6eScindi }
4927aec1d6eScindi 
4937c478bd9Sstevel@tonic-gate /*
4947c478bd9Sstevel@tonic-gate  * cfgcollect -- Assemble raw configuration data in string form suitable
4957c478bd9Sstevel@tonic-gate  *		 for checkpointing.
4967c478bd9Sstevel@tonic-gate  */
4977aec1d6eScindi static int
4987aec1d6eScindi cfgcollect(topo_hdl_t *thp, tnode_t *node, void *arg)
4997c478bd9Sstevel@tonic-gate {
5007c478bd9Sstevel@tonic-gate 	struct cfgdata *rawdata = (struct cfgdata *)arg;
5010eb822a1Scindi 	int err, addlen;
5027aec1d6eScindi 	char *propn, *path = NULL;
5037aec1d6eScindi 	nvlist_t *p_nv, *pg_nv, *pv_nv;
5047aec1d6eScindi 	nvpair_t *nvp, *pg_nvp, *pv_nvp;
5057c478bd9Sstevel@tonic-gate 
5067aec1d6eScindi 	path = hc_path(node);
5077aec1d6eScindi 	if (path == NULL)
5087aec1d6eScindi 		return (TOPO_WALK_ERR);
5097aec1d6eScindi 
5107c478bd9Sstevel@tonic-gate 	addlen = strlen(path) + 1;
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	cfgadjust(rawdata, addlen);
5137c478bd9Sstevel@tonic-gate 	(void) strcpy(rawdata->nextfree, path);
5147c478bd9Sstevel@tonic-gate 	rawdata->nextfree += addlen;
5157c478bd9Sstevel@tonic-gate 
5167aec1d6eScindi 	/*
517b5016cbbSstephh 	 * If the prune_raw_config flag is set then we will only include in the
518b5016cbbSstephh 	 * raw config those nodes that are used by the rules remaining after
519b5016cbbSstephh 	 * prune_propagations() has been run - ie only those that could possibly
520b5016cbbSstephh 	 * be relevant to the incoming ereport given the current rules. This
521b5016cbbSstephh 	 * means that any other parts of the config will not get saved to the
522b5016cbbSstephh 	 * checkpoint file (even if they may theoretically be used if the
523b5016cbbSstephh 	 * rules are subsequently modified).
524b5016cbbSstephh 	 *
525b5016cbbSstephh 	 * For now prune_raw_config is 0 for Solaris, though it is expected to
526b5016cbbSstephh 	 * be set to 1 for fmsp.
527b5016cbbSstephh 	 *
528b5016cbbSstephh 	 * Note we only prune the raw config like this if we have been called
529b5016cbbSstephh 	 * from newfme(), not if we have been called when handling dev or cpu
530b5016cbbSstephh 	 * scheme ereports from platform_getpath(), as this is called before
531b5016cbbSstephh 	 * prune_propagations() - again this is not an issue on fmsp as the
532b5016cbbSstephh 	 * ereports are all in hc scheme.
533b5016cbbSstephh 	 */
534b5016cbbSstephh 	if (!in_getpath && prune_raw_config &&
535b5016cbbSstephh 	    lut_lookup(Usednames, (void *)lastcomp, NULL) == NULL)
536b5016cbbSstephh 		return (TOPO_WALK_NEXT);
537b5016cbbSstephh 
538b5016cbbSstephh 	/*
5397aec1d6eScindi 	 * Collect properties
5407aec1d6eScindi 	 *
5417aec1d6eScindi 	 * eversholt should support alternate property types
5427aec1d6eScindi 	 * Better yet, topo properties could be represented as
5437aec1d6eScindi 	 * a packed nvlist
5447aec1d6eScindi 	 */
5450eb822a1Scindi 	p_nv = topo_prop_getprops(node, &err);
5467aec1d6eScindi 	for (nvp = nvlist_next_nvpair(p_nv, NULL); nvp != NULL;
5477aec1d6eScindi 	    nvp = nvlist_next_nvpair(p_nv, nvp)) {
5487aec1d6eScindi 		if (strcmp(TOPO_PROP_GROUP, nvpair_name(nvp)) != 0 ||
5497aec1d6eScindi 		    nvpair_type(nvp) != DATA_TYPE_NVLIST)
5507aec1d6eScindi 			continue;
5517aec1d6eScindi 
5527aec1d6eScindi 		(void) nvpair_value_nvlist(nvp, &pg_nv);
5537aec1d6eScindi 
5547aec1d6eScindi 		for (pg_nvp = nvlist_next_nvpair(pg_nv, NULL); pg_nvp != NULL;
5557aec1d6eScindi 		    pg_nvp = nvlist_next_nvpair(pg_nv, pg_nvp)) {
5567aec1d6eScindi 
5577aec1d6eScindi 			if (strcmp(TOPO_PROP_VAL, nvpair_name(pg_nvp)) != 0 ||
5587aec1d6eScindi 			    nvpair_type(pg_nvp) != DATA_TYPE_NVLIST)
5597aec1d6eScindi 				continue;
5607aec1d6eScindi 
5617aec1d6eScindi 			(void) nvpair_value_nvlist(pg_nvp, &pv_nv);
5627aec1d6eScindi 
5630eb822a1Scindi 			propn = NULL;
5647aec1d6eScindi 			for (pv_nvp = nvlist_next_nvpair(pv_nv, NULL);
5657aec1d6eScindi 			    pv_nvp != NULL;
5667aec1d6eScindi 			    pv_nvp = nvlist_next_nvpair(pv_nv, pv_nvp)) {
5677aec1d6eScindi 
5687aec1d6eScindi 				/* Get property name */
5690eb822a1Scindi 				if (strcmp(TOPO_PROP_VAL_NAME,
5700eb822a1Scindi 				    nvpair_name(pv_nvp)) == 0)
5710eb822a1Scindi 					(void) nvpair_value_string(pv_nvp,
5720eb822a1Scindi 					    &propn);
5737aec1d6eScindi 
5747aec1d6eScindi 				/*
5757aec1d6eScindi 				 * Get property value
5767aec1d6eScindi 				 */
5770eb822a1Scindi 				if (strcmp(TOPO_PROP_VAL_VAL,
5780eb822a1Scindi 				    nvpair_name(pv_nvp)) == 0)
5790eb822a1Scindi 					add_prop_val(thp, rawdata, propn,
5800eb822a1Scindi 					    pv_nvp);
5817c478bd9Sstevel@tonic-gate 			}
5827aec1d6eScindi 
5837aec1d6eScindi 		}
5847aec1d6eScindi 	}
5857aec1d6eScindi 
5867aec1d6eScindi 	nvlist_free(p_nv);
5877aec1d6eScindi 
5887aec1d6eScindi 	return (TOPO_WALK_NEXT);
5897c478bd9Sstevel@tonic-gate }
5907c478bd9Sstevel@tonic-gate 
591b5016cbbSstephh void
592b5016cbbSstephh platform_restore_config(fmd_hdl_t *hdl, fmd_case_t *fmcase)
593b5016cbbSstephh {
594b5016cbbSstephh 	if (hdl == Lasthdl && fmcase == Lastfmcase) {
595b5016cbbSstephh 		size_t cfglen;
596b5016cbbSstephh 
597b5016cbbSstephh 		fmd_buf_read(Lasthdl, Lastfmcase, WOBUF_CFGLEN, (void *)&cfglen,
598b5016cbbSstephh 		    sizeof (size_t));
599b5016cbbSstephh 		Lastcfg->begin = MALLOC(cfglen);
600b5016cbbSstephh 		Lastcfg->end = Lastcfg->nextfree = Lastcfg->begin + cfglen;
601b5016cbbSstephh 		fmd_buf_read(Lasthdl, Lastfmcase, WOBUF_CFG, Lastcfg->begin,
602b5016cbbSstephh 		    cfglen);
603b5016cbbSstephh 		Lasthdl = NULL;
604b5016cbbSstephh 		Lastfmcase = NULL;
605b5016cbbSstephh 	}
606b5016cbbSstephh }
607b5016cbbSstephh 
608b5016cbbSstephh void
609b5016cbbSstephh platform_save_config(fmd_hdl_t *hdl, fmd_case_t *fmcase)
610b5016cbbSstephh {
611b5016cbbSstephh 	size_t cfglen;
612b5016cbbSstephh 
613b5016cbbSstephh 	/*
614b5016cbbSstephh 	 * Put the raw config into an fmd_buf. Then we can free it to
615b5016cbbSstephh 	 * save space.
616b5016cbbSstephh 	 */
617b5016cbbSstephh 	Lastfmcase = fmcase;
618b5016cbbSstephh 	Lasthdl = hdl;
619b5016cbbSstephh 	cfglen = Lastcfg->nextfree - Lastcfg->begin;
620b5016cbbSstephh 	fmd_buf_create(hdl, fmcase, WOBUF_CFGLEN, sizeof (cfglen));
621b5016cbbSstephh 	fmd_buf_write(hdl, fmcase, WOBUF_CFGLEN, (void *)&cfglen,
622b5016cbbSstephh 	    sizeof (cfglen));
623b5016cbbSstephh 	if (cfglen != 0) {
624b5016cbbSstephh 		fmd_buf_create(hdl, fmcase, WOBUF_CFG, cfglen);
625b5016cbbSstephh 		fmd_buf_write(hdl, fmcase, WOBUF_CFG, Lastcfg->begin, cfglen);
626b5016cbbSstephh 	}
627b5016cbbSstephh 	FREE(Lastcfg->begin);
628b5016cbbSstephh 	Lastcfg->begin = NULL;
629b5016cbbSstephh 	Lastcfg->end = NULL;
630b5016cbbSstephh 	Lastcfg->nextfree = NULL;
631b5016cbbSstephh }
632b5016cbbSstephh 
6337c478bd9Sstevel@tonic-gate /*
6347c478bd9Sstevel@tonic-gate  * platform_config_snapshot -- gather a snapshot of the current configuration
6357c478bd9Sstevel@tonic-gate  */
6367c478bd9Sstevel@tonic-gate struct cfgdata *
6377c478bd9Sstevel@tonic-gate platform_config_snapshot(void)
6387c478bd9Sstevel@tonic-gate {
6397aec1d6eScindi 	int err;
6407aec1d6eScindi 	topo_walk_t *twp;
6410eb822a1Scindi 	static uint64_t lastgen;
6420eb822a1Scindi 	uint64_t curgen;
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	/*
6457c478bd9Sstevel@tonic-gate 	 * If the DR generation number has changed,
6467c478bd9Sstevel@tonic-gate 	 * we need to grab a new snapshot, otherwise we
6477c478bd9Sstevel@tonic-gate 	 * can simply point them at the last config.
6487c478bd9Sstevel@tonic-gate 	 */
649b5016cbbSstephh 	if (prune_raw_config == 0 && (curgen = fmd_fmri_get_drgen()) <=
650b5016cbbSstephh 	    lastgen && Lastcfg != NULL) {
651b5016cbbSstephh 		Lastcfg->raw_refcnt++;
652b5016cbbSstephh 		/*
653b5016cbbSstephh 		 * if config has been backed away to an fmd_buf, restore it
654b5016cbbSstephh 		 */
655b5016cbbSstephh 		if (Lastcfg->begin == NULL)
656b5016cbbSstephh 			platform_restore_config(Lasthdl, Lastfmcase);
6570eb822a1Scindi 		return (Lastcfg);
6580eb822a1Scindi 	}
6597c478bd9Sstevel@tonic-gate 
6600eb822a1Scindi 	lastgen = curgen;
6617c478bd9Sstevel@tonic-gate 	/* we're getting a new config, so clean up the last one */
662b5016cbbSstephh 	if (Lastcfg != NULL) {
663b5016cbbSstephh 		if (--Lastcfg->raw_refcnt == 0) {
664b5016cbbSstephh 			if (Lastcfg->begin != NULL)
665b5016cbbSstephh 				FREE(Lastcfg->begin);
666b5016cbbSstephh 			FREE(Lastcfg);
667b5016cbbSstephh 		}
668b5016cbbSstephh 	}
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	Lastcfg = MALLOC(sizeof (struct cfgdata));
671b5016cbbSstephh 	Lastcfg->raw_refcnt = 2;	/* caller + Lastcfg */
6727c478bd9Sstevel@tonic-gate 	Lastcfg->begin = Lastcfg->nextfree = Lastcfg->end = NULL;
6737c478bd9Sstevel@tonic-gate 	Lastcfg->cooked = NULL;
6747c478bd9Sstevel@tonic-gate 	Lastcfg->devcache = NULL;
6757c478bd9Sstevel@tonic-gate 	Lastcfg->cpucache = NULL;
6767c478bd9Sstevel@tonic-gate 
6770eb822a1Scindi 
67824db4641Seschrock 	fmd_hdl_topo_rele(Hdl, Eft_topo_hdl);
67924db4641Seschrock 	Eft_topo_hdl = fmd_hdl_topo_hold(Hdl, TOPO_VERSION);
6807c478bd9Sstevel@tonic-gate 
6817aec1d6eScindi 	if ((twp = topo_walk_init(Eft_topo_hdl, FM_FMRI_SCHEME_HC, cfgcollect,
6827aec1d6eScindi 	    Lastcfg, &err)) == NULL) {
6837aec1d6eScindi 		out(O_DIE, "platform_config_snapshot: NULL topology tree: %s",
6847aec1d6eScindi 		    topo_strerror(err));
6857aec1d6eScindi 	}
6867aec1d6eScindi 
6877aec1d6eScindi 	if (topo_walk_step(twp, TOPO_WALK_CHILD) == TOPO_WALK_ERR) {
6887aec1d6eScindi 		topo_walk_fini(twp);
6897aec1d6eScindi 		out(O_DIE, "platform_config_snapshot: error walking topology "
6907aec1d6eScindi 		    "tree");
6917aec1d6eScindi 	}
6927aec1d6eScindi 
6937aec1d6eScindi 	topo_walk_fini(twp);
694b5016cbbSstephh 	out(O_ALTFP|O_STAMP, "raw config complete");
6957aec1d6eScindi 
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	return (Lastcfg);
6987c478bd9Sstevel@tonic-gate }
6997c478bd9Sstevel@tonic-gate 
7007aec1d6eScindi static const char *
7017aec1d6eScindi cfgstrprop_lookup(struct config *croot, char *path, char *pname)
7027c478bd9Sstevel@tonic-gate {
7037aec1d6eScindi 	struct config *cresource;
7047aec1d6eScindi 	const char *fmristr;
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 	/*
7077aec1d6eScindi 	 * The first order of business is to find the resource in the
7087c478bd9Sstevel@tonic-gate 	 * config database so we can examine properties associated with
7097c478bd9Sstevel@tonic-gate 	 * that node.
7107c478bd9Sstevel@tonic-gate 	 */
7117aec1d6eScindi 	if ((cresource = config_lookup(croot, path, 0)) == NULL) {
7127aec1d6eScindi 		out(O_ALTFP, "Cannot find config info for %s.", path);
7137aec1d6eScindi 		return (NULL);
7147aec1d6eScindi 	}
7157aec1d6eScindi 	if ((fmristr = config_getprop(cresource, pname)) == NULL) {
7167aec1d6eScindi 		out(O_ALTFP, "Cannot find %s property for %s resource "
7177aec1d6eScindi 		    "re-write", pname, path);
7187aec1d6eScindi 		return (NULL);
7197aec1d6eScindi 	}
7207aec1d6eScindi 	return (fmristr);
7217c478bd9Sstevel@tonic-gate }
7227c478bd9Sstevel@tonic-gate 
7237aec1d6eScindi static nvlist_t *
7247aec1d6eScindi rewrite_resource(char *pname, struct config *croot, char *path)
7257c478bd9Sstevel@tonic-gate {
7267aec1d6eScindi 	const char *fmristr;
7277aec1d6eScindi 	nvlist_t *fmri;
7287aec1d6eScindi 	int err;
7297c478bd9Sstevel@tonic-gate 
7307aec1d6eScindi 	if ((fmristr = cfgstrprop_lookup(croot, path, pname)) == NULL)
7317aec1d6eScindi 		return (NULL);
7327aec1d6eScindi 
7337aec1d6eScindi 	if (topo_fmri_str2nvl(Eft_topo_hdl, fmristr, &fmri, &err) < 0) {
7347aec1d6eScindi 		out(O_ALTFP, "Can not convert config info: %s",
7357aec1d6eScindi 		    topo_strerror(err));
7367aec1d6eScindi 		return (NULL);
7377c478bd9Sstevel@tonic-gate 	}
7387c478bd9Sstevel@tonic-gate 
7397aec1d6eScindi 	return (fmri);
7407c478bd9Sstevel@tonic-gate }
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate static void
7439dd0f810Scindi defect_units(nvlist_t **ap, struct config *croot, char *path)
7447c478bd9Sstevel@tonic-gate {
7459dd0f810Scindi 	const char *modstr;
7467c478bd9Sstevel@tonic-gate 	nvlist_t *na;
7477aec1d6eScindi 	int err;
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	/*
7509dd0f810Scindi 	 * Defects aren't required to have ASRUs defined with
7517c478bd9Sstevel@tonic-gate 	 * them in the eversholt fault tree, so usually we'll be
7529dd0f810Scindi 	 * creating original FMRIs here.  If the ASRU
7537c478bd9Sstevel@tonic-gate 	 * is defined when we get here, we won't replace it.
7547c478bd9Sstevel@tonic-gate 	 */
7559dd0f810Scindi 	if (*ap != NULL)
7567c478bd9Sstevel@tonic-gate 		return;
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 	/*
7597aec1d6eScindi 	 * Find the driver for this resource and use that to get
7609dd0f810Scindi 	 * a mod fmri for ASRU.  There are no FRUs for defects.
7617c478bd9Sstevel@tonic-gate 	 */
7629dd0f810Scindi 	if ((modstr = cfgstrprop_lookup(croot, path, TOPO_IO_MODULE)) == NULL)
7637c478bd9Sstevel@tonic-gate 		return;
7647c478bd9Sstevel@tonic-gate 
7659dd0f810Scindi 	if (topo_fmri_str2nvl(Eft_topo_hdl, modstr, &na, &err) < 0) {
7669dd0f810Scindi 		out(O_ALTFP, "topo_fmri_str2nvl() of %s failed", modstr);
7677aec1d6eScindi 		return;
7687aec1d6eScindi 	}
7697aec1d6eScindi 
7707c478bd9Sstevel@tonic-gate 	*ap = na;
7717c478bd9Sstevel@tonic-gate }
7727c478bd9Sstevel@tonic-gate 
7737c478bd9Sstevel@tonic-gate /*
7747c478bd9Sstevel@tonic-gate  * platform_units_translate
7757c478bd9Sstevel@tonic-gate  *	This routines offers a chance for platform-specific rewrites of
7767c478bd9Sstevel@tonic-gate  *	the hc scheme FRU and ASRUs associated with a suspect fault.
7777c478bd9Sstevel@tonic-gate  */
7787c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7797c478bd9Sstevel@tonic-gate void
7807c478bd9Sstevel@tonic-gate platform_units_translate(int isdefect, struct config *croot,
7817c478bd9Sstevel@tonic-gate     nvlist_t **dfltasru, nvlist_t **dfltfru, nvlist_t **dfltrsrc, char *path)
7827c478bd9Sstevel@tonic-gate {
7837aec1d6eScindi 	nvlist_t *asru, *rsrc, *fru;
7847c478bd9Sstevel@tonic-gate 
7857aec1d6eScindi 	out(O_ALTFP, "platform_units_translate(%d, ....)", isdefect);
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 	/*
7887aec1d6eScindi 	 * Get our FMRIs from libtopo
7897c478bd9Sstevel@tonic-gate 	 */
7907aec1d6eScindi 	if ((rsrc = rewrite_resource(TOPO_PROP_RESOURCE, croot, path))
7917aec1d6eScindi 	    == NULL) {
7927aec1d6eScindi 		out(O_ALTFP, "Cannot rewrite resource for %s.", path);
7937aec1d6eScindi 	} else {
7947aec1d6eScindi 		nvlist_free(*dfltrsrc);
7957aec1d6eScindi 		*dfltrsrc = rsrc;
7967aec1d6eScindi 	}
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate 	/*
7997c478bd9Sstevel@tonic-gate 	 * If it is a defect we want to re-write the FRU as the pkg
8007c478bd9Sstevel@tonic-gate 	 * scheme fmri of the package containing the buggy driver, and
8017c478bd9Sstevel@tonic-gate 	 * the ASRU as the mod scheme fmri of the driver's kernel
8027c478bd9Sstevel@tonic-gate 	 * module.
8037c478bd9Sstevel@tonic-gate 	 */
8047c478bd9Sstevel@tonic-gate 	if (isdefect) {
8059dd0f810Scindi 		defect_units(dfltasru, croot, path);
8067c478bd9Sstevel@tonic-gate 		return;
8077c478bd9Sstevel@tonic-gate 	}
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	/*
8107aec1d6eScindi 	 * Find the TOPO_PROP_ASRU and TOPO_PROP_FRU properties
8119dd0f810Scindi 	 * for this resource if *dfltasru and *dfltfru are set
8127c478bd9Sstevel@tonic-gate 	 */
8139dd0f810Scindi 	if (*dfltasru != NULL) {
8149dd0f810Scindi 		if ((asru = rewrite_resource(TOPO_PROP_ASRU, croot, path))
8159dd0f810Scindi 		    == NULL) {
8169dd0f810Scindi 			out(O_ALTFP, "Cannot rewrite %s for %s.",
8179dd0f810Scindi 			    TOPO_PROP_ASRU, path);
8187aec1d6eScindi 		} else {
8197aec1d6eScindi 			nvlist_free(*dfltasru);
8207aec1d6eScindi 			*dfltasru = asru;
8217c478bd9Sstevel@tonic-gate 		}
8229dd0f810Scindi 	}
8237c478bd9Sstevel@tonic-gate 
8249dd0f810Scindi 	if (*dfltfru != NULL) {
8259dd0f810Scindi 		if ((fru = rewrite_resource(TOPO_PROP_FRU, croot, path))
8269dd0f810Scindi 		    == NULL) {
8277aec1d6eScindi 			out(O_ALTFP, "Cannot rewrite %s for %s.",
8287aec1d6eScindi 			    TOPO_PROP_FRU, path);
8297aec1d6eScindi 		} else {
8307aec1d6eScindi 			nvlist_free(*dfltfru);
8317aec1d6eScindi 			*dfltfru = fru;
8327c478bd9Sstevel@tonic-gate 		}
8337c478bd9Sstevel@tonic-gate 	}
8349dd0f810Scindi }
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate /*
8377c478bd9Sstevel@tonic-gate  * platform_get_files -- return names of all files we should load
8387c478bd9Sstevel@tonic-gate  *
8397c478bd9Sstevel@tonic-gate  * search directories in dirname[] for all files with names ending with the
8407c478bd9Sstevel@tonic-gate  * substring fnstr.  dirname[] should be a NULL-terminated array.  fnstr
8417c478bd9Sstevel@tonic-gate  * may be set to "*" to indicate all files in a directory.
8427c478bd9Sstevel@tonic-gate  *
8437c478bd9Sstevel@tonic-gate  * if nodups is non-zero, then the first file of a given name found is
8447c478bd9Sstevel@tonic-gate  * the only file added to the list of names.  for example if nodups is
8457c478bd9Sstevel@tonic-gate  * set and we're looking for .efts, and find a pci.eft in the dirname[0],
8467c478bd9Sstevel@tonic-gate  * then no pci.eft found in any of the other dirname[] entries will be
8477c478bd9Sstevel@tonic-gate  * included in the final list of names.
8487c478bd9Sstevel@tonic-gate  *
8497c478bd9Sstevel@tonic-gate  * this routine doesn't return NULL, even if no files are found (in that
8507c478bd9Sstevel@tonic-gate  * case, a char ** is returned with the first element NULL).
8517c478bd9Sstevel@tonic-gate  */
8527c478bd9Sstevel@tonic-gate static char **
8537c478bd9Sstevel@tonic-gate platform_get_files(const char *dirname[], const char *fnstr, int nodups)
8547c478bd9Sstevel@tonic-gate {
8557c478bd9Sstevel@tonic-gate 	DIR *dirp;
8567c478bd9Sstevel@tonic-gate 	struct dirent *dp;
8577c478bd9Sstevel@tonic-gate 	struct lut *foundnames = NULL;
8587c478bd9Sstevel@tonic-gate 	char **files = NULL;	/* char * array of filenames found */
8597c478bd9Sstevel@tonic-gate 	int nfiles = 0;		/* files found so far */
8607c478bd9Sstevel@tonic-gate 	int slots = 0;		/* char * slots allocated in files */
8617c478bd9Sstevel@tonic-gate 	size_t fnlen, d_namelen;
8627c478bd9Sstevel@tonic-gate 	size_t totlen;
8637c478bd9Sstevel@tonic-gate 	int i;
8647c478bd9Sstevel@tonic-gate 	static char *nullav;
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate 	ASSERT(fnstr != NULL);
8677c478bd9Sstevel@tonic-gate 	fnlen = strlen(fnstr);
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 	for (i = 0; dirname[i] != NULL; i++) {
8707c478bd9Sstevel@tonic-gate 		out(O_DEBUG, "Looking for %s files in %s", fnstr, dirname[i]);
8717c478bd9Sstevel@tonic-gate 		if ((dirp = opendir(dirname[i])) == NULL) {
8727c478bd9Sstevel@tonic-gate 			out(O_DEBUG|O_SYS,
8737c478bd9Sstevel@tonic-gate 			    "platform_get_files: opendir failed for %s",
8747c478bd9Sstevel@tonic-gate 			    dirname[i]);
8757c478bd9Sstevel@tonic-gate 			continue;
8767c478bd9Sstevel@tonic-gate 		}
8777c478bd9Sstevel@tonic-gate 		while ((dp = readdir(dirp)) != NULL) {
8787c478bd9Sstevel@tonic-gate 			if ((fnlen == 1 && *fnstr == '*') ||
8797c478bd9Sstevel@tonic-gate 			    ((d_namelen = strlen(dp->d_name)) >= fnlen &&
8807c478bd9Sstevel@tonic-gate 			    strncmp(dp->d_name + d_namelen - fnlen,
8817c478bd9Sstevel@tonic-gate 			    fnstr, fnlen) == 0)) {
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 				if (nodups != 0) {
8847c478bd9Sstevel@tonic-gate 					const char *snm = stable(dp->d_name);
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 					if (lut_lookup(foundnames,
8877c478bd9Sstevel@tonic-gate 					    (void *)snm,
8887c478bd9Sstevel@tonic-gate 					    NULL) != NULL) {
8897c478bd9Sstevel@tonic-gate 						out(O_DEBUG,
8907c478bd9Sstevel@tonic-gate 						    "platform_get_files: "
8917c478bd9Sstevel@tonic-gate 						    "skipping repeated name "
8927c478bd9Sstevel@tonic-gate 						    "%s/%s",
8937c478bd9Sstevel@tonic-gate 						    dirname[i],
8947c478bd9Sstevel@tonic-gate 						    snm);
8957c478bd9Sstevel@tonic-gate 						continue;
8967c478bd9Sstevel@tonic-gate 					}
8977c478bd9Sstevel@tonic-gate 					foundnames = lut_add(foundnames,
8987c478bd9Sstevel@tonic-gate 					    (void *)snm,
8997c478bd9Sstevel@tonic-gate 					    (void *)snm,
9007c478bd9Sstevel@tonic-gate 					    NULL);
9017c478bd9Sstevel@tonic-gate 				}
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate 				if (nfiles > slots - 2) {
9047c478bd9Sstevel@tonic-gate 					/* allocate ten more slots */
9057c478bd9Sstevel@tonic-gate 					slots += 10;
9067c478bd9Sstevel@tonic-gate 					files = (char **)REALLOC(files,
9077c478bd9Sstevel@tonic-gate 					    slots * sizeof (char *));
9087c478bd9Sstevel@tonic-gate 				}
9097c478bd9Sstevel@tonic-gate 				/* prepend directory name and / */
9107c478bd9Sstevel@tonic-gate 				totlen = strlen(dirname[i]) + 1;
9117c478bd9Sstevel@tonic-gate 				totlen += strlen(dp->d_name) + 1;
9127c478bd9Sstevel@tonic-gate 				files[nfiles] = MALLOC(totlen);
9137aec1d6eScindi 				out(O_DEBUG, "File %d: \"%s/%s\"", nfiles,
9147aec1d6eScindi 				    dirname[i], dp->d_name);
9157c478bd9Sstevel@tonic-gate 				(void) snprintf(files[nfiles++], totlen,
9167c478bd9Sstevel@tonic-gate 				    "%s/%s", dirname[i], dp->d_name);
9177c478bd9Sstevel@tonic-gate 			}
9187c478bd9Sstevel@tonic-gate 		}
9197c478bd9Sstevel@tonic-gate 		(void) closedir(dirp);
9207c478bd9Sstevel@tonic-gate 	}
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate 	if (foundnames != NULL)
9237c478bd9Sstevel@tonic-gate 		lut_free(foundnames, NULL, NULL);
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate 	if (nfiles == 0)
9267c478bd9Sstevel@tonic-gate 		return (&nullav);
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate 	files[nfiles] = NULL;
9297c478bd9Sstevel@tonic-gate 	return (files);
9307c478bd9Sstevel@tonic-gate }
9317c478bd9Sstevel@tonic-gate 
9327c478bd9Sstevel@tonic-gate /*
9333e8d8e18Sdb35262  * search for files in a standard set of directories
9343e8d8e18Sdb35262  */
9353e8d8e18Sdb35262 static char **
9363e8d8e18Sdb35262 platform_get_files_stddirs(char *fname, int nodups)
9373e8d8e18Sdb35262 {
9383e8d8e18Sdb35262 	const char *dirlist[4];
9393e8d8e18Sdb35262 	char **flist;
9403e8d8e18Sdb35262 	char *eftgendir, *eftmachdir, *eftplatdir;
9413e8d8e18Sdb35262 
9423e8d8e18Sdb35262 	eftgendir = MALLOC(MAXPATHLEN);
9433e8d8e18Sdb35262 	eftmachdir = MALLOC(MAXPATHLEN);
9443e8d8e18Sdb35262 	eftplatdir = MALLOC(MAXPATHLEN);
9453e8d8e18Sdb35262 
9463e8d8e18Sdb35262 	/* Generic files that apply to any machine */
9473e8d8e18Sdb35262 	(void) snprintf(eftgendir, MAXPATHLEN, "%s/usr/lib/fm/eft", Root);
9483e8d8e18Sdb35262 
9493e8d8e18Sdb35262 	(void) snprintf(eftmachdir,
9503e8d8e18Sdb35262 	    MAXPATHLEN, "%s/usr/platform/%s/lib/fm/eft", Root, Mach);
9513e8d8e18Sdb35262 
9523e8d8e18Sdb35262 	(void) snprintf(eftplatdir,
9533e8d8e18Sdb35262 	    MAXPATHLEN, "%s/usr/platform/%s/lib/fm/eft", Root, Plat);
9543e8d8e18Sdb35262 
9553e8d8e18Sdb35262 	dirlist[0] = eftplatdir;
9563e8d8e18Sdb35262 	dirlist[1] = eftmachdir;
9573e8d8e18Sdb35262 	dirlist[2] = eftgendir;
9583e8d8e18Sdb35262 	dirlist[3] = NULL;
9593e8d8e18Sdb35262 
9603e8d8e18Sdb35262 	flist = platform_get_files(dirlist, fname, nodups);
9613e8d8e18Sdb35262 
9623e8d8e18Sdb35262 	FREE(eftplatdir);
9633e8d8e18Sdb35262 	FREE(eftmachdir);
9643e8d8e18Sdb35262 	FREE(eftgendir);
9653e8d8e18Sdb35262 
9663e8d8e18Sdb35262 	return (flist);
9673e8d8e18Sdb35262 }
9683e8d8e18Sdb35262 
9693e8d8e18Sdb35262 /*
9707c478bd9Sstevel@tonic-gate  * platform_run_poller -- execute a poller
9717c478bd9Sstevel@tonic-gate  *
9727c478bd9Sstevel@tonic-gate  * when eft needs to know if a polled ereport exists this routine
9737c478bd9Sstevel@tonic-gate  * is called so the poller code may be run in a platform-specific way.
9747c478bd9Sstevel@tonic-gate  * there's no return value from this routine -- either the polled ereport
9757c478bd9Sstevel@tonic-gate  * is generated (and delivered *before* this routine returns) or not.
9767c478bd9Sstevel@tonic-gate  * any errors, like "poller unknown" are considered platform-specific
9777c478bd9Sstevel@tonic-gate  * should be handled here rather than passing an error back up.
9787c478bd9Sstevel@tonic-gate  */
9797c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9807c478bd9Sstevel@tonic-gate void
9817c478bd9Sstevel@tonic-gate platform_run_poller(const char *poller)
9827c478bd9Sstevel@tonic-gate {
9837c478bd9Sstevel@tonic-gate }
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate /*
9867c478bd9Sstevel@tonic-gate  * fork and execve path with argument array argv and environment array
9877c478bd9Sstevel@tonic-gate  * envp.  data from stdout and stderr are placed in outbuf and errbuf,
9887c478bd9Sstevel@tonic-gate  * respectively.
9897c478bd9Sstevel@tonic-gate  *
9907c478bd9Sstevel@tonic-gate  * see execve(2) for more descriptions for path, argv and envp.
9917c478bd9Sstevel@tonic-gate  */
9927c478bd9Sstevel@tonic-gate static int
9937c478bd9Sstevel@tonic-gate forkandexecve(const char *path, char *const argv[], char *const envp[],
9947c478bd9Sstevel@tonic-gate 	char *outbuf, size_t outbuflen, char *errbuf, size_t errbuflen)
9957c478bd9Sstevel@tonic-gate {
9967c478bd9Sstevel@tonic-gate 	pid_t pid;
9977c478bd9Sstevel@tonic-gate 	int outpipe[2], errpipe[2];
9987c478bd9Sstevel@tonic-gate 	int rt = 0;
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate 	/*
10017c478bd9Sstevel@tonic-gate 	 * run the cmd and see if it failed.  this function is *not* a
10027c478bd9Sstevel@tonic-gate 	 * generic command runner -- we depend on some knowledge we
10037c478bd9Sstevel@tonic-gate 	 * have about the commands we run.  first of all, we expect
10047c478bd9Sstevel@tonic-gate 	 * errors to spew something to stdout, and that something is
10057c478bd9Sstevel@tonic-gate 	 * typically short enough to fit into a pipe so we can wait()
10067c478bd9Sstevel@tonic-gate 	 * for the command to complete and then fetch the error text
10077c478bd9Sstevel@tonic-gate 	 * from the pipe.
10087c478bd9Sstevel@tonic-gate 	 */
10097c478bd9Sstevel@tonic-gate 	if (pipe(outpipe) < 0)
10107c478bd9Sstevel@tonic-gate 		if (strlcat(errbuf, ": pipe(outpipe) failed",
10117c478bd9Sstevel@tonic-gate 		    errbuflen) >= errbuflen)
10127c478bd9Sstevel@tonic-gate 			return (1);
10137c478bd9Sstevel@tonic-gate 	if (pipe(errpipe) < 0)
10147c478bd9Sstevel@tonic-gate 		if (strlcat(errbuf, ": pipe(errpipe) failed",
10157c478bd9Sstevel@tonic-gate 		    errbuflen) >= errbuflen)
10167c478bd9Sstevel@tonic-gate 			return (1);
10177c478bd9Sstevel@tonic-gate 
101824db4641Seschrock 	if ((pid = fork()) < 0) {
10197c478bd9Sstevel@tonic-gate 		rt = (int)strlcat(errbuf, ": fork() failed", errbuflen);
102024db4641Seschrock 	} else if (pid) {
10217c478bd9Sstevel@tonic-gate 		int wstat, count;
10227c478bd9Sstevel@tonic-gate 
10237c478bd9Sstevel@tonic-gate 		/* parent */
10247c478bd9Sstevel@tonic-gate 		(void) close(errpipe[1]);
10257c478bd9Sstevel@tonic-gate 		(void) close(outpipe[1]);
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 		/* PHASE2 need to guard against hang in child? */
10287c478bd9Sstevel@tonic-gate 		if (waitpid(pid, &wstat, 0) < 0)
10297c478bd9Sstevel@tonic-gate 			if (strlcat(errbuf, ": waitpid() failed",
10307c478bd9Sstevel@tonic-gate 			    errbuflen) >= errbuflen)
10317c478bd9Sstevel@tonic-gate 				return (1);
10327c478bd9Sstevel@tonic-gate 
10337c478bd9Sstevel@tonic-gate 		/* check for stderr contents */
10347c478bd9Sstevel@tonic-gate 		if (ioctl(errpipe[0], FIONREAD, &count) >= 0 && count) {
10357c478bd9Sstevel@tonic-gate 			if (read(errpipe[0], errbuf, errbuflen) <= 0) {
10367c478bd9Sstevel@tonic-gate 				/*
10377c478bd9Sstevel@tonic-gate 				 * read failed even though ioctl indicated
10387c478bd9Sstevel@tonic-gate 				 * that nonzero bytes were available for
10397c478bd9Sstevel@tonic-gate 				 * reading
10407c478bd9Sstevel@tonic-gate 				 */
10417c478bd9Sstevel@tonic-gate 				if (strlcat(errbuf, ": read(errpipe) failed",
10427c478bd9Sstevel@tonic-gate 				    errbuflen) >= errbuflen)
10437c478bd9Sstevel@tonic-gate 					return (1);
10447c478bd9Sstevel@tonic-gate 			}
10457c478bd9Sstevel@tonic-gate 			/*
10467c478bd9Sstevel@tonic-gate 			 * handle case where errbuf is not properly
10477c478bd9Sstevel@tonic-gate 			 * terminated
10487c478bd9Sstevel@tonic-gate 			 */
10497c478bd9Sstevel@tonic-gate 			if (count > errbuflen - 1)
10507c478bd9Sstevel@tonic-gate 				count = errbuflen - 1;
10517c478bd9Sstevel@tonic-gate 			if (errbuf[count - 1] != '\0' &&
10527c478bd9Sstevel@tonic-gate 			    errbuf[count - 1] != '\n')
10537c478bd9Sstevel@tonic-gate 				errbuf[count] = '\0';
10547c478bd9Sstevel@tonic-gate 		} else if (WIFSIGNALED(wstat))
10557c478bd9Sstevel@tonic-gate 			if (strlcat(errbuf, ": signaled",
10567c478bd9Sstevel@tonic-gate 			    errbuflen) >= errbuflen)
10577c478bd9Sstevel@tonic-gate 				return (1);
10587c478bd9Sstevel@tonic-gate 		else if (WIFEXITED(wstat) && WEXITSTATUS(wstat))
10597c478bd9Sstevel@tonic-gate 			if (strlcat(errbuf, ": abnormal exit",
10607c478bd9Sstevel@tonic-gate 			    errbuflen) >= errbuflen)
10617c478bd9Sstevel@tonic-gate 				return (1);
10627c478bd9Sstevel@tonic-gate 
10637c478bd9Sstevel@tonic-gate 		/* check for stdout contents */
10647c478bd9Sstevel@tonic-gate 		if (ioctl(outpipe[0], FIONREAD, &count) >= 0 && count) {
10657c478bd9Sstevel@tonic-gate 			if (read(outpipe[0], outbuf, outbuflen) <= 0) {
10667c478bd9Sstevel@tonic-gate 				/*
10677c478bd9Sstevel@tonic-gate 				 * read failed even though ioctl indicated
10687c478bd9Sstevel@tonic-gate 				 * that nonzero bytes were available for
10697c478bd9Sstevel@tonic-gate 				 * reading
10707c478bd9Sstevel@tonic-gate 				 */
10717c478bd9Sstevel@tonic-gate 				if (strlcat(errbuf, ": read(outpipe) failed",
10727c478bd9Sstevel@tonic-gate 				    errbuflen) >= errbuflen)
10737c478bd9Sstevel@tonic-gate 					return (1);
10747c478bd9Sstevel@tonic-gate 			}
10757c478bd9Sstevel@tonic-gate 			/*
10767c478bd9Sstevel@tonic-gate 			 * handle case where outbuf is not properly
10777c478bd9Sstevel@tonic-gate 			 * terminated
10787c478bd9Sstevel@tonic-gate 			 */
10797c478bd9Sstevel@tonic-gate 			if (count > outbuflen - 1)
10807c478bd9Sstevel@tonic-gate 				count = outbuflen - 1;
10817c478bd9Sstevel@tonic-gate 			if (outbuf[count - 1] != '\0' &&
10827c478bd9Sstevel@tonic-gate 			    outbuf[count - 1] != '\n')
10837c478bd9Sstevel@tonic-gate 				outbuf[count] = '\0';
10847c478bd9Sstevel@tonic-gate 		}
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 		(void) close(errpipe[0]);
10877c478bd9Sstevel@tonic-gate 		(void) close(outpipe[0]);
10887c478bd9Sstevel@tonic-gate 	} else {
10897c478bd9Sstevel@tonic-gate 		/* child */
10907c478bd9Sstevel@tonic-gate 		(void) dup2(errpipe[1], fileno(stderr));
10917c478bd9Sstevel@tonic-gate 		(void) close(errpipe[0]);
10927c478bd9Sstevel@tonic-gate 		(void) dup2(outpipe[1], fileno(stdout));
10937c478bd9Sstevel@tonic-gate 		(void) close(outpipe[0]);
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 		if (execve(path, argv, envp))
10967c478bd9Sstevel@tonic-gate 			perror(path);
10977c478bd9Sstevel@tonic-gate 		_exit(1);
10987c478bd9Sstevel@tonic-gate 	}
10997c478bd9Sstevel@tonic-gate 
11007c478bd9Sstevel@tonic-gate 	return (rt);
11017c478bd9Sstevel@tonic-gate }
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate #define	MAXDIGITIDX	23
11047c478bd9Sstevel@tonic-gate 
11057c478bd9Sstevel@tonic-gate static int
11067c478bd9Sstevel@tonic-gate arglist2argv(struct node *np, struct lut **globals, struct config *croot,
11077c478bd9Sstevel@tonic-gate 	struct arrow *arrowp, char ***argv, int *argc, int *argvlen)
11087c478bd9Sstevel@tonic-gate {
11097c478bd9Sstevel@tonic-gate 	struct node *namep;
11107c478bd9Sstevel@tonic-gate 	char numbuf[MAXDIGITIDX + 1];
11117c478bd9Sstevel@tonic-gate 	char *numstr, *nullbyte;
11127c478bd9Sstevel@tonic-gate 	char *addthisarg = NULL;
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate 	if (np == NULL)
11157c478bd9Sstevel@tonic-gate 		return (0);
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate 	switch (np->t) {
11187c478bd9Sstevel@tonic-gate 	case T_QUOTE:
11197c478bd9Sstevel@tonic-gate 		addthisarg = STRDUP(np->u.func.s);
11207c478bd9Sstevel@tonic-gate 		break;
11217c478bd9Sstevel@tonic-gate 	case T_LIST:
11227c478bd9Sstevel@tonic-gate 		if (arglist2argv(np->u.expr.left, globals, croot, arrowp,
11237c478bd9Sstevel@tonic-gate 		    argv, argc, argvlen))
11247c478bd9Sstevel@tonic-gate 			return (1);
11257c478bd9Sstevel@tonic-gate 		/*
11267c478bd9Sstevel@tonic-gate 		 * only leftmost element of a list can provide the command
11277c478bd9Sstevel@tonic-gate 		 * name (after which *argc becomes 1)
11287c478bd9Sstevel@tonic-gate 		 */
11297c478bd9Sstevel@tonic-gate 		ASSERT(*argc > 0);
11307c478bd9Sstevel@tonic-gate 		if (arglist2argv(np->u.expr.right, globals, croot, arrowp,
11317c478bd9Sstevel@tonic-gate 		    argv, argc, argvlen))
11327c478bd9Sstevel@tonic-gate 			return (1);
11337c478bd9Sstevel@tonic-gate 		break;
11347c478bd9Sstevel@tonic-gate 	case T_FUNC:
11357c478bd9Sstevel@tonic-gate 	case T_GLOBID:
11367c478bd9Sstevel@tonic-gate 	case T_ASSIGN:
11377c478bd9Sstevel@tonic-gate 	case T_CONDIF:
11387c478bd9Sstevel@tonic-gate 	case T_CONDELSE:
11397c478bd9Sstevel@tonic-gate 	case T_EQ:
11407c478bd9Sstevel@tonic-gate 	case T_NE:
11417c478bd9Sstevel@tonic-gate 	case T_LT:
11427c478bd9Sstevel@tonic-gate 	case T_LE:
11437c478bd9Sstevel@tonic-gate 	case T_GT:
11447c478bd9Sstevel@tonic-gate 	case T_GE:
11457c478bd9Sstevel@tonic-gate 	case T_BITAND:
11467c478bd9Sstevel@tonic-gate 	case T_BITOR:
11477c478bd9Sstevel@tonic-gate 	case T_BITXOR:
11487c478bd9Sstevel@tonic-gate 	case T_BITNOT:
11497c478bd9Sstevel@tonic-gate 	case T_LSHIFT:
11507c478bd9Sstevel@tonic-gate 	case T_RSHIFT:
11517c478bd9Sstevel@tonic-gate 	case T_AND:
11527c478bd9Sstevel@tonic-gate 	case T_OR:
11537c478bd9Sstevel@tonic-gate 	case T_NOT:
11547c478bd9Sstevel@tonic-gate 	case T_ADD:
11557c478bd9Sstevel@tonic-gate 	case T_SUB:
11567c478bd9Sstevel@tonic-gate 	case T_MUL:
11577c478bd9Sstevel@tonic-gate 	case T_DIV:
11587c478bd9Sstevel@tonic-gate 	case T_MOD: {
11597c478bd9Sstevel@tonic-gate 		struct evalue value;
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate 		if (!eval_expr(np, NULL, NULL, globals, croot, arrowp,
11627c478bd9Sstevel@tonic-gate 		    0, &value))
11637c478bd9Sstevel@tonic-gate 			return (1);
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate 		switch (value.t) {
11667c478bd9Sstevel@tonic-gate 		case UINT64:
11677c478bd9Sstevel@tonic-gate 			numbuf[MAXDIGITIDX] = '\0';
11687c478bd9Sstevel@tonic-gate 			nullbyte = &numbuf[MAXDIGITIDX];
11697c478bd9Sstevel@tonic-gate 			numstr = ulltostr(value.v, nullbyte);
11707c478bd9Sstevel@tonic-gate 			addthisarg = STRDUP(numstr);
11717c478bd9Sstevel@tonic-gate 			break;
11727c478bd9Sstevel@tonic-gate 		case STRING:
117380ab886dSwesolows 			addthisarg = STRDUP((const char *)(uintptr_t)value.v);
11747c478bd9Sstevel@tonic-gate 			break;
11757c478bd9Sstevel@tonic-gate 		case NODEPTR :
117680ab886dSwesolows 			namep = (struct node *)(uintptr_t)value.v;
11777c478bd9Sstevel@tonic-gate 			addthisarg = ipath2str(NULL, ipath(namep));
11787c478bd9Sstevel@tonic-gate 			break;
11797c478bd9Sstevel@tonic-gate 		default:
11807c478bd9Sstevel@tonic-gate 			out(O_ERR,
11817c478bd9Sstevel@tonic-gate 			    "call: arglist2argv: unexpected result from"
11827c478bd9Sstevel@tonic-gate 			    " operation %s",
11837c478bd9Sstevel@tonic-gate 			    ptree_nodetype2str(np->t));
11847c478bd9Sstevel@tonic-gate 			return (1);
11857c478bd9Sstevel@tonic-gate 		}
11867c478bd9Sstevel@tonic-gate 		break;
11877c478bd9Sstevel@tonic-gate 	}
11887c478bd9Sstevel@tonic-gate 	case T_NUM:
11897c478bd9Sstevel@tonic-gate 	case T_TIMEVAL:
11907c478bd9Sstevel@tonic-gate 		numbuf[MAXDIGITIDX] = '\0';
11917c478bd9Sstevel@tonic-gate 		nullbyte = &numbuf[MAXDIGITIDX];
11927c478bd9Sstevel@tonic-gate 		numstr = ulltostr(np->u.ull, nullbyte);
11937c478bd9Sstevel@tonic-gate 		addthisarg = STRDUP(numstr);
11947c478bd9Sstevel@tonic-gate 		break;
11957c478bd9Sstevel@tonic-gate 	case T_NAME:
11967c478bd9Sstevel@tonic-gate 		addthisarg = ipath2str(NULL, ipath(np));
11977c478bd9Sstevel@tonic-gate 		break;
11987c478bd9Sstevel@tonic-gate 	case T_EVENT:
11997c478bd9Sstevel@tonic-gate 		addthisarg = ipath2str(np->u.event.ename->u.name.s,
12007c478bd9Sstevel@tonic-gate 		    ipath(np->u.event.epname));
12017c478bd9Sstevel@tonic-gate 		break;
12027c478bd9Sstevel@tonic-gate 	default:
12037c478bd9Sstevel@tonic-gate 		out(O_ERR, "call: arglist2argv: node type %s is unsupported",
12047c478bd9Sstevel@tonic-gate 		    ptree_nodetype2str(np->t));
12057c478bd9Sstevel@tonic-gate 		return (1);
12067c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
12077c478bd9Sstevel@tonic-gate 		break;
12087c478bd9Sstevel@tonic-gate 	}
12097c478bd9Sstevel@tonic-gate 
12107c478bd9Sstevel@tonic-gate 	if (*argc == 0 && addthisarg != NULL) {
12117c478bd9Sstevel@tonic-gate 		/*
12127c478bd9Sstevel@tonic-gate 		 * first argument added is the command name.
12137c478bd9Sstevel@tonic-gate 		 */
12147c478bd9Sstevel@tonic-gate 		char **files;
12157c478bd9Sstevel@tonic-gate 
12163e8d8e18Sdb35262 		files = platform_get_files_stddirs(addthisarg, 0);
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 		/* do not proceed if number of files found != 1 */
12197c478bd9Sstevel@tonic-gate 		if (files[0] == NULL)
12207c478bd9Sstevel@tonic-gate 			out(O_DIE, "call: function %s not found", addthisarg);
12217c478bd9Sstevel@tonic-gate 		if (files[1] != NULL)
12227c478bd9Sstevel@tonic-gate 			out(O_DIE, "call: multiple functions %s found",
12237c478bd9Sstevel@tonic-gate 			    addthisarg);
12247c478bd9Sstevel@tonic-gate 		FREE(addthisarg);
12257c478bd9Sstevel@tonic-gate 
12267c478bd9Sstevel@tonic-gate 		addthisarg = STRDUP(files[0]);
12277c478bd9Sstevel@tonic-gate 		FREE(files[0]);
12287c478bd9Sstevel@tonic-gate 		FREE(files);
12297c478bd9Sstevel@tonic-gate 	}
12307c478bd9Sstevel@tonic-gate 
12317c478bd9Sstevel@tonic-gate 	if (addthisarg != NULL) {
12327c478bd9Sstevel@tonic-gate 		if (*argc >= *argvlen - 2) {
12337c478bd9Sstevel@tonic-gate 			/*
12347c478bd9Sstevel@tonic-gate 			 * make sure argv is long enough so it has a
12357c478bd9Sstevel@tonic-gate 			 * terminating element set to NULL
12367c478bd9Sstevel@tonic-gate 			 */
12377c478bd9Sstevel@tonic-gate 			*argvlen += 10;
12387c478bd9Sstevel@tonic-gate 			*argv = (char **)REALLOC(*argv,
12397c478bd9Sstevel@tonic-gate 			    sizeof (char *) * *argvlen);
12407c478bd9Sstevel@tonic-gate 		}
12417c478bd9Sstevel@tonic-gate 		(*argv)[*argc] = addthisarg;
12427c478bd9Sstevel@tonic-gate 		(*argc)++;
12437c478bd9Sstevel@tonic-gate 		(*argv)[*argc] = NULL;
12447c478bd9Sstevel@tonic-gate 	}
12457c478bd9Sstevel@tonic-gate 
12467c478bd9Sstevel@tonic-gate 	return (0);
12477c478bd9Sstevel@tonic-gate }
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate static int
12507c478bd9Sstevel@tonic-gate generate_envp(struct arrow *arrowp, char ***envp, int *envc, int *envplen)
12517c478bd9Sstevel@tonic-gate {
12527c478bd9Sstevel@tonic-gate 	char *envnames[] = { "EFT_FROM_EVENT", "EFT_TO_EVENT",
12537c478bd9Sstevel@tonic-gate 			    "EFT_FILE", "EFT_LINE", NULL };
12547c478bd9Sstevel@tonic-gate 	char *envvalues[4];
12557c478bd9Sstevel@tonic-gate 	char *none = "(none)";
12567c478bd9Sstevel@tonic-gate 	size_t elen;
12577c478bd9Sstevel@tonic-gate 	int i;
12587c478bd9Sstevel@tonic-gate 
12597c478bd9Sstevel@tonic-gate 	*envc = 4;
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate 	/*
12627c478bd9Sstevel@tonic-gate 	 * make sure envp is long enough so it has a terminating element
12637c478bd9Sstevel@tonic-gate 	 * set to NULL
12647c478bd9Sstevel@tonic-gate 	 */
12657c478bd9Sstevel@tonic-gate 	*envplen = *envc + 1;
12667c478bd9Sstevel@tonic-gate 	*envp = (char **)MALLOC(sizeof (char *) * *envplen);
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate 	envvalues[0] = ipath2str(
12697c478bd9Sstevel@tonic-gate 	    arrowp->tail->myevent->enode->u.event.ename->u.name.s,
12707c478bd9Sstevel@tonic-gate 	    arrowp->tail->myevent->ipp);
12717c478bd9Sstevel@tonic-gate 	envvalues[1] = ipath2str(
12727c478bd9Sstevel@tonic-gate 	    arrowp->head->myevent->enode->u.event.ename->u.name.s,
12737c478bd9Sstevel@tonic-gate 	    arrowp->head->myevent->ipp);
12747c478bd9Sstevel@tonic-gate 
12757c478bd9Sstevel@tonic-gate 	if (arrowp->head->myevent->enode->file == NULL) {
12767c478bd9Sstevel@tonic-gate 		envvalues[2] = STRDUP(none);
12777c478bd9Sstevel@tonic-gate 		envvalues[3] = STRDUP(none);
12787c478bd9Sstevel@tonic-gate 	} else {
12797c478bd9Sstevel@tonic-gate 		envvalues[2] = STRDUP(arrowp->head->myevent->enode->file);
12807c478bd9Sstevel@tonic-gate 
12817c478bd9Sstevel@tonic-gate 		/* large enough for max int */
12827c478bd9Sstevel@tonic-gate 		envvalues[3] = MALLOC(sizeof (char) * 25);
12837c478bd9Sstevel@tonic-gate 		(void) snprintf(envvalues[3], sizeof (envvalues[3]), "%d",
12847c478bd9Sstevel@tonic-gate 		    arrowp->head->myevent->enode->line);
12857c478bd9Sstevel@tonic-gate 	}
12867c478bd9Sstevel@tonic-gate 
12877c478bd9Sstevel@tonic-gate 	for (i = 0; envnames[i] != NULL && i < *envc; i++) {
12887c478bd9Sstevel@tonic-gate 		elen = strlen(envnames[i]) + strlen(envvalues[i]) + 2;
12897c478bd9Sstevel@tonic-gate 		(*envp)[i] = MALLOC(elen);
12907c478bd9Sstevel@tonic-gate 		(void) snprintf((*envp)[i], elen, "%s=%s",
12917c478bd9Sstevel@tonic-gate 		    envnames[i], envvalues[i]);
12927c478bd9Sstevel@tonic-gate 		FREE(envvalues[i]);
12937c478bd9Sstevel@tonic-gate 	}
12947c478bd9Sstevel@tonic-gate 	(*envp)[*envc] = NULL;
12957c478bd9Sstevel@tonic-gate 
12967c478bd9Sstevel@tonic-gate 	return (0);
12977c478bd9Sstevel@tonic-gate }
12987c478bd9Sstevel@tonic-gate 
12997c478bd9Sstevel@tonic-gate /*
13007c478bd9Sstevel@tonic-gate  * platform_call -- call an external function
13017c478bd9Sstevel@tonic-gate  *
13027c478bd9Sstevel@tonic-gate  * evaluate a user-defined function and place result in valuep.  return 0
13037c478bd9Sstevel@tonic-gate  * if function evaluation was successful; 1 if otherwise.
13047c478bd9Sstevel@tonic-gate  */
13057c478bd9Sstevel@tonic-gate int
13067c478bd9Sstevel@tonic-gate platform_call(struct node *np, struct lut **globals, struct config *croot,
13077c478bd9Sstevel@tonic-gate 	struct arrow *arrowp, struct evalue *valuep)
13087c478bd9Sstevel@tonic-gate {
13097c478bd9Sstevel@tonic-gate 	/*
13107c478bd9Sstevel@tonic-gate 	 * use rather short buffers.  only the first string on outbuf[] is
13117c478bd9Sstevel@tonic-gate 	 * taken as output from the called function.  any message in
13127c478bd9Sstevel@tonic-gate 	 * errbuf[] is echoed out as an error message.
13137c478bd9Sstevel@tonic-gate 	 */
13147c478bd9Sstevel@tonic-gate 	char outbuf[256], errbuf[512];
13153e8d8e18Sdb35262 	struct stat buf;
13167c478bd9Sstevel@tonic-gate 	char **argv, **envp;
13177c478bd9Sstevel@tonic-gate 	int argc, argvlen, envc, envplen;
13187c478bd9Sstevel@tonic-gate 	int i, ret;
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate 	/*
13217c478bd9Sstevel@tonic-gate 	 * np is the argument list.  the user-defined function is the first
13227c478bd9Sstevel@tonic-gate 	 * element of the list.
13237c478bd9Sstevel@tonic-gate 	 */
13247c478bd9Sstevel@tonic-gate 	ASSERT(np->t == T_LIST);
13257c478bd9Sstevel@tonic-gate 
13267c478bd9Sstevel@tonic-gate 	argv = NULL;
13277c478bd9Sstevel@tonic-gate 	argc = 0;
13287c478bd9Sstevel@tonic-gate 	argvlen = 0;
13297c478bd9Sstevel@tonic-gate 	if (arglist2argv(np, globals, croot, arrowp, &argv, &argc, &argvlen) ||
13307c478bd9Sstevel@tonic-gate 	    argc == 0)
13317c478bd9Sstevel@tonic-gate 		return (1);
13327c478bd9Sstevel@tonic-gate 
13333e8d8e18Sdb35262 	/*
13343e8d8e18Sdb35262 	 * make sure program has executable bit set
13353e8d8e18Sdb35262 	 */
13363e8d8e18Sdb35262 	if (stat(argv[0], &buf) == 0) {
13373e8d8e18Sdb35262 		int exec_bit_set = 0;
13383e8d8e18Sdb35262 
13393e8d8e18Sdb35262 		if (buf.st_uid == geteuid() && buf.st_mode & S_IXUSR)
13403e8d8e18Sdb35262 			exec_bit_set = 1;
13413e8d8e18Sdb35262 		else if (buf.st_gid == getegid() && buf.st_mode & S_IXGRP)
13423e8d8e18Sdb35262 			exec_bit_set = 1;
13433e8d8e18Sdb35262 		else if (buf.st_mode & S_IXOTH)
13443e8d8e18Sdb35262 			exec_bit_set = 1;
13453e8d8e18Sdb35262 
13463e8d8e18Sdb35262 		if (exec_bit_set == 0)
13473e8d8e18Sdb35262 			out(O_DIE, "call: executable bit not set on %s",
13483e8d8e18Sdb35262 			    argv[0]);
13493e8d8e18Sdb35262 	} else {
13503e8d8e18Sdb35262 		out(O_DIE, "call: failure in stat(), errno = %d\n", errno);
13513e8d8e18Sdb35262 	}
13523e8d8e18Sdb35262 
13537c478bd9Sstevel@tonic-gate 	envp = NULL;
13547c478bd9Sstevel@tonic-gate 	envc = 0;
13557c478bd9Sstevel@tonic-gate 	envplen = 0;
13567c478bd9Sstevel@tonic-gate 	if (generate_envp(arrowp, &envp, &envc, &envplen))
13577c478bd9Sstevel@tonic-gate 		return (1);
13587c478bd9Sstevel@tonic-gate 
13597c478bd9Sstevel@tonic-gate 	outbuf[0] = '\0';
13607c478bd9Sstevel@tonic-gate 	errbuf[0] = '\0';
13617c478bd9Sstevel@tonic-gate 
13627c478bd9Sstevel@tonic-gate 	ret = forkandexecve((const char *) argv[0], (char *const *) argv,
13637c478bd9Sstevel@tonic-gate 	    (char *const *) envp, outbuf, sizeof (outbuf),
13647c478bd9Sstevel@tonic-gate 	    errbuf, sizeof (errbuf));
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 	for (i = 0; i < envc; i++)
13677c478bd9Sstevel@tonic-gate 		FREE(envp[i]);
13687c478bd9Sstevel@tonic-gate 	if (envp)
13697c478bd9Sstevel@tonic-gate 		FREE(envp);
13707c478bd9Sstevel@tonic-gate 
13717c478bd9Sstevel@tonic-gate 	if (ret) {
13727c478bd9Sstevel@tonic-gate 		outfl(O_OK, np->file, np->line,
13737c478bd9Sstevel@tonic-gate 		    "call: failure in fork + exec of %s", argv[0]);
13747c478bd9Sstevel@tonic-gate 	} else {
13757aec1d6eScindi 		char *ptr;
13767aec1d6eScindi 
13777aec1d6eScindi 		/* chomp the result */
13787aec1d6eScindi 		for (ptr = outbuf; *ptr; ptr++)
13797aec1d6eScindi 			if (*ptr == '\n' || *ptr == '\r') {
13807aec1d6eScindi 				*ptr = '\0';
13817aec1d6eScindi 				break;
13827aec1d6eScindi 			}
13837aec1d6eScindi 		valuep->t = STRING;
138480ab886dSwesolows 		valuep->v = (uintptr_t)stable(outbuf);
13857c478bd9Sstevel@tonic-gate 	}
13867c478bd9Sstevel@tonic-gate 
13877c478bd9Sstevel@tonic-gate 	if (errbuf[0] != '\0') {
13887c478bd9Sstevel@tonic-gate 		ret = 1;
13897c478bd9Sstevel@tonic-gate 		outfl(O_OK, np->file, np->line,
13907c478bd9Sstevel@tonic-gate 		    "call: unexpected stderr output from %s: %s",
13917c478bd9Sstevel@tonic-gate 		    argv[0], errbuf);
13927c478bd9Sstevel@tonic-gate 	}
13937c478bd9Sstevel@tonic-gate 
13947c478bd9Sstevel@tonic-gate 	for (i = 0; i < argc; i++)
13957c478bd9Sstevel@tonic-gate 		FREE(argv[i]);
13967c478bd9Sstevel@tonic-gate 	FREE(argv);
13977c478bd9Sstevel@tonic-gate 
13987c478bd9Sstevel@tonic-gate 	return (ret);
13997c478bd9Sstevel@tonic-gate }
14007c478bd9Sstevel@tonic-gate 
14017c478bd9Sstevel@tonic-gate /*
14027aec1d6eScindi  * platform_confcall -- call a configuration database function
14037aec1d6eScindi  *
14047aec1d6eScindi  * returns result in *valuep, return 0 on success
14057aec1d6eScindi  */
14067aec1d6eScindi /*ARGSUSED*/
14077aec1d6eScindi int
14087aec1d6eScindi platform_confcall(struct node *np, struct lut **globals, struct config *croot,
14097aec1d6eScindi 	struct arrow *arrowp, struct evalue *valuep)
14107aec1d6eScindi {
14117aec1d6eScindi 	nvlist_t *rsrc, *hcs;
14127aec1d6eScindi 	nvpair_t *nvp;
14137aec1d6eScindi 
14147aec1d6eScindi 	ASSERT(np != NULL);
14157aec1d6eScindi 
14167aec1d6eScindi 	/* assume we're returning true */
14177aec1d6eScindi 	valuep->t = UINT64;
14187aec1d6eScindi 	valuep->v = 1;
14197aec1d6eScindi 
14207aec1d6eScindi 	/*
14217aec1d6eScindi 	 * We've detected a well-formed confcall() to rewrite
14227aec1d6eScindi 	 * an ASRU in a fault.  We get here via lines like this
14237aec1d6eScindi 	 * in the eversholt rules:
14247aec1d6eScindi 	 *
14257aec1d6eScindi 	 *	event fault.memory.page@dimm, FITrate=PAGE_FIT,
14267aec1d6eScindi 	 *		ASRU=dimm, message=0,
14277aec1d6eScindi 	 *		count=stat.page_fault@dimm,
14287aec1d6eScindi 	 *		action=confcall("rewrite-ASRU");
14297aec1d6eScindi 	 *
14307aec1d6eScindi 	 * So first rewrite the resource in the fault.  Any payload data
14317aec1d6eScindi 	 * following the FM_FMRI_HC_SPECIFIC member is used to expand the
14327aec1d6eScindi 	 * resource nvlist.  Next, use libtopo to compute the ASRU from
14337aec1d6eScindi 	 * from the new resource.
14347aec1d6eScindi 	 */
14357aec1d6eScindi 	if (np->t == T_QUOTE && np->u.quote.s == stable("rewrite-ASRU")) {
14367aec1d6eScindi 		int err;
14377aec1d6eScindi 		nvlist_t *asru;
14387aec1d6eScindi 
14397aec1d6eScindi 		out(O_ALTFP|O_VERB, "platform_confcall: rewrite-ASRU");
14407aec1d6eScindi 
14417aec1d6eScindi 		if (nvlist_lookup_nvlist(Action_nvl, FM_FAULT_RESOURCE, &rsrc)
14427aec1d6eScindi 		    != 0) {
14437aec1d6eScindi 			outfl(O_ALTFP|O_VERB, np->file, np->line, "no resource "
14447aec1d6eScindi 			    "in fault event");
14457aec1d6eScindi 			return (0);
14467aec1d6eScindi 		}
14477aec1d6eScindi 
14487aec1d6eScindi 		if (topo_hdl_nvalloc(Eft_topo_hdl, &hcs, NV_UNIQUE_NAME) != 0) {
14497aec1d6eScindi 			outfl(O_ALTFP|O_VERB, np->file, np->line,
14507aec1d6eScindi 			    "unable to allocate nvlist for resource rewrite");
14517aec1d6eScindi 			return (0);
14527aec1d6eScindi 		}
14537aec1d6eScindi 
14547aec1d6eScindi 		/*
14558a40a695Sgavinm 		 * Loop until we run across asru-specific payload.  All
14568a40a695Sgavinm 		 * payload members prefixed "asru-" will be added to the
14578a40a695Sgavinm 		 * hc-specific nvlist and removed from the original.
14587aec1d6eScindi 		 */
14598a40a695Sgavinm 		nvp = nvlist_next_nvpair(Action_nvl, NULL);
14608a40a695Sgavinm 		while (nvp != NULL) {
14618a40a695Sgavinm 			if (strncmp(nvpair_name(nvp), "asru-", 5) == 0) {
14628a40a695Sgavinm 				if (nvlist_add_nvpair(hcs, nvp) != 0) {
14638a40a695Sgavinm 					nvlist_free(hcs);
14648a40a695Sgavinm 					outfl(O_ALTFP|O_VERB, np->file,
14658a40a695Sgavinm 					    np->line, "unable to rewrite "
14668a40a695Sgavinm 					    "resource - nvlist_add_nvpair for "
14678a40a695Sgavinm 					    "'%s' failed", nvpair_name(nvp));
14688a40a695Sgavinm 					return (0);
14697aec1d6eScindi 				}
14707aec1d6eScindi 
14718a40a695Sgavinm 				(void) nvlist_remove(Action_nvl,
14728a40a695Sgavinm 				    nvpair_name(nvp), nvpair_type(nvp));
14738a40a695Sgavinm 				nvp = nvlist_next_nvpair(Action_nvl, NULL);
14748a40a695Sgavinm 			} else {
14758a40a695Sgavinm 				nvp = nvlist_next_nvpair(Action_nvl, nvp);
14767aec1d6eScindi 			}
14777aec1d6eScindi 		}
14787aec1d6eScindi 
14797aec1d6eScindi 		if (nvlist_add_nvlist(rsrc, FM_FMRI_HC_SPECIFIC, hcs) != 0) {
14807aec1d6eScindi 			nvlist_free(hcs);
14817aec1d6eScindi 			outfl(O_ALTFP|O_VERB, np->file, np->line, "unable to "
14827aec1d6eScindi 			    "rewrite resource with HC specific data");
14837aec1d6eScindi 			return (0);
14847aec1d6eScindi 		}
14857aec1d6eScindi 		nvlist_free(hcs);
14867aec1d6eScindi 
14877aec1d6eScindi 		if (topo_fmri_asru(Eft_topo_hdl, rsrc, &asru, &err) != 0) {
14887aec1d6eScindi 			outfl(O_ALTFP|O_VERB, np->file, np->line, "unable to "
14897aec1d6eScindi 			    "rewrite asru: %s", topo_strerror(err));
14907aec1d6eScindi 			return (0);
14917aec1d6eScindi 		}
14927aec1d6eScindi 
14937aec1d6eScindi 		if (nvlist_remove(Action_nvl, FM_FAULT_ASRU, DATA_TYPE_NVLIST)
14947aec1d6eScindi 		    != 0) {
14957aec1d6eScindi 			nvlist_free(asru);
14967aec1d6eScindi 			outfl(O_ALTFP|O_VERB, np->file, np->line,
14977aec1d6eScindi 			    "failed to remove old asru during rewrite");
14987aec1d6eScindi 			return (0);
14997aec1d6eScindi 		}
15007aec1d6eScindi 		if (nvlist_add_nvlist(Action_nvl, FM_FAULT_ASRU, asru) != 0) {
15017aec1d6eScindi 			nvlist_free(asru);
15027aec1d6eScindi 			outfl(O_ALTFP|O_VERB, np->file, np->line,
15037aec1d6eScindi 			    "unable to add re-written asru");
15047aec1d6eScindi 			return (0);
15057aec1d6eScindi 		}
15067aec1d6eScindi 		nvlist_free(asru);
15077aec1d6eScindi 	} else {
15087aec1d6eScindi 		outfl(O_ALTFP|O_VERB, np->file, np->line, "unknown confcall");
15097aec1d6eScindi 	}
15107aec1d6eScindi 
15117aec1d6eScindi 	return (0);
15127aec1d6eScindi }
15137aec1d6eScindi 
15147aec1d6eScindi /*
15157c478bd9Sstevel@tonic-gate  * platform_get_eft_files -- return names of all eft files we should load
15167c478bd9Sstevel@tonic-gate  *
15177c478bd9Sstevel@tonic-gate  * this routine doesn't return NULL, even if no files are found (in that
15187c478bd9Sstevel@tonic-gate  * case, a char ** is returned with the first element NULL).
15197c478bd9Sstevel@tonic-gate  */
15207c478bd9Sstevel@tonic-gate char **
15217c478bd9Sstevel@tonic-gate platform_get_eft_files(void)
15227c478bd9Sstevel@tonic-gate {
15233e8d8e18Sdb35262 	return (platform_get_files_stddirs(".eft", 1));
15247c478bd9Sstevel@tonic-gate }
15257c478bd9Sstevel@tonic-gate 
15267c478bd9Sstevel@tonic-gate void
15277c478bd9Sstevel@tonic-gate platform_free_eft_files(char **flist)
15287c478bd9Sstevel@tonic-gate {
15297c478bd9Sstevel@tonic-gate 	char **f;
15307c478bd9Sstevel@tonic-gate 
15317c478bd9Sstevel@tonic-gate 	if (flist == NULL || *flist == NULL)
15327c478bd9Sstevel@tonic-gate 		return;	/* no files were found so we're done */
15337c478bd9Sstevel@tonic-gate 
15347c478bd9Sstevel@tonic-gate 	f = flist;
15357c478bd9Sstevel@tonic-gate 	while (*f != NULL) {
15367c478bd9Sstevel@tonic-gate 		FREE(*f);
15377c478bd9Sstevel@tonic-gate 		f++;
15387c478bd9Sstevel@tonic-gate 	}
15397c478bd9Sstevel@tonic-gate 	FREE(flist);
15407c478bd9Sstevel@tonic-gate }
15417c478bd9Sstevel@tonic-gate 
15427c478bd9Sstevel@tonic-gate static nvlist_t *payloadnvp = NULL;
15437c478bd9Sstevel@tonic-gate 
15447c478bd9Sstevel@tonic-gate void
15457c478bd9Sstevel@tonic-gate platform_set_payloadnvp(nvlist_t *nvlp)
15467c478bd9Sstevel@tonic-gate {
15477c478bd9Sstevel@tonic-gate 	/*
15487c478bd9Sstevel@tonic-gate 	 * cannot replace a non-NULL payloadnvp with a non-NULL nvlp
15497c478bd9Sstevel@tonic-gate 	 */
15507c478bd9Sstevel@tonic-gate 	ASSERT(payloadnvp != NULL ? nvlp == NULL : 1);
15517c478bd9Sstevel@tonic-gate 	payloadnvp = nvlp;
15527c478bd9Sstevel@tonic-gate }
15537c478bd9Sstevel@tonic-gate 
15547c478bd9Sstevel@tonic-gate /*
15557c478bd9Sstevel@tonic-gate  * given array notation in inputstr such as "foo[1]" or "foo [ 1 ]" (spaces
15567c478bd9Sstevel@tonic-gate  * allowed), figure out the array name and index.  return 0 if successful,
15577c478bd9Sstevel@tonic-gate  * nonzero if otherwise.
15587c478bd9Sstevel@tonic-gate  */
15597c478bd9Sstevel@tonic-gate static int
15607c478bd9Sstevel@tonic-gate get_array_info(const char *inputstr, const char **name, unsigned int *index)
15617c478bd9Sstevel@tonic-gate {
15627c478bd9Sstevel@tonic-gate 	char *indexptr, *indexend, *dupname, *endname;
15637c478bd9Sstevel@tonic-gate 
15647c478bd9Sstevel@tonic-gate 	if (strchr(inputstr, '[') == NULL)
15657c478bd9Sstevel@tonic-gate 		return (1);
15667c478bd9Sstevel@tonic-gate 
15677c478bd9Sstevel@tonic-gate 	dupname = STRDUP(inputstr);
15687c478bd9Sstevel@tonic-gate 	indexptr = strchr(dupname, '[');
15697c478bd9Sstevel@tonic-gate 	indexend = strchr(dupname, ']');
15707c478bd9Sstevel@tonic-gate 
15717c478bd9Sstevel@tonic-gate 	/*
15727c478bd9Sstevel@tonic-gate 	 * return if array notation is not complete or if index is negative
15737c478bd9Sstevel@tonic-gate 	 */
15747c478bd9Sstevel@tonic-gate 	if (indexend == NULL || indexptr >= indexend ||
15757c478bd9Sstevel@tonic-gate 	    strchr(indexptr, '-') != NULL) {
15767c478bd9Sstevel@tonic-gate 		FREE(dupname);
15777c478bd9Sstevel@tonic-gate 		return (1);
15787c478bd9Sstevel@tonic-gate 	}
15797c478bd9Sstevel@tonic-gate 
15807c478bd9Sstevel@tonic-gate 	/*
15817c478bd9Sstevel@tonic-gate 	 * search past any spaces between the name string and '['
15827c478bd9Sstevel@tonic-gate 	 */
15837c478bd9Sstevel@tonic-gate 	endname = indexptr;
15847c478bd9Sstevel@tonic-gate 	while (isspace(*(endname - 1)) && dupname < endname)
15857c478bd9Sstevel@tonic-gate 		endname--;
15867c478bd9Sstevel@tonic-gate 	*endname = '\0';
15877c478bd9Sstevel@tonic-gate 	ASSERT(dupname < endname);
15887c478bd9Sstevel@tonic-gate 
15897c478bd9Sstevel@tonic-gate 	/*
15907c478bd9Sstevel@tonic-gate 	 * search until indexptr points to the first digit and indexend
15917c478bd9Sstevel@tonic-gate 	 * points to the last digit
15927c478bd9Sstevel@tonic-gate 	 */
15937c478bd9Sstevel@tonic-gate 	while (!isdigit(*indexptr) && indexptr < indexend)
15947c478bd9Sstevel@tonic-gate 		indexptr++;
15957c478bd9Sstevel@tonic-gate 	while (!isdigit(*indexend) && indexptr <= indexend)
15967c478bd9Sstevel@tonic-gate 		indexend--;
15977c478bd9Sstevel@tonic-gate 
15987c478bd9Sstevel@tonic-gate 	*(indexend + 1) = '\0';
15997c478bd9Sstevel@tonic-gate 	*index = (unsigned int)atoi(indexptr);
16007c478bd9Sstevel@tonic-gate 
16017c478bd9Sstevel@tonic-gate 	*name = stable(dupname);
16027c478bd9Sstevel@tonic-gate 	FREE(dupname);
16037c478bd9Sstevel@tonic-gate 
16047c478bd9Sstevel@tonic-gate 	return (0);
16057c478bd9Sstevel@tonic-gate }
16067c478bd9Sstevel@tonic-gate 
16077aec1d6eScindi /*
16087aec1d6eScindi  * platform_payloadprop -- fetch a payload value
16097aec1d6eScindi  *
16107aec1d6eScindi  * XXX this function should be replaced and eval_func() should be
16117aec1d6eScindi  * XXX changed to use the more general platform_payloadprop_values().
16127aec1d6eScindi  */
16137c478bd9Sstevel@tonic-gate int
16147c478bd9Sstevel@tonic-gate platform_payloadprop(struct node *np, struct evalue *valuep)
16157c478bd9Sstevel@tonic-gate {
16163e8d8e18Sdb35262 	nvlist_t *basenvp;
16177aec1d6eScindi 	nvlist_t *embnvp = NULL;
16187c478bd9Sstevel@tonic-gate 	nvpair_t *nvpair;
16193e8d8e18Sdb35262 	const char *nameptr, *propstr, *lastnameptr;
16207c478bd9Sstevel@tonic-gate 	int not_array = 0;
16217c478bd9Sstevel@tonic-gate 	unsigned int index = 0;
16227c478bd9Sstevel@tonic-gate 	uint_t nelem;
16233e8d8e18Sdb35262 	char *nvpname, *nameslist = NULL;
16247aec1d6eScindi 	char *scheme = NULL;
16257c478bd9Sstevel@tonic-gate 
16267c478bd9Sstevel@tonic-gate 	ASSERT(np->t == T_QUOTE);
16277c478bd9Sstevel@tonic-gate 
16283e8d8e18Sdb35262 	propstr = np->u.quote.s;
16297c478bd9Sstevel@tonic-gate 	if (payloadnvp == NULL) {
16308a40a695Sgavinm 		out(O_ALTFP | O_VERB2, "platform_payloadprop: no nvp for %s",
16313e8d8e18Sdb35262 		    propstr);
16323e8d8e18Sdb35262 		return (1);
16333e8d8e18Sdb35262 	}
16343e8d8e18Sdb35262 	basenvp = payloadnvp;
16353e8d8e18Sdb35262 
16363e8d8e18Sdb35262 	/*
16373e8d8e18Sdb35262 	 * first handle any embedded nvlists.  if propstr is "foo.bar[2]"
16383e8d8e18Sdb35262 	 * then lastnameptr should end up being "bar[2]" with basenvp set
16393e8d8e18Sdb35262 	 * to the nvlist for "foo".  (the search for "bar" within "foo"
16403e8d8e18Sdb35262 	 * will be done later.)
16413e8d8e18Sdb35262 	 */
16423e8d8e18Sdb35262 	if (strchr(propstr, '.') != NULL) {
16433e8d8e18Sdb35262 		nvlist_t **arraynvp;
16443e8d8e18Sdb35262 		uint_t nelem;
16453e8d8e18Sdb35262 		char *w;
16463e8d8e18Sdb35262 		int ier;
16473e8d8e18Sdb35262 
16483e8d8e18Sdb35262 		nameslist = STRDUP(propstr);
16493e8d8e18Sdb35262 		lastnameptr = strtok(nameslist, ".");
16503e8d8e18Sdb35262 
16513e8d8e18Sdb35262 		/*
16523e8d8e18Sdb35262 		 * decompose nameslist into its component names while
16533e8d8e18Sdb35262 		 * extracting the embedded nvlist
16543e8d8e18Sdb35262 		 */
16553e8d8e18Sdb35262 		while ((w = strtok(NULL, ".")) != NULL) {
16563e8d8e18Sdb35262 			if (get_array_info(lastnameptr, &nameptr, &index)) {
16573e8d8e18Sdb35262 				ier = nvlist_lookup_nvlist(basenvp,
16583e8d8e18Sdb35262 				    lastnameptr, &basenvp);
16593e8d8e18Sdb35262 			} else {
16603e8d8e18Sdb35262 				/* handle array of nvlists */
16613e8d8e18Sdb35262 				ier = nvlist_lookup_nvlist_array(basenvp,
16623e8d8e18Sdb35262 				    nameptr, &arraynvp, &nelem);
16633e8d8e18Sdb35262 				if (ier == 0) {
16643e8d8e18Sdb35262 					if ((uint_t)index > nelem - 1)
16653e8d8e18Sdb35262 						ier = 1;
16663e8d8e18Sdb35262 					else
16673e8d8e18Sdb35262 						basenvp = arraynvp[index];
16683e8d8e18Sdb35262 				}
16693e8d8e18Sdb35262 			}
16703e8d8e18Sdb35262 
16713e8d8e18Sdb35262 			if (ier) {
16723e8d8e18Sdb35262 				out(O_ALTFP, "platform_payloadprop: "
16733e8d8e18Sdb35262 				    " invalid list for %s (in %s)",
16743e8d8e18Sdb35262 				    lastnameptr, propstr);
16753e8d8e18Sdb35262 				FREE(nameslist);
16767c478bd9Sstevel@tonic-gate 				return (1);
16777c478bd9Sstevel@tonic-gate 			}
16787c478bd9Sstevel@tonic-gate 
16793e8d8e18Sdb35262 			lastnameptr = w;
16803e8d8e18Sdb35262 		}
16813e8d8e18Sdb35262 	} else {
16823e8d8e18Sdb35262 		lastnameptr = propstr;
16833e8d8e18Sdb35262 	}
16843e8d8e18Sdb35262 
16853e8d8e18Sdb35262 	/* if property is an array reference, extract array name and index */
16863e8d8e18Sdb35262 	not_array = get_array_info(lastnameptr, &nameptr, &index);
16873e8d8e18Sdb35262 	if (not_array)
16883e8d8e18Sdb35262 		nameptr = stable(lastnameptr);
16893e8d8e18Sdb35262 
16903e8d8e18Sdb35262 	if (nameslist != NULL)
16913e8d8e18Sdb35262 		FREE(nameslist);
16927c478bd9Sstevel@tonic-gate 
16937c478bd9Sstevel@tonic-gate 	/* search for nvpair entry */
16947c478bd9Sstevel@tonic-gate 	nvpair = NULL;
16953e8d8e18Sdb35262 	while ((nvpair = nvlist_next_nvpair(basenvp, nvpair)) != NULL) {
16967c478bd9Sstevel@tonic-gate 		nvpname = nvpair_name(nvpair);
16977c478bd9Sstevel@tonic-gate 		ASSERT(nvpname != NULL);
16987c478bd9Sstevel@tonic-gate 
16993e8d8e18Sdb35262 		if (nameptr == stable(nvpname))
17007c478bd9Sstevel@tonic-gate 			break;
17017c478bd9Sstevel@tonic-gate 	}
17027c478bd9Sstevel@tonic-gate 
17037c478bd9Sstevel@tonic-gate 	if (nvpair == NULL) {
17043e8d8e18Sdb35262 		out(O_ALTFP, "platform_payloadprop: no entry for %s", propstr);
17057c478bd9Sstevel@tonic-gate 		return (1);
17067aec1d6eScindi 	} else if (valuep == NULL) {
17077aec1d6eScindi 		/*
17087aec1d6eScindi 		 * caller is interested in the existence of a property with
17097aec1d6eScindi 		 * this name, regardless of type or value
17107aec1d6eScindi 		 */
17117aec1d6eScindi 		return (0);
17127c478bd9Sstevel@tonic-gate 	}
17137c478bd9Sstevel@tonic-gate 
17147aec1d6eScindi 	valuep->t = UNDEFINED;
17157aec1d6eScindi 
17167c478bd9Sstevel@tonic-gate 	/*
17177c478bd9Sstevel@tonic-gate 	 * get to this point if we found an entry.  figure out its data
17187c478bd9Sstevel@tonic-gate 	 * type and copy its value.
17197c478bd9Sstevel@tonic-gate 	 */
17207aec1d6eScindi 	(void) nvpair_value_nvlist(nvpair, &embnvp);
17217aec1d6eScindi 	if (nvlist_lookup_string(embnvp, FM_FMRI_SCHEME, &scheme) == 0) {
17227aec1d6eScindi 		if (strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
17237aec1d6eScindi 			valuep->t = NODEPTR;
172480ab886dSwesolows 			valuep->v = (uintptr_t)hc_fmri_nodeize(embnvp);
17257aec1d6eScindi 			return (0);
17267aec1d6eScindi 		}
17277aec1d6eScindi 	}
17287c478bd9Sstevel@tonic-gate 	switch (nvpair_type(nvpair)) {
17297c478bd9Sstevel@tonic-gate 	case DATA_TYPE_BOOLEAN:
17307c478bd9Sstevel@tonic-gate 	case DATA_TYPE_BOOLEAN_VALUE: {
17317c478bd9Sstevel@tonic-gate 		boolean_t val;
17327c478bd9Sstevel@tonic-gate 		(void) nvpair_value_boolean_value(nvpair, &val);
17337c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17347c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
17357c478bd9Sstevel@tonic-gate 		break;
17367c478bd9Sstevel@tonic-gate 	}
17377c478bd9Sstevel@tonic-gate 	case DATA_TYPE_BYTE: {
17387c478bd9Sstevel@tonic-gate 		uchar_t val;
17397c478bd9Sstevel@tonic-gate 		(void) nvpair_value_byte(nvpair, &val);
17407c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17417c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
17427c478bd9Sstevel@tonic-gate 		break;
17437c478bd9Sstevel@tonic-gate 	}
17447c478bd9Sstevel@tonic-gate 	case DATA_TYPE_STRING: {
17457c478bd9Sstevel@tonic-gate 		char *val;
17467c478bd9Sstevel@tonic-gate 		valuep->t = STRING;
17477c478bd9Sstevel@tonic-gate 		(void) nvpair_value_string(nvpair, &val);
174880ab886dSwesolows 		valuep->v = (uintptr_t)stable(val);
17497c478bd9Sstevel@tonic-gate 		break;
17507c478bd9Sstevel@tonic-gate 	}
17517c478bd9Sstevel@tonic-gate 
17527c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT8: {
17537c478bd9Sstevel@tonic-gate 		int8_t val;
17547c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int8(nvpair, &val);
17557c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17567c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
17577c478bd9Sstevel@tonic-gate 		break;
17587c478bd9Sstevel@tonic-gate 	}
17597c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT8: {
17607c478bd9Sstevel@tonic-gate 		uint8_t val;
17617c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint8(nvpair, &val);
17627c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17637c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
17647c478bd9Sstevel@tonic-gate 		break;
17657c478bd9Sstevel@tonic-gate 	}
17667c478bd9Sstevel@tonic-gate 
17677c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT16: {
17687c478bd9Sstevel@tonic-gate 		int16_t val;
17697c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int16(nvpair, &val);
17707c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17717c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
17727c478bd9Sstevel@tonic-gate 		break;
17737c478bd9Sstevel@tonic-gate 	}
17747c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT16: {
17757c478bd9Sstevel@tonic-gate 		uint16_t val;
17767c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint16(nvpair, &val);
17777c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17787c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
17797c478bd9Sstevel@tonic-gate 		break;
17807c478bd9Sstevel@tonic-gate 	}
17817c478bd9Sstevel@tonic-gate 
17827c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT32: {
17837c478bd9Sstevel@tonic-gate 		int32_t val;
17847c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int32(nvpair, &val);
17857c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17867c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
17877c478bd9Sstevel@tonic-gate 		break;
17887c478bd9Sstevel@tonic-gate 	}
17897c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT32: {
17907c478bd9Sstevel@tonic-gate 		uint32_t val;
17917c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint32(nvpair, &val);
17927c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17937c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
17947c478bd9Sstevel@tonic-gate 		break;
17957c478bd9Sstevel@tonic-gate 	}
17967c478bd9Sstevel@tonic-gate 
17977c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT64: {
17987c478bd9Sstevel@tonic-gate 		int64_t val;
17997c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int64(nvpair, &val);
18007c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
18017c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
18027c478bd9Sstevel@tonic-gate 		break;
18037c478bd9Sstevel@tonic-gate 	}
18047c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT64: {
18057c478bd9Sstevel@tonic-gate 		uint64_t val;
18067c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint64(nvpair, &val);
18077c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
18087c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
18097c478bd9Sstevel@tonic-gate 		break;
18107c478bd9Sstevel@tonic-gate 	}
18117c478bd9Sstevel@tonic-gate 
18127c478bd9Sstevel@tonic-gate 	case DATA_TYPE_BOOLEAN_ARRAY: {
18137c478bd9Sstevel@tonic-gate 		boolean_t *val;
18147c478bd9Sstevel@tonic-gate 		(void) nvpair_value_boolean_array(nvpair, &val, &nelem);
18157c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
18167c478bd9Sstevel@tonic-gate 			goto invalid;
18177c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
18187c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
18197c478bd9Sstevel@tonic-gate 		break;
18207c478bd9Sstevel@tonic-gate 	}
18217c478bd9Sstevel@tonic-gate 	case DATA_TYPE_BYTE_ARRAY: {
18227c478bd9Sstevel@tonic-gate 		uchar_t *val;
18237c478bd9Sstevel@tonic-gate 		(void) nvpair_value_byte_array(nvpair, &val, &nelem);
18247c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
18257c478bd9Sstevel@tonic-gate 			goto invalid;
18267c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
18277c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
18287c478bd9Sstevel@tonic-gate 		break;
18297c478bd9Sstevel@tonic-gate 	}
18307c478bd9Sstevel@tonic-gate 	case DATA_TYPE_STRING_ARRAY: {
18317c478bd9Sstevel@tonic-gate 		char **val;
18327c478bd9Sstevel@tonic-gate 		(void) nvpair_value_string_array(nvpair, &val, &nelem);
18337c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
18347c478bd9Sstevel@tonic-gate 			goto invalid;
18357c478bd9Sstevel@tonic-gate 		valuep->t = STRING;
183680ab886dSwesolows 		valuep->v = (uintptr_t)stable(val[index]);
18377c478bd9Sstevel@tonic-gate 		break;
18387c478bd9Sstevel@tonic-gate 	}
18397c478bd9Sstevel@tonic-gate 
18407c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT8_ARRAY: {
18417c478bd9Sstevel@tonic-gate 		int8_t *val;
18427c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int8_array(nvpair, &val, &nelem);
18437c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
18447c478bd9Sstevel@tonic-gate 			goto invalid;
18457c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
18467c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
18477c478bd9Sstevel@tonic-gate 		break;
18487c478bd9Sstevel@tonic-gate 	}
18497c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT8_ARRAY: {
18507c478bd9Sstevel@tonic-gate 		uint8_t *val;
18517c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint8_array(nvpair, &val, &nelem);
18527c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
18537c478bd9Sstevel@tonic-gate 			goto invalid;
18547c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
18557c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
18567c478bd9Sstevel@tonic-gate 		break;
18577c478bd9Sstevel@tonic-gate 	}
18587c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT16_ARRAY: {
18597c478bd9Sstevel@tonic-gate 		int16_t *val;
18607c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int16_array(nvpair, &val, &nelem);
18617c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
18627c478bd9Sstevel@tonic-gate 			goto invalid;
18637c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
18647c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
18657c478bd9Sstevel@tonic-gate 		break;
18667c478bd9Sstevel@tonic-gate 	}
18677c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT16_ARRAY: {
18687c478bd9Sstevel@tonic-gate 		uint16_t *val;
18697c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint16_array(nvpair, &val, &nelem);
18707c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
18717c478bd9Sstevel@tonic-gate 			goto invalid;
18727c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
18737c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
18747c478bd9Sstevel@tonic-gate 		break;
18757c478bd9Sstevel@tonic-gate 	}
18767c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT32_ARRAY: {
18777c478bd9Sstevel@tonic-gate 		int32_t *val;
18787c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int32_array(nvpair, &val, &nelem);
18797c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
18807c478bd9Sstevel@tonic-gate 			goto invalid;
18817c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
18827c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
18837c478bd9Sstevel@tonic-gate 		break;
18847c478bd9Sstevel@tonic-gate 	}
18857c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT32_ARRAY: {
18867c478bd9Sstevel@tonic-gate 		uint32_t *val;
18877c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint32_array(nvpair, &val, &nelem);
18887c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
18897c478bd9Sstevel@tonic-gate 			goto invalid;
18907c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
18917c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
18927c478bd9Sstevel@tonic-gate 		break;
18937c478bd9Sstevel@tonic-gate 	}
18947c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT64_ARRAY: {
18957c478bd9Sstevel@tonic-gate 		int64_t *val;
18967c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int64_array(nvpair, &val, &nelem);
18977c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
18987c478bd9Sstevel@tonic-gate 			goto invalid;
18997c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
19007c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
19017c478bd9Sstevel@tonic-gate 		break;
19027c478bd9Sstevel@tonic-gate 	}
19037c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT64_ARRAY: {
19047c478bd9Sstevel@tonic-gate 		uint64_t *val;
19057c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint64_array(nvpair, &val, &nelem);
19067c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
19077c478bd9Sstevel@tonic-gate 			goto invalid;
19087c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
19097c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
19107c478bd9Sstevel@tonic-gate 		break;
19117c478bd9Sstevel@tonic-gate 	}
19127c478bd9Sstevel@tonic-gate 
19137c478bd9Sstevel@tonic-gate 	default :
19147aec1d6eScindi 		out(O_ALTFP|O_VERB2,
19157c478bd9Sstevel@tonic-gate 		    "platform_payloadprop: unsupported data type for %s",
19163e8d8e18Sdb35262 		    propstr);
19177c478bd9Sstevel@tonic-gate 		return (1);
19187c478bd9Sstevel@tonic-gate 	}
19197c478bd9Sstevel@tonic-gate 
19207c478bd9Sstevel@tonic-gate 	return (0);
19217c478bd9Sstevel@tonic-gate 
19227c478bd9Sstevel@tonic-gate invalid:
19237aec1d6eScindi 	out(O_ALTFP|O_VERB2,
19247aec1d6eScindi 	    "platform_payloadprop: invalid array reference for %s", propstr);
19257c478bd9Sstevel@tonic-gate 	return (1);
19267c478bd9Sstevel@tonic-gate }
19277aec1d6eScindi 
19287aec1d6eScindi /*ARGSUSED*/
19297aec1d6eScindi int
19307aec1d6eScindi platform_path_exists(nvlist_t *fmri)
19317aec1d6eScindi {
19327aec1d6eScindi 	return (fmd_nvl_fmri_present(Hdl, fmri));
19337aec1d6eScindi }
19347aec1d6eScindi 
19357aec1d6eScindi struct evalue *
19367aec1d6eScindi platform_payloadprop_values(const char *propstr, int *nvals)
19377aec1d6eScindi {
19387aec1d6eScindi 	struct evalue *retvals;
19397aec1d6eScindi 	nvlist_t *basenvp;
19407aec1d6eScindi 	nvpair_t *nvpair;
19417aec1d6eScindi 	char *nvpname;
19427aec1d6eScindi 
19437aec1d6eScindi 	*nvals = 0;
19447aec1d6eScindi 
19457aec1d6eScindi 	if (payloadnvp == NULL)
19467aec1d6eScindi 		return (NULL);
19477aec1d6eScindi 
19487aec1d6eScindi 	basenvp = payloadnvp;
19497aec1d6eScindi 
19507aec1d6eScindi 	/* search for nvpair entry */
19517aec1d6eScindi 	nvpair = NULL;
19527aec1d6eScindi 	while ((nvpair = nvlist_next_nvpair(basenvp, nvpair)) != NULL) {
19537aec1d6eScindi 		nvpname = nvpair_name(nvpair);
19547aec1d6eScindi 		ASSERT(nvpname != NULL);
19557aec1d6eScindi 
19567aec1d6eScindi 		if (strcmp(propstr, nvpname) == 0)
19577aec1d6eScindi 			break;
19587aec1d6eScindi 	}
19597aec1d6eScindi 
19607aec1d6eScindi 	if (nvpair == NULL)
19617aec1d6eScindi 		return (NULL);	/* property not found */
19627aec1d6eScindi 
19637aec1d6eScindi 	switch (nvpair_type(nvpair)) {
19647aec1d6eScindi 	case DATA_TYPE_NVLIST: {
19657aec1d6eScindi 		nvlist_t *embnvp = NULL;
19667aec1d6eScindi 		char *scheme = NULL;
19677aec1d6eScindi 
19687aec1d6eScindi 		(void) nvpair_value_nvlist(nvpair, &embnvp);
19697aec1d6eScindi 		if (nvlist_lookup_string(embnvp, FM_FMRI_SCHEME,
19707aec1d6eScindi 		    &scheme) == 0) {
19717aec1d6eScindi 			if (strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
19727aec1d6eScindi 				*nvals = 1;
19737aec1d6eScindi 				retvals = MALLOC(sizeof (struct evalue));
19747aec1d6eScindi 				retvals->t = NODEPTR;
19757aec1d6eScindi 				retvals->v =
197680ab886dSwesolows 				    (uintptr_t)hc_fmri_nodeize(embnvp);
19777aec1d6eScindi 				return (retvals);
19787aec1d6eScindi 			}
19797aec1d6eScindi 		}
19807aec1d6eScindi 		return (NULL);
19817aec1d6eScindi 	}
19827aec1d6eScindi 	case DATA_TYPE_NVLIST_ARRAY: {
19837aec1d6eScindi 		char *scheme = NULL;
19847aec1d6eScindi 		nvlist_t **nvap;
19857aec1d6eScindi 		uint_t nel;
19867aec1d6eScindi 		int i;
19877aec1d6eScindi 		int hccount;
19887aec1d6eScindi 
19897aec1d6eScindi 		/*
19907aec1d6eScindi 		 * since we're only willing to handle hc fmri's, we
19917aec1d6eScindi 		 * must count them first before allocating retvals.
19927aec1d6eScindi 		 */
19937aec1d6eScindi 		if (nvpair_value_nvlist_array(nvpair, &nvap, &nel) != 0)
19947aec1d6eScindi 			return (NULL);
19957aec1d6eScindi 
19967aec1d6eScindi 		hccount = 0;
19977aec1d6eScindi 		for (i = 0; i < nel; i++) {
19987aec1d6eScindi 			if (nvlist_lookup_string(nvap[i], FM_FMRI_SCHEME,
19997aec1d6eScindi 			    &scheme) == 0 &&
20007aec1d6eScindi 			    strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
20017aec1d6eScindi 				hccount++;
20027aec1d6eScindi 			}
20037aec1d6eScindi 		}
20047aec1d6eScindi 
20057aec1d6eScindi 		if (hccount == 0)
20067aec1d6eScindi 			return (NULL);
20077aec1d6eScindi 
20087aec1d6eScindi 		*nvals = hccount;
20097aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * hccount);
20107aec1d6eScindi 
20117aec1d6eScindi 		hccount = 0;
20127aec1d6eScindi 		for (i = 0; i < nel; i++) {
20137aec1d6eScindi 			if (nvlist_lookup_string(nvap[i], FM_FMRI_SCHEME,
20147aec1d6eScindi 			    &scheme) == 0 &&
20157aec1d6eScindi 			    strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
20167aec1d6eScindi 				retvals[hccount].t = NODEPTR;
201780ab886dSwesolows 				retvals[hccount].v = (uintptr_t)
20187aec1d6eScindi 				    hc_fmri_nodeize(nvap[i]);
20197aec1d6eScindi 				hccount++;
20207aec1d6eScindi 			}
20217aec1d6eScindi 		}
20227aec1d6eScindi 		return (retvals);
20237aec1d6eScindi 	}
20247aec1d6eScindi 	case DATA_TYPE_BOOLEAN:
20257aec1d6eScindi 	case DATA_TYPE_BOOLEAN_VALUE: {
20267aec1d6eScindi 		boolean_t val;
20277aec1d6eScindi 
20287aec1d6eScindi 		*nvals = 1;
20297aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
20307aec1d6eScindi 		(void) nvpair_value_boolean_value(nvpair, &val);
20317aec1d6eScindi 		retvals->t = UINT64;
20327aec1d6eScindi 		retvals->v = (unsigned long long)val;
20337aec1d6eScindi 		return (retvals);
20347aec1d6eScindi 	}
20357aec1d6eScindi 	case DATA_TYPE_BYTE: {
20367aec1d6eScindi 		uchar_t val;
20377aec1d6eScindi 
20387aec1d6eScindi 		*nvals = 1;
20397aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
20407aec1d6eScindi 		(void) nvpair_value_byte(nvpair, &val);
20417aec1d6eScindi 		retvals->t = UINT64;
20427aec1d6eScindi 		retvals->v = (unsigned long long)val;
20437aec1d6eScindi 		return (retvals);
20447aec1d6eScindi 	}
20457aec1d6eScindi 	case DATA_TYPE_STRING: {
20467aec1d6eScindi 		char *val;
20477aec1d6eScindi 
20487aec1d6eScindi 		*nvals = 1;
20497aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
20507aec1d6eScindi 		retvals->t = STRING;
20517aec1d6eScindi 		(void) nvpair_value_string(nvpair, &val);
205280ab886dSwesolows 		retvals->v = (uintptr_t)stable(val);
20537aec1d6eScindi 		return (retvals);
20547aec1d6eScindi 	}
20557aec1d6eScindi 
20567aec1d6eScindi 	case DATA_TYPE_INT8: {
20577aec1d6eScindi 		int8_t val;
20587aec1d6eScindi 
20597aec1d6eScindi 		*nvals = 1;
20607aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
20617aec1d6eScindi 		(void) nvpair_value_int8(nvpair, &val);
20627aec1d6eScindi 		retvals->t = UINT64;
20637aec1d6eScindi 		retvals->v = (unsigned long long)val;
20647aec1d6eScindi 		return (retvals);
20657aec1d6eScindi 	}
20667aec1d6eScindi 	case DATA_TYPE_UINT8: {
20677aec1d6eScindi 		uint8_t val;
20687aec1d6eScindi 
20697aec1d6eScindi 		*nvals = 1;
20707aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
20717aec1d6eScindi 		(void) nvpair_value_uint8(nvpair, &val);
20727aec1d6eScindi 		retvals->t = UINT64;
20737aec1d6eScindi 		retvals->v = (unsigned long long)val;
20747aec1d6eScindi 		return (retvals);
20757aec1d6eScindi 	}
20767aec1d6eScindi 
20777aec1d6eScindi 	case DATA_TYPE_INT16: {
20787aec1d6eScindi 		int16_t val;
20797aec1d6eScindi 
20807aec1d6eScindi 		*nvals = 1;
20817aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
20827aec1d6eScindi 		(void) nvpair_value_int16(nvpair, &val);
20837aec1d6eScindi 		retvals->t = UINT64;
20847aec1d6eScindi 		retvals->v = (unsigned long long)val;
20857aec1d6eScindi 		return (retvals);
20867aec1d6eScindi 	}
20877aec1d6eScindi 	case DATA_TYPE_UINT16: {
20887aec1d6eScindi 		uint16_t val;
20897aec1d6eScindi 
20907aec1d6eScindi 		*nvals = 1;
20917aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
20927aec1d6eScindi 		(void) nvpair_value_uint16(nvpair, &val);
20937aec1d6eScindi 		retvals->t = UINT64;
20947aec1d6eScindi 		retvals->v = (unsigned long long)val;
20957aec1d6eScindi 		return (retvals);
20967aec1d6eScindi 	}
20977aec1d6eScindi 
20987aec1d6eScindi 	case DATA_TYPE_INT32: {
20997aec1d6eScindi 		int32_t val;
21007aec1d6eScindi 
21017aec1d6eScindi 		*nvals = 1;
21027aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
21037aec1d6eScindi 		(void) nvpair_value_int32(nvpair, &val);
21047aec1d6eScindi 		retvals->t = UINT64;
21057aec1d6eScindi 		retvals->v = (unsigned long long)val;
21067aec1d6eScindi 		return (retvals);
21077aec1d6eScindi 	}
21087aec1d6eScindi 	case DATA_TYPE_UINT32: {
21097aec1d6eScindi 		uint32_t val;
21107aec1d6eScindi 
21117aec1d6eScindi 		*nvals = 1;
21127aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
21137aec1d6eScindi 		(void) nvpair_value_uint32(nvpair, &val);
21147aec1d6eScindi 		retvals->t = UINT64;
21157aec1d6eScindi 		retvals->v = (unsigned long long)val;
21167aec1d6eScindi 		return (retvals);
21177aec1d6eScindi 	}
21187aec1d6eScindi 
21197aec1d6eScindi 	case DATA_TYPE_INT64: {
21207aec1d6eScindi 		int64_t val;
21217aec1d6eScindi 
21227aec1d6eScindi 		*nvals = 1;
21237aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
21247aec1d6eScindi 		(void) nvpair_value_int64(nvpair, &val);
21257aec1d6eScindi 		retvals->t = UINT64;
21267aec1d6eScindi 		retvals->v = (unsigned long long)val;
21277aec1d6eScindi 		return (retvals);
21287aec1d6eScindi 	}
21297aec1d6eScindi 	case DATA_TYPE_UINT64: {
21307aec1d6eScindi 		uint64_t val;
21317aec1d6eScindi 
21327aec1d6eScindi 		*nvals = 1;
21337aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
21347aec1d6eScindi 		(void) nvpair_value_uint64(nvpair, &val);
21357aec1d6eScindi 		retvals->t = UINT64;
21367aec1d6eScindi 		retvals->v = (unsigned long long)val;
21377aec1d6eScindi 		return (retvals);
21387aec1d6eScindi 	}
21397aec1d6eScindi 
21407aec1d6eScindi 	case DATA_TYPE_BOOLEAN_ARRAY: {
21417aec1d6eScindi 		boolean_t *val;
21427aec1d6eScindi 		uint_t nel;
21437aec1d6eScindi 		int i;
21447aec1d6eScindi 
21457aec1d6eScindi 		(void) nvpair_value_boolean_array(nvpair, &val, &nel);
21467aec1d6eScindi 		*nvals = nel;
21477aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
21487aec1d6eScindi 		for (i = 0; i < nel; i++) {
21497aec1d6eScindi 			retvals[i].t = UINT64;
21507aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
21517aec1d6eScindi 		}
21527aec1d6eScindi 		return (retvals);
21537aec1d6eScindi 	}
21547aec1d6eScindi 	case DATA_TYPE_BYTE_ARRAY: {
21557aec1d6eScindi 		uchar_t *val;
21567aec1d6eScindi 		uint_t nel;
21577aec1d6eScindi 		int i;
21587aec1d6eScindi 
21597aec1d6eScindi 		(void) nvpair_value_byte_array(nvpair, &val, &nel);
21607aec1d6eScindi 		*nvals = nel;
21617aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
21627aec1d6eScindi 		for (i = 0; i < nel; i++) {
21637aec1d6eScindi 			retvals[i].t = UINT64;
21647aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
21657aec1d6eScindi 		}
21667aec1d6eScindi 		return (retvals);
21677aec1d6eScindi 	}
21687aec1d6eScindi 	case DATA_TYPE_STRING_ARRAY: {
21697aec1d6eScindi 		char **val;
21707aec1d6eScindi 		uint_t nel;
21717aec1d6eScindi 		int i;
21727aec1d6eScindi 
21737aec1d6eScindi 		(void) nvpair_value_string_array(nvpair, &val, &nel);
21747aec1d6eScindi 		*nvals = nel;
21757aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
21767aec1d6eScindi 		for (i = 0; i < nel; i++) {
21777aec1d6eScindi 			retvals[i].t = STRING;
217880ab886dSwesolows 			retvals[i].v = (uintptr_t)stable(val[i]);
21797aec1d6eScindi 		}
21807aec1d6eScindi 		return (retvals);
21817aec1d6eScindi 	}
21827aec1d6eScindi 
21837aec1d6eScindi 	case DATA_TYPE_INT8_ARRAY: {
21847aec1d6eScindi 		int8_t *val;
21857aec1d6eScindi 		uint_t nel;
21867aec1d6eScindi 		int i;
21877aec1d6eScindi 
21887aec1d6eScindi 		(void) nvpair_value_int8_array(nvpair, &val, &nel);
21897aec1d6eScindi 		*nvals = nel;
21907aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
21917aec1d6eScindi 		for (i = 0; i < nel; i++) {
21927aec1d6eScindi 			retvals[i].t = UINT64;
21937aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
21947aec1d6eScindi 		}
21957aec1d6eScindi 		return (retvals);
21967aec1d6eScindi 	}
21977aec1d6eScindi 	case DATA_TYPE_UINT8_ARRAY: {
21987aec1d6eScindi 		uint8_t *val;
21997aec1d6eScindi 		uint_t nel;
22007aec1d6eScindi 		int i;
22017aec1d6eScindi 
22027aec1d6eScindi 		(void) nvpair_value_uint8_array(nvpair, &val, &nel);
22037aec1d6eScindi 		*nvals = nel;
22047aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
22057aec1d6eScindi 		for (i = 0; i < nel; i++) {
22067aec1d6eScindi 			retvals[i].t = UINT64;
22077aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
22087aec1d6eScindi 		}
22097aec1d6eScindi 		return (retvals);
22107aec1d6eScindi 	}
22117aec1d6eScindi 	case DATA_TYPE_INT16_ARRAY: {
22127aec1d6eScindi 		int16_t *val;
22137aec1d6eScindi 		uint_t nel;
22147aec1d6eScindi 		int i;
22157aec1d6eScindi 
22167aec1d6eScindi 		(void) nvpair_value_int16_array(nvpair, &val, &nel);
22177aec1d6eScindi 		*nvals = nel;
22187aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
22197aec1d6eScindi 		for (i = 0; i < nel; i++) {
22207aec1d6eScindi 			retvals[i].t = UINT64;
22217aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
22227aec1d6eScindi 		}
22237aec1d6eScindi 		return (retvals);
22247aec1d6eScindi 	}
22257aec1d6eScindi 	case DATA_TYPE_UINT16_ARRAY: {
22267aec1d6eScindi 		uint16_t *val;
22277aec1d6eScindi 		uint_t nel;
22287aec1d6eScindi 		int i;
22297aec1d6eScindi 
22307aec1d6eScindi 		(void) nvpair_value_uint16_array(nvpair, &val, &nel);
22317aec1d6eScindi 		*nvals = nel;
22327aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
22337aec1d6eScindi 		for (i = 0; i < nel; i++) {
22347aec1d6eScindi 			retvals[i].t = UINT64;
22357aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
22367aec1d6eScindi 		}
22377aec1d6eScindi 		return (retvals);
22387aec1d6eScindi 	}
22397aec1d6eScindi 	case DATA_TYPE_INT32_ARRAY: {
22407aec1d6eScindi 		int32_t *val;
22417aec1d6eScindi 		uint_t nel;
22427aec1d6eScindi 		int i;
22437aec1d6eScindi 
22447aec1d6eScindi 		(void) nvpair_value_int32_array(nvpair, &val, &nel);
22457aec1d6eScindi 		*nvals = nel;
22467aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
22477aec1d6eScindi 		for (i = 0; i < nel; i++) {
22487aec1d6eScindi 			retvals[i].t = UINT64;
22497aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
22507aec1d6eScindi 		}
22517aec1d6eScindi 		return (retvals);
22527aec1d6eScindi 	}
22537aec1d6eScindi 	case DATA_TYPE_UINT32_ARRAY: {
22547aec1d6eScindi 		uint32_t *val;
22557aec1d6eScindi 		uint_t nel;
22567aec1d6eScindi 		int i;
22577aec1d6eScindi 
22587aec1d6eScindi 		(void) nvpair_value_uint32_array(nvpair, &val, &nel);
22597aec1d6eScindi 		*nvals = nel;
22607aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
22617aec1d6eScindi 		for (i = 0; i < nel; i++) {
22627aec1d6eScindi 			retvals[i].t = UINT64;
22637aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
22647aec1d6eScindi 		}
22657aec1d6eScindi 		return (retvals);
22667aec1d6eScindi 	}
22677aec1d6eScindi 	case DATA_TYPE_INT64_ARRAY: {
22687aec1d6eScindi 		int64_t *val;
22697aec1d6eScindi 		uint_t nel;
22707aec1d6eScindi 		int i;
22717aec1d6eScindi 
22727aec1d6eScindi 		(void) nvpair_value_int64_array(nvpair, &val, &nel);
22737aec1d6eScindi 		*nvals = nel;
22747aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
22757aec1d6eScindi 		for (i = 0; i < nel; i++) {
22767aec1d6eScindi 			retvals[i].t = UINT64;
22777aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
22787aec1d6eScindi 		}
22797aec1d6eScindi 		return (retvals);
22807aec1d6eScindi 	}
22817aec1d6eScindi 	case DATA_TYPE_UINT64_ARRAY: {
22827aec1d6eScindi 		uint64_t *val;
22837aec1d6eScindi 		uint_t nel;
22847aec1d6eScindi 		int i;
22857aec1d6eScindi 
22867aec1d6eScindi 		(void) nvpair_value_uint64_array(nvpair, &val, &nel);
22877aec1d6eScindi 		*nvals = nel;
22887aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
22897aec1d6eScindi 		for (i = 0; i < nel; i++) {
22907aec1d6eScindi 			retvals[i].t = UINT64;
22917aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
22927aec1d6eScindi 		}
22937aec1d6eScindi 		return (retvals);
22947aec1d6eScindi 	}
22957aec1d6eScindi 
22967aec1d6eScindi 	}
22977aec1d6eScindi 
22987aec1d6eScindi 	return (NULL);
22997aec1d6eScindi }
230008f6c065Sgavinm 
230108f6c065Sgavinm /*
230208f6c065Sgavinm  * When a list.repaired event is seen the following is called for
230308f6c065Sgavinm  * each fault in the associated fault list to convert the given FMRI
230408f6c065Sgavinm  * to an instanced path.  Only hc scheme is supported.
230508f6c065Sgavinm  */
230608f6c065Sgavinm const struct ipath *
230708f6c065Sgavinm platform_fault2ipath(nvlist_t *flt)
230808f6c065Sgavinm {
230908f6c065Sgavinm 	nvlist_t *rsrc;
231008f6c065Sgavinm 	struct node *np;
231108f6c065Sgavinm 	char *scheme;
23129dd0f810Scindi 	const struct ipath *ip;
231308f6c065Sgavinm 
231408f6c065Sgavinm 	if (nvlist_lookup_nvlist(flt, FM_FAULT_RESOURCE, &rsrc) != 0) {
231508f6c065Sgavinm 		out(O_ALTFP, "platform_fault2ipath: no resource member");
231608f6c065Sgavinm 		return (NULL);
231708f6c065Sgavinm 	} else if (nvlist_lookup_string(rsrc, FM_FMRI_SCHEME, &scheme) != 0) {
231808f6c065Sgavinm 		out(O_ALTFP, "platform_fault2ipath: no scheme type for rsrc");
231908f6c065Sgavinm 		return (NULL);
232008f6c065Sgavinm 	}
232108f6c065Sgavinm 
232208f6c065Sgavinm 	if (strncmp(scheme, FM_FMRI_SCHEME_HC,
232308f6c065Sgavinm 	    sizeof (FM_FMRI_SCHEME_HC) - 1) != 0) {
232408f6c065Sgavinm 		out(O_ALTFP, "platform_fault2ipath: returning NULL for non-hc "
232508f6c065Sgavinm 		"scheme %s", scheme);
232608f6c065Sgavinm 		return (NULL);
232708f6c065Sgavinm 	}
232808f6c065Sgavinm 
232908f6c065Sgavinm 	if ((np = hc_fmri_nodeize(rsrc)) == NULL)
233008f6c065Sgavinm 		return (NULL);		/* nodeize will already have whinged */
233108f6c065Sgavinm 
23329dd0f810Scindi 	ip = ipath(np);
23339dd0f810Scindi 	tree_free(np);
23349dd0f810Scindi 	return (ip);
233508f6c065Sgavinm }
2336