1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <strings.h> 29 #include <assert.h> 30 #include <fm/libtopo.h> 31 #include <topo_prop.h> 32 #include <topo_string.h> 33 #include <topo_alloc.h> 34 #include <topo_error.h> 35 36 static topo_pgroup_t * 37 pgroup_get(tnode_t *node, const char *pgname) 38 { 39 topo_pgroup_t *pg; 40 /* 41 * Check for an existing pgroup 42 */ 43 for (pg = topo_list_next(&node->tn_pgroups); pg != NULL; 44 pg = topo_list_next(pg)) { 45 if (strcmp(pg->tpg_info->tpi_name, pgname) == 0) { 46 return (pg); 47 } 48 } 49 50 return (NULL); 51 } 52 53 static topo_propval_t * 54 propval_get(topo_pgroup_t *pg, const char *pname) 55 { 56 topo_proplist_t *pvl; 57 58 for (pvl = topo_list_next(&pg->tpg_pvals); pvl != NULL; 59 pvl = topo_list_next(pvl)) { 60 if (strcmp(pvl->tp_pval->tp_name, pname) == 0) 61 return (pvl->tp_pval); 62 } 63 64 return (NULL); 65 } 66 67 static topo_propval_t * 68 topo_prop_get(tnode_t *node, const char *pgname, const char *pname, int *err) 69 { 70 topo_pgroup_t *pg = NULL; 71 topo_propval_t *pv = NULL; 72 73 if ((pg = pgroup_get(node, pgname)) == NULL) { 74 *err = ETOPO_PROP_NOENT; 75 return (NULL); 76 } 77 78 if ((pv = propval_get(pg, pname)) == NULL) { 79 *err = ETOPO_PROP_NOENT; 80 return (NULL); 81 } 82 83 return (pv); 84 } 85 86 static int 87 prop_val_add(nvlist_t *nvl, topo_propval_t *pv, int *err) 88 { 89 int ret = 0; 90 uint_t nelems; 91 92 if (nvlist_add_int32(nvl, TOPO_PROP_VAL_TYPE, pv->tp_type) != 0) 93 return (-1); 94 95 switch (pv->tp_type) { 96 case TOPO_TYPE_INT32: 97 { 98 int32_t val; 99 if ((ret = nvlist_lookup_int32(pv->tp_val, 100 TOPO_PROP_VAL_VAL, &val)) < 0) 101 break; 102 ret = nvlist_add_int32(nvl, TOPO_PROP_VAL_VAL, val); 103 } 104 break; 105 case TOPO_TYPE_UINT32: 106 { 107 uint32_t val; 108 if ((ret = nvlist_lookup_uint32(pv->tp_val, 109 TOPO_PROP_VAL_VAL, &val)) < 0) 110 break; 111 ret = nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, val); 112 } 113 break; 114 case TOPO_TYPE_INT64: 115 { 116 int64_t val; 117 if ((ret = nvlist_lookup_int64(pv->tp_val, 118 TOPO_PROP_VAL_VAL, &val)) < 0) 119 break; 120 ret = nvlist_add_int64(nvl, TOPO_PROP_VAL_VAL, val); 121 } 122 break; 123 case TOPO_TYPE_UINT64: 124 { 125 uint64_t val; 126 if ((ret = nvlist_lookup_uint64(pv->tp_val, 127 TOPO_PROP_VAL_VAL, &val)) < 0) 128 break; 129 ret = nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL, val); 130 } 131 break; 132 case TOPO_TYPE_STRING: 133 { 134 char *val; 135 if ((ret = nvlist_lookup_string(pv->tp_val, 136 TOPO_PROP_VAL_VAL, &val)) < 0) 137 break; 138 ret = nvlist_add_string(nvl, TOPO_PROP_VAL_VAL, val); 139 } 140 break; 141 case TOPO_TYPE_FMRI: 142 { 143 nvlist_t *val; 144 if ((ret = nvlist_lookup_nvlist(pv->tp_val, 145 TOPO_PROP_VAL_VAL, &val)) < 0) 146 break; 147 ret = nvlist_add_nvlist(nvl, TOPO_PROP_VAL_VAL, val); 148 } 149 break; 150 case TOPO_TYPE_INT32_ARRAY: 151 { 152 int32_t *val; 153 if ((ret = nvlist_lookup_int32_array(pv->tp_val, 154 TOPO_PROP_VAL_VAL, &val, &nelems)) < 0) 155 break; 156 ret = nvlist_add_int32_array(nvl, TOPO_PROP_VAL_VAL, 157 val, nelems); 158 } 159 break; 160 case TOPO_TYPE_UINT32_ARRAY: 161 { 162 uint32_t *val; 163 if ((ret = nvlist_lookup_uint32_array(pv->tp_val, 164 TOPO_PROP_VAL_VAL, &val, &nelems)) < 0) 165 break; 166 ret = nvlist_add_uint32_array(nvl, TOPO_PROP_VAL_VAL, 167 val, nelems); 168 } 169 break; 170 case TOPO_TYPE_INT64_ARRAY: 171 { 172 int64_t *val; 173 if ((ret = nvlist_lookup_int64_array(pv->tp_val, 174 TOPO_PROP_VAL_VAL, &val, &nelems)) < 0) 175 break; 176 ret = nvlist_add_int64_array(nvl, TOPO_PROP_VAL_VAL, 177 val, nelems); 178 } 179 break; 180 case TOPO_TYPE_UINT64_ARRAY: 181 { 182 uint64_t *val; 183 if ((ret = nvlist_lookup_uint64_array(pv->tp_val, 184 TOPO_PROP_VAL_VAL, &val, &nelems)) < 0) 185 break; 186 ret = nvlist_add_uint64_array(nvl, TOPO_PROP_VAL_VAL, 187 val, nelems); 188 } 189 break; 190 case TOPO_TYPE_STRING_ARRAY: 191 { 192 char **val; 193 if ((ret = nvlist_lookup_string_array(pv->tp_val, 194 TOPO_PROP_VAL_VAL, &val, &nelems)) < 0) 195 break; 196 ret = nvlist_add_string_array(nvl, TOPO_PROP_VAL_VAL, 197 val, nelems); 198 } 199 break; 200 case TOPO_TYPE_FMRI_ARRAY: 201 { 202 nvlist_t **val; 203 if ((ret = nvlist_lookup_nvlist_array(pv->tp_val, 204 TOPO_PROP_VAL_VAL, &val, &nelems)) < 0) 205 break; 206 ret = nvlist_add_nvlist_array(nvl, TOPO_PROP_VAL_VAL, 207 val, nelems); 208 } 209 break; 210 default: 211 ret = ETOPO_PROP_TYPE; 212 } 213 214 if (ret != 0) { 215 if (ret == ENOMEM) 216 *err = ETOPO_NOMEM; 217 else 218 *err = ETOPO_PROP_NVL; 219 return (-1); 220 } 221 222 return (0); 223 } 224 225 nvlist_t * 226 get_all_seterror(tnode_t *node, nvlist_t *nvl, int *errp, int err) 227 { 228 topo_node_unlock(node); 229 230 if (nvl != NULL) 231 nvlist_free(nvl); 232 233 *errp = err; 234 235 return (NULL); 236 } 237 238 nvlist_t * 239 topo_prop_getprops(tnode_t *node, int *err) 240 { 241 int ret; 242 topo_hdl_t *thp = node->tn_hdl; 243 nvlist_t *nvl, *pgnvl, *pvnvl; 244 topo_pgroup_t *pg; 245 topo_propval_t *pv; 246 topo_proplist_t *pvl; 247 248 if (topo_hdl_nvalloc(thp, &nvl, 0) != 0) { 249 return (get_all_seterror(node, NULL, err, ETOPO_NOMEM)); 250 } 251 252 topo_node_lock(node); 253 for (pg = topo_list_next(&node->tn_pgroups); pg != NULL; 254 pg = topo_list_next(pg)) { 255 if (topo_hdl_nvalloc(thp, &pgnvl, 0) != 0) 256 return (get_all_seterror(node, nvl, err, ETOPO_NOMEM)); 257 258 if (nvlist_add_string(pgnvl, TOPO_PROP_GROUP_NAME, 259 pg->tpg_info->tpi_name) != 0 || 260 nvlist_add_string(pgnvl, TOPO_PROP_GROUP_NSTAB, 261 topo_stability2name(pg->tpg_info->tpi_namestab)) != 0 || 262 nvlist_add_string(pgnvl, TOPO_PROP_GROUP_DSTAB, 263 topo_stability2name(pg->tpg_info->tpi_datastab)) != 0 || 264 nvlist_add_int32(pgnvl, TOPO_PROP_GROUP_VERSION, 265 pg->tpg_info->tpi_version) != 0) 266 return (get_all_seterror(node, nvl, err, 267 ETOPO_PROP_NVL)); 268 269 for (pvl = topo_list_next(&pg->tpg_pvals); pvl != NULL; 270 pvl = topo_list_next(pvl)) { 271 272 pv = pvl->tp_pval; 273 if (topo_hdl_nvalloc(thp, &pvnvl, 0) 274 != 0) { 275 nvlist_free(pgnvl); 276 return (get_all_seterror(node, nvl, err, 277 ETOPO_NOMEM)); 278 } 279 if ((ret = nvlist_add_string(pvnvl, TOPO_PROP_VAL_NAME, 280 pv->tp_name)) != 0) { 281 nvlist_free(pgnvl); 282 nvlist_free(pvnvl); 283 return (get_all_seterror(node, nvl, err, ret)); 284 } 285 if (prop_val_add(pvnvl, pv, err) < 0) { 286 nvlist_free(pgnvl); 287 nvlist_free(pvnvl); 288 return (get_all_seterror(node, nvl, err, ret)); 289 } 290 if ((ret = nvlist_add_nvlist(pgnvl, TOPO_PROP_VAL, 291 pvnvl)) != 0) { 292 nvlist_free(pgnvl); 293 nvlist_free(pvnvl); 294 return (get_all_seterror(node, nvl, err, ret)); 295 } 296 297 nvlist_free(pvnvl); 298 } 299 if ((ret = nvlist_add_nvlist(nvl, TOPO_PROP_GROUP, pgnvl)) 300 != 0) { 301 nvlist_free(pgnvl); 302 return (get_all_seterror(node, nvl, err, ret)); 303 } 304 305 nvlist_free(pgnvl); 306 } 307 308 topo_node_unlock(node); 309 310 return (nvl); 311 } 312 313 static int 314 get_seterror(tnode_t *node, int *errp, int err) 315 { 316 topo_node_unlock(node); 317 *errp = err; 318 return (-1); 319 } 320 321 static int 322 prop_getval(tnode_t *node, const char *pgname, const char *pname, void *val, 323 topo_type_t type, uint_t *nelems, int *err) 324 { 325 int i, j, ret = 0; 326 topo_hdl_t *thp = node->tn_hdl; 327 topo_propval_t *pv; 328 329 topo_node_lock(node); 330 if ((pv = topo_prop_get(node, pgname, pname, err)) 331 == NULL) 332 return (get_seterror(node, err, *err)); 333 334 if (pv->tp_type != type) 335 return (get_seterror(node, err, ETOPO_PROP_TYPE)); 336 337 switch (type) { 338 case TOPO_TYPE_INT32: 339 ret = nvlist_lookup_int32(pv->tp_val, TOPO_PROP_VAL_VAL, 340 (int32_t *)val); 341 break; 342 case TOPO_TYPE_UINT32: 343 ret = nvlist_lookup_uint32(pv->tp_val, 344 TOPO_PROP_VAL_VAL, (uint32_t *)val); 345 break; 346 case TOPO_TYPE_INT64: 347 ret = nvlist_lookup_int64(pv->tp_val, TOPO_PROP_VAL_VAL, 348 (int64_t *)val); 349 break; 350 case TOPO_TYPE_UINT64: 351 ret = nvlist_lookup_uint64(pv->tp_val, 352 TOPO_PROP_VAL_VAL, (uint64_t *)val); 353 break; 354 case TOPO_TYPE_STRING: { 355 char *str; 356 357 ret = nvlist_lookup_string(pv->tp_val, 358 TOPO_PROP_VAL_VAL, &str); 359 if (ret == 0) 360 *(char **)val = topo_hdl_strdup(thp, str); 361 break; 362 } 363 case TOPO_TYPE_FMRI: { 364 nvlist_t *nvl; 365 366 ret = nvlist_lookup_nvlist(pv->tp_val, 367 TOPO_PROP_VAL_VAL, &nvl); 368 if (ret == 0) 369 ret = topo_hdl_nvdup(thp, nvl, 370 (nvlist_t **)val); 371 break; 372 } 373 case TOPO_TYPE_INT32_ARRAY: { 374 int32_t *a1, *a2; 375 376 if ((ret = nvlist_lookup_int32_array(pv->tp_val, 377 TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) 378 break; 379 if ((a1 = topo_hdl_alloc(thp, sizeof (int32_t) * 380 *nelems)) == NULL) { 381 ret = ETOPO_NOMEM; 382 break; 383 } 384 for (i = 0; i < *nelems; ++i) 385 a1[i] = a2[i]; 386 *(int32_t **)val = a1; 387 break; 388 } 389 case TOPO_TYPE_UINT32_ARRAY: { 390 uint32_t *a1, *a2; 391 392 if ((ret = nvlist_lookup_uint32_array(pv->tp_val, 393 TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) 394 break; 395 if ((a1 = topo_hdl_alloc(thp, sizeof (uint32_t) * 396 *nelems)) == NULL) { 397 ret = ETOPO_NOMEM; 398 break; 399 } 400 for (i = 0; i < *nelems; ++i) 401 a1[i] = a2[i]; 402 *(uint32_t **)val = a1; 403 break; 404 } 405 case TOPO_TYPE_INT64_ARRAY: { 406 int64_t *a1, *a2; 407 408 if ((ret = nvlist_lookup_int64_array(pv->tp_val, 409 TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) 410 break; 411 if ((a1 = topo_hdl_alloc(thp, sizeof (int64_t) * 412 *nelems)) == NULL) { 413 ret = ETOPO_NOMEM; 414 break; 415 } 416 for (i = 0; i < *nelems; ++i) 417 a1[i] = a2[i]; 418 *(int64_t **)val = a1; 419 break; 420 } 421 case TOPO_TYPE_UINT64_ARRAY: { 422 uint64_t *a1, *a2; 423 424 if ((ret = nvlist_lookup_uint64_array(pv->tp_val, 425 TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) 426 break; 427 if ((a1 = topo_hdl_alloc(thp, sizeof (uint64_t) * 428 *nelems)) == NULL) { 429 ret = ETOPO_NOMEM; 430 break; 431 } 432 for (i = 0; i < *nelems; ++i) 433 a1[i] = a2[i]; 434 *(uint64_t **)val = a1; 435 break; 436 } 437 case TOPO_TYPE_STRING_ARRAY: { 438 char **a1, **a2; 439 440 if ((ret = nvlist_lookup_string_array(pv->tp_val, 441 TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) 442 break; 443 if ((a1 = topo_hdl_alloc(thp, sizeof (char *) * 444 *nelems)) == NULL) { 445 ret = ETOPO_NOMEM; 446 break; 447 } 448 for (i = 0; i < *nelems; ++i) { 449 if ((a1[i] = topo_hdl_strdup(thp, a2[i])) 450 == NULL) { 451 for (j = 0; j < i; ++j) 452 topo_hdl_free(thp, a1[j], 453 sizeof (char *)); 454 topo_hdl_free(thp, a1, 455 sizeof (char *) * *nelems); 456 break; 457 } 458 } 459 *(char ***)val = a1; 460 break; 461 } 462 case TOPO_TYPE_FMRI_ARRAY: { 463 nvlist_t **a1, **a2; 464 465 if ((ret = nvlist_lookup_nvlist_array(pv->tp_val, 466 TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) 467 break; 468 if ((a1 = topo_hdl_alloc(thp, sizeof (nvlist_t *) * 469 *nelems)) == NULL) { 470 ret = ETOPO_NOMEM; 471 break; 472 } 473 for (i = 0; i < *nelems; ++i) { 474 if (topo_hdl_nvdup(thp, a2[i], &a1[i]) < 0) { 475 for (j = 0; j < i; ++j) 476 nvlist_free(a1[j]); 477 topo_hdl_free(thp, a1, 478 sizeof (nvlist_t *) * *nelems); 479 break; 480 } 481 } 482 *(nvlist_t ***)val = a1; 483 break; 484 } 485 default: 486 ret = ETOPO_PROP_NOENT; 487 } 488 489 if (ret != 0) 490 if (ret == ENOENT) 491 return (get_seterror(node, err, ETOPO_PROP_NOENT)); 492 else if (ret < ETOPO_UNKNOWN) 493 return (get_seterror(node, err, ETOPO_PROP_NVL)); 494 else 495 return (get_seterror(node, err, ret)); 496 497 topo_node_unlock(node); 498 return (0); 499 } 500 501 int 502 topo_prop_get_int32(tnode_t *node, const char *pgname, const char *pname, 503 int32_t *val, int *err) 504 { 505 return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_INT32, 506 NULL, err)); 507 } 508 509 int 510 topo_prop_get_uint32(tnode_t *node, const char *pgname, const char *pname, 511 uint32_t *val, int *err) 512 { 513 return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_UINT32, 514 NULL, err)); 515 } 516 517 int 518 topo_prop_get_int64(tnode_t *node, const char *pgname, const char *pname, 519 int64_t *val, int *err) 520 { 521 return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_INT64, 522 NULL, err)); 523 } 524 525 int 526 topo_prop_get_uint64(tnode_t *node, const char *pgname, const char *pname, 527 uint64_t *val, int *err) 528 { 529 return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_UINT64, 530 NULL, err)); 531 } 532 533 int 534 topo_prop_get_string(tnode_t *node, const char *pgname, const char *pname, 535 char **val, int *err) 536 { 537 return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_STRING, 538 NULL, err)); 539 } 540 541 int 542 topo_prop_get_fmri(tnode_t *node, const char *pgname, const char *pname, 543 nvlist_t **val, int *err) 544 { 545 return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_FMRI, 546 NULL, err)); 547 } 548 549 int 550 topo_prop_get_int32_array(tnode_t *node, const char *pgname, const char *pname, 551 int32_t **val, uint_t *nelem, int *err) 552 { 553 return (prop_getval(node, pgname, pname, (void *)val, 554 TOPO_TYPE_INT32_ARRAY, nelem, err)); 555 } 556 557 int 558 topo_prop_get_uint32_array(tnode_t *node, const char *pgname, const char *pname, 559 uint32_t **val, uint_t *nelem, int *err) 560 { 561 return (prop_getval(node, pgname, pname, (void *)val, 562 TOPO_TYPE_UINT32_ARRAY, nelem, err)); 563 } 564 565 int 566 topo_prop_get_int64_array(tnode_t *node, const char *pgname, const char *pname, 567 int64_t **val, uint_t *nelem, int *err) 568 { 569 return (prop_getval(node, pgname, pname, (void *)val, 570 TOPO_TYPE_INT64_ARRAY, nelem, err)); 571 } 572 573 int 574 topo_prop_get_uint64_array(tnode_t *node, const char *pgname, const char *pname, 575 uint64_t **val, uint_t *nelem, int *err) 576 { 577 return (prop_getval(node, pgname, pname, (void *)val, 578 TOPO_TYPE_UINT64_ARRAY, nelem, err)); 579 } 580 581 int 582 topo_prop_get_string_array(tnode_t *node, const char *pgname, const char *pname, 583 char ***val, uint_t *nelem, int *err) 584 { 585 return (prop_getval(node, pgname, pname, (void *)val, 586 TOPO_TYPE_STRING_ARRAY, nelem, err)); 587 } 588 589 int 590 topo_prop_get_fmri_array(tnode_t *node, const char *pgname, const char *pname, 591 nvlist_t ***val, uint_t *nelem, int *err) 592 { 593 return (prop_getval(node, pgname, pname, (void *)val, 594 TOPO_TYPE_FMRI_ARRAY, nelem, err)); 595 } 596 597 static int 598 set_seterror(tnode_t *node, topo_proplist_t *pvl, int *errp, int err) 599 { 600 topo_hdl_t *thp = node->tn_hdl; 601 topo_propval_t *pv; 602 603 if (pvl != NULL) { 604 pv = pvl->tp_pval; 605 if (pv != NULL) { 606 if (pv->tp_name != NULL) 607 topo_hdl_strfree(thp, pv->tp_name); 608 if (pv->tp_val != NULL) 609 nvlist_free(pv->tp_val); 610 topo_hdl_free(thp, pv, sizeof (topo_propval_t)); 611 } 612 topo_hdl_free(thp, pvl, sizeof (topo_proplist_t)); 613 } 614 615 topo_node_unlock(node); 616 *errp = err; 617 618 return (-1); 619 } 620 621 static int 622 topo_prop_set(tnode_t *node, const char *pgname, const char *pname, 623 topo_type_t type, int flag, void *val, int nelems, int *err) 624 { 625 int ret, new_prop = 0; 626 topo_hdl_t *thp = node->tn_hdl; 627 topo_pgroup_t *pg; 628 topo_propval_t *pv; 629 topo_proplist_t *pvl; 630 631 topo_node_lock(node); 632 if ((pg = pgroup_get(node, pgname)) == NULL) 633 return (set_seterror(node, NULL, err, ETOPO_PROP_NOENT)); 634 635 /* 636 * Replace existing prop value with new one 637 */ 638 if ((pv = propval_get(pg, pname)) != NULL) { 639 if (pv->tp_type != type) 640 return (set_seterror(node, NULL, err, ETOPO_PROP_TYPE)); 641 else if (pv->tp_flag == TOPO_PROP_IMMUTABLE) 642 return (set_seterror(node, NULL, err, ETOPO_PROP_DEFD)); 643 nvlist_free(pv->tp_val); 644 pv->tp_val = NULL; 645 } else { 646 /* 647 * Property values may be a shared resources among 648 * different nodes. We will allocate resources 649 * on a per-handle basis. 650 */ 651 if ((pvl = topo_hdl_zalloc(thp, sizeof (topo_proplist_t))) 652 == NULL) 653 return (set_seterror(node, NULL, err, ETOPO_NOMEM)); 654 655 if ((pv = topo_hdl_zalloc(thp, sizeof (topo_propval_t))) 656 == NULL) 657 return (set_seterror(node, pvl, err, ETOPO_NOMEM)); 658 pvl->tp_pval = pv; 659 660 if ((pv->tp_name = topo_hdl_strdup(thp, pname)) 661 == NULL) 662 return (set_seterror(node, pvl, err, ETOPO_NOMEM)); 663 pv->tp_flag = flag; 664 pv->tp_type = type; 665 pv->tp_hdl = thp; 666 topo_prop_hold(pv); 667 new_prop++; 668 } 669 670 if (topo_hdl_nvalloc(thp, &pv->tp_val, NV_UNIQUE_NAME) < 0) 671 return (set_seterror(node, pvl, err, ETOPO_PROP_NVL)); 672 673 ret = 0; 674 switch (type) { 675 case TOPO_TYPE_INT32: 676 ret = nvlist_add_int32(pv->tp_val, TOPO_PROP_VAL_VAL, 677 *(int32_t *)val); 678 break; 679 case TOPO_TYPE_UINT32: 680 ret = nvlist_add_uint32(pv->tp_val, TOPO_PROP_VAL_VAL, 681 *(uint32_t *)val); 682 break; 683 case TOPO_TYPE_INT64: 684 ret = nvlist_add_int64(pv->tp_val, TOPO_PROP_VAL_VAL, 685 *(int64_t *)val); 686 break; 687 case TOPO_TYPE_UINT64: 688 ret = nvlist_add_uint64(pv->tp_val, TOPO_PROP_VAL_VAL, 689 *(uint64_t *)val); 690 break; 691 case TOPO_TYPE_STRING: 692 ret = nvlist_add_string(pv->tp_val, TOPO_PROP_VAL_VAL, 693 (char *)val); 694 break; 695 case TOPO_TYPE_FMRI: 696 ret = nvlist_add_nvlist(pv->tp_val, TOPO_PROP_VAL_VAL, 697 (nvlist_t *)val); 698 break; 699 case TOPO_TYPE_INT32_ARRAY: 700 ret = nvlist_add_int32_array(pv->tp_val, 701 TOPO_PROP_VAL_VAL, (int32_t *)val, nelems); 702 break; 703 case TOPO_TYPE_UINT32_ARRAY: 704 ret = nvlist_add_uint32_array(pv->tp_val, 705 TOPO_PROP_VAL_VAL, (uint32_t *)val, nelems); 706 break; 707 case TOPO_TYPE_INT64_ARRAY: 708 ret = nvlist_add_int64_array(pv->tp_val, 709 TOPO_PROP_VAL_VAL, (int64_t *)val, nelems); 710 break; 711 case TOPO_TYPE_UINT64_ARRAY: 712 ret = nvlist_add_uint64_array(pv->tp_val, 713 TOPO_PROP_VAL_VAL, (uint64_t *)val, nelems); 714 break; 715 case TOPO_TYPE_STRING_ARRAY: 716 ret = nvlist_add_string_array(pv->tp_val, 717 TOPO_PROP_VAL_VAL, (char **)val, nelems); 718 break; 719 case TOPO_TYPE_FMRI_ARRAY: 720 ret = nvlist_add_nvlist_array(pv->tp_val, 721 TOPO_PROP_VAL_VAL, (nvlist_t **)val, nelems); 722 break; 723 default: 724 return (set_seterror(node, pvl, err, ETOPO_PROP_TYPE)); 725 } 726 727 if (ret != 0) { 728 if (ret == ENOMEM) 729 return (set_seterror(node, pvl, err, ETOPO_NOMEM)); 730 else 731 return (set_seterror(node, pvl, err, ETOPO_PROP_NVL)); 732 } 733 734 if (new_prop > 0) 735 topo_list_append(&pg->tpg_pvals, pvl); 736 737 topo_node_unlock(node); 738 739 return (0); 740 } 741 742 int 743 topo_prop_set_int32(tnode_t *node, const char *pgname, const char *pname, 744 int flag, int32_t val, int *err) 745 { 746 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_INT32, flag, 747 &val, 1, err)); 748 } 749 750 int 751 topo_prop_set_uint32(tnode_t *node, const char *pgname, const char *pname, 752 int flag, uint32_t val, int *err) 753 { 754 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_UINT32, flag, 755 &val, 1, err)); 756 } 757 758 int 759 topo_prop_set_int64(tnode_t *node, const char *pgname, const char *pname, 760 int flag, int64_t val, int *err) 761 { 762 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_INT64, flag, 763 &val, 1, err)); 764 } 765 766 int 767 topo_prop_set_uint64(tnode_t *node, const char *pgname, const char *pname, 768 int flag, uint64_t val, int *err) 769 { 770 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_UINT64, flag, 771 &val, 1, err)); 772 } 773 774 int 775 topo_prop_set_string(tnode_t *node, const char *pgname, const char *pname, 776 int flag, const char *val, int *err) 777 { 778 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_STRING, flag, 779 (void *)val, 1, err)); 780 } 781 782 int 783 topo_prop_set_fmri(tnode_t *node, const char *pgname, const char *pname, 784 int flag, const nvlist_t *fmri, int *err) 785 { 786 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_FMRI, flag, 787 (void *)fmri, 1, err)); 788 } 789 790 int 791 topo_prop_set_int32_array(tnode_t *node, const char *pgname, const char *pname, 792 int flag, int32_t *val, uint_t nelems, int *err) 793 { 794 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_INT32_ARRAY, flag, 795 val, nelems, err)); 796 } 797 798 int 799 topo_prop_set_uint32_array(tnode_t *node, const char *pgname, const char *pname, 800 int flag, uint32_t *val, uint_t nelems, int *err) 801 { 802 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_UINT32_ARRAY, flag, 803 val, nelems, err)); 804 } 805 806 int 807 topo_prop_set_int64_array(tnode_t *node, const char *pgname, const char *pname, 808 int flag, int64_t *val, uint_t nelems, int *err) 809 { 810 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_INT64_ARRAY, flag, 811 val, nelems, err)); 812 } 813 814 int 815 topo_prop_set_uint64_array(tnode_t *node, const char *pgname, const char *pname, 816 int flag, uint64_t *val, uint_t nelems, int *err) 817 { 818 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_UINT64_ARRAY, flag, 819 val, nelems, err)); 820 } 821 822 int 823 topo_prop_set_string_array(tnode_t *node, const char *pgname, const char *pname, 824 int flag, const char **val, uint_t nelems, int *err) 825 { 826 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_STRING_ARRAY, flag, 827 (void *)val, nelems, err)); 828 } 829 830 int 831 topo_prop_set_fmri_array(tnode_t *node, const char *pgname, const char *pname, 832 int flag, const nvlist_t **fmri, uint_t nelems, int *err) 833 { 834 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_FMRI_ARRAY, flag, 835 (void *)fmri, nelems, err)); 836 } 837 838 static int 839 inherit_seterror(tnode_t *node, int *errp, int err) 840 { 841 topo_node_unlock(node); 842 topo_node_unlock(node->tn_parent); 843 844 *errp = err; 845 846 return (-1); 847 } 848 849 int 850 topo_prop_inherit(tnode_t *node, const char *pgname, const char *name, int *err) 851 { 852 topo_hdl_t *thp = node->tn_hdl; 853 tnode_t *pnode = node->tn_parent; 854 topo_pgroup_t *pg; 855 topo_propval_t *pv; 856 topo_proplist_t *pvl; 857 858 topo_node_lock(pnode); 859 topo_node_lock(node); 860 /* 861 * Check for an existing property group and prop val 862 */ 863 if ((pg = pgroup_get(pnode, pgname)) == NULL) 864 return (inherit_seterror(node, err, ETOPO_PROP_NOENT)); 865 866 if ((pv = propval_get(pg, name)) == NULL) 867 return (inherit_seterror(node, err, ETOPO_PROP_NOENT)); 868 869 /* 870 * Can this propval be inherited? 871 */ 872 if (pv->tp_flag != TOPO_PROP_IMMUTABLE) 873 return (inherit_seterror(node, err, ETOPO_PROP_NOINHERIT)); 874 875 /* 876 * Property group should already exist: bump the ref count for this 877 * propval and add it to the node's property group 878 */ 879 if ((pg = pgroup_get(node, pgname)) == NULL) 880 return (inherit_seterror(node, err, ETOPO_PROP_NOENT)); 881 882 if ((pvl = topo_hdl_zalloc(thp, sizeof (topo_proplist_t))) 883 == NULL) 884 return (inherit_seterror(node, err, ETOPO_NOMEM)); 885 886 topo_prop_hold(pv); 887 pvl->tp_pval = pv; 888 topo_list_append(&pg->tpg_pvals, pvl); 889 890 topo_node_unlock(node); 891 topo_node_unlock(pnode); 892 893 return (0); 894 } 895 896 topo_pgroup_info_t * 897 topo_pgroup_info(tnode_t *node, const char *pgname, int *err) 898 { 899 topo_hdl_t *thp = node->tn_hdl; 900 topo_pgroup_t *pg; 901 topo_ipgroup_info_t *pip; 902 topo_pgroup_info_t *info; 903 904 topo_node_lock(node); 905 for (pg = topo_list_next(&node->tn_pgroups); pg != NULL; 906 pg = topo_list_next(pg)) { 907 if (strcmp(pgname, pg->tpg_info->tpi_name) == 0) { 908 if ((info = topo_hdl_alloc(thp, 909 sizeof (topo_pgroup_info_t))) == NULL) 910 return (NULL); 911 912 pip = pg->tpg_info; 913 if ((info->tpi_name = 914 topo_hdl_strdup(thp, pip->tpi_name)) == NULL) { 915 *err = ETOPO_PROP_NOMEM; 916 topo_hdl_free(thp, info, 917 sizeof (topo_pgroup_info_t)); 918 topo_node_unlock(node); 919 return (NULL); 920 } 921 info->tpi_namestab = pip->tpi_namestab; 922 info->tpi_datastab = pip->tpi_datastab; 923 info->tpi_version = pip->tpi_version; 924 topo_node_unlock(node); 925 return (info); 926 } 927 } 928 929 *err = ETOPO_PROP_NOENT; 930 topo_node_unlock(node); 931 return (NULL); 932 } 933 934 static int 935 pgroup_seterr(tnode_t *node, topo_pgroup_t *pg, topo_ipgroup_info_t *pip, 936 int *err) 937 { 938 topo_hdl_t *thp = node->tn_hdl; 939 940 if (pip != NULL) { 941 if (pip->tpi_name != NULL) 942 topo_hdl_strfree(thp, (char *)pip->tpi_name); 943 topo_hdl_free(thp, pip, sizeof (topo_ipgroup_info_t)); 944 } 945 946 topo_hdl_free(thp, pg, sizeof (topo_pgroup_t)); 947 *err = ETOPO_NOMEM; 948 949 topo_node_unlock(node); 950 951 return (-1); 952 } 953 954 int 955 topo_pgroup_create(tnode_t *node, const topo_pgroup_info_t *pinfo, int *err) 956 { 957 topo_pgroup_t *pg; 958 topo_ipgroup_info_t *pip; 959 topo_hdl_t *thp = node->tn_hdl; 960 961 *err = 0; 962 963 topo_node_lock(node); 964 /* 965 * Check for an existing pgroup 966 */ 967 for (pg = topo_list_next(&node->tn_pgroups); pg != NULL; 968 pg = topo_list_next(pg)) { 969 if (strcmp(pg->tpg_info->tpi_name, pinfo->tpi_name) == 0) { 970 *err = ETOPO_PROP_DEFD; 971 topo_node_unlock(node); 972 return (-1); 973 } 974 } 975 976 if ((pg = topo_hdl_zalloc(thp, sizeof (topo_pgroup_t))) == NULL) { 977 *err = ETOPO_NOMEM; 978 topo_node_unlock(node); 979 return (-1); 980 } 981 982 if ((pip = topo_hdl_zalloc(thp, sizeof (topo_ipgroup_info_t))) 983 == NULL) 984 return (pgroup_seterr(node, pg, pip, err)); 985 986 if ((pip->tpi_name = topo_hdl_strdup(thp, pinfo->tpi_name)) 987 == NULL) 988 return (pgroup_seterr(node, pg, pip, err)); 989 990 pip->tpi_namestab = pinfo->tpi_namestab; 991 pip->tpi_datastab = pinfo->tpi_datastab; 992 pip->tpi_version = pinfo->tpi_version; 993 994 pg->tpg_info = pip; 995 996 topo_list_append(&node->tn_pgroups, pg); 997 topo_node_unlock(node); 998 999 return (0); 1000 } 1001 1002 void 1003 topo_pgroup_destroy(tnode_t *node, const char *pname) 1004 { 1005 topo_hdl_t *thp = node->tn_hdl; 1006 topo_pgroup_t *pg; 1007 topo_proplist_t *pvl; 1008 topo_ipgroup_info_t *pip; 1009 1010 topo_node_lock(node); 1011 for (pg = topo_list_next(&node->tn_pgroups); pg != NULL; 1012 pg = topo_list_next(pg)) { 1013 if (strcmp(pg->tpg_info->tpi_name, pname) == 0) { 1014 break; 1015 } 1016 } 1017 1018 if (pg == NULL) { 1019 topo_node_unlock(node); 1020 return; 1021 } 1022 1023 while ((pvl = topo_list_next(&pg->tpg_list)) != NULL) { 1024 topo_list_delete(&pg->tpg_pvals, pvl); 1025 topo_prop_rele(pvl->tp_pval); 1026 topo_hdl_free(thp, pvl, sizeof (topo_proplist_t)); 1027 } 1028 1029 topo_list_delete(&node->tn_pgroups, pg); 1030 topo_node_unlock(node); 1031 1032 pip = pg->tpg_info; 1033 if (pip != NULL) { 1034 if (pip->tpi_name != NULL) 1035 topo_hdl_strfree(thp, (char *)pip->tpi_name); 1036 topo_hdl_free(thp, pip, sizeof (topo_ipgroup_info_t)); 1037 } 1038 1039 topo_hdl_free(thp, pg, sizeof (topo_pgroup_t)); 1040 } 1041 1042 void 1043 topo_pgroup_destroy_all(tnode_t *node) 1044 { 1045 topo_hdl_t *thp = node->tn_hdl; 1046 topo_pgroup_t *pg; 1047 topo_proplist_t *pvl; 1048 topo_ipgroup_info_t *pip; 1049 1050 topo_node_lock(node); 1051 while ((pg = topo_list_next(&node->tn_pgroups)) != NULL) { 1052 while ((pvl = topo_list_next(&pg->tpg_pvals)) != NULL) { 1053 topo_list_delete(&pg->tpg_pvals, pvl); 1054 topo_prop_rele(pvl->tp_pval); 1055 topo_hdl_free(thp, pvl, sizeof (topo_proplist_t)); 1056 } 1057 1058 topo_list_delete(&node->tn_pgroups, pg); 1059 1060 pip = pg->tpg_info; 1061 if (pip != NULL) { 1062 if (pip->tpi_name != NULL) 1063 topo_hdl_strfree(thp, (char *)pip->tpi_name); 1064 topo_hdl_free(thp, pip, sizeof (topo_pgroup_info_t)); 1065 } 1066 1067 topo_hdl_free(thp, pg, sizeof (topo_pgroup_t)); 1068 } 1069 topo_node_unlock(node); 1070 } 1071 static void 1072 topo_propval_destroy(topo_propval_t *pv) 1073 { 1074 topo_hdl_t *thp = pv->tp_hdl; 1075 1076 if (pv->tp_name != NULL) 1077 topo_hdl_strfree(thp, pv->tp_name); 1078 1079 if (pv->tp_val != NULL) 1080 nvlist_free(pv->tp_val); 1081 1082 topo_hdl_free(thp, pv, sizeof (topo_propval_t)); 1083 } 1084 1085 void 1086 topo_prop_hold(topo_propval_t *pv) 1087 { 1088 pv->tp_refs++; 1089 } 1090 1091 void 1092 topo_prop_rele(topo_propval_t *pv) 1093 { 1094 pv->tp_refs--; 1095 1096 assert(pv->tp_refs >= 0); 1097 1098 if (pv->tp_refs == 0) 1099 topo_propval_destroy(pv); 1100 } 1101