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