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.
26 #include <fm/fmd_fmri.h>
27 #include <fm/libtopo.h>
28 #include <fm/topo_mod.h>
42 fmd_fmri_nvl2str(nvlist_t
*nvl
, char *buf
, size_t buflen
)
50 if (nvlist_lookup_uint8(nvl
, FM_VERSION
, &version
) != 0 ||
51 version
> FM_HC_SCHEME_VERSION
)
52 return (fmd_fmri_set_errno(EINVAL
));
54 if ((thp
= fmd_fmri_topo_hold(TOPO_VERSION
)) == NULL
)
55 return (fmd_fmri_set_errno(EINVAL
));
56 if (topo_fmri_nvl2str(thp
, nvl
, &str
, &err
) != 0) {
57 fmd_fmri_topo_rele(thp
);
58 return (fmd_fmri_set_errno(EINVAL
));
62 len
= snprintf(buf
, buflen
, "%s", str
);
66 topo_hdl_strfree(thp
, str
);
67 fmd_fmri_topo_rele(thp
);
73 fmd_fmri_present(nvlist_t
*nvl
)
81 err
= nvlist_lookup_nvlist_array(nvl
, FM_FMRI_HC_LIST
, &hcprs
, &hcnprs
);
83 return (fmd_fmri_set_errno(EINVAL
));
84 err
= nvlist_lookup_string(hcprs
[0], FM_FMRI_HC_NAME
, &nm
);
86 return (fmd_fmri_set_errno(EINVAL
));
88 if ((thp
= fmd_fmri_topo_hold(TOPO_VERSION
)) == NULL
)
89 return (fmd_fmri_set_errno(EINVAL
));
90 present
= topo_fmri_present(thp
, nvl
, &err
);
91 fmd_fmri_topo_rele(thp
);
97 fmd_fmri_replaced(nvlist_t
*nvl
)
105 err
= nvlist_lookup_nvlist_array(nvl
, FM_FMRI_HC_LIST
, &hcprs
, &hcnprs
);
107 return (fmd_fmri_set_errno(EINVAL
));
108 err
= nvlist_lookup_string(hcprs
[0], FM_FMRI_HC_NAME
, &nm
);
110 return (fmd_fmri_set_errno(EINVAL
));
112 if ((thp
= fmd_fmri_topo_hold(TOPO_VERSION
)) == NULL
)
113 return (fmd_fmri_set_errno(EINVAL
));
114 replaced
= topo_fmri_replaced(thp
, nvl
, &err
);
115 fmd_fmri_topo_rele(thp
);
121 fmd_fmri_unusable(nvlist_t
*nvl
)
129 if (nvlist_lookup_nvlist_array(nvl
, FM_FMRI_HC_LIST
,
130 &hcprs
, &hcnprs
) != 0 ||
131 nvlist_lookup_string(hcprs
[0], FM_FMRI_HC_NAME
, &nm
) != 0)
134 if ((thp
= fmd_fmri_topo_hold(TOPO_VERSION
)) == NULL
)
135 return (fmd_fmri_set_errno(EINVAL
));
136 unusable
= topo_fmri_unusable(thp
, nvl
, &err
);
137 fmd_fmri_topo_rele(thp
);
139 return (unusable
== 1 ? 1 : 0);
143 auth_compare(nvlist_t
*nvl1
, nvlist_t
*nvl2
)
145 const char *names
[] = {
146 FM_FMRI_AUTH_PRODUCT
,
147 FM_FMRI_AUTH_PRODUCT_SN
,
148 FM_FMRI_AUTH_CHASSIS
,
155 nvlist_t
*auth1
= NULL
, *auth2
= NULL
;
157 (void) nvlist_lookup_nvlist(nvl1
, FM_FMRI_AUTHORITY
, &auth1
);
158 (void) nvlist_lookup_nvlist(nvl2
, FM_FMRI_AUTHORITY
, &auth2
);
159 if (auth1
== NULL
&& auth2
== NULL
)
161 if (auth1
== NULL
|| auth2
== NULL
)
164 for (namep
= names
; *namep
!= NULL
; namep
++) {
165 char *val1
= NULL
, *val2
= NULL
;
167 (void) nvlist_lookup_string(auth1
, *namep
, &val1
);
168 (void) nvlist_lookup_string(auth2
, *namep
, &val2
);
169 if (val1
== NULL
&& val2
== NULL
)
171 if (val1
== NULL
|| val2
== NULL
|| strcmp(val1
, val2
) != 0)
179 hclist_contains(nvlist_t
**erhcl
, uint_t erhclsz
, nvlist_t
**eehcl
,
185 if (erhclsz
> eehclsz
|| erhcl
== NULL
|| eehcl
== NULL
)
188 for (i
= 0; i
< erhclsz
; i
++) {
189 (void) nvlist_lookup_string(erhcl
[i
], FM_FMRI_HC_NAME
,
191 (void) nvlist_lookup_string(eehcl
[i
], FM_FMRI_HC_NAME
,
193 if (strcmp(erval
, eeval
) != 0)
195 (void) nvlist_lookup_string(erhcl
[i
], FM_FMRI_HC_ID
,
197 (void) nvlist_lookup_string(eehcl
[i
], FM_FMRI_HC_ID
,
199 if (strcmp(erval
, eeval
) != 0)
207 fru_compare(nvlist_t
*r1
, nvlist_t
*r2
)
210 nvlist_t
*f1
= NULL
, *f2
= NULL
;
211 nvlist_t
**h1
= NULL
, **h2
= NULL
;
215 if ((thp
= fmd_fmri_topo_hold(TOPO_VERSION
)) == NULL
)
216 return (fmd_fmri_set_errno(EINVAL
));
218 (void) topo_fmri_fru(thp
, r1
, &f1
, &err
);
219 (void) topo_fmri_fru(thp
, r2
, &f2
, &err
);
220 if (f1
!= NULL
&& f2
!= NULL
) {
221 (void) nvlist_lookup_nvlist_array(f1
, FM_FMRI_HC_LIST
, &h1
,
223 (void) nvlist_lookup_nvlist_array(f2
, FM_FMRI_HC_LIST
, &h2
,
225 if (h1sz
== h2sz
&& hclist_contains(h1
, h1sz
, h2
, h2sz
) == 1)
229 fmd_fmri_topo_rele(thp
);
236 fmd_fmri_contains(nvlist_t
*er
, nvlist_t
*ee
)
238 nvlist_t
**erhcl
, **eehcl
;
239 uint_t erhclsz
, eehclsz
;
241 uint64_t eroff
, eeoff
;
243 if (nvlist_lookup_nvlist_array(er
, FM_FMRI_HC_LIST
, &erhcl
,
244 &erhclsz
) != 0 || nvlist_lookup_nvlist_array(ee
,
245 FM_FMRI_HC_LIST
, &eehcl
, &eehclsz
) != 0)
246 return (fmd_fmri_set_errno(EINVAL
));
249 * Check ee is further down the hc tree than er; er and ee have
250 * the same auth and are on the same fru.
252 if (hclist_contains(erhcl
, erhclsz
, eehcl
, eehclsz
) == 0 ||
253 auth_compare(er
, ee
) != 0 || fru_compare(er
, ee
) != 0)
257 * return true if er is parent of ee, or er is not a page
259 if (erhclsz
< eehclsz
|| nvlist_lookup_nvlist(er
,
260 FM_FMRI_HC_SPECIFIC
, &hcsp
) != 0 || (nvlist_lookup_uint64(hcsp
,
261 FM_FMRI_HC_SPECIFIC_OFFSET
, &eroff
) != 0 &&
262 nvlist_lookup_uint64(hcsp
, "asru-" FM_FMRI_HC_SPECIFIC_OFFSET
,
267 * special case for page fmri: return true if ee is the same page
269 if (nvlist_lookup_nvlist(ee
, FM_FMRI_HC_SPECIFIC
, &hcsp
) == 0 &&
270 (nvlist_lookup_uint64(hcsp
, FM_FMRI_HC_SPECIFIC_OFFSET
,
271 &eeoff
) == 0 || nvlist_lookup_uint64(hcsp
, "asru-"
272 FM_FMRI_HC_SPECIFIC_OFFSET
, &eeoff
) == 0) && eroff
== eeoff
)
279 fmd_fmri_service_state(nvlist_t
*nvl
)
282 int err
, service_state
;
285 if (nvlist_lookup_uint8(nvl
, FM_VERSION
, &version
) != 0 ||
286 version
> FM_DEV_SCHEME_VERSION
)
287 return (fmd_fmri_set_errno(EINVAL
));
289 if ((thp
= fmd_fmri_topo_hold(TOPO_VERSION
)) == NULL
)
290 return (fmd_fmri_set_errno(EINVAL
));
292 service_state
= topo_fmri_service_state(thp
, nvl
, &err
);
293 fmd_fmri_topo_rele(thp
);
296 return (FMD_SERVICE_STATE_UNKNOWN
);
298 return (service_state
);