4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24 * platform.c -- interfaces to the platform's configuration information
26 * this platform.c allows eft to run on Solaris systems.
35 #include <libnvpair.h>
40 #include <sys/types.h>
43 #include <sys/filio.h>
44 #include <sys/param.h>
45 #include <sys/fm/protocol.h>
46 #include <fm/fmd_api.h>
47 #include <fm/fmd_fmri.h>
48 #include <fm/libtopo.h>
49 #include <fm/topo_hc.h>
62 extern fmd_hdl_t
*Hdl
; /* handle from eft.c */
65 * Lastcfg points to the last configuration snapshot we made.
67 static struct cfgdata
*Lastcfg
;
68 static fmd_hdl_t
*Lasthdl
;
69 static fmd_case_t
*Lastfmcase
;
70 static const char *lastcomp
;
71 static int in_getpath
;
72 extern struct lut
*Usednames
;
73 int prune_raw_config
= 0;
75 static topo_hdl_t
*Eft_topo_hdl
;
78 topo_use_alloc(size_t bytes
)
80 void *p
= alloc_malloc(bytes
, NULL
, 0);
87 topo_use_free(void *p
)
89 alloc_free(p
, NULL
, 0);
94 alloc_nv_alloc(nv_alloc_t
*nva
, size_t size
)
96 return (alloc_malloc(size
, NULL
, 0));
101 alloc_nv_free(nv_alloc_t
*nva
, void *p
, size_t sz
)
103 alloc_free(p
, NULL
, 0);
106 const nv_alloc_ops_t Eft_nv_alloc_ops
= {
107 NULL
, /* nv_ao_init() */
108 NULL
, /* nv_ao_fini() */
109 alloc_nv_alloc
, /* nv_ao_alloc() */
110 alloc_nv_free
, /* nv_ao_free() */
111 NULL
/* nv_ao_reset() */
114 nv_alloc_t Eft_nv_hdl
;
119 static char tmpbuf
[MAXPATHLEN
];
120 static char numbuf
[MAXPATHLEN
];
123 * platform_globals -- set global variables based on sysinfo() calls
128 Root
= fmd_prop_get_string(Hdl
, "fmd.rootdir");
129 Mach
= fmd_prop_get_string(Hdl
, "fmd.machine");
130 Plat
= fmd_prop_get_string(Hdl
, "fmd.platform");
134 platform_free_globals()
136 fmd_prop_free_string(Hdl
, Root
);
137 fmd_prop_free_string(Hdl
, Mach
);
138 fmd_prop_free_string(Hdl
, Plat
);
142 * platform_init -- perform any platform-specific initialization
147 (void) nv_alloc_init(&Eft_nv_hdl
, &Eft_nv_alloc_ops
);
148 Eft_topo_hdl
= fmd_hdl_topo_hold(Hdl
, TOPO_VERSION
);
151 out(O_ALTFP
, "platform_init() sucessful");
157 if (Lastcfg
!= NULL
) {
158 config_free(Lastcfg
);
161 fmd_hdl_topo_rele(Hdl
, Eft_topo_hdl
);
162 platform_free_globals();
163 (void) nv_alloc_fini(&Eft_nv_hdl
);
165 out(O_ALTFP
, "platform_fini() sucessful");
169 * hc_fmri_nodeize -- convert hc-scheme FMRI to eft compatible format
171 * this is an internal platform.c helper routine
174 hc_fmri_nodeize(nvlist_t
*hcfmri
)
176 struct node
*pathtree
= NULL
;
186 * What to do with/about hc-root? Would we have any clue what
187 * to do with it if it weren't /? For now, we don't bother
188 * even looking it up.
192 * Get the hc-list of elements in the FMRI
194 if (nvlist_lookup_nvlist_array(hcfmri
, FM_FMRI_HC_LIST
,
195 &hc_prs
, &hc_nprs
) != 0) {
196 out(O_ALTFP
, "XFILE: hc FMRI missing %s", FM_FMRI_HC_LIST
);
200 for (e
= 0; e
< hc_nprs
; e
++) {
203 r
= nvlist_lookup_string(hc_prs
[e
], FM_FMRI_HC_NAME
, &ename
);
204 r
|= nvlist_lookup_string(hc_prs
[e
], FM_FMRI_HC_ID
, &eid
);
206 /* probably should bail */
209 sname
= stable(ename
);
210 tmpn
= tree_name_iterator(
211 tree_name(sname
, IT_VERTICAL
, NULL
, 0),
212 tree_num(eid
, NULL
, 0));
214 if (pathtree
== NULL
)
217 (void) tree_name_append(pathtree
, tmpn
);
224 * platform_getpath -- extract eft-compatible path from ereport
227 platform_getpath(nvlist_t
*nvl
)
230 nvlist_t
*dfmri
, *real_fmri
, *resource
;
237 enum {DT_HC
, DT_DEVID
, DT_TP
, DT_DEV
, DT_CPU
, DT_UNKNOWN
} type
=
240 /* Find the detector */
241 if (nvlist_lookup_nvlist(nvl
, FM_EREPORT_DETECTOR
, &dfmri
) != 0) {
242 out(O_ALTFP
, "XFILE: ereport has no detector FMRI");
246 /* get the scheme from the detector */
247 if (nvlist_lookup_string(dfmri
, FM_FMRI_SCHEME
, &scheme
) != 0) {
248 out(O_ALTFP
, "XFILE: detector FMRI missing scheme");
252 /* based on scheme, determine type */
253 if (strcmp(scheme
, FM_FMRI_SCHEME_HC
) == 0) {
254 /* already in hc scheme */
256 } else if (strcmp(scheme
, FM_FMRI_SCHEME_DEV
) == 0) {
258 * devid takes precedence over tp which takes precedence over
261 if (nvlist_lookup_string(dfmri
,
262 FM_FMRI_DEV_ID
, &devid
) == 0)
264 else if (nvlist_lookup_string(dfmri
,
265 TOPO_STORAGE_TARGET_PORT_L0ID
, &tp
) == 0)
267 else if (nvlist_lookup_string(dfmri
,
268 FM_FMRI_DEV_PATH
, &path
) == 0)
271 out(O_ALTFP
, "XFILE: detector FMRI missing %s or %s",
272 FM_FMRI_DEV_ID
, FM_FMRI_DEV_PATH
);
275 } else if (strcmp(scheme
, FM_FMRI_SCHEME_CPU
) == 0) {
276 if (nvlist_lookup_uint32(dfmri
, FM_FMRI_CPU_ID
, &cpuid
) == 0)
279 out(O_ALTFP
, "XFILE: detector FMRI missing %s",
284 out(O_ALTFP
, "XFILE: detector FMRI not recognized "
285 "(scheme is %s, expect %s or %s or %s)",
286 scheme
, FM_FMRI_SCHEME_HC
, FM_FMRI_SCHEME_DEV
,
291 out(O_ALTFP
|O_VERB
, "Received ereport in scheme %s", scheme
);
293 /* take a config snapshot */
294 lut_free(Usednames
, NULL
, NULL
);
297 if (config_snapshot() == NULL
) {
300 * If hc-scheme use the fmri that was passed in.
303 return (hc_fmri_nodeize(dfmri
));
305 out(O_ALTFP
, "XFILE: cannot snapshot configuration");
311 * For hc scheme, if we can find the resource from the tolopogy, use
312 * that - otherwise use the fmri that was passed in. For other schemes
313 * look up the path, cpuid, tp or devid in the topology.
317 if (topo_fmri_getprop(Eft_topo_hdl
, dfmri
, TOPO_PGROUP_PROTOCOL
,
318 TOPO_PROP_RESOURCE
, NULL
, &resource
, &err
) == -1) {
319 ret
= hc_fmri_nodeize(dfmri
);
321 } else if (nvlist_lookup_nvlist(resource
,
322 TOPO_PROP_VAL_VAL
, &real_fmri
) != 0)
323 ret
= hc_fmri_nodeize(dfmri
);
325 ret
= hc_fmri_nodeize(real_fmri
);
327 nvlist_free(resource
);
331 if ((ret
= config_bydev_lookup(Lastcfg
, path
)) == NULL
)
332 out(O_ALTFP
, "platform_getpath: no configuration node "
333 "has device path matching \"%s\".", path
);
338 if ((ret
= config_bytp_lookup(Lastcfg
, tp
)) == NULL
)
339 out(O_ALTFP
, "platform_getpath: no configuration node "
340 "has tp matching \"%s\".", tp
);
344 if ((ret
= config_bydevid_lookup(Lastcfg
, devid
)) == NULL
)
345 out(O_ALTFP
, "platform_getpath: no configuration node "
346 "has devid matching \"%s\".", devid
);
350 if ((ret
= config_bycpuid_lookup(Lastcfg
, cpuid
)) == NULL
)
351 out(O_ALTFP
, "platform_getpath: no configuration node "
352 "has cpu-id matching %u.", cpuid
);
356 /* free the snapshot */
357 structconfig_free(Lastcfg
->cooked
);
358 config_free(Lastcfg
);
363 /* Allocate space for raw config strings in chunks of this size */
364 #define STRSBUFLEN 512
367 * cfgadjust -- Make sure the amount we want to add to the raw config string
368 * buffer will fit, and if not, increase the size of the buffer.
371 cfgadjust(struct cfgdata
*rawdata
, int addlen
)
375 if (rawdata
->nextfree
+ addlen
>= rawdata
->end
) {
376 newlen
= (((rawdata
->nextfree
- rawdata
->begin
+ 1 + addlen
)
377 / STRSBUFLEN
) + 1) * STRSBUFLEN
;
378 curnext
= rawdata
->nextfree
- rawdata
->begin
;
379 rawdata
->begin
= REALLOC(rawdata
->begin
, newlen
);
380 rawdata
->nextfree
= rawdata
->begin
+ curnext
;
381 rawdata
->end
= rawdata
->begin
+ newlen
;
386 hc_path(tnode_t
*node
)
389 char *name
, *instance
, *estr
;
390 nvlist_t
*fmri
, **hcl
;
394 if (topo_prop_get_fmri(node
, TOPO_PGROUP_PROTOCOL
, TOPO_PROP_RESOURCE
,
398 if (nvlist_lookup_nvlist_array(fmri
, FM_FMRI_HC_LIST
, &hcl
, &nhc
)
405 for (i
= 0; i
< nhc
; ++i
) {
406 err
= nvlist_lookup_string(hcl
[i
], FM_FMRI_HC_NAME
, &name
);
407 err
|= nvlist_lookup_string(hcl
[i
], FM_FMRI_HC_ID
, &instance
);
413 ul
= strtoul(instance
, &estr
, 10);
414 /* conversion to number failed? */
415 if (estr
== instance
) {
420 (void) strlcat(tmpbuf
, "/", MAXPATHLEN
);
421 (void) strlcat(tmpbuf
, name
, MAXPATHLEN
);
422 (void) snprintf(numbuf
, MAXPATHLEN
, "%lu", ul
);
423 (void) strlcat(tmpbuf
, numbuf
, MAXPATHLEN
);
424 lastcomp
= stable(name
);
433 add_prop_val(topo_hdl_t
*thp
, struct cfgdata
*rawdata
, char *propn
,
437 char *propv
, *fmristr
= NULL
;
444 char buf
[32]; /* big enough for any 64-bit int */
450 * malformed prop nvpair
455 switch (nvpair_type(pv_nvp
)) {
456 case DATA_TYPE_STRING_ARRAY
:
458 * Convert string array into single space-separated string
460 (void) nvpair_value_string_array(pv_nvp
, &propvv
, &nelem
);
461 for (sz
= 0, i
= 0; i
< nelem
; i
++)
462 sz
+= strlen(propvv
[i
]) + 1;
464 for (j
= 0, i
= 0; i
< nelem
; j
++, i
++) {
465 (void) strcpy(&propv
[j
], propvv
[i
]);
466 j
+= strlen(propvv
[i
]);
472 case DATA_TYPE_STRING
:
473 (void) nvpair_value_string(pv_nvp
, &propv
);
476 case DATA_TYPE_NVLIST
:
478 * At least try to collect the protocol
481 (void) nvpair_value_nvlist(pv_nvp
, &fmri
);
482 if (topo_fmri_nvl2str(thp
, fmri
, &fmristr
, &err
) < 0) {
483 out(O_ALTFP
, "cfgcollect: failed to convert fmri to "
491 case DATA_TYPE_UINT64
:
493 * Convert uint64 to hex strings
495 (void) nvpair_value_uint64(pv_nvp
, &ui64
);
496 (void) snprintf(buf
, sizeof (buf
), "0x%llx", ui64
);
500 case DATA_TYPE_BOOLEAN_VALUE
:
502 * Convert boolean_t to hex strings
504 (void) nvpair_value_boolean_value(pv_nvp
, &b
);
505 (void) snprintf(buf
, sizeof (buf
), "0x%llx", (uint64_t)b
);
509 case DATA_TYPE_INT32
:
511 * Convert int32 to hex strings
513 (void) nvpair_value_int32(pv_nvp
, &i32
);
514 (void) snprintf(buf
, sizeof (buf
), "0x%llx",
515 (uint64_t)(int64_t)i32
);
519 case DATA_TYPE_INT64
:
521 * Convert int64 to hex strings
523 (void) nvpair_value_int64(pv_nvp
, &i64
);
524 (void) snprintf(buf
, sizeof (buf
), "0x%llx", (uint64_t)i64
);
528 case DATA_TYPE_UINT32
:
530 * Convert uint32 to hex strings
532 (void) nvpair_value_uint32(pv_nvp
, &ui32
);
533 (void) snprintf(buf
, sizeof (buf
), "0x%llx", (uint64_t)ui32
);
538 out(O_ALTFP
, "cfgcollect: failed to get property value for "
544 addlen
= strlen(propn
) + strlen(propv
) + 2;
545 cfgadjust(rawdata
, addlen
);
546 (void) snprintf(rawdata
->nextfree
,
547 rawdata
->end
- rawdata
->nextfree
, "%s=%s",
549 if (strcmp(propn
, TOPO_PROP_RESOURCE
) == 0)
550 out(O_ALTFP
|O_VERB3
, "cfgcollect: %s", propv
);
552 if (nvpair_type(pv_nvp
) == DATA_TYPE_STRING_ARRAY
)
555 rawdata
->nextfree
+= addlen
;
558 topo_hdl_strfree(thp
, fmristr
);
562 * cfgcollect -- Assemble raw configuration data in string form suitable
566 cfgcollect(topo_hdl_t
*thp
, tnode_t
*node
, void *arg
)
568 struct cfgdata
*rawdata
= (struct cfgdata
*)arg
;
570 char *propn
, *path
= NULL
;
571 nvlist_t
*p_nv
, *pg_nv
, *pv_nv
;
572 nvpair_t
*nvp
, *pg_nvp
, *pv_nvp
;
574 if (topo_node_flags(node
) == TOPO_NODE_FACILITY
)
575 return (TOPO_WALK_NEXT
);
577 path
= hc_path(node
);
579 return (TOPO_WALK_ERR
);
581 addlen
= strlen(path
) + 1;
583 cfgadjust(rawdata
, addlen
);
584 (void) strcpy(rawdata
->nextfree
, path
);
585 rawdata
->nextfree
+= addlen
;
588 * If the prune_raw_config flag is set then we will only include in the
589 * raw config those nodes that are used by the rules remaining after
590 * prune_propagations() has been run - ie only those that could possibly
591 * be relevant to the incoming ereport given the current rules. This
592 * means that any other parts of the config will not get saved to the
593 * checkpoint file (even if they may theoretically be used if the
594 * rules are subsequently modified).
596 * For now prune_raw_config is 0 for Solaris, though it is expected to
597 * be set to 1 for fmsp.
599 * Note we only prune the raw config like this if we have been called
600 * from newfme(), not if we have been called when handling dev or cpu
601 * scheme ereports from platform_getpath(), as this is called before
602 * prune_propagations() - again this is not an issue on fmsp as the
603 * ereports are all in hc scheme.
605 if (!in_getpath
&& prune_raw_config
&&
606 lut_lookup(Usednames
, (void *)lastcomp
, NULL
) == NULL
)
607 return (TOPO_WALK_NEXT
);
612 * eversholt should support alternate property types
613 * Better yet, topo properties could be represented as
616 p_nv
= topo_prop_getprops(node
, &err
);
617 for (nvp
= nvlist_next_nvpair(p_nv
, NULL
); nvp
!= NULL
;
618 nvp
= nvlist_next_nvpair(p_nv
, nvp
)) {
619 if (strcmp(TOPO_PROP_GROUP
, nvpair_name(nvp
)) != 0 ||
620 nvpair_type(nvp
) != DATA_TYPE_NVLIST
)
623 (void) nvpair_value_nvlist(nvp
, &pg_nv
);
625 for (pg_nvp
= nvlist_next_nvpair(pg_nv
, NULL
); pg_nvp
!= NULL
;
626 pg_nvp
= nvlist_next_nvpair(pg_nv
, pg_nvp
)) {
628 if (strcmp(TOPO_PROP_VAL
, nvpair_name(pg_nvp
)) != 0 ||
629 nvpair_type(pg_nvp
) != DATA_TYPE_NVLIST
)
632 (void) nvpair_value_nvlist(pg_nvp
, &pv_nv
);
635 for (pv_nvp
= nvlist_next_nvpair(pv_nv
, NULL
);
637 pv_nvp
= nvlist_next_nvpair(pv_nv
, pv_nvp
)) {
639 /* Get property name */
640 if (strcmp(TOPO_PROP_VAL_NAME
,
641 nvpair_name(pv_nvp
)) == 0)
642 (void) nvpair_value_string(pv_nvp
,
648 if (strcmp(TOPO_PROP_VAL_VAL
,
649 nvpair_name(pv_nvp
)) == 0)
650 add_prop_val(thp
, rawdata
, propn
,
659 return (TOPO_WALK_NEXT
);
663 platform_restore_config(fmd_hdl_t
*hdl
, fmd_case_t
*fmcase
)
665 if (hdl
== Lasthdl
&& fmcase
== Lastfmcase
) {
668 fmd_buf_read(Lasthdl
, Lastfmcase
, WOBUF_CFGLEN
, (void *)&cfglen
,
670 Lastcfg
->begin
= MALLOC(cfglen
);
671 Lastcfg
->end
= Lastcfg
->nextfree
= Lastcfg
->begin
+ cfglen
;
672 fmd_buf_read(Lasthdl
, Lastfmcase
, WOBUF_CFG
, Lastcfg
->begin
,
680 platform_save_config(fmd_hdl_t
*hdl
, fmd_case_t
*fmcase
)
685 * Put the raw config into an fmd_buf. Then we can free it to
690 cfglen
= Lastcfg
->nextfree
- Lastcfg
->begin
;
691 fmd_buf_create(hdl
, fmcase
, WOBUF_CFGLEN
, sizeof (cfglen
));
692 fmd_buf_write(hdl
, fmcase
, WOBUF_CFGLEN
, (void *)&cfglen
,
695 fmd_buf_create(hdl
, fmcase
, WOBUF_CFG
, cfglen
);
696 fmd_buf_write(hdl
, fmcase
, WOBUF_CFG
, Lastcfg
->begin
, cfglen
);
698 FREE(Lastcfg
->begin
);
699 Lastcfg
->begin
= NULL
;
701 Lastcfg
->nextfree
= NULL
;
705 * platform_config_snapshot -- gather a snapshot of the current configuration
708 platform_config_snapshot(void)
712 static uint64_t lastgen
;
716 * If the DR generation number has changed,
717 * we need to grab a new snapshot, otherwise we
718 * can simply point them at the last config.
720 if (prune_raw_config
== 0 && (curgen
= fmd_fmri_get_drgen()) <=
721 lastgen
&& Lastcfg
!= NULL
) {
722 Lastcfg
->raw_refcnt
++;
724 * if config has been backed away to an fmd_buf, restore it
726 if (Lastcfg
->begin
== NULL
)
727 platform_restore_config(Lasthdl
, Lastfmcase
);
732 /* we're getting a new config, so clean up the last one */
733 if (Lastcfg
!= NULL
) {
734 config_free(Lastcfg
);
737 Lastcfg
= MALLOC(sizeof (struct cfgdata
));
738 Lastcfg
->raw_refcnt
= 2; /* caller + Lastcfg */
739 Lastcfg
->begin
= Lastcfg
->nextfree
= Lastcfg
->end
= NULL
;
740 Lastcfg
->cooked
= NULL
;
741 Lastcfg
->devcache
= NULL
;
742 Lastcfg
->devidcache
= NULL
;
743 Lastcfg
->tpcache
= NULL
;
744 Lastcfg
->cpucache
= NULL
;
747 fmd_hdl_topo_rele(Hdl
, Eft_topo_hdl
);
748 Eft_topo_hdl
= fmd_hdl_topo_hold(Hdl
, TOPO_VERSION
);
750 if ((twp
= topo_walk_init(Eft_topo_hdl
, FM_FMRI_SCHEME_HC
, cfgcollect
,
751 Lastcfg
, &err
)) == NULL
) {
752 out(O_DIE
, "platform_config_snapshot: NULL topology tree: %s",
756 if (topo_walk_step(twp
, TOPO_WALK_CHILD
) == TOPO_WALK_ERR
) {
758 out(O_DIE
, "platform_config_snapshot: error walking topology "
763 out(O_ALTFP
|O_STAMP
, "raw config complete");
770 cfgstrprop_lookup(struct config
*croot
, char *path
, char *pname
)
772 struct config
*cresource
;
776 * The first order of business is to find the resource in the
777 * config database so we can examine properties associated with
780 if ((cresource
= config_lookup(croot
, path
, 0)) == NULL
) {
781 out(O_ALTFP
, "Cannot find config info for %s.", path
);
784 if ((fmristr
= config_getprop(cresource
, pname
)) == NULL
) {
785 out(O_ALTFP
, "Cannot find %s property for %s resource "
786 "re-write", pname
, path
);
793 * Get resource FMRI from libtopo
797 platform_units_translate(int isdefect
, struct config
*croot
,
798 nvlist_t
**dfltasru
, nvlist_t
**dfltfru
, nvlist_t
**dfltrsrc
, char *path
)
805 fmristr
= cfgstrprop_lookup(croot
, path
, TOPO_PROP_RESOURCE
);
806 if (fmristr
== NULL
) {
807 out(O_ALTFP
, "Cannot rewrite resource for %s.", path
);
810 if (topo_fmri_str2nvl(Eft_topo_hdl
, fmristr
, &rsrc
, &err
) < 0) {
811 out(O_ALTFP
, "Can not convert config info: %s",
813 out(O_ALTFP
, "Cannot rewrite resource for %s.", path
);
818 * If we don't have a serial number in the resource then check if it
819 * is available as a separate property and if so then add it.
821 if (nvlist_lookup_string(rsrc
, FM_FMRI_HC_SERIAL_ID
, &serial
) != 0) {
822 serial
= (char *)cfgstrprop_lookup(croot
, path
,
823 FM_FMRI_HC_SERIAL_ID
);
825 (void) nvlist_add_string(rsrc
, FM_FMRI_HC_SERIAL_ID
,
833 * platform_get_files -- return names of all files we should load
835 * search directories in dirname[] for all files with names ending with the
836 * substring fnstr. dirname[] should be a NULL-terminated array. fnstr
837 * may be set to "*" to indicate all files in a directory.
839 * if nodups is non-zero, then the first file of a given name found is
840 * the only file added to the list of names. for example if nodups is
841 * set and we're looking for .efts, and find a pci.eft in the dirname[0],
842 * then no pci.eft found in any of the other dirname[] entries will be
843 * included in the final list of names.
845 * this routine doesn't return NULL, even if no files are found (in that
846 * case, a char ** is returned with the first element NULL).
849 platform_get_files(const char *dirname
[], const char *fnstr
, int nodups
)
853 struct lut
*foundnames
= NULL
;
854 char **files
= NULL
; /* char * array of filenames found */
855 int nfiles
= 0; /* files found so far */
856 int slots
= 0; /* char * slots allocated in files */
857 size_t fnlen
, d_namelen
;
862 ASSERT(fnstr
!= NULL
);
863 fnlen
= strlen(fnstr
);
865 for (i
= 0; dirname
[i
] != NULL
; i
++) {
866 out(O_VERB
, "Looking for %s files in %s", fnstr
, dirname
[i
]);
867 if ((dirp
= opendir(dirname
[i
])) == NULL
) {
869 "platform_get_files: opendir failed for %s",
873 while ((dp
= readdir(dirp
)) != NULL
) {
874 if ((fnlen
== 1 && *fnstr
== '*') ||
875 ((d_namelen
= strlen(dp
->d_name
)) >= fnlen
&&
876 strncmp(dp
->d_name
+ d_namelen
- fnlen
,
877 fnstr
, fnlen
) == 0)) {
880 const char *snm
= stable(dp
->d_name
);
882 if (lut_lookup(foundnames
,
886 "platform_get_files: "
887 "skipping repeated name "
893 foundnames
= lut_add(foundnames
,
899 if (nfiles
> slots
- 2) {
900 /* allocate ten more slots */
902 files
= (char **)REALLOC(files
,
903 slots
* sizeof (char *));
905 /* prepend directory name and / */
906 totlen
= strlen(dirname
[i
]) + 1;
907 totlen
+= strlen(dp
->d_name
) + 1;
908 files
[nfiles
] = MALLOC(totlen
);
909 out(O_VERB
, "File %d: \"%s/%s\"", nfiles
,
910 dirname
[i
], dp
->d_name
);
911 (void) snprintf(files
[nfiles
++], totlen
,
912 "%s/%s", dirname
[i
], dp
->d_name
);
915 (void) closedir(dirp
);
918 if (foundnames
!= NULL
)
919 lut_free(foundnames
, NULL
, NULL
);
924 files
[nfiles
] = NULL
;
929 * search for files in a standard set of directories
932 platform_get_files_stddirs(char *fname
, int nodups
)
934 const char *dirlist
[4];
936 char *eftgendir
, *eftmachdir
, *eftplatdir
;
938 eftgendir
= MALLOC(MAXPATHLEN
);
939 eftmachdir
= MALLOC(MAXPATHLEN
);
940 eftplatdir
= MALLOC(MAXPATHLEN
);
942 /* Generic files that apply to any machine */
943 (void) snprintf(eftgendir
, MAXPATHLEN
, "%s/usr/lib/fm/eft", Root
);
945 (void) snprintf(eftmachdir
,
946 MAXPATHLEN
, "%s/usr/platform/%s/lib/fm/eft", Root
, Mach
);
948 (void) snprintf(eftplatdir
,
949 MAXPATHLEN
, "%s/usr/platform/%s/lib/fm/eft", Root
, Plat
);
951 dirlist
[0] = eftplatdir
;
952 dirlist
[1] = eftmachdir
;
953 dirlist
[2] = eftgendir
;
956 flist
= platform_get_files(dirlist
, fname
, nodups
);
966 * platform_run_poller -- execute a poller
968 * when eft needs to know if a polled ereport exists this routine
969 * is called so the poller code may be run in a platform-specific way.
970 * there's no return value from this routine -- either the polled ereport
971 * is generated (and delivered *before* this routine returns) or not.
972 * any errors, like "poller unknown" are considered platform-specific
973 * should be handled here rather than passing an error back up.
977 platform_run_poller(const char *poller
)
982 * fork and execve path with argument array argv and environment array
983 * envp. data from stdout and stderr are placed in outbuf and errbuf,
986 * see execve(2) for more descriptions for path, argv and envp.
989 forkandexecve(const char *path
, char *const argv
[], char *const envp
[],
990 char *outbuf
, size_t outbuflen
, char *errbuf
, size_t errbuflen
)
993 int outpipe
[2], errpipe
[2];
997 * run the cmd and see if it failed. this function is *not* a
998 * generic command runner -- we depend on some knowledge we
999 * have about the commands we run. first of all, we expect
1000 * errors to spew something to stdout, and that something is
1001 * typically short enough to fit into a pipe so we can wait()
1002 * for the command to complete and then fetch the error text
1005 if (pipe(outpipe
) < 0)
1006 if (strlcat(errbuf
, ": pipe(outpipe) failed",
1007 errbuflen
) >= errbuflen
)
1009 if (pipe(errpipe
) < 0)
1010 if (strlcat(errbuf
, ": pipe(errpipe) failed",
1011 errbuflen
) >= errbuflen
)
1014 if ((pid
= fork()) < 0) {
1015 rt
= (int)strlcat(errbuf
, ": fork() failed", errbuflen
);
1020 (void) close(errpipe
[1]);
1021 (void) close(outpipe
[1]);
1023 /* PHASE2 need to guard against hang in child? */
1024 if (waitpid(pid
, &wstat
, 0) < 0)
1025 if (strlcat(errbuf
, ": waitpid() failed",
1026 errbuflen
) >= errbuflen
)
1029 /* check for stderr contents */
1030 if (ioctl(errpipe
[0], FIONREAD
, &count
) >= 0 && count
) {
1031 if (read(errpipe
[0], errbuf
, errbuflen
) <= 0) {
1033 * read failed even though ioctl indicated
1034 * that nonzero bytes were available for
1037 if (strlcat(errbuf
, ": read(errpipe) failed",
1038 errbuflen
) >= errbuflen
)
1042 * handle case where errbuf is not properly
1045 if (count
> errbuflen
- 1)
1046 count
= errbuflen
- 1;
1047 if (errbuf
[count
- 1] != '\0' &&
1048 errbuf
[count
- 1] != '\n')
1049 errbuf
[count
] = '\0';
1050 } else if (WIFSIGNALED(wstat
))
1051 if (strlcat(errbuf
, ": signaled",
1052 errbuflen
) >= errbuflen
)
1054 else if (WIFEXITED(wstat
) && WEXITSTATUS(wstat
))
1055 if (strlcat(errbuf
, ": abnormal exit",
1056 errbuflen
) >= errbuflen
)
1059 /* check for stdout contents */
1060 if (ioctl(outpipe
[0], FIONREAD
, &count
) >= 0 && count
) {
1061 if (read(outpipe
[0], outbuf
, outbuflen
) <= 0) {
1063 * read failed even though ioctl indicated
1064 * that nonzero bytes were available for
1067 if (strlcat(errbuf
, ": read(outpipe) failed",
1068 errbuflen
) >= errbuflen
)
1072 * handle case where outbuf is not properly
1075 if (count
> outbuflen
- 1)
1076 count
= outbuflen
- 1;
1077 if (outbuf
[count
- 1] != '\0' &&
1078 outbuf
[count
- 1] != '\n')
1079 outbuf
[count
] = '\0';
1082 (void) close(errpipe
[0]);
1083 (void) close(outpipe
[0]);
1086 (void) dup2(errpipe
[1], fileno(stderr
));
1087 (void) close(errpipe
[0]);
1088 (void) dup2(outpipe
[1], fileno(stdout
));
1089 (void) close(outpipe
[0]);
1091 if (execve(path
, argv
, envp
))
1099 #define MAXDIGITIDX 23
1102 arglist2argv(struct node
*np
, struct lut
**globals
, struct config
*croot
,
1103 struct arrow
*arrowp
, char ***argv
, int *argc
, int *argvlen
)
1106 char numbuf
[MAXDIGITIDX
+ 1];
1107 char *numstr
, *nullbyte
;
1108 char *addthisarg
= NULL
;
1115 addthisarg
= STRDUP(np
->u
.func
.s
);
1118 if (arglist2argv(np
->u
.expr
.left
, globals
, croot
, arrowp
,
1119 argv
, argc
, argvlen
))
1122 * only leftmost element of a list can provide the command
1123 * name (after which *argc becomes 1)
1126 if (arglist2argv(np
->u
.expr
.right
, globals
, croot
, arrowp
,
1127 argv
, argc
, argvlen
))
1155 struct evalue value
;
1157 if (!eval_expr(np
, NULL
, NULL
, globals
, croot
, arrowp
,
1163 numbuf
[MAXDIGITIDX
] = '\0';
1164 nullbyte
= &numbuf
[MAXDIGITIDX
];
1165 numstr
= ulltostr(value
.v
, nullbyte
);
1166 addthisarg
= STRDUP(numstr
);
1169 addthisarg
= STRDUP((const char *)(uintptr_t)value
.v
);
1172 namep
= (struct node
*)(uintptr_t)value
.v
;
1173 addthisarg
= ipath2str(NULL
, ipath(namep
));
1177 "call: arglist2argv: unexpected result from"
1179 ptree_nodetype2str(np
->t
));
1186 numbuf
[MAXDIGITIDX
] = '\0';
1187 nullbyte
= &numbuf
[MAXDIGITIDX
];
1188 numstr
= ulltostr(np
->u
.ull
, nullbyte
);
1189 addthisarg
= STRDUP(numstr
);
1192 addthisarg
= ipath2str(NULL
, ipath(np
));
1195 addthisarg
= ipath2str(np
->u
.event
.ename
->u
.name
.s
,
1196 ipath(np
->u
.event
.epname
));
1199 out(O_ERR
, "call: arglist2argv: node type %s is unsupported",
1200 ptree_nodetype2str(np
->t
));
1206 if (*argc
== 0 && addthisarg
!= NULL
) {
1208 * first argument added is the command name.
1212 files
= platform_get_files_stddirs(addthisarg
, 0);
1214 /* do not proceed if number of files found != 1 */
1215 if (files
[0] == NULL
)
1216 out(O_DIE
, "call: function %s not found", addthisarg
);
1217 if (files
[1] != NULL
)
1218 out(O_DIE
, "call: multiple functions %s found",
1222 addthisarg
= STRDUP(files
[0]);
1227 if (addthisarg
!= NULL
) {
1228 if (*argc
>= *argvlen
- 2) {
1230 * make sure argv is long enough so it has a
1231 * terminating element set to NULL
1234 *argv
= (char **)REALLOC(*argv
,
1235 sizeof (char *) * *argvlen
);
1237 (*argv
)[*argc
] = addthisarg
;
1239 (*argv
)[*argc
] = NULL
;
1246 generate_envp(struct arrow
*arrowp
, char ***envp
, int *envc
, int *envplen
)
1248 char *envnames
[] = { "EFT_FROM_EVENT", "EFT_TO_EVENT",
1249 "EFT_FILE", "EFT_LINE", NULL
};
1251 char *none
= "(none)";
1258 * make sure envp is long enough so it has a terminating element
1261 *envplen
= *envc
+ 1;
1262 *envp
= (char **)MALLOC(sizeof (char *) * *envplen
);
1264 envvalues
[0] = ipath2str(
1265 arrowp
->tail
->myevent
->enode
->u
.event
.ename
->u
.name
.s
,
1266 arrowp
->tail
->myevent
->ipp
);
1267 envvalues
[1] = ipath2str(
1268 arrowp
->head
->myevent
->enode
->u
.event
.ename
->u
.name
.s
,
1269 arrowp
->head
->myevent
->ipp
);
1271 if (arrowp
->head
->myevent
->enode
->file
== NULL
) {
1272 envvalues
[2] = STRDUP(none
);
1273 envvalues
[3] = STRDUP(none
);
1275 envvalues
[2] = STRDUP(arrowp
->head
->myevent
->enode
->file
);
1277 /* large enough for max int */
1278 envvalues
[3] = MALLOC(sizeof (char) * 25);
1279 (void) snprintf(envvalues
[3], sizeof (envvalues
[3]), "%d",
1280 arrowp
->head
->myevent
->enode
->line
);
1283 for (i
= 0; envnames
[i
] != NULL
&& i
< *envc
; i
++) {
1284 elen
= strlen(envnames
[i
]) + strlen(envvalues
[i
]) + 2;
1285 (*envp
)[i
] = MALLOC(elen
);
1286 (void) snprintf((*envp
)[i
], elen
, "%s=%s",
1287 envnames
[i
], envvalues
[i
]);
1290 (*envp
)[*envc
] = NULL
;
1296 * platform_call -- call an external function
1298 * evaluate a user-defined function and place result in valuep. return 0
1299 * if function evaluation was successful; 1 if otherwise.
1302 platform_call(struct node
*np
, struct lut
**globals
, struct config
*croot
,
1303 struct arrow
*arrowp
, struct evalue
*valuep
)
1306 * use rather short buffers. only the first string on outbuf[] is
1307 * taken as output from the called function. any message in
1308 * errbuf[] is echoed out as an error message.
1310 char outbuf
[256], errbuf
[512];
1312 char **argv
, **envp
;
1313 int argc
, argvlen
, envc
, envplen
;
1317 * np is the argument list. the user-defined function is the first
1318 * element of the list.
1320 ASSERT(np
->t
== T_LIST
);
1325 if (arglist2argv(np
, globals
, croot
, arrowp
, &argv
, &argc
, &argvlen
) ||
1330 * make sure program has executable bit set
1332 if (stat(argv
[0], &buf
) == 0) {
1333 int exec_bit_set
= 0;
1335 if (buf
.st_uid
== geteuid() && buf
.st_mode
& S_IXUSR
)
1337 else if (buf
.st_gid
== getegid() && buf
.st_mode
& S_IXGRP
)
1339 else if (buf
.st_mode
& S_IXOTH
)
1342 if (exec_bit_set
== 0)
1343 out(O_DIE
, "call: executable bit not set on %s",
1346 out(O_DIE
, "call: failure in stat(), errno = %d\n", errno
);
1352 if (generate_envp(arrowp
, &envp
, &envc
, &envplen
))
1358 ret
= forkandexecve((const char *) argv
[0], (char *const *) argv
,
1359 (char *const *) envp
, outbuf
, sizeof (outbuf
),
1360 errbuf
, sizeof (errbuf
));
1362 for (i
= 0; i
< envc
; i
++)
1368 outfl(O_OK
, np
->file
, np
->line
,
1369 "call: failure in fork + exec of %s", argv
[0]);
1373 /* chomp the result */
1374 for (ptr
= outbuf
; *ptr
; ptr
++)
1375 if (*ptr
== '\n' || *ptr
== '\r') {
1380 valuep
->v
= (uintptr_t)stable(outbuf
);
1383 if (errbuf
[0] != '\0') {
1385 outfl(O_OK
, np
->file
, np
->line
,
1386 "call: unexpected stderr output from %s: %s",
1390 for (i
= 0; i
< argc
; i
++)
1398 * platform_confcall -- call a configuration database function
1400 * returns result in *valuep, return 0 on success
1404 platform_confcall(struct node
*np
, struct lut
**globals
, struct config
*croot
,
1405 struct arrow
*arrowp
, struct evalue
*valuep
)
1407 outfl(O_ALTFP
|O_VERB
, np
->file
, np
->line
, "unknown confcall");
1412 * platform_get_eft_files -- return names of all eft files we should load
1414 * this routine doesn't return NULL, even if no files are found (in that
1415 * case, a char ** is returned with the first element NULL).
1418 platform_get_eft_files(void)
1420 return (platform_get_files_stddirs(".eft", 1));
1424 platform_free_eft_files(char **flist
)
1428 if (flist
== NULL
|| *flist
== NULL
)
1429 return; /* no files were found so we're done */
1432 while (*f
!= NULL
) {
1439 static nvlist_t
*payloadnvp
= NULL
;
1442 platform_set_payloadnvp(nvlist_t
*nvlp
)
1445 * cannot replace a non-NULL payloadnvp with a non-NULL nvlp
1447 ASSERT(payloadnvp
!= NULL
? nvlp
== NULL
: 1);
1452 * given array notation in inputstr such as "foo[1]" or "foo [ 1 ]" (spaces
1453 * allowed), figure out the array name and index. return 0 if successful,
1454 * nonzero if otherwise.
1457 get_array_info(const char *inputstr
, const char **name
, unsigned int *index
)
1459 char *indexptr
, *indexend
, *dupname
, *endname
;
1461 if (strchr(inputstr
, '[') == NULL
)
1464 dupname
= STRDUP(inputstr
);
1465 indexptr
= strchr(dupname
, '[');
1466 indexend
= strchr(dupname
, ']');
1469 * return if array notation is not complete or if index is negative
1471 if (indexend
== NULL
|| indexptr
>= indexend
||
1472 strchr(indexptr
, '-') != NULL
) {
1478 * search past any spaces between the name string and '['
1481 while (isspace(*(endname
- 1)) && dupname
< endname
)
1484 ASSERT(dupname
< endname
);
1487 * search until indexptr points to the first digit and indexend
1488 * points to the last digit
1490 while (!isdigit(*indexptr
) && indexptr
< indexend
)
1492 while (!isdigit(*indexend
) && indexptr
<= indexend
)
1495 *(indexend
+ 1) = '\0';
1496 *index
= (unsigned int)atoi(indexptr
);
1498 *name
= stable(dupname
);
1505 * platform_payloadprop -- fetch a payload value
1507 * XXX this function should be replaced and eval_func() should be
1508 * XXX changed to use the more general platform_payloadprop_values().
1511 platform_payloadprop(struct node
*np
, struct evalue
*valuep
)
1514 nvlist_t
*embnvp
= NULL
;
1516 const char *nameptr
, *propstr
, *lastnameptr
;
1518 unsigned int index
= 0;
1520 char *nvpname
, *nameslist
= NULL
;
1521 char *scheme
= NULL
;
1523 ASSERT(np
->t
== T_QUOTE
);
1525 propstr
= np
->u
.quote
.s
;
1526 if (payloadnvp
== NULL
) {
1527 out(O_ALTFP
| O_VERB2
, "platform_payloadprop: no nvp for %s",
1531 basenvp
= payloadnvp
;
1534 * first handle any embedded nvlists. if propstr is "foo.bar[2]"
1535 * then lastnameptr should end up being "bar[2]" with basenvp set
1536 * to the nvlist for "foo". (the search for "bar" within "foo"
1537 * will be done later.)
1539 if (strchr(propstr
, '.') != NULL
) {
1540 nvlist_t
**arraynvp
;
1545 nameslist
= STRDUP(propstr
);
1546 lastnameptr
= strtok(nameslist
, ".");
1549 * decompose nameslist into its component names while
1550 * extracting the embedded nvlist
1552 while ((w
= strtok(NULL
, ".")) != NULL
) {
1553 if (get_array_info(lastnameptr
, &nameptr
, &index
)) {
1554 ier
= nvlist_lookup_nvlist(basenvp
,
1555 lastnameptr
, &basenvp
);
1557 /* handle array of nvlists */
1558 ier
= nvlist_lookup_nvlist_array(basenvp
,
1559 nameptr
, &arraynvp
, &nelem
);
1561 if ((uint_t
)index
> nelem
- 1)
1564 basenvp
= arraynvp
[index
];
1569 out(O_ALTFP
, "platform_payloadprop: "
1570 " invalid list for %s (in %s)",
1571 lastnameptr
, propstr
);
1579 lastnameptr
= propstr
;
1582 /* if property is an array reference, extract array name and index */
1583 not_array
= get_array_info(lastnameptr
, &nameptr
, &index
);
1585 nameptr
= stable(lastnameptr
);
1587 if (nameslist
!= NULL
)
1590 /* search for nvpair entry */
1592 while ((nvpair
= nvlist_next_nvpair(basenvp
, nvpair
)) != NULL
) {
1593 nvpname
= nvpair_name(nvpair
);
1594 ASSERT(nvpname
!= NULL
);
1596 if (nameptr
== stable(nvpname
))
1600 if (nvpair
== NULL
) {
1601 out(O_ALTFP
, "platform_payloadprop: no entry for %s", propstr
);
1603 } else if (valuep
== NULL
) {
1605 * caller is interested in the existence of a property with
1606 * this name, regardless of type or value
1611 valuep
->t
= UNDEFINED
;
1614 * get to this point if we found an entry. figure out its data
1615 * type and copy its value.
1617 (void) nvpair_value_nvlist(nvpair
, &embnvp
);
1618 if (nvlist_lookup_string(embnvp
, FM_FMRI_SCHEME
, &scheme
) == 0) {
1619 if (strcmp(scheme
, FM_FMRI_SCHEME_HC
) == 0) {
1620 valuep
->t
= NODEPTR
;
1621 valuep
->v
= (uintptr_t)hc_fmri_nodeize(embnvp
);
1625 switch (nvpair_type(nvpair
)) {
1626 case DATA_TYPE_BOOLEAN
:
1627 case DATA_TYPE_BOOLEAN_VALUE
: {
1629 (void) nvpair_value_boolean_value(nvpair
, &val
);
1631 valuep
->v
= (unsigned long long)val
;
1634 case DATA_TYPE_BYTE
: {
1636 (void) nvpair_value_byte(nvpair
, &val
);
1638 valuep
->v
= (unsigned long long)val
;
1641 case DATA_TYPE_STRING
: {
1644 (void) nvpair_value_string(nvpair
, &val
);
1645 valuep
->v
= (uintptr_t)stable(val
);
1649 case DATA_TYPE_INT8
: {
1651 (void) nvpair_value_int8(nvpair
, &val
);
1653 valuep
->v
= (unsigned long long)val
;
1656 case DATA_TYPE_UINT8
: {
1658 (void) nvpair_value_uint8(nvpair
, &val
);
1660 valuep
->v
= (unsigned long long)val
;
1664 case DATA_TYPE_INT16
: {
1666 (void) nvpair_value_int16(nvpair
, &val
);
1668 valuep
->v
= (unsigned long long)val
;
1671 case DATA_TYPE_UINT16
: {
1673 (void) nvpair_value_uint16(nvpair
, &val
);
1675 valuep
->v
= (unsigned long long)val
;
1679 case DATA_TYPE_INT32
: {
1681 (void) nvpair_value_int32(nvpair
, &val
);
1683 valuep
->v
= (unsigned long long)val
;
1686 case DATA_TYPE_UINT32
: {
1688 (void) nvpair_value_uint32(nvpair
, &val
);
1690 valuep
->v
= (unsigned long long)val
;
1694 case DATA_TYPE_INT64
: {
1696 (void) nvpair_value_int64(nvpair
, &val
);
1698 valuep
->v
= (unsigned long long)val
;
1701 case DATA_TYPE_UINT64
: {
1703 (void) nvpair_value_uint64(nvpair
, &val
);
1705 valuep
->v
= (unsigned long long)val
;
1709 case DATA_TYPE_BOOLEAN_ARRAY
: {
1711 (void) nvpair_value_boolean_array(nvpair
, &val
, &nelem
);
1712 if (not_array
== 1 || index
>= nelem
)
1715 valuep
->v
= (unsigned long long)val
[index
];
1718 case DATA_TYPE_BYTE_ARRAY
: {
1720 (void) nvpair_value_byte_array(nvpair
, &val
, &nelem
);
1721 if (not_array
== 1 || index
>= nelem
)
1724 valuep
->v
= (unsigned long long)val
[index
];
1727 case DATA_TYPE_STRING_ARRAY
: {
1729 (void) nvpair_value_string_array(nvpair
, &val
, &nelem
);
1730 if (not_array
== 1 || index
>= nelem
)
1733 valuep
->v
= (uintptr_t)stable(val
[index
]);
1737 case DATA_TYPE_INT8_ARRAY
: {
1739 (void) nvpair_value_int8_array(nvpair
, &val
, &nelem
);
1740 if (not_array
== 1 || index
>= nelem
)
1743 valuep
->v
= (unsigned long long)val
[index
];
1746 case DATA_TYPE_UINT8_ARRAY
: {
1748 (void) nvpair_value_uint8_array(nvpair
, &val
, &nelem
);
1749 if (not_array
== 1 || index
>= nelem
)
1752 valuep
->v
= (unsigned long long)val
[index
];
1755 case DATA_TYPE_INT16_ARRAY
: {
1757 (void) nvpair_value_int16_array(nvpair
, &val
, &nelem
);
1758 if (not_array
== 1 || index
>= nelem
)
1761 valuep
->v
= (unsigned long long)val
[index
];
1764 case DATA_TYPE_UINT16_ARRAY
: {
1766 (void) nvpair_value_uint16_array(nvpair
, &val
, &nelem
);
1767 if (not_array
== 1 || index
>= nelem
)
1770 valuep
->v
= (unsigned long long)val
[index
];
1773 case DATA_TYPE_INT32_ARRAY
: {
1775 (void) nvpair_value_int32_array(nvpair
, &val
, &nelem
);
1776 if (not_array
== 1 || index
>= nelem
)
1779 valuep
->v
= (unsigned long long)val
[index
];
1782 case DATA_TYPE_UINT32_ARRAY
: {
1784 (void) nvpair_value_uint32_array(nvpair
, &val
, &nelem
);
1785 if (not_array
== 1 || index
>= nelem
)
1788 valuep
->v
= (unsigned long long)val
[index
];
1791 case DATA_TYPE_INT64_ARRAY
: {
1793 (void) nvpair_value_int64_array(nvpair
, &val
, &nelem
);
1794 if (not_array
== 1 || index
>= nelem
)
1797 valuep
->v
= (unsigned long long)val
[index
];
1800 case DATA_TYPE_UINT64_ARRAY
: {
1802 (void) nvpair_value_uint64_array(nvpair
, &val
, &nelem
);
1803 if (not_array
== 1 || index
>= nelem
)
1806 valuep
->v
= (unsigned long long)val
[index
];
1811 out(O_ALTFP
|O_VERB2
,
1812 "platform_payloadprop: unsupported data type for %s",
1820 out(O_ALTFP
|O_VERB2
,
1821 "platform_payloadprop: invalid array reference for %s", propstr
);
1827 platform_path_exists(nvlist_t
*fmri
)
1829 return (fmd_nvl_fmri_present(Hdl
, fmri
));
1833 platform_payloadprop_values(const char *propstr
, int *nvals
)
1835 struct evalue
*retvals
;
1842 if (payloadnvp
== NULL
)
1845 basenvp
= payloadnvp
;
1847 /* search for nvpair entry */
1849 while ((nvpair
= nvlist_next_nvpair(basenvp
, nvpair
)) != NULL
) {
1850 nvpname
= nvpair_name(nvpair
);
1851 ASSERT(nvpname
!= NULL
);
1853 if (strcmp(propstr
, nvpname
) == 0)
1858 return (NULL
); /* property not found */
1860 switch (nvpair_type(nvpair
)) {
1861 case DATA_TYPE_NVLIST
: {
1862 nvlist_t
*embnvp
= NULL
;
1863 char *scheme
= NULL
;
1865 (void) nvpair_value_nvlist(nvpair
, &embnvp
);
1866 if (nvlist_lookup_string(embnvp
, FM_FMRI_SCHEME
,
1868 if (strcmp(scheme
, FM_FMRI_SCHEME_HC
) == 0) {
1870 retvals
= MALLOC(sizeof (struct evalue
));
1871 retvals
->t
= NODEPTR
;
1873 (uintptr_t)hc_fmri_nodeize(embnvp
);
1879 case DATA_TYPE_NVLIST_ARRAY
: {
1880 char *scheme
= NULL
;
1887 * since we're only willing to handle hc fmri's, we
1888 * must count them first before allocating retvals.
1890 if (nvpair_value_nvlist_array(nvpair
, &nvap
, &nel
) != 0)
1894 for (i
= 0; i
< nel
; i
++) {
1895 if (nvlist_lookup_string(nvap
[i
], FM_FMRI_SCHEME
,
1897 strcmp(scheme
, FM_FMRI_SCHEME_HC
) == 0) {
1906 retvals
= MALLOC(sizeof (struct evalue
) * hccount
);
1909 for (i
= 0; i
< nel
; i
++) {
1910 if (nvlist_lookup_string(nvap
[i
], FM_FMRI_SCHEME
,
1912 strcmp(scheme
, FM_FMRI_SCHEME_HC
) == 0) {
1913 retvals
[hccount
].t
= NODEPTR
;
1914 retvals
[hccount
].v
= (uintptr_t)
1915 hc_fmri_nodeize(nvap
[i
]);
1921 case DATA_TYPE_BOOLEAN
:
1922 case DATA_TYPE_BOOLEAN_VALUE
: {
1926 retvals
= MALLOC(sizeof (struct evalue
));
1927 (void) nvpair_value_boolean_value(nvpair
, &val
);
1928 retvals
->t
= UINT64
;
1929 retvals
->v
= (unsigned long long)val
;
1932 case DATA_TYPE_BYTE
: {
1936 retvals
= MALLOC(sizeof (struct evalue
));
1937 (void) nvpair_value_byte(nvpair
, &val
);
1938 retvals
->t
= UINT64
;
1939 retvals
->v
= (unsigned long long)val
;
1942 case DATA_TYPE_STRING
: {
1946 retvals
= MALLOC(sizeof (struct evalue
));
1947 retvals
->t
= STRING
;
1948 (void) nvpair_value_string(nvpair
, &val
);
1949 retvals
->v
= (uintptr_t)stable(val
);
1953 case DATA_TYPE_INT8
: {
1957 retvals
= MALLOC(sizeof (struct evalue
));
1958 (void) nvpair_value_int8(nvpair
, &val
);
1959 retvals
->t
= UINT64
;
1960 retvals
->v
= (unsigned long long)val
;
1963 case DATA_TYPE_UINT8
: {
1967 retvals
= MALLOC(sizeof (struct evalue
));
1968 (void) nvpair_value_uint8(nvpair
, &val
);
1969 retvals
->t
= UINT64
;
1970 retvals
->v
= (unsigned long long)val
;
1974 case DATA_TYPE_INT16
: {
1978 retvals
= MALLOC(sizeof (struct evalue
));
1979 (void) nvpair_value_int16(nvpair
, &val
);
1980 retvals
->t
= UINT64
;
1981 retvals
->v
= (unsigned long long)val
;
1984 case DATA_TYPE_UINT16
: {
1988 retvals
= MALLOC(sizeof (struct evalue
));
1989 (void) nvpair_value_uint16(nvpair
, &val
);
1990 retvals
->t
= UINT64
;
1991 retvals
->v
= (unsigned long long)val
;
1995 case DATA_TYPE_INT32
: {
1999 retvals
= MALLOC(sizeof (struct evalue
));
2000 (void) nvpair_value_int32(nvpair
, &val
);
2001 retvals
->t
= UINT64
;
2002 retvals
->v
= (unsigned long long)val
;
2005 case DATA_TYPE_UINT32
: {
2009 retvals
= MALLOC(sizeof (struct evalue
));
2010 (void) nvpair_value_uint32(nvpair
, &val
);
2011 retvals
->t
= UINT64
;
2012 retvals
->v
= (unsigned long long)val
;
2016 case DATA_TYPE_INT64
: {
2020 retvals
= MALLOC(sizeof (struct evalue
));
2021 (void) nvpair_value_int64(nvpair
, &val
);
2022 retvals
->t
= UINT64
;
2023 retvals
->v
= (unsigned long long)val
;
2026 case DATA_TYPE_UINT64
: {
2030 retvals
= MALLOC(sizeof (struct evalue
));
2031 (void) nvpair_value_uint64(nvpair
, &val
);
2032 retvals
->t
= UINT64
;
2033 retvals
->v
= (unsigned long long)val
;
2037 case DATA_TYPE_BOOLEAN_ARRAY
: {
2042 (void) nvpair_value_boolean_array(nvpair
, &val
, &nel
);
2044 retvals
= MALLOC(sizeof (struct evalue
) * nel
);
2045 for (i
= 0; i
< nel
; i
++) {
2046 retvals
[i
].t
= UINT64
;
2047 retvals
[i
].v
= (unsigned long long)val
[i
];
2051 case DATA_TYPE_BYTE_ARRAY
: {
2056 (void) nvpair_value_byte_array(nvpair
, &val
, &nel
);
2058 retvals
= MALLOC(sizeof (struct evalue
) * nel
);
2059 for (i
= 0; i
< nel
; i
++) {
2060 retvals
[i
].t
= UINT64
;
2061 retvals
[i
].v
= (unsigned long long)val
[i
];
2065 case DATA_TYPE_STRING_ARRAY
: {
2070 (void) nvpair_value_string_array(nvpair
, &val
, &nel
);
2072 retvals
= MALLOC(sizeof (struct evalue
) * nel
);
2073 for (i
= 0; i
< nel
; i
++) {
2074 retvals
[i
].t
= STRING
;
2075 retvals
[i
].v
= (uintptr_t)stable(val
[i
]);
2080 case DATA_TYPE_INT8_ARRAY
: {
2085 (void) nvpair_value_int8_array(nvpair
, &val
, &nel
);
2087 retvals
= MALLOC(sizeof (struct evalue
) * nel
);
2088 for (i
= 0; i
< nel
; i
++) {
2089 retvals
[i
].t
= UINT64
;
2090 retvals
[i
].v
= (unsigned long long)val
[i
];
2094 case DATA_TYPE_UINT8_ARRAY
: {
2099 (void) nvpair_value_uint8_array(nvpair
, &val
, &nel
);
2101 retvals
= MALLOC(sizeof (struct evalue
) * nel
);
2102 for (i
= 0; i
< nel
; i
++) {
2103 retvals
[i
].t
= UINT64
;
2104 retvals
[i
].v
= (unsigned long long)val
[i
];
2108 case DATA_TYPE_INT16_ARRAY
: {
2113 (void) nvpair_value_int16_array(nvpair
, &val
, &nel
);
2115 retvals
= MALLOC(sizeof (struct evalue
) * nel
);
2116 for (i
= 0; i
< nel
; i
++) {
2117 retvals
[i
].t
= UINT64
;
2118 retvals
[i
].v
= (unsigned long long)val
[i
];
2122 case DATA_TYPE_UINT16_ARRAY
: {
2127 (void) nvpair_value_uint16_array(nvpair
, &val
, &nel
);
2129 retvals
= MALLOC(sizeof (struct evalue
) * nel
);
2130 for (i
= 0; i
< nel
; i
++) {
2131 retvals
[i
].t
= UINT64
;
2132 retvals
[i
].v
= (unsigned long long)val
[i
];
2136 case DATA_TYPE_INT32_ARRAY
: {
2141 (void) nvpair_value_int32_array(nvpair
, &val
, &nel
);
2143 retvals
= MALLOC(sizeof (struct evalue
) * nel
);
2144 for (i
= 0; i
< nel
; i
++) {
2145 retvals
[i
].t
= UINT64
;
2146 retvals
[i
].v
= (unsigned long long)val
[i
];
2150 case DATA_TYPE_UINT32_ARRAY
: {
2155 (void) nvpair_value_uint32_array(nvpair
, &val
, &nel
);
2157 retvals
= MALLOC(sizeof (struct evalue
) * nel
);
2158 for (i
= 0; i
< nel
; i
++) {
2159 retvals
[i
].t
= UINT64
;
2160 retvals
[i
].v
= (unsigned long long)val
[i
];
2164 case DATA_TYPE_INT64_ARRAY
: {
2169 (void) nvpair_value_int64_array(nvpair
, &val
, &nel
);
2171 retvals
= MALLOC(sizeof (struct evalue
) * nel
);
2172 for (i
= 0; i
< nel
; i
++) {
2173 retvals
[i
].t
= UINT64
;
2174 retvals
[i
].v
= (unsigned long long)val
[i
];
2178 case DATA_TYPE_UINT64_ARRAY
: {
2183 (void) nvpair_value_uint64_array(nvpair
, &val
, &nel
);
2185 retvals
= MALLOC(sizeof (struct evalue
) * nel
);
2186 for (i
= 0; i
< nel
; i
++) {
2187 retvals
[i
].t
= UINT64
;
2188 retvals
[i
].v
= (unsigned long long)val
[i
];
2199 * When a list.repaired event is seen the following is called for
2200 * each fault in the associated fault list to convert the given FMRI
2201 * to an instanced path. Only hc scheme is supported.
2203 const struct ipath
*
2204 platform_fault2ipath(nvlist_t
*flt
)
2209 const struct ipath
*ip
;
2211 if (nvlist_lookup_nvlist(flt
, FM_FAULT_RESOURCE
, &rsrc
) != 0) {
2212 out(O_ALTFP
, "platform_fault2ipath: no resource member");
2214 } else if (nvlist_lookup_string(rsrc
, FM_FMRI_SCHEME
, &scheme
) != 0) {
2215 out(O_ALTFP
, "platform_fault2ipath: no scheme type for rsrc");
2219 if (strncmp(scheme
, FM_FMRI_SCHEME_HC
,
2220 sizeof (FM_FMRI_SCHEME_HC
) - 1) != 0) {
2221 out(O_ALTFP
, "platform_fault2ipath: returning NULL for non-hc "
2222 "scheme %s", scheme
);
2226 if ((np
= hc_fmri_nodeize(rsrc
)) == NULL
)
2227 return (NULL
); /* nodeize will already have whinged */