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