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