Print this page
patch tsoome-feedback
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/fm/topo/libtopo/common/hc.c
+++ new/usr/src/lib/fm/topo/libtopo/common/hc.c
1 1 /*
2 2 *
3 3 * CDDL HEADER START
4 4 *
5 5 * The contents of this file are subject to the terms of the
6 6 * Common Development and Distribution License (the "License").
7 7 * You may not use this file except in compliance with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22
23 23 /*
24 24 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
25 25 */
26 26
27 27 #include <stdio.h>
28 28 #include <stdlib.h>
29 29 #include <string.h>
30 30 #include <errno.h>
31 31 #include <ctype.h>
32 32 #include <alloca.h>
33 33 #include <assert.h>
34 34 #include <limits.h>
35 35 #include <zone.h>
36 36 #include <fm/topo_mod.h>
37 37 #include <fm/topo_hc.h>
38 38 #include <fm/fmd_fmri.h>
39 39 #include <sys/param.h>
40 40 #include <sys/systeminfo.h>
41 41 #include <sys/fm/protocol.h>
42 42 #include <sys/stat.h>
43 43 #include <sys/systeminfo.h>
44 44 #include <sys/utsname.h>
45 45
46 46 #include <topo_method.h>
47 47 #include <topo_module.h>
48 48 #include <topo_subr.h>
49 49 #include <topo_prop.h>
50 50 #include <topo_tree.h>
51 51 #include <hc.h>
52 52
53 53 static int hc_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
54 54 topo_instance_t, void *, void *);
55 55 static void hc_release(topo_mod_t *, tnode_t *);
56 56 static int hc_fmri_nvl2str(topo_mod_t *, tnode_t *, topo_version_t,
57 57 nvlist_t *, nvlist_t **);
58 58 static int hc_fmri_str2nvl(topo_mod_t *, tnode_t *, topo_version_t,
59 59 nvlist_t *, nvlist_t **);
60 60 static int hc_compare(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
61 61 nvlist_t **);
62 62 static int hc_fmri_present(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
63 63 nvlist_t **);
64 64 static int hc_fmri_replaced(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
65 65 nvlist_t **);
66 66 static int hc_fmri_unusable(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
67 67 nvlist_t **);
68 68 static int hc_fmri_expand(topo_mod_t *, tnode_t *, topo_version_t,
69 69 nvlist_t *, nvlist_t **);
70 70 static int hc_fmri_retire(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
71 71 nvlist_t **);
72 72 static int hc_fmri_unretire(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
73 73 nvlist_t **);
74 74 static int hc_fmri_service_state(topo_mod_t *, tnode_t *, topo_version_t,
75 75 nvlist_t *, nvlist_t **);
76 76 static int hc_fmri_create_meth(topo_mod_t *, tnode_t *, topo_version_t,
77 77 nvlist_t *, nvlist_t **);
78 78 static int hc_fmri_prop_get(topo_mod_t *, tnode_t *, topo_version_t,
79 79 nvlist_t *, nvlist_t **);
80 80 static int hc_fmri_prop_set(topo_mod_t *, tnode_t *, topo_version_t,
81 81 nvlist_t *, nvlist_t **);
82 82 static int hc_fmri_pgrp_get(topo_mod_t *, tnode_t *, topo_version_t,
83 83 nvlist_t *, nvlist_t **);
84 84 static int hc_fmri_facility(topo_mod_t *, tnode_t *, topo_version_t,
85 85 nvlist_t *, nvlist_t **);
86 86
87 87 static nvlist_t *hc_fmri_create(topo_mod_t *, nvlist_t *, int, const char *,
88 88 topo_instance_t inst, const nvlist_t *, const char *, const char *,
89 89 const char *);
90 90
91 91 const topo_method_t hc_methods[] = {
92 92 { TOPO_METH_NVL2STR, TOPO_METH_NVL2STR_DESC, TOPO_METH_NVL2STR_VERSION,
93 93 TOPO_STABILITY_INTERNAL, hc_fmri_nvl2str },
94 94 { TOPO_METH_STR2NVL, TOPO_METH_STR2NVL_DESC, TOPO_METH_STR2NVL_VERSION,
95 95 TOPO_STABILITY_INTERNAL, hc_fmri_str2nvl },
96 96 { TOPO_METH_COMPARE, TOPO_METH_COMPARE_DESC, TOPO_METH_COMPARE_VERSION,
97 97 TOPO_STABILITY_INTERNAL, hc_compare },
98 98 { TOPO_METH_PRESENT, TOPO_METH_PRESENT_DESC, TOPO_METH_PRESENT_VERSION,
99 99 TOPO_STABILITY_INTERNAL, hc_fmri_present },
100 100 { TOPO_METH_REPLACED, TOPO_METH_REPLACED_DESC,
101 101 TOPO_METH_REPLACED_VERSION, TOPO_STABILITY_INTERNAL,
102 102 hc_fmri_replaced },
103 103 { TOPO_METH_UNUSABLE, TOPO_METH_UNUSABLE_DESC,
104 104 TOPO_METH_UNUSABLE_VERSION, TOPO_STABILITY_INTERNAL,
105 105 hc_fmri_unusable },
106 106 { TOPO_METH_EXPAND, TOPO_METH_EXPAND_DESC,
107 107 TOPO_METH_EXPAND_VERSION, TOPO_STABILITY_INTERNAL,
108 108 hc_fmri_expand },
109 109 { TOPO_METH_RETIRE, TOPO_METH_RETIRE_DESC,
110 110 TOPO_METH_RETIRE_VERSION, TOPO_STABILITY_INTERNAL,
111 111 hc_fmri_retire },
112 112 { TOPO_METH_UNRETIRE, TOPO_METH_UNRETIRE_DESC,
113 113 TOPO_METH_UNRETIRE_VERSION, TOPO_STABILITY_INTERNAL,
114 114 hc_fmri_unretire },
115 115 { TOPO_METH_SERVICE_STATE, TOPO_METH_SERVICE_STATE_DESC,
116 116 TOPO_METH_SERVICE_STATE_VERSION, TOPO_STABILITY_INTERNAL,
117 117 hc_fmri_service_state },
118 118 { TOPO_METH_FMRI, TOPO_METH_FMRI_DESC, TOPO_METH_FMRI_VERSION,
119 119 TOPO_STABILITY_INTERNAL, hc_fmri_create_meth },
120 120 { TOPO_METH_PROP_GET, TOPO_METH_PROP_GET_DESC,
121 121 TOPO_METH_PROP_GET_VERSION, TOPO_STABILITY_INTERNAL,
122 122 hc_fmri_prop_get },
123 123 { TOPO_METH_PROP_SET, TOPO_METH_PROP_SET_DESC,
124 124 TOPO_METH_PROP_SET_VERSION, TOPO_STABILITY_INTERNAL,
125 125 hc_fmri_prop_set },
126 126 { TOPO_METH_PGRP_GET, TOPO_METH_PGRP_GET_DESC,
127 127 TOPO_METH_PGRP_GET_VERSION, TOPO_STABILITY_INTERNAL,
128 128 hc_fmri_pgrp_get },
129 129 { TOPO_METH_FACILITY, TOPO_METH_FACILITY_DESC,
130 130 TOPO_METH_FACILITY_VERSION, TOPO_STABILITY_INTERNAL,
131 131 hc_fmri_facility },
132 132 { NULL }
133 133 };
134 134
135 135 static const topo_modops_t hc_ops =
136 136 { hc_enum, hc_release };
137 137 static const topo_modinfo_t hc_info =
138 138 { HC, FM_FMRI_SCHEME_HC, HC_VERSION, &hc_ops };
139 139
140 140 static const hcc_t hc_canon[] = {
141 141 { BANK, TOPO_STABILITY_PRIVATE },
142 142 { BAY, TOPO_STABILITY_PRIVATE },
143 143 { BLADE, TOPO_STABILITY_PRIVATE },
144 144 { BRANCH, TOPO_STABILITY_PRIVATE },
145 145 { CMP, TOPO_STABILITY_PRIVATE },
146 146 { CENTERPLANE, TOPO_STABILITY_PRIVATE },
147 147 { CHASSIS, TOPO_STABILITY_PRIVATE },
148 148 { CHIP, TOPO_STABILITY_PRIVATE },
149 149 { CHIP_SELECT, TOPO_STABILITY_PRIVATE },
150 150 { CORE, TOPO_STABILITY_PRIVATE },
151 151 { CONTROLLER, TOPO_STABILITY_PRIVATE },
152 152 { CPU, TOPO_STABILITY_PRIVATE },
153 153 { CPUBOARD, TOPO_STABILITY_PRIVATE },
154 154 { DIMM, TOPO_STABILITY_PRIVATE },
155 155 { DISK, TOPO_STABILITY_PRIVATE },
156 156 { DRAM, TOPO_STABILITY_PRIVATE },
157 157 { DRAMCHANNEL, TOPO_STABILITY_PRIVATE },
158 158 { FAN, TOPO_STABILITY_PRIVATE },
159 159 { FANBOARD, TOPO_STABILITY_PRIVATE },
160 160 { FANMODULE, TOPO_STABILITY_PRIVATE },
161 161 { HBA, TOPO_STABILITY_PRIVATE },
162 162 { HOSTBRIDGE, TOPO_STABILITY_PRIVATE },
163 163 { INTERCONNECT, TOPO_STABILITY_PRIVATE },
164 164 { IOBOARD, TOPO_STABILITY_PRIVATE },
165 165 { IPORT, TOPO_STABILITY_PRIVATE },
166 166 { MEMBOARD, TOPO_STABILITY_PRIVATE },
167 167 { MEMORYBUFFER, TOPO_STABILITY_PRIVATE },
168 168 { MEMORYCONTROL, TOPO_STABILITY_PRIVATE },
169 169 { MICROCORE, TOPO_STABILITY_PRIVATE },
170 170 { MOTHERBOARD, TOPO_STABILITY_PRIVATE },
171 171 { NIU, TOPO_STABILITY_PRIVATE },
172 172 { NIUFN, TOPO_STABILITY_PRIVATE },
173 173 { PCI_BUS, TOPO_STABILITY_PRIVATE },
174 174 { PCI_DEVICE, TOPO_STABILITY_PRIVATE },
175 175 { PCI_FUNCTION, TOPO_STABILITY_PRIVATE },
176 176 { PCIEX_BUS, TOPO_STABILITY_PRIVATE },
177 177 { PCIEX_DEVICE, TOPO_STABILITY_PRIVATE },
178 178 { PCIEX_FUNCTION, TOPO_STABILITY_PRIVATE },
179 179 { PCIEX_ROOT, TOPO_STABILITY_PRIVATE },
180 180 { PCIEX_SWUP, TOPO_STABILITY_PRIVATE },
181 181 { PCIEX_SWDWN, TOPO_STABILITY_PRIVATE },
182 182 { POWERBOARD, TOPO_STABILITY_PRIVATE },
183 183 { POWERMODULE, TOPO_STABILITY_PRIVATE },
184 184 { PSU, TOPO_STABILITY_PRIVATE },
185 185 { RANK, TOPO_STABILITY_PRIVATE },
186 186 { RECEPTACLE, TOPO_STABILITY_PRIVATE },
187 187 { RISER, TOPO_STABILITY_PRIVATE },
188 188 { SASEXPANDER, TOPO_STABILITY_PRIVATE },
189 189 { SCSI_DEVICE, TOPO_STABILITY_PRIVATE },
190 190 { SHELF, TOPO_STABILITY_PRIVATE },
191 191 { SES_ENCLOSURE, TOPO_STABILITY_PRIVATE },
192 192 { SMP_DEVICE, TOPO_STABILITY_PRIVATE },
193 193 { SP, TOPO_STABILITY_PRIVATE },
194 194 { STRAND, TOPO_STABILITY_PRIVATE },
195 195 { SUBCHASSIS, TOPO_STABILITY_PRIVATE },
196 196 { SYSTEMBOARD, TOPO_STABILITY_PRIVATE },
197 197 { XAUI, TOPO_STABILITY_PRIVATE },
198 198 { XFP, TOPO_STABILITY_PRIVATE }
199 199 };
200 200
201 201 static int hc_ncanon = sizeof (hc_canon) / sizeof (hcc_t);
202 202
203 203 int
204 204 hc_init(topo_mod_t *mod, topo_version_t version)
205 205 {
206 206 /*
207 207 * Turn on module debugging output
208 208 */
209 209 if (getenv("TOPOHCDEBUG"))
210 210 topo_mod_setdebug(mod);
211 211
212 212 topo_mod_dprintf(mod, "initializing hc builtin\n");
213 213
214 214 if (version != HC_VERSION)
215 215 return (topo_mod_seterrno(mod, EMOD_VER_NEW));
216 216
217 217 if (topo_mod_register(mod, &hc_info, TOPO_VERSION) != 0) {
218 218 topo_mod_dprintf(mod, "failed to register hc: "
219 219 "%s\n", topo_mod_errmsg(mod));
220 220 return (-1); /* mod errno already set */
221 221 }
222 222
223 223 return (0);
224 224 }
225 225
226 226 void
227 227 hc_fini(topo_mod_t *mod)
228 228 {
229 229 topo_mod_unregister(mod);
230 230 }
231 231
232 232
233 233 static const topo_pgroup_info_t sys_pgroup = {
234 234 TOPO_PGROUP_SYSTEM,
235 235 TOPO_STABILITY_PRIVATE,
236 236 TOPO_STABILITY_PRIVATE,
237 237 1
238 238 };
239 239
240 240 static const topo_pgroup_info_t auth_pgroup = {
241 241 FM_FMRI_AUTHORITY,
242 242 TOPO_STABILITY_PRIVATE,
243 243 TOPO_STABILITY_PRIVATE,
244 244 1
245 245 };
246 246
247 247 static void
248 248 hc_prop_set(tnode_t *node, nvlist_t *auth)
249 249 {
250 250 int err;
251 251 char isa[MAXNAMELEN];
252 252 struct utsname uts;
253 253 char *prod, *psn, *csn, *server;
254 254
255 255 if (auth == NULL)
256 256 return;
257 257
258 258 if (topo_pgroup_create(node, &auth_pgroup, &err) != 0) {
259 259 if (err != ETOPO_PROP_DEFD)
260 260 return;
261 261 }
262 262
263 263 /*
264 264 * Inherit if we can, it saves memory
265 265 */
266 266 if ((topo_prop_inherit(node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT,
267 267 &err) != 0) && (err != ETOPO_PROP_DEFD)) {
268 268 if (nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT, &prod)
269 269 == 0)
270 270 (void) topo_prop_set_string(node, FM_FMRI_AUTHORITY,
271 271 FM_FMRI_AUTH_PRODUCT, TOPO_PROP_IMMUTABLE, prod,
272 272 &err);
273 273 }
274 274 if ((topo_prop_inherit(node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT_SN,
275 275 &err) != 0) && (err != ETOPO_PROP_DEFD)) {
276 276 if (nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN, &psn)
277 277 == 0)
278 278 (void) topo_prop_set_string(node, FM_FMRI_AUTHORITY,
279 279 FM_FMRI_AUTH_PRODUCT_SN, TOPO_PROP_IMMUTABLE, psn,
280 280 &err);
281 281 }
282 282 if ((topo_prop_inherit(node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
283 283 &err) != 0) && (err != ETOPO_PROP_DEFD)) {
284 284 if (nvlist_lookup_string(auth, FM_FMRI_AUTH_CHASSIS, &csn) == 0)
285 285 (void) topo_prop_set_string(node, FM_FMRI_AUTHORITY,
286 286 FM_FMRI_AUTH_CHASSIS, TOPO_PROP_IMMUTABLE, csn,
287 287 &err);
288 288 }
289 289 if ((topo_prop_inherit(node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_SERVER,
290 290 &err) != 0) && (err != ETOPO_PROP_DEFD)) {
291 291 if (nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER, &server)
292 292 == 0)
293 293 (void) topo_prop_set_string(node, FM_FMRI_AUTHORITY,
294 294 FM_FMRI_AUTH_SERVER, TOPO_PROP_IMMUTABLE, server,
295 295 &err);
296 296 }
297 297
298 298 if (topo_pgroup_create(node, &sys_pgroup, &err) != 0)
299 299 return;
300 300
301 301 isa[0] = '\0';
302 302 (void) sysinfo(SI_ARCHITECTURE, isa, sizeof (isa));
303 303 (void) uname(&uts);
304 304 (void) topo_prop_set_string(node, TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA,
305 305 TOPO_PROP_IMMUTABLE, isa, &err);
306 306 (void) topo_prop_set_string(node, TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE,
307 307 TOPO_PROP_IMMUTABLE, uts.machine, &err);
308 308 }
309 309
310 310 /*ARGSUSED*/
311 311 int
312 312 hc_enum(topo_mod_t *mod, tnode_t *pnode, const char *name, topo_instance_t min,
313 313 topo_instance_t max, void *notused1, void *notused2)
314 314 {
315 315 int isglobal = (getzoneid() == GLOBAL_ZONEID);
316 316 nvlist_t *pfmri = NULL;
317 317 nvlist_t *nvl;
318 318 nvlist_t *auth;
319 319 tnode_t *node;
320 320 int err;
321 321 /*
322 322 * Register root node methods
323 323 */
324 324 if (strcmp(name, HC) == 0) {
325 325 (void) topo_method_register(mod, pnode, hc_methods);
326 326 return (0);
327 327 }
328 328 if (min != max) {
329 329 topo_mod_dprintf(mod,
330 330 "Request to enumerate %s component with an "
331 331 "ambiguous instance number, min (%d) != max (%d).\n",
332 332 HC, min, max);
333 333 return (topo_mod_seterrno(mod, EINVAL));
334 334 }
335 335
336 336 if (!isglobal)
337 337 return (0);
338 338
339 339 (void) topo_node_resource(pnode, &pfmri, &err);
340 340 auth = topo_mod_auth(mod, pnode);
341 341 nvl = hc_fmri_create(mod, pfmri, FM_HC_SCHEME_VERSION, name, min,
342 342 auth, NULL, NULL, NULL);
343 343 nvlist_free(pfmri); /* callee ignores NULLs */
344 344 if (nvl == NULL) {
345 345 nvlist_free(auth);
346 346 return (-1);
347 347 }
348 348
349 349 if ((node = topo_node_bind(mod, pnode, name, min, nvl)) == NULL) {
350 350 topo_mod_dprintf(mod, "topo_node_bind failed: %s\n",
351 351 topo_strerror(topo_mod_errno(mod)));
352 352 nvlist_free(auth);
353 353 nvlist_free(nvl);
354 354 return (-1);
355 355 }
356 356
357 357 /*
358 358 * Set FRU for the motherboard node
359 359 */
360 360 if (strcmp(name, MOTHERBOARD) == 0)
361 361 (void) topo_node_fru_set(node, nvl, 0, &err);
362 362
363 363 hc_prop_set(node, auth);
364 364 nvlist_free(nvl);
365 365 nvlist_free(auth);
366 366
367 367 return (0);
368 368 }
369 369
370 370 /*ARGSUSED*/
371 371 static void
372 372 hc_release(topo_mod_t *mp, tnode_t *node)
373 373 {
374 374 topo_method_unregister_all(mp, node);
375 375 }
376 376
377 377 static int
378 378 fmri_compare(topo_mod_t *mod, nvlist_t *nv1, nvlist_t *nv2)
379 379 {
380 380 uint8_t v1, v2;
381 381 nvlist_t **hcp1, **hcp2;
382 382 nvlist_t *f1 = NULL, *f2 = NULL;
383 383 int err, i;
384 384 uint_t nhcp1, nhcp2;
385 385 char *f1str, *f2str;
386 386
387 387 if (nvlist_lookup_uint8(nv1, FM_VERSION, &v1) != 0 ||
388 388 nvlist_lookup_uint8(nv2, FM_VERSION, &v2) != 0 ||
389 389 v1 > FM_HC_SCHEME_VERSION || v2 > FM_HC_SCHEME_VERSION)
390 390 return (topo_mod_seterrno(mod, EMOD_FMRI_VERSION));
391 391
392 392 err = nvlist_lookup_nvlist_array(nv1, FM_FMRI_HC_LIST, &hcp1, &nhcp1);
393 393 err |= nvlist_lookup_nvlist_array(nv2, FM_FMRI_HC_LIST, &hcp2, &nhcp2);
394 394 if (err != 0)
395 395 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
396 396
397 397 if (nhcp1 != nhcp2)
398 398 return (0);
399 399
400 400 for (i = 0; i < nhcp1; i++) {
401 401 char *nm1 = NULL;
402 402 char *nm2 = NULL;
403 403 char *id1 = NULL;
404 404 char *id2 = NULL;
405 405
406 406 (void) nvlist_lookup_string(hcp1[i], FM_FMRI_HC_NAME, &nm1);
407 407 (void) nvlist_lookup_string(hcp2[i], FM_FMRI_HC_NAME, &nm2);
408 408 (void) nvlist_lookup_string(hcp1[i], FM_FMRI_HC_ID, &id1);
409 409 (void) nvlist_lookup_string(hcp2[i], FM_FMRI_HC_ID, &id2);
410 410 if (nm1 == NULL || nm2 == NULL || id1 == NULL || id2 == NULL)
411 411 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
412 412
413 413 if (strcmp(nm1, nm2) == 0 && strcmp(id1, id2) == 0)
414 414 continue;
415 415
416 416 return (0);
417 417 }
418 418
419 419 /*
420 420 * Finally, check if the FMRI's represent a facility node. If so, then
421 421 * verify that the facilty type ("sensor"|"indicator") and facility
422 422 * name match.
423 423 */
424 424 (void) nvlist_lookup_nvlist(nv1, FM_FMRI_FACILITY, &f1);
425 425 (void) nvlist_lookup_nvlist(nv2, FM_FMRI_FACILITY, &f2);
426 426
427 427 if (f1 == NULL && f2 == NULL)
428 428 return (1);
429 429 else if (f1 == NULL || f2 == NULL)
430 430 return (0);
431 431
432 432 if (nvlist_lookup_string(f1, FM_FMRI_FACILITY_NAME, &f1str) == 0 &&
433 433 nvlist_lookup_string(f2, FM_FMRI_FACILITY_NAME, &f2str) == 0 &&
434 434 strcmp(f1str, f2str) == 0 &&
435 435 nvlist_lookup_string(f1, FM_FMRI_FACILITY_TYPE, &f1str) == 0 &&
436 436 nvlist_lookup_string(f2, FM_FMRI_FACILITY_TYPE, &f2str) == 0 &&
437 437 strcmp(f1str, f2str) == 0) {
438 438 return (1);
439 439 }
440 440 return (0);
441 441 }
442 442
443 443 /*ARGSUSED*/
444 444 static int
445 445 hc_compare(topo_mod_t *mod, tnode_t *node, topo_version_t version,
446 446 nvlist_t *in, nvlist_t **out)
447 447 {
448 448 int ret;
449 449 uint32_t compare;
450 450 nvlist_t *nv1, *nv2;
451 451
452 452 if (version > TOPO_METH_COMPARE_VERSION)
453 453 return (topo_mod_seterrno(mod, EMOD_VER_NEW));
454 454
455 455 if (nvlist_lookup_nvlist(in, TOPO_METH_FMRI_ARG_NV1, &nv1) != 0 ||
456 456 nvlist_lookup_nvlist(in, TOPO_METH_FMRI_ARG_NV2, &nv2) != 0)
457 457 return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
458 458
459 459 ret = fmri_compare(mod, nv1, nv2);
460 460 if (ret < 0)
461 461 return (-1);
462 462
463 463 compare = ret;
464 464 if (topo_mod_nvalloc(mod, out, NV_UNIQUE_NAME) == 0) {
465 465 if (nvlist_add_uint32(*out, TOPO_METH_COMPARE_RET,
466 466 compare) == 0)
467 467 return (0);
468 468 else
469 469 nvlist_free(*out);
470 470 }
471 471
472 472 return (-1);
473 473 }
474 474
475 475 static ssize_t
476 476 fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen)
477 477 {
478 478 nvlist_t **hcprs = NULL;
479 479 nvlist_t *hcsp = NULL;
480 480 nvlist_t *anvl = NULL;
481 481 nvpair_t *apair;
482 482 nvlist_t *fnvl;
483 483 uint8_t version;
484 484 ssize_t size = 0;
485 485 uint_t hcnprs;
486 486 char *serial = NULL;
487 487 char *part = NULL;
488 488 char *root = NULL;
489 489 char *rev = NULL;
490 490 char *aname, *aval;
491 491 char *fname = NULL, *ftype = NULL;
492 492 int err, i;
493 493
494 494 if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 ||
495 495 version > FM_HC_SCHEME_VERSION)
496 496 return (0);
497 497
498 498 /* Get authority, if present */
499 499 err = nvlist_lookup_nvlist(nvl, FM_FMRI_AUTHORITY, &anvl);
500 500 if (err != 0 && err != ENOENT)
501 501 return (0);
502 502
503 503 (void) nvlist_lookup_string(nvl, FM_FMRI_HC_ROOT, &root);
504 504
505 505 err = nvlist_lookup_nvlist_array(nvl, FM_FMRI_HC_LIST, &hcprs, &hcnprs);
506 506 if (err != 0 || hcprs == NULL)
507 507 return (0);
508 508
509 509 (void) nvlist_lookup_string(nvl, FM_FMRI_HC_SERIAL_ID, &serial);
510 510 (void) nvlist_lookup_string(nvl, FM_FMRI_HC_PART, &part);
511 511 (void) nvlist_lookup_string(nvl, FM_FMRI_HC_REVISION, &rev);
512 512
513 513 /* hc:// */
514 514 topo_fmristr_build(&size, buf, buflen, FM_FMRI_SCHEME_HC, NULL, "://");
515 515
516 516 /* authority, if any */
517 517 if (anvl != NULL) {
518 518 for (apair = nvlist_next_nvpair(anvl, NULL);
519 519 apair != NULL; apair = nvlist_next_nvpair(anvl, apair)) {
520 520 if (nvpair_type(apair) != DATA_TYPE_STRING ||
521 521 nvpair_value_string(apair, &aval) != 0)
522 522 continue;
523 523 aname = nvpair_name(apair);
524 524 topo_fmristr_build(&size, buf, buflen, ":", NULL, NULL);
525 525 topo_fmristr_build(&size, buf, buflen, "=",
526 526 aname, aval);
527 527 }
528 528 }
529 529
530 530 /* hardware-id part */
531 531 topo_fmristr_build(&size,
532 532 buf, buflen, serial, ":" FM_FMRI_HC_SERIAL_ID "=", NULL);
533 533 topo_fmristr_build(&size,
534 534 buf, buflen, part, ":" FM_FMRI_HC_PART "=", NULL);
535 535 topo_fmristr_build(&size,
536 536 buf, buflen, rev, ":" FM_FMRI_HC_REVISION "=", NULL);
537 537
538 538 /* separating slash */
539 539 topo_fmristr_build(&size, buf, buflen, "/", NULL, NULL);
540 540
541 541 /* hc-root */
542 542 if (root)
543 543 topo_fmristr_build(&size, buf, buflen, root, NULL, NULL);
544 544
545 545 /* all the pairs */
546 546 for (i = 0; i < hcnprs; i++) {
547 547 char *nm = NULL;
548 548 char *id = NULL;
549 549
550 550 if (i > 0)
551 551 topo_fmristr_build(&size,
552 552 buf, buflen, "/", NULL, NULL);
553 553 (void) nvlist_lookup_string(hcprs[i], FM_FMRI_HC_NAME, &nm);
554 554 (void) nvlist_lookup_string(hcprs[i], FM_FMRI_HC_ID, &id);
555 555 if (nm == NULL || id == NULL)
556 556 return (0);
557 557 topo_fmristr_build(&size, buf, buflen, nm, NULL, "=");
558 558 topo_fmristr_build(&size, buf, buflen, id, NULL, NULL);
559 559 }
560 560
561 561 /* append offset/physaddr if it exists in hc-specific */
562 562 if (nvlist_lookup_nvlist(nvl, FM_FMRI_HC_SPECIFIC, &hcsp) == 0) {
563 563 char *hcsn = NULL;
564 564 char hexstr[17];
565 565 uint64_t val;
566 566
567 567 if (nvlist_lookup_uint64(hcsp, FM_FMRI_HC_SPECIFIC_OFFSET,
568 568 &val) == 0 || nvlist_lookup_uint64(hcsp,
569 569 "asru-" FM_FMRI_HC_SPECIFIC_OFFSET, &val) == 0)
570 570 hcsn = FM_FMRI_HC_SPECIFIC_OFFSET;
571 571 else if (nvlist_lookup_uint64(hcsp,
572 572 FM_FMRI_HC_SPECIFIC_PHYSADDR, &val) == 0 ||
573 573 nvlist_lookup_uint64(hcsp,
574 574 "asru-" FM_FMRI_HC_SPECIFIC_PHYSADDR, &val) == 0)
575 575 hcsn = FM_FMRI_HC_SPECIFIC_PHYSADDR;
576 576
577 577 if (hcsn != NULL) {
578 578 (void) snprintf(hexstr, sizeof (hexstr), "%llx", val);
579 579 topo_fmristr_build(&size, buf, buflen, "/", NULL, NULL);
580 580 topo_fmristr_build(&size, buf, buflen, "=", hcsn,
581 581 hexstr);
582 582 }
583 583 }
584 584
585 585 /*
586 586 * If the nvlist represents a facility node, then we append the
587 587 * facility type and name to the end of the string representation using
588 588 * the format below:
589 589 *
590 590 * ?<ftype>=<fname>
591 591 */
592 592 if (nvlist_lookup_nvlist(nvl, FM_FMRI_FACILITY, &fnvl) == 0) {
593 593 if (nvlist_lookup_string(fnvl, FM_FMRI_FACILITY_NAME,
594 594 &fname) != 0 || nvlist_lookup_string(fnvl,
595 595 FM_FMRI_FACILITY_TYPE, &ftype) != 0)
596 596 return (0);
597 597 topo_fmristr_build(&size, buf, buflen, "?", NULL, NULL);
598 598 topo_fmristr_build(&size, buf, buflen, "=", ftype, fname);
599 599 }
600 600
601 601 return (size);
602 602 }
603 603
604 604 /*ARGSUSED*/
605 605 static int
606 606 hc_fmri_nvl2str(topo_mod_t *mod, tnode_t *node, topo_version_t version,
607 607 nvlist_t *nvl, nvlist_t **out)
608 608 {
609 609 ssize_t len;
610 610 char *name = NULL;
611 611 nvlist_t *fmristr;
612 612
613 613 if (version > TOPO_METH_NVL2STR_VERSION)
614 614 return (topo_mod_seterrno(mod, EMOD_VER_NEW));
615 615
616 616 if ((len = fmri_nvl2str(nvl, NULL, 0)) == 0 ||
617 617 (name = topo_mod_alloc(mod, len + 1)) == NULL ||
618 618 fmri_nvl2str(nvl, name, len + 1) == 0) {
619 619 if (name != NULL)
620 620 topo_mod_free(mod, name, len + 1);
621 621 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
622 622 }
623 623
624 624 if (topo_mod_nvalloc(mod, &fmristr, NV_UNIQUE_NAME) != 0) {
625 625 topo_mod_free(mod, name, len + 1);
626 626 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
627 627 }
628 628 if (nvlist_add_string(fmristr, "fmri-string", name) != 0) {
629 629 topo_mod_free(mod, name, len + 1);
630 630 nvlist_free(fmristr);
631 631 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
632 632 }
633 633 topo_mod_free(mod, name, len + 1);
634 634 *out = fmristr;
635 635
636 636 return (0);
637 637 }
638 638
639 639 static nvlist_t *
640 640 hc_base_fmri_create(topo_mod_t *mod, const nvlist_t *auth, const char *part,
641 641 const char *rev, const char *serial)
642 642 {
643 643 nvlist_t *fmri;
644 644 int err = 0;
645 645
646 646 /*
647 647 * Create base HC nvlist
648 648 */
649 649 if (topo_mod_nvalloc(mod, &fmri, NV_UNIQUE_NAME) != 0)
650 650 return (NULL);
651 651
652 652 err = nvlist_add_uint8(fmri, FM_VERSION, FM_HC_SCHEME_VERSION);
653 653 err |= nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC);
654 654 err |= nvlist_add_string(fmri, FM_FMRI_HC_ROOT, "");
655 655 if (err != 0) {
656 656 nvlist_free(fmri);
657 657 return (NULL);
658 658 }
659 659
660 660 /*
661 661 * Add optional payload members
662 662 */
663 663 if (serial != NULL)
664 664 (void) nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID, serial);
665 665 if (part != NULL)
666 666 (void) nvlist_add_string(fmri, FM_FMRI_HC_PART, part);
667 667 if (rev != NULL)
668 668 (void) nvlist_add_string(fmri, FM_FMRI_HC_REVISION, rev);
669 669 if (auth != NULL)
670 670 (void) nvlist_add_nvlist(fmri, FM_FMRI_AUTHORITY,
671 671 (nvlist_t *)auth);
672 672
673 673 return (fmri);
674 674 }
675 675
676 676 static nvlist_t **
677 677 make_hc_pairs(topo_mod_t *mod, char *fmri, int *num)
678 678 {
679 679 nvlist_t **pa;
680 680 char *hc, *fromstr;
681 681 char *starti, *startn, *endi, *endi2;
682 682 char *ne, *ns;
683 683 char *cname = NULL;
684 684 char *find;
685 685 char *cid = NULL;
686 686 int nslashes = 0;
687 687 int npairs = 0;
688 688 int i, hclen;
689 689
690 690 if ((hc = topo_mod_strdup(mod, fmri + 5)) == NULL)
691 691 return (NULL);
692 692
693 693 hclen = strlen(hc) + 1;
694 694
695 695 /*
696 696 * Count equal signs and slashes to determine how many
697 697 * hc-pairs will be present in the final FMRI. There should
698 698 * be at least as many slashes as equal signs. There can be
699 699 * more, though if the string after an = includes them.
700 700 */
701 701 if ((fromstr = strchr(hc, '/')) == NULL)
702 702 return (NULL);
703 703
704 704 find = fromstr;
705 705 while ((ne = strchr(find, '=')) != NULL) {
706 706 find = ne + 1;
707 707 npairs++;
708 708 }
709 709
710 710 find = fromstr;
711 711 while ((ns = strchr(find, '/')) != NULL) {
712 712 find = ns + 1;
713 713 nslashes++;
714 714 }
715 715
716 716 /*
717 717 * Do we appear to have a well-formed string version of the FMRI?
718 718 */
719 719 if (nslashes < npairs || npairs == 0) {
720 720 topo_mod_free(mod, hc, hclen);
721 721 return (NULL);
722 722 }
723 723
724 724 *num = npairs;
725 725
726 726 find = fromstr;
727 727
728 728 if ((pa = topo_mod_zalloc(mod, npairs * sizeof (nvlist_t *))) == NULL) {
729 729 topo_mod_free(mod, hc, hclen);
730 730 return (NULL);
731 731 }
732 732
733 733 /*
734 734 * We go through a pretty complicated procedure to find the
735 735 * name and id for each pair. That's because, unfortunately,
736 736 * we have some ids that can have slashes within them. So
737 737 * we can't just search for the next slash after the equal sign
738 738 * and decide that starts a new pair. Instead we have to find
739 739 * an equal sign for the next pair and work our way back to the
740 740 * slash from there.
741 741 */
742 742 for (i = 0; i < npairs; i++) {
743 743 startn = strchr(find, '/');
744 744 if (startn == NULL)
745 745 break;
746 746 startn++;
747 747 starti = strchr(find, '=');
748 748 if (starti == NULL)
749 749 break;
750 750 *starti = '\0';
751 751 if ((cname = topo_mod_strdup(mod, startn)) == NULL)
752 752 break;
753 753 *starti++ = '=';
754 754 endi = strchr(starti, '=');
755 755 if (endi != NULL) {
756 756 *endi = '\0';
757 757 endi2 = strrchr(starti, '/');
758 758 if (endi2 == NULL)
759 759 break;
760 760 *endi = '=';
761 761 *endi2 = '\0';
762 762 if ((cid = topo_mod_strdup(mod, starti)) == NULL)
763 763 break;
764 764 *endi2 = '/';
765 765 find = endi2;
766 766 } else {
767 767 if ((cid = topo_mod_strdup(mod, starti)) == NULL)
768 768 break;
769 769 find = starti + strlen(starti);
770 770 }
771 771 if (topo_mod_nvalloc(mod, &pa[i], NV_UNIQUE_NAME) < 0)
772 772 break;
773 773
774 774 if (nvlist_add_string(pa[i], FM_FMRI_HC_NAME, cname) ||
775 775 nvlist_add_string(pa[i], FM_FMRI_HC_ID, cid))
776 776 break;
777 777
778 778 topo_mod_strfree(mod, cname);
779 779 topo_mod_strfree(mod, cid);
780 780 cname = NULL;
781 781 cid = NULL;
782 782 }
783 783
784 784 topo_mod_strfree(mod, cname);
785 785 topo_mod_strfree(mod, cid);
786 786
787 787 if (i < npairs) {
788 788 for (i = 0; i < npairs; i++)
789 789 nvlist_free(pa[i]);
790 790 topo_mod_free(mod, pa, npairs * sizeof (nvlist_t *));
791 791 topo_mod_free(mod, hc, hclen);
792 792 return (NULL);
793 793 }
794 794
795 795 topo_mod_free(mod, hc, hclen);
796 796
797 797 return (pa);
798 798 }
799 799
800 800 int
801 801 make_hc_auth(topo_mod_t *mod, char *fmri, char **serial, char **part,
802 802 char **rev, nvlist_t **auth)
803 803 {
804 804 char *starti, *startn, *endi, *copy;
805 805 char *aname = NULL, *aid = NULL, *fs;
806 806 nvlist_t *na = NULL;
807 807 size_t len;
808 808
809 809 if ((copy = topo_mod_strdup(mod, fmri + 5)) == NULL)
810 810 return (-1);
811 811
812 812 len = strlen(copy);
813 813
814 814 /*
815 815 * Make sure there are a valid authority members
816 816 */
817 817 startn = strchr(copy, ':');
818 818 fs = strchr(copy, '/');
819 819
820 820 if (startn == NULL || fs == NULL) {
821 821 topo_mod_strfree(mod, copy);
822 822 return (0);
823 823 }
824 824
825 825 /*
826 826 * The first colon we encounter must occur before the
827 827 * first slash
828 828 */
829 829 if (startn > fs)
830 830 goto hcabail;
831 831
832 832 do {
833 833 if (++startn >= copy + len)
834 834 break;
835 835
836 836 if ((starti = strchr(startn, '=')) == NULL)
837 837 goto hcabail;
838 838
839 839 *starti = '\0';
840 840 if (++starti > copy + len)
841 841 goto hcabail;
842 842
843 843 if ((aname = topo_mod_strdup(mod, startn)) == NULL)
844 844 goto hcabail;
845 845
846 846 startn = endi = strchr(starti, ':');
847 847 if (endi == NULL)
848 848 if ((endi = strchr(starti, '/')) == NULL)
849 849 break;
850 850
851 851 *endi = '\0';
852 852 if ((aid = topo_mod_strdup(mod, starti)) == NULL)
853 853 goto hcabail;
854 854
855 855 /*
856 856 * Return possible serial, part and revision
857 857 */
858 858 if (strcmp(aname, FM_FMRI_HC_SERIAL_ID) == 0) {
859 859 *serial = topo_mod_strdup(mod, aid);
860 860 } else if (strcmp(aname, FM_FMRI_HC_PART) == 0) {
861 861 *part = topo_mod_strdup(mod, aid);
862 862 } else if (strcmp(aname, FM_FMRI_HC_REVISION) == 0) {
863 863 *rev = topo_mod_strdup(mod, aid);
864 864 } else {
865 865 if (na == NULL) {
866 866 if (topo_mod_nvalloc(mod, &na,
867 867 NV_UNIQUE_NAME) == 0) {
868 868 (void) nvlist_add_string(na, aname,
869 869 aid);
870 870 }
871 871 } else {
872 872 (void) nvlist_add_string(na, aname, aid);
873 873 }
874 874 }
875 875 topo_mod_strfree(mod, aname);
876 876 topo_mod_strfree(mod, aid);
877 877 aname = aid = NULL;
878 878
879 879 } while (startn != NULL);
880 880
881 881 *auth = na;
882 882
883 883 topo_mod_free(mod, copy, len + 1);
884 884 return (0);
885 885
886 886 hcabail:
887 887 topo_mod_free(mod, copy, len + 1);
888 888 topo_mod_strfree(mod, aname);
889 889 topo_mod_strfree(mod, aid);
890 890 nvlist_free(na);
891 891 return (-1);
892 892 }
893 893
894 894
895 895 /*
896 896 * This function creates an nvlist to represent the facility portion of an
897 897 * hc-scheme node, given a string representation of the fmri. This is called by
898 898 * hc_fmri_str2nvl. If the string does not contain a facility component
899 899 * (e.g. ?<ftype>=<fname>) then it bails early and returns 0.
900 900 *
901 901 * On failure it returns -1 and sets the topo mod errno
902 902 */
903 903 int
904 904 make_facility(topo_mod_t *mod, char *str, nvlist_t **nvl)
905 905 {
906 906 char *fac, *copy, *fname, *ftype;
907 907 nvlist_t *nf = NULL;
908 908 size_t len;
909 909
910 910 if ((fac = strchr(str, '?')) == NULL)
911 911 return (0);
912 912
913 913 ++fac;
914 914 if ((copy = topo_mod_strdup(mod, fac)) == NULL)
915 915 return (topo_mod_seterrno(mod, EMOD_NOMEM));
916 916
917 917 fac = copy;
918 918 len = strlen(fac);
919 919
920 920 if ((fname = strchr(fac, '=')) == NULL) {
921 921 topo_mod_free(mod, copy, len + 1);
922 922 return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
923 923 }
924 924
925 925 fname[0] = '\0';
926 926 ++fname;
927 927 ftype = fac;
928 928
929 929 if (topo_mod_nvalloc(mod, &nf, NV_UNIQUE_NAME) != 0) {
930 930 topo_mod_free(mod, copy, len + 1);
931 931 return (topo_mod_seterrno(mod, EMOD_NOMEM));
932 932 }
933 933
934 934 if (nvlist_add_string(nf, FM_FMRI_FACILITY_NAME, fname) != 0 ||
935 935 nvlist_add_string(nf, FM_FMRI_FACILITY_TYPE, ftype) != 0) {
936 936 topo_mod_free(mod, copy, len + 1);
937 937 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
938 938 }
939 939
940 940 topo_mod_free(mod, copy, len + 1);
941 941
942 942 *nvl = nf;
943 943
944 944 return (0);
945 945 }
946 946
947 947 /*ARGSUSED*/
948 948 static int
949 949 hc_fmri_str2nvl(topo_mod_t *mod, tnode_t *node, topo_version_t version,
950 950 nvlist_t *in, nvlist_t **out)
951 951 {
952 952 nvlist_t **pa = NULL;
953 953 nvlist_t *nf = NULL;
954 954 nvlist_t *auth = NULL;
955 955 nvlist_t *fac = NULL;
956 956 char *str;
957 957 char *serial = NULL, *part = NULL, *rev = NULL, *hcsn = NULL;
958 958 int npairs, n;
959 959 int i, e;
960 960
961 961 if (version > TOPO_METH_STR2NVL_VERSION)
962 962 return (topo_mod_seterrno(mod, EMOD_VER_NEW));
963 963
964 964 if (nvlist_lookup_string(in, "fmri-string", &str) != 0)
965 965 return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
966 966
967 967 /* We're expecting a string version of an hc scheme FMRI */
968 968 if (strncmp(str, "hc://", 5) != 0)
969 969 return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
970 970
971 971 if ((pa = make_hc_pairs(mod, str, &npairs)) == NULL)
972 972 return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
973 973
974 974 if (make_hc_auth(mod, str, &serial, &part, &rev, &auth) < 0)
975 975 goto hcfmbail;
976 976
977 977 if ((nf = hc_base_fmri_create(mod, auth, part, rev, serial)) == NULL)
978 978 goto hcfmbail;
979 979
980 980 n = npairs;
981 981
982 982 /*
983 983 * If the last pair in hc-list is offset or physaddr, we move
984 984 * it to hc-specific.
985 985 */
986 986 (void) nvlist_lookup_string(pa[npairs - 1], FM_FMRI_HC_NAME, &hcsn);
987 987 if (strcmp(hcsn, FM_FMRI_HC_SPECIFIC_OFFSET) == 0 ||
988 988 strcmp(hcsn, FM_FMRI_HC_SPECIFIC_PHYSADDR) == 0) {
989 989 char *hcid;
990 990 nvlist_t *hcsp;
991 991 uint64_t val;
992 992
993 993 (void) nvlist_lookup_string(pa[npairs - 1], FM_FMRI_HC_ID,
994 994 &hcid);
995 995 val = strtoull(hcid, NULL, 16);
996 996 if (topo_mod_nvalloc(mod, &hcsp, NV_UNIQUE_NAME) != 0)
997 997 goto hcfmbail;
998 998 if (nvlist_add_uint64(hcsp, hcsn, val) != 0 ||
999 999 nvlist_add_nvlist(nf, FM_FMRI_HC_SPECIFIC, hcsp) != 0) {
1000 1000 nvlist_free(hcsp);
1001 1001 goto hcfmbail;
1002 1002 }
1003 1003
1004 1004 nvlist_free(hcsp);
1005 1005 n--;
1006 1006 }
1007 1007
1008 1008 if ((e = nvlist_add_uint32(nf, FM_FMRI_HC_LIST_SZ, n)) == 0)
1009 1009 e = nvlist_add_nvlist_array(nf, FM_FMRI_HC_LIST, pa, n);
1010 1010 if (e != 0) {
1011 1011 topo_mod_dprintf(mod, "construction of new hc nvl failed");
1012 1012 goto hcfmbail;
1013 1013 }
1014 1014
1015 1015 /*
1016 1016 * Clean-up
1017 1017 */
1018 1018 for (i = 0; i < npairs; i++)
1019 1019 nvlist_free(pa[i]);
1020 1020 topo_mod_free(mod, pa, npairs * sizeof (nvlist_t *));
1021 1021 topo_mod_strfree(mod, serial);
1022 1022 topo_mod_strfree(mod, part);
1023 1023 topo_mod_strfree(mod, rev);
1024 1024 nvlist_free(auth);
1025 1025
1026 1026 if (make_facility(mod, str, &fac) == -1)
1027 1027 goto hcfmbail;
1028 1028
↓ open down ↓ |
1028 lines elided |
↑ open up ↑ |
1029 1029 if (fac != NULL) {
1030 1030 if (nvlist_add_nvlist(nf, FM_FMRI_FACILITY, fac) != 0)
1031 1031 goto hcfmbail;
1032 1032 }
1033 1033
1034 1034 *out = nf;
1035 1035
1036 1036 return (0);
1037 1037
1038 1038 hcfmbail:
1039 - if (nf != NULL)
1040 - nvlist_free(nf);
1039 + nvlist_free(nf);
1041 1040 for (i = 0; i < npairs; i++)
1042 1041 nvlist_free(pa[i]);
1043 1042 topo_mod_free(mod, pa, npairs * sizeof (nvlist_t *));
1044 1043
1045 1044 topo_mod_strfree(mod, serial);
1046 1045 topo_mod_strfree(mod, part);
1047 1046 topo_mod_strfree(mod, rev);
1048 1047 nvlist_free(auth);
1049 1048 nvlist_free(nf);
1050 1049 return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
1051 1050 }
1052 1051
1053 1052 static nvlist_t *
1054 1053 hc_list_create(topo_mod_t *mod, const char *name, char *inst)
1055 1054 {
1056 1055 int err;
1057 1056 nvlist_t *hc;
1058 1057
1059 1058 if (topo_mod_nvalloc(mod, &hc, NV_UNIQUE_NAME) != 0)
1060 1059 return (NULL);
1061 1060
1062 1061 err = nvlist_add_string(hc, FM_FMRI_HC_NAME, name);
1063 1062 err |= nvlist_add_string(hc, FM_FMRI_HC_ID, inst);
1064 1063 if (err != 0) {
1065 1064 nvlist_free(hc);
1066 1065 return (NULL);
1067 1066 }
1068 1067
1069 1068 return (hc);
1070 1069 }
1071 1070
1072 1071 static nvlist_t *
1073 1072 hc_create_seterror(topo_mod_t *mod, nvlist_t **hcl, int n, nvlist_t *fmri,
1074 1073 int err)
1075 1074 {
1076 1075 int i;
1077 1076
1078 1077 if (hcl != NULL) {
1079 1078 for (i = 0; i < n + 1; ++i)
1080 1079 nvlist_free(hcl[i]);
1081 1080
1082 1081 topo_mod_free(mod, hcl, sizeof (nvlist_t *) * (n + 1));
1083 1082 }
1084 1083
1085 1084 nvlist_free(fmri);
1086 1085
1087 1086 (void) topo_mod_seterrno(mod, err);
1088 1087
1089 1088 topo_mod_dprintf(mod, "unable to create hc FMRI: %s\n",
1090 1089 topo_mod_errmsg(mod));
1091 1090
1092 1091 return (NULL);
1093 1092 }
1094 1093
1095 1094 static int
1096 1095 hc_name_canonical(topo_mod_t *mod, const char *name)
1097 1096 {
1098 1097 int i;
1099 1098
1100 1099 if (getenv("NOHCCHECK") != NULL)
1101 1100 return (1);
1102 1101
1103 1102 /*
1104 1103 * Only enumerate elements with correct canonical names
1105 1104 */
1106 1105 for (i = 0; i < hc_ncanon; i++) {
1107 1106 if (strcmp(name, hc_canon[i].hcc_name) == 0)
1108 1107 break;
1109 1108 }
1110 1109 if (i >= hc_ncanon) {
1111 1110 topo_mod_dprintf(mod, "non-canonical name %s\n",
1112 1111 name);
1113 1112 return (0);
1114 1113 } else {
1115 1114 return (1);
1116 1115 }
1117 1116 }
1118 1117
1119 1118 static nvlist_t *
1120 1119 hc_fmri_create(topo_mod_t *mod, nvlist_t *pfmri, int version, const char *name,
1121 1120 topo_instance_t inst, const nvlist_t *auth, const char *part,
1122 1121 const char *rev, const char *serial)
1123 1122 {
1124 1123 int i;
1125 1124 char str[21]; /* sizeof (UINT64_MAX) + '\0' */
1126 1125 uint_t pelems = 0;
1127 1126 nvlist_t **phcl = NULL;
1128 1127 nvlist_t **hcl = NULL;
1129 1128 nvlist_t *fmri = NULL;
1130 1129
1131 1130 if (version > FM_HC_SCHEME_VERSION)
1132 1131 return (hc_create_seterror(mod,
1133 1132 hcl, pelems, fmri, EMOD_VER_OLD));
1134 1133 else if (version < FM_HC_SCHEME_VERSION)
1135 1134 return (hc_create_seterror(mod,
1136 1135 hcl, pelems, fmri, EMOD_VER_NEW));
1137 1136
1138 1137 /*
1139 1138 * Check that the requested name is in our canonical list
1140 1139 */
1141 1140 if (hc_name_canonical(mod, name) == 0)
1142 1141 return (hc_create_seterror(mod,
1143 1142 hcl, pelems, fmri, EMOD_NONCANON));
1144 1143 /*
1145 1144 * Copy the parent's HC_LIST
1146 1145 */
1147 1146 if (pfmri != NULL) {
1148 1147 if (nvlist_lookup_nvlist_array(pfmri, FM_FMRI_HC_LIST,
1149 1148 &phcl, &pelems) != 0)
1150 1149 return (hc_create_seterror(mod,
1151 1150 hcl, pelems, fmri, EMOD_FMRI_MALFORM));
1152 1151 }
1153 1152
1154 1153 hcl = topo_mod_zalloc(mod, sizeof (nvlist_t *) * (pelems + 1));
1155 1154 if (hcl == NULL)
1156 1155 return (hc_create_seterror(mod, hcl, pelems, fmri,
1157 1156 EMOD_NOMEM));
1158 1157
1159 1158 for (i = 0; i < pelems; ++i)
1160 1159 if (topo_mod_nvdup(mod, phcl[i], &hcl[i]) != 0)
1161 1160 return (hc_create_seterror(mod,
1162 1161 hcl, pelems, fmri, EMOD_FMRI_NVL));
1163 1162
1164 1163 (void) snprintf(str, sizeof (str), "%d", inst);
1165 1164 if ((hcl[i] = hc_list_create(mod, name, str)) == NULL)
1166 1165 return (hc_create_seterror(mod,
1167 1166 hcl, pelems, fmri, EMOD_FMRI_NVL));
1168 1167
1169 1168 if ((fmri = hc_base_fmri_create(mod, auth, part, rev, serial)) == NULL)
↓ open down ↓ |
119 lines elided |
↑ open up ↑ |
1170 1169 return (hc_create_seterror(mod,
1171 1170 hcl, pelems, fmri, EMOD_FMRI_NVL));
1172 1171
1173 1172 if (nvlist_add_nvlist_array(fmri, FM_FMRI_HC_LIST, hcl, pelems + 1)
1174 1173 != 0)
1175 1174 return (hc_create_seterror(mod,
1176 1175 hcl, pelems, fmri, EMOD_FMRI_NVL));
1177 1176
1178 1177 if (hcl != NULL) {
1179 1178 for (i = 0; i < pelems + 1; ++i) {
1180 - if (hcl[i] != NULL)
1181 - nvlist_free(hcl[i]);
1179 + nvlist_free(hcl[i]);
1182 1180 }
1183 1181 topo_mod_free(mod, hcl, sizeof (nvlist_t *) * (pelems + 1));
1184 1182 }
1185 1183
1186 1184 return (fmri);
1187 1185 }
1188 1186
1189 1187 /*ARGSUSED*/
1190 1188 static int
1191 1189 hc_fmri_create_meth(topo_mod_t *mod, tnode_t *node, topo_version_t version,
1192 1190 nvlist_t *in, nvlist_t **out)
1193 1191 {
1194 1192 int ret;
1195 1193 nvlist_t *args, *pfmri = NULL;
1196 1194 nvlist_t *auth;
1197 1195 uint32_t inst;
1198 1196 char *name, *serial, *rev, *part;
1199 1197
1200 1198 if (version > TOPO_METH_FMRI_VERSION)
1201 1199 return (topo_mod_seterrno(mod, EMOD_VER_NEW));
1202 1200
1203 1201 /* First the must-have fields */
1204 1202 if (nvlist_lookup_string(in, TOPO_METH_FMRI_ARG_NAME, &name) != 0)
1205 1203 return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
1206 1204 if (nvlist_lookup_uint32(in, TOPO_METH_FMRI_ARG_INST, &inst) != 0)
1207 1205 return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
1208 1206
1209 1207 /*
1210 1208 * args is optional
1211 1209 */
1212 1210 pfmri = NULL;
1213 1211 auth = NULL;
1214 1212 serial = rev = part = NULL;
1215 1213 if ((ret = nvlist_lookup_nvlist(in, TOPO_METH_FMRI_ARG_NVL, &args))
1216 1214 != 0) {
1217 1215 if (ret != ENOENT)
1218 1216 return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
1219 1217 } else {
1220 1218
1221 1219 /* And then optional arguments */
1222 1220 (void) nvlist_lookup_nvlist(args, TOPO_METH_FMRI_ARG_PARENT,
1223 1221 &pfmri);
1224 1222 (void) nvlist_lookup_nvlist(args, TOPO_METH_FMRI_ARG_AUTH,
1225 1223 &auth);
1226 1224 (void) nvlist_lookup_string(args, TOPO_METH_FMRI_ARG_PART,
1227 1225 &part);
1228 1226 (void) nvlist_lookup_string(args, TOPO_METH_FMRI_ARG_REV, &rev);
1229 1227 (void) nvlist_lookup_string(args, TOPO_METH_FMRI_ARG_SER,
1230 1228 &serial);
1231 1229 }
1232 1230
1233 1231 *out = hc_fmri_create(mod, pfmri, version, name, inst, auth, part,
1234 1232 rev, serial);
1235 1233 if (*out == NULL)
1236 1234 return (-1);
1237 1235 return (0);
1238 1236 }
1239 1237
1240 1238 struct hc_walk {
1241 1239 topo_mod_walk_cb_t hcw_cb;
1242 1240 void *hcw_priv;
1243 1241 topo_walk_t *hcw_wp;
1244 1242 nvlist_t **hcw_list;
1245 1243 nvlist_t *hcw_fmri;
1246 1244 nvlist_t *hcw_fac;
1247 1245 uint_t hcw_index;
1248 1246 uint_t hcw_end;
1249 1247 };
1250 1248
1251 1249 /*
1252 1250 * Returns true if the given node is beneath the specified FMRI. This uses
1253 1251 * the TOPO_METH_CONTAINS method, because some enumerators (such as external
1254 1252 * enclosures) may want to do a comparison based on chassis WWN instead of the
1255 1253 * instance ID. If this comparison function fails or is not supported, then we
1256 1254 * fall back to a direct name/instance comparison.
1257 1255 */
1258 1256 static int
1259 1257 hc_match(topo_mod_t *mod, tnode_t *node, nvlist_t *fmri, const char *name,
1260 1258 topo_instance_t inst, boolean_t *result)
1261 1259 {
1262 1260 nvlist_t *rsrc;
1263 1261 nvlist_t *arg, *nvl;
1264 1262 uint32_t match = 0;
1265 1263 int err;
1266 1264
1267 1265 if (topo_node_resource(node, &rsrc, &err) != 0)
1268 1266 return (-1);
1269 1267
1270 1268 if (topo_mod_nvalloc(mod, &arg, NV_UNIQUE_NAME) != 0 ||
1271 1269 nvlist_add_nvlist(arg, TOPO_METH_FMRI_ARG_FMRI,
1272 1270 rsrc) != 0 ||
1273 1271 nvlist_add_nvlist(arg, TOPO_METH_FMRI_ARG_SUBFMRI,
1274 1272 fmri) != 0) {
1275 1273 nvlist_free(rsrc);
1276 1274 (void) topo_mod_seterrno(mod, EMOD_NOMEM);
1277 1275 return (-1);
1278 1276 }
1279 1277
1280 1278 nvlist_free(rsrc);
1281 1279
1282 1280 if (topo_method_invoke(node, TOPO_METH_CONTAINS,
1283 1281 TOPO_METH_CONTAINS_VERSION, arg, &nvl, &err) != 0) {
1284 1282 nvlist_free(arg);
1285 1283 if (err == ETOPO_METHOD_NOTSUP) {
1286 1284 match = (strcmp(name,
1287 1285 topo_node_name(node)) == 0 &&
1288 1286 inst == topo_node_instance(node));
1289 1287 } else {
1290 1288 return (-1);
1291 1289 }
1292 1290 } else {
1293 1291 nvlist_free(arg);
1294 1292 if (nvlist_lookup_uint32(nvl, TOPO_METH_CONTAINS_RET,
1295 1293 &match) != 0) {
1296 1294 nvlist_free(nvl);
1297 1295 (void) topo_mod_seterrno(mod, EMOD_NVL_INVAL);
1298 1296 return (-1);
1299 1297 }
1300 1298 nvlist_free(nvl);
1301 1299 }
1302 1300
1303 1301 *result = (match != 0);
1304 1302 return (0);
1305 1303 }
1306 1304
1307 1305 /*
1308 1306 * Ideally, we should just be able to call topo_walk_bysibling(). But that
1309 1307 * code assumes that the name/instance pair will match, so we need to
1310 1308 * explicitly iterate over children of the parent looking for a matching value.
1311 1309 */
1312 1310 static int
1313 1311 hc_walk_sibling(topo_mod_t *mod, tnode_t *node, struct hc_walk *hwp,
1314 1312 const char *name, topo_instance_t inst)
1315 1313 {
1316 1314 tnode_t *pnp = topo_node_parent(node);
1317 1315 topo_walk_t *wp = hwp->hcw_wp;
1318 1316 tnode_t *np;
1319 1317 boolean_t matched;
1320 1318 int status;
1321 1319
1322 1320 for (np = topo_child_first(pnp); np != NULL;
1323 1321 np = topo_child_next(pnp, np)) {
1324 1322 topo_node_hold(np);
1325 1323 if (hc_match(mod, np, hwp->hcw_fmri, name, inst,
1326 1324 &matched) == 0 && matched) {
1327 1325 wp->tw_node = np;
1328 1326 if (wp->tw_mod != NULL)
1329 1327 status = wp->tw_cb(mod, np, hwp);
1330 1328 else
1331 1329 status = wp->tw_cb(wp->tw_thp, np, hwp);
1332 1330 topo_node_rele(np);
1333 1331 wp->tw_node = node;
1334 1332 return (status);
1335 1333 }
1336 1334
1337 1335 topo_node_rele(np);
1338 1336 }
1339 1337
1340 1338 return (TOPO_WALK_TERMINATE);
1341 1339 }
1342 1340
1343 1341 /*
1344 1342 * Generic walker for the hc-scheme topo tree. This function uses the
1345 1343 * hierachical nature of the hc-scheme to efficiently step through
1346 1344 * the topo hc tree. Node lookups are done by topo_walk_byid() and
1347 1345 * topo_walk_bysibling() at each component level to avoid unnecessary
1348 1346 * traversal of the tree. hc_walker() never returns TOPO_WALK_NEXT, so
1349 1347 * whether TOPO_WALK_CHILD or TOPO_WALK_SIBLING is specified by
1350 1348 * topo_walk_step() doesn't affect the traversal.
1351 1349 */
1352 1350 static int
1353 1351 hc_walker(topo_mod_t *mod, tnode_t *node, void *pdata)
1354 1352 {
1355 1353 int i, err;
1356 1354 struct hc_walk *hwp = (struct hc_walk *)pdata;
1357 1355 char *name, *id;
1358 1356 char *fname, *ftype;
1359 1357 topo_instance_t inst;
1360 1358 boolean_t match;
1361 1359
1362 1360 i = hwp->hcw_index;
1363 1361 if (i > hwp->hcw_end) {
1364 1362 if (hwp->hcw_fac != NULL) {
1365 1363 if ((err = hwp->hcw_cb(mod, node, hwp->hcw_priv))
1366 1364 != 0) {
1367 1365 (void) topo_mod_seterrno(mod, err);
1368 1366 topo_mod_dprintf(mod, "hc_walker: callback "
1369 1367 "failed: %s\n ", topo_mod_errmsg(mod));
1370 1368 return (TOPO_WALK_ERR);
1371 1369 }
1372 1370 topo_mod_dprintf(mod, "hc_walker: callback "
1373 1371 "complete: terminate walk\n");
1374 1372 return (TOPO_WALK_TERMINATE);
1375 1373 } else {
1376 1374 topo_mod_dprintf(mod, "hc_walker: node not found\n");
1377 1375 return (TOPO_WALK_TERMINATE);
1378 1376 }
1379 1377 }
1380 1378
1381 1379 err = nvlist_lookup_string(hwp->hcw_list[i], FM_FMRI_HC_NAME, &name);
1382 1380 err |= nvlist_lookup_string(hwp->hcw_list[i], FM_FMRI_HC_ID, &id);
1383 1381
1384 1382 if (err != 0) {
1385 1383 (void) topo_mod_seterrno(mod, EMOD_NVL_INVAL);
1386 1384 return (TOPO_WALK_ERR);
1387 1385 }
1388 1386
1389 1387 inst = atoi(id);
1390 1388
1391 1389 /*
1392 1390 * Check to see if our node matches the requested FMRI. If it doesn't
1393 1391 * (because the enumerator determines matching based on something other
1394 1392 * than name/instance, or because we're at the first level below the
1395 1393 * root), then iterate over siblings to find the matching node.
1396 1394 */
1397 1395 if (hc_match(mod, node, hwp->hcw_fmri, name, inst, &match) != 0)
1398 1396 return (TOPO_WALK_ERR);
1399 1397
1400 1398 if (!match)
1401 1399 return (hc_walk_sibling(mod, node, hwp, name, inst));
1402 1400
1403 1401 topo_mod_dprintf(mod, "hc_walker: walking node:%s=%d for hc:"
1404 1402 "%s=%d at %d, end at %d \n", topo_node_name(node),
1405 1403 topo_node_instance(node), name, inst, i, hwp->hcw_end);
1406 1404
1407 1405 if (i == hwp->hcw_end) {
1408 1406
1409 1407 /*
1410 1408 * We are at the end of the hc-list. Now, check for
1411 1409 * a facility leaf and walk one more time.
1412 1410 */
1413 1411 if (hwp->hcw_fac != NULL) {
1414 1412 err = nvlist_lookup_string(hwp->hcw_fac,
1415 1413 FM_FMRI_FACILITY_NAME, &fname);
1416 1414 err |= nvlist_lookup_string(hwp->hcw_fac,
1417 1415 FM_FMRI_FACILITY_TYPE, &ftype);
1418 1416 if (err != 0) {
1419 1417 (void) topo_mod_seterrno(mod, EMOD_NVL_INVAL);
1420 1418 return (TOPO_WALK_ERR);
1421 1419 }
1422 1420 hwp->hcw_index++;
1423 1421 topo_mod_dprintf(mod, "hc_walker: walk to facility "
1424 1422 "node:%s=%s\n", fname, ftype);
1425 1423 return (topo_walk_byid(hwp->hcw_wp, fname, 0));
1426 1424 }
1427 1425
1428 1426 /*
1429 1427 * Otherwise, this is the node we're looking for.
1430 1428 */
1431 1429 if ((err = hwp->hcw_cb(mod, node, hwp->hcw_priv)) != 0) {
1432 1430 (void) topo_mod_seterrno(mod, err);
1433 1431 topo_mod_dprintf(mod, "hc_walker: callback "
1434 1432 "failed: %s\n ", topo_mod_errmsg(mod));
1435 1433 return (TOPO_WALK_ERR);
1436 1434 } else {
1437 1435 topo_mod_dprintf(mod, "hc_walker: callback "
1438 1436 "complete: terminate walk\n");
1439 1437 return (TOPO_WALK_TERMINATE);
1440 1438 }
1441 1439 }
1442 1440
1443 1441 /*
1444 1442 * Move on to the next component in the hc-list
1445 1443 */
1446 1444 hwp->hcw_index = ++i;
1447 1445 err = nvlist_lookup_string(hwp->hcw_list[i], FM_FMRI_HC_NAME, &name);
1448 1446 err |= nvlist_lookup_string(hwp->hcw_list[i], FM_FMRI_HC_ID, &id);
1449 1447 if (err != 0) {
1450 1448 (void) topo_mod_seterrno(mod, err);
1451 1449 return (TOPO_WALK_ERR);
1452 1450 }
1453 1451 inst = atoi(id);
1454 1452
1455 1453 return (topo_walk_byid(hwp->hcw_wp, name, inst));
1456 1454
1457 1455 }
1458 1456
1459 1457 static struct hc_walk *
1460 1458 hc_walk_init(topo_mod_t *mod, tnode_t *node, nvlist_t *rsrc,
1461 1459 topo_mod_walk_cb_t cb, void *pdata)
1462 1460 {
1463 1461 int err, ret;
1464 1462 uint_t sz;
1465 1463 struct hc_walk *hwp;
1466 1464 topo_walk_t *wp;
1467 1465
1468 1466 if ((hwp = topo_mod_alloc(mod, sizeof (struct hc_walk))) == NULL) {
1469 1467 (void) topo_mod_seterrno(mod, EMOD_NOMEM);
1470 1468 return (NULL);
1471 1469 }
1472 1470
1473 1471 if (nvlist_lookup_nvlist_array(rsrc, FM_FMRI_HC_LIST, &hwp->hcw_list,
1474 1472 &sz) != 0) {
1475 1473 topo_mod_dprintf(mod, "hc_walk_init: failed to lookup %s "
1476 1474 "nvlist\n", FM_FMRI_HC_LIST);
1477 1475 topo_mod_free(mod, hwp, sizeof (struct hc_walk));
1478 1476 (void) topo_mod_seterrno(mod, EMOD_METHOD_INVAL);
1479 1477 return (NULL);
1480 1478 }
1481 1479 if ((ret = nvlist_lookup_nvlist(rsrc, FM_FMRI_FACILITY, &hwp->hcw_fac))
1482 1480 != 0) {
1483 1481 if (ret != ENOENT) {
1484 1482 topo_mod_dprintf(mod, "hc_walk_init: unexpected error "
1485 1483 "looking up %s nvlist", FM_FMRI_FACILITY);
1486 1484 topo_mod_free(mod, hwp, sizeof (struct hc_walk));
1487 1485 (void) topo_mod_seterrno(mod, EMOD_METHOD_INVAL);
1488 1486 return (NULL);
1489 1487 } else {
1490 1488 hwp->hcw_fac = NULL;
1491 1489 }
1492 1490 }
1493 1491
1494 1492 hwp->hcw_fmri = rsrc;
1495 1493 hwp->hcw_end = sz - 1;
1496 1494 hwp->hcw_index = 0;
1497 1495 hwp->hcw_priv = pdata;
1498 1496 hwp->hcw_cb = cb;
1499 1497 if ((wp = topo_mod_walk_init(mod, node, hc_walker, (void *)hwp, &err))
1500 1498 == NULL) {
1501 1499 topo_mod_dprintf(mod, "hc_walk_init: topo_mod_walk_init failed "
1502 1500 "(%s)\n", topo_strerror(err));
1503 1501 topo_mod_free(mod, hwp, sizeof (struct hc_walk));
1504 1502 (void) topo_mod_seterrno(mod, err);
1505 1503 return (NULL);
1506 1504 }
1507 1505
1508 1506 hwp->hcw_wp = wp;
1509 1507
1510 1508 return (hwp);
1511 1509 }
1512 1510
1513 1511 struct prop_lookup {
1514 1512 const char *pl_pgroup;
1515 1513 const char *pl_pname;
1516 1514 int pl_flag;
1517 1515 nvlist_t *pl_args;
1518 1516 nvlist_t *pl_rsrc;
1519 1517 nvlist_t *pl_prop;
1520 1518 };
1521 1519
1522 1520 /*ARGSUSED*/
1523 1521 static int
1524 1522 hc_prop_get(topo_mod_t *mod, tnode_t *node, void *pdata)
1525 1523 {
1526 1524 int err = 0;
1527 1525
1528 1526 struct prop_lookup *plp = (struct prop_lookup *)pdata;
1529 1527
1530 1528 (void) topo_prop_getprop(node, plp->pl_pgroup, plp->pl_pname,
1531 1529 plp->pl_args, &plp->pl_prop, &err);
1532 1530
1533 1531 return (err);
1534 1532 }
1535 1533
1536 1534 static int
1537 1535 hc_fmri_prop_get(topo_mod_t *mod, tnode_t *node, topo_version_t version,
1538 1536 nvlist_t *in, nvlist_t **out)
1539 1537 {
1540 1538 int err;
1541 1539 struct hc_walk *hwp;
1542 1540 struct prop_lookup *plp;
1543 1541
1544 1542 if (version > TOPO_METH_PROP_GET_VERSION)
1545 1543 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
1546 1544
1547 1545 if ((plp = topo_mod_alloc(mod, sizeof (struct prop_lookup))) == NULL)
1548 1546 return (topo_mod_seterrno(mod, EMOD_NOMEM));
1549 1547
1550 1548 err = nvlist_lookup_string(in, TOPO_PROP_GROUP,
1551 1549 (char **)&plp->pl_pgroup);
1552 1550 err |= nvlist_lookup_string(in, TOPO_PROP_VAL_NAME,
1553 1551 (char **)&plp->pl_pname);
1554 1552 err |= nvlist_lookup_nvlist(in, TOPO_PROP_RESOURCE, &plp->pl_rsrc);
1555 1553 if (err != 0) {
1556 1554 topo_mod_free(mod, plp, sizeof (struct prop_lookup));
1557 1555 return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
1558 1556 }
1559 1557
1560 1558 /*
1561 1559 * Private args to prop method are optional
1562 1560 */
1563 1561 if ((err = nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &plp->pl_args))
1564 1562 != 0) {
1565 1563 if (err != ENOENT) {
1566 1564 topo_mod_free(mod, plp, sizeof (struct prop_lookup));
1567 1565 return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
1568 1566 } else {
1569 1567 plp->pl_args = NULL;
1570 1568 }
1571 1569 }
1572 1570
1573 1571 plp->pl_prop = NULL;
1574 1572 if ((hwp = hc_walk_init(mod, node, plp->pl_rsrc, hc_prop_get,
1575 1573 (void *)plp)) != NULL) {
1576 1574 if (topo_walk_step(hwp->hcw_wp, TOPO_WALK_CHILD) ==
1577 1575 TOPO_WALK_ERR)
1578 1576 err = -1;
1579 1577 else
1580 1578 err = 0;
1581 1579 topo_walk_fini(hwp->hcw_wp);
1582 1580 topo_mod_free(mod, hwp, sizeof (struct hc_walk));
1583 1581 } else {
1584 1582 err = -1;
1585 1583 }
1586 1584
1587 1585 if (plp->pl_prop != NULL)
1588 1586 *out = plp->pl_prop;
1589 1587
1590 1588 topo_mod_free(mod, plp, sizeof (struct prop_lookup));
1591 1589
1592 1590 return (err);
1593 1591 }
1594 1592
1595 1593 /*ARGSUSED*/
1596 1594 static int
1597 1595 hc_pgrp_get(topo_mod_t *mod, tnode_t *node, void *pdata)
1598 1596 {
1599 1597 int err = 0;
1600 1598
1601 1599 struct prop_lookup *plp = (struct prop_lookup *)pdata;
1602 1600
1603 1601 (void) topo_prop_getpgrp(node, plp->pl_pgroup, &plp->pl_prop, &err);
1604 1602
1605 1603 return (err);
1606 1604 }
1607 1605
1608 1606 static int
1609 1607 hc_fmri_pgrp_get(topo_mod_t *mod, tnode_t *node, topo_version_t version,
1610 1608 nvlist_t *in, nvlist_t **out)
1611 1609 {
1612 1610 int err;
1613 1611 struct hc_walk *hwp;
1614 1612 struct prop_lookup *plp;
1615 1613
1616 1614 if (version > TOPO_METH_PGRP_GET_VERSION)
1617 1615 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
1618 1616
1619 1617 if ((plp = topo_mod_alloc(mod, sizeof (struct prop_lookup))) == NULL)
1620 1618 return (topo_mod_seterrno(mod, EMOD_NOMEM));
1621 1619
1622 1620 err = nvlist_lookup_string(in, TOPO_PROP_GROUP,
1623 1621 (char **)&plp->pl_pgroup);
1624 1622 err |= nvlist_lookup_nvlist(in, TOPO_PROP_RESOURCE, &plp->pl_rsrc);
1625 1623 if (err != 0) {
1626 1624 topo_mod_free(mod, plp, sizeof (struct prop_lookup));
1627 1625 return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
1628 1626 }
1629 1627
1630 1628 plp->pl_prop = NULL;
1631 1629 if ((hwp = hc_walk_init(mod, node, plp->pl_rsrc, hc_pgrp_get,
1632 1630 (void *)plp)) != NULL) {
1633 1631 if (topo_walk_step(hwp->hcw_wp, TOPO_WALK_CHILD) ==
1634 1632 TOPO_WALK_ERR)
1635 1633 err = -1;
1636 1634 else
1637 1635 err = 0;
1638 1636 topo_walk_fini(hwp->hcw_wp);
1639 1637 topo_mod_free(mod, hwp, sizeof (struct hc_walk));
1640 1638 } else {
1641 1639 err = -1;
1642 1640 }
1643 1641
1644 1642 if (plp->pl_prop != NULL)
1645 1643 *out = plp->pl_prop;
1646 1644
1647 1645 topo_mod_free(mod, plp, sizeof (struct prop_lookup));
1648 1646
1649 1647 return (err);
1650 1648 }
1651 1649
1652 1650 /*ARGSUSED*/
1653 1651 static int
1654 1652 hc_prop_setprop(topo_mod_t *mod, tnode_t *node, void *pdata)
1655 1653 {
1656 1654 int err = 0;
1657 1655
1658 1656 struct prop_lookup *plp = (struct prop_lookup *)pdata;
1659 1657
1660 1658 (void) topo_prop_setprop(node, plp->pl_pgroup, plp->pl_prop,
1661 1659 plp->pl_flag, plp->pl_args, &err);
1662 1660
1663 1661 return (err);
1664 1662 }
1665 1663
1666 1664 /*ARGSUSED*/
1667 1665 static int
1668 1666 hc_fmri_prop_set(topo_mod_t *mod, tnode_t *node, topo_version_t version,
1669 1667 nvlist_t *in, nvlist_t **out)
1670 1668 {
1671 1669 int err;
1672 1670 struct hc_walk *hwp;
1673 1671 struct prop_lookup *plp;
1674 1672
1675 1673 if (version > TOPO_METH_PROP_SET_VERSION)
1676 1674 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
1677 1675
1678 1676 if ((plp = topo_mod_alloc(mod, sizeof (struct prop_lookup))) == NULL)
1679 1677 return (topo_mod_seterrno(mod, EMOD_NOMEM));
1680 1678
1681 1679 err = nvlist_lookup_string(in, TOPO_PROP_GROUP,
1682 1680 (char **)&plp->pl_pgroup);
1683 1681 err |= nvlist_lookup_nvlist(in, TOPO_PROP_RESOURCE, &plp->pl_rsrc);
1684 1682 err |= nvlist_lookup_nvlist(in, TOPO_PROP_VAL, &plp->pl_prop);
1685 1683 err |= nvlist_lookup_int32(in, TOPO_PROP_FLAG, &plp->pl_flag);
1686 1684 if (err != 0) {
1687 1685 topo_mod_free(mod, plp, sizeof (struct prop_lookup));
1688 1686 return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
1689 1687 }
1690 1688
1691 1689 /*
1692 1690 * Private args to prop method are optional
1693 1691 */
1694 1692 if ((err = nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &plp->pl_args))
1695 1693 != 0) {
1696 1694 if (err != ENOENT)
1697 1695 return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
1698 1696 else
1699 1697 plp->pl_args = NULL;
1700 1698 }
1701 1699
1702 1700 if ((hwp = hc_walk_init(mod, node, plp->pl_rsrc, hc_prop_setprop,
1703 1701 (void *)plp)) != NULL) {
1704 1702 if (topo_walk_step(hwp->hcw_wp, TOPO_WALK_CHILD) ==
1705 1703 TOPO_WALK_ERR)
1706 1704 err = -1;
1707 1705 else
1708 1706 err = 0;
1709 1707 topo_walk_fini(hwp->hcw_wp);
1710 1708 topo_mod_free(mod, hwp, sizeof (struct hc_walk));
1711 1709 } else {
1712 1710 err = -1;
1713 1711 }
1714 1712
1715 1713 topo_mod_free(mod, plp, sizeof (struct prop_lookup));
1716 1714
1717 1715 return (err);
1718 1716 }
1719 1717
1720 1718 struct hc_args {
1721 1719 nvlist_t *ha_fmri;
1722 1720 nvlist_t *ha_nvl;
1723 1721 char *ha_method_name;
1724 1722 topo_version_t ha_method_ver;
1725 1723 };
1726 1724
1727 1725 static int
1728 1726 hc_auth_changed(nvlist_t *nva, nvlist_t *nvb, const char *propname)
1729 1727 {
1730 1728 char *stra, *strb;
1731 1729
1732 1730 if (nvlist_lookup_string(nva, propname, &stra) != 0 ||
1733 1731 nvlist_lookup_string(nvb, propname, &strb) != 0)
1734 1732 return (FMD_OBJ_STATE_UNKNOWN);
1735 1733
1736 1734 if (strcmp(stra, strb) != 0)
1737 1735 return (FMD_OBJ_STATE_REPLACED);
1738 1736 else
1739 1737 return (FMD_OBJ_STATE_STILL_PRESENT);
1740 1738 }
1741 1739
1742 1740 static int
1743 1741 hc_is_present(topo_mod_t *mod, tnode_t *node, void *pdata)
1744 1742 {
1745 1743 int err;
1746 1744 struct hc_args *hap = (struct hc_args *)pdata;
1747 1745 nvlist_t *rsrc;
1748 1746 boolean_t present;
1749 1747
1750 1748 /*
1751 1749 * check with the enumerator that created this FMRI
1752 1750 * (topo node)
1753 1751 */
1754 1752 if (topo_method_invoke(node, TOPO_METH_PRESENT,
1755 1753 TOPO_METH_PRESENT_VERSION, hap->ha_fmri, &hap->ha_nvl,
1756 1754 &err) < 0) {
1757 1755
1758 1756 /*
1759 1757 * If the method exists but failed for some other reason,
1760 1758 * propagate the error as making any decision over presence is
1761 1759 * impossible.
1762 1760 */
1763 1761 if (err != ETOPO_METHOD_NOTSUP)
1764 1762 return (err);
1765 1763
1766 1764 /*
1767 1765 * Check the authority information. If the part id or serial
1768 1766 * number doesn't match, then it isn't the same FMRI.
1769 1767 * Otherwise, assume presence.
1770 1768 */
1771 1769 if (topo_node_resource(node, &rsrc, &err) != 0)
1772 1770 return (err);
1773 1771
1774 1772 present = B_TRUE;
1775 1773 if (hc_auth_changed(hap->ha_fmri, rsrc,
1776 1774 FM_FMRI_HC_SERIAL_ID) == FMD_OBJ_STATE_REPLACED ||
1777 1775 hc_auth_changed(hap->ha_fmri, rsrc,
1778 1776 FM_FMRI_HC_PART) == FMD_OBJ_STATE_REPLACED) {
1779 1777 present = B_FALSE;
1780 1778 }
1781 1779 nvlist_free(rsrc);
1782 1780
1783 1781 if (topo_mod_nvalloc(mod, &hap->ha_nvl, NV_UNIQUE_NAME) != 0)
1784 1782 return (EMOD_NOMEM);
1785 1783
1786 1784 if (nvlist_add_uint32(hap->ha_nvl,
1787 1785 TOPO_METH_PRESENT_RET, present) != 0) {
1788 1786 nvlist_free(hap->ha_nvl);
1789 1787 hap->ha_nvl = NULL;
1790 1788 return (EMOD_NOMEM);
1791 1789 }
1792 1790 }
1793 1791
1794 1792 return (0);
1795 1793 }
1796 1794
1797 1795 static int
1798 1796 hc_fmri_present(topo_mod_t *mod, tnode_t *node, topo_version_t version,
1799 1797 nvlist_t *in, nvlist_t **out)
1800 1798 {
1801 1799 int err;
1802 1800 struct hc_walk *hwp;
1803 1801 struct hc_args *hap;
1804 1802
1805 1803 if (version > TOPO_METH_PRESENT_VERSION)
1806 1804 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
1807 1805
1808 1806 if ((hap = topo_mod_alloc(mod, sizeof (struct hc_args))) == NULL)
1809 1807 return (topo_mod_seterrno(mod, EMOD_NOMEM));
1810 1808
1811 1809 hap->ha_fmri = in;
1812 1810 hap->ha_nvl = NULL;
1813 1811 if ((hwp = hc_walk_init(mod, node, hap->ha_fmri, hc_is_present,
1814 1812 (void *)hap)) != NULL) {
1815 1813 if (topo_walk_step(hwp->hcw_wp, TOPO_WALK_CHILD) ==
1816 1814 TOPO_WALK_ERR)
1817 1815 err = -1;
1818 1816 else
1819 1817 err = 0;
1820 1818 topo_walk_fini(hwp->hcw_wp);
1821 1819 topo_mod_free(mod, hwp, sizeof (struct hc_walk));
1822 1820 } else {
1823 1821 err = -1;
1824 1822 }
1825 1823
1826 1824 if (hap->ha_nvl != NULL)
1827 1825 *out = hap->ha_nvl;
1828 1826
1829 1827 topo_mod_free(mod, hap, sizeof (struct hc_args));
1830 1828
1831 1829 return (err);
1832 1830 }
1833 1831
1834 1832 static int
1835 1833 hc_is_replaced(topo_mod_t *mod, tnode_t *node, void *pdata)
1836 1834 {
1837 1835 int err;
1838 1836 struct hc_args *hap = (struct hc_args *)pdata;
1839 1837 uint32_t present = 0;
1840 1838 nvlist_t *rsrc;
1841 1839 uint32_t rval = FMD_OBJ_STATE_UNKNOWN;
1842 1840
1843 1841 /*
1844 1842 * check with the enumerator that created this FMRI
1845 1843 * (topo node)
1846 1844 */
1847 1845 if (topo_method_invoke(node, TOPO_METH_REPLACED,
1848 1846 TOPO_METH_REPLACED_VERSION, hap->ha_fmri, &hap->ha_nvl,
1849 1847 &err) < 0) {
1850 1848 /*
1851 1849 * If the method exists but failed for some other
1852 1850 * reason, propagate the error as making any decision
1853 1851 * over presence is impossible.
1854 1852 */
1855 1853 if (err != ETOPO_METHOD_NOTSUP)
1856 1854 return (err);
1857 1855
1858 1856 /*
1859 1857 * Enumerator didn't provide "replaced" method -
1860 1858 * try "present" method
1861 1859 */
1862 1860 if (topo_method_invoke(node, TOPO_METH_PRESENT,
1863 1861 TOPO_METH_PRESENT_VERSION, hap->ha_fmri, &hap->ha_nvl,
1864 1862 &err) < 0) {
1865 1863 /*
1866 1864 * If the method exists but failed for some other
1867 1865 * reason, propagate the error as making any decision
1868 1866 * over presence is impossible.
1869 1867 */
1870 1868 if (err != ETOPO_METHOD_NOTSUP)
1871 1869 return (err);
1872 1870
1873 1871 /*
1874 1872 * Enumerator didn't provide "present" method either -
1875 1873 * so check the authority information. If the part id
1876 1874 * or serial number doesn't match, then it isn't the
1877 1875 * same FMRI. Otherwise, if we have a serial number and
1878 1876 * it hasn't changed, then assume it is the same FMRI.
1879 1877 */
1880 1878 if (topo_node_resource(node, &rsrc, &err) != 0)
1881 1879 return (err);
1882 1880 rval = hc_auth_changed(hap->ha_fmri, rsrc,
1883 1881 FM_FMRI_HC_PART);
1884 1882 if (rval != FMD_OBJ_STATE_REPLACED)
1885 1883 rval = hc_auth_changed(hap->ha_fmri, rsrc,
1886 1884 FM_FMRI_HC_SERIAL_ID);
1887 1885 nvlist_free(rsrc);
1888 1886 if (topo_mod_nvalloc(mod, &hap->ha_nvl,
1889 1887 NV_UNIQUE_NAME) != 0)
1890 1888 return (EMOD_NOMEM);
1891 1889 if (nvlist_add_uint32(hap->ha_nvl,
1892 1890 TOPO_METH_REPLACED_RET, rval) != 0) {
1893 1891 nvlist_free(hap->ha_nvl);
1894 1892 hap->ha_nvl = NULL;
1895 1893 return (ETOPO_PROP_NVL);
1896 1894 }
1897 1895 } else {
1898 1896 (void) nvlist_lookup_uint32(hap->ha_nvl,
1899 1897 TOPO_METH_PRESENT_RET, &present);
1900 1898 (void) nvlist_remove(hap->ha_nvl,
1901 1899 TOPO_METH_PRESENT_RET, DATA_TYPE_UINT32);
1902 1900 if (nvlist_add_uint32(hap->ha_nvl,
1903 1901 TOPO_METH_REPLACED_RET,
1904 1902 present ? FMD_OBJ_STATE_UNKNOWN :
1905 1903 FMD_OBJ_STATE_NOT_PRESENT) != 0) {
1906 1904 nvlist_free(hap->ha_nvl);
1907 1905 hap->ha_nvl = NULL;
1908 1906 return (ETOPO_PROP_NVL);
1909 1907 }
1910 1908 }
1911 1909 }
1912 1910 return (0);
1913 1911 }
1914 1912
1915 1913 static int
1916 1914 hc_fmri_replaced(topo_mod_t *mod, tnode_t *node, topo_version_t version,
1917 1915 nvlist_t *in, nvlist_t **out)
1918 1916 {
1919 1917 int err;
1920 1918 struct hc_walk *hwp;
1921 1919 struct hc_args *hap;
1922 1920
1923 1921 if (version > TOPO_METH_REPLACED_VERSION)
1924 1922 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
1925 1923
1926 1924 if ((hap = topo_mod_alloc(mod, sizeof (struct hc_args))) == NULL)
1927 1925 return (topo_mod_seterrno(mod, EMOD_NOMEM));
1928 1926
1929 1927 hap->ha_fmri = in;
1930 1928 hap->ha_nvl = NULL;
1931 1929 if ((hwp = hc_walk_init(mod, node, hap->ha_fmri, hc_is_replaced,
1932 1930 (void *)hap)) != NULL) {
1933 1931 if (topo_walk_step(hwp->hcw_wp, TOPO_WALK_CHILD) ==
1934 1932 TOPO_WALK_ERR)
1935 1933 err = -1;
1936 1934 else
1937 1935 err = 0;
1938 1936 topo_walk_fini(hwp->hcw_wp);
1939 1937 topo_mod_free(mod, hwp, sizeof (struct hc_walk));
1940 1938 } else {
1941 1939 err = -1;
1942 1940 }
1943 1941
1944 1942 if (hap->ha_nvl != NULL)
1945 1943 *out = hap->ha_nvl;
1946 1944
1947 1945 topo_mod_free(mod, hap, sizeof (struct hc_args));
1948 1946
1949 1947 return (err);
1950 1948 }
1951 1949
1952 1950 static int
1953 1951 hc_unusable(topo_mod_t *mod, tnode_t *node, void *pdata)
1954 1952 {
1955 1953 int err;
1956 1954 struct hc_args *hap = (struct hc_args *)pdata;
1957 1955
1958 1956 /*
1959 1957 * check with the enumerator that created this FMRI
1960 1958 * (topo node)
1961 1959 */
1962 1960 if (topo_method_invoke(node, TOPO_METH_UNUSABLE,
1963 1961 TOPO_METH_UNUSABLE_VERSION, hap->ha_fmri, &hap->ha_nvl,
1964 1962 &err) < 0) {
1965 1963
1966 1964 /*
1967 1965 * Err on the side of caution and return usable
1968 1966 */
1969 1967 if (topo_mod_nvalloc(mod, &hap->ha_nvl, NV_UNIQUE_NAME) == 0)
1970 1968 if (nvlist_add_uint32(hap->ha_nvl,
1971 1969 TOPO_METH_UNUSABLE_RET, 0) == 0)
1972 1970 return (0);
1973 1971
1974 1972 return (ETOPO_PROP_NVL);
1975 1973 }
1976 1974
1977 1975 return (0);
1978 1976 }
1979 1977
1980 1978 static int
1981 1979 hc_fmri_unusable(topo_mod_t *mod, tnode_t *node, topo_version_t version,
1982 1980 nvlist_t *in, nvlist_t **out)
1983 1981 {
1984 1982 int err;
1985 1983 struct hc_walk *hwp;
1986 1984 struct hc_args *hap;
1987 1985
1988 1986 if (version > TOPO_METH_UNUSABLE_VERSION)
1989 1987 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
1990 1988
1991 1989 if ((hap = topo_mod_alloc(mod, sizeof (struct hc_args))) == NULL)
1992 1990 return (topo_mod_seterrno(mod, EMOD_NOMEM));
1993 1991
1994 1992 hap->ha_fmri = in;
1995 1993 hap->ha_nvl = NULL;
1996 1994 if ((hwp = hc_walk_init(mod, node, hap->ha_fmri, hc_unusable,
1997 1995 (void *)hap)) != NULL) {
1998 1996 if (topo_walk_step(hwp->hcw_wp, TOPO_WALK_CHILD) ==
1999 1997 TOPO_WALK_ERR)
2000 1998 err = -1;
2001 1999 else
2002 2000 err = 0;
2003 2001 topo_walk_fini(hwp->hcw_wp);
2004 2002 topo_mod_free(mod, hwp, sizeof (struct hc_walk));
2005 2003 } else {
2006 2004 err = -1;
2007 2005 }
2008 2006
2009 2007 if (hap->ha_nvl != NULL)
2010 2008 *out = hap->ha_nvl;
2011 2009
2012 2010 topo_mod_free(mod, hap, sizeof (struct hc_args));
2013 2011
2014 2012 return (err);
2015 2013 }
2016 2014
2017 2015 struct fac_lookup {
2018 2016 const char *fl_fac_type;
2019 2017 uint32_t fl_fac_subtype;
2020 2018 #ifdef _LP64
2021 2019 uint64_t fl_callback;
2022 2020 uint64_t fl_callback_args;
2023 2021 #else
2024 2022 uint32_t fl_callback;
2025 2023 uint32_t fl_callback_args;
2026 2024 #endif
2027 2025 nvlist_t *fl_rsrc;
2028 2026 nvlist_t *fl_fac_rsrc;
2029 2027 };
2030 2028
2031 2029 static int
2032 2030 hc_fac_get(topo_mod_t *mod, tnode_t *node, void *pdata)
2033 2031 {
2034 2032 struct fac_lookup *flp = (struct fac_lookup *)pdata;
2035 2033 topo_walk_cb_t cb = (topo_walk_cb_t)flp->fl_callback;
2036 2034 topo_faclist_t faclist, *tmp;
2037 2035 int err, ret = 0;
2038 2036
2039 2037 /*
2040 2038 * Lookup the specified facility node. Return with an error if we can't
2041 2039 * find it.
2042 2040 */
2043 2041 if (topo_node_facility(mod->tm_hdl, node, flp->fl_fac_type,
2044 2042 flp->fl_fac_subtype, &faclist, &err) != 0) {
2045 2043 topo_mod_dprintf(mod, "hc_fac_get: topo_node_facility "
2046 2044 "failed\n");
2047 2045 return (TOPO_WALK_ERR);
2048 2046 }
2049 2047
2050 2048 /*
2051 2049 * Invoke user's callback for each facility node in the topo list,
2052 2050 * passing in a pointer to the facility node
2053 2051 */
2054 2052 for (tmp = topo_list_next(&faclist.tf_list); tmp != NULL;
2055 2053 tmp = topo_list_next(tmp)) {
2056 2054
2057 2055 if ((err = cb(mod->tm_hdl, tmp->tf_node,
2058 2056 (void *)flp->fl_callback_args)) != 0) {
2059 2057 (void) topo_mod_seterrno(mod, err);
2060 2058 topo_mod_dprintf(mod, "hc_fac_get: callback failed: "
2061 2059 "%s\n ", topo_mod_errmsg(mod));
2062 2060 ret = TOPO_WALK_ERR;
2063 2061 break;
2064 2062 }
2065 2063 }
2066 2064
2067 2065 while ((tmp = topo_list_next(&faclist.tf_list)) != NULL) {
2068 2066 topo_list_delete(&faclist.tf_list, tmp);
2069 2067 topo_mod_free(mod, tmp, sizeof (topo_faclist_t));
2070 2068 }
2071 2069 return (ret);
2072 2070 }
2073 2071
2074 2072 static int
2075 2073 hc_fmri_facility(topo_mod_t *mod, tnode_t *node, topo_version_t version,
2076 2074 nvlist_t *in, nvlist_t **out)
2077 2075 {
2078 2076 int err = 0;
2079 2077 struct hc_walk *hwp;
2080 2078 struct fac_lookup *flp;
2081 2079
2082 2080 if (version > TOPO_METH_FACILITY_VERSION)
2083 2081 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
2084 2082
2085 2083 if ((flp = topo_mod_alloc(mod, sizeof (struct fac_lookup))) == NULL)
2086 2084 return (topo_mod_seterrno(mod, EMOD_NOMEM));
2087 2085
2088 2086 /*
2089 2087 * lookup arguments: hw resource, facility type, facility subtype,
2090 2088 * callback and callback args
2091 2089 */
2092 2090 err = nvlist_lookup_nvlist(in, TOPO_PROP_RESOURCE, &flp->fl_rsrc);
2093 2091 err |= nvlist_lookup_string(in, FM_FMRI_FACILITY_TYPE,
2094 2092 (char **)&flp->fl_fac_type);
2095 2093 err |= nvlist_lookup_uint32(in, "type", &flp->fl_fac_subtype);
2096 2094 #ifdef _LP64
2097 2095 err |= nvlist_lookup_uint64(in, "callback", &flp->fl_callback);
2098 2096 err |= nvlist_lookup_uint64(in, "callback-args",
2099 2097 &flp->fl_callback_args);
2100 2098 #else
2101 2099 err |= nvlist_lookup_uint32(in, "callback", &flp->fl_callback);
2102 2100 err |= nvlist_lookup_uint32(in, "callback-args",
2103 2101 &flp->fl_callback_args);
2104 2102 #endif
2105 2103 if (err != 0) {
2106 2104 topo_mod_dprintf(mod, "hc_fmri_facility: failed to construct "
2107 2105 "walker arg nvlist\n");
2108 2106 topo_mod_free(mod, flp, sizeof (struct fac_lookup));
2109 2107 return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
2110 2108 }
2111 2109
2112 2110 flp->fl_fac_rsrc = NULL;
2113 2111 if ((hwp = hc_walk_init(mod, node, flp->fl_rsrc, hc_fac_get,
2114 2112 (void *)flp)) != NULL) {
2115 2113 if (topo_walk_step(hwp->hcw_wp, TOPO_WALK_CHILD) ==
2116 2114 TOPO_WALK_ERR)
2117 2115 err = -1;
2118 2116 else
2119 2117 err = 0;
2120 2118 topo_walk_fini(hwp->hcw_wp);
2121 2119 topo_mod_free(mod, hwp, sizeof (struct hc_walk));
2122 2120 } else {
2123 2121 topo_mod_dprintf(mod, "hc_fmri_facility: failed to initialize "
2124 2122 "hc walker\n");
2125 2123 err = -1;
2126 2124 }
2127 2125
2128 2126 if (flp->fl_fac_rsrc != NULL)
2129 2127 *out = flp->fl_fac_rsrc;
2130 2128
2131 2129 topo_mod_free(mod, flp, sizeof (struct fac_lookup));
2132 2130
2133 2131 return (err);
2134 2132 }
2135 2133
2136 2134 /* ARGSUSED */
2137 2135 static int
2138 2136 hc_expand(topo_mod_t *mod, tnode_t *node, void *pdata)
2139 2137 {
2140 2138 int err;
2141 2139 nvlist_t *nvl;
2142 2140 const char **namep;
2143 2141 struct hc_args *hap = (struct hc_args *)pdata;
2144 2142 const char *names[] = {
2145 2143 FM_FMRI_HC_SERIAL_ID,
2146 2144 FM_FMRI_HC_PART,
2147 2145 FM_FMRI_HC_REVISION,
2148 2146 NULL
2149 2147 };
2150 2148
2151 2149 if (topo_node_resource(node, &nvl, &err) != 0)
2152 2150 return (ETOPO_METHOD_FAIL);
2153 2151
2154 2152 for (namep = names; *namep != NULL; namep++) {
2155 2153 char *in_val, *node_val;
2156 2154
2157 2155 if (nvlist_lookup_string(nvl, *namep, &node_val) != 0)
2158 2156 continue;
2159 2157
2160 2158 if (nvlist_lookup_string(hap->ha_fmri, *namep, &in_val) == 0) {
2161 2159 if (strcmp(in_val, node_val) == 0)
2162 2160 continue;
2163 2161 (void) nvlist_remove(hap->ha_fmri, *namep,
2164 2162 DATA_TYPE_STRING);
2165 2163 }
2166 2164
2167 2165 if (nvlist_add_string(hap->ha_fmri, *namep, node_val) != 0) {
2168 2166 nvlist_free(nvl);
2169 2167 return (ETOPO_PROP_NVL);
2170 2168 }
2171 2169 }
2172 2170 nvlist_free(nvl);
2173 2171
2174 2172 return (0);
2175 2173 }
2176 2174
2177 2175 /* ARGSUSED */
2178 2176 static int
2179 2177 hc_fmri_expand(topo_mod_t *mod, tnode_t *node, topo_version_t version,
2180 2178 nvlist_t *in, nvlist_t **out)
2181 2179 {
2182 2180 int err;
2183 2181 struct hc_walk *hwp;
2184 2182 struct hc_args *hap;
2185 2183
2186 2184 if (version > TOPO_METH_EXPAND_VERSION)
2187 2185 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
2188 2186
2189 2187 if ((hap = topo_mod_alloc(mod, sizeof (struct hc_args))) == NULL)
2190 2188 return (topo_mod_seterrno(mod, EMOD_NOMEM));
2191 2189
2192 2190 hap->ha_fmri = in;
2193 2191 hap->ha_nvl = NULL;
2194 2192 if ((hwp = hc_walk_init(mod, node, hap->ha_fmri, hc_expand,
2195 2193 (void *)hap)) != NULL) {
2196 2194 if (topo_walk_step(hwp->hcw_wp, TOPO_WALK_CHILD) ==
2197 2195 TOPO_WALK_ERR)
2198 2196 err = -1;
2199 2197 else
2200 2198 err = 0;
2201 2199 topo_walk_fini(hwp->hcw_wp);
2202 2200 } else {
2203 2201 err = -1;
2204 2202 }
2205 2203
2206 2204 topo_mod_free(mod, hwp, sizeof (struct hc_walk));
2207 2205
2208 2206 /* expand method should not return out nvlist */
2209 2207 assert(hap->ha_nvl == NULL);
2210 2208
2211 2209 topo_mod_free(mod, hap, sizeof (struct hc_args));
2212 2210
2213 2211 return (err);
2214 2212 }
2215 2213
2216 2214 static int
2217 2215 hc_retire_subr(topo_mod_t *mod, tnode_t *node, void *pdata)
2218 2216 {
2219 2217 int err, rc;
2220 2218 struct hc_args *hap = (struct hc_args *)pdata;
2221 2219
2222 2220 topo_mod_dprintf(mod, "hc_retire_subr: invoking method %s\n",
2223 2221 hap->ha_method_name);
2224 2222 /*
2225 2223 * check with the enumerator that created this FMRI
2226 2224 * (topo node)
2227 2225 */
2228 2226 rc = topo_method_invoke(node, hap->ha_method_name,
2229 2227 hap->ha_method_ver, hap->ha_fmri, &hap->ha_nvl, &err);
2230 2228
2231 2229 topo_mod_dprintf(mod, "hc_retire_subr: invoking method %s "
2232 2230 "returned %d\n", hap->ha_method_name, rc);
2233 2231
2234 2232 return (rc < 0 ? err : 0);
2235 2233 }
2236 2234
2237 2235 static int
2238 2236 hc_fmri_retire_subr(topo_mod_t *mod, tnode_t *node, char *method_name,
2239 2237 topo_version_t builtin_version, topo_version_t version, nvlist_t *in,
2240 2238 nvlist_t **out)
2241 2239 {
2242 2240 int err;
2243 2241 struct hc_walk *hwp;
2244 2242 struct hc_args *hap;
2245 2243
2246 2244 if (version > builtin_version)
2247 2245 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
2248 2246
2249 2247 if ((hap = topo_mod_alloc(mod, sizeof (struct hc_args))) == NULL)
2250 2248 return (topo_mod_seterrno(mod, EMOD_NOMEM));
2251 2249
2252 2250 hap->ha_fmri = in;
2253 2251 hap->ha_nvl = NULL;
2254 2252 hap->ha_method_name = method_name;
2255 2253 hap->ha_method_ver = version;
2256 2254 if ((hwp = hc_walk_init(mod, node, hap->ha_fmri, hc_retire_subr,
2257 2255 (void *)hap)) != NULL) {
2258 2256 if (topo_walk_step(hwp->hcw_wp, TOPO_WALK_CHILD) ==
2259 2257 TOPO_WALK_ERR)
2260 2258 err = -1;
2261 2259 else
2262 2260 err = 0;
2263 2261 topo_walk_fini(hwp->hcw_wp);
2264 2262 } else {
2265 2263 err = -1;
2266 2264 }
2267 2265
2268 2266 topo_mod_free(mod, hwp, sizeof (struct hc_walk));
2269 2267
2270 2268 if (hap->ha_nvl != NULL)
2271 2269 *out = hap->ha_nvl;
2272 2270
2273 2271 topo_mod_free(mod, hap, sizeof (struct hc_args));
2274 2272
2275 2273 return (err);
2276 2274 }
2277 2275
2278 2276 static int
2279 2277 hc_fmri_retire(topo_mod_t *mod, tnode_t *node, topo_version_t version,
2280 2278 nvlist_t *in, nvlist_t **out)
2281 2279 {
2282 2280 return (hc_fmri_retire_subr(mod, node, TOPO_METH_RETIRE,
2283 2281 TOPO_METH_RETIRE_VERSION, version, in, out));
2284 2282 }
2285 2283
2286 2284 static int
2287 2285 hc_fmri_unretire(topo_mod_t *mod, tnode_t *node, topo_version_t version,
2288 2286 nvlist_t *in, nvlist_t **out)
2289 2287 {
2290 2288 return (hc_fmri_retire_subr(mod, node, TOPO_METH_UNRETIRE,
2291 2289 TOPO_METH_UNRETIRE_VERSION, version, in, out));
2292 2290 }
2293 2291
2294 2292 static int
2295 2293 hc_fmri_service_state(topo_mod_t *mod, tnode_t *node, topo_version_t version,
2296 2294 nvlist_t *in, nvlist_t **out)
2297 2295 {
2298 2296 return (hc_fmri_retire_subr(mod, node, TOPO_METH_SERVICE_STATE,
2299 2297 TOPO_METH_SERVICE_STATE_VERSION, version, in, out));
2300 2298 }
↓ open down ↓ |
1109 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX