Print this page
patch tsoome-feedback
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/fm/topo/libtopo/common/topo_fmri.c
+++ new/usr/src/lib/fm/topo/libtopo/common/topo_fmri.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 #include <ctype.h>
28 28 #include <string.h>
29 29 #include <limits.h>
30 30 #include <fm/topo_mod.h>
31 31 #include <fm/fmd_fmri.h>
32 32 #include <sys/fm/protocol.h>
33 33 #include <topo_alloc.h>
34 34 #include <topo_error.h>
35 35 #include <topo_hc.h>
36 36 #include <topo_method.h>
37 37 #include <topo_subr.h>
38 38 #include <topo_string.h>
39 39
40 40 /*
41 41 * Topology node properties and method operations may be accessed by FMRI.
42 42 * The FMRI used to perform property look-ups and method operations is
43 43 * the FMRI contained in the matching topology node's protocol property
44 44 * grouping for the resource property. The full range of fmd(1M)
45 45 * scheme plugin operations are supported as long as a backend method is
46 46 * supplied by a scheme-specific enumerator or the enumerator module that
47 47 * created the matching topology node. Support for fmd scheme operations
48 48 * include:
49 49 *
50 50 * - expand
51 51 * - present
52 52 * - replaced
53 53 * - contains
54 54 * - unusable
55 55 * - service_state
56 56 * - nvl2str
57 57 * - retire
58 58 * - unretire
59 59 *
60 60 * In addition, the following operations are supported per-FMRI:
61 61 *
62 62 * - str2nvl: convert string-based FMRI to nvlist
63 63 * - compare: compare two FMRIs
64 64 * - asru: lookup associated ASRU property by FMRI
65 65 * - fru: lookup associated FRU by FMRI
66 66 * - create: an FMRI nvlist by scheme type
↓ open down ↓ |
66 lines elided |
↑ open up ↑ |
67 67 * - propery lookup
68 68 *
69 69 * These routines may only be called by consumers of a topology snapshot.
70 70 * They may not be called by libtopo enumerator or method modules.
71 71 */
72 72
73 73 /*ARGSUSED*/
74 74 static int
75 75 set_error(topo_hdl_t *thp, int err, int *errp, char *method, nvlist_t *nvlp)
76 76 {
77 - if (nvlp != NULL)
78 - nvlist_free(nvlp);
77 + nvlist_free(nvlp);
79 78
80 79 topo_dprintf(thp, TOPO_DBG_ERR, "%s failed: %s\n", method,
81 80 topo_strerror(err));
82 81
83 82 *errp = err;
84 83 return (-1);
85 84 }
86 85
87 86 /*ARGSUSED*/
88 87 static nvlist_t *
89 88 set_nverror(topo_hdl_t *thp, int err, int *errp, char *method, nvlist_t *nvlp)
90 89 {
91 - if (nvlp != NULL)
92 - nvlist_free(nvlp);
90 + nvlist_free(nvlp);
93 91
94 92 topo_dprintf(thp, TOPO_DBG_ERR, "%s failed: %s\n", method,
95 93 topo_strerror(err));
96 94
97 95 *errp = err;
98 96 return (NULL);
99 97 }
100 98
101 99 int
102 100 topo_fmri_nvl2str(topo_hdl_t *thp, nvlist_t *fmri, char **fmristr, int *err)
103 101 {
104 102 char *scheme, *str;
105 103 nvlist_t *out = NULL;
106 104 tnode_t *rnode;
107 105
108 106 if (nvlist_lookup_string(fmri, FM_FMRI_SCHEME, &scheme) != 0)
109 107 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
110 108 TOPO_METH_NVL2STR, out));
111 109
112 110 if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
113 111 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
114 112 TOPO_METH_NVL2STR, out));
115 113
116 114 if (topo_method_invoke(rnode, TOPO_METH_NVL2STR,
117 115 TOPO_METH_NVL2STR_VERSION, fmri, &out, err) != 0)
118 116 return (set_error(thp, *err, err, TOPO_METH_NVL2STR, out));
119 117
120 118 if (out == NULL || nvlist_lookup_string(out, "fmri-string", &str) != 0)
121 119 return (set_error(thp, ETOPO_METHOD_INVAL, err,
122 120 TOPO_METH_NVL2STR, out));
123 121
124 122 if ((*fmristr = topo_hdl_strdup(thp, str)) == NULL)
125 123 return (set_error(thp, ETOPO_NOMEM, err,
126 124 TOPO_METH_NVL2STR, out));
127 125
128 126 nvlist_free(out);
129 127
130 128 return (0);
131 129 }
132 130
133 131 int
134 132 topo_fmri_str2nvl(topo_hdl_t *thp, const char *fmristr, nvlist_t **fmri,
135 133 int *err)
136 134 {
137 135 char *f, buf[PATH_MAX];
138 136 nvlist_t *out = NULL, *in = NULL;
139 137 tnode_t *rnode;
140 138
141 139 (void) strlcpy(buf, fmristr, sizeof (buf));
142 140 if ((f = strchr(buf, ':')) == NULL)
143 141 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
144 142 TOPO_METH_STR2NVL, in));
145 143
146 144 *f = '\0'; /* strip trailing FMRI path */
147 145
148 146 if ((rnode = topo_hdl_root(thp, buf)) == NULL)
149 147 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
150 148 TOPO_METH_STR2NVL, in));
151 149
152 150 if (topo_hdl_nvalloc(thp, &in, NV_UNIQUE_NAME) != 0)
153 151 return (set_error(thp, ETOPO_FMRI_NVL, err, TOPO_METH_STR2NVL,
154 152 in));
155 153
156 154 if (nvlist_add_string(in, "fmri-string", fmristr) != 0)
157 155 return (set_error(thp, ETOPO_FMRI_NVL, err, TOPO_METH_STR2NVL,
158 156 in));
159 157
160 158 if (topo_method_invoke(rnode, TOPO_METH_STR2NVL,
161 159 TOPO_METH_STR2NVL_VERSION, in, &out, err) != 0)
162 160 return (set_error(thp, *err, err, TOPO_METH_STR2NVL, in));
163 161
164 162 nvlist_free(in);
165 163
166 164 if (out == NULL ||
167 165 topo_hdl_nvdup(thp, out, fmri) != 0)
168 166 return (set_error(thp, ETOPO_FMRI_NVL, err,
169 167 TOPO_METH_STR2NVL, out));
170 168
171 169 nvlist_free(out);
172 170
173 171 return (0);
174 172 }
175 173
176 174 int
177 175 topo_fmri_present(topo_hdl_t *thp, nvlist_t *fmri, int *err)
178 176 {
179 177 uint32_t present = 0;
180 178 char *scheme;
181 179 nvlist_t *out = NULL;
182 180 tnode_t *rnode;
183 181
184 182 if (nvlist_lookup_string(fmri, FM_FMRI_SCHEME, &scheme) != 0)
185 183 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
186 184 TOPO_METH_PRESENT, out));
187 185
188 186 if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
189 187 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
190 188 TOPO_METH_PRESENT, out));
191 189
192 190 if (topo_method_invoke(rnode, TOPO_METH_PRESENT,
193 191 TOPO_METH_PRESENT_VERSION, fmri, &out, err) < 0) {
194 192 (void) set_error(thp, *err, err, TOPO_METH_PRESENT, out);
195 193 return (present);
196 194 }
197 195
198 196 (void) nvlist_lookup_uint32(out, TOPO_METH_PRESENT_RET, &present);
199 197 nvlist_free(out);
200 198
201 199 return (present);
202 200 }
203 201
204 202 int
205 203 topo_fmri_replaced(topo_hdl_t *thp, nvlist_t *fmri, int *err)
206 204 {
207 205 uint32_t replaced = FMD_OBJ_STATE_NOT_PRESENT;
208 206 char *scheme;
209 207 nvlist_t *out = NULL;
210 208 tnode_t *rnode;
211 209
212 210 if (nvlist_lookup_string(fmri, FM_FMRI_SCHEME, &scheme) != 0)
213 211 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
214 212 TOPO_METH_REPLACED, out));
215 213
216 214 if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
217 215 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
218 216 TOPO_METH_REPLACED, out));
219 217
220 218 if (topo_method_invoke(rnode, TOPO_METH_REPLACED,
221 219 TOPO_METH_REPLACED_VERSION, fmri, &out, err) < 0) {
222 220 (void) set_error(thp, *err, err, TOPO_METH_REPLACED, out);
223 221 return (FMD_OBJ_STATE_UNKNOWN);
224 222 }
225 223
226 224 (void) nvlist_lookup_uint32(out, TOPO_METH_REPLACED_RET, &replaced);
227 225 nvlist_free(out);
228 226
229 227 return (replaced);
230 228 }
231 229
232 230 int
233 231 topo_fmri_contains(topo_hdl_t *thp, nvlist_t *fmri, nvlist_t *subfmri, int *err)
234 232 {
235 233 uint32_t contains;
236 234 char *scheme;
237 235 nvlist_t *in = NULL, *out = NULL;
238 236 tnode_t *rnode;
239 237
240 238 if (nvlist_lookup_string(fmri, FM_FMRI_SCHEME, &scheme) != 0)
241 239 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
242 240 TOPO_METH_CONTAINS, NULL));
243 241
244 242 if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
245 243 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
246 244 TOPO_METH_CONTAINS, NULL));
247 245
248 246 if (topo_hdl_nvalloc(thp, &in, NV_UNIQUE_NAME) != 0)
249 247 return (set_error(thp, ETOPO_FMRI_NVL, err, TOPO_METH_CONTAINS,
250 248 NULL));
251 249
252 250 if (nvlist_add_nvlist(in, TOPO_METH_FMRI_ARG_FMRI, fmri) != 0 ||
253 251 nvlist_add_nvlist(in, TOPO_METH_FMRI_ARG_SUBFMRI, subfmri) != 0)
254 252 return (set_error(thp, ETOPO_FMRI_NVL, err, TOPO_METH_CONTAINS,
255 253 in));
256 254
257 255 if (topo_method_invoke(rnode, TOPO_METH_CONTAINS,
258 256 TOPO_METH_CONTAINS_VERSION, in, &out, err) < 0)
259 257 return (set_error(thp, *err, err, TOPO_METH_CONTAINS, in));
260 258
261 259 (void) nvlist_lookup_uint32(out, TOPO_METH_CONTAINS_RET, &contains);
262 260 nvlist_free(in);
263 261 nvlist_free(out);
264 262
265 263 return (contains);
266 264 }
267 265
268 266 int
269 267 topo_fmri_unusable(topo_hdl_t *thp, nvlist_t *fmri, int *err)
270 268 {
271 269 char *scheme;
272 270 uint32_t unusable = 0;
273 271 nvlist_t *out = NULL;
274 272 tnode_t *rnode;
275 273
276 274 if (nvlist_lookup_string(fmri, FM_FMRI_SCHEME, &scheme) != 0)
277 275 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
278 276 TOPO_METH_UNUSABLE, out));
279 277
280 278 if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
281 279 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
282 280 TOPO_METH_UNUSABLE, out));
283 281
284 282 if (topo_method_invoke(rnode, TOPO_METH_UNUSABLE,
285 283 TOPO_METH_UNUSABLE_VERSION, fmri, &out, err) < 0)
286 284 return (set_error(thp, *err, err, TOPO_METH_UNUSABLE, out));
287 285
288 286 (void) nvlist_lookup_uint32(out, TOPO_METH_UNUSABLE_RET, &unusable);
289 287 nvlist_free(out);
290 288
291 289 return (unusable);
292 290 }
293 291
294 292 int
295 293 topo_fmri_retire(topo_hdl_t *thp, nvlist_t *fmri, int *err)
296 294 {
297 295 char *scheme;
298 296 uint32_t status;
299 297 nvlist_t *out = NULL;
300 298 tnode_t *rnode;
301 299
302 300 if (nvlist_lookup_string(fmri, FM_FMRI_SCHEME, &scheme) != 0)
303 301 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
304 302 TOPO_METH_RETIRE, out));
305 303
306 304 if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
307 305 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
308 306 TOPO_METH_RETIRE, out));
309 307
310 308 if (topo_method_invoke(rnode, TOPO_METH_RETIRE,
311 309 TOPO_METH_RETIRE_VERSION, fmri, &out, err) < 0)
312 310 return (set_error(thp, *err, err, TOPO_METH_RETIRE, out));
313 311
314 312 if (nvlist_lookup_uint32(out, TOPO_METH_RETIRE_RET, &status) != 0)
315 313 return (set_error(thp, ETOPO_METHOD_FAIL, err,
316 314 TOPO_METH_RETIRE, out));
317 315 nvlist_free(out);
318 316
319 317 return (status);
320 318 }
321 319
322 320 int
323 321 topo_fmri_unretire(topo_hdl_t *thp, nvlist_t *fmri, int *err)
324 322 {
325 323 char *scheme;
326 324 uint32_t status;
327 325 nvlist_t *out = NULL;
328 326 tnode_t *rnode;
329 327
330 328 if (nvlist_lookup_string(fmri, FM_FMRI_SCHEME, &scheme) != 0)
331 329 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
332 330 TOPO_METH_UNRETIRE, out));
333 331
334 332 if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
335 333 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
336 334 TOPO_METH_UNRETIRE, out));
337 335
338 336 if (topo_method_invoke(rnode, TOPO_METH_UNRETIRE,
339 337 TOPO_METH_UNRETIRE_VERSION, fmri, &out, err) < 0)
340 338 return (set_error(thp, *err, err, TOPO_METH_UNRETIRE, out));
341 339
342 340 if (nvlist_lookup_uint32(out, TOPO_METH_UNRETIRE_RET, &status) != 0) {
343 341 nvlist_free(out);
344 342 return (set_error(thp, ETOPO_METHOD_FAIL, err,
345 343 TOPO_METH_UNRETIRE, out));
346 344 }
347 345 nvlist_free(out);
348 346
349 347 return (status);
350 348 }
351 349
352 350 int
353 351 topo_fmri_service_state(topo_hdl_t *thp, nvlist_t *fmri, int *err)
354 352 {
355 353 char *scheme;
356 354 uint32_t service_state = FMD_SERVICE_STATE_UNKNOWN;
357 355 nvlist_t *out = NULL;
358 356 tnode_t *rnode;
359 357
360 358 if (nvlist_lookup_string(fmri, FM_FMRI_SCHEME, &scheme) != 0)
361 359 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
362 360 TOPO_METH_SERVICE_STATE, out));
363 361
364 362 if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
365 363 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
366 364 TOPO_METH_SERVICE_STATE, out));
367 365
368 366 if (topo_method_invoke(rnode, TOPO_METH_SERVICE_STATE,
369 367 TOPO_METH_SERVICE_STATE_VERSION, fmri, &out, err) < 0)
370 368 return (set_error(thp, *err, err, TOPO_METH_SERVICE_STATE,
371 369 out));
372 370
373 371 (void) nvlist_lookup_uint32(out, TOPO_METH_SERVICE_STATE_RET,
374 372 &service_state);
375 373 nvlist_free(out);
376 374
377 375 return (service_state);
378 376 }
379 377
380 378 int
381 379 topo_fmri_expand(topo_hdl_t *thp, nvlist_t *fmri, int *err)
382 380 {
383 381 char *scheme;
384 382 nvlist_t *out = NULL;
385 383 tnode_t *rnode;
386 384
387 385 if (nvlist_lookup_string(fmri, FM_FMRI_SCHEME, &scheme) != 0)
388 386 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
389 387 TOPO_METH_EXPAND, out));
390 388
391 389 if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
392 390 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
393 391 TOPO_METH_EXPAND, out));
394 392
395 393 if (topo_method_invoke(rnode, TOPO_METH_EXPAND,
396 394 TOPO_METH_EXPAND_VERSION, fmri, &out, err) != 0)
397 395 return (set_error(thp, *err, err, TOPO_METH_EXPAND, out));
398 396
399 397 return (0);
400 398 }
401 399
402 400 static int
403 401 fmri_prop(topo_hdl_t *thp, nvlist_t *rsrc, const char *pgname,
404 402 const char *pname, nvlist_t *args, nvlist_t **prop,
405 403 int *err)
406 404 {
407 405 int rv;
408 406 nvlist_t *in = NULL;
409 407 tnode_t *rnode;
410 408 char *scheme;
411 409
412 410 if (nvlist_lookup_string(rsrc, FM_FMRI_SCHEME, &scheme) != 0)
413 411 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
414 412 TOPO_METH_PROP_GET, in));
415 413
416 414 if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
417 415 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
418 416 TOPO_METH_PROP_GET, in));
419 417
420 418 if (topo_hdl_nvalloc(thp, &in, NV_UNIQUE_NAME) != 0)
421 419 return (set_error(thp, ETOPO_FMRI_NVL, err,
422 420 TOPO_METH_PROP_GET, in));
423 421
424 422 rv = nvlist_add_nvlist(in, TOPO_PROP_RESOURCE, rsrc);
425 423 rv |= nvlist_add_string(in, TOPO_PROP_GROUP, pgname);
426 424 rv |= nvlist_add_string(in, TOPO_PROP_VAL_NAME, pname);
427 425 if (args != NULL)
428 426 rv |= nvlist_add_nvlist(in, TOPO_PROP_PARGS, args);
429 427 if (rv != 0)
430 428 return (set_error(thp, ETOPO_FMRI_NVL, err,
431 429 TOPO_METH_PROP_GET, in));
432 430
433 431 *prop = NULL;
434 432 rv = topo_method_invoke(rnode, TOPO_METH_PROP_GET,
435 433 TOPO_METH_PROP_GET_VERSION, in, prop, err);
436 434
437 435 nvlist_free(in);
438 436
439 437 if (rv != 0)
440 438 return (-1); /* *err is set for us */
441 439
442 440 if (*prop == NULL)
443 441 return (set_error(thp, ETOPO_PROP_NOENT, err,
444 442 TOPO_METH_PROP_GET, NULL));
445 443 return (0);
446 444 }
447 445
448 446 int
449 447 topo_fmri_asru(topo_hdl_t *thp, nvlist_t *nvl, nvlist_t **asru, int *err)
450 448 {
451 449 nvlist_t *ap, *prop = NULL;
452 450
453 451 if (fmri_prop(thp, nvl, TOPO_PGROUP_PROTOCOL, TOPO_PROP_ASRU,
454 452 nvl, &prop, err) < 0)
455 453 return (set_error(thp, *err, err, "topo_fmri_asru", NULL));
456 454
457 455 if (nvlist_lookup_nvlist(prop, TOPO_PROP_VAL_VAL, &ap) != 0)
458 456 return (set_error(thp, ETOPO_PROP_NVL, err, "topo_fmri_asru",
459 457 prop));
460 458
461 459 if (topo_hdl_nvdup(thp, ap, asru) < 0)
462 460 return (set_error(thp, ETOPO_PROP_NOMEM, err, "topo_fmri_asru",
463 461 prop));
464 462
465 463 nvlist_free(prop);
466 464
467 465 return (0);
468 466 }
469 467
470 468 int
471 469 topo_fmri_fru(topo_hdl_t *thp, nvlist_t *nvl, nvlist_t **fru, int *err)
472 470 {
473 471 nvlist_t *fp, *prop = NULL;
474 472
475 473 if (fmri_prop(thp, nvl, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU,
476 474 nvl, &prop, err) < 0)
477 475 return (set_error(thp, *err, err, "topo_fmri_fru", NULL));
478 476
479 477 if (nvlist_lookup_nvlist(prop, TOPO_PROP_VAL_VAL, &fp) != 0)
480 478 return (set_error(thp, ETOPO_PROP_NVL, err, "topo_fmri_fru",
481 479 prop));
482 480
483 481 if (topo_hdl_nvdup(thp, fp, fru) < 0)
484 482 return (set_error(thp, ETOPO_PROP_NOMEM, err, "topo_fmri_fru",
485 483 prop));
486 484
487 485 nvlist_free(prop);
488 486
489 487 return (0);
490 488 }
491 489
492 490 int
493 491 topo_fmri_label(topo_hdl_t *thp, nvlist_t *nvl, char **label, int *err)
494 492 {
495 493 nvlist_t *prop = NULL;
496 494 char *lp;
497 495
498 496 if (fmri_prop(thp, nvl, TOPO_PGROUP_PROTOCOL, TOPO_PROP_LABEL,
499 497 NULL, &prop, err) < 0)
500 498 return (set_error(thp, *err, err, "topo_fmri_label", NULL));
501 499
502 500 if (nvlist_lookup_string(prop, TOPO_PROP_VAL_VAL, &lp) != 0)
503 501 return (set_error(thp, ETOPO_PROP_NVL, err, "topo_fmri_label",
504 502 prop));
505 503
506 504 if ((*label = topo_hdl_strdup(thp, lp)) == NULL)
507 505 return (set_error(thp, ETOPO_PROP_NOMEM, err, "topo_fmri_label",
508 506 prop));
509 507
510 508 nvlist_free(prop);
511 509
512 510 return (0);
513 511 }
514 512
515 513 int
516 514 topo_fmri_serial(topo_hdl_t *thp, nvlist_t *nvl, char **serial, int *err)
517 515 {
518 516 nvlist_t *prop = NULL;
519 517 char *sp;
520 518
521 519 /*
522 520 * If there is a serial id in the resource fmri, then use that.
523 521 * Otherwise fall back to looking for a serial id property in the
524 522 * protocol group.
525 523 */
526 524 if (nvlist_lookup_string(nvl, FM_FMRI_HC_SERIAL_ID, &sp) == 0) {
527 525 if ((*serial = topo_hdl_strdup(thp, sp)) == NULL)
528 526 return (set_error(thp, ETOPO_PROP_NOMEM, err,
529 527 "topo_fmri_serial", prop));
530 528 else
531 529 return (0);
532 530 }
533 531
534 532 if (fmri_prop(thp, nvl, TOPO_PGROUP_PROTOCOL, FM_FMRI_HC_SERIAL_ID,
535 533 NULL, &prop, err) < 0)
536 534 return (set_error(thp, *err, err, "topo_fmri_serial", NULL));
537 535
538 536 if (nvlist_lookup_string(prop, TOPO_PROP_VAL_VAL, &sp) != 0)
539 537 return (set_error(thp, ETOPO_PROP_NVL, err, "topo_fmri_serial",
540 538 prop));
541 539
542 540 if ((*serial = topo_hdl_strdup(thp, sp)) == NULL)
543 541 return (set_error(thp, ETOPO_PROP_NOMEM, err,
544 542 "topo_fmri_serial", prop));
545 543
546 544 nvlist_free(prop);
547 545
548 546 return (0);
549 547 }
550 548
551 549 int topo_fmri_getprop(topo_hdl_t *thp, nvlist_t *nvl, const char *pg,
552 550 const char *pname, nvlist_t *args, nvlist_t **prop,
553 551 int *err)
554 552 {
555 553 *prop = NULL;
556 554
557 555 return (fmri_prop(thp, nvl, pg, pname, args, prop, err));
558 556 }
559 557
560 558 int topo_fmri_setprop(topo_hdl_t *thp, nvlist_t *nvl, const char *pg,
561 559 nvlist_t *prop, int flag, nvlist_t *args, int *err)
562 560 {
563 561 int rv;
564 562 nvlist_t *in = NULL, *out = NULL;
565 563 tnode_t *rnode;
566 564 char *scheme;
567 565
568 566 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &scheme) != 0)
569 567 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
570 568 TOPO_METH_PROP_SET, in));
571 569
572 570 if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
573 571 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
574 572 TOPO_METH_PROP_SET, in));
575 573
576 574 if (topo_hdl_nvalloc(thp, &in, NV_UNIQUE_NAME) != 0)
577 575 return (set_error(thp, ETOPO_FMRI_NVL, err,
578 576 TOPO_METH_PROP_SET, in));
579 577
580 578 rv = nvlist_add_nvlist(in, TOPO_PROP_RESOURCE, nvl);
581 579 rv |= nvlist_add_string(in, TOPO_PROP_GROUP, pg);
582 580 rv |= nvlist_add_nvlist(in, TOPO_PROP_VAL, prop);
583 581 rv |= nvlist_add_int32(in, TOPO_PROP_FLAG, (int32_t)flag);
584 582 if (args != NULL)
585 583 rv |= nvlist_add_nvlist(in, TOPO_PROP_PARGS, args);
↓ open down ↓ |
483 lines elided |
↑ open up ↑ |
586 584 if (rv != 0)
587 585 return (set_error(thp, ETOPO_FMRI_NVL, err,
588 586 TOPO_METH_PROP_SET, in));
589 587
590 588 rv = topo_method_invoke(rnode, TOPO_METH_PROP_SET,
591 589 TOPO_METH_PROP_SET_VERSION, in, &out, err);
592 590
593 591 nvlist_free(in);
594 592
595 593 /* no return values */
596 - if (out != NULL)
597 - nvlist_free(out);
594 + nvlist_free(out);
598 595
599 596 if (rv)
600 597 return (-1);
601 598
602 599 return (0);
603 600
604 601 }
605 602
606 603 int
607 604 topo_fmri_getpgrp(topo_hdl_t *thp, nvlist_t *rsrc, const char *pgname,
608 605 nvlist_t **pgroup, int *err)
609 606 {
610 607 int rv;
611 608 nvlist_t *in = NULL;
612 609 tnode_t *rnode;
613 610 char *scheme;
614 611
615 612 if (nvlist_lookup_string(rsrc, FM_FMRI_SCHEME, &scheme) != 0)
616 613 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
617 614 TOPO_METH_PROP_GET, in));
618 615
619 616 if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
620 617 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
621 618 TOPO_METH_PROP_GET, in));
622 619
623 620 if (topo_hdl_nvalloc(thp, &in, NV_UNIQUE_NAME) != 0)
624 621 return (set_error(thp, ETOPO_FMRI_NVL, err,
625 622 TOPO_METH_PROP_GET, in));
626 623
627 624 rv = nvlist_add_nvlist(in, TOPO_PROP_RESOURCE, rsrc);
628 625 rv |= nvlist_add_string(in, TOPO_PROP_GROUP, pgname);
629 626 if (rv != 0)
630 627 return (set_error(thp, ETOPO_FMRI_NVL, err,
631 628 TOPO_METH_PROP_GET, in));
632 629
633 630 *pgroup = NULL;
634 631 rv = topo_method_invoke(rnode, TOPO_METH_PGRP_GET,
635 632 TOPO_METH_PGRP_GET_VERSION, in, pgroup, err);
636 633
637 634 nvlist_free(in);
638 635
639 636 if (rv != 0)
640 637 return (-1); /* *err is set for us */
641 638
642 639 if (*pgroup == NULL)
643 640 return (set_error(thp, ETOPO_PROP_NOENT, err,
644 641 TOPO_METH_PROP_GET, NULL));
645 642 return (0);
646 643 }
647 644
648 645 int
649 646 topo_fmri_compare(topo_hdl_t *thp, nvlist_t *f1, nvlist_t *f2, int *err)
650 647 {
651 648 uint32_t compare;
652 649 char *scheme1, *scheme2;
653 650 nvlist_t *in;
654 651 nvlist_t *out = NULL;
655 652 tnode_t *rnode;
656 653
657 654 if (nvlist_lookup_string(f1, FM_FMRI_SCHEME, &scheme1) != 0)
658 655 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
659 656 TOPO_METH_COMPARE, NULL));
660 657 if (nvlist_lookup_string(f2, FM_FMRI_SCHEME, &scheme2) != 0)
661 658 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
662 659 TOPO_METH_COMPARE, NULL));
663 660
664 661 if (strcmp(scheme1, scheme2) != 0)
665 662 return (0);
666 663
667 664 if ((rnode = topo_hdl_root(thp, scheme1)) == NULL)
668 665 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
669 666 TOPO_METH_COMPARE, NULL));
670 667
671 668 if (topo_hdl_nvalloc(thp, &in, NV_UNIQUE_NAME) != 0)
672 669 return (set_error(thp, ETOPO_FMRI_NVL, err, TOPO_METH_COMPARE,
673 670 NULL));
674 671
675 672 if (nvlist_add_nvlist(in, TOPO_METH_FMRI_ARG_NV1, f1) != 0 ||
676 673 nvlist_add_nvlist(in, TOPO_METH_FMRI_ARG_NV2, f2) != 0)
677 674 return (set_error(thp, ETOPO_FMRI_NVL, err, TOPO_METH_COMPARE,
678 675 in));
679 676
680 677 if (topo_method_invoke(rnode, TOPO_METH_COMPARE,
681 678 TOPO_METH_COMPARE_VERSION, in, &out, err) < 0)
682 679 return (set_error(thp, *err, err, TOPO_METH_COMPARE, in));
683 680
684 681 (void) nvlist_lookup_uint32(out, TOPO_METH_COMPARE_RET, &compare);
685 682 nvlist_free(out);
686 683 nvlist_free(in);
687 684
688 685 return (compare);
689 686 }
690 687
691 688 /*
692 689 * topo_fmri_create
693 690 *
694 691 * If possible, creates an FMRI of the requested version in the
695 692 * requested scheme. Args are passed as part of the inputs to the
696 693 * fmri-create method of the scheme.
697 694 */
698 695 nvlist_t *
699 696 topo_fmri_create(topo_hdl_t *thp, const char *scheme, const char *name,
700 697 topo_instance_t inst, nvlist_t *nvl, int *err)
701 698 {
702 699 nvlist_t *ins;
703 700 nvlist_t *out;
704 701 tnode_t *rnode;
705 702
706 703 ins = out = NULL;
707 704
708 705 if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
709 706 return (set_nverror(thp, ETOPO_METHOD_NOTSUP, err,
710 707 TOPO_METH_FMRI, NULL));
711 708
712 709 if ((*err = topo_hdl_nvalloc(thp, &ins, NV_UNIQUE_NAME)) != 0)
713 710 return (set_nverror(thp, ETOPO_FMRI_NVL, err,
714 711 TOPO_METH_FMRI, NULL));
715 712
716 713 if (nvlist_add_string(ins, TOPO_METH_FMRI_ARG_NAME, name) != 0 ||
717 714 nvlist_add_uint32(ins, TOPO_METH_FMRI_ARG_INST, inst) != 0) {
718 715 return (set_nverror(thp, ETOPO_FMRI_NVL, err,
719 716 TOPO_METH_FMRI, ins));
720 717 }
721 718
722 719 if (nvl != NULL &&
723 720 nvlist_add_nvlist(ins, TOPO_METH_FMRI_ARG_NVL, nvl) != 0) {
724 721 return (set_nverror(thp, ETOPO_FMRI_NVL, err,
725 722 TOPO_METH_FMRI, ins));
726 723 }
727 724 if (topo_method_invoke(rnode,
728 725 TOPO_METH_FMRI, TOPO_METH_FMRI_VERSION, ins, &out, err) != 0) {
729 726 return (set_nverror(thp, *err, err, TOPO_METH_FMRI, ins));
730 727 }
731 728 nvlist_free(ins);
732 729 return (out);
733 730 }
734 731
735 732 /*
736 733 * These private utility functions are used by fmd to maintain its resource
737 734 * cache. Because hc instance numbers are not guaranteed, it's possible to
738 735 * have two different FMRI strings represent the same logical entity. These
739 736 * functions hide this implementation detail from unknowing consumers such as
740 737 * fmd.
741 738 *
742 739 * Ideally, we'd like to do a str2nvl() and then a full FMRI hash and
743 740 * comparison, but these functions are designed to be fast and efficient.
744 741 * Given that there is only a single hc node that has this property
745 742 * (ses-enclosure), we hard-code this behavior here. If there are more
746 743 * instances of this behavior in the future, this function could be made more
747 744 * generic.
748 745 *
749 746 * This code also handles changes in the server-id or revision fields of the hc
750 747 * FMRI, as these fields have no bearing on equivalence of FRUs.
751 748 */
752 749 static ulong_t
753 750 topo_fmri_strhash_one(const char *fmri, size_t len)
754 751 {
755 752 ulong_t g, h = 0;
756 753 size_t i;
757 754
758 755 for (i = 0; i < len; i++) {
759 756 h = (h << 4) + fmri[i];
760 757
761 758 if ((g = (h & 0xf0000000)) != 0) {
762 759 h ^= (g >> 24);
763 760 h ^= g;
764 761 }
765 762 }
766 763
767 764 return (h);
768 765 }
769 766
770 767 static const char *
771 768 topo_fmri_next_auth(const char *auth)
772 769 {
773 770 const char *colon, *slash;
774 771
775 772 colon = strchr(auth + 1, ':');
776 773 slash = strchr(auth, '/');
777 774
778 775 if (colon == NULL && slash == NULL)
779 776 return (NULL);
780 777
781 778 if (colon == NULL)
782 779 return (slash);
783 780 else if (slash < colon)
784 781 return (slash);
785 782 else
786 783 return (colon);
787 784 }
788 785
789 786 /*
790 787 * List of authority information we care about. Note that we explicitly ignore
791 788 * things that are properties of the chassis and not the resource itself:
792 789 *
793 790 * FM_FMRI_AUTH_PRODUCT_SN "product-sn"
794 791 * FM_FMRI_AUTH_PRODUCT "product-id"
795 792 * FM_FMRI_AUTH_DOMAIN "domain-id"
796 793 * FM_FMRI_AUTH_SERVER "server-id"
797 794 * FM_FMRI_AUTH_HOST "host-id"
798 795 *
799 796 * We also ignore the "revision" authority member, as that typically indicates
800 797 * the firmware revision and is not a static property of the FRU. This leaves
801 798 * the following interesting members:
802 799 *
803 800 * FM_FMRI_AUTH_CHASSIS "chassis-id"
804 801 * FM_FMRI_HC_SERIAL_ID "serial"
805 802 * FM_FMRI_HC_PART "part"
806 803 */
807 804 typedef enum {
808 805 HC_AUTH_CHASSIS,
809 806 HC_AUTH_SERIAL,
810 807 HC_AUTH_PART,
811 808 HC_AUTH_MAX
812 809 } hc_auth_type_t;
813 810
814 811 static char *hc_auth_table[] = {
815 812 FM_FMRI_AUTH_CHASSIS,
816 813 FM_FMRI_HC_SERIAL_ID,
817 814 FM_FMRI_HC_PART
818 815 };
819 816
820 817 /*
821 818 * Takes an authority member, with leading ":" and trailing "=", and returns
822 819 * one of the above types if it's one of the things we care about. If
823 820 * 'authlen' is specified, it is filled in with the length of the authority
824 821 * member, including leading and trailing characters.
825 822 */
826 823 static hc_auth_type_t
827 824 hc_auth_to_type(const char *auth, size_t *authlen)
828 825 {
829 826 int i;
830 827 size_t len;
831 828
832 829 if (auth[0] != ':')
833 830 return (HC_AUTH_MAX);
834 831
835 832 for (i = 0; i < HC_AUTH_MAX; i++) {
836 833 len = strlen(hc_auth_table[i]);
837 834
838 835 if (strncmp(auth + 1, hc_auth_table[i], len) == 0 &&
839 836 auth[len + 1] == '=') {
840 837 if (authlen)
841 838 *authlen = len + 2;
842 839 break;
843 840 }
844 841 }
845 842
846 843 return (i);
847 844 }
848 845
849 846 /*ARGSUSED*/
850 847 ulong_t
851 848 topo_fmri_strhash_internal(topo_hdl_t *thp, const char *fmri, boolean_t noauth)
852 849 {
853 850 const char *auth, *next;
854 851 const char *enclosure;
855 852 ulong_t h;
856 853 hc_auth_type_t type;
857 854
858 855 if (strncmp(fmri, "hc://", 5) != 0)
859 856 return (topo_fmri_strhash_one(fmri, strlen(fmri)));
860 857
861 858 enclosure = strstr(fmri, SES_ENCLOSURE);
862 859
863 860 h = 0;
864 861
865 862 auth = next = fmri + 5;
866 863 while (*next != '/') {
867 864 auth = next;
868 865
869 866 if ((next = topo_fmri_next_auth(auth)) == NULL) {
870 867 next = auth;
871 868 break;
872 869 }
873 870
874 871 if ((type = hc_auth_to_type(auth, NULL)) == HC_AUTH_MAX)
875 872 continue;
876 873
877 874 if (!noauth || type == HC_AUTH_CHASSIS)
878 875 h += topo_fmri_strhash_one(auth, next - auth);
879 876 }
880 877
881 878 if (enclosure) {
882 879 next = enclosure + sizeof (SES_ENCLOSURE);
883 880 while (isdigit(*next))
884 881 next++;
885 882 }
886 883
887 884 h += topo_fmri_strhash_one(next, strlen(next));
888 885
889 886 return (h);
890 887 }
891 888
892 889 /*ARGSUSED*/
893 890 ulong_t
894 891 topo_fmri_strhash(topo_hdl_t *thp, const char *fmri)
895 892 {
896 893 return (topo_fmri_strhash_internal(thp, fmri, B_FALSE));
897 894 }
898 895
899 896 /*ARGSUSED*/
900 897 ulong_t
901 898 topo_fmri_strhash_noauth(topo_hdl_t *thp, const char *fmri)
902 899 {
903 900 return (topo_fmri_strhash_internal(thp, fmri, B_TRUE));
904 901 }
905 902
906 903
907 904 static void
908 905 topo_fmri_strcmp_parse_auth(const char *auth, const char *authtype[],
909 906 size_t authlen[])
910 907 {
911 908 int i;
912 909 const char *next;
913 910 hc_auth_type_t type;
914 911 size_t len;
915 912
916 913 for (i = 0; i < HC_AUTH_MAX; i++)
917 914 authlen[i] = 0;
918 915
919 916 while (*auth != '/' &&
920 917 (next = topo_fmri_next_auth(auth)) != NULL) {
921 918 if ((type = hc_auth_to_type(auth, &len)) == HC_AUTH_MAX) {
922 919 auth = next;
923 920 continue;
924 921 }
925 922
926 923 authtype[type] = auth + len;
927 924 authlen[type] = next - (auth + len);
928 925 auth = next;
929 926 }
930 927 }
931 928
932 929 /*ARGSUSED*/
933 930 static boolean_t
934 931 topo_fmri_strcmp_internal(topo_hdl_t *thp, const char *a, const char *b,
935 932 boolean_t noauth)
936 933 {
937 934 const char *fmria, *fmrib;
938 935 const char *autha[HC_AUTH_MAX], *authb[HC_AUTH_MAX];
939 936 size_t authlena[HC_AUTH_MAX], authlenb[HC_AUTH_MAX];
940 937 int i;
941 938
942 939 /*
943 940 * For non-hc FMRIs, we don't do anything.
944 941 */
945 942 if (strncmp(a, "hc://", 5) != 0 ||
946 943 strncmp(b, "hc://", 5) != 0)
947 944 return (strcmp(a, b) == 0);
948 945
949 946 /*
950 947 * Get the portion of the FMRI independent of the authority
951 948 * information.
952 949 */
953 950 fmria = strchr(a + 5, '/');
954 951 fmrib = strchr(b + 5, '/');
955 952 if (fmria == NULL || fmrib == NULL)
956 953 return (strcmp(a, b));
957 954 fmria++;
958 955 fmrib++;
959 956
960 957 /*
961 958 * Comparing fmri authority information is a bit of a pain, because
962 959 * there may be a different number of members, and they can (but
963 960 * shouldn't be) in a different order. We need to create a copy of the
964 961 * authority and parse it into pieces. Because this function is
965 962 * intended to be fast (and not necessarily extensible), we hard-code
966 963 * the list of possible authority members in an enum and parse it into
967 964 * an array.
968 965 */
969 966 topo_fmri_strcmp_parse_auth(a + 5, autha, authlena);
970 967 topo_fmri_strcmp_parse_auth(b + 5, authb, authlenb);
971 968
972 969 for (i = 0; i < HC_AUTH_MAX; i++) {
973 970 if (noauth && i != HC_AUTH_CHASSIS)
974 971 continue;
975 972
976 973 if (authlena[i] == 0 && authlenb[i] == 0)
977 974 continue;
978 975
979 976 if (authlena[i] != authlenb[i])
980 977 return (B_FALSE);
981 978
982 979 if (strncmp(autha[i], authb[i], authlena[i]) != 0)
983 980 return (B_FALSE);
984 981 }
985 982
986 983 /*
987 984 * If this is rooted at a ses-enclosure node, skip past the instance
988 985 * number, as it has no meaning.
989 986 */
990 987 if (strncmp(fmria, SES_ENCLOSURE, sizeof (SES_ENCLOSURE) - 1) == 0 &&
991 988 strncmp(fmrib, SES_ENCLOSURE, sizeof (SES_ENCLOSURE) - 1) == 0) {
992 989 fmria += sizeof (SES_ENCLOSURE);
993 990 fmrib += sizeof (SES_ENCLOSURE);
994 991
995 992 while (isdigit(*fmria))
996 993 fmria++;
997 994 while (isdigit(*fmrib))
998 995 fmrib++;
999 996 }
1000 997
1001 998 return (strcmp(fmria, fmrib) == 0);
1002 999 }
1003 1000
1004 1001 /*ARGSUSED*/
1005 1002 boolean_t
1006 1003 topo_fmri_strcmp(topo_hdl_t *thp, const char *a, const char *b)
1007 1004 {
1008 1005 return (topo_fmri_strcmp_internal(thp, a, b, B_FALSE));
1009 1006 }
1010 1007
1011 1008 /*ARGSUSED*/
1012 1009 boolean_t
1013 1010 topo_fmri_strcmp_noauth(topo_hdl_t *thp, const char *a, const char *b)
1014 1011 {
1015 1012 return (topo_fmri_strcmp_internal(thp, a, b, B_TRUE));
1016 1013 }
1017 1014
1018 1015 int
1019 1016 topo_fmri_facility(topo_hdl_t *thp, nvlist_t *rsrc, const char *fac_type,
1020 1017 uint32_t fac_subtype, topo_walk_cb_t cb, void *cb_args, int *err)
1021 1018 {
1022 1019 int rv;
1023 1020 nvlist_t *in = NULL, *out;
1024 1021 tnode_t *rnode;
1025 1022 char *scheme;
1026 1023
1027 1024 if (nvlist_lookup_string(rsrc, FM_FMRI_SCHEME, &scheme) != 0)
1028 1025 return (set_error(thp, ETOPO_FMRI_MALFORM, err,
1029 1026 TOPO_METH_PROP_GET, in));
1030 1027
1031 1028 if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
1032 1029 return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
1033 1030 TOPO_METH_PROP_GET, in));
1034 1031
1035 1032 if (topo_hdl_nvalloc(thp, &in, NV_UNIQUE_NAME) != 0)
1036 1033 return (set_error(thp, ETOPO_FMRI_NVL, err,
1037 1034 TOPO_METH_PROP_GET, in));
1038 1035
1039 1036 rv = nvlist_add_nvlist(in, TOPO_PROP_RESOURCE, rsrc);
1040 1037 rv |= nvlist_add_string(in, FM_FMRI_FACILITY_TYPE, fac_type);
1041 1038 rv |= nvlist_add_uint32(in, "type", fac_subtype);
1042 1039 #ifdef _LP64
1043 1040 rv |= nvlist_add_uint64(in, "callback", (uint64_t)cb);
1044 1041 rv |= nvlist_add_uint64(in, "callback-args", (uint64_t)cb_args);
1045 1042 #else
1046 1043 rv |= nvlist_add_uint32(in, "callback", (uint32_t)cb);
1047 1044 rv |= nvlist_add_uint32(in, "callback-args", (uint32_t)cb_args);
1048 1045 #endif
1049 1046 if (rv != 0)
1050 1047 return (set_error(thp, ETOPO_FMRI_NVL, err,
1051 1048 TOPO_METH_PROP_GET, in));
1052 1049
1053 1050 rv = topo_method_invoke(rnode, TOPO_METH_FACILITY,
1054 1051 TOPO_METH_FACILITY_VERSION, in, &out, err);
1055 1052
1056 1053 nvlist_free(in);
1057 1054
1058 1055 if (rv != 0)
1059 1056 return (-1); /* *err is set for us */
1060 1057
1061 1058 return (0);
1062 1059 }
↓ open down ↓ |
455 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX