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 /* 29 * Topology Plugin Modules 30 * 31 * Topology plugin modules are shared libraries that are dlopen'd and 32 * used to enumerate resources in the system. 33 * They are loaded by our builtin scheme-specific plugins or other modules 34 * to enumerate and create nodes for resources that are present in the system. 35 * They may also export a set of resource (node) specific methods that can be 36 * called on node-by-node basis. 37 * 38 * Module Plugin API 39 * 40 * Enumerators must provide entry points for intialization and clean-up 41 * (_topo_init() and _topo_fini()). In their _topo_init() function, an 42 * enumerator should register (topo_mod_register()) its enumeration callback 43 * and allocate resources required for a subsequent call to the callback. 44 * Optionally, methods may also be registered with topo_method_register(). 45 * 46 * In its enumeration callback routine, the module should search for resources 47 * within its realm of resposibility and create any node ranges, 48 * topo_node_range_create() or nodes, topo_node_bind(). The Enumerator 49 * module is handed a node to which it may begin attaching additional 50 * topology nodes. 51 * 52 * If additional helper modules need to be loaded to complete the enumeration 53 * the module may do so by calling topo_mod_load(). Enumeration may then 54 * continue with the module handing off enumeration to its helper module 55 * by calling topo_mod_enumerate(). 56 * 57 * If the module registers a release callback, it will be called on a node 58 * by node basis during topo_snap_rele(). Any private node data may be 59 * deallocated or methods unregistered at that time. Global module data 60 * should be clean-up before or at the time that the module _topo_fini 61 * entry point is called. 62 */ 63 64 #include <pthread.h> 65 #include <assert.h> 66 #include <errno.h> 67 #include <dirent.h> 68 #include <limits.h> 69 #include <alloca.h> 70 #include <unistd.h> 71 #include <stdio.h> 72 #include <sys/param.h> 73 #include <sys/utsname.h> 74 #include <sys/smbios.h> 75 #include <sys/fm/protocol.h> 76 77 #include <topo_alloc.h> 78 #include <topo_error.h> 79 #include <topo_file.h> 80 #include <topo_fmri.h> 81 #include <topo_module.h> 82 #include <topo_method.h> 83 #include <topo_string.h> 84 #include <topo_subr.h> 85 #include <topo_tree.h> 86 87 #define PLUGIN_PATH "plugins" 88 #define PLUGIN_PATH_LEN MAXNAMELEN + 5 89 90 topo_mod_t * 91 topo_mod_load(topo_mod_t *pmod, const char *name, 92 topo_version_t version) 93 { 94 char *path; 95 char file[PLUGIN_PATH_LEN]; 96 topo_mod_t *mod = NULL; 97 topo_hdl_t *thp; 98 99 thp = pmod->tm_hdl; 100 101 /* 102 * Already loaded, topo_mod_lookup will bump the ref count 103 */ 104 if ((mod = topo_mod_lookup(thp, name, 1)) != NULL) { 105 if (mod->tm_info->tmi_version != version) { 106 topo_mod_rele(mod); 107 (void) topo_mod_seterrno(pmod, ETOPO_MOD_VER); 108 return (NULL); 109 } 110 return (mod); 111 } 112 113 (void) snprintf(file, PLUGIN_PATH_LEN, "%s/%s.so", 114 PLUGIN_PATH, name); 115 path = topo_search_path(pmod, thp->th_rootdir, (const char *)file); 116 if (path == NULL || 117 (mod = topo_modhash_load(thp, name, path, &topo_rtld_ops, version)) 118 == NULL) { /* returned with mod held */ 119 topo_mod_strfree(pmod, path); 120 (void) topo_mod_seterrno(pmod, topo_hdl_errno(thp) ? 121 topo_hdl_errno(thp) : ETOPO_MOD_NOENT); 122 return (NULL); 123 } 124 125 topo_mod_strfree(pmod, path); 126 127 return (mod); 128 } 129 130 void 131 topo_mod_unload(topo_mod_t *mod) 132 { 133 topo_mod_rele(mod); 134 } 135 136 static int 137 set_register_error(topo_mod_t *mod, int err) 138 { 139 if (mod->tm_info != NULL) 140 topo_mod_unregister(mod); 141 142 topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR, 143 "module registration failed for %s: %s\n", 144 mod->tm_name, topo_strerror(err)); 145 146 return (topo_mod_seterrno(mod, err)); 147 } 148 149 int 150 topo_mod_register(topo_mod_t *mod, const topo_modinfo_t *mip, 151 topo_version_t version) 152 { 153 154 assert(!(mod->tm_flags & TOPO_MOD_FINI || 155 mod->tm_flags & TOPO_MOD_REG)); 156 157 if (version != TOPO_VERSION) 158 return (set_register_error(mod, EMOD_VER_ABI)); 159 160 if ((mod->tm_info = topo_mod_alloc(mod, sizeof (topo_imodinfo_t))) 161 == NULL) 162 return (set_register_error(mod, EMOD_NOMEM)); 163 if ((mod->tm_info->tmi_ops = topo_mod_alloc(mod, 164 sizeof (topo_modops_t))) == NULL) 165 return (set_register_error(mod, EMOD_NOMEM)); 166 167 mod->tm_info->tmi_desc = topo_mod_strdup(mod, mip->tmi_desc); 168 if (mod->tm_info->tmi_desc == NULL) 169 return (set_register_error(mod, EMOD_NOMEM)); 170 171 mod->tm_info->tmi_scheme = topo_mod_strdup(mod, mip->tmi_scheme); 172 if (mod->tm_info->tmi_scheme == NULL) 173 return (set_register_error(mod, EMOD_NOMEM)); 174 175 176 mod->tm_info->tmi_version = (topo_version_t)mip->tmi_version; 177 mod->tm_info->tmi_ops->tmo_enum = mip->tmi_ops->tmo_enum; 178 mod->tm_info->tmi_ops->tmo_release = mip->tmi_ops->tmo_release; 179 180 mod->tm_flags |= TOPO_MOD_REG; 181 182 topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC, 183 "registration succeeded for %s\n", mod->tm_name); 184 185 return (0); 186 } 187 188 void 189 topo_mod_unregister(topo_mod_t *mod) 190 { 191 if (mod->tm_info == NULL) 192 return; 193 194 assert(!(mod->tm_flags & TOPO_MOD_FINI)); 195 196 mod->tm_flags &= ~TOPO_MOD_REG; 197 198 if (mod->tm_info == NULL) 199 return; 200 201 if (mod->tm_info->tmi_ops != NULL) 202 topo_mod_free(mod, mod->tm_info->tmi_ops, 203 sizeof (topo_modops_t)); 204 if (mod->tm_info->tmi_desc != NULL) 205 topo_mod_strfree(mod, mod->tm_info->tmi_desc); 206 if (mod->tm_info->tmi_scheme != NULL) 207 topo_mod_strfree(mod, mod->tm_info->tmi_scheme); 208 209 topo_mod_free(mod, mod->tm_info, sizeof (topo_imodinfo_t)); 210 211 mod->tm_info = NULL; 212 } 213 214 int 215 topo_mod_enumerate(topo_mod_t *mod, tnode_t *node, const char *enum_name, 216 const char *name, topo_instance_t min, topo_instance_t max, void *data) 217 { 218 int err = 0; 219 topo_mod_t *enum_mod; 220 221 assert(mod->tm_flags & TOPO_MOD_REG); 222 223 if ((enum_mod = topo_mod_lookup(mod->tm_hdl, enum_name, 0)) == NULL) 224 return (topo_mod_seterrno(mod, EMOD_MOD_NOENT)); 225 226 topo_node_hold(node); 227 228 topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC, "module %s enumerating " 229 "node %s=%d\n", (char *)mod->tm_name, (char *)node->tn_name, 230 node->tn_instance); 231 232 topo_mod_enter(enum_mod); 233 err = enum_mod->tm_info->tmi_ops->tmo_enum(enum_mod, node, name, min, 234 max, enum_mod->tm_priv, data); 235 topo_mod_exit(enum_mod); 236 237 if (err != 0) { 238 (void) topo_mod_seterrno(mod, EMOD_UKNOWN_ENUM); 239 240 topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR, 241 "module %s failed enumeration for " 242 " node %s=%d\n", (char *)mod->tm_name, 243 (char *)node->tn_name, node->tn_instance); 244 245 topo_node_rele(node); 246 return (-1); 247 } 248 249 topo_node_rele(node); 250 251 return (0); 252 } 253 254 int 255 topo_mod_enummap(topo_mod_t *mod, tnode_t *node, const char *name, 256 const char *scheme) 257 { 258 return (topo_file_load(mod, node, (char *)name, (char *)scheme)); 259 } 260 261 static nvlist_t * 262 set_fmri_err(topo_mod_t *mod, int err) 263 { 264 (void) topo_mod_seterrno(mod, err); 265 return (NULL); 266 } 267 268 nvlist_t * 269 topo_mod_hcfmri(topo_mod_t *mod, tnode_t *pnode, int version, const char *name, 270 topo_instance_t inst, nvlist_t *hc_specific, nvlist_t *auth, 271 const char *part, const char *rev, const char *serial) 272 { 273 int err; 274 nvlist_t *pfmri = NULL, *fmri = NULL, *args = NULL; 275 nvlist_t *nfp = NULL; 276 277 if (version != FM_HC_SCHEME_VERSION) 278 return (set_fmri_err(mod, EMOD_FMRI_VERSION)); 279 280 /* 281 * Do we have any args to pass? 282 */ 283 if (pnode != NULL || auth != NULL || part != NULL || rev != NULL || 284 serial != NULL || hc_specific != NULL) { 285 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) 286 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 287 } 288 289 if (pnode != NULL) { 290 if (topo_node_resource(pnode, &pfmri, &err) < 0) 291 return (set_fmri_err(mod, EMOD_NVL_INVAL)); 292 293 if (nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT, 294 pfmri) != 0) { 295 nvlist_free(pfmri); 296 nvlist_free(args); 297 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 298 } 299 nvlist_free(pfmri); 300 } 301 302 /* 303 * Add optional payload 304 */ 305 if (auth != NULL) 306 (void) nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_AUTH, auth); 307 if (part != NULL) 308 (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_PART, part); 309 if (rev != NULL) 310 (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_REV, rev); 311 if (serial != NULL) 312 (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_SER, 313 serial); 314 if (hc_specific != NULL) 315 (void) nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_HCS, 316 hc_specific); 317 318 if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_HC, name, inst, 319 args, &err)) == NULL) { 320 nvlist_free(args); 321 return (set_fmri_err(mod, err)); 322 } 323 324 nvlist_free(args); 325 326 (void) topo_mod_nvdup(mod, fmri, &nfp); 327 nvlist_free(fmri); 328 329 return (nfp); 330 } 331 332 nvlist_t * 333 topo_mod_devfmri(topo_mod_t *mod, int version, const char *dev_path, 334 const char *devid) 335 { 336 int err; 337 nvlist_t *fmri, *args; 338 nvlist_t *nfp = NULL; 339 340 if (version != FM_DEV_SCHEME_VERSION) 341 return (set_fmri_err(mod, EMOD_FMRI_VERSION)); 342 343 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) 344 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 345 346 if (nvlist_add_string(args, FM_FMRI_DEV_PATH, dev_path) != 0) { 347 nvlist_free(args); 348 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 349 } 350 351 (void) nvlist_add_string(args, FM_FMRI_DEV_ID, devid); 352 353 if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_DEV, 354 FM_FMRI_SCHEME_DEV, 0, args, &err)) == NULL) { 355 nvlist_free(args); 356 return (set_fmri_err(mod, err)); 357 } 358 359 nvlist_free(args); 360 361 (void) topo_mod_nvdup(mod, fmri, &nfp); 362 nvlist_free(fmri); 363 364 return (nfp); 365 } 366 367 nvlist_t * 368 topo_mod_cpufmri(topo_mod_t *mod, int version, uint32_t cpu_id, uint8_t cpumask, 369 const char *serial) 370 { 371 int err; 372 nvlist_t *fmri = NULL, *args = NULL; 373 nvlist_t *nfp = NULL; 374 375 if (version != FM_CPU_SCHEME_VERSION) 376 return (set_fmri_err(mod, EMOD_FMRI_VERSION)); 377 378 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) 379 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 380 381 if (nvlist_add_uint32(args, FM_FMRI_CPU_ID, cpu_id) != 0) { 382 nvlist_free(args); 383 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 384 } 385 386 /* 387 * Add optional payload 388 */ 389 (void) nvlist_add_uint8(args, FM_FMRI_CPU_MASK, cpumask); 390 (void) nvlist_add_string(args, FM_FMRI_CPU_SERIAL_ID, serial); 391 392 if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_CPU, 393 FM_FMRI_SCHEME_CPU, 0, args, &err)) == NULL) { 394 nvlist_free(args); 395 return (set_fmri_err(mod, err)); 396 } 397 398 nvlist_free(args); 399 400 (void) topo_mod_nvdup(mod, fmri, &nfp); 401 nvlist_free(fmri); 402 403 return (nfp); 404 } 405 406 nvlist_t * 407 topo_mod_memfmri(topo_mod_t *mod, int version, uint64_t pa, uint64_t offset, 408 const char *unum, int flags) 409 { 410 int err; 411 nvlist_t *args = NULL, *fmri = NULL; 412 nvlist_t *nfp = NULL; 413 414 if (version != FM_MEM_SCHEME_VERSION) 415 return (set_fmri_err(mod, EMOD_FMRI_VERSION)); 416 417 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) 418 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 419 420 err = nvlist_add_string(args, FM_FMRI_MEM_UNUM, unum); 421 nvlist_free(args); 422 if (flags & TOPO_MEMFMRI_PA) 423 err |= nvlist_add_uint64(args, FM_FMRI_MEM_PHYSADDR, pa); 424 if (flags & TOPO_MEMFMRI_OFFSET) 425 err |= nvlist_add_uint64(args, FM_FMRI_MEM_OFFSET, offset); 426 427 if (err != 0) { 428 nvlist_free(args); 429 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 430 } 431 432 if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_MEM, 433 FM_FMRI_SCHEME_MEM, 0, args, &err)) == NULL) { 434 nvlist_free(args); 435 return (set_fmri_err(mod, err)); 436 } 437 438 nvlist_free(args); 439 440 (void) topo_mod_nvdup(mod, fmri, &nfp); 441 nvlist_free(fmri); 442 443 return (nfp); 444 445 } 446 447 nvlist_t * 448 topo_mod_pkgfmri(topo_mod_t *mod, int version, const char *path) 449 { 450 int err; 451 nvlist_t *fmri = NULL, *args = NULL; 452 nvlist_t *nfp = NULL; 453 454 if (version != FM_PKG_SCHEME_VERSION) 455 return (set_fmri_err(mod, EMOD_FMRI_VERSION)); 456 457 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) 458 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 459 460 if (nvlist_add_string(args, "path", path) != 0) { 461 nvlist_free(args); 462 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 463 } 464 465 if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_PKG, 466 FM_FMRI_SCHEME_PKG, 0, args, &err)) == NULL) { 467 nvlist_free(args); 468 return (set_fmri_err(mod, err)); 469 } 470 471 nvlist_free(args); 472 473 (void) topo_mod_nvdup(mod, fmri, &nfp); 474 nvlist_free(fmri); 475 476 return (nfp); 477 } 478 479 nvlist_t * 480 topo_mod_modfmri(topo_mod_t *mod, int version, const char *driver) 481 { 482 int err; 483 nvlist_t *fmri = NULL, *args = NULL; 484 nvlist_t *nfp = NULL; 485 486 if (version != FM_MOD_SCHEME_VERSION) 487 return (set_fmri_err(mod, EMOD_FMRI_VERSION)); 488 489 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) 490 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 491 492 if (nvlist_add_string(args, "DRIVER", driver) != 0) { 493 nvlist_free(args); 494 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 495 } 496 497 if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_MOD, 498 FM_FMRI_SCHEME_MOD, 0, args, &err)) == NULL) { 499 nvlist_free(args); 500 return (set_fmri_err(mod, err)); 501 } 502 503 nvlist_free(args); 504 505 (void) topo_mod_nvdup(mod, fmri, &nfp); 506 nvlist_free(fmri); 507 508 return (nfp); 509 } 510 511 int 512 topo_mod_str2nvl(topo_mod_t *mod, const char *fmristr, nvlist_t **fmri) 513 { 514 int err; 515 nvlist_t *np = NULL; 516 517 if (topo_fmri_str2nvl(mod->tm_hdl, fmristr, &np, &err) < 0) 518 return (topo_mod_seterrno(mod, err)); 519 520 if (topo_mod_nvdup(mod, np, fmri) < 0) { 521 nvlist_free(np); 522 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); 523 } 524 525 nvlist_free(np); 526 527 return (0); 528 } 529 530 int 531 topo_mod_nvl2str(topo_mod_t *mod, nvlist_t *fmri, char **fmristr) 532 { 533 int err; 534 char *sp; 535 536 if (topo_fmri_nvl2str(mod->tm_hdl, fmri, &sp, &err) < 0) 537 return (topo_mod_seterrno(mod, err)); 538 539 if ((*fmristr = topo_mod_strdup(mod, sp)) == NULL) { 540 topo_hdl_strfree(mod->tm_hdl, sp); 541 return (topo_mod_seterrno(mod, EMOD_NOMEM)); 542 } 543 544 topo_hdl_strfree(mod->tm_hdl, sp); 545 546 return (0); 547 } 548 549 void * 550 topo_mod_getspecific(topo_mod_t *mod) 551 { 552 return (mod->tm_priv); 553 } 554 555 void 556 topo_mod_setspecific(topo_mod_t *mod, void *data) 557 { 558 mod->tm_priv = data; 559 } 560 561 void 562 topo_mod_setdebug(topo_mod_t *mod) 563 { 564 mod->tm_debug = 1; 565 } 566 567 di_node_t 568 topo_mod_devinfo(topo_mod_t *mod) 569 { 570 topo_hdl_t *thp = mod->tm_hdl; 571 572 if (thp->th_di == DI_NODE_NIL) 573 thp->th_di = di_init("/", DINFOCPYALL); 574 575 return (thp->th_di); 576 } 577 578 di_prom_handle_t 579 topo_mod_prominfo(topo_mod_t *mod) 580 { 581 topo_hdl_t *thp = mod->tm_hdl; 582 583 if (thp->th_pi == DI_PROM_HANDLE_NIL) 584 thp->th_pi = di_prom_init(); 585 586 return (thp->th_pi); 587 } 588 589 void 590 topo_mod_clrdebug(topo_mod_t *mod) 591 { 592 mod->tm_debug = 0; 593 } 594 595 /*PRINTFLIKE2*/ 596 void 597 topo_mod_dprintf(topo_mod_t *mod, const char *format, ...) 598 { 599 va_list alist; 600 601 if (mod->tm_debug == 0) 602 return; 603 604 va_start(alist, format); 605 topo_vdprintf(mod->tm_hdl, TOPO_DBG_MOD, (const char *)mod->tm_name, 606 format, alist); 607 va_end(alist); 608 } 609 610 static char * 611 topo_mod_product(topo_mod_t *mod) 612 { 613 return (topo_mod_strdup(mod, mod->tm_hdl->th_product)); 614 } 615 616 static char * 617 topo_mod_server(topo_mod_t *mod) 618 { 619 static struct utsname uts; 620 621 (void) uname(&uts); 622 return (topo_mod_strdup(mod, uts.nodename)); 623 } 624 625 static char * 626 topo_mod_csn(topo_mod_t *mod) 627 { 628 char csn[MAXNAMELEN]; 629 di_prom_handle_t promh = DI_PROM_HANDLE_NIL; 630 di_node_t rooth = DI_NODE_NIL; 631 char *bufp, *str; 632 smbios_hdl_t *shp; 633 smbios_system_t s1; 634 smbios_info_t s2; 635 id_t id; 636 637 if ((shp = smbios_open(NULL, SMB_VERSION, 0, NULL)) != NULL) { 638 if ((id = smbios_info_system(shp, &s1)) != SMB_ERR && 639 smbios_info_common(shp, id, &s2) != SMB_ERR) { 640 (void) strlcpy(csn, s2.smbi_serial, MAXNAMELEN); 641 } 642 smbios_close(shp); 643 644 if (strcmp(csn, SMB_DEFAULT1) == 0 || 645 strcmp(csn, SMB_DEFAULT2) == 0) 646 return (NULL); 647 648 /* 649 * Terminate CSN at the first white space 650 */ 651 if ((str = strchr(csn, ' ')) != NULL) 652 *str = '\0'; 653 654 } else if ((rooth = topo_mod_devinfo(mod)) != DI_NODE_NIL && 655 (promh = topo_mod_prominfo(mod)) != DI_PROM_HANDLE_NIL) { 656 if (di_prom_prop_lookup_bytes(promh, rooth, "chassis-sn", 657 (unsigned char **)&bufp) != -1) { 658 (void) strlcpy(csn, bufp, MAXNAMELEN); 659 } else { 660 return (NULL); 661 } 662 } else { 663 return (NULL); 664 } 665 666 return (topo_mod_strdup(mod, csn)); 667 } 668 669 nvlist_t * 670 topo_mod_auth(topo_mod_t *mod, tnode_t *pnode) 671 { 672 int err; 673 char *prod = NULL; 674 char *csn = NULL; 675 char *server = NULL; 676 nvlist_t *auth; 677 678 (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY, 679 FM_FMRI_AUTH_PRODUCT, &prod, &err); 680 (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY, 681 FM_FMRI_AUTH_CHASSIS, &csn, &err); 682 (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY, 683 FM_FMRI_AUTH_SERVER, &server, &err); 684 685 /* 686 * Let's do this the hard way 687 */ 688 if (prod == NULL) 689 prod = topo_mod_product(mod); 690 if (csn == NULL) 691 csn = topo_mod_csn(mod); 692 if (server == NULL) { 693 server = topo_mod_server(mod); 694 } 695 696 /* 697 * No luck, return NULL 698 */ 699 if (!prod && !server && !csn) 700 return (NULL); 701 702 if ((err = topo_mod_nvalloc(mod, &auth, NV_UNIQUE_NAME)) != 0) { 703 (void) topo_mod_seterrno(mod, EMOD_FMRI_NVL); 704 return (NULL); 705 } 706 707 if (prod != NULL) { 708 err |= nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT, prod); 709 topo_mod_strfree(mod, prod); 710 } 711 if (server != NULL) { 712 err |= nvlist_add_string(auth, FM_FMRI_AUTH_SERVER, server); 713 topo_mod_strfree(mod, server); 714 } 715 if (csn != NULL) { 716 err |= nvlist_add_string(auth, FM_FMRI_AUTH_CHASSIS, csn); 717 topo_mod_strfree(mod, csn); 718 } 719 720 if (err != 0) { 721 nvlist_free(auth); 722 (void) topo_mod_seterrno(mod, EMOD_NVL_INVAL); 723 return (NULL); 724 } 725 726 return (auth); 727 } 728