5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License (the "License").
7 * You may not use this file except in compliance with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
25 * Copyright (c) 2017, Joyent, Inc.
37 #include <fm/topo_mod.h>
38 #include <fm/topo_hc.h>
39 #include <fm/fmd_fmri.h>
40 #include <sys/param.h>
41 #include <sys/systeminfo.h>
42 #include <sys/fm/protocol.h>
44 #include <sys/systeminfo.h>
45 #include <sys/utsname.h>
47 #include <topo_method.h>
48 #include <topo_module.h>
49 #include <topo_subr.h>
50 #include <topo_prop.h>
51 #include <topo_tree.h>
54 static int hc_enum(topo_mod_t
*, tnode_t
*, const char *, topo_instance_t
,
55 topo_instance_t
, void *, void *);
56 static void hc_release(topo_mod_t
*, tnode_t
*);
57 static int hc_fmri_nvl2str(topo_mod_t
*, tnode_t
*, topo_version_t
,
58 nvlist_t
*, nvlist_t
**);
59 static int hc_fmri_str2nvl(topo_mod_t
*, tnode_t
*, topo_version_t
,
60 nvlist_t
*, nvlist_t
**);
61 static int hc_compare(topo_mod_t
*, tnode_t
*, topo_version_t
, nvlist_t
*,
63 static int hc_fmri_present(topo_mod_t
*, tnode_t
*, topo_version_t
, nvlist_t
*,
65 static int hc_fmri_replaced(topo_mod_t
*, tnode_t
*, topo_version_t
, nvlist_t
*,
67 static int hc_fmri_unusable(topo_mod_t
*, tnode_t
*, topo_version_t
, nvlist_t
*,
69 static int hc_fmri_expand(topo_mod_t
*, tnode_t
*, topo_version_t
,
70 nvlist_t
*, nvlist_t
**);
71 static int hc_fmri_retire(topo_mod_t
*, tnode_t
*, topo_version_t
, nvlist_t
*,
73 static int hc_fmri_unretire(topo_mod_t
*, tnode_t
*, topo_version_t
, nvlist_t
*,
75 static int hc_fmri_service_state(topo_mod_t
*, tnode_t
*, topo_version_t
,
76 nvlist_t
*, nvlist_t
**);
77 static int hc_fmri_create_meth(topo_mod_t
*, tnode_t
*, topo_version_t
,
78 nvlist_t
*, nvlist_t
**);
79 static int hc_fmri_prop_get(topo_mod_t
*, tnode_t
*, topo_version_t
,
80 nvlist_t
*, nvlist_t
**);
81 static int hc_fmri_prop_set(topo_mod_t
*, tnode_t
*, topo_version_t
,
82 nvlist_t
*, nvlist_t
**);
83 static int hc_fmri_pgrp_get(topo_mod_t
*, tnode_t
*, topo_version_t
,
84 nvlist_t
*, nvlist_t
**);
85 static int hc_fmri_facility(topo_mod_t
*, tnode_t
*, topo_version_t
,
86 nvlist_t
*, nvlist_t
**);
88 static nvlist_t
*hc_fmri_create(topo_mod_t
*, nvlist_t
*, int, const char *,
89 topo_instance_t inst
, const nvlist_t
*, const char *, const char *,
92 const topo_method_t hc_methods
[] = {
93 { TOPO_METH_NVL2STR
, TOPO_METH_NVL2STR_DESC
, TOPO_METH_NVL2STR_VERSION
,
94 TOPO_STABILITY_INTERNAL
, hc_fmri_nvl2str
},
95 { TOPO_METH_STR2NVL
, TOPO_METH_STR2NVL_DESC
, TOPO_METH_STR2NVL_VERSION
,
96 TOPO_STABILITY_INTERNAL
, hc_fmri_str2nvl
},
97 { TOPO_METH_COMPARE
, TOPO_METH_COMPARE_DESC
, TOPO_METH_COMPARE_VERSION
,
98 TOPO_STABILITY_INTERNAL
, hc_compare
},
99 { TOPO_METH_PRESENT
, TOPO_METH_PRESENT_DESC
, TOPO_METH_PRESENT_VERSION
,
100 TOPO_STABILITY_INTERNAL
, hc_fmri_present
},
101 { TOPO_METH_REPLACED
, TOPO_METH_REPLACED_DESC
,
102 TOPO_METH_REPLACED_VERSION
, TOPO_STABILITY_INTERNAL
,
104 { TOPO_METH_UNUSABLE
, TOPO_METH_UNUSABLE_DESC
,
105 TOPO_METH_UNUSABLE_VERSION
, TOPO_STABILITY_INTERNAL
,
107 { TOPO_METH_EXPAND
, TOPO_METH_EXPAND_DESC
,
108 TOPO_METH_EXPAND_VERSION
, TOPO_STABILITY_INTERNAL
,
110 { TOPO_METH_RETIRE
, TOPO_METH_RETIRE_DESC
,
111 TOPO_METH_RETIRE_VERSION
, TOPO_STABILITY_INTERNAL
,
113 { TOPO_METH_UNRETIRE
, TOPO_METH_UNRETIRE_DESC
,
114 TOPO_METH_UNRETIRE_VERSION
, TOPO_STABILITY_INTERNAL
,
116 { TOPO_METH_SERVICE_STATE
, TOPO_METH_SERVICE_STATE_DESC
,
117 TOPO_METH_SERVICE_STATE_VERSION
, TOPO_STABILITY_INTERNAL
,
118 hc_fmri_service_state
},
119 { TOPO_METH_FMRI
, TOPO_METH_FMRI_DESC
, TOPO_METH_FMRI_VERSION
,
120 TOPO_STABILITY_INTERNAL
, hc_fmri_create_meth
},
121 { TOPO_METH_PROP_GET
, TOPO_METH_PROP_GET_DESC
,
122 TOPO_METH_PROP_GET_VERSION
, TOPO_STABILITY_INTERNAL
,
124 { TOPO_METH_PROP_SET
, TOPO_METH_PROP_SET_DESC
,
125 TOPO_METH_PROP_SET_VERSION
, TOPO_STABILITY_INTERNAL
,
127 { TOPO_METH_PGRP_GET
, TOPO_METH_PGRP_GET_DESC
,
128 TOPO_METH_PGRP_GET_VERSION
, TOPO_STABILITY_INTERNAL
,
130 { TOPO_METH_FACILITY
, TOPO_METH_FACILITY_DESC
,
131 TOPO_METH_FACILITY_VERSION
, TOPO_STABILITY_INTERNAL
,
136 static const topo_modops_t hc_ops
=
137 { hc_enum
, hc_release
};
138 static const topo_modinfo_t hc_info
=
139 { HC
, FM_FMRI_SCHEME_HC
, HC_VERSION
, &hc_ops
};
141 static const hcc_t hc_canon
[] = {
142 { BANK
, TOPO_STABILITY_PRIVATE
},
143 { BAY
, TOPO_STABILITY_PRIVATE
},
144 { BLADE
, TOPO_STABILITY_PRIVATE
},
145 { BRANCH
, TOPO_STABILITY_PRIVATE
},
146 { CMP
, TOPO_STABILITY_PRIVATE
},
147 { CENTERPLANE
, TOPO_STABILITY_PRIVATE
},
148 { CHASSIS
, TOPO_STABILITY_PRIVATE
},
149 { CHIP
, TOPO_STABILITY_PRIVATE
},
150 { CHIP_SELECT
, TOPO_STABILITY_PRIVATE
},
151 { CORE
, TOPO_STABILITY_PRIVATE
},
152 { CONTROLLER
, TOPO_STABILITY_PRIVATE
},
153 { CPU
, TOPO_STABILITY_PRIVATE
},
154 { CPUBOARD
, TOPO_STABILITY_PRIVATE
},
155 { DIMM
, TOPO_STABILITY_PRIVATE
},
156 { DISK
, TOPO_STABILITY_PRIVATE
},
157 { DRAM
, TOPO_STABILITY_PRIVATE
},
158 { DRAMCHANNEL
, TOPO_STABILITY_PRIVATE
},
159 { FAN
, TOPO_STABILITY_PRIVATE
},
160 { FANBOARD
, TOPO_STABILITY_PRIVATE
},
161 { FANMODULE
, TOPO_STABILITY_PRIVATE
},
162 { HBA
, TOPO_STABILITY_PRIVATE
},
163 { HOSTBRIDGE
, TOPO_STABILITY_PRIVATE
},
164 { INTERCONNECT
, TOPO_STABILITY_PRIVATE
},
165 { IOBOARD
, TOPO_STABILITY_PRIVATE
},
166 { IPORT
, TOPO_STABILITY_PRIVATE
},
167 { MEMBOARD
, TOPO_STABILITY_PRIVATE
},
168 { MEMORYBUFFER
, TOPO_STABILITY_PRIVATE
},
169 { MEMORYCONTROL
, TOPO_STABILITY_PRIVATE
},
170 { MICROCORE
, TOPO_STABILITY_PRIVATE
},
171 { MOTHERBOARD
, TOPO_STABILITY_PRIVATE
},
172 { NIU
, TOPO_STABILITY_PRIVATE
},
173 { NIUFN
, TOPO_STABILITY_PRIVATE
},
174 { PCI_BUS
, TOPO_STABILITY_PRIVATE
},
175 { PCI_DEVICE
, TOPO_STABILITY_PRIVATE
},
176 { PCI_FUNCTION
, TOPO_STABILITY_PRIVATE
},
177 { PCIEX_BUS
, TOPO_STABILITY_PRIVATE
},
178 { PCIEX_DEVICE
, TOPO_STABILITY_PRIVATE
},
179 { PCIEX_FUNCTION
, TOPO_STABILITY_PRIVATE
},
180 { PCIEX_ROOT
, TOPO_STABILITY_PRIVATE
},
181 { PCIEX_SWUP
, TOPO_STABILITY_PRIVATE
},
182 { PCIEX_SWDWN
, TOPO_STABILITY_PRIVATE
},
183 { PORT
, TOPO_STABILITY_PRIVATE
},
184 { POWERBOARD
, TOPO_STABILITY_PRIVATE
},
185 { POWERMODULE
, TOPO_STABILITY_PRIVATE
},
186 { PSU
, TOPO_STABILITY_PRIVATE
},
187 { RANK
, TOPO_STABILITY_PRIVATE
},
188 { RECEPTACLE
, TOPO_STABILITY_PRIVATE
},
189 { RISER
, TOPO_STABILITY_PRIVATE
},
190 { SASEXPANDER
, TOPO_STABILITY_PRIVATE
},
191 { SCSI_DEVICE
, TOPO_STABILITY_PRIVATE
},
192 { SHELF
, TOPO_STABILITY_PRIVATE
},
193 { SES_ENCLOSURE
, TOPO_STABILITY_PRIVATE
},
194 { SMP_DEVICE
, TOPO_STABILITY_PRIVATE
},
195 { SP
, TOPO_STABILITY_PRIVATE
},
196 { STRAND
, TOPO_STABILITY_PRIVATE
},
197 { SUBCHASSIS
, TOPO_STABILITY_PRIVATE
},
198 { SYSTEMBOARD
, TOPO_STABILITY_PRIVATE
},
199 { TRANSCEIVER
, TOPO_STABILITY_PRIVATE
},
200 { XAUI
, TOPO_STABILITY_PRIVATE
},
201 { XFP
, TOPO_STABILITY_PRIVATE
}
204 static int hc_ncanon
= sizeof (hc_canon
) / sizeof (hcc_t
);
207 hc_init(topo_mod_t
*mod
, topo_version_t version
)
210 * Turn on module debugging output
212 if (getenv("TOPOHCDEBUG"))
213 topo_mod_setdebug(mod
);
215 topo_mod_dprintf(mod
, "initializing hc builtin\n");
217 if (version
!= HC_VERSION
)
218 return (topo_mod_seterrno(mod
, EMOD_VER_NEW
));
220 if (topo_mod_register(mod
, &hc_info
, TOPO_VERSION
) != 0) {
221 topo_mod_dprintf(mod
, "failed to register hc: "
222 "%s\n", topo_mod_errmsg(mod
));
223 return (-1); /* mod errno already set */
230 hc_fini(topo_mod_t
*mod
)
232 topo_mod_unregister(mod
);
236 static const topo_pgroup_info_t sys_pgroup
= {
238 TOPO_STABILITY_PRIVATE
,
239 TOPO_STABILITY_PRIVATE
,
243 static const topo_pgroup_info_t auth_pgroup
= {
245 TOPO_STABILITY_PRIVATE
,
246 TOPO_STABILITY_PRIVATE
,
251 hc_prop_set(tnode_t
*node
, nvlist_t
*auth
)
254 char isa
[MAXNAMELEN
];
256 char *prod
, *psn
, *csn
, *server
;
261 if (topo_pgroup_create(node
, &auth_pgroup
, &err
) != 0) {
262 if (err
!= ETOPO_PROP_DEFD
)
267 * Inherit if we can, it saves memory
269 if ((topo_prop_inherit(node
, FM_FMRI_AUTHORITY
, FM_FMRI_AUTH_PRODUCT
,
270 &err
) != 0) && (err
!= ETOPO_PROP_DEFD
)) {
271 if (nvlist_lookup_string(auth
, FM_FMRI_AUTH_PRODUCT
, &prod
)
273 (void) topo_prop_set_string(node
, FM_FMRI_AUTHORITY
,
274 FM_FMRI_AUTH_PRODUCT
, TOPO_PROP_IMMUTABLE
, prod
,
277 if ((topo_prop_inherit(node
, FM_FMRI_AUTHORITY
, FM_FMRI_AUTH_PRODUCT_SN
,
278 &err
) != 0) && (err
!= ETOPO_PROP_DEFD
)) {
279 if (nvlist_lookup_string(auth
, FM_FMRI_AUTH_PRODUCT_SN
, &psn
)
281 (void) topo_prop_set_string(node
, FM_FMRI_AUTHORITY
,
282 FM_FMRI_AUTH_PRODUCT_SN
, TOPO_PROP_IMMUTABLE
, psn
,
285 if ((topo_prop_inherit(node
, FM_FMRI_AUTHORITY
, FM_FMRI_AUTH_CHASSIS
,
286 &err
) != 0) && (err
!= ETOPO_PROP_DEFD
)) {
287 if (nvlist_lookup_string(auth
, FM_FMRI_AUTH_CHASSIS
, &csn
) == 0)
288 (void) topo_prop_set_string(node
, FM_FMRI_AUTHORITY
,
289 FM_FMRI_AUTH_CHASSIS
, TOPO_PROP_IMMUTABLE
, csn
,
292 if ((topo_prop_inherit(node
, FM_FMRI_AUTHORITY
, FM_FMRI_AUTH_SERVER
,
293 &err
) != 0) && (err
!= ETOPO_PROP_DEFD
)) {
294 if (nvlist_lookup_string(auth
, FM_FMRI_AUTH_SERVER
, &server
)
296 (void) topo_prop_set_string(node
, FM_FMRI_AUTHORITY
,
297 FM_FMRI_AUTH_SERVER
, TOPO_PROP_IMMUTABLE
, server
,
301 if (topo_pgroup_create(node
, &sys_pgroup
, &err
) != 0)
305 (void) sysinfo(SI_ARCHITECTURE
, isa
, sizeof (isa
));
307 (void) topo_prop_set_string(node
, TOPO_PGROUP_SYSTEM
, TOPO_PROP_ISA
,
308 TOPO_PROP_IMMUTABLE
, isa
, &err
);
309 (void) topo_prop_set_string(node
, TOPO_PGROUP_SYSTEM
, TOPO_PROP_MACHINE
,
310 TOPO_PROP_IMMUTABLE
, uts
.machine
, &err
);
315 hc_enum(topo_mod_t
*mod
, tnode_t
*pnode
, const char *name
, topo_instance_t min
,
316 topo_instance_t max
, void *notused1
, void *notused2
)
318 int isglobal
= (getzoneid() == GLOBAL_ZONEID
);
319 nvlist_t
*pfmri
= NULL
;
325 * Register root node methods
327 if (strcmp(name
, HC
) == 0) {
328 (void) topo_method_register(mod
, pnode
, hc_methods
);
332 topo_mod_dprintf(mod
,
333 "Request to enumerate %s component with an "
334 "ambiguous instance number, min (%d) != max (%d).\n",
336 return (topo_mod_seterrno(mod
, EINVAL
));
342 (void) topo_node_resource(pnode
, &pfmri
, &err
);
343 auth
= topo_mod_auth(mod
, pnode
);
344 nvl
= hc_fmri_create(mod
, pfmri
, FM_HC_SCHEME_VERSION
, name
, min
,
345 auth
, NULL
, NULL
, NULL
);
346 nvlist_free(pfmri
); /* callee ignores NULLs */
352 if ((node
= topo_node_bind(mod
, pnode
, name
, min
, nvl
)) == NULL
) {
353 topo_mod_dprintf(mod
, "topo_node_bind failed: %s\n",
354 topo_strerror(topo_mod_errno(mod
)));
361 * Set FRU for the motherboard node
363 if (strcmp(name
, MOTHERBOARD
) == 0)
364 (void) topo_node_fru_set(node
, nvl
, 0, &err
);
366 hc_prop_set(node
, auth
);
375 hc_release(topo_mod_t
*mp
, tnode_t
*node
)
377 topo_method_unregister_all(mp
, node
);
381 fmri_compare(topo_mod_t
*mod
, nvlist_t
*nv1
, nvlist_t
*nv2
)
384 nvlist_t
**hcp1
, **hcp2
;
385 nvlist_t
*f1
= NULL
, *f2
= NULL
;
390 if (nvlist_lookup_uint8(nv1
, FM_VERSION
, &v1
) != 0 ||
391 nvlist_lookup_uint8(nv2
, FM_VERSION
, &v2
) != 0 ||
392 v1
> FM_HC_SCHEME_VERSION
|| v2
> FM_HC_SCHEME_VERSION
)
393 return (topo_mod_seterrno(mod
, EMOD_FMRI_VERSION
));
395 err
= nvlist_lookup_nvlist_array(nv1
, FM_FMRI_HC_LIST
, &hcp1
, &nhcp1
);
396 err
|= nvlist_lookup_nvlist_array(nv2
, FM_FMRI_HC_LIST
, &hcp2
, &nhcp2
);
398 return (topo_mod_seterrno(mod
, EMOD_FMRI_NVL
));
403 for (i
= 0; i
< nhcp1
; i
++) {
409 (void) nvlist_lookup_string(hcp1
[i
], FM_FMRI_HC_NAME
, &nm1
);
410 (void) nvlist_lookup_string(hcp2
[i
], FM_FMRI_HC_NAME
, &nm2
);
411 (void) nvlist_lookup_string(hcp1
[i
], FM_FMRI_HC_ID
, &id1
);
412 (void) nvlist_lookup_string(hcp2
[i
], FM_FMRI_HC_ID
, &id2
);
413 if (nm1
== NULL
|| nm2
== NULL
|| id1
== NULL
|| id2
== NULL
)
414 return (topo_mod_seterrno(mod
, EMOD_FMRI_NVL
));
416 if (strcmp(nm1
, nm2
) == 0 && strcmp(id1
, id2
) == 0)
423 * Finally, check if the FMRI's represent a facility node. If so, then
424 * verify that the facilty type ("sensor"|"indicator") and facility
427 (void) nvlist_lookup_nvlist(nv1
, FM_FMRI_FACILITY
, &f1
);
428 (void) nvlist_lookup_nvlist(nv2
, FM_FMRI_FACILITY
, &f2
);
430 if (f1
== NULL
&& f2
== NULL
)
432 else if (f1
== NULL
|| f2
== NULL
)
435 if (nvlist_lookup_string(f1
, FM_FMRI_FACILITY_NAME
, &f1str
) == 0 &&
436 nvlist_lookup_string(f2
, FM_FMRI_FACILITY_NAME
, &f2str
) == 0 &&
437 strcmp(f1str
, f2str
) == 0 &&
438 nvlist_lookup_string(f1
, FM_FMRI_FACILITY_TYPE
, &f1str
) == 0 &&
439 nvlist_lookup_string(f2
, FM_FMRI_FACILITY_TYPE
, &f2str
) == 0 &&
440 strcmp(f1str
, f2str
) == 0) {
448 hc_compare(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
449 nvlist_t
*in
, nvlist_t
**out
)
455 if (version
> TOPO_METH_COMPARE_VERSION
)
456 return (topo_mod_seterrno(mod
, EMOD_VER_NEW
));
458 if (nvlist_lookup_nvlist(in
, TOPO_METH_FMRI_ARG_NV1
, &nv1
) != 0 ||
459 nvlist_lookup_nvlist(in
, TOPO_METH_FMRI_ARG_NV2
, &nv2
) != 0)
460 return (topo_mod_seterrno(mod
, EMOD_METHOD_INVAL
));
462 ret
= fmri_compare(mod
, nv1
, nv2
);
467 if (topo_mod_nvalloc(mod
, out
, NV_UNIQUE_NAME
) == 0) {
468 if (nvlist_add_uint32(*out
, TOPO_METH_COMPARE_RET
,
479 fmri_nvl2str(nvlist_t
*nvl
, char *buf
, size_t buflen
)
481 nvlist_t
**hcprs
= NULL
;
482 nvlist_t
*hcsp
= NULL
;
483 nvlist_t
*anvl
= NULL
;
494 char *fname
= NULL
, *ftype
= NULL
;
497 if (nvlist_lookup_uint8(nvl
, FM_VERSION
, &version
) != 0 ||
498 version
> FM_HC_SCHEME_VERSION
)
501 /* Get authority, if present */
502 err
= nvlist_lookup_nvlist(nvl
, FM_FMRI_AUTHORITY
, &anvl
);
503 if (err
!= 0 && err
!= ENOENT
)
506 (void) nvlist_lookup_string(nvl
, FM_FMRI_HC_ROOT
, &root
);
508 err
= nvlist_lookup_nvlist_array(nvl
, FM_FMRI_HC_LIST
, &hcprs
, &hcnprs
);
509 if (err
!= 0 || hcprs
== NULL
)
512 (void) nvlist_lookup_string(nvl
, FM_FMRI_HC_SERIAL_ID
, &serial
);
513 (void) nvlist_lookup_string(nvl
, FM_FMRI_HC_PART
, &part
);
514 (void) nvlist_lookup_string(nvl
, FM_FMRI_HC_REVISION
, &rev
);
517 topo_fmristr_build(&size
, buf
, buflen
, FM_FMRI_SCHEME_HC
, NULL
, "://");
519 /* authority, if any */
521 for (apair
= nvlist_next_nvpair(anvl
, NULL
);
522 apair
!= NULL
; apair
= nvlist_next_nvpair(anvl
, apair
)) {
523 if (nvpair_type(apair
) != DATA_TYPE_STRING
||
524 nvpair_value_string(apair
, &aval
) != 0)
526 aname
= nvpair_name(apair
);
527 topo_fmristr_build(&size
, buf
, buflen
, ":", NULL
, NULL
);
528 topo_fmristr_build(&size
, buf
, buflen
, "=",
533 /* hardware-id part */
534 topo_fmristr_build(&size
,
535 buf
, buflen
, serial
, ":" FM_FMRI_HC_SERIAL_ID
"=", NULL
);
536 topo_fmristr_build(&size
,
537 buf
, buflen
, part
, ":" FM_FMRI_HC_PART
"=", NULL
);
538 topo_fmristr_build(&size
,
539 buf
, buflen
, rev
, ":" FM_FMRI_HC_REVISION
"=", NULL
);
541 /* separating slash */
542 topo_fmristr_build(&size
, buf
, buflen
, "/", NULL
, NULL
);
546 topo_fmristr_build(&size
, buf
, buflen
, root
, NULL
, NULL
);
549 for (i
= 0; i
< hcnprs
; i
++) {
554 topo_fmristr_build(&size
,
555 buf
, buflen
, "/", NULL
, NULL
);
556 (void) nvlist_lookup_string(hcprs
[i
], FM_FMRI_HC_NAME
, &nm
);
557 (void) nvlist_lookup_string(hcprs
[i
], FM_FMRI_HC_ID
, &id
);
558 if (nm
== NULL
|| id
== NULL
)
560 topo_fmristr_build(&size
, buf
, buflen
, nm
, NULL
, "=");
561 topo_fmristr_build(&size
, buf
, buflen
, id
, NULL
, NULL
);
564 /* append offset/physaddr if it exists in hc-specific */
565 if (nvlist_lookup_nvlist(nvl
, FM_FMRI_HC_SPECIFIC
, &hcsp
) == 0) {
570 if (nvlist_lookup_uint64(hcsp
, FM_FMRI_HC_SPECIFIC_OFFSET
,
571 &val
) == 0 || nvlist_lookup_uint64(hcsp
,
572 "asru-" FM_FMRI_HC_SPECIFIC_OFFSET
, &val
) == 0)
573 hcsn
= FM_FMRI_HC_SPECIFIC_OFFSET
;
574 else if (nvlist_lookup_uint64(hcsp
,
575 FM_FMRI_HC_SPECIFIC_PHYSADDR
, &val
) == 0 ||
576 nvlist_lookup_uint64(hcsp
,
577 "asru-" FM_FMRI_HC_SPECIFIC_PHYSADDR
, &val
) == 0)
578 hcsn
= FM_FMRI_HC_SPECIFIC_PHYSADDR
;
581 (void) snprintf(hexstr
, sizeof (hexstr
), "%llx", val
);
582 topo_fmristr_build(&size
, buf
, buflen
, "/", NULL
, NULL
);
583 topo_fmristr_build(&size
, buf
, buflen
, "=", hcsn
,
589 * If the nvlist represents a facility node, then we append the
590 * facility type and name to the end of the string representation using
595 if (nvlist_lookup_nvlist(nvl
, FM_FMRI_FACILITY
, &fnvl
) == 0) {
596 if (nvlist_lookup_string(fnvl
, FM_FMRI_FACILITY_NAME
,
597 &fname
) != 0 || nvlist_lookup_string(fnvl
,
598 FM_FMRI_FACILITY_TYPE
, &ftype
) != 0)
600 topo_fmristr_build(&size
, buf
, buflen
, "?", NULL
, NULL
);
601 topo_fmristr_build(&size
, buf
, buflen
, "=", ftype
, fname
);
609 hc_fmri_nvl2str(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
610 nvlist_t
*nvl
, nvlist_t
**out
)
616 if (version
> TOPO_METH_NVL2STR_VERSION
)
617 return (topo_mod_seterrno(mod
, EMOD_VER_NEW
));
619 if ((len
= fmri_nvl2str(nvl
, NULL
, 0)) == 0 ||
620 (name
= topo_mod_alloc(mod
, len
+ 1)) == NULL
||
621 fmri_nvl2str(nvl
, name
, len
+ 1) == 0) {
623 topo_mod_free(mod
, name
, len
+ 1);
624 return (topo_mod_seterrno(mod
, EMOD_FMRI_NVL
));
627 if (topo_mod_nvalloc(mod
, &fmristr
, NV_UNIQUE_NAME
) != 0) {
628 topo_mod_free(mod
, name
, len
+ 1);
629 return (topo_mod_seterrno(mod
, EMOD_FMRI_NVL
));
631 if (nvlist_add_string(fmristr
, "fmri-string", name
) != 0) {
632 topo_mod_free(mod
, name
, len
+ 1);
633 nvlist_free(fmristr
);
634 return (topo_mod_seterrno(mod
, EMOD_FMRI_NVL
));
636 topo_mod_free(mod
, name
, len
+ 1);
643 hc_base_fmri_create(topo_mod_t
*mod
, const nvlist_t
*auth
, const char *part
,
644 const char *rev
, const char *serial
)
650 * Create base HC nvlist
652 if (topo_mod_nvalloc(mod
, &fmri
, NV_UNIQUE_NAME
) != 0)
655 err
= nvlist_add_uint8(fmri
, FM_VERSION
, FM_HC_SCHEME_VERSION
);
656 err
|= nvlist_add_string(fmri
, FM_FMRI_SCHEME
, FM_FMRI_SCHEME_HC
);
657 err
|= nvlist_add_string(fmri
, FM_FMRI_HC_ROOT
, "");
664 * Add optional payload members
667 (void) nvlist_add_string(fmri
, FM_FMRI_HC_SERIAL_ID
, serial
);
669 (void) nvlist_add_string(fmri
, FM_FMRI_HC_PART
, part
);
671 (void) nvlist_add_string(fmri
, FM_FMRI_HC_REVISION
, rev
);
673 (void) nvlist_add_nvlist(fmri
, FM_FMRI_AUTHORITY
,
680 make_hc_pairs(topo_mod_t
*mod
, char *fmri
, int *num
)
684 char *starti
, *startn
, *endi
, *endi2
;
693 if ((hc
= topo_mod_strdup(mod
, fmri
+ 5)) == NULL
)
696 hclen
= strlen(hc
) + 1;
699 * Count equal signs and slashes to determine how many
700 * hc-pairs will be present in the final FMRI. There should
701 * be at least as many slashes as equal signs. There can be
702 * more, though if the string after an = includes them.
704 if ((fromstr
= strchr(hc
, '/')) == NULL
)
708 while ((ne
= strchr(find
, '=')) != NULL
) {
714 while ((ns
= strchr(find
, '/')) != NULL
) {
720 * Do we appear to have a well-formed string version of the FMRI?
722 if (nslashes
< npairs
|| npairs
== 0) {
723 topo_mod_free(mod
, hc
, hclen
);
731 if ((pa
= topo_mod_zalloc(mod
, npairs
* sizeof (nvlist_t
*))) == NULL
) {
732 topo_mod_free(mod
, hc
, hclen
);
737 * We go through a pretty complicated procedure to find the
738 * name and id for each pair. That's because, unfortunately,
739 * we have some ids that can have slashes within them. So
740 * we can't just search for the next slash after the equal sign
741 * and decide that starts a new pair. Instead we have to find
742 * an equal sign for the next pair and work our way back to the
745 for (i
= 0; i
< npairs
; i
++) {
746 startn
= strchr(find
, '/');
750 starti
= strchr(find
, '=');
754 if ((cname
= topo_mod_strdup(mod
, startn
)) == NULL
)
757 endi
= strchr(starti
, '=');
760 endi2
= strrchr(starti
, '/');
765 if ((cid
= topo_mod_strdup(mod
, starti
)) == NULL
)
770 if ((cid
= topo_mod_strdup(mod
, starti
)) == NULL
)
772 find
= starti
+ strlen(starti
);
774 if (topo_mod_nvalloc(mod
, &pa
[i
], NV_UNIQUE_NAME
) < 0)
777 if (nvlist_add_string(pa
[i
], FM_FMRI_HC_NAME
, cname
) ||
778 nvlist_add_string(pa
[i
], FM_FMRI_HC_ID
, cid
))
781 topo_mod_strfree(mod
, cname
);
782 topo_mod_strfree(mod
, cid
);
787 topo_mod_strfree(mod
, cname
);
788 topo_mod_strfree(mod
, cid
);
791 for (i
= 0; i
< npairs
; i
++)
793 topo_mod_free(mod
, pa
, npairs
* sizeof (nvlist_t
*));
794 topo_mod_free(mod
, hc
, hclen
);
798 topo_mod_free(mod
, hc
, hclen
);
804 make_hc_auth(topo_mod_t
*mod
, char *fmri
, char **serial
, char **part
,
805 char **rev
, nvlist_t
**auth
)
807 char *starti
, *startn
, *endi
, *copy
;
808 char *aname
= NULL
, *aid
= NULL
, *fs
;
812 if ((copy
= topo_mod_strdup(mod
, fmri
+ 5)) == NULL
)
818 * Make sure there are a valid authority members
820 startn
= strchr(copy
, ':');
821 fs
= strchr(copy
, '/');
823 if (startn
== NULL
|| fs
== NULL
) {
824 topo_mod_strfree(mod
, copy
);
829 * The first colon we encounter must occur before the
836 if (++startn
>= copy
+ len
)
839 if ((starti
= strchr(startn
, '=')) == NULL
)
843 if (++starti
> copy
+ len
)
846 if ((aname
= topo_mod_strdup(mod
, startn
)) == NULL
)
849 startn
= endi
= strchr(starti
, ':');
851 if ((endi
= strchr(starti
, '/')) == NULL
)
855 if ((aid
= topo_mod_strdup(mod
, starti
)) == NULL
)
859 * Return possible serial, part and revision
861 if (strcmp(aname
, FM_FMRI_HC_SERIAL_ID
) == 0) {
862 *serial
= topo_mod_strdup(mod
, aid
);
863 } else if (strcmp(aname
, FM_FMRI_HC_PART
) == 0) {
864 *part
= topo_mod_strdup(mod
, aid
);
865 } else if (strcmp(aname
, FM_FMRI_HC_REVISION
) == 0) {
866 *rev
= topo_mod_strdup(mod
, aid
);
869 if (topo_mod_nvalloc(mod
, &na
,
870 NV_UNIQUE_NAME
) == 0) {
871 (void) nvlist_add_string(na
, aname
,
875 (void) nvlist_add_string(na
, aname
, aid
);
878 topo_mod_strfree(mod
, aname
);
879 topo_mod_strfree(mod
, aid
);
882 } while (startn
!= NULL
);
886 topo_mod_free(mod
, copy
, len
+ 1);
890 topo_mod_free(mod
, copy
, len
+ 1);
891 topo_mod_strfree(mod
, aname
);
892 topo_mod_strfree(mod
, aid
);
899 * This function creates an nvlist to represent the facility portion of an
900 * hc-scheme node, given a string representation of the fmri. This is called by
901 * hc_fmri_str2nvl. If the string does not contain a facility component
902 * (e.g. ?<ftype>=<fname>) then it bails early and returns 0.
904 * On failure it returns -1 and sets the topo mod errno
907 make_facility(topo_mod_t
*mod
, char *str
, nvlist_t
**nvl
)
909 char *fac
, *copy
, *fname
, *ftype
;
913 if ((fac
= strchr(str
, '?')) == NULL
)
917 if ((copy
= topo_mod_strdup(mod
, fac
)) == NULL
)
918 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
923 if ((fname
= strchr(fac
, '=')) == NULL
) {
924 topo_mod_free(mod
, copy
, len
+ 1);
925 return (topo_mod_seterrno(mod
, EMOD_FMRI_MALFORM
));
932 if (topo_mod_nvalloc(mod
, &nf
, NV_UNIQUE_NAME
) != 0) {
933 topo_mod_free(mod
, copy
, len
+ 1);
934 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
937 if (nvlist_add_string(nf
, FM_FMRI_FACILITY_NAME
, fname
) != 0 ||
938 nvlist_add_string(nf
, FM_FMRI_FACILITY_TYPE
, ftype
) != 0) {
939 topo_mod_free(mod
, copy
, len
+ 1);
940 return (topo_mod_seterrno(mod
, EMOD_FMRI_NVL
));
943 topo_mod_free(mod
, copy
, len
+ 1);
952 hc_fmri_str2nvl(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
953 nvlist_t
*in
, nvlist_t
**out
)
955 nvlist_t
**pa
= NULL
;
957 nvlist_t
*auth
= NULL
;
958 nvlist_t
*fac
= NULL
;
960 char *serial
= NULL
, *part
= NULL
, *rev
= NULL
, *hcsn
= NULL
;
964 if (version
> TOPO_METH_STR2NVL_VERSION
)
965 return (topo_mod_seterrno(mod
, EMOD_VER_NEW
));
967 if (nvlist_lookup_string(in
, "fmri-string", &str
) != 0)
968 return (topo_mod_seterrno(mod
, EMOD_METHOD_INVAL
));
970 /* We're expecting a string version of an hc scheme FMRI */
971 if (strncmp(str
, "hc://", 5) != 0)
972 return (topo_mod_seterrno(mod
, EMOD_FMRI_MALFORM
));
974 if ((pa
= make_hc_pairs(mod
, str
, &npairs
)) == NULL
)
975 return (topo_mod_seterrno(mod
, EMOD_FMRI_MALFORM
));
977 if (make_hc_auth(mod
, str
, &serial
, &part
, &rev
, &auth
) < 0)
980 if ((nf
= hc_base_fmri_create(mod
, auth
, part
, rev
, serial
)) == NULL
)
986 * If the last pair in hc-list is offset or physaddr, we move
989 (void) nvlist_lookup_string(pa
[npairs
- 1], FM_FMRI_HC_NAME
, &hcsn
);
990 if (strcmp(hcsn
, FM_FMRI_HC_SPECIFIC_OFFSET
) == 0 ||
991 strcmp(hcsn
, FM_FMRI_HC_SPECIFIC_PHYSADDR
) == 0) {
996 (void) nvlist_lookup_string(pa
[npairs
- 1], FM_FMRI_HC_ID
,
998 val
= strtoull(hcid
, NULL
, 16);
999 if (topo_mod_nvalloc(mod
, &hcsp
, NV_UNIQUE_NAME
) != 0)
1001 if (nvlist_add_uint64(hcsp
, hcsn
, val
) != 0 ||
1002 nvlist_add_nvlist(nf
, FM_FMRI_HC_SPECIFIC
, hcsp
) != 0) {
1011 if ((e
= nvlist_add_uint32(nf
, FM_FMRI_HC_LIST_SZ
, n
)) == 0)
1012 e
= nvlist_add_nvlist_array(nf
, FM_FMRI_HC_LIST
, pa
, n
);
1014 topo_mod_dprintf(mod
, "construction of new hc nvl failed");
1021 for (i
= 0; i
< npairs
; i
++)
1023 topo_mod_free(mod
, pa
, npairs
* sizeof (nvlist_t
*));
1024 topo_mod_strfree(mod
, serial
);
1025 topo_mod_strfree(mod
, part
);
1026 topo_mod_strfree(mod
, rev
);
1029 if (make_facility(mod
, str
, &fac
) == -1)
1033 if (nvlist_add_nvlist(nf
, FM_FMRI_FACILITY
, fac
) != 0)
1043 for (i
= 0; i
< npairs
; i
++)
1045 topo_mod_free(mod
, pa
, npairs
* sizeof (nvlist_t
*));
1047 topo_mod_strfree(mod
, serial
);
1048 topo_mod_strfree(mod
, part
);
1049 topo_mod_strfree(mod
, rev
);
1052 return (topo_mod_seterrno(mod
, EMOD_FMRI_MALFORM
));
1056 hc_list_create(topo_mod_t
*mod
, const char *name
, char *inst
)
1061 if (topo_mod_nvalloc(mod
, &hc
, NV_UNIQUE_NAME
) != 0)
1064 err
= nvlist_add_string(hc
, FM_FMRI_HC_NAME
, name
);
1065 err
|= nvlist_add_string(hc
, FM_FMRI_HC_ID
, inst
);
1075 hc_create_seterror(topo_mod_t
*mod
, nvlist_t
**hcl
, int n
, nvlist_t
*fmri
,
1081 for (i
= 0; i
< n
+ 1; ++i
)
1082 nvlist_free(hcl
[i
]);
1084 topo_mod_free(mod
, hcl
, sizeof (nvlist_t
*) * (n
+ 1));
1089 (void) topo_mod_seterrno(mod
, err
);
1091 topo_mod_dprintf(mod
, "unable to create hc FMRI: %s\n",
1092 topo_mod_errmsg(mod
));
1098 hc_name_canonical(topo_mod_t
*mod
, const char *name
)
1102 if (getenv("NOHCCHECK") != NULL
)
1106 * Only enumerate elements with correct canonical names
1108 for (i
= 0; i
< hc_ncanon
; i
++) {
1109 if (strcmp(name
, hc_canon
[i
].hcc_name
) == 0)
1112 if (i
>= hc_ncanon
) {
1113 topo_mod_dprintf(mod
, "non-canonical name %s\n",
1122 hc_fmri_create(topo_mod_t
*mod
, nvlist_t
*pfmri
, int version
, const char *name
,
1123 topo_instance_t inst
, const nvlist_t
*auth
, const char *part
,
1124 const char *rev
, const char *serial
)
1127 char str
[21]; /* sizeof (UINT64_MAX) + '\0' */
1129 nvlist_t
**phcl
= NULL
;
1130 nvlist_t
**hcl
= NULL
;
1131 nvlist_t
*fmri
= NULL
;
1133 if (version
> FM_HC_SCHEME_VERSION
)
1134 return (hc_create_seterror(mod
,
1135 hcl
, pelems
, fmri
, EMOD_VER_OLD
));
1136 else if (version
< FM_HC_SCHEME_VERSION
)
1137 return (hc_create_seterror(mod
,
1138 hcl
, pelems
, fmri
, EMOD_VER_NEW
));
1141 * Check that the requested name is in our canonical list
1143 if (hc_name_canonical(mod
, name
) == 0)
1144 return (hc_create_seterror(mod
,
1145 hcl
, pelems
, fmri
, EMOD_NONCANON
));
1147 * Copy the parent's HC_LIST
1149 if (pfmri
!= NULL
) {
1150 if (nvlist_lookup_nvlist_array(pfmri
, FM_FMRI_HC_LIST
,
1151 &phcl
, &pelems
) != 0)
1152 return (hc_create_seterror(mod
,
1153 hcl
, pelems
, fmri
, EMOD_FMRI_MALFORM
));
1156 hcl
= topo_mod_zalloc(mod
, sizeof (nvlist_t
*) * (pelems
+ 1));
1158 return (hc_create_seterror(mod
, hcl
, pelems
, fmri
,
1161 for (i
= 0; i
< pelems
; ++i
)
1162 if (topo_mod_nvdup(mod
, phcl
[i
], &hcl
[i
]) != 0)
1163 return (hc_create_seterror(mod
,
1164 hcl
, pelems
, fmri
, EMOD_FMRI_NVL
));
1166 (void) snprintf(str
, sizeof (str
), "%d", inst
);
1167 if ((hcl
[i
] = hc_list_create(mod
, name
, str
)) == NULL
)
1168 return (hc_create_seterror(mod
,
1169 hcl
, pelems
, fmri
, EMOD_FMRI_NVL
));
1171 if ((fmri
= hc_base_fmri_create(mod
, auth
, part
, rev
, serial
)) == NULL
)
1172 return (hc_create_seterror(mod
,
1173 hcl
, pelems
, fmri
, EMOD_FMRI_NVL
));
1175 if (nvlist_add_nvlist_array(fmri
, FM_FMRI_HC_LIST
, hcl
, pelems
+ 1)
1177 return (hc_create_seterror(mod
,
1178 hcl
, pelems
, fmri
, EMOD_FMRI_NVL
));
1181 for (i
= 0; i
< pelems
+ 1; ++i
) {
1182 nvlist_free(hcl
[i
]);
1184 topo_mod_free(mod
, hcl
, sizeof (nvlist_t
*) * (pelems
+ 1));
1192 hc_fmri_create_meth(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
1193 nvlist_t
*in
, nvlist_t
**out
)
1196 nvlist_t
*args
, *pfmri
= NULL
;
1199 char *name
, *serial
, *rev
, *part
;
1201 if (version
> TOPO_METH_FMRI_VERSION
)
1202 return (topo_mod_seterrno(mod
, EMOD_VER_NEW
));
1204 /* First the must-have fields */
1205 if (nvlist_lookup_string(in
, TOPO_METH_FMRI_ARG_NAME
, &name
) != 0)
1206 return (topo_mod_seterrno(mod
, EMOD_METHOD_INVAL
));
1207 if (nvlist_lookup_uint32(in
, TOPO_METH_FMRI_ARG_INST
, &inst
) != 0)
1208 return (topo_mod_seterrno(mod
, EMOD_METHOD_INVAL
));
1215 serial
= rev
= part
= NULL
;
1216 if ((ret
= nvlist_lookup_nvlist(in
, TOPO_METH_FMRI_ARG_NVL
, &args
))
1219 return (topo_mod_seterrno(mod
, EMOD_METHOD_INVAL
));
1222 /* And then optional arguments */
1223 (void) nvlist_lookup_nvlist(args
, TOPO_METH_FMRI_ARG_PARENT
,
1225 (void) nvlist_lookup_nvlist(args
, TOPO_METH_FMRI_ARG_AUTH
,
1227 (void) nvlist_lookup_string(args
, TOPO_METH_FMRI_ARG_PART
,
1229 (void) nvlist_lookup_string(args
, TOPO_METH_FMRI_ARG_REV
, &rev
);
1230 (void) nvlist_lookup_string(args
, TOPO_METH_FMRI_ARG_SER
,
1234 *out
= hc_fmri_create(mod
, pfmri
, version
, name
, inst
, auth
, part
,
1242 topo_mod_walk_cb_t hcw_cb
;
1244 topo_walk_t
*hcw_wp
;
1245 nvlist_t
**hcw_list
;
1253 * Returns true if the given node is beneath the specified FMRI. This uses
1254 * the TOPO_METH_CONTAINS method, because some enumerators (such as external
1255 * enclosures) may want to do a comparison based on chassis WWN instead of the
1256 * instance ID. If this comparison function fails or is not supported, then we
1257 * fall back to a direct name/instance comparison.
1260 hc_match(topo_mod_t
*mod
, tnode_t
*node
, nvlist_t
*fmri
, const char *name
,
1261 topo_instance_t inst
, boolean_t
*result
)
1264 nvlist_t
*arg
, *nvl
;
1268 if (topo_node_resource(node
, &rsrc
, &err
) != 0)
1271 if (topo_mod_nvalloc(mod
, &arg
, NV_UNIQUE_NAME
) != 0 ||
1272 nvlist_add_nvlist(arg
, TOPO_METH_FMRI_ARG_FMRI
,
1274 nvlist_add_nvlist(arg
, TOPO_METH_FMRI_ARG_SUBFMRI
,
1277 (void) topo_mod_seterrno(mod
, EMOD_NOMEM
);
1283 if (topo_method_invoke(node
, TOPO_METH_CONTAINS
,
1284 TOPO_METH_CONTAINS_VERSION
, arg
, &nvl
, &err
) != 0) {
1286 if (err
== ETOPO_METHOD_NOTSUP
) {
1287 match
= (strcmp(name
,
1288 topo_node_name(node
)) == 0 &&
1289 inst
== topo_node_instance(node
));
1295 if (nvlist_lookup_uint32(nvl
, TOPO_METH_CONTAINS_RET
,
1298 (void) topo_mod_seterrno(mod
, EMOD_NVL_INVAL
);
1304 *result
= (match
!= 0);
1309 * Ideally, we should just be able to call topo_walk_bysibling(). But that
1310 * code assumes that the name/instance pair will match, so we need to
1311 * explicitly iterate over children of the parent looking for a matching value.
1314 hc_walk_sibling(topo_mod_t
*mod
, tnode_t
*node
, struct hc_walk
*hwp
,
1315 const char *name
, topo_instance_t inst
)
1317 tnode_t
*pnp
= topo_node_parent(node
);
1318 topo_walk_t
*wp
= hwp
->hcw_wp
;
1323 for (np
= topo_child_first(pnp
); np
!= NULL
;
1324 np
= topo_child_next(pnp
, np
)) {
1326 if (hc_match(mod
, np
, hwp
->hcw_fmri
, name
, inst
,
1327 &matched
) == 0 && matched
) {
1329 if (wp
->tw_mod
!= NULL
)
1330 status
= wp
->tw_cb(mod
, np
, hwp
);
1332 status
= wp
->tw_cb(wp
->tw_thp
, np
, hwp
);
1341 return (TOPO_WALK_TERMINATE
);
1345 * Generic walker for the hc-scheme topo tree. This function uses the
1346 * hierachical nature of the hc-scheme to efficiently step through
1347 * the topo hc tree. Node lookups are done by topo_walk_byid() and
1348 * topo_walk_bysibling() at each component level to avoid unnecessary
1349 * traversal of the tree. hc_walker() never returns TOPO_WALK_NEXT, so
1350 * whether TOPO_WALK_CHILD or TOPO_WALK_SIBLING is specified by
1351 * topo_walk_step() doesn't affect the traversal.
1354 hc_walker(topo_mod_t
*mod
, tnode_t
*node
, void *pdata
)
1357 struct hc_walk
*hwp
= (struct hc_walk
*)pdata
;
1359 char *fname
, *ftype
;
1360 topo_instance_t inst
;
1364 if (i
> hwp
->hcw_end
) {
1365 if (hwp
->hcw_fac
!= NULL
) {
1366 if ((err
= hwp
->hcw_cb(mod
, node
, hwp
->hcw_priv
))
1368 (void) topo_mod_seterrno(mod
, err
);
1369 topo_mod_dprintf(mod
, "hc_walker: callback "
1370 "failed: %s\n ", topo_mod_errmsg(mod
));
1371 return (TOPO_WALK_ERR
);
1373 topo_mod_dprintf(mod
, "hc_walker: callback "
1374 "complete: terminate walk\n");
1375 return (TOPO_WALK_TERMINATE
);
1377 topo_mod_dprintf(mod
, "hc_walker: node not found\n");
1378 return (TOPO_WALK_TERMINATE
);
1382 err
= nvlist_lookup_string(hwp
->hcw_list
[i
], FM_FMRI_HC_NAME
, &name
);
1383 err
|= nvlist_lookup_string(hwp
->hcw_list
[i
], FM_FMRI_HC_ID
, &id
);
1386 (void) topo_mod_seterrno(mod
, EMOD_NVL_INVAL
);
1387 return (TOPO_WALK_ERR
);
1393 * Check to see if our node matches the requested FMRI. If it doesn't
1394 * (because the enumerator determines matching based on something other
1395 * than name/instance, or because we're at the first level below the
1396 * root), then iterate over siblings to find the matching node.
1398 if (hc_match(mod
, node
, hwp
->hcw_fmri
, name
, inst
, &match
) != 0)
1399 return (TOPO_WALK_ERR
);
1402 return (hc_walk_sibling(mod
, node
, hwp
, name
, inst
));
1404 topo_mod_dprintf(mod
, "hc_walker: walking node:%s=%d for hc:"
1405 "%s=%d at %d, end at %d \n", topo_node_name(node
),
1406 topo_node_instance(node
), name
, inst
, i
, hwp
->hcw_end
);
1408 if (i
== hwp
->hcw_end
) {
1411 * We are at the end of the hc-list. Now, check for
1412 * a facility leaf and walk one more time.
1414 if (hwp
->hcw_fac
!= NULL
) {
1415 err
= nvlist_lookup_string(hwp
->hcw_fac
,
1416 FM_FMRI_FACILITY_NAME
, &fname
);
1417 err
|= nvlist_lookup_string(hwp
->hcw_fac
,
1418 FM_FMRI_FACILITY_TYPE
, &ftype
);
1420 (void) topo_mod_seterrno(mod
, EMOD_NVL_INVAL
);
1421 return (TOPO_WALK_ERR
);
1424 topo_mod_dprintf(mod
, "hc_walker: walk to facility "
1425 "node:%s=%s\n", fname
, ftype
);
1426 return (topo_walk_byid(hwp
->hcw_wp
, fname
, 0));
1430 * Otherwise, this is the node we're looking for.
1432 if ((err
= hwp
->hcw_cb(mod
, node
, hwp
->hcw_priv
)) != 0) {
1433 (void) topo_mod_seterrno(mod
, err
);
1434 topo_mod_dprintf(mod
, "hc_walker: callback "
1435 "failed: %s\n ", topo_mod_errmsg(mod
));
1436 return (TOPO_WALK_ERR
);
1438 topo_mod_dprintf(mod
, "hc_walker: callback "
1439 "complete: terminate walk\n");
1440 return (TOPO_WALK_TERMINATE
);
1445 * Move on to the next component in the hc-list
1447 hwp
->hcw_index
= ++i
;
1448 err
= nvlist_lookup_string(hwp
->hcw_list
[i
], FM_FMRI_HC_NAME
, &name
);
1449 err
|= nvlist_lookup_string(hwp
->hcw_list
[i
], FM_FMRI_HC_ID
, &id
);
1451 (void) topo_mod_seterrno(mod
, err
);
1452 return (TOPO_WALK_ERR
);
1456 return (topo_walk_byid(hwp
->hcw_wp
, name
, inst
));
1460 static struct hc_walk
*
1461 hc_walk_init(topo_mod_t
*mod
, tnode_t
*node
, nvlist_t
*rsrc
,
1462 topo_mod_walk_cb_t cb
, void *pdata
)
1466 struct hc_walk
*hwp
;
1469 if ((hwp
= topo_mod_alloc(mod
, sizeof (struct hc_walk
))) == NULL
) {
1470 (void) topo_mod_seterrno(mod
, EMOD_NOMEM
);
1474 if (nvlist_lookup_nvlist_array(rsrc
, FM_FMRI_HC_LIST
, &hwp
->hcw_list
,
1476 topo_mod_dprintf(mod
, "hc_walk_init: failed to lookup %s "
1477 "nvlist\n", FM_FMRI_HC_LIST
);
1478 topo_mod_free(mod
, hwp
, sizeof (struct hc_walk
));
1479 (void) topo_mod_seterrno(mod
, EMOD_METHOD_INVAL
);
1482 if ((ret
= nvlist_lookup_nvlist(rsrc
, FM_FMRI_FACILITY
, &hwp
->hcw_fac
))
1484 if (ret
!= ENOENT
) {
1485 topo_mod_dprintf(mod
, "hc_walk_init: unexpected error "
1486 "looking up %s nvlist", FM_FMRI_FACILITY
);
1487 topo_mod_free(mod
, hwp
, sizeof (struct hc_walk
));
1488 (void) topo_mod_seterrno(mod
, EMOD_METHOD_INVAL
);
1491 hwp
->hcw_fac
= NULL
;
1495 hwp
->hcw_fmri
= rsrc
;
1496 hwp
->hcw_end
= sz
- 1;
1498 hwp
->hcw_priv
= pdata
;
1500 if ((wp
= topo_mod_walk_init(mod
, node
, hc_walker
, (void *)hwp
, &err
))
1502 topo_mod_dprintf(mod
, "hc_walk_init: topo_mod_walk_init failed "
1503 "(%s)\n", topo_strerror(err
));
1504 topo_mod_free(mod
, hwp
, sizeof (struct hc_walk
));
1505 (void) topo_mod_seterrno(mod
, err
);
1514 struct prop_lookup
{
1515 const char *pl_pgroup
;
1516 const char *pl_pname
;
1525 hc_prop_get(topo_mod_t
*mod
, tnode_t
*node
, void *pdata
)
1529 struct prop_lookup
*plp
= (struct prop_lookup
*)pdata
;
1531 (void) topo_prop_getprop(node
, plp
->pl_pgroup
, plp
->pl_pname
,
1532 plp
->pl_args
, &plp
->pl_prop
, &err
);
1538 hc_fmri_prop_get(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
1539 nvlist_t
*in
, nvlist_t
**out
)
1542 struct hc_walk
*hwp
;
1543 struct prop_lookup
*plp
;
1545 if (version
> TOPO_METH_PROP_GET_VERSION
)
1546 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
1548 if ((plp
= topo_mod_alloc(mod
, sizeof (struct prop_lookup
))) == NULL
)
1549 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1551 err
= nvlist_lookup_string(in
, TOPO_PROP_GROUP
,
1552 (char **)&plp
->pl_pgroup
);
1553 err
|= nvlist_lookup_string(in
, TOPO_PROP_VAL_NAME
,
1554 (char **)&plp
->pl_pname
);
1555 err
|= nvlist_lookup_nvlist(in
, TOPO_PROP_RESOURCE
, &plp
->pl_rsrc
);
1557 topo_mod_free(mod
, plp
, sizeof (struct prop_lookup
));
1558 return (topo_mod_seterrno(mod
, EMOD_METHOD_INVAL
));
1562 * Private args to prop method are optional
1564 if ((err
= nvlist_lookup_nvlist(in
, TOPO_PROP_PARGS
, &plp
->pl_args
))
1566 if (err
!= ENOENT
) {
1567 topo_mod_free(mod
, plp
, sizeof (struct prop_lookup
));
1568 return (topo_mod_seterrno(mod
, EMOD_METHOD_INVAL
));
1570 plp
->pl_args
= NULL
;
1574 plp
->pl_prop
= NULL
;
1575 if ((hwp
= hc_walk_init(mod
, node
, plp
->pl_rsrc
, hc_prop_get
,
1576 (void *)plp
)) != NULL
) {
1577 if (topo_walk_step(hwp
->hcw_wp
, TOPO_WALK_CHILD
) ==
1582 topo_walk_fini(hwp
->hcw_wp
);
1583 topo_mod_free(mod
, hwp
, sizeof (struct hc_walk
));
1588 if (plp
->pl_prop
!= NULL
)
1589 *out
= plp
->pl_prop
;
1591 topo_mod_free(mod
, plp
, sizeof (struct prop_lookup
));
1598 hc_pgrp_get(topo_mod_t
*mod
, tnode_t
*node
, void *pdata
)
1602 struct prop_lookup
*plp
= (struct prop_lookup
*)pdata
;
1604 (void) topo_prop_getpgrp(node
, plp
->pl_pgroup
, &plp
->pl_prop
, &err
);
1610 hc_fmri_pgrp_get(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
1611 nvlist_t
*in
, nvlist_t
**out
)
1614 struct hc_walk
*hwp
;
1615 struct prop_lookup
*plp
;
1617 if (version
> TOPO_METH_PGRP_GET_VERSION
)
1618 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
1620 if ((plp
= topo_mod_alloc(mod
, sizeof (struct prop_lookup
))) == NULL
)
1621 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1623 err
= nvlist_lookup_string(in
, TOPO_PROP_GROUP
,
1624 (char **)&plp
->pl_pgroup
);
1625 err
|= nvlist_lookup_nvlist(in
, TOPO_PROP_RESOURCE
, &plp
->pl_rsrc
);
1627 topo_mod_free(mod
, plp
, sizeof (struct prop_lookup
));
1628 return (topo_mod_seterrno(mod
, EMOD_METHOD_INVAL
));
1631 plp
->pl_prop
= NULL
;
1632 if ((hwp
= hc_walk_init(mod
, node
, plp
->pl_rsrc
, hc_pgrp_get
,
1633 (void *)plp
)) != NULL
) {
1634 if (topo_walk_step(hwp
->hcw_wp
, TOPO_WALK_CHILD
) ==
1639 topo_walk_fini(hwp
->hcw_wp
);
1640 topo_mod_free(mod
, hwp
, sizeof (struct hc_walk
));
1645 if (plp
->pl_prop
!= NULL
)
1646 *out
= plp
->pl_prop
;
1648 topo_mod_free(mod
, plp
, sizeof (struct prop_lookup
));
1655 hc_prop_setprop(topo_mod_t
*mod
, tnode_t
*node
, void *pdata
)
1659 struct prop_lookup
*plp
= (struct prop_lookup
*)pdata
;
1661 (void) topo_prop_setprop(node
, plp
->pl_pgroup
, plp
->pl_prop
,
1662 plp
->pl_flag
, plp
->pl_args
, &err
);
1669 hc_fmri_prop_set(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
1670 nvlist_t
*in
, nvlist_t
**out
)
1673 struct hc_walk
*hwp
;
1674 struct prop_lookup
*plp
;
1676 if (version
> TOPO_METH_PROP_SET_VERSION
)
1677 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
1679 if ((plp
= topo_mod_alloc(mod
, sizeof (struct prop_lookup
))) == NULL
)
1680 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1682 err
= nvlist_lookup_string(in
, TOPO_PROP_GROUP
,
1683 (char **)&plp
->pl_pgroup
);
1684 err
|= nvlist_lookup_nvlist(in
, TOPO_PROP_RESOURCE
, &plp
->pl_rsrc
);
1685 err
|= nvlist_lookup_nvlist(in
, TOPO_PROP_VAL
, &plp
->pl_prop
);
1686 err
|= nvlist_lookup_int32(in
, TOPO_PROP_FLAG
, &plp
->pl_flag
);
1688 topo_mod_free(mod
, plp
, sizeof (struct prop_lookup
));
1689 return (topo_mod_seterrno(mod
, EMOD_METHOD_INVAL
));
1693 * Private args to prop method are optional
1695 if ((err
= nvlist_lookup_nvlist(in
, TOPO_PROP_PARGS
, &plp
->pl_args
))
1698 return (topo_mod_seterrno(mod
, EMOD_METHOD_INVAL
));
1700 plp
->pl_args
= NULL
;
1703 if ((hwp
= hc_walk_init(mod
, node
, plp
->pl_rsrc
, hc_prop_setprop
,
1704 (void *)plp
)) != NULL
) {
1705 if (topo_walk_step(hwp
->hcw_wp
, TOPO_WALK_CHILD
) ==
1710 topo_walk_fini(hwp
->hcw_wp
);
1711 topo_mod_free(mod
, hwp
, sizeof (struct hc_walk
));
1716 topo_mod_free(mod
, plp
, sizeof (struct prop_lookup
));
1724 char *ha_method_name
;
1725 topo_version_t ha_method_ver
;
1729 hc_auth_changed(nvlist_t
*nva
, nvlist_t
*nvb
, const char *propname
)
1733 if (nvlist_lookup_string(nva
, propname
, &stra
) != 0 ||
1734 nvlist_lookup_string(nvb
, propname
, &strb
) != 0)
1735 return (FMD_OBJ_STATE_UNKNOWN
);
1737 if (strcmp(stra
, strb
) != 0)
1738 return (FMD_OBJ_STATE_REPLACED
);
1740 return (FMD_OBJ_STATE_STILL_PRESENT
);
1744 hc_is_present(topo_mod_t
*mod
, tnode_t
*node
, void *pdata
)
1747 struct hc_args
*hap
= (struct hc_args
*)pdata
;
1752 * check with the enumerator that created this FMRI
1755 if (topo_method_invoke(node
, TOPO_METH_PRESENT
,
1756 TOPO_METH_PRESENT_VERSION
, hap
->ha_fmri
, &hap
->ha_nvl
,
1760 * If the method exists but failed for some other reason,
1761 * propagate the error as making any decision over presence is
1764 if (err
!= ETOPO_METHOD_NOTSUP
)
1768 * Check the authority information. If the part id or serial
1769 * number doesn't match, then it isn't the same FMRI.
1770 * Otherwise, assume presence.
1772 if (topo_node_resource(node
, &rsrc
, &err
) != 0)
1776 if (hc_auth_changed(hap
->ha_fmri
, rsrc
,
1777 FM_FMRI_HC_SERIAL_ID
) == FMD_OBJ_STATE_REPLACED
||
1778 hc_auth_changed(hap
->ha_fmri
, rsrc
,
1779 FM_FMRI_HC_PART
) == FMD_OBJ_STATE_REPLACED
) {
1784 if (topo_mod_nvalloc(mod
, &hap
->ha_nvl
, NV_UNIQUE_NAME
) != 0)
1785 return (EMOD_NOMEM
);
1787 if (nvlist_add_uint32(hap
->ha_nvl
,
1788 TOPO_METH_PRESENT_RET
, present
) != 0) {
1789 nvlist_free(hap
->ha_nvl
);
1791 return (EMOD_NOMEM
);
1799 hc_fmri_present(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
1800 nvlist_t
*in
, nvlist_t
**out
)
1803 struct hc_walk
*hwp
;
1804 struct hc_args
*hap
;
1806 if (version
> TOPO_METH_PRESENT_VERSION
)
1807 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
1809 if ((hap
= topo_mod_alloc(mod
, sizeof (struct hc_args
))) == NULL
)
1810 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1814 if ((hwp
= hc_walk_init(mod
, node
, hap
->ha_fmri
, hc_is_present
,
1815 (void *)hap
)) != NULL
) {
1816 if (topo_walk_step(hwp
->hcw_wp
, TOPO_WALK_CHILD
) ==
1821 topo_walk_fini(hwp
->hcw_wp
);
1822 topo_mod_free(mod
, hwp
, sizeof (struct hc_walk
));
1827 if (hap
->ha_nvl
!= NULL
)
1830 topo_mod_free(mod
, hap
, sizeof (struct hc_args
));
1836 hc_is_replaced(topo_mod_t
*mod
, tnode_t
*node
, void *pdata
)
1839 struct hc_args
*hap
= (struct hc_args
*)pdata
;
1840 uint32_t present
= 0;
1842 uint32_t rval
= FMD_OBJ_STATE_UNKNOWN
;
1845 * check with the enumerator that created this FMRI
1848 if (topo_method_invoke(node
, TOPO_METH_REPLACED
,
1849 TOPO_METH_REPLACED_VERSION
, hap
->ha_fmri
, &hap
->ha_nvl
,
1852 * If the method exists but failed for some other
1853 * reason, propagate the error as making any decision
1854 * over presence is impossible.
1856 if (err
!= ETOPO_METHOD_NOTSUP
)
1860 * Enumerator didn't provide "replaced" method -
1861 * try "present" method
1863 if (topo_method_invoke(node
, TOPO_METH_PRESENT
,
1864 TOPO_METH_PRESENT_VERSION
, hap
->ha_fmri
, &hap
->ha_nvl
,
1867 * If the method exists but failed for some other
1868 * reason, propagate the error as making any decision
1869 * over presence is impossible.
1871 if (err
!= ETOPO_METHOD_NOTSUP
)
1875 * Enumerator didn't provide "present" method either -
1876 * so check the authority information. If the part id
1877 * or serial number doesn't match, then it isn't the
1878 * same FMRI. Otherwise, if we have a serial number and
1879 * it hasn't changed, then assume it is the same FMRI.
1881 if (topo_node_resource(node
, &rsrc
, &err
) != 0)
1883 rval
= hc_auth_changed(hap
->ha_fmri
, rsrc
,
1885 if (rval
!= FMD_OBJ_STATE_REPLACED
)
1886 rval
= hc_auth_changed(hap
->ha_fmri
, rsrc
,
1887 FM_FMRI_HC_SERIAL_ID
);
1889 if (topo_mod_nvalloc(mod
, &hap
->ha_nvl
,
1890 NV_UNIQUE_NAME
) != 0)
1891 return (EMOD_NOMEM
);
1892 if (nvlist_add_uint32(hap
->ha_nvl
,
1893 TOPO_METH_REPLACED_RET
, rval
) != 0) {
1894 nvlist_free(hap
->ha_nvl
);
1896 return (ETOPO_PROP_NVL
);
1899 (void) nvlist_lookup_uint32(hap
->ha_nvl
,
1900 TOPO_METH_PRESENT_RET
, &present
);
1901 (void) nvlist_remove(hap
->ha_nvl
,
1902 TOPO_METH_PRESENT_RET
, DATA_TYPE_UINT32
);
1903 if (nvlist_add_uint32(hap
->ha_nvl
,
1904 TOPO_METH_REPLACED_RET
,
1905 present
? FMD_OBJ_STATE_UNKNOWN
:
1906 FMD_OBJ_STATE_NOT_PRESENT
) != 0) {
1907 nvlist_free(hap
->ha_nvl
);
1909 return (ETOPO_PROP_NVL
);
1917 hc_fmri_replaced(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
1918 nvlist_t
*in
, nvlist_t
**out
)
1921 struct hc_walk
*hwp
;
1922 struct hc_args
*hap
;
1924 if (version
> TOPO_METH_REPLACED_VERSION
)
1925 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
1927 if ((hap
= topo_mod_alloc(mod
, sizeof (struct hc_args
))) == NULL
)
1928 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1932 if ((hwp
= hc_walk_init(mod
, node
, hap
->ha_fmri
, hc_is_replaced
,
1933 (void *)hap
)) != NULL
) {
1934 if (topo_walk_step(hwp
->hcw_wp
, TOPO_WALK_CHILD
) ==
1939 topo_walk_fini(hwp
->hcw_wp
);
1940 topo_mod_free(mod
, hwp
, sizeof (struct hc_walk
));
1945 if (hap
->ha_nvl
!= NULL
)
1948 topo_mod_free(mod
, hap
, sizeof (struct hc_args
));
1954 hc_unusable(topo_mod_t
*mod
, tnode_t
*node
, void *pdata
)
1957 struct hc_args
*hap
= (struct hc_args
*)pdata
;
1960 * check with the enumerator that created this FMRI
1963 if (topo_method_invoke(node
, TOPO_METH_UNUSABLE
,
1964 TOPO_METH_UNUSABLE_VERSION
, hap
->ha_fmri
, &hap
->ha_nvl
,
1968 * Err on the side of caution and return usable
1970 if (topo_mod_nvalloc(mod
, &hap
->ha_nvl
, NV_UNIQUE_NAME
) == 0)
1971 if (nvlist_add_uint32(hap
->ha_nvl
,
1972 TOPO_METH_UNUSABLE_RET
, 0) == 0)
1975 return (ETOPO_PROP_NVL
);
1982 hc_fmri_unusable(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
1983 nvlist_t
*in
, nvlist_t
**out
)
1986 struct hc_walk
*hwp
;
1987 struct hc_args
*hap
;
1989 if (version
> TOPO_METH_UNUSABLE_VERSION
)
1990 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
1992 if ((hap
= topo_mod_alloc(mod
, sizeof (struct hc_args
))) == NULL
)
1993 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1997 if ((hwp
= hc_walk_init(mod
, node
, hap
->ha_fmri
, hc_unusable
,
1998 (void *)hap
)) != NULL
) {
1999 if (topo_walk_step(hwp
->hcw_wp
, TOPO_WALK_CHILD
) ==
2004 topo_walk_fini(hwp
->hcw_wp
);
2005 topo_mod_free(mod
, hwp
, sizeof (struct hc_walk
));
2010 if (hap
->ha_nvl
!= NULL
)
2013 topo_mod_free(mod
, hap
, sizeof (struct hc_args
));
2019 const char *fl_fac_type
;
2020 uint32_t fl_fac_subtype
;
2022 uint64_t fl_callback
;
2023 uint64_t fl_callback_args
;
2025 uint32_t fl_callback
;
2026 uint32_t fl_callback_args
;
2029 nvlist_t
*fl_fac_rsrc
;
2033 hc_fac_get(topo_mod_t
*mod
, tnode_t
*node
, void *pdata
)
2035 struct fac_lookup
*flp
= (struct fac_lookup
*)pdata
;
2036 topo_walk_cb_t cb
= (topo_walk_cb_t
)flp
->fl_callback
;
2037 topo_faclist_t faclist
, *tmp
;
2041 * Lookup the specified facility node. Return with an error if we can't
2044 if (topo_node_facility(mod
->tm_hdl
, node
, flp
->fl_fac_type
,
2045 flp
->fl_fac_subtype
, &faclist
, &err
) != 0) {
2046 topo_mod_dprintf(mod
, "hc_fac_get: topo_node_facility "
2048 return (TOPO_WALK_ERR
);
2052 * Invoke user's callback for each facility node in the topo list,
2053 * passing in a pointer to the facility node
2055 for (tmp
= topo_list_next(&faclist
.tf_list
); tmp
!= NULL
;
2056 tmp
= topo_list_next(tmp
)) {
2058 if ((err
= cb(mod
->tm_hdl
, tmp
->tf_node
,
2059 (void *)flp
->fl_callback_args
)) != 0) {
2060 (void) topo_mod_seterrno(mod
, err
);
2061 topo_mod_dprintf(mod
, "hc_fac_get: callback failed: "
2062 "%s\n ", topo_mod_errmsg(mod
));
2063 ret
= TOPO_WALK_ERR
;
2068 while ((tmp
= topo_list_next(&faclist
.tf_list
)) != NULL
) {
2069 topo_list_delete(&faclist
.tf_list
, tmp
);
2070 topo_mod_free(mod
, tmp
, sizeof (topo_faclist_t
));
2076 hc_fmri_facility(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
2077 nvlist_t
*in
, nvlist_t
**out
)
2080 struct hc_walk
*hwp
;
2081 struct fac_lookup
*flp
;
2083 if (version
> TOPO_METH_FACILITY_VERSION
)
2084 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
2086 if ((flp
= topo_mod_alloc(mod
, sizeof (struct fac_lookup
))) == NULL
)
2087 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
2090 * lookup arguments: hw resource, facility type, facility subtype,
2091 * callback and callback args
2093 err
= nvlist_lookup_nvlist(in
, TOPO_PROP_RESOURCE
, &flp
->fl_rsrc
);
2094 err
|= nvlist_lookup_string(in
, FM_FMRI_FACILITY_TYPE
,
2095 (char **)&flp
->fl_fac_type
);
2096 err
|= nvlist_lookup_uint32(in
, "type", &flp
->fl_fac_subtype
);
2098 err
|= nvlist_lookup_uint64(in
, "callback", &flp
->fl_callback
);
2099 err
|= nvlist_lookup_uint64(in
, "callback-args",
2100 &flp
->fl_callback_args
);
2102 err
|= nvlist_lookup_uint32(in
, "callback", &flp
->fl_callback
);
2103 err
|= nvlist_lookup_uint32(in
, "callback-args",
2104 &flp
->fl_callback_args
);
2107 topo_mod_dprintf(mod
, "hc_fmri_facility: failed to construct "
2108 "walker arg nvlist\n");
2109 topo_mod_free(mod
, flp
, sizeof (struct fac_lookup
));
2110 return (topo_mod_seterrno(mod
, EMOD_METHOD_INVAL
));
2113 flp
->fl_fac_rsrc
= NULL
;
2114 if ((hwp
= hc_walk_init(mod
, node
, flp
->fl_rsrc
, hc_fac_get
,
2115 (void *)flp
)) != NULL
) {
2116 if (topo_walk_step(hwp
->hcw_wp
, TOPO_WALK_CHILD
) ==
2121 topo_walk_fini(hwp
->hcw_wp
);
2122 topo_mod_free(mod
, hwp
, sizeof (struct hc_walk
));
2124 topo_mod_dprintf(mod
, "hc_fmri_facility: failed to initialize "
2129 if (flp
->fl_fac_rsrc
!= NULL
)
2130 *out
= flp
->fl_fac_rsrc
;
2132 topo_mod_free(mod
, flp
, sizeof (struct fac_lookup
));
2139 hc_expand(topo_mod_t
*mod
, tnode_t
*node
, void *pdata
)
2144 struct hc_args
*hap
= (struct hc_args
*)pdata
;
2145 const char *names
[] = {
2146 FM_FMRI_HC_SERIAL_ID
,
2148 FM_FMRI_HC_REVISION
,
2152 if (topo_node_resource(node
, &nvl
, &err
) != 0)
2153 return (ETOPO_METHOD_FAIL
);
2155 for (namep
= names
; *namep
!= NULL
; namep
++) {
2156 char *in_val
, *node_val
;
2158 if (nvlist_lookup_string(nvl
, *namep
, &node_val
) != 0)
2161 if (nvlist_lookup_string(hap
->ha_fmri
, *namep
, &in_val
) == 0) {
2162 if (strcmp(in_val
, node_val
) == 0)
2164 (void) nvlist_remove(hap
->ha_fmri
, *namep
,
2168 if (nvlist_add_string(hap
->ha_fmri
, *namep
, node_val
) != 0) {
2170 return (ETOPO_PROP_NVL
);
2180 hc_fmri_expand(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
2181 nvlist_t
*in
, nvlist_t
**out
)
2184 struct hc_walk
*hwp
;
2185 struct hc_args
*hap
;
2187 if (version
> TOPO_METH_EXPAND_VERSION
)
2188 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
2190 if ((hap
= topo_mod_alloc(mod
, sizeof (struct hc_args
))) == NULL
)
2191 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
2195 if ((hwp
= hc_walk_init(mod
, node
, hap
->ha_fmri
, hc_expand
,
2196 (void *)hap
)) != NULL
) {
2197 if (topo_walk_step(hwp
->hcw_wp
, TOPO_WALK_CHILD
) ==
2202 topo_walk_fini(hwp
->hcw_wp
);
2207 topo_mod_free(mod
, hwp
, sizeof (struct hc_walk
));
2209 /* expand method should not return out nvlist */
2210 assert(hap
->ha_nvl
== NULL
);
2212 topo_mod_free(mod
, hap
, sizeof (struct hc_args
));
2218 hc_retire_subr(topo_mod_t
*mod
, tnode_t
*node
, void *pdata
)
2221 struct hc_args
*hap
= (struct hc_args
*)pdata
;
2223 topo_mod_dprintf(mod
, "hc_retire_subr: invoking method %s\n",
2224 hap
->ha_method_name
);
2226 * check with the enumerator that created this FMRI
2229 rc
= topo_method_invoke(node
, hap
->ha_method_name
,
2230 hap
->ha_method_ver
, hap
->ha_fmri
, &hap
->ha_nvl
, &err
);
2232 topo_mod_dprintf(mod
, "hc_retire_subr: invoking method %s "
2233 "returned %d\n", hap
->ha_method_name
, rc
);
2235 return (rc
< 0 ? err
: 0);
2239 hc_fmri_retire_subr(topo_mod_t
*mod
, tnode_t
*node
, char *method_name
,
2240 topo_version_t builtin_version
, topo_version_t version
, nvlist_t
*in
,
2244 struct hc_walk
*hwp
;
2245 struct hc_args
*hap
;
2247 if (version
> builtin_version
)
2248 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
2250 if ((hap
= topo_mod_alloc(mod
, sizeof (struct hc_args
))) == NULL
)
2251 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
2255 hap
->ha_method_name
= method_name
;
2256 hap
->ha_method_ver
= version
;
2257 if ((hwp
= hc_walk_init(mod
, node
, hap
->ha_fmri
, hc_retire_subr
,
2258 (void *)hap
)) != NULL
) {
2259 if (topo_walk_step(hwp
->hcw_wp
, TOPO_WALK_CHILD
) ==
2264 topo_walk_fini(hwp
->hcw_wp
);
2269 topo_mod_free(mod
, hwp
, sizeof (struct hc_walk
));
2271 if (hap
->ha_nvl
!= NULL
)
2274 topo_mod_free(mod
, hap
, sizeof (struct hc_args
));
2280 hc_fmri_retire(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
2281 nvlist_t
*in
, nvlist_t
**out
)
2283 return (hc_fmri_retire_subr(mod
, node
, TOPO_METH_RETIRE
,
2284 TOPO_METH_RETIRE_VERSION
, version
, in
, out
));
2288 hc_fmri_unretire(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
2289 nvlist_t
*in
, nvlist_t
**out
)
2291 return (hc_fmri_retire_subr(mod
, node
, TOPO_METH_UNRETIRE
,
2292 TOPO_METH_UNRETIRE_VERSION
, version
, in
, out
));
2296 hc_fmri_service_state(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t version
,
2297 nvlist_t
*in
, nvlist_t
**out
)
2299 return (hc_fmri_retire_subr(mod
, node
, TOPO_METH_SERVICE_STATE
,
2300 TOPO_METH_SERVICE_STATE_VERSION
, version
, in
, out
));