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 /*
2244ed9dbbSStephen Hanson  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  *
247c478bd9Sstevel@tonic-gate  * platform.c -- interfaces to the platform's configuration information
257c478bd9Sstevel@tonic-gate  *
267c478bd9Sstevel@tonic-gate  * this platform.c allows eft to run on Solaris systems.
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <stdio.h>
307c478bd9Sstevel@tonic-gate #include <stdlib.h>
317c478bd9Sstevel@tonic-gate #include <string.h>
327c478bd9Sstevel@tonic-gate #include <strings.h>
337c478bd9Sstevel@tonic-gate #include <ctype.h>
347c478bd9Sstevel@tonic-gate #include <dirent.h>
357c478bd9Sstevel@tonic-gate #include <libnvpair.h>
367c478bd9Sstevel@tonic-gate #include <dlfcn.h>
377c478bd9Sstevel@tonic-gate #include <unistd.h>
387c478bd9Sstevel@tonic-gate #include <errno.h>
397c478bd9Sstevel@tonic-gate #include <stropts.h>
407c478bd9Sstevel@tonic-gate #include <sys/types.h>
413e8d8e18Sdb #include <sys/stat.h>
427c478bd9Sstevel@tonic-gate #include <sys/wait.h>
437c478bd9Sstevel@tonic-gate #include <sys/filio.h>
447c478bd9Sstevel@tonic-gate #include <sys/param.h>
457c478bd9Sstevel@tonic-gate #include <sys/fm/protocol.h>
467c478bd9Sstevel@tonic-gate #include <fm/fmd_api.h>
470eb822a1Scindi #include <fm/fmd_fmri.h>
487aec1d6eScindi #include <fm/libtopo.h>
490eb822a1Scindi #include <fm/topo_hc.h>
507c478bd9Sstevel@tonic-gate #include "alloc.h"
517c478bd9Sstevel@tonic-gate #include "out.h"
527c478bd9Sstevel@tonic-gate #include "tree.h"
537c478bd9Sstevel@tonic-gate #include "itree.h"
547c478bd9Sstevel@tonic-gate #include "ipath.h"
557c478bd9Sstevel@tonic-gate #include "ptree.h"
567c478bd9Sstevel@tonic-gate #include "fme.h"
577c478bd9Sstevel@tonic-gate #include "stable.h"
587c478bd9Sstevel@tonic-gate #include "eval.h"
597c478bd9Sstevel@tonic-gate #include "config.h"
607c478bd9Sstevel@tonic-gate #include "platform.h"
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate extern fmd_hdl_t *Hdl;		/* handle from eft.c */
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /*
65b5016cbbSstephh  * Lastcfg points to the last configuration snapshot we made.
667c478bd9Sstevel@tonic-gate  */
677c478bd9Sstevel@tonic-gate static struct cfgdata *Lastcfg;
68b5016cbbSstephh static fmd_hdl_t *Lasthdl;
69b5016cbbSstephh static fmd_case_t *Lastfmcase;
70b5016cbbSstephh static const char *lastcomp;
71b5016cbbSstephh static int in_getpath;
72b5016cbbSstephh extern struct lut *Usednames;
73b5016cbbSstephh int prune_raw_config = 0;
747c478bd9Sstevel@tonic-gate 
75b5016cbbSstephh static topo_hdl_t *Eft_topo_hdl;
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate void *
topo_use_alloc(size_t bytes)787c478bd9Sstevel@tonic-gate topo_use_alloc(size_t bytes)
797c478bd9Sstevel@tonic-gate {
807c478bd9Sstevel@tonic-gate 	void *p = alloc_malloc(bytes, NULL, 0);
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 	bzero(p, bytes);
837c478bd9Sstevel@tonic-gate 	return (p);
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate void
topo_use_free(void * p)877c478bd9Sstevel@tonic-gate topo_use_free(void *p)
887c478bd9Sstevel@tonic-gate {
897c478bd9Sstevel@tonic-gate 	alloc_free(p, NULL, 0);
907c478bd9Sstevel@tonic-gate }
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate /*ARGSUSED*/
937c478bd9Sstevel@tonic-gate static void *
alloc_nv_alloc(nv_alloc_t * nva,size_t size)947c478bd9Sstevel@tonic-gate alloc_nv_alloc(nv_alloc_t *nva, size_t size)
957c478bd9Sstevel@tonic-gate {
967c478bd9Sstevel@tonic-gate 	return (alloc_malloc(size, NULL, 0));
977c478bd9Sstevel@tonic-gate }
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1007c478bd9Sstevel@tonic-gate static void
alloc_nv_free(nv_alloc_t * nva,void * p,size_t sz)1017c478bd9Sstevel@tonic-gate alloc_nv_free(nv_alloc_t *nva, void *p, size_t sz)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate 	alloc_free(p, NULL, 0);
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate const nv_alloc_ops_t Eft_nv_alloc_ops = {
1077c478bd9Sstevel@tonic-gate 	NULL,		/* nv_ao_init() */
1087c478bd9Sstevel@tonic-gate 	NULL,		/* nv_ao_fini() */
1097c478bd9Sstevel@tonic-gate 	alloc_nv_alloc,	/* nv_ao_alloc() */
1107c478bd9Sstevel@tonic-gate 	alloc_nv_free,	/* nv_ao_free() */
1117c478bd9Sstevel@tonic-gate 	NULL		/* nv_ao_reset() */
1127c478bd9Sstevel@tonic-gate };
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate nv_alloc_t Eft_nv_hdl;
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate static char *Root;
1177c478bd9Sstevel@tonic-gate static char *Mach;
1187c478bd9Sstevel@tonic-gate static char *Plat;
1197aec1d6eScindi static char tmpbuf[MAXPATHLEN];
1207aec1d6eScindi static char numbuf[MAXPATHLEN];
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate /*
1237c478bd9Sstevel@tonic-gate  * platform_globals -- set global variables based on sysinfo() calls
1247c478bd9Sstevel@tonic-gate  */
1257c478bd9Sstevel@tonic-gate static void
platform_globals()1267c478bd9Sstevel@tonic-gate platform_globals()
1277c478bd9Sstevel@tonic-gate {
1287c478bd9Sstevel@tonic-gate 	Root = fmd_prop_get_string(Hdl, "fmd.rootdir");
1297c478bd9Sstevel@tonic-gate 	Mach = fmd_prop_get_string(Hdl, "fmd.machine");
1307c478bd9Sstevel@tonic-gate 	Plat = fmd_prop_get_string(Hdl, "fmd.platform");
1317c478bd9Sstevel@tonic-gate }
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate static void
platform_free_globals()1347c478bd9Sstevel@tonic-gate platform_free_globals()
1357c478bd9Sstevel@tonic-gate {
1367c478bd9Sstevel@tonic-gate 	fmd_prop_free_string(Hdl, Root);
1377c478bd9Sstevel@tonic-gate 	fmd_prop_free_string(Hdl, Mach);
1387c478bd9Sstevel@tonic-gate 	fmd_prop_free_string(Hdl, Plat);
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate /*
1427c478bd9Sstevel@tonic-gate  * platform_init -- perform any platform-specific initialization
1437c478bd9Sstevel@tonic-gate  */
1447c478bd9Sstevel@tonic-gate void
platform_init(void)1457c478bd9Sstevel@tonic-gate platform_init(void)
1467c478bd9Sstevel@tonic-gate {
1477c478bd9Sstevel@tonic-gate 	(void) nv_alloc_init(&Eft_nv_hdl, &Eft_nv_alloc_ops);
14824db4641Seschrock 	Eft_topo_hdl = fmd_hdl_topo_hold(Hdl, TOPO_VERSION);
1497c478bd9Sstevel@tonic-gate 	platform_globals();
1507aec1d6eScindi 
1517aec1d6eScindi 	out(O_ALTFP, "platform_init() sucessful");
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate void
platform_fini(void)1557c478bd9Sstevel@tonic-gate platform_fini(void)
1567c478bd9Sstevel@tonic-gate {
1577c478bd9Sstevel@tonic-gate 	if (Lastcfg != NULL) {
1587c478bd9Sstevel@tonic-gate 		config_free(Lastcfg);
1597c478bd9Sstevel@tonic-gate 		Lastcfg = NULL;
1607c478bd9Sstevel@tonic-gate 	}
16124db4641Seschrock 	fmd_hdl_topo_rele(Hdl, Eft_topo_hdl);
1627c478bd9Sstevel@tonic-gate 	platform_free_globals();
1637c478bd9Sstevel@tonic-gate 	(void) nv_alloc_fini(&Eft_nv_hdl);
1647aec1d6eScindi 
1657aec1d6eScindi 	out(O_ALTFP, "platform_fini() sucessful");
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate /*
1697c478bd9Sstevel@tonic-gate  * hc_fmri_nodeize -- convert hc-scheme FMRI to eft compatible format
1707c478bd9Sstevel@tonic-gate  *
1717c478bd9Sstevel@tonic-gate  * this is an internal platform.c helper routine
1727c478bd9Sstevel@tonic-gate  */
1737c478bd9Sstevel@tonic-gate static struct node *
hc_fmri_nodeize(nvlist_t * hcfmri)1747c478bd9Sstevel@tonic-gate hc_fmri_nodeize(nvlist_t *hcfmri)
1757c478bd9Sstevel@tonic-gate {
1767c478bd9Sstevel@tonic-gate 	struct node *pathtree = NULL;
1777c478bd9Sstevel@tonic-gate 	struct node *tmpn;
1787c478bd9Sstevel@tonic-gate 	nvlist_t **hc_prs;
1797c478bd9Sstevel@tonic-gate 	uint_t hc_nprs;
1807c478bd9Sstevel@tonic-gate 	const char *sname;
1817c478bd9Sstevel@tonic-gate 	char *ename;
1827c478bd9Sstevel@tonic-gate 	char *eid;
1837c478bd9Sstevel@tonic-gate 	int e, r;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	/*
1867c478bd9Sstevel@tonic-gate 	 * What to do with/about hc-root?  Would we have any clue what
1877c478bd9Sstevel@tonic-gate 	 * to do with it if it weren't /?  For now, we don't bother
1887c478bd9Sstevel@tonic-gate 	 * even looking it up.
1897c478bd9Sstevel@tonic-gate 	 */
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	/*
1927c478bd9Sstevel@tonic-gate 	 * Get the hc-list of elements in the FMRI
1937c478bd9Sstevel@tonic-gate 	 */
1947c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_nvlist_array(hcfmri, FM_FMRI_HC_LIST,
1957c478bd9Sstevel@tonic-gate 	    &hc_prs, &hc_nprs) != 0) {
1967c478bd9Sstevel@tonic-gate 		out(O_ALTFP, "XFILE: hc FMRI missing %s", FM_FMRI_HC_LIST);
1977c478bd9Sstevel@tonic-gate 		return (NULL);
1987c478bd9Sstevel@tonic-gate 	}
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	for (e = 0; e < hc_nprs; e++) {
2017c478bd9Sstevel@tonic-gate 		ename = NULL;
2027c478bd9Sstevel@tonic-gate 		eid = NULL;
2037c478bd9Sstevel@tonic-gate 		r = nvlist_lookup_string(hc_prs[e], FM_FMRI_HC_NAME, &ename);
2047c478bd9Sstevel@tonic-gate 		r |= nvlist_lookup_string(hc_prs[e], FM_FMRI_HC_ID, &eid);
2057c478bd9Sstevel@tonic-gate 		if (r != 0) {
2067c478bd9Sstevel@tonic-gate 			/* probably should bail */
2077c478bd9Sstevel@tonic-gate 			continue;
2087c478bd9Sstevel@tonic-gate 		}
2097c478bd9Sstevel@tonic-gate 		sname = stable(ename);
2107c478bd9Sstevel@tonic-gate 		tmpn = tree_name_iterator(
21124db4641Seschrock 		    tree_name(sname, IT_VERTICAL, NULL, 0),
21224db4641Seschrock 		    tree_num(eid, NULL, 0));
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 		if (pathtree == NULL)
2157c478bd9Sstevel@tonic-gate 			pathtree = tmpn;
2167c478bd9Sstevel@tonic-gate 		else
2177c478bd9Sstevel@tonic-gate 			(void) tree_name_append(pathtree, tmpn);
2187c478bd9Sstevel@tonic-gate 	}
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	return (pathtree);
2217c478bd9Sstevel@tonic-gate }
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate /*
2247c478bd9Sstevel@tonic-gate  * platform_getpath -- extract eft-compatible path from ereport
2257c478bd9Sstevel@tonic-gate  */
2267c478bd9Sstevel@tonic-gate struct node *
platform_getpath(nvlist_t * nvl)2277c478bd9Sstevel@tonic-gate platform_getpath(nvlist_t *nvl)
2287c478bd9Sstevel@tonic-gate {
229602ca9eaScth 	struct node	*ret;
23044ed9dbbSStephen Hanson 	nvlist_t	*dfmri, *real_fmri, *resource;
231602ca9eaScth 	char		*scheme;
232602ca9eaScth 	char		*path;
233602ca9eaScth 	char		*devid;
23444ed9dbbSStephen Hanson 	char		*tp;
235602ca9eaScth 	uint32_t	cpuid;
23644ed9dbbSStephen Hanson 	int		err;
23744ed9dbbSStephen Hanson 	enum {DT_HC, DT_DEVID, DT_TP, DT_DEV, DT_CPU, DT_UNKNOWN} type =
23844ed9dbbSStephen Hanson 		DT_UNKNOWN;
239602ca9eaScth 
240602ca9eaScth 	/* Find the detector */
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 
246602ca9eaScth 	/* get the scheme from the detector */
2477c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_string(dfmri, FM_FMRI_SCHEME, &scheme) != 0) {
2487c478bd9Sstevel@tonic-gate 		out(O_ALTFP, "XFILE: detector FMRI missing scheme");
2497c478bd9Sstevel@tonic-gate 		return (NULL);
2507c478bd9Sstevel@tonic-gate 	}
2517c478bd9Sstevel@tonic-gate 
252602ca9eaScth 	/* based on scheme, determine type */
253602ca9eaScth 	if (strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
254602ca9eaScth 		/* already in hc scheme */
25544ed9dbbSStephen Hanson 		type = DT_HC;
256602ca9eaScth 	} else if (strcmp(scheme, FM_FMRI_SCHEME_DEV) == 0) {
25744ed9dbbSStephen Hanson 		/*
25844ed9dbbSStephen Hanson 		 * devid takes precedence over tp which takes precedence over
25944ed9dbbSStephen Hanson 		 * path
26044ed9dbbSStephen Hanson 		 */
261602ca9eaScth 		if (nvlist_lookup_string(dfmri,
262602ca9eaScth 		    FM_FMRI_DEV_ID, &devid) == 0)
263602ca9eaScth 			type = DT_DEVID;
264392e836bSGavin Maltby 		else if (nvlist_lookup_string(dfmri,
26544ed9dbbSStephen Hanson 		    TOPO_STORAGE_TARGET_PORT_L0ID, &tp) == 0)
26644ed9dbbSStephen Hanson 			type = DT_TP;
267602ca9eaScth 		else if (nvlist_lookup_string(dfmri,
268602ca9eaScth 		    FM_FMRI_DEV_PATH, &path) == 0)
269602ca9eaScth 			type = DT_DEV;
270602ca9eaScth 		else {
271602ca9eaScth 			out(O_ALTFP, "XFILE: detector FMRI missing %s or %s",
272602ca9eaScth 			    FM_FMRI_DEV_ID, FM_FMRI_DEV_PATH);
2737c478bd9Sstevel@tonic-gate 			return (NULL);
2747c478bd9Sstevel@tonic-gate 		}
275c7d6cfd6SStephen Hanson 	} else if (strcmp(scheme, FM_FMRI_SCHEME_CPU) == 0) {
276602ca9eaScth 		if (nvlist_lookup_uint32(dfmri, FM_FMRI_CPU_ID, &cpuid) == 0)
277602ca9eaScth 			type = DT_CPU;
278602ca9eaScth 		else {
2797c478bd9Sstevel@tonic-gate 			out(O_ALTFP, "XFILE: detector FMRI missing %s",
2807c478bd9Sstevel@tonic-gate 			    FM_FMRI_CPU_ID);
2817c478bd9Sstevel@tonic-gate 			return (NULL);
2827c478bd9Sstevel@tonic-gate 		}
283602ca9eaScth 	} else {
284602ca9eaScth 		out(O_ALTFP, "XFILE: detector FMRI not recognized "
285602ca9eaScth 		    "(scheme is %s, expect %s or %s or %s)",
286602ca9eaScth 		    scheme, FM_FMRI_SCHEME_HC, FM_FMRI_SCHEME_DEV,
287602ca9eaScth 		    FM_FMRI_SCHEME_CPU);
288602ca9eaScth 		return (NULL);
289602ca9eaScth 	}
2907c478bd9Sstevel@tonic-gate 
291602ca9eaScth 	out(O_ALTFP|O_VERB, "Received ereport in scheme %s", scheme);
2927c478bd9Sstevel@tonic-gate 
293602ca9eaScth 	/* take a config snapshot */
294602ca9eaScth 	lut_free(Usednames, NULL, NULL);
295602ca9eaScth 	Usednames = NULL;
296602ca9eaScth 	in_getpath = 1;
297602ca9eaScth 	if (config_snapshot() == NULL) {
29844ed9dbbSStephen Hanson 		if (type == DT_HC) {
29944ed9dbbSStephen Hanson 			/*
30044ed9dbbSStephen Hanson 			 * If hc-scheme use the fmri that was passed in.
30144ed9dbbSStephen Hanson 			 */
30244ed9dbbSStephen Hanson 			in_getpath = 0;
30344ed9dbbSStephen Hanson 			return (hc_fmri_nodeize(dfmri));
30444ed9dbbSStephen Hanson 		}
305602ca9eaScth 		out(O_ALTFP, "XFILE: cannot snapshot configuration");
306b5016cbbSstephh 		in_getpath = 0;
307602ca9eaScth 		return (NULL);
308602ca9eaScth 	}
309602ca9eaScth 
31044ed9dbbSStephen Hanson 	/*
31144ed9dbbSStephen Hanson 	 * For hc scheme, if we can find the resource from the tolopogy, use
31244ed9dbbSStephen Hanson 	 * that - otherwise use the fmri that was passed in. For other schemes
31344ed9dbbSStephen Hanson 	 * look up the path, cpuid, tp or devid in the topology.
31444ed9dbbSStephen Hanson 	 */
315602ca9eaScth 	switch (type) {
31644ed9dbbSStephen Hanson 	case DT_HC:
31744ed9dbbSStephen Hanson 		if (topo_fmri_getprop(Eft_topo_hdl, dfmri, TOPO_PGROUP_PROTOCOL,
318015ed3f8SRobert Johnston 		    TOPO_PROP_RESOURCE, NULL, &resource, &err) == -1) {
31944ed9dbbSStephen Hanson 			ret = hc_fmri_nodeize(dfmri);
320015ed3f8SRobert Johnston 			break;
321015ed3f8SRobert Johnston 		} else if (nvlist_lookup_nvlist(resource,
32244ed9dbbSStephen Hanson 		    TOPO_PROP_VAL_VAL, &real_fmri) != 0)
32344ed9dbbSStephen Hanson 			ret = hc_fmri_nodeize(dfmri);
32444ed9dbbSStephen Hanson 		else
32544ed9dbbSStephen Hanson 			ret = hc_fmri_nodeize(real_fmri);
326015ed3f8SRobert Johnston 
327015ed3f8SRobert Johnston 		nvlist_free(resource);
32844ed9dbbSStephen Hanson 		break;
32944ed9dbbSStephen Hanson 
330602ca9eaScth 	case DT_DEV:
331602ca9eaScth 		if ((ret = config_bydev_lookup(Lastcfg, path)) == NULL)
332602ca9eaScth 			out(O_ALTFP, "platform_getpath: no configuration node "
333602ca9eaScth 			    "has device path matching \"%s\".", path);
334602ca9eaScth 
335602ca9eaScth 		break;
336602ca9eaScth 
33744ed9dbbSStephen Hanson 	case DT_TP:
33844ed9dbbSStephen Hanson 		if ((ret = config_bytp_lookup(Lastcfg, tp)) == NULL)
33944ed9dbbSStephen Hanson 			out(O_ALTFP, "platform_getpath: no configuration node "
34044ed9dbbSStephen Hanson 			    "has tp matching \"%s\".", tp);
34144ed9dbbSStephen Hanson 		break;
34244ed9dbbSStephen Hanson 
343602ca9eaScth 	case DT_DEVID:
344602ca9eaScth 		if ((ret = config_bydevid_lookup(Lastcfg, devid)) == NULL)
345602ca9eaScth 			out(O_ALTFP, "platform_getpath: no configuration node "
346602ca9eaScth 			    "has devid matching \"%s\".", devid);
347602ca9eaScth 		break;
348602ca9eaScth 
349602ca9eaScth 	case DT_CPU:
350602ca9eaScth 		if ((ret = config_bycpuid_lookup(Lastcfg, cpuid)) == NULL)
351602ca9eaScth 			out(O_ALTFP, "platform_getpath: no configuration node "
352602ca9eaScth 			    "has cpu-id matching %u.", cpuid);
353602ca9eaScth 		break;
3547c478bd9Sstevel@tonic-gate 	}
3557c478bd9Sstevel@tonic-gate 
356602ca9eaScth 	/* free the snapshot */
357602ca9eaScth 	structconfig_free(Lastcfg->cooked);
358602ca9eaScth 	config_free(Lastcfg);
359602ca9eaScth 	in_getpath = 0;
360602ca9eaScth 	return (ret);
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate /* Allocate space for raw config strings in chunks of this size */
3647c478bd9Sstevel@tonic-gate #define	STRSBUFLEN	512
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate /*
3677c478bd9Sstevel@tonic-gate  * cfgadjust -- Make sure the amount we want to add to the raw config string
3687c478bd9Sstevel@tonic-gate  *		buffer will fit, and if not, increase the size of the buffer.
3697c478bd9Sstevel@tonic-gate  */
3707c478bd9Sstevel@tonic-gate static void
cfgadjust(struct cfgdata * rawdata,int addlen)3717c478bd9Sstevel@tonic-gate cfgadjust(struct cfgdata *rawdata, int addlen)
3727c478bd9Sstevel@tonic-gate {
3737c478bd9Sstevel@tonic-gate 	int curnext, newlen;
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	if (rawdata->nextfree + addlen >= rawdata->end) {
3767c478bd9Sstevel@tonic-gate 		newlen = (((rawdata->nextfree - rawdata->begin + 1 + addlen)
3777c478bd9Sstevel@tonic-gate 		    / STRSBUFLEN) + 1) * STRSBUFLEN;
3787c478bd9Sstevel@tonic-gate 		curnext = rawdata->nextfree - rawdata->begin;
3797c478bd9Sstevel@tonic-gate 		rawdata->begin = REALLOC(rawdata->begin, newlen);
3807c478bd9Sstevel@tonic-gate 		rawdata->nextfree = rawdata->begin + curnext;
3817c478bd9Sstevel@tonic-gate 		rawdata->end = rawdata->begin + newlen;
3827c478bd9Sstevel@tonic-gate 	}
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate 
3857aec1d6eScindi static char *
hc_path(tnode_t * node)3867aec1d6eScindi hc_path(tnode_t *node)
3877aec1d6eScindi {
3887aec1d6eScindi 	int i, err;
3897aec1d6eScindi 	char *name, *instance, *estr;
3907aec1d6eScindi 	nvlist_t *fmri, **hcl;
3917aec1d6eScindi 	ulong_t ul;
3927aec1d6eScindi 	uint_t nhc;
3937aec1d6eScindi 
3947aec1d6eScindi 	if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE,
3957aec1d6eScindi 	    &fmri, &err) < 0)
3967aec1d6eScindi 		return (NULL);
3977aec1d6eScindi 
3987aec1d6eScindi 	if (nvlist_lookup_nvlist_array(fmri, FM_FMRI_HC_LIST, &hcl, &nhc)
3997aec1d6eScindi 	    != 0) {
4007aec1d6eScindi 		nvlist_free(fmri);
4017aec1d6eScindi 		return (NULL);
4027aec1d6eScindi 	}
4037aec1d6eScindi 
4047aec1d6eScindi 	tmpbuf[0] = '\0';
4057aec1d6eScindi 	for (i = 0; i < nhc; ++i) {
4067aec1d6eScindi 		err = nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name);
4077aec1d6eScindi 		err |= nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &instance);
4087aec1d6eScindi 		if (err) {
4097aec1d6eScindi 			nvlist_free(fmri);
4107aec1d6eScindi 			return (NULL);
4117aec1d6eScindi 		}
4127aec1d6eScindi 
4137aec1d6eScindi 		ul = strtoul(instance, &estr, 10);
4147aec1d6eScindi 		/* conversion to number failed? */
4157aec1d6eScindi 		if (estr == instance) {
4167aec1d6eScindi 			nvlist_free(fmri);
4177aec1d6eScindi 			return (NULL);
4187aec1d6eScindi 		}
4197aec1d6eScindi 
4207aec1d6eScindi 		(void) strlcat(tmpbuf, "/", MAXPATHLEN);
4217aec1d6eScindi 		(void) strlcat(tmpbuf, name, MAXPATHLEN);
422837416c3Scy 		(void) snprintf(numbuf, MAXPATHLEN, "%lu", ul);
4237aec1d6eScindi 		(void) strlcat(tmpbuf, numbuf, MAXPATHLEN);
424b5016cbbSstephh 		lastcomp = stable(name);
4257aec1d6eScindi 	}
4267aec1d6eScindi 
4277aec1d6eScindi 	nvlist_free(fmri);
4287aec1d6eScindi 
4297aec1d6eScindi 	return (tmpbuf);
4307aec1d6eScindi }
4317aec1d6eScindi 
4327aec1d6eScindi static void
add_prop_val(topo_hdl_t * thp,struct cfgdata * rawdata,char * propn,nvpair_t * pv_nvp)4337aec1d6eScindi add_prop_val(topo_hdl_t *thp, struct cfgdata *rawdata, char *propn,
4347aec1d6eScindi     nvpair_t *pv_nvp)
4357aec1d6eScindi {
4367aec1d6eScindi 	int addlen, err;
4377aec1d6eScindi 	char *propv, *fmristr = NULL;
4387aec1d6eScindi 	nvlist_t *fmri;
439b5016cbbSstephh 	uint32_t ui32;
440b5016cbbSstephh 	int64_t i64;
441b5016cbbSstephh 	int32_t i32;
442b5016cbbSstephh 	boolean_t bool;
4438a40a695Sgavinm 	uint64_t ui64;
4448a40a695Sgavinm 	char buf[32];	/* big enough for any 64-bit int */
44544ed9dbbSStephen Hanson 	uint_t nelem;
44644ed9dbbSStephen Hanson 	int i, j, sz;
44744ed9dbbSStephen Hanson 	char **propvv;
4487aec1d6eScindi 
4490eb822a1Scindi 	/*
4500eb822a1Scindi 	 * malformed prop nvpair
4510eb822a1Scindi 	 */
4520eb822a1Scindi 	if (propn == NULL)
4530eb822a1Scindi 		return;
4540eb822a1Scindi 
4558a40a695Sgavinm 	switch (nvpair_type(pv_nvp)) {
45644ed9dbbSStephen Hanson 	case DATA_TYPE_STRING_ARRAY:
45744ed9dbbSStephen Hanson 		/*
45844ed9dbbSStephen Hanson 		 * Convert string array into single space-separated string
45944ed9dbbSStephen Hanson 		 */
46044ed9dbbSStephen Hanson 		(void) nvpair_value_string_array(pv_nvp, &propvv, &nelem);
46144ed9dbbSStephen Hanson 		for (sz = 0, i = 0; i < nelem; i++)
46244ed9dbbSStephen Hanson 			sz += strlen(propvv[i]) + 1;
46344ed9dbbSStephen Hanson 		propv = MALLOC(sz);
46444ed9dbbSStephen Hanson 		for (j = 0, i = 0; i < nelem; j++, i++) {
46544ed9dbbSStephen Hanson 			(void) strcpy(&propv[j], propvv[i]);
46644ed9dbbSStephen Hanson 			j += strlen(propvv[i]);
46744ed9dbbSStephen Hanson 			if (i < nelem - 1)
46844ed9dbbSStephen Hanson 				propv[j] = ' ';
46944ed9dbbSStephen Hanson 		}
47044ed9dbbSStephen Hanson 		break;
47144ed9dbbSStephen Hanson 
4728a40a695Sgavinm 	case DATA_TYPE_STRING:
4738a40a695Sgavinm 		(void) nvpair_value_string(pv_nvp, &propv);
4748a40a695Sgavinm 		break;
4758a40a695Sgavinm 
4768a40a695Sgavinm 	case DATA_TYPE_NVLIST:
4778a40a695Sgavinm 		/*
4788a40a695Sgavinm 		 * At least try to collect the protocol
4798a40a695Sgavinm 		 * properties
4808a40a695Sgavinm 		 */
4817aec1d6eScindi 		(void) nvpair_value_nvlist(pv_nvp, &fmri);
4827aec1d6eScindi 		if (topo_fmri_nvl2str(thp, fmri, &fmristr, &err) < 0) {
4837aec1d6eScindi 			out(O_ALTFP, "cfgcollect: failed to convert fmri to "
4847aec1d6eScindi 			    "string");
4857aec1d6eScindi 			return;
4867aec1d6eScindi 		} else {
4877aec1d6eScindi 			propv = fmristr;
4887aec1d6eScindi 		}
4898a40a695Sgavinm 		break;
4907aec1d6eScindi 
4918a40a695Sgavinm 	case DATA_TYPE_UINT64:
4928a40a695Sgavinm 		/*
4938a40a695Sgavinm 		 * Convert uint64 to hex strings
4948a40a695Sgavinm 		 */
4958a40a695Sgavinm 		(void) nvpair_value_uint64(pv_nvp, &ui64);
4968a40a695Sgavinm 		(void) snprintf(buf, sizeof (buf), "0x%llx", ui64);
4978a40a695Sgavinm 		propv = buf;
4988a40a695Sgavinm 		break;
4998a40a695Sgavinm 
500b5016cbbSstephh 	case DATA_TYPE_BOOLEAN_VALUE:
501b5016cbbSstephh 		/*
502b5016cbbSstephh 		 * Convert boolean_t to hex strings
503b5016cbbSstephh 		 */
504b5016cbbSstephh 		(void) nvpair_value_boolean_value(pv_nvp, &bool);
505b5016cbbSstephh 		(void) snprintf(buf, sizeof (buf), "0x%llx", (uint64_t)bool);
506b5016cbbSstephh 		propv = buf;
507b5016cbbSstephh 		break;
508b5016cbbSstephh 
509b5016cbbSstephh 	case DATA_TYPE_INT32:
510b5016cbbSstephh 		/*
511b5016cbbSstephh 		 * Convert int32 to hex strings
512b5016cbbSstephh 		 */
513b5016cbbSstephh 		(void) nvpair_value_int32(pv_nvp, &i32);
514b5016cbbSstephh 		(void) snprintf(buf, sizeof (buf), "0x%llx",
515b5016cbbSstephh 		    (uint64_t)(int64_t)i32);
516b5016cbbSstephh 		propv = buf;
517b5016cbbSstephh 		break;
518b5016cbbSstephh 
519b5016cbbSstephh 	case DATA_TYPE_INT64:
520b5016cbbSstephh 		/*
521b5016cbbSstephh 		 * Convert int64 to hex strings
522b5016cbbSstephh 		 */
523b5016cbbSstephh 		(void) nvpair_value_int64(pv_nvp, &i64);
524b5016cbbSstephh 		(void) snprintf(buf, sizeof (buf), "0x%llx", (uint64_t)i64);
525b5016cbbSstephh 		propv = buf;
526b5016cbbSstephh 		break;
527b5016cbbSstephh 
528b5016cbbSstephh 	case DATA_TYPE_UINT32:
529b5016cbbSstephh 		/*
530b5016cbbSstephh 		 * Convert uint32 to hex strings
531b5016cbbSstephh 		 */
532b5016cbbSstephh 		(void) nvpair_value_uint32(pv_nvp, &ui32);
533b5016cbbSstephh 		(void) snprintf(buf, sizeof (buf), "0x%llx", (uint64_t)ui32);
534b5016cbbSstephh 		propv = buf;
535b5016cbbSstephh 		break;
536b5016cbbSstephh 
5378a40a695Sgavinm 	default:
5380eb822a1Scindi 		out(O_ALTFP, "cfgcollect: failed to get property value for "
5390eb822a1Scindi 		    "%s", propn);
5407aec1d6eScindi 		return;
5417aec1d6eScindi 	}
5427aec1d6eScindi 
5437aec1d6eScindi 	/* = & NULL */
5447aec1d6eScindi 	addlen = strlen(propn) + strlen(propv) + 2;
5457aec1d6eScindi 	cfgadjust(rawdata, addlen);
5467aec1d6eScindi 	(void) snprintf(rawdata->nextfree,
5477aec1d6eScindi 	    rawdata->end - rawdata->nextfree, "%s=%s",
5487aec1d6eScindi 	    propn, propv);
5490eb822a1Scindi 	if (strcmp(propn, TOPO_PROP_RESOURCE) == 0)
550b5016cbbSstephh 		out(O_ALTFP|O_VERB3, "cfgcollect: %s", propv);
5510eb822a1Scindi 
55244ed9dbbSStephen Hanson 	if (nvpair_type(pv_nvp) == DATA_TYPE_STRING_ARRAY)
55344ed9dbbSStephen Hanson 		FREE(propv);
55444ed9dbbSStephen Hanson 
5557aec1d6eScindi 	rawdata->nextfree += addlen;
5567aec1d6eScindi 
5577aec1d6eScindi 	if (fmristr != NULL)
5587aec1d6eScindi 		topo_hdl_strfree(thp, fmristr);
5597aec1d6eScindi }
5607aec1d6eScindi 
5617c478bd9Sstevel@tonic-gate /*
5627c478bd9Sstevel@tonic-gate  * cfgcollect -- Assemble raw configuration data in string form suitable
5637c478bd9Sstevel@tonic-gate  *		 for checkpointing.
5647c478bd9Sstevel@tonic-gate  */
5657aec1d6eScindi static int
cfgcollect(topo_hdl_t * thp,tnode_t * node,void * arg)5667aec1d6eScindi cfgcollect(topo_hdl_t *thp, tnode_t *node, void *arg)
5677c478bd9Sstevel@tonic-gate {
5687c478bd9Sstevel@tonic-gate 	struct cfgdata *rawdata = (struct cfgdata *)arg;
5690eb822a1Scindi 	int err, addlen;
5707aec1d6eScindi 	char *propn, *path = NULL;
5717aec1d6eScindi 	nvlist_t *p_nv, *pg_nv, *pv_nv;
5727aec1d6eScindi 	nvpair_t *nvp, *pg_nvp, *pv_nvp;
5737aec1d6eScindi 
574c7d6cfd6SStephen Hanson 	if (topo_node_flags(node) == TOPO_NODE_FACILITY)
575c7d6cfd6SStephen Hanson 		return (TOPO_WALK_NEXT);
576c7d6cfd6SStephen Hanson 
5777aec1d6eScindi 	path = hc_path(node);
5787aec1d6eScindi 	if (path == NULL)
5797aec1d6eScindi 		return (TOPO_WALK_ERR);
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 	addlen = strlen(path) + 1;
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	cfgadjust(rawdata, addlen);
5847c478bd9Sstevel@tonic-gate 	(void) strcpy(rawdata->nextfree, path);
5857c478bd9Sstevel@tonic-gate 	rawdata->nextfree += addlen;
5867c478bd9Sstevel@tonic-gate 
587b5016cbbSstephh 	/*
588b5016cbbSstephh 	 * If the prune_raw_config flag is set then we will only include in the
589b5016cbbSstephh 	 * raw config those nodes that are used by the rules remaining after
590b5016cbbSstephh 	 * prune_propagations() has been run - ie only those that could possibly
591b5016cbbSstephh 	 * be relevant to the incoming ereport given the current rules. This
592b5016cbbSstephh 	 * means that any other parts of the config will not get saved to the
593b5016cbbSstephh 	 * checkpoint file (even if they may theoretically be used if the
594b5016cbbSstephh 	 * rules are subsequently modified).
595b5016cbbSstephh 	 *
596b5016cbbSstephh 	 * For now prune_raw_config is 0 for Solaris, though it is expected to
597b5016cbbSstephh 	 * be set to 1 for fmsp.
598b5016cbbSstephh 	 *
599b5016cbbSstephh 	 * Note we only prune the raw config like this if we have been called
600b5016cbbSstephh 	 * from newfme(), not if we have been called when handling dev or cpu
601b5016cbbSstephh 	 * scheme ereports from platform_getpath(), as this is called before
602b5016cbbSstephh 	 * prune_propagations() - again this is not an issue on fmsp as the
603b5016cbbSstephh 	 * ereports are all in hc scheme.
604b5016cbbSstephh 	 */
605b5016cbbSstephh 	if (!in_getpath && prune_raw_config &&
606b5016cbbSstephh 	    lut_lookup(Usednames, (void *)lastcomp, NULL) == NULL)
607b5016cbbSstephh 		return (TOPO_WALK_NEXT);
608b5016cbbSstephh 
6097aec1d6eScindi 	/*
6107aec1d6eScindi 	 * Collect properties
6117aec1d6eScindi 	 *
6127aec1d6eScindi 	 * eversholt should support alternate property types
6137aec1d6eScindi 	 * Better yet, topo properties could be represented as
6147aec1d6eScindi 	 * a packed nvlist
6157aec1d6eScindi 	 */
6160eb822a1Scindi 	p_nv = topo_prop_getprops(node, &err);
6177aec1d6eScindi 	for (nvp = nvlist_next_nvpair(p_nv, NULL); nvp != NULL;
6187aec1d6eScindi 	    nvp = nvlist_next_nvpair(p_nv, nvp)) {
6197aec1d6eScindi 		if (strcmp(TOPO_PROP_GROUP, nvpair_name(nvp)) != 0 ||
6207aec1d6eScindi 		    nvpair_type(nvp) != DATA_TYPE_NVLIST)
6217aec1d6eScindi 			continue;
6227aec1d6eScindi 
6237aec1d6eScindi 		(void) nvpair_value_nvlist(nvp, &pg_nv);
6247aec1d6eScindi 
6257aec1d6eScindi 		for (pg_nvp = nvlist_next_nvpair(pg_nv, NULL); pg_nvp != NULL;
6267aec1d6eScindi 		    pg_nvp = nvlist_next_nvpair(pg_nv, pg_nvp)) {
6277aec1d6eScindi 
6287aec1d6eScindi 			if (strcmp(TOPO_PROP_VAL, nvpair_name(pg_nvp)) != 0 ||
6297aec1d6eScindi 			    nvpair_type(pg_nvp) != DATA_TYPE_NVLIST)
6307aec1d6eScindi 				continue;
6317aec1d6eScindi 
6327aec1d6eScindi 			(void) nvpair_value_nvlist(pg_nvp, &pv_nv);
6337aec1d6eScindi 
6340eb822a1Scindi 			propn = NULL;
6357aec1d6eScindi 			for (pv_nvp = nvlist_next_nvpair(pv_nv, NULL);
6367aec1d6eScindi 			    pv_nvp != NULL;
6377aec1d6eScindi 			    pv_nvp = nvlist_next_nvpair(pv_nv, pv_nvp)) {
6387aec1d6eScindi 
6397aec1d6eScindi 				/* Get property name */
6400eb822a1Scindi 				if (strcmp(TOPO_PROP_VAL_NAME,
6410eb822a1Scindi 				    nvpair_name(pv_nvp)) == 0)
6420eb822a1Scindi 					(void) nvpair_value_string(pv_nvp,
6430eb822a1Scindi 					    &propn);
6447aec1d6eScindi 
6457aec1d6eScindi 				/*
6467aec1d6eScindi 				 * Get property value
6477aec1d6eScindi 				 */
6480eb822a1Scindi 				if (strcmp(TOPO_PROP_VAL_VAL,
6490eb822a1Scindi 				    nvpair_name(pv_nvp)) == 0)
6500eb822a1Scindi 					add_prop_val(thp, rawdata, propn,
6510eb822a1Scindi 					    pv_nvp);
6527aec1d6eScindi 			}
6537aec1d6eScindi 
6547aec1d6eScindi 		}
6557c478bd9Sstevel@tonic-gate 	}
6567aec1d6eScindi 
6577aec1d6eScindi 	nvlist_free(p_nv);
6587aec1d6eScindi 
6597aec1d6eScindi 	return (TOPO_WALK_NEXT);
6607c478bd9Sstevel@tonic-gate }
6617c478bd9Sstevel@tonic-gate 
662b5016cbbSstephh void
platform_restore_config(fmd_hdl_t * hdl,fmd_case_t * fmcase)663b5016cbbSstephh platform_restore_config(fmd_hdl_t *hdl, fmd_case_t *fmcase)
664b5016cbbSstephh {
665b5016cbbSstephh 	if (hdl == Lasthdl && fmcase == Lastfmcase) {
666b5016cbbSstephh 		size_t cfglen;
667b5016cbbSstephh 
668b5016cbbSstephh 		fmd_buf_read(Lasthdl, Lastfmcase, WOBUF_CFGLEN, (void *)&cfglen,
669b5016cbbSstephh 		    sizeof (size_t));
670b5016cbbSstephh 		Lastcfg->begin = MALLOC(cfglen);
671b5016cbbSstephh 		Lastcfg->end = Lastcfg->nextfree = Lastcfg->begin + cfglen;
672b5016cbbSstephh 		fmd_buf_read(Lasthdl, Lastfmcase, WOBUF_CFG, Lastcfg->begin,
673b5016cbbSstephh 		    cfglen);
674b5016cbbSstephh 		Lasthdl = NULL;
675b5016cbbSstephh 		Lastfmcase = NULL;
676b5016cbbSstephh 	}
677b5016cbbSstephh }
678b5016cbbSstephh 
679b5016cbbSstephh void
platform_save_config(fmd_hdl_t * hdl,fmd_case_t * fmcase)680b5016cbbSstephh platform_save_config(fmd_hdl_t *hdl, fmd_case_t *fmcase)
681b5016cbbSstephh {
682b5016cbbSstephh 	size_t cfglen;
683b5016cbbSstephh 
684b5016cbbSstephh 	/*
685b5016cbbSstephh 	 * Put the raw config into an fmd_buf. Then we can free it to
686b5016cbbSstephh 	 * save space.
687b5016cbbSstephh 	 */
688b5016cbbSstephh 	Lastfmcase = fmcase;
689b5016cbbSstephh 	Lasthdl = hdl;
690b5016cbbSstephh 	cfglen = Lastcfg->nextfree - Lastcfg->begin;
691b5016cbbSstephh 	fmd_buf_create(hdl, fmcase, WOBUF_CFGLEN, sizeof (cfglen));
692b5016cbbSstephh 	fmd_buf_write(hdl, fmcase, WOBUF_CFGLEN, (void *)&cfglen,
693b5016cbbSstephh 	    sizeof (cfglen));
694b5016cbbSstephh 	if (cfglen != 0) {
695b5016cbbSstephh 		fmd_buf_create(hdl, fmcase, WOBUF_CFG, cfglen);
696b5016cbbSstephh 		fmd_buf_write(hdl, fmcase, WOBUF_CFG, Lastcfg->begin, cfglen);
697b5016cbbSstephh 	}
698b5016cbbSstephh 	FREE(Lastcfg->begin);
699b5016cbbSstephh 	Lastcfg->begin = NULL;
700b5016cbbSstephh 	Lastcfg->end = NULL;
701b5016cbbSstephh 	Lastcfg->nextfree = NULL;
702b5016cbbSstephh }
703b5016cbbSstephh 
7047c478bd9Sstevel@tonic-gate /*
7057c478bd9Sstevel@tonic-gate  * platform_config_snapshot -- gather a snapshot of the current configuration
7067c478bd9Sstevel@tonic-gate  */
7077c478bd9Sstevel@tonic-gate struct cfgdata *
platform_config_snapshot(void)7087c478bd9Sstevel@tonic-gate platform_config_snapshot(void)
7097c478bd9Sstevel@tonic-gate {
7107aec1d6eScindi 	int err;
7117aec1d6eScindi 	topo_walk_t *twp;
7120eb822a1Scindi 	static uint64_t lastgen;
7130eb822a1Scindi 	uint64_t curgen;
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 	/*
7167c478bd9Sstevel@tonic-gate 	 * If the DR generation number has changed,
7177c478bd9Sstevel@tonic-gate 	 * we need to grab a new snapshot, otherwise we
7187c478bd9Sstevel@tonic-gate 	 * can simply point them at the last config.
7197c478bd9Sstevel@tonic-gate 	 */
720b5016cbbSstephh 	if (prune_raw_config == 0 && (curgen = fmd_fmri_get_drgen()) <=
721b5016cbbSstephh 	    lastgen && Lastcfg != NULL) {
722b5016cbbSstephh 		Lastcfg->raw_refcnt++;
723b5016cbbSstephh 		/*
724b5016cbbSstephh 		 * if config has been backed away to an fmd_buf, restore it
725b5016cbbSstephh 		 */
726b5016cbbSstephh 		if (Lastcfg->begin == NULL)
727b5016cbbSstephh 			platform_restore_config(Lasthdl, Lastfmcase);
7280eb822a1Scindi 		return (Lastcfg);
7290eb822a1Scindi 	}
7307c478bd9Sstevel@tonic-gate 
7310eb822a1Scindi 	lastgen = curgen;
7327c478bd9Sstevel@tonic-gate 	/* we're getting a new config, so clean up the last one */
733b5016cbbSstephh 	if (Lastcfg != NULL) {
73435f59e50SStephen Hanson 		config_free(Lastcfg);
735b5016cbbSstephh 	}
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate 	Lastcfg = MALLOC(sizeof (struct cfgdata));
738b5016cbbSstephh 	Lastcfg->raw_refcnt = 2;	/* caller + Lastcfg */
7397c478bd9Sstevel@tonic-gate 	Lastcfg->begin = Lastcfg->nextfree = Lastcfg->end = NULL;
7407c478bd9Sstevel@tonic-gate 	Lastcfg->cooked = NULL;
7417c478bd9Sstevel@tonic-gate 	Lastcfg->devcache = NULL;
742602ca9eaScth 	Lastcfg->devidcache = NULL;
74344ed9dbbSStephen Hanson 	Lastcfg->tpcache = NULL;
7447c478bd9Sstevel@tonic-gate 	Lastcfg->cpucache = NULL;
7457c478bd9Sstevel@tonic-gate 
7460eb822a1Scindi 
74724db4641Seschrock 	fmd_hdl_topo_rele(Hdl, Eft_topo_hdl);
74824db4641Seschrock 	Eft_topo_hdl = fmd_hdl_topo_hold(Hdl, TOPO_VERSION);
7497c478bd9Sstevel@tonic-gate 
7507aec1d6eScindi 	if ((twp = topo_walk_init(Eft_topo_hdl, FM_FMRI_SCHEME_HC, cfgcollect,
7517aec1d6eScindi 	    Lastcfg, &err)) == NULL) {
7527aec1d6eScindi 		out(O_DIE, "platform_config_snapshot: NULL topology tree: %s",
7537aec1d6eScindi 		    topo_strerror(err));
7547c478bd9Sstevel@tonic-gate 	}
7557c478bd9Sstevel@tonic-gate 
7567aec1d6eScindi 	if (topo_walk_step(twp, TOPO_WALK_CHILD) == TOPO_WALK_ERR) {
7577aec1d6eScindi 		topo_walk_fini(twp);
7587aec1d6eScindi 		out(O_DIE, "platform_config_snapshot: error walking topology "
7597aec1d6eScindi 		    "tree");
7607c478bd9Sstevel@tonic-gate 	}
7617c478bd9Sstevel@tonic-gate 
7627aec1d6eScindi 	topo_walk_fini(twp);
763b5016cbbSstephh 	out(O_ALTFP|O_STAMP, "raw config complete");
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 
7667aec1d6eScindi 	return (Lastcfg);
7677c478bd9Sstevel@tonic-gate }
7687c478bd9Sstevel@tonic-gate 
7697aec1d6eScindi static const char *
cfgstrprop_lookup(struct config * croot,char * path,const char * pname)770*da40b264SAlex Wilson cfgstrprop_lookup(struct config *croot, char *path, const char *pname)
7717c478bd9Sstevel@tonic-gate {
7727aec1d6eScindi 	struct config *cresource;
7737aec1d6eScindi 	const char *fmristr;
7747c478bd9Sstevel@tonic-gate 
7757aec1d6eScindi 	/*
7767aec1d6eScindi 	 * The first order of business is to find the resource in the
7777aec1d6eScindi 	 * config database so we can examine properties associated with
7787aec1d6eScindi 	 * that node.
7797aec1d6eScindi 	 */
7807aec1d6eScindi 	if ((cresource = config_lookup(croot, path, 0)) == NULL) {
7817aec1d6eScindi 		out(O_ALTFP, "Cannot find config info for %s.", path);
7827c478bd9Sstevel@tonic-gate 		return (NULL);
7837c478bd9Sstevel@tonic-gate 	}
7847aec1d6eScindi 	if ((fmristr = config_getprop(cresource, pname)) == NULL) {
7857aec1d6eScindi 		out(O_ALTFP, "Cannot find %s property for %s resource "
7867aec1d6eScindi 		    "re-write", pname, path);
7877c478bd9Sstevel@tonic-gate 		return (NULL);
7887c478bd9Sstevel@tonic-gate 	}
7897aec1d6eScindi 	return (fmristr);
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate /*
793*da40b264SAlex Wilson  * Get FMRI for a particular unit from libtopo. The unit is specified by the
794*da40b264SAlex Wilson  * "path" argument (a stringified ipath). "prop" argument should be one
795*da40b264SAlex Wilson  * of the constants TOPO_PROP_RESOURCE, TOPO_PROP_ASRU, TOPO_PROP_FRU, etc.
7967c478bd9Sstevel@tonic-gate  */
7977c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7987c478bd9Sstevel@tonic-gate void
platform_unit_translate(int isdefect,struct config * croot,const char * prop,nvlist_t ** fmrip,char * path)799*da40b264SAlex Wilson platform_unit_translate(int isdefect, struct config *croot, const char *prop,
800*da40b264SAlex Wilson     nvlist_t **fmrip, char *path)
8017c478bd9Sstevel@tonic-gate {
802b7d3956bSstephh 	const char *fmristr;
803b0daa853SStephen Hanson 	char *serial;
804*da40b264SAlex Wilson 	nvlist_t *fmri;
805b7d3956bSstephh 	int err;
8067c478bd9Sstevel@tonic-gate 
807*da40b264SAlex Wilson 	fmristr = cfgstrprop_lookup(croot, path, prop);
808b7d3956bSstephh 	if (fmristr == NULL) {
809*da40b264SAlex Wilson 		out(O_ALTFP, "Cannot rewrite unit FMRI for %s.", path);
8107c478bd9Sstevel@tonic-gate 		return;
8117c478bd9Sstevel@tonic-gate 	}
812*da40b264SAlex Wilson 	if (topo_fmri_str2nvl(Eft_topo_hdl, fmristr, &fmri, &err) < 0) {
813b7d3956bSstephh 		out(O_ALTFP, "Can not convert config info: %s",
814b7d3956bSstephh 		    topo_strerror(err));
815*da40b264SAlex Wilson 		out(O_ALTFP, "Cannot rewrite unit FMRI for %s.", path);
816b7d3956bSstephh 		return;
8177c478bd9Sstevel@tonic-gate 	}
818b0daa853SStephen Hanson 
819b0daa853SStephen Hanson 	/*
820*da40b264SAlex Wilson 	 * If we don't have a serial number in the unit then check if it
821b0daa853SStephen Hanson 	 * is available as a separate property and if so then add it.
822b0daa853SStephen Hanson 	 */
823*da40b264SAlex Wilson 	if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID, &serial) != 0) {
824b0daa853SStephen Hanson 		serial = (char *)cfgstrprop_lookup(croot, path,
825b0daa853SStephen Hanson 		    FM_FMRI_HC_SERIAL_ID);
826b0daa853SStephen Hanson 		if (serial != NULL)
827*da40b264SAlex Wilson 			(void) nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID,
828b0daa853SStephen Hanson 			    serial);
829b0daa853SStephen Hanson 	}
830b0daa853SStephen Hanson 
831*da40b264SAlex Wilson 	*fmrip = fmri;
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate /*
8357c478bd9Sstevel@tonic-gate  * platform_get_files -- return names of all files we should load
8367c478bd9Sstevel@tonic-gate  *
8377c478bd9Sstevel@tonic-gate  * search directories in dirname[] for all files with names ending with the
8387c478bd9Sstevel@tonic-gate  * substring fnstr.  dirname[] should be a NULL-terminated array.  fnstr
8397c478bd9Sstevel@tonic-gate  * may be set to "*" to indicate all files in a directory.
8407c478bd9Sstevel@tonic-gate  *
8417c478bd9Sstevel@tonic-gate  * if nodups is non-zero, then the first file of a given name found is
8427c478bd9Sstevel@tonic-gate  * the only file added to the list of names.  for example if nodups is
8437c478bd9Sstevel@tonic-gate  * set and we're looking for .efts, and find a pci.eft in the dirname[0],
8447c478bd9Sstevel@tonic-gate  * then no pci.eft found in any of the other dirname[] entries will be
8457c478bd9Sstevel@tonic-gate  * included in the final list of names.
8467c478bd9Sstevel@tonic-gate  *
8477c478bd9Sstevel@tonic-gate  * this routine doesn't return NULL, even if no files are found (in that
8487c478bd9Sstevel@tonic-gate  * case, a char ** is returned with the first element NULL).
8497c478bd9Sstevel@tonic-gate  */
8507c478bd9Sstevel@tonic-gate static char **
platform_get_files(const char * dirname[],const char * fnstr,int nodups)8517c478bd9Sstevel@tonic-gate platform_get_files(const char *dirname[], const char *fnstr, int nodups)
8527c478bd9Sstevel@tonic-gate {
8537c478bd9Sstevel@tonic-gate 	DIR *dirp;
8547c478bd9Sstevel@tonic-gate 	struct dirent *dp;
8557c478bd9Sstevel@tonic-gate 	struct lut *foundnames = NULL;
8567c478bd9Sstevel@tonic-gate 	char **files = NULL;	/* char * array of filenames found */
8577c478bd9Sstevel@tonic-gate 	int nfiles = 0;		/* files found so far */
8587c478bd9Sstevel@tonic-gate 	int slots = 0;		/* char * slots allocated in files */
8597c478bd9Sstevel@tonic-gate 	size_t fnlen, d_namelen;
8607c478bd9Sstevel@tonic-gate 	size_t totlen;
8617c478bd9Sstevel@tonic-gate 	int i;
8627c478bd9Sstevel@tonic-gate 	static char *nullav;
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 	ASSERT(fnstr != NULL);
8657c478bd9Sstevel@tonic-gate 	fnlen = strlen(fnstr);
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 	for (i = 0; dirname[i] != NULL; i++) {
868f6e214c7SGavin Maltby 		out(O_VERB, "Looking for %s files in %s", fnstr, dirname[i]);
8697c478bd9Sstevel@tonic-gate 		if ((dirp = opendir(dirname[i])) == NULL) {
8707c478bd9Sstevel@tonic-gate 			out(O_DEBUG|O_SYS,
8717c478bd9Sstevel@tonic-gate 			    "platform_get_files: opendir failed for %s",
8727c478bd9Sstevel@tonic-gate 			    dirname[i]);
8737c478bd9Sstevel@tonic-gate 			continue;
8747c478bd9Sstevel@tonic-gate 		}
8757c478bd9Sstevel@tonic-gate 		while ((dp = readdir(dirp)) != NULL) {
8767c478bd9Sstevel@tonic-gate 			if ((fnlen == 1 && *fnstr == '*') ||
8777c478bd9Sstevel@tonic-gate 			    ((d_namelen = strlen(dp->d_name)) >= fnlen &&
8787c478bd9Sstevel@tonic-gate 			    strncmp(dp->d_name + d_namelen - fnlen,
8797c478bd9Sstevel@tonic-gate 			    fnstr, fnlen) == 0)) {
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate 				if (nodups != 0) {
8827c478bd9Sstevel@tonic-gate 					const char *snm = stable(dp->d_name);
8837c478bd9Sstevel@tonic-gate 
8847c478bd9Sstevel@tonic-gate 					if (lut_lookup(foundnames,
8857c478bd9Sstevel@tonic-gate 					    (void *)snm,
8867c478bd9Sstevel@tonic-gate 					    NULL) != NULL) {
887f6e214c7SGavin Maltby 						out(O_VERB,
8887c478bd9Sstevel@tonic-gate 						    "platform_get_files: "
8897c478bd9Sstevel@tonic-gate 						    "skipping repeated name "
8907c478bd9Sstevel@tonic-gate 						    "%s/%s",
8917c478bd9Sstevel@tonic-gate 						    dirname[i],
8927c478bd9Sstevel@tonic-gate 						    snm);
8937c478bd9Sstevel@tonic-gate 						continue;
8947c478bd9Sstevel@tonic-gate 					}
8957c478bd9Sstevel@tonic-gate 					foundnames = lut_add(foundnames,
8967c478bd9Sstevel@tonic-gate 					    (void *)snm,
8977c478bd9Sstevel@tonic-gate 					    (void *)snm,
8987c478bd9Sstevel@tonic-gate 					    NULL);
8997c478bd9Sstevel@tonic-gate 				}
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 				if (nfiles > slots - 2) {
9027c478bd9Sstevel@tonic-gate 					/* allocate ten more slots */
9037c478bd9Sstevel@tonic-gate 					slots += 10;
9047c478bd9Sstevel@tonic-gate 					files = (char **)REALLOC(files,
90524db4641Seschrock 					    slots * sizeof (char *));
9067c478bd9Sstevel@tonic-gate 				}
9077c478bd9Sstevel@tonic-gate 				/* prepend directory name and / */
9087c478bd9Sstevel@tonic-gate 				totlen = strlen(dirname[i]) + 1;
9097c478bd9Sstevel@tonic-gate 				totlen += strlen(dp->d_name) + 1;
9107c478bd9Sstevel@tonic-gate 				files[nfiles] = MALLOC(totlen);
911f6e214c7SGavin Maltby 				out(O_VERB, "File %d: \"%s/%s\"", nfiles,
9127aec1d6eScindi 				    dirname[i], dp->d_name);
9137c478bd9Sstevel@tonic-gate 				(void) snprintf(files[nfiles++], totlen,
9147c478bd9Sstevel@tonic-gate 				    "%s/%s", dirname[i], dp->d_name);
9157c478bd9Sstevel@tonic-gate 			}
9167c478bd9Sstevel@tonic-gate 		}
9177c478bd9Sstevel@tonic-gate 		(void) closedir(dirp);
9187c478bd9Sstevel@tonic-gate 	}
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 	if (foundnames != NULL)
9217c478bd9Sstevel@tonic-gate 		lut_free(foundnames, NULL, NULL);
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 	if (nfiles == 0)
9247c478bd9Sstevel@tonic-gate 		return (&nullav);
9257c478bd9Sstevel@tonic-gate 
9267c478bd9Sstevel@tonic-gate 	files[nfiles] = NULL;
9277c478bd9Sstevel@tonic-gate 	return (files);
9287c478bd9Sstevel@tonic-gate }
9297c478bd9Sstevel@tonic-gate 
9303e8d8e18Sdb /*
9313e8d8e18Sdb  * search for files in a standard set of directories
9323e8d8e18Sdb  */
9333e8d8e18Sdb static char **
platform_get_files_stddirs(char * fname,int nodups)9343e8d8e18Sdb platform_get_files_stddirs(char *fname, int nodups)
9353e8d8e18Sdb {
9363e8d8e18Sdb 	const char *dirlist[4];
9373e8d8e18Sdb 	char **flist;
9383e8d8e18Sdb 	char *eftgendir, *eftmachdir, *eftplatdir;
9393e8d8e18Sdb 
9403e8d8e18Sdb 	eftgendir = MALLOC(MAXPATHLEN);
9413e8d8e18Sdb 	eftmachdir = MALLOC(MAXPATHLEN);
9423e8d8e18Sdb 	eftplatdir = MALLOC(MAXPATHLEN);
9433e8d8e18Sdb 
9443e8d8e18Sdb 	/* Generic files that apply to any machine */
9453e8d8e18Sdb 	(void) snprintf(eftgendir, MAXPATHLEN, "%s/usr/lib/fm/eft", Root);
9463e8d8e18Sdb 
9473e8d8e18Sdb 	(void) snprintf(eftmachdir,
9483e8d8e18Sdb 	    MAXPATHLEN, "%s/usr/platform/%s/lib/fm/eft", Root, Mach);
9493e8d8e18Sdb 
9503e8d8e18Sdb 	(void) snprintf(eftplatdir,
9513e8d8e18Sdb 	    MAXPATHLEN, "%s/usr/platform/%s/lib/fm/eft", Root, Plat);
9523e8d8e18Sdb 
9533e8d8e18Sdb 	dirlist[0] = eftplatdir;
9543e8d8e18Sdb 	dirlist[1] = eftmachdir;
9553e8d8e18Sdb 	dirlist[2] = eftgendir;
9563e8d8e18Sdb 	dirlist[3] = NULL;
9573e8d8e18Sdb 
9583e8d8e18Sdb 	flist = platform_get_files(dirlist, fname, nodups);
9593e8d8e18Sdb 
9603e8d8e18Sdb 	FREE(eftplatdir);
9613e8d8e18Sdb 	FREE(eftmachdir);
9623e8d8e18Sdb 	FREE(eftgendir);
9633e8d8e18Sdb 
9643e8d8e18Sdb 	return (flist);
9653e8d8e18Sdb }
9663e8d8e18Sdb 
9677c478bd9Sstevel@tonic-gate /*
9687c478bd9Sstevel@tonic-gate  * platform_run_poller -- execute a poller
9697c478bd9Sstevel@tonic-gate  *
9707c478bd9Sstevel@tonic-gate  * when eft needs to know if a polled ereport exists this routine
9717c478bd9Sstevel@tonic-gate  * is called so the poller code may be run in a platform-specific way.
9727c478bd9Sstevel@tonic-gate  * there's no return value from this routine -- either the polled ereport
9737c478bd9Sstevel@tonic-gate  * is generated (and delivered *before* this routine returns) or not.
9747c478bd9Sstevel@tonic-gate  * any errors, like "poller unknown" are considered platform-specific
9757c478bd9Sstevel@tonic-gate  * should be handled here rather than passing an error back up.
9767c478bd9Sstevel@tonic-gate  */
9777c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9787c478bd9Sstevel@tonic-gate void
platform_run_poller(const char * poller)9797c478bd9Sstevel@tonic-gate platform_run_poller(const char *poller)
9807c478bd9Sstevel@tonic-gate {
9817c478bd9Sstevel@tonic-gate }
9827c478bd9Sstevel@tonic-gate 
9837c478bd9Sstevel@tonic-gate /*
9847c478bd9Sstevel@tonic-gate  * fork and execve path with argument array argv and environment array
9857c478bd9Sstevel@tonic-gate  * envp.  data from stdout and stderr are placed in outbuf and errbuf,
9867c478bd9Sstevel@tonic-gate  * respectively.
9877c478bd9Sstevel@tonic-gate  *
9887c478bd9Sstevel@tonic-gate  * see execve(2) for more descriptions for path, argv and envp.
9897c478bd9Sstevel@tonic-gate  */
9907c478bd9Sstevel@tonic-gate static int
forkandexecve(const char * path,char * const argv[],char * const envp[],char * outbuf,size_t outbuflen,char * errbuf,size_t errbuflen)9917c478bd9Sstevel@tonic-gate forkandexecve(const char *path, char *const argv[], char *const envp[],
9927c478bd9Sstevel@tonic-gate 	char *outbuf, size_t outbuflen, char *errbuf, size_t errbuflen)
9937c478bd9Sstevel@tonic-gate {
9947c478bd9Sstevel@tonic-gate 	pid_t pid;
9957c478bd9Sstevel@tonic-gate 	int outpipe[2], errpipe[2];
9967c478bd9Sstevel@tonic-gate 	int rt = 0;
9977c478bd9Sstevel@tonic-gate 
9987c478bd9Sstevel@tonic-gate 	/*
9997c478bd9Sstevel@tonic-gate 	 * run the cmd and see if it failed.  this function is *not* a
10007c478bd9Sstevel@tonic-gate 	 * generic command runner -- we depend on some knowledge we
10017c478bd9Sstevel@tonic-gate 	 * have about the commands we run.  first of all, we expect
10027c478bd9Sstevel@tonic-gate 	 * errors to spew something to stdout, and that something is
10037c478bd9Sstevel@tonic-gate 	 * typically short enough to fit into a pipe so we can wait()
10047c478bd9Sstevel@tonic-gate 	 * for the command to complete and then fetch the error text
10057c478bd9Sstevel@tonic-gate 	 * from the pipe.
10067c478bd9Sstevel@tonic-gate 	 */
10077c478bd9Sstevel@tonic-gate 	if (pipe(outpipe) < 0)
10087c478bd9Sstevel@tonic-gate 		if (strlcat(errbuf, ": pipe(outpipe) failed",
100924db4641Seschrock 		    errbuflen) >= errbuflen)
10107c478bd9Sstevel@tonic-gate 			return (1);
10117c478bd9Sstevel@tonic-gate 	if (pipe(errpipe) < 0)
10127c478bd9Sstevel@tonic-gate 		if (strlcat(errbuf, ": pipe(errpipe) failed",
101324db4641Seschrock 		    errbuflen) >= errbuflen)
10147c478bd9Sstevel@tonic-gate 			return (1);
10157c478bd9Sstevel@tonic-gate 
101624db4641Seschrock 	if ((pid = fork()) < 0) {
10177c478bd9Sstevel@tonic-gate 		rt = (int)strlcat(errbuf, ": fork() failed", errbuflen);
101824db4641Seschrock 	} else if (pid) {
10197c478bd9Sstevel@tonic-gate 		int wstat, count;
10207c478bd9Sstevel@tonic-gate 
10217c478bd9Sstevel@tonic-gate 		/* parent */
10227c478bd9Sstevel@tonic-gate 		(void) close(errpipe[1]);
10237c478bd9Sstevel@tonic-gate 		(void) close(outpipe[1]);
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 		/* PHASE2 need to guard against hang in child? */
10267c478bd9Sstevel@tonic-gate 		if (waitpid(pid, &wstat, 0) < 0)
10277c478bd9Sstevel@tonic-gate 			if (strlcat(errbuf, ": waitpid() failed",
102824db4641Seschrock 			    errbuflen) >= errbuflen)
10297c478bd9Sstevel@tonic-gate 				return (1);
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 		/* check for stderr contents */
10327c478bd9Sstevel@tonic-gate 		if (ioctl(errpipe[0], FIONREAD, &count) >= 0 && count) {
10337c478bd9Sstevel@tonic-gate 			if (read(errpipe[0], errbuf, errbuflen) <= 0) {
10347c478bd9Sstevel@tonic-gate 				/*
10357c478bd9Sstevel@tonic-gate 				 * read failed even though ioctl indicated
10367c478bd9Sstevel@tonic-gate 				 * that nonzero bytes were available for
10377c478bd9Sstevel@tonic-gate 				 * reading
10387c478bd9Sstevel@tonic-gate 				 */
10397c478bd9Sstevel@tonic-gate 				if (strlcat(errbuf, ": read(errpipe) failed",
104024db4641Seschrock 				    errbuflen) >= errbuflen)
10417c478bd9Sstevel@tonic-gate 					return (1);
10427c478bd9Sstevel@tonic-gate 			}
10437c478bd9Sstevel@tonic-gate 			/*
10447c478bd9Sstevel@tonic-gate 			 * handle case where errbuf is not properly
10457c478bd9Sstevel@tonic-gate 			 * terminated
10467c478bd9Sstevel@tonic-gate 			 */
10477c478bd9Sstevel@tonic-gate 			if (count > errbuflen - 1)
10487c478bd9Sstevel@tonic-gate 				count = errbuflen - 1;
10497c478bd9Sstevel@tonic-gate 			if (errbuf[count - 1] != '\0' &&
10507c478bd9Sstevel@tonic-gate 			    errbuf[count - 1] != '\n')
10517c478bd9Sstevel@tonic-gate 				errbuf[count] = '\0';
10527c478bd9Sstevel@tonic-gate 		} else if (WIFSIGNALED(wstat))
10537c478bd9Sstevel@tonic-gate 			if (strlcat(errbuf, ": signaled",
105424db4641Seschrock 			    errbuflen) >= errbuflen)
10557c478bd9Sstevel@tonic-gate 				return (1);
10567c478bd9Sstevel@tonic-gate 		else if (WIFEXITED(wstat) && WEXITSTATUS(wstat))
10577c478bd9Sstevel@tonic-gate 			if (strlcat(errbuf, ": abnormal exit",
105824db4641Seschrock 			    errbuflen) >= errbuflen)
10597c478bd9Sstevel@tonic-gate 				return (1);
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate 		/* check for stdout contents */
10627c478bd9Sstevel@tonic-gate 		if (ioctl(outpipe[0], FIONREAD, &count) >= 0 && count) {
10637c478bd9Sstevel@tonic-gate 			if (read(outpipe[0], outbuf, outbuflen) <= 0) {
10647c478bd9Sstevel@tonic-gate 				/*
10657c478bd9Sstevel@tonic-gate 				 * read failed even though ioctl indicated
10667c478bd9Sstevel@tonic-gate 				 * that nonzero bytes were available for
10677c478bd9Sstevel@tonic-gate 				 * reading
10687c478bd9Sstevel@tonic-gate 				 */
10697c478bd9Sstevel@tonic-gate 				if (strlcat(errbuf, ": read(outpipe) failed",
107024db4641Seschrock 				    errbuflen) >= errbuflen)
10717c478bd9Sstevel@tonic-gate 					return (1);
10727c478bd9Sstevel@tonic-gate 			}
10737c478bd9Sstevel@tonic-gate 			/*
10747c478bd9Sstevel@tonic-gate 			 * handle case where outbuf is not properly
10757c478bd9Sstevel@tonic-gate 			 * terminated
10767c478bd9Sstevel@tonic-gate 			 */
10777c478bd9Sstevel@tonic-gate 			if (count > outbuflen - 1)
10787c478bd9Sstevel@tonic-gate 				count = outbuflen - 1;
10797c478bd9Sstevel@tonic-gate 			if (outbuf[count - 1] != '\0' &&
10807c478bd9Sstevel@tonic-gate 			    outbuf[count - 1] != '\n')
10817c478bd9Sstevel@tonic-gate 				outbuf[count] = '\0';
10827c478bd9Sstevel@tonic-gate 		}
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 		(void) close(errpipe[0]);
10857c478bd9Sstevel@tonic-gate 		(void) close(outpipe[0]);
10867c478bd9Sstevel@tonic-gate 	} else {
10877c478bd9Sstevel@tonic-gate 		/* child */
10887c478bd9Sstevel@tonic-gate 		(void) dup2(errpipe[1], fileno(stderr));
10897c478bd9Sstevel@tonic-gate 		(void) close(errpipe[0]);
10907c478bd9Sstevel@tonic-gate 		(void) dup2(outpipe[1], fileno(stdout));
10917c478bd9Sstevel@tonic-gate 		(void) close(outpipe[0]);
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 		if (execve(path, argv, envp))
10947c478bd9Sstevel@tonic-gate 			perror(path);
10957c478bd9Sstevel@tonic-gate 		_exit(1);
10967c478bd9Sstevel@tonic-gate 	}
10977c478bd9Sstevel@tonic-gate 
10987c478bd9Sstevel@tonic-gate 	return (rt);
10997c478bd9Sstevel@tonic-gate }
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate #define	MAXDIGITIDX	23
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate static int
arglist2argv(struct node * np,struct lut ** globals,struct config * croot,struct arrow * arrowp,char *** argv,int * argc,int * argvlen)11047c478bd9Sstevel@tonic-gate arglist2argv(struct node *np, struct lut **globals, struct config *croot,
11057c478bd9Sstevel@tonic-gate 	struct arrow *arrowp, char ***argv, int *argc, int *argvlen)
11067c478bd9Sstevel@tonic-gate {
11077c478bd9Sstevel@tonic-gate 	struct node *namep;
11087c478bd9Sstevel@tonic-gate 	char numbuf[MAXDIGITIDX + 1];
11097c478bd9Sstevel@tonic-gate 	char *numstr, *nullbyte;
11107c478bd9Sstevel@tonic-gate 	char *addthisarg = NULL;
11117c478bd9Sstevel@tonic-gate 
11127c478bd9Sstevel@tonic-gate 	if (np == NULL)
11137c478bd9Sstevel@tonic-gate 		return (0);
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate 	switch (np->t) {
11167c478bd9Sstevel@tonic-gate 	case T_QUOTE:
11177c478bd9Sstevel@tonic-gate 		addthisarg = STRDUP(np->u.func.s);
11187c478bd9Sstevel@tonic-gate 		break;
11197c478bd9Sstevel@tonic-gate 	case T_LIST:
11207c478bd9Sstevel@tonic-gate 		if (arglist2argv(np->u.expr.left, globals, croot, arrowp,
112124db4641Seschrock 		    argv, argc, argvlen))
11227c478bd9Sstevel@tonic-gate 			return (1);
11237c478bd9Sstevel@tonic-gate 		/*
11247c478bd9Sstevel@tonic-gate 		 * only leftmost element of a list can provide the command
11257c478bd9Sstevel@tonic-gate 		 * name (after which *argc becomes 1)
11267c478bd9Sstevel@tonic-gate 		 */
11277c478bd9Sstevel@tonic-gate 		ASSERT(*argc > 0);
11287c478bd9Sstevel@tonic-gate 		if (arglist2argv(np->u.expr.right, globals, croot, arrowp,
112924db4641Seschrock 		    argv, argc, argvlen))
11307c478bd9Sstevel@tonic-gate 			return (1);
11317c478bd9Sstevel@tonic-gate 		break;
11327c478bd9Sstevel@tonic-gate 	case T_FUNC:
11337c478bd9Sstevel@tonic-gate 	case T_GLOBID:
11347c478bd9Sstevel@tonic-gate 	case T_ASSIGN:
11357c478bd9Sstevel@tonic-gate 	case T_CONDIF:
11367c478bd9Sstevel@tonic-gate 	case T_CONDELSE:
11377c478bd9Sstevel@tonic-gate 	case T_EQ:
11387c478bd9Sstevel@tonic-gate 	case T_NE:
11397c478bd9Sstevel@tonic-gate 	case T_LT:
11407c478bd9Sstevel@tonic-gate 	case T_LE:
11417c478bd9Sstevel@tonic-gate 	case T_GT:
11427c478bd9Sstevel@tonic-gate 	case T_GE:
11437c478bd9Sstevel@tonic-gate 	case T_BITAND:
11447c478bd9Sstevel@tonic-gate 	case T_BITOR:
11457c478bd9Sstevel@tonic-gate 	case T_BITXOR:
11467c478bd9Sstevel@tonic-gate 	case T_BITNOT:
11477c478bd9Sstevel@tonic-gate 	case T_LSHIFT:
11487c478bd9Sstevel@tonic-gate 	case T_RSHIFT:
11497c478bd9Sstevel@tonic-gate 	case T_AND:
11507c478bd9Sstevel@tonic-gate 	case T_OR:
11517c478bd9Sstevel@tonic-gate 	case T_NOT:
11527c478bd9Sstevel@tonic-gate 	case T_ADD:
11537c478bd9Sstevel@tonic-gate 	case T_SUB:
11547c478bd9Sstevel@tonic-gate 	case T_MUL:
11557c478bd9Sstevel@tonic-gate 	case T_DIV:
11567c478bd9Sstevel@tonic-gate 	case T_MOD: {
11577c478bd9Sstevel@tonic-gate 		struct evalue value;
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate 		if (!eval_expr(np, NULL, NULL, globals, croot, arrowp,
116024db4641Seschrock 		    0, &value))
11617c478bd9Sstevel@tonic-gate 			return (1);
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 		switch (value.t) {
11647c478bd9Sstevel@tonic-gate 		case UINT64:
11657c478bd9Sstevel@tonic-gate 			numbuf[MAXDIGITIDX] = '\0';
11667c478bd9Sstevel@tonic-gate 			nullbyte = &numbuf[MAXDIGITIDX];
11677c478bd9Sstevel@tonic-gate 			numstr = ulltostr(value.v, nullbyte);
11687c478bd9Sstevel@tonic-gate 			addthisarg = STRDUP(numstr);
11697c478bd9Sstevel@tonic-gate 			break;
11707c478bd9Sstevel@tonic-gate 		case STRING:
117180ab886dSwesolows 			addthisarg = STRDUP((const char *)(uintptr_t)value.v);
11727c478bd9Sstevel@tonic-gate 			break;
11737c478bd9Sstevel@tonic-gate 		case NODEPTR :
117480ab886dSwesolows 			namep = (struct node *)(uintptr_t)value.v;
11757c478bd9Sstevel@tonic-gate 			addthisarg = ipath2str(NULL, ipath(namep));
11767c478bd9Sstevel@tonic-gate 			break;
11777c478bd9Sstevel@tonic-gate 		default:
11787c478bd9Sstevel@tonic-gate 			out(O_ERR,
11797c478bd9Sstevel@tonic-gate 			    "call: arglist2argv: unexpected result from"
11807c478bd9Sstevel@tonic-gate 			    " operation %s",
11817c478bd9Sstevel@tonic-gate 			    ptree_nodetype2str(np->t));
11827c478bd9Sstevel@tonic-gate 			return (1);
11837c478bd9Sstevel@tonic-gate 		}
11847c478bd9Sstevel@tonic-gate 		break;
11857c478bd9Sstevel@tonic-gate 	}
11867c478bd9Sstevel@tonic-gate 	case T_NUM:
11877c478bd9Sstevel@tonic-gate 	case T_TIMEVAL:
11887c478bd9Sstevel@tonic-gate 		numbuf[MAXDIGITIDX] = '\0';
11897c478bd9Sstevel@tonic-gate 		nullbyte = &numbuf[MAXDIGITIDX];
11907c478bd9Sstevel@tonic-gate 		numstr = ulltostr(np->u.ull, nullbyte);
11917c478bd9Sstevel@tonic-gate 		addthisarg = STRDUP(numstr);
11927c478bd9Sstevel@tonic-gate 		break;
11937c478bd9Sstevel@tonic-gate 	case T_NAME:
11947c478bd9Sstevel@tonic-gate 		addthisarg = ipath2str(NULL, ipath(np));
11957c478bd9Sstevel@tonic-gate 		break;
11967c478bd9Sstevel@tonic-gate 	case T_EVENT:
11977c478bd9Sstevel@tonic-gate 		addthisarg = ipath2str(np->u.event.ename->u.name.s,
11987c478bd9Sstevel@tonic-gate 		    ipath(np->u.event.epname));
11997c478bd9Sstevel@tonic-gate 		break;
12007c478bd9Sstevel@tonic-gate 	default:
12017c478bd9Sstevel@tonic-gate 		out(O_ERR, "call: arglist2argv: node type %s is unsupported",
12027c478bd9Sstevel@tonic-gate 		    ptree_nodetype2str(np->t));
12037c478bd9Sstevel@tonic-gate 		return (1);
12047c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
12057c478bd9Sstevel@tonic-gate 		break;
12067c478bd9Sstevel@tonic-gate 	}
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate 	if (*argc == 0 && addthisarg != NULL) {
12097c478bd9Sstevel@tonic-gate 		/*
12107c478bd9Sstevel@tonic-gate 		 * first argument added is the command name.
12117c478bd9Sstevel@tonic-gate 		 */
12127c478bd9Sstevel@tonic-gate 		char **files;
12137c478bd9Sstevel@tonic-gate 
12143e8d8e18Sdb 		files = platform_get_files_stddirs(addthisarg, 0);
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate 		/* do not proceed if number of files found != 1 */
12177c478bd9Sstevel@tonic-gate 		if (files[0] == NULL)
12187c478bd9Sstevel@tonic-gate 			out(O_DIE, "call: function %s not found", addthisarg);
12197c478bd9Sstevel@tonic-gate 		if (files[1] != NULL)
12207c478bd9Sstevel@tonic-gate 			out(O_DIE, "call: multiple functions %s found",
12217c478bd9Sstevel@tonic-gate 			    addthisarg);
12227c478bd9Sstevel@tonic-gate 		FREE(addthisarg);
12237c478bd9Sstevel@tonic-gate 
12247c478bd9Sstevel@tonic-gate 		addthisarg = STRDUP(files[0]);
12257c478bd9Sstevel@tonic-gate 		FREE(files[0]);
12267c478bd9Sstevel@tonic-gate 		FREE(files);
12277c478bd9Sstevel@tonic-gate 	}
12287c478bd9Sstevel@tonic-gate 
12297c478bd9Sstevel@tonic-gate 	if (addthisarg != NULL) {
12307c478bd9Sstevel@tonic-gate 		if (*argc >= *argvlen - 2) {
12317c478bd9Sstevel@tonic-gate 			/*
12327c478bd9Sstevel@tonic-gate 			 * make sure argv is long enough so it has a
12337c478bd9Sstevel@tonic-gate 			 * terminating element set to NULL
12347c478bd9Sstevel@tonic-gate 			 */
12357c478bd9Sstevel@tonic-gate 			*argvlen += 10;
12367c478bd9Sstevel@tonic-gate 			*argv = (char **)REALLOC(*argv,
123724db4641Seschrock 			    sizeof (char *) * *argvlen);
12387c478bd9Sstevel@tonic-gate 		}
12397c478bd9Sstevel@tonic-gate 		(*argv)[*argc] = addthisarg;
12407c478bd9Sstevel@tonic-gate 		(*argc)++;
12417c478bd9Sstevel@tonic-gate 		(*argv)[*argc] = NULL;
12427c478bd9Sstevel@tonic-gate 	}
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 	return (0);
12457c478bd9Sstevel@tonic-gate }
12467c478bd9Sstevel@tonic-gate 
12477c478bd9Sstevel@tonic-gate static int
generate_envp(struct arrow * arrowp,char *** envp,int * envc,int * envplen)12487c478bd9Sstevel@tonic-gate generate_envp(struct arrow *arrowp, char ***envp, int *envc, int *envplen)
12497c478bd9Sstevel@tonic-gate {
12507c478bd9Sstevel@tonic-gate 	char *envnames[] = { "EFT_FROM_EVENT", "EFT_TO_EVENT",
12517c478bd9Sstevel@tonic-gate 			    "EFT_FILE", "EFT_LINE", NULL };
12527c478bd9Sstevel@tonic-gate 	char *envvalues[4];
12537c478bd9Sstevel@tonic-gate 	char *none = "(none)";
12547c478bd9Sstevel@tonic-gate 	size_t elen;
12557c478bd9Sstevel@tonic-gate 	int i;
12567c478bd9Sstevel@tonic-gate 
12577c478bd9Sstevel@tonic-gate 	*envc = 4;
12587c478bd9Sstevel@tonic-gate 
12597c478bd9Sstevel@tonic-gate 	/*
12607c478bd9Sstevel@tonic-gate 	 * make sure envp is long enough so it has a terminating element
12617c478bd9Sstevel@tonic-gate 	 * set to NULL
12627c478bd9Sstevel@tonic-gate 	 */
12637c478bd9Sstevel@tonic-gate 	*envplen = *envc + 1;
12647c478bd9Sstevel@tonic-gate 	*envp = (char **)MALLOC(sizeof (char *) * *envplen);
12657c478bd9Sstevel@tonic-gate 
12667c478bd9Sstevel@tonic-gate 	envvalues[0] = ipath2str(
12677c478bd9Sstevel@tonic-gate 	    arrowp->tail->myevent->enode->u.event.ename->u.name.s,
12687c478bd9Sstevel@tonic-gate 	    arrowp->tail->myevent->ipp);
12697c478bd9Sstevel@tonic-gate 	envvalues[1] = ipath2str(
12707c478bd9Sstevel@tonic-gate 	    arrowp->head->myevent->enode->u.event.ename->u.name.s,
12717c478bd9Sstevel@tonic-gate 	    arrowp->head->myevent->ipp);
12727c478bd9Sstevel@tonic-gate 
12737c478bd9Sstevel@tonic-gate 	if (arrowp->head->myevent->enode->file == NULL) {
12747c478bd9Sstevel@tonic-gate 		envvalues[2] = STRDUP(none);
12757c478bd9Sstevel@tonic-gate 		envvalues[3] = STRDUP(none);
12767c478bd9Sstevel@tonic-gate 	} else {
12777c478bd9Sstevel@tonic-gate 		envvalues[2] = STRDUP(arrowp->head->myevent->enode->file);
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate 		/* large enough for max int */
12807c478bd9Sstevel@tonic-gate 		envvalues[3] = MALLOC(sizeof (char) * 25);
12817c478bd9Sstevel@tonic-gate 		(void) snprintf(envvalues[3], sizeof (envvalues[3]), "%d",
128224db4641Seschrock 		    arrowp->head->myevent->enode->line);
12837c478bd9Sstevel@tonic-gate 	}
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate 	for (i = 0; envnames[i] != NULL && i < *envc; i++) {
12867c478bd9Sstevel@tonic-gate 		elen = strlen(envnames[i]) + strlen(envvalues[i]) + 2;
12877c478bd9Sstevel@tonic-gate 		(*envp)[i] = MALLOC(elen);
12887c478bd9Sstevel@tonic-gate 		(void) snprintf((*envp)[i], elen, "%s=%s",
12897c478bd9Sstevel@tonic-gate 		    envnames[i], envvalues[i]);
12907c478bd9Sstevel@tonic-gate 		FREE(envvalues[i]);
12917c478bd9Sstevel@tonic-gate 	}
12927c478bd9Sstevel@tonic-gate 	(*envp)[*envc] = NULL;
12937c478bd9Sstevel@tonic-gate 
12947c478bd9Sstevel@tonic-gate 	return (0);
12957c478bd9Sstevel@tonic-gate }
12967c478bd9Sstevel@tonic-gate 
12977c478bd9Sstevel@tonic-gate /*
12987c478bd9Sstevel@tonic-gate  * platform_call -- call an external function
12997c478bd9Sstevel@tonic-gate  *
13007c478bd9Sstevel@tonic-gate  * evaluate a user-defined function and place result in valuep.  return 0
13017c478bd9Sstevel@tonic-gate  * if function evaluation was successful; 1 if otherwise.
13027c478bd9Sstevel@tonic-gate  */
13037c478bd9Sstevel@tonic-gate int
platform_call(struct node * np,struct lut ** globals,struct config * croot,struct arrow * arrowp,struct evalue * valuep)13047c478bd9Sstevel@tonic-gate platform_call(struct node *np, struct lut **globals, struct config *croot,
13057c478bd9Sstevel@tonic-gate 	struct arrow *arrowp, struct evalue *valuep)
13067c478bd9Sstevel@tonic-gate {
13077c478bd9Sstevel@tonic-gate 	/*
13087c478bd9Sstevel@tonic-gate 	 * use rather short buffers.  only the first string on outbuf[] is
13097c478bd9Sstevel@tonic-gate 	 * taken as output from the called function.  any message in
13107c478bd9Sstevel@tonic-gate 	 * errbuf[] is echoed out as an error message.
13117c478bd9Sstevel@tonic-gate 	 */
13127c478bd9Sstevel@tonic-gate 	char outbuf[256], errbuf[512];
13133e8d8e18Sdb 	struct stat buf;
13147c478bd9Sstevel@tonic-gate 	char **argv, **envp;
13157c478bd9Sstevel@tonic-gate 	int argc, argvlen, envc, envplen;
13167c478bd9Sstevel@tonic-gate 	int i, ret;
13177c478bd9Sstevel@tonic-gate 
13187c478bd9Sstevel@tonic-gate 	/*
13197c478bd9Sstevel@tonic-gate 	 * np is the argument list.  the user-defined function is the first
13207c478bd9Sstevel@tonic-gate 	 * element of the list.
13217c478bd9Sstevel@tonic-gate 	 */
13227c478bd9Sstevel@tonic-gate 	ASSERT(np->t == T_LIST);
13237c478bd9Sstevel@tonic-gate 
13247c478bd9Sstevel@tonic-gate 	argv = NULL;
13257c478bd9Sstevel@tonic-gate 	argc = 0;
13267c478bd9Sstevel@tonic-gate 	argvlen = 0;
13277c478bd9Sstevel@tonic-gate 	if (arglist2argv(np, globals, croot, arrowp, &argv, &argc, &argvlen) ||
13287c478bd9Sstevel@tonic-gate 	    argc == 0)
13297c478bd9Sstevel@tonic-gate 		return (1);
13307c478bd9Sstevel@tonic-gate 
13313e8d8e18Sdb 	/*
13323e8d8e18Sdb 	 * make sure program has executable bit set
13333e8d8e18Sdb 	 */
13343e8d8e18Sdb 	if (stat(argv[0], &buf) == 0) {
13353e8d8e18Sdb 		int exec_bit_set = 0;
13363e8d8e18Sdb 
13373e8d8e18Sdb 		if (buf.st_uid == geteuid() && buf.st_mode & S_IXUSR)
13383e8d8e18Sdb 			exec_bit_set = 1;
13393e8d8e18Sdb 		else if (buf.st_gid == getegid() && buf.st_mode & S_IXGRP)
13403e8d8e18Sdb 			exec_bit_set = 1;
13413e8d8e18Sdb 		else if (buf.st_mode & S_IXOTH)
13423e8d8e18Sdb 			exec_bit_set = 1;
13433e8d8e18Sdb 
13443e8d8e18Sdb 		if (exec_bit_set == 0)
13453e8d8e18Sdb 			out(O_DIE, "call: executable bit not set on %s",
13463e8d8e18Sdb 			    argv[0]);
13473e8d8e18Sdb 	} else {
13483e8d8e18Sdb 		out(O_DIE, "call: failure in stat(), errno = %d\n", errno);
13493e8d8e18Sdb 	}
13503e8d8e18Sdb 
13517c478bd9Sstevel@tonic-gate 	envp = NULL;
13527c478bd9Sstevel@tonic-gate 	envc = 0;
13537c478bd9Sstevel@tonic-gate 	envplen = 0;
13547c478bd9Sstevel@tonic-gate 	if (generate_envp(arrowp, &envp, &envc, &envplen))
13557c478bd9Sstevel@tonic-gate 		return (1);
13567c478bd9Sstevel@tonic-gate 
13577c478bd9Sstevel@tonic-gate 	outbuf[0] = '\0';
13587c478bd9Sstevel@tonic-gate 	errbuf[0] = '\0';
13597c478bd9Sstevel@tonic-gate 
13607c478bd9Sstevel@tonic-gate 	ret = forkandexecve((const char *) argv[0], (char *const *) argv,
136124db4641Seschrock 	    (char *const *) envp, outbuf, sizeof (outbuf),
136224db4641Seschrock 	    errbuf, sizeof (errbuf));
13637c478bd9Sstevel@tonic-gate 
13647c478bd9Sstevel@tonic-gate 	for (i = 0; i < envc; i++)
13657c478bd9Sstevel@tonic-gate 		FREE(envp[i]);
13667c478bd9Sstevel@tonic-gate 	if (envp)
13677c478bd9Sstevel@tonic-gate 		FREE(envp);
13687c478bd9Sstevel@tonic-gate 
13697c478bd9Sstevel@tonic-gate 	if (ret) {
13707c478bd9Sstevel@tonic-gate 		outfl(O_OK, np->file, np->line,
137124db4641Seschrock 		    "call: failure in fork + exec of %s", argv[0]);
13727c478bd9Sstevel@tonic-gate 	} else {
13737aec1d6eScindi 		char *ptr;
13747aec1d6eScindi 
13757aec1d6eScindi 		/* chomp the result */
13767aec1d6eScindi 		for (ptr = outbuf; *ptr; ptr++)
13777aec1d6eScindi 			if (*ptr == '\n' || *ptr == '\r') {
13787aec1d6eScindi 				*ptr = '\0';
13797aec1d6eScindi 				break;
13807aec1d6eScindi 			}
13817aec1d6eScindi 		valuep->t = STRING;
138280ab886dSwesolows 		valuep->v = (uintptr_t)stable(outbuf);
13837c478bd9Sstevel@tonic-gate 	}
13847c478bd9Sstevel@tonic-gate 
13857c478bd9Sstevel@tonic-gate 	if (errbuf[0] != '\0') {
13867c478bd9Sstevel@tonic-gate 		ret = 1;
13877c478bd9Sstevel@tonic-gate 		outfl(O_OK, np->file, np->line,
138824db4641Seschrock 		    "call: unexpected stderr output from %s: %s",
138924db4641Seschrock 		    argv[0], errbuf);
13907c478bd9Sstevel@tonic-gate 	}
13917c478bd9Sstevel@tonic-gate 
13927c478bd9Sstevel@tonic-gate 	for (i = 0; i < argc; i++)
13937c478bd9Sstevel@tonic-gate 		FREE(argv[i]);
13947c478bd9Sstevel@tonic-gate 	FREE(argv);
13957c478bd9Sstevel@tonic-gate 
13967c478bd9Sstevel@tonic-gate 	return (ret);
13977c478bd9Sstevel@tonic-gate }
13987c478bd9Sstevel@tonic-gate 
13997aec1d6eScindi /*
14007aec1d6eScindi  * platform_confcall -- call a configuration database function
14017aec1d6eScindi  *
14027aec1d6eScindi  * returns result in *valuep, return 0 on success
14037aec1d6eScindi  */
14047aec1d6eScindi /*ARGSUSED*/
14057aec1d6eScindi int
platform_confcall(struct node * np,struct lut ** globals,struct config * croot,struct arrow * arrowp,struct evalue * valuep)14067aec1d6eScindi platform_confcall(struct node *np, struct lut **globals, struct config *croot,
14077aec1d6eScindi 	struct arrow *arrowp, struct evalue *valuep)
14087aec1d6eScindi {
1409b7d3956bSstephh 	outfl(O_ALTFP|O_VERB, np->file, np->line, "unknown confcall");
14107aec1d6eScindi 	return (0);
14117aec1d6eScindi }
14127aec1d6eScindi 
14137c478bd9Sstevel@tonic-gate /*
14147c478bd9Sstevel@tonic-gate  * platform_get_eft_files -- return names of all eft files we should load
14157c478bd9Sstevel@tonic-gate  *
14167c478bd9Sstevel@tonic-gate  * this routine doesn't return NULL, even if no files are found (in that
14177c478bd9Sstevel@tonic-gate  * case, a char ** is returned with the first element NULL).
14187c478bd9Sstevel@tonic-gate  */
14197c478bd9Sstevel@tonic-gate char **
platform_get_eft_files(void)14207c478bd9Sstevel@tonic-gate platform_get_eft_files(void)
14217c478bd9Sstevel@tonic-gate {
14223e8d8e18Sdb 	return (platform_get_files_stddirs(".eft", 1));
14237c478bd9Sstevel@tonic-gate }
14247c478bd9Sstevel@tonic-gate 
14257c478bd9Sstevel@tonic-gate void
platform_free_eft_files(char ** flist)14267c478bd9Sstevel@tonic-gate platform_free_eft_files(char **flist)
14277c478bd9Sstevel@tonic-gate {
14287c478bd9Sstevel@tonic-gate 	char **f;
14297c478bd9Sstevel@tonic-gate 
14307c478bd9Sstevel@tonic-gate 	if (flist == NULL || *flist == NULL)
14317c478bd9Sstevel@tonic-gate 		return;	/* no files were found so we're done */
14327c478bd9Sstevel@tonic-gate 
14337c478bd9Sstevel@tonic-gate 	f = flist;
14347c478bd9Sstevel@tonic-gate 	while (*f != NULL) {
14357c478bd9Sstevel@tonic-gate 		FREE(*f);
14367c478bd9Sstevel@tonic-gate 		f++;
14377c478bd9Sstevel@tonic-gate 	}
14387c478bd9Sstevel@tonic-gate 	FREE(flist);
14397c478bd9Sstevel@tonic-gate }
14407c478bd9Sstevel@tonic-gate 
14417c478bd9Sstevel@tonic-gate static nvlist_t *payloadnvp = NULL;
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate void
platform_set_payloadnvp(nvlist_t * nvlp)14447c478bd9Sstevel@tonic-gate platform_set_payloadnvp(nvlist_t *nvlp)
14457c478bd9Sstevel@tonic-gate {
14467c478bd9Sstevel@tonic-gate 	/*
14477c478bd9Sstevel@tonic-gate 	 * cannot replace a non-NULL payloadnvp with a non-NULL nvlp
14487c478bd9Sstevel@tonic-gate 	 */
14497c478bd9Sstevel@tonic-gate 	ASSERT(payloadnvp != NULL ? nvlp == NULL : 1);
14507c478bd9Sstevel@tonic-gate 	payloadnvp = nvlp;
14517c478bd9Sstevel@tonic-gate }
14527c478bd9Sstevel@tonic-gate 
14537c478bd9Sstevel@tonic-gate /*
14547c478bd9Sstevel@tonic-gate  * given array notation in inputstr such as "foo[1]" or "foo [ 1 ]" (spaces
14557c478bd9Sstevel@tonic-gate  * allowed), figure out the array name and index.  return 0 if successful,
14567c478bd9Sstevel@tonic-gate  * nonzero if otherwise.
14577c478bd9Sstevel@tonic-gate  */
14587c478bd9Sstevel@tonic-gate static int
get_array_info(const char * inputstr,const char ** name,unsigned int * index)14597c478bd9Sstevel@tonic-gate get_array_info(const char *inputstr, const char **name, unsigned int *index)
14607c478bd9Sstevel@tonic-gate {
14617c478bd9Sstevel@tonic-gate 	char *indexptr, *indexend, *dupname, *endname;
14627c478bd9Sstevel@tonic-gate 
14637c478bd9Sstevel@tonic-gate 	if (strchr(inputstr, '[') == NULL)
14647c478bd9Sstevel@tonic-gate 		return (1);
14657c478bd9Sstevel@tonic-gate 
14667c478bd9Sstevel@tonic-gate 	dupname = STRDUP(inputstr);
14677c478bd9Sstevel@tonic-gate 	indexptr = strchr(dupname, '[');
14687c478bd9Sstevel@tonic-gate 	indexend = strchr(dupname, ']');
14697c478bd9Sstevel@tonic-gate 
14707c478bd9Sstevel@tonic-gate 	/*
14717c478bd9Sstevel@tonic-gate 	 * return if array notation is not complete or if index is negative
14727c478bd9Sstevel@tonic-gate 	 */
14737c478bd9Sstevel@tonic-gate 	if (indexend == NULL || indexptr >= indexend ||
14747c478bd9Sstevel@tonic-gate 	    strchr(indexptr, '-') != NULL) {
14757c478bd9Sstevel@tonic-gate 		FREE(dupname);
14767c478bd9Sstevel@tonic-gate 		return (1);
14777c478bd9Sstevel@tonic-gate 	}
14787c478bd9Sstevel@tonic-gate 
14797c478bd9Sstevel@tonic-gate 	/*
14807c478bd9Sstevel@tonic-gate 	 * search past any spaces between the name string and '['
14817c478bd9Sstevel@tonic-gate 	 */
14827c478bd9Sstevel@tonic-gate 	endname = indexptr;
14837c478bd9Sstevel@tonic-gate 	while (isspace(*(endname - 1)) && dupname < endname)
14847c478bd9Sstevel@tonic-gate 		endname--;
14857c478bd9Sstevel@tonic-gate 	*endname = '\0';
14867c478bd9Sstevel@tonic-gate 	ASSERT(dupname < endname);
14877c478bd9Sstevel@tonic-gate 
14887c478bd9Sstevel@tonic-gate 	/*
14897c478bd9Sstevel@tonic-gate 	 * search until indexptr points to the first digit and indexend
14907c478bd9Sstevel@tonic-gate 	 * points to the last digit
14917c478bd9Sstevel@tonic-gate 	 */
14927c478bd9Sstevel@tonic-gate 	while (!isdigit(*indexptr) && indexptr < indexend)
14937c478bd9Sstevel@tonic-gate 		indexptr++;
14947c478bd9Sstevel@tonic-gate 	while (!isdigit(*indexend) && indexptr <= indexend)
14957c478bd9Sstevel@tonic-gate 		indexend--;
14967c478bd9Sstevel@tonic-gate 
14977c478bd9Sstevel@tonic-gate 	*(indexend + 1) = '\0';
14987c478bd9Sstevel@tonic-gate 	*index = (unsigned int)atoi(indexptr);
14997c478bd9Sstevel@tonic-gate 
15007c478bd9Sstevel@tonic-gate 	*name = stable(dupname);
15017c478bd9Sstevel@tonic-gate 	FREE(dupname);
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate 	return (0);
15047c478bd9Sstevel@tonic-gate }
15057c478bd9Sstevel@tonic-gate 
15067aec1d6eScindi /*
15077aec1d6eScindi  * platform_payloadprop -- fetch a payload value
15087aec1d6eScindi  *
15097aec1d6eScindi  * XXX this function should be replaced and eval_func() should be
15107aec1d6eScindi  * XXX changed to use the more general platform_payloadprop_values().
15117aec1d6eScindi  */
15127c478bd9Sstevel@tonic-gate int
platform_payloadprop(struct node * np,struct evalue * valuep)15137c478bd9Sstevel@tonic-gate platform_payloadprop(struct node *np, struct evalue *valuep)
15147c478bd9Sstevel@tonic-gate {
15153e8d8e18Sdb 	nvlist_t *basenvp;
15167aec1d6eScindi 	nvlist_t *embnvp = NULL;
15177c478bd9Sstevel@tonic-gate 	nvpair_t *nvpair;
15183e8d8e18Sdb 	const char *nameptr, *propstr, *lastnameptr;
15197c478bd9Sstevel@tonic-gate 	int not_array = 0;
15207c478bd9Sstevel@tonic-gate 	unsigned int index = 0;
15217c478bd9Sstevel@tonic-gate 	uint_t nelem;
15223e8d8e18Sdb 	char *nvpname, *nameslist = NULL;
15237aec1d6eScindi 	char *scheme = NULL;
15247c478bd9Sstevel@tonic-gate 
15257c478bd9Sstevel@tonic-gate 	ASSERT(np->t == T_QUOTE);
15267c478bd9Sstevel@tonic-gate 
15273e8d8e18Sdb 	propstr = np->u.quote.s;
15287c478bd9Sstevel@tonic-gate 	if (payloadnvp == NULL) {
15298a40a695Sgavinm 		out(O_ALTFP | O_VERB2, "platform_payloadprop: no nvp for %s",
15303e8d8e18Sdb 		    propstr);
15317c478bd9Sstevel@tonic-gate 		return (1);
15327c478bd9Sstevel@tonic-gate 	}
15333e8d8e18Sdb 	basenvp = payloadnvp;
15343e8d8e18Sdb 
15353e8d8e18Sdb 	/*
15363e8d8e18Sdb 	 * first handle any embedded nvlists.  if propstr is "foo.bar[2]"
15373e8d8e18Sdb 	 * then lastnameptr should end up being "bar[2]" with basenvp set
15383e8d8e18Sdb 	 * to the nvlist for "foo".  (the search for "bar" within "foo"
15393e8d8e18Sdb 	 * will be done later.)
15403e8d8e18Sdb 	 */
15413e8d8e18Sdb 	if (strchr(propstr, '.') != NULL) {
15423e8d8e18Sdb 		nvlist_t **arraynvp;
15433e8d8e18Sdb 		uint_t nelem;
15443e8d8e18Sdb 		char *w;
15453e8d8e18Sdb 		int ier;
15463e8d8e18Sdb 
15473e8d8e18Sdb 		nameslist = STRDUP(propstr);
15483e8d8e18Sdb 		lastnameptr = strtok(nameslist, ".");
15493e8d8e18Sdb 
15503e8d8e18Sdb 		/*
15513e8d8e18Sdb 		 * decompose nameslist into its component names while
15523e8d8e18Sdb 		 * extracting the embedded nvlist
15533e8d8e18Sdb 		 */
15543e8d8e18Sdb 		while ((w = strtok(NULL, ".")) != NULL) {
15553e8d8e18Sdb 			if (get_array_info(lastnameptr, &nameptr, &index)) {
15563e8d8e18Sdb 				ier = nvlist_lookup_nvlist(basenvp,
155724db4641Seschrock 				    lastnameptr, &basenvp);
15583e8d8e18Sdb 			} else {
15593e8d8e18Sdb 				/* handle array of nvlists */
15603e8d8e18Sdb 				ier = nvlist_lookup_nvlist_array(basenvp,
156124db4641Seschrock 				    nameptr, &arraynvp, &nelem);
15623e8d8e18Sdb 				if (ier == 0) {
15633e8d8e18Sdb 					if ((uint_t)index > nelem - 1)
15643e8d8e18Sdb 						ier = 1;
15653e8d8e18Sdb 					else
15663e8d8e18Sdb 						basenvp = arraynvp[index];
15673e8d8e18Sdb 				}
15683e8d8e18Sdb 			}
15693e8d8e18Sdb 
15703e8d8e18Sdb 			if (ier) {
15713e8d8e18Sdb 				out(O_ALTFP, "platform_payloadprop: "
15723e8d8e18Sdb 				    " invalid list for %s (in %s)",
15733e8d8e18Sdb 				    lastnameptr, propstr);
15743e8d8e18Sdb 				FREE(nameslist);
15753e8d8e18Sdb 				return (1);
15763e8d8e18Sdb 			}
15773e8d8e18Sdb 
15783e8d8e18Sdb 			lastnameptr = w;
15793e8d8e18Sdb 		}
15803e8d8e18Sdb 	} else {
15813e8d8e18Sdb 		lastnameptr = propstr;
15823e8d8e18Sdb 	}
15833e8d8e18Sdb 
15843e8d8e18Sdb 	/* if property is an array reference, extract array name and index */
15853e8d8e18Sdb 	not_array = get_array_info(lastnameptr, &nameptr, &index);
15863e8d8e18Sdb 	if (not_array)
15873e8d8e18Sdb 		nameptr = stable(lastnameptr);
15887c478bd9Sstevel@tonic-gate 
15893e8d8e18Sdb 	if (nameslist != NULL)
15903e8d8e18Sdb 		FREE(nameslist);
15917c478bd9Sstevel@tonic-gate 
15927c478bd9Sstevel@tonic-gate 	/* search for nvpair entry */
15937c478bd9Sstevel@tonic-gate 	nvpair = NULL;
15943e8d8e18Sdb 	while ((nvpair = nvlist_next_nvpair(basenvp, nvpair)) != NULL) {
15957c478bd9Sstevel@tonic-gate 		nvpname = nvpair_name(nvpair);
15967c478bd9Sstevel@tonic-gate 		ASSERT(nvpname != NULL);
15977c478bd9Sstevel@tonic-gate 
15983e8d8e18Sdb 		if (nameptr == stable(nvpname))
15997c478bd9Sstevel@tonic-gate 			break;
16007c478bd9Sstevel@tonic-gate 	}
16017c478bd9Sstevel@tonic-gate 
16027c478bd9Sstevel@tonic-gate 	if (nvpair == NULL) {
16033e8d8e18Sdb 		out(O_ALTFP, "platform_payloadprop: no entry for %s", propstr);
16047c478bd9Sstevel@tonic-gate 		return (1);
16057aec1d6eScindi 	} else if (valuep == NULL) {
16067aec1d6eScindi 		/*
16077aec1d6eScindi 		 * caller is interested in the existence of a property with
16087aec1d6eScindi 		 * this name, regardless of type or value
16097aec1d6eScindi 		 */
16107aec1d6eScindi 		return (0);
16117c478bd9Sstevel@tonic-gate 	}
16127c478bd9Sstevel@tonic-gate 
16137aec1d6eScindi 	valuep->t = UNDEFINED;
16147aec1d6eScindi 
16157c478bd9Sstevel@tonic-gate 	/*
16167c478bd9Sstevel@tonic-gate 	 * get to this point if we found an entry.  figure out its data
16177c478bd9Sstevel@tonic-gate 	 * type and copy its value.
16187c478bd9Sstevel@tonic-gate 	 */
16197aec1d6eScindi 	(void) nvpair_value_nvlist(nvpair, &embnvp);
16207aec1d6eScindi 	if (nvlist_lookup_string(embnvp, FM_FMRI_SCHEME, &scheme) == 0) {
16217aec1d6eScindi 		if (strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
16227aec1d6eScindi 			valuep->t = NODEPTR;
162380ab886dSwesolows 			valuep->v = (uintptr_t)hc_fmri_nodeize(embnvp);
16247aec1d6eScindi 			return (0);
16257aec1d6eScindi 		}
16267aec1d6eScindi 	}
16277c478bd9Sstevel@tonic-gate 	switch (nvpair_type(nvpair)) {
16287c478bd9Sstevel@tonic-gate 	case DATA_TYPE_BOOLEAN:
16297c478bd9Sstevel@tonic-gate 	case DATA_TYPE_BOOLEAN_VALUE: {
16307c478bd9Sstevel@tonic-gate 		boolean_t val;
16317c478bd9Sstevel@tonic-gate 		(void) nvpair_value_boolean_value(nvpair, &val);
16327c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
16337c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
16347c478bd9Sstevel@tonic-gate 		break;
16357c478bd9Sstevel@tonic-gate 	}
16367c478bd9Sstevel@tonic-gate 	case DATA_TYPE_BYTE: {
16377c478bd9Sstevel@tonic-gate 		uchar_t val;
16387c478bd9Sstevel@tonic-gate 		(void) nvpair_value_byte(nvpair, &val);
16397c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
16407c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
16417c478bd9Sstevel@tonic-gate 		break;
16427c478bd9Sstevel@tonic-gate 	}
16437c478bd9Sstevel@tonic-gate 	case DATA_TYPE_STRING: {
16447c478bd9Sstevel@tonic-gate 		char *val;
16457c478bd9Sstevel@tonic-gate 		valuep->t = STRING;
16467c478bd9Sstevel@tonic-gate 		(void) nvpair_value_string(nvpair, &val);
164780ab886dSwesolows 		valuep->v = (uintptr_t)stable(val);
16487c478bd9Sstevel@tonic-gate 		break;
16497c478bd9Sstevel@tonic-gate 	}
16507c478bd9Sstevel@tonic-gate 
16517c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT8: {
16527c478bd9Sstevel@tonic-gate 		int8_t val;
16537c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int8(nvpair, &val);
16547c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
16557c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
16567c478bd9Sstevel@tonic-gate 		break;
16577c478bd9Sstevel@tonic-gate 	}
16587c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT8: {
16597c478bd9Sstevel@tonic-gate 		uint8_t val;
16607c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint8(nvpair, &val);
16617c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
16627c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
16637c478bd9Sstevel@tonic-gate 		break;
16647c478bd9Sstevel@tonic-gate 	}
16657c478bd9Sstevel@tonic-gate 
16667c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT16: {
16677c478bd9Sstevel@tonic-gate 		int16_t val;
16687c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int16(nvpair, &val);
16697c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
16707c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
16717c478bd9Sstevel@tonic-gate 		break;
16727c478bd9Sstevel@tonic-gate 	}
16737c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT16: {
16747c478bd9Sstevel@tonic-gate 		uint16_t val;
16757c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint16(nvpair, &val);
16767c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
16777c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
16787c478bd9Sstevel@tonic-gate 		break;
16797c478bd9Sstevel@tonic-gate 	}
16807c478bd9Sstevel@tonic-gate 
16817c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT32: {
16827c478bd9Sstevel@tonic-gate 		int32_t val;
16837c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int32(nvpair, &val);
16847c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
16857c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
16867c478bd9Sstevel@tonic-gate 		break;
16877c478bd9Sstevel@tonic-gate 	}
16887c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT32: {
16897c478bd9Sstevel@tonic-gate 		uint32_t val;
16907c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint32(nvpair, &val);
16917c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
16927c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
16937c478bd9Sstevel@tonic-gate 		break;
16947c478bd9Sstevel@tonic-gate 	}
16957c478bd9Sstevel@tonic-gate 
16967c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT64: {
16977c478bd9Sstevel@tonic-gate 		int64_t val;
16987c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int64(nvpair, &val);
16997c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17007c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
17017c478bd9Sstevel@tonic-gate 		break;
17027c478bd9Sstevel@tonic-gate 	}
17037c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT64: {
17047c478bd9Sstevel@tonic-gate 		uint64_t val;
17057c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint64(nvpair, &val);
17067c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17077c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val;
17087c478bd9Sstevel@tonic-gate 		break;
17097c478bd9Sstevel@tonic-gate 	}
17107c478bd9Sstevel@tonic-gate 
17117c478bd9Sstevel@tonic-gate 	case DATA_TYPE_BOOLEAN_ARRAY: {
17127c478bd9Sstevel@tonic-gate 		boolean_t *val;
17137c478bd9Sstevel@tonic-gate 		(void) nvpair_value_boolean_array(nvpair, &val, &nelem);
17147c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
17157c478bd9Sstevel@tonic-gate 			goto invalid;
17167c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17177c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
17187c478bd9Sstevel@tonic-gate 		break;
17197c478bd9Sstevel@tonic-gate 	}
17207c478bd9Sstevel@tonic-gate 	case DATA_TYPE_BYTE_ARRAY: {
17217c478bd9Sstevel@tonic-gate 		uchar_t *val;
17227c478bd9Sstevel@tonic-gate 		(void) nvpair_value_byte_array(nvpair, &val, &nelem);
17237c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
17247c478bd9Sstevel@tonic-gate 			goto invalid;
17257c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17267c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
17277c478bd9Sstevel@tonic-gate 		break;
17287c478bd9Sstevel@tonic-gate 	}
17297c478bd9Sstevel@tonic-gate 	case DATA_TYPE_STRING_ARRAY: {
17307c478bd9Sstevel@tonic-gate 		char **val;
17317c478bd9Sstevel@tonic-gate 		(void) nvpair_value_string_array(nvpair, &val, &nelem);
17327c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
17337c478bd9Sstevel@tonic-gate 			goto invalid;
17347c478bd9Sstevel@tonic-gate 		valuep->t = STRING;
173580ab886dSwesolows 		valuep->v = (uintptr_t)stable(val[index]);
17367c478bd9Sstevel@tonic-gate 		break;
17377c478bd9Sstevel@tonic-gate 	}
17387c478bd9Sstevel@tonic-gate 
17397c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT8_ARRAY: {
17407c478bd9Sstevel@tonic-gate 		int8_t *val;
17417c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int8_array(nvpair, &val, &nelem);
17427c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
17437c478bd9Sstevel@tonic-gate 			goto invalid;
17447c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17457c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
17467c478bd9Sstevel@tonic-gate 		break;
17477c478bd9Sstevel@tonic-gate 	}
17487c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT8_ARRAY: {
17497c478bd9Sstevel@tonic-gate 		uint8_t *val;
17507c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint8_array(nvpair, &val, &nelem);
17517c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
17527c478bd9Sstevel@tonic-gate 			goto invalid;
17537c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17547c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
17557c478bd9Sstevel@tonic-gate 		break;
17567c478bd9Sstevel@tonic-gate 	}
17577c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT16_ARRAY: {
17587c478bd9Sstevel@tonic-gate 		int16_t *val;
17597c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int16_array(nvpair, &val, &nelem);
17607c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
17617c478bd9Sstevel@tonic-gate 			goto invalid;
17627c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17637c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
17647c478bd9Sstevel@tonic-gate 		break;
17657c478bd9Sstevel@tonic-gate 	}
17667c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT16_ARRAY: {
17677c478bd9Sstevel@tonic-gate 		uint16_t *val;
17687c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint16_array(nvpair, &val, &nelem);
17697c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
17707c478bd9Sstevel@tonic-gate 			goto invalid;
17717c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17727c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
17737c478bd9Sstevel@tonic-gate 		break;
17747c478bd9Sstevel@tonic-gate 	}
17757c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT32_ARRAY: {
17767c478bd9Sstevel@tonic-gate 		int32_t *val;
17777c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int32_array(nvpair, &val, &nelem);
17787c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
17797c478bd9Sstevel@tonic-gate 			goto invalid;
17807c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17817c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
17827c478bd9Sstevel@tonic-gate 		break;
17837c478bd9Sstevel@tonic-gate 	}
17847c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT32_ARRAY: {
17857c478bd9Sstevel@tonic-gate 		uint32_t *val;
17867c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint32_array(nvpair, &val, &nelem);
17877c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
17887c478bd9Sstevel@tonic-gate 			goto invalid;
17897c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17907c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
17917c478bd9Sstevel@tonic-gate 		break;
17927c478bd9Sstevel@tonic-gate 	}
17937c478bd9Sstevel@tonic-gate 	case DATA_TYPE_INT64_ARRAY: {
17947c478bd9Sstevel@tonic-gate 		int64_t *val;
17957c478bd9Sstevel@tonic-gate 		(void) nvpair_value_int64_array(nvpair, &val, &nelem);
17967c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
17977c478bd9Sstevel@tonic-gate 			goto invalid;
17987c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
17997c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
18007c478bd9Sstevel@tonic-gate 		break;
18017c478bd9Sstevel@tonic-gate 	}
18027c478bd9Sstevel@tonic-gate 	case DATA_TYPE_UINT64_ARRAY: {
18037c478bd9Sstevel@tonic-gate 		uint64_t *val;
18047c478bd9Sstevel@tonic-gate 		(void) nvpair_value_uint64_array(nvpair, &val, &nelem);
18057c478bd9Sstevel@tonic-gate 		if (not_array == 1 || index >= nelem)
18067c478bd9Sstevel@tonic-gate 			goto invalid;
18077c478bd9Sstevel@tonic-gate 		valuep->t = UINT64;
18087c478bd9Sstevel@tonic-gate 		valuep->v = (unsigned long long)val[index];
18097c478bd9Sstevel@tonic-gate 		break;
18107c478bd9Sstevel@tonic-gate 	}
18117c478bd9Sstevel@tonic-gate 
18127c478bd9Sstevel@tonic-gate 	default :
18137aec1d6eScindi 		out(O_ALTFP|O_VERB2,
18147c478bd9Sstevel@tonic-gate 		    "platform_payloadprop: unsupported data type for %s",
18153e8d8e18Sdb 		    propstr);
18167c478bd9Sstevel@tonic-gate 		return (1);
18177c478bd9Sstevel@tonic-gate 	}
18187c478bd9Sstevel@tonic-gate 
18197c478bd9Sstevel@tonic-gate 	return (0);
18207c478bd9Sstevel@tonic-gate 
18217c478bd9Sstevel@tonic-gate invalid:
18227aec1d6eScindi 	out(O_ALTFP|O_VERB2,
18237aec1d6eScindi 	    "platform_payloadprop: invalid array reference for %s", propstr);
18247c478bd9Sstevel@tonic-gate 	return (1);
18257c478bd9Sstevel@tonic-gate }
18267aec1d6eScindi 
18277aec1d6eScindi /*ARGSUSED*/
18287aec1d6eScindi int
platform_path_exists(nvlist_t * fmri)18297aec1d6eScindi platform_path_exists(nvlist_t *fmri)
18307aec1d6eScindi {
18317aec1d6eScindi 	return (fmd_nvl_fmri_present(Hdl, fmri));
18327aec1d6eScindi }
18337aec1d6eScindi 
18347aec1d6eScindi struct evalue *
platform_payloadprop_values(const char * propstr,int * nvals)18357aec1d6eScindi platform_payloadprop_values(const char *propstr, int *nvals)
18367aec1d6eScindi {
18377aec1d6eScindi 	struct evalue *retvals;
18387aec1d6eScindi 	nvlist_t *basenvp;
18397aec1d6eScindi 	nvpair_t *nvpair;
18407aec1d6eScindi 	char *nvpname;
18417aec1d6eScindi 
18427aec1d6eScindi 	*nvals = 0;
18437aec1d6eScindi 
18447aec1d6eScindi 	if (payloadnvp == NULL)
18457aec1d6eScindi 		return (NULL);
18467aec1d6eScindi 
18477aec1d6eScindi 	basenvp = payloadnvp;
18487aec1d6eScindi 
18497aec1d6eScindi 	/* search for nvpair entry */
18507aec1d6eScindi 	nvpair = NULL;
18517aec1d6eScindi 	while ((nvpair = nvlist_next_nvpair(basenvp, nvpair)) != NULL) {
18527aec1d6eScindi 		nvpname = nvpair_name(nvpair);
18537aec1d6eScindi 		ASSERT(nvpname != NULL);
18547aec1d6eScindi 
18557aec1d6eScindi 		if (strcmp(propstr, nvpname) == 0)
18567aec1d6eScindi 			break;
18577aec1d6eScindi 	}
18587aec1d6eScindi 
18597aec1d6eScindi 	if (nvpair == NULL)
18607aec1d6eScindi 		return (NULL);	/* property not found */
18617aec1d6eScindi 
18627aec1d6eScindi 	switch (nvpair_type(nvpair)) {
18637aec1d6eScindi 	case DATA_TYPE_NVLIST: {
18647aec1d6eScindi 		nvlist_t *embnvp = NULL;
18657aec1d6eScindi 		char *scheme = NULL;
18667aec1d6eScindi 
18677aec1d6eScindi 		(void) nvpair_value_nvlist(nvpair, &embnvp);
18687aec1d6eScindi 		if (nvlist_lookup_string(embnvp, FM_FMRI_SCHEME,
18697aec1d6eScindi 		    &scheme) == 0) {
18707aec1d6eScindi 			if (strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
18717aec1d6eScindi 				*nvals = 1;
18727aec1d6eScindi 				retvals = MALLOC(sizeof (struct evalue));
18737aec1d6eScindi 				retvals->t = NODEPTR;
18747aec1d6eScindi 				retvals->v =
187580ab886dSwesolows 				    (uintptr_t)hc_fmri_nodeize(embnvp);
18767aec1d6eScindi 				return (retvals);
18777aec1d6eScindi 			}
18787aec1d6eScindi 		}
18797aec1d6eScindi 		return (NULL);
18807aec1d6eScindi 	}
18817aec1d6eScindi 	case DATA_TYPE_NVLIST_ARRAY: {
18827aec1d6eScindi 		char *scheme = NULL;
18837aec1d6eScindi 		nvlist_t **nvap;
18847aec1d6eScindi 		uint_t nel;
18857aec1d6eScindi 		int i;
18867aec1d6eScindi 		int hccount;
18877aec1d6eScindi 
18887aec1d6eScindi 		/*
18897aec1d6eScindi 		 * since we're only willing to handle hc fmri's, we
18907aec1d6eScindi 		 * must count them first before allocating retvals.
18917aec1d6eScindi 		 */
18927aec1d6eScindi 		if (nvpair_value_nvlist_array(nvpair, &nvap, &nel) != 0)
18937aec1d6eScindi 			return (NULL);
18947aec1d6eScindi 
18957aec1d6eScindi 		hccount = 0;
18967aec1d6eScindi 		for (i = 0; i < nel; i++) {
18977aec1d6eScindi 			if (nvlist_lookup_string(nvap[i], FM_FMRI_SCHEME,
18987aec1d6eScindi 			    &scheme) == 0 &&
18997aec1d6eScindi 			    strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
19007aec1d6eScindi 				hccount++;
19017aec1d6eScindi 			}
19027aec1d6eScindi 		}
19037aec1d6eScindi 
19047aec1d6eScindi 		if (hccount == 0)
19057aec1d6eScindi 			return (NULL);
19067aec1d6eScindi 
19077aec1d6eScindi 		*nvals = hccount;
19087aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * hccount);
19097aec1d6eScindi 
19107aec1d6eScindi 		hccount = 0;
19117aec1d6eScindi 		for (i = 0; i < nel; i++) {
19127aec1d6eScindi 			if (nvlist_lookup_string(nvap[i], FM_FMRI_SCHEME,
19137aec1d6eScindi 			    &scheme) == 0 &&
19147aec1d6eScindi 			    strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
19157aec1d6eScindi 				retvals[hccount].t = NODEPTR;
191680ab886dSwesolows 				retvals[hccount].v = (uintptr_t)
19177aec1d6eScindi 				    hc_fmri_nodeize(nvap[i]);
19187aec1d6eScindi 				hccount++;
19197aec1d6eScindi 			}
19207aec1d6eScindi 		}
19217aec1d6eScindi 		return (retvals);
19227aec1d6eScindi 	}
19237aec1d6eScindi 	case DATA_TYPE_BOOLEAN:
19247aec1d6eScindi 	case DATA_TYPE_BOOLEAN_VALUE: {
19257aec1d6eScindi 		boolean_t val;
19267aec1d6eScindi 
19277aec1d6eScindi 		*nvals = 1;
19287aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
19297aec1d6eScindi 		(void) nvpair_value_boolean_value(nvpair, &val);
19307aec1d6eScindi 		retvals->t = UINT64;
19317aec1d6eScindi 		retvals->v = (unsigned long long)val;
19327aec1d6eScindi 		return (retvals);
19337aec1d6eScindi 	}
19347aec1d6eScindi 	case DATA_TYPE_BYTE: {
19357aec1d6eScindi 		uchar_t val;
19367aec1d6eScindi 
19377aec1d6eScindi 		*nvals = 1;
19387aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
19397aec1d6eScindi 		(void) nvpair_value_byte(nvpair, &val);
19407aec1d6eScindi 		retvals->t = UINT64;
19417aec1d6eScindi 		retvals->v = (unsigned long long)val;
19427aec1d6eScindi 		return (retvals);
19437aec1d6eScindi 	}
19447aec1d6eScindi 	case DATA_TYPE_STRING: {
19457aec1d6eScindi 		char *val;
19467aec1d6eScindi 
19477aec1d6eScindi 		*nvals = 1;
19487aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
19497aec1d6eScindi 		retvals->t = STRING;
19507aec1d6eScindi 		(void) nvpair_value_string(nvpair, &val);
195180ab886dSwesolows 		retvals->v = (uintptr_t)stable(val);
19527aec1d6eScindi 		return (retvals);
19537aec1d6eScindi 	}
19547aec1d6eScindi 
19557aec1d6eScindi 	case DATA_TYPE_INT8: {
19567aec1d6eScindi 		int8_t val;
19577aec1d6eScindi 
19587aec1d6eScindi 		*nvals = 1;
19597aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
19607aec1d6eScindi 		(void) nvpair_value_int8(nvpair, &val);
19617aec1d6eScindi 		retvals->t = UINT64;
19627aec1d6eScindi 		retvals->v = (unsigned long long)val;
19637aec1d6eScindi 		return (retvals);
19647aec1d6eScindi 	}
19657aec1d6eScindi 	case DATA_TYPE_UINT8: {
19667aec1d6eScindi 		uint8_t val;
19677aec1d6eScindi 
19687aec1d6eScindi 		*nvals = 1;
19697aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
19707aec1d6eScindi 		(void) nvpair_value_uint8(nvpair, &val);
19717aec1d6eScindi 		retvals->t = UINT64;
19727aec1d6eScindi 		retvals->v = (unsigned long long)val;
19737aec1d6eScindi 		return (retvals);
19747aec1d6eScindi 	}
19757aec1d6eScindi 
19767aec1d6eScindi 	case DATA_TYPE_INT16: {
19777aec1d6eScindi 		int16_t val;
19787aec1d6eScindi 
19797aec1d6eScindi 		*nvals = 1;
19807aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
19817aec1d6eScindi 		(void) nvpair_value_int16(nvpair, &val);
19827aec1d6eScindi 		retvals->t = UINT64;
19837aec1d6eScindi 		retvals->v = (unsigned long long)val;
19847aec1d6eScindi 		return (retvals);
19857aec1d6eScindi 	}
19867aec1d6eScindi 	case DATA_TYPE_UINT16: {
19877aec1d6eScindi 		uint16_t val;
19887aec1d6eScindi 
19897aec1d6eScindi 		*nvals = 1;
19907aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
19917aec1d6eScindi 		(void) nvpair_value_uint16(nvpair, &val);
19927aec1d6eScindi 		retvals->t = UINT64;
19937aec1d6eScindi 		retvals->v = (unsigned long long)val;
19947aec1d6eScindi 		return (retvals);
19957aec1d6eScindi 	}
19967aec1d6eScindi 
19977aec1d6eScindi 	case DATA_TYPE_INT32: {
19987aec1d6eScindi 		int32_t val;
19997aec1d6eScindi 
20007aec1d6eScindi 		*nvals = 1;
20017aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
20027aec1d6eScindi 		(void) nvpair_value_int32(nvpair, &val);
20037aec1d6eScindi 		retvals->t = UINT64;
20047aec1d6eScindi 		retvals->v = (unsigned long long)val;
20057aec1d6eScindi 		return (retvals);
20067aec1d6eScindi 	}
20077aec1d6eScindi 	case DATA_TYPE_UINT32: {
20087aec1d6eScindi 		uint32_t val;
20097aec1d6eScindi 
20107aec1d6eScindi 		*nvals = 1;
20117aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
20127aec1d6eScindi 		(void) nvpair_value_uint32(nvpair, &val);
20137aec1d6eScindi 		retvals->t = UINT64;
20147aec1d6eScindi 		retvals->v = (unsigned long long)val;
20157aec1d6eScindi 		return (retvals);
20167aec1d6eScindi 	}
20177aec1d6eScindi 
20187aec1d6eScindi 	case DATA_TYPE_INT64: {
20197aec1d6eScindi 		int64_t val;
20207aec1d6eScindi 
20217aec1d6eScindi 		*nvals = 1;
20227aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
20237aec1d6eScindi 		(void) nvpair_value_int64(nvpair, &val);
20247aec1d6eScindi 		retvals->t = UINT64;
20257aec1d6eScindi 		retvals->v = (unsigned long long)val;
20267aec1d6eScindi 		return (retvals);
20277aec1d6eScindi 	}
20287aec1d6eScindi 	case DATA_TYPE_UINT64: {
20297aec1d6eScindi 		uint64_t val;
20307aec1d6eScindi 
20317aec1d6eScindi 		*nvals = 1;
20327aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue));
20337aec1d6eScindi 		(void) nvpair_value_uint64(nvpair, &val);
20347aec1d6eScindi 		retvals->t = UINT64;
20357aec1d6eScindi 		retvals->v = (unsigned long long)val;
20367aec1d6eScindi 		return (retvals);
20377aec1d6eScindi 	}
20387aec1d6eScindi 
20397aec1d6eScindi 	case DATA_TYPE_BOOLEAN_ARRAY: {
20407aec1d6eScindi 		boolean_t *val;
20417aec1d6eScindi 		uint_t nel;
20427aec1d6eScindi 		int i;
20437aec1d6eScindi 
20447aec1d6eScindi 		(void) nvpair_value_boolean_array(nvpair, &val, &nel);
20457aec1d6eScindi 		*nvals = nel;
20467aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
20477aec1d6eScindi 		for (i = 0; i < nel; i++) {
20487aec1d6eScindi 			retvals[i].t = UINT64;
20497aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
20507aec1d6eScindi 		}
20517aec1d6eScindi 		return (retvals);
20527aec1d6eScindi 	}
20537aec1d6eScindi 	case DATA_TYPE_BYTE_ARRAY: {
20547aec1d6eScindi 		uchar_t *val;
20557aec1d6eScindi 		uint_t nel;
20567aec1d6eScindi 		int i;
20577aec1d6eScindi 
20587aec1d6eScindi 		(void) nvpair_value_byte_array(nvpair, &val, &nel);
20597aec1d6eScindi 		*nvals = nel;
20607aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
20617aec1d6eScindi 		for (i = 0; i < nel; i++) {
20627aec1d6eScindi 			retvals[i].t = UINT64;
20637aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
20647aec1d6eScindi 		}
20657aec1d6eScindi 		return (retvals);
20667aec1d6eScindi 	}
20677aec1d6eScindi 	case DATA_TYPE_STRING_ARRAY: {
20687aec1d6eScindi 		char **val;
20697aec1d6eScindi 		uint_t nel;
20707aec1d6eScindi 		int i;
20717aec1d6eScindi 
20727aec1d6eScindi 		(void) nvpair_value_string_array(nvpair, &val, &nel);
20737aec1d6eScindi 		*nvals = nel;
20747aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
20757aec1d6eScindi 		for (i = 0; i < nel; i++) {
20767aec1d6eScindi 			retvals[i].t = STRING;
207780ab886dSwesolows 			retvals[i].v = (uintptr_t)stable(val[i]);
20787aec1d6eScindi 		}
20797aec1d6eScindi 		return (retvals);
20807aec1d6eScindi 	}
20817aec1d6eScindi 
20827aec1d6eScindi 	case DATA_TYPE_INT8_ARRAY: {
20837aec1d6eScindi 		int8_t *val;
20847aec1d6eScindi 		uint_t nel;
20857aec1d6eScindi 		int i;
20867aec1d6eScindi 
20877aec1d6eScindi 		(void) nvpair_value_int8_array(nvpair, &val, &nel);
20887aec1d6eScindi 		*nvals = nel;
20897aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
20907aec1d6eScindi 		for (i = 0; i < nel; i++) {
20917aec1d6eScindi 			retvals[i].t = UINT64;
20927aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
20937aec1d6eScindi 		}
20947aec1d6eScindi 		return (retvals);
20957aec1d6eScindi 	}
20967aec1d6eScindi 	case DATA_TYPE_UINT8_ARRAY: {
20977aec1d6eScindi 		uint8_t *val;
20987aec1d6eScindi 		uint_t nel;
20997aec1d6eScindi 		int i;
21007aec1d6eScindi 
21017aec1d6eScindi 		(void) nvpair_value_uint8_array(nvpair, &val, &nel);
21027aec1d6eScindi 		*nvals = nel;
21037aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
21047aec1d6eScindi 		for (i = 0; i < nel; i++) {
21057aec1d6eScindi 			retvals[i].t = UINT64;
21067aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
21077aec1d6eScindi 		}
21087aec1d6eScindi 		return (retvals);
21097aec1d6eScindi 	}
21107aec1d6eScindi 	case DATA_TYPE_INT16_ARRAY: {
21117aec1d6eScindi 		int16_t *val;
21127aec1d6eScindi 		uint_t nel;
21137aec1d6eScindi 		int i;
21147aec1d6eScindi 
21157aec1d6eScindi 		(void) nvpair_value_int16_array(nvpair, &val, &nel);
21167aec1d6eScindi 		*nvals = nel;
21177aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
21187aec1d6eScindi 		for (i = 0; i < nel; i++) {
21197aec1d6eScindi 			retvals[i].t = UINT64;
21207aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
21217aec1d6eScindi 		}
21227aec1d6eScindi 		return (retvals);
21237aec1d6eScindi 	}
21247aec1d6eScindi 	case DATA_TYPE_UINT16_ARRAY: {
21257aec1d6eScindi 		uint16_t *val;
21267aec1d6eScindi 		uint_t nel;
21277aec1d6eScindi 		int i;
21287aec1d6eScindi 
21297aec1d6eScindi 		(void) nvpair_value_uint16_array(nvpair, &val, &nel);
21307aec1d6eScindi 		*nvals = nel;
21317aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
21327aec1d6eScindi 		for (i = 0; i < nel; i++) {
21337aec1d6eScindi 			retvals[i].t = UINT64;
21347aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
21357aec1d6eScindi 		}
21367aec1d6eScindi 		return (retvals);
21377aec1d6eScindi 	}
21387aec1d6eScindi 	case DATA_TYPE_INT32_ARRAY: {
21397aec1d6eScindi 		int32_t *val;
21407aec1d6eScindi 		uint_t nel;
21417aec1d6eScindi 		int i;
21427aec1d6eScindi 
21437aec1d6eScindi 		(void) nvpair_value_int32_array(nvpair, &val, &nel);
21447aec1d6eScindi 		*nvals = nel;
21457aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
21467aec1d6eScindi 		for (i = 0; i < nel; i++) {
21477aec1d6eScindi 			retvals[i].t = UINT64;
21487aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
21497aec1d6eScindi 		}
21507aec1d6eScindi 		return (retvals);
21517aec1d6eScindi 	}
21527aec1d6eScindi 	case DATA_TYPE_UINT32_ARRAY: {
21537aec1d6eScindi 		uint32_t *val;
21547aec1d6eScindi 		uint_t nel;
21557aec1d6eScindi 		int i;
21567aec1d6eScindi 
21577aec1d6eScindi 		(void) nvpair_value_uint32_array(nvpair, &val, &nel);
21587aec1d6eScindi 		*nvals = nel;
21597aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
21607aec1d6eScindi 		for (i = 0; i < nel; i++) {
21617aec1d6eScindi 			retvals[i].t = UINT64;
21627aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
21637aec1d6eScindi 		}
21647aec1d6eScindi 		return (retvals);
21657aec1d6eScindi 	}
21667aec1d6eScindi 	case DATA_TYPE_INT64_ARRAY: {
21677aec1d6eScindi 		int64_t *val;
21687aec1d6eScindi 		uint_t nel;
21697aec1d6eScindi 		int i;
21707aec1d6eScindi 
21717aec1d6eScindi 		(void) nvpair_value_int64_array(nvpair, &val, &nel);
21727aec1d6eScindi 		*nvals = nel;
21737aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
21747aec1d6eScindi 		for (i = 0; i < nel; i++) {
21757aec1d6eScindi 			retvals[i].t = UINT64;
21767aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
21777aec1d6eScindi 		}
21787aec1d6eScindi 		return (retvals);
21797aec1d6eScindi 	}
21807aec1d6eScindi 	case DATA_TYPE_UINT64_ARRAY: {
21817aec1d6eScindi 		uint64_t *val;
21827aec1d6eScindi 		uint_t nel;
21837aec1d6eScindi 		int i;
21847aec1d6eScindi 
21857aec1d6eScindi 		(void) nvpair_value_uint64_array(nvpair, &val, &nel);
21867aec1d6eScindi 		*nvals = nel;
21877aec1d6eScindi 		retvals = MALLOC(sizeof (struct evalue) * nel);
21887aec1d6eScindi 		for (i = 0; i < nel; i++) {
21897aec1d6eScindi 			retvals[i].t = UINT64;
21907aec1d6eScindi 			retvals[i].v = (unsigned long long)val[i];
21917aec1d6eScindi 		}
21927aec1d6eScindi 		return (retvals);
21937aec1d6eScindi 	}
21947aec1d6eScindi 
21957aec1d6eScindi 	}
21967aec1d6eScindi 
21977aec1d6eScindi 	return (NULL);
21987aec1d6eScindi }
219908f6c065Sgavinm 
220008f6c065Sgavinm /*
220108f6c065Sgavinm  * When a list.repaired event is seen the following is called for
220208f6c065Sgavinm  * each fault in the associated fault list to convert the given FMRI
220308f6c065Sgavinm  * to an instanced path.  Only hc scheme is supported.
220408f6c065Sgavinm  */
220508f6c065Sgavinm const struct ipath *
platform_fault2ipath(nvlist_t * flt)220608f6c065Sgavinm platform_fault2ipath(nvlist_t *flt)
220708f6c065Sgavinm {
220808f6c065Sgavinm 	nvlist_t *rsrc;
220908f6c065Sgavinm 	struct node *np;
221008f6c065Sgavinm 	char *scheme;
22119dd0f810Scindi 	const struct ipath *ip;
221208f6c065Sgavinm 
221308f6c065Sgavinm 	if (nvlist_lookup_nvlist(flt, FM_FAULT_RESOURCE, &rsrc) != 0) {
221408f6c065Sgavinm 		out(O_ALTFP, "platform_fault2ipath: no resource member");
221508f6c065Sgavinm 		return (NULL);
221608f6c065Sgavinm 	} else if (nvlist_lookup_string(rsrc, FM_FMRI_SCHEME, &scheme) != 0) {
221708f6c065Sgavinm 		out(O_ALTFP, "platform_fault2ipath: no scheme type for rsrc");
221808f6c065Sgavinm 		return (NULL);
221908f6c065Sgavinm 	}
222008f6c065Sgavinm 
222108f6c065Sgavinm 	if (strncmp(scheme, FM_FMRI_SCHEME_HC,
222208f6c065Sgavinm 	    sizeof (FM_FMRI_SCHEME_HC) - 1) != 0) {
222308f6c065Sgavinm 		out(O_ALTFP, "platform_fault2ipath: returning NULL for non-hc "
222408f6c065Sgavinm 		"scheme %s", scheme);
222508f6c065Sgavinm 		return (NULL);
222608f6c065Sgavinm 	}
222708f6c065Sgavinm 
222808f6c065Sgavinm 	if ((np = hc_fmri_nodeize(rsrc)) == NULL)
222908f6c065Sgavinm 		return (NULL);		/* nodeize will already have whinged */
223008f6c065Sgavinm 
22319dd0f810Scindi 	ip = ipath(np);
22329dd0f810Scindi 	tree_free(np);
22339dd0f810Scindi 	return (ip);
223408f6c065Sgavinm }
2235