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