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