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 2009 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 <ctype.h> 94 #include <sys/param.h> 95 #include <sys/utsname.h> 96 #include <sys/smbios.h> 97 #include <sys/fm/protocol.h> 98 99 #include <topo_alloc.h> 100 #include <topo_error.h> 101 #include <topo_file.h> 102 #include <topo_fmri.h> 103 #include <topo_module.h> 104 #include <topo_method.h> 105 #include <topo_string.h> 106 #include <topo_subr.h> 107 #include <topo_tree.h> 108 109 #define PLUGIN_PATH "plugins" 110 #define PLUGIN_PATH_LEN MAXNAMELEN + 5 111 112 topo_mod_t * 113 topo_mod_load(topo_mod_t *pmod, const char *name, 114 topo_version_t version) 115 { 116 char *path; 117 char file[PLUGIN_PATH_LEN]; 118 topo_mod_t *mod = NULL; 119 topo_hdl_t *thp; 120 121 thp = pmod->tm_hdl; 122 123 /* 124 * Already loaded, topo_mod_lookup will bump the ref count 125 */ 126 if ((mod = topo_mod_lookup(thp, name, 1)) != NULL) { 127 if (mod->tm_info->tmi_version != version) { 128 topo_mod_rele(mod); 129 (void) topo_mod_seterrno(pmod, ETOPO_MOD_VER); 130 return (NULL); 131 } 132 return (mod); 133 } 134 135 (void) snprintf(file, PLUGIN_PATH_LEN, "%s/%s.so", 136 PLUGIN_PATH, name); 137 path = topo_search_path(pmod, thp->th_rootdir, (const char *)file); 138 if (path == NULL || 139 (mod = topo_modhash_load(thp, name, path, &topo_rtld_ops, version)) 140 == NULL) { /* returned with mod held */ 141 topo_mod_strfree(pmod, path); 142 (void) topo_mod_seterrno(pmod, topo_hdl_errno(thp) ? 143 topo_hdl_errno(thp) : ETOPO_MOD_NOENT); 144 return (NULL); 145 } 146 147 topo_mod_strfree(pmod, path); 148 149 return (mod); 150 } 151 152 void 153 topo_mod_unload(topo_mod_t *mod) 154 { 155 topo_mod_rele(mod); 156 } 157 158 static int 159 set_register_error(topo_mod_t *mod, int err) 160 { 161 if (mod->tm_info != NULL) 162 topo_mod_unregister(mod); 163 164 topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR, 165 "module registration failed for %s: %s\n", 166 mod->tm_name, topo_strerror(err)); 167 168 return (topo_mod_seterrno(mod, err)); 169 } 170 171 int 172 topo_mod_register(topo_mod_t *mod, const topo_modinfo_t *mip, 173 topo_version_t version) 174 { 175 176 assert(!(mod->tm_flags & TOPO_MOD_FINI || 177 mod->tm_flags & TOPO_MOD_REG)); 178 179 if (version != TOPO_VERSION) 180 return (set_register_error(mod, EMOD_VER_ABI)); 181 182 if ((mod->tm_info = topo_mod_zalloc(mod, sizeof (topo_imodinfo_t))) 183 == NULL) 184 return (set_register_error(mod, EMOD_NOMEM)); 185 if ((mod->tm_info->tmi_ops = topo_mod_alloc(mod, 186 sizeof (topo_modops_t))) == NULL) 187 return (set_register_error(mod, EMOD_NOMEM)); 188 189 mod->tm_info->tmi_desc = topo_mod_strdup(mod, mip->tmi_desc); 190 if (mod->tm_info->tmi_desc == NULL) 191 return (set_register_error(mod, EMOD_NOMEM)); 192 193 mod->tm_info->tmi_scheme = topo_mod_strdup(mod, mip->tmi_scheme); 194 if (mod->tm_info->tmi_scheme == NULL) 195 return (set_register_error(mod, EMOD_NOMEM)); 196 197 198 mod->tm_info->tmi_version = (topo_version_t)mip->tmi_version; 199 mod->tm_info->tmi_ops->tmo_enum = mip->tmi_ops->tmo_enum; 200 mod->tm_info->tmi_ops->tmo_release = mip->tmi_ops->tmo_release; 201 202 mod->tm_flags |= TOPO_MOD_REG; 203 204 topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC, 205 "registration succeeded for %s\n", mod->tm_name); 206 207 return (0); 208 } 209 210 void 211 topo_mod_unregister(topo_mod_t *mod) 212 { 213 if (mod->tm_info == NULL) 214 return; 215 216 assert(!(mod->tm_flags & TOPO_MOD_FINI)); 217 218 mod->tm_flags &= ~TOPO_MOD_REG; 219 220 if (mod->tm_info == NULL) 221 return; 222 223 if (mod->tm_info->tmi_ops != NULL) 224 topo_mod_free(mod, mod->tm_info->tmi_ops, 225 sizeof (topo_modops_t)); 226 if (mod->tm_info->tmi_desc != NULL) 227 topo_mod_strfree(mod, mod->tm_info->tmi_desc); 228 if (mod->tm_info->tmi_scheme != NULL) 229 topo_mod_strfree(mod, mod->tm_info->tmi_scheme); 230 231 topo_mod_free(mod, mod->tm_info, sizeof (topo_imodinfo_t)); 232 233 mod->tm_info = NULL; 234 } 235 236 int 237 topo_mod_enumerate(topo_mod_t *mod, tnode_t *node, const char *enum_name, 238 const char *name, topo_instance_t min, topo_instance_t max, void *data) 239 { 240 int err = 0; 241 topo_mod_t *enum_mod; 242 243 assert(mod->tm_flags & TOPO_MOD_REG); 244 245 if ((enum_mod = topo_mod_lookup(mod->tm_hdl, enum_name, 0)) == NULL) 246 return (topo_mod_seterrno(mod, EMOD_MOD_NOENT)); 247 248 topo_node_hold(node); 249 250 topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC, "module %s enumerating " 251 "node %s=%d\n", (char *)mod->tm_name, (char *)node->tn_name, 252 node->tn_instance); 253 254 topo_mod_enter(enum_mod); 255 err = enum_mod->tm_info->tmi_ops->tmo_enum(enum_mod, node, name, min, 256 max, enum_mod->tm_priv, data); 257 topo_mod_exit(enum_mod); 258 259 if (err != 0) { 260 (void) topo_mod_seterrno(mod, EMOD_UKNOWN_ENUM); 261 262 topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR, 263 "module %s failed enumeration for " 264 " node %s=%d\n", (char *)mod->tm_name, 265 (char *)node->tn_name, node->tn_instance); 266 267 topo_node_rele(node); 268 return (-1); 269 } 270 271 topo_node_rele(node); 272 273 return (0); 274 } 275 276 int 277 topo_mod_enummap(topo_mod_t *mod, tnode_t *node, const char *name, 278 const char *scheme) 279 { 280 return (topo_file_load(mod, node, (char *)name, (char *)scheme, 0)); 281 } 282 283 static nvlist_t * 284 set_fmri_err(topo_mod_t *mod, int err) 285 { 286 (void) topo_mod_seterrno(mod, err); 287 return (NULL); 288 } 289 290 nvlist_t * 291 topo_mod_hcfmri(topo_mod_t *mod, tnode_t *pnode, int version, const char *name, 292 topo_instance_t inst, nvlist_t *hc_specific, nvlist_t *auth, 293 const char *part, const char *rev, const char *serial) 294 { 295 int err; 296 nvlist_t *pfmri = NULL, *fmri = NULL, *args = NULL; 297 nvlist_t *nfp = NULL; 298 char *lpart, *lrev, *lserial; 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 lpart = topo_cleanup_auth_str(mod->tm_hdl, part); 334 if (lpart != NULL) { 335 (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_PART, 336 lpart); 337 topo_hdl_free(mod->tm_hdl, lpart, strlen(lpart) + 1); 338 } else { 339 (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_PART, 340 ""); 341 } 342 } 343 if (rev != NULL) { 344 lrev = topo_cleanup_auth_str(mod->tm_hdl, rev); 345 if (lrev != NULL) { 346 (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_REV, 347 lrev); 348 topo_hdl_free(mod->tm_hdl, lrev, strlen(lrev) + 1); 349 } else { 350 (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_REV, 351 ""); 352 } 353 } 354 if (serial != NULL) { 355 lserial = topo_cleanup_auth_str(mod->tm_hdl, serial); 356 if (lserial != NULL) { 357 (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_SER, 358 lserial); 359 topo_hdl_free(mod->tm_hdl, lserial, 360 strlen(lserial) + 1); 361 } else { 362 (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_SER, 363 ""); 364 } 365 } 366 if (hc_specific != NULL) 367 (void) nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_HCS, 368 hc_specific); 369 370 if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_HC, name, inst, 371 args, &err)) == NULL) { 372 nvlist_free(args); 373 return (set_fmri_err(mod, err)); 374 } 375 376 nvlist_free(args); 377 378 (void) topo_mod_nvdup(mod, fmri, &nfp); 379 nvlist_free(fmri); 380 381 return (nfp); 382 } 383 384 nvlist_t * 385 topo_mod_devfmri(topo_mod_t *mod, int version, const char *dev_path, 386 const char *devid) 387 { 388 int err; 389 nvlist_t *fmri, *args; 390 nvlist_t *nfp = NULL; 391 392 if (version != FM_DEV_SCHEME_VERSION) 393 return (set_fmri_err(mod, EMOD_FMRI_VERSION)); 394 395 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) 396 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 397 398 if (nvlist_add_string(args, FM_FMRI_DEV_PATH, dev_path) != 0) { 399 nvlist_free(args); 400 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 401 } 402 403 (void) nvlist_add_string(args, FM_FMRI_DEV_ID, devid); 404 405 if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_DEV, 406 FM_FMRI_SCHEME_DEV, 0, args, &err)) == NULL) { 407 nvlist_free(args); 408 return (set_fmri_err(mod, err)); 409 } 410 411 nvlist_free(args); 412 413 (void) topo_mod_nvdup(mod, fmri, &nfp); 414 nvlist_free(fmri); 415 416 return (nfp); 417 } 418 419 nvlist_t * 420 topo_mod_cpufmri(topo_mod_t *mod, int version, uint32_t cpu_id, uint8_t cpumask, 421 const char *serial) 422 { 423 int err; 424 nvlist_t *fmri = NULL, *args = NULL; 425 nvlist_t *nfp = NULL; 426 427 if (version != FM_CPU_SCHEME_VERSION) 428 return (set_fmri_err(mod, EMOD_FMRI_VERSION)); 429 430 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) 431 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 432 433 if (nvlist_add_uint32(args, FM_FMRI_CPU_ID, cpu_id) != 0) { 434 nvlist_free(args); 435 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 436 } 437 438 /* 439 * Add optional payload 440 */ 441 (void) nvlist_add_uint8(args, FM_FMRI_CPU_MASK, cpumask); 442 (void) nvlist_add_string(args, FM_FMRI_CPU_SERIAL_ID, serial); 443 444 if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_CPU, 445 FM_FMRI_SCHEME_CPU, 0, args, &err)) == NULL) { 446 nvlist_free(args); 447 return (set_fmri_err(mod, err)); 448 } 449 450 nvlist_free(args); 451 452 (void) topo_mod_nvdup(mod, fmri, &nfp); 453 nvlist_free(fmri); 454 455 return (nfp); 456 } 457 458 nvlist_t * 459 topo_mod_memfmri(topo_mod_t *mod, int version, uint64_t pa, uint64_t offset, 460 const char *unum, int flags) 461 { 462 int err; 463 nvlist_t *args = NULL, *fmri = NULL; 464 nvlist_t *nfp = NULL; 465 466 if (version != FM_MEM_SCHEME_VERSION) 467 return (set_fmri_err(mod, EMOD_FMRI_VERSION)); 468 469 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) 470 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 471 472 err = nvlist_add_string(args, FM_FMRI_MEM_UNUM, unum); 473 nvlist_free(args); 474 if (flags & TOPO_MEMFMRI_PA) 475 err |= nvlist_add_uint64(args, FM_FMRI_MEM_PHYSADDR, pa); 476 if (flags & TOPO_MEMFMRI_OFFSET) 477 err |= nvlist_add_uint64(args, FM_FMRI_MEM_OFFSET, offset); 478 479 if (err != 0) { 480 nvlist_free(args); 481 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 482 } 483 484 if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_MEM, 485 FM_FMRI_SCHEME_MEM, 0, args, &err)) == NULL) { 486 nvlist_free(args); 487 return (set_fmri_err(mod, err)); 488 } 489 490 nvlist_free(args); 491 492 (void) topo_mod_nvdup(mod, fmri, &nfp); 493 nvlist_free(fmri); 494 495 return (nfp); 496 497 } 498 499 nvlist_t * 500 topo_mod_pkgfmri(topo_mod_t *mod, int version, const char *path) 501 { 502 int err; 503 nvlist_t *fmri = NULL, *args = NULL; 504 nvlist_t *nfp = NULL; 505 506 if (version != FM_PKG_SCHEME_VERSION) 507 return (set_fmri_err(mod, EMOD_FMRI_VERSION)); 508 509 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) 510 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 511 512 if (nvlist_add_string(args, "path", path) != 0) { 513 nvlist_free(args); 514 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 515 } 516 517 if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_PKG, 518 FM_FMRI_SCHEME_PKG, 0, args, &err)) == NULL) { 519 nvlist_free(args); 520 return (set_fmri_err(mod, err)); 521 } 522 523 nvlist_free(args); 524 525 (void) topo_mod_nvdup(mod, fmri, &nfp); 526 nvlist_free(fmri); 527 528 return (nfp); 529 } 530 531 nvlist_t * 532 topo_mod_modfmri(topo_mod_t *mod, int version, const char *driver) 533 { 534 int err; 535 nvlist_t *fmri = NULL, *args = NULL; 536 nvlist_t *nfp = NULL; 537 538 if (version != FM_MOD_SCHEME_VERSION) 539 return (set_fmri_err(mod, EMOD_FMRI_VERSION)); 540 541 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) 542 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 543 544 if (nvlist_add_string(args, "DRIVER", driver) != 0) { 545 nvlist_free(args); 546 return (set_fmri_err(mod, EMOD_FMRI_NVL)); 547 } 548 549 if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_MOD, 550 FM_FMRI_SCHEME_MOD, 0, args, &err)) == NULL) { 551 nvlist_free(args); 552 return (set_fmri_err(mod, err)); 553 } 554 555 nvlist_free(args); 556 557 (void) topo_mod_nvdup(mod, fmri, &nfp); 558 nvlist_free(fmri); 559 560 return (nfp); 561 } 562 563 int 564 topo_mod_str2nvl(topo_mod_t *mod, const char *fmristr, nvlist_t **fmri) 565 { 566 int err; 567 nvlist_t *np = NULL; 568 569 if (topo_fmri_str2nvl(mod->tm_hdl, fmristr, &np, &err) < 0) 570 return (topo_mod_seterrno(mod, err)); 571 572 if (topo_mod_nvdup(mod, np, fmri) < 0) { 573 nvlist_free(np); 574 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); 575 } 576 577 nvlist_free(np); 578 579 return (0); 580 } 581 582 int 583 topo_mod_nvl2str(topo_mod_t *mod, nvlist_t *fmri, char **fmristr) 584 { 585 int err; 586 char *sp; 587 588 if (topo_fmri_nvl2str(mod->tm_hdl, fmri, &sp, &err) < 0) 589 return (topo_mod_seterrno(mod, err)); 590 591 if ((*fmristr = topo_mod_strdup(mod, sp)) == NULL) { 592 topo_hdl_strfree(mod->tm_hdl, sp); 593 return (topo_mod_seterrno(mod, EMOD_NOMEM)); 594 } 595 596 topo_hdl_strfree(mod->tm_hdl, sp); 597 598 return (0); 599 } 600 601 void * 602 topo_mod_getspecific(topo_mod_t *mod) 603 { 604 return (mod->tm_priv); 605 } 606 607 void 608 topo_mod_setspecific(topo_mod_t *mod, void *data) 609 { 610 mod->tm_priv = data; 611 } 612 613 void 614 topo_mod_setdebug(topo_mod_t *mod) 615 { 616 mod->tm_debug = 1; 617 } 618 619 ipmi_handle_t * 620 topo_mod_ipmi_hold(topo_mod_t *mod) 621 { 622 topo_hdl_t *thp = mod->tm_hdl; 623 int err; 624 char *errmsg; 625 626 (void) pthread_mutex_lock(&thp->th_ipmi_lock); 627 if (thp->th_ipmi == NULL) { 628 if ((thp->th_ipmi = ipmi_open(&err, &errmsg)) == NULL) { 629 topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR, 630 "ipmi_open() failed: %s (ipmi errno=%d)", errmsg, 631 err); 632 (void) pthread_mutex_unlock(&thp->th_ipmi_lock); 633 } 634 } 635 636 637 return (thp->th_ipmi); 638 } 639 640 void 641 topo_mod_ipmi_rele(topo_mod_t *mod) 642 { 643 topo_hdl_t *thp = mod->tm_hdl; 644 645 (void) pthread_mutex_unlock(&thp->th_ipmi_lock); 646 } 647 648 di_node_t 649 topo_mod_devinfo(topo_mod_t *mod) 650 { 651 return (topo_hdl_devinfo(mod->tm_hdl)); 652 } 653 654 smbios_hdl_t * 655 topo_mod_smbios(topo_mod_t *mod) 656 { 657 topo_hdl_t *thp = mod->tm_hdl; 658 659 if (thp->th_smbios == NULL) 660 thp->th_smbios = smbios_open(NULL, SMB_VERSION, 0, NULL); 661 662 return (thp->th_smbios); 663 } 664 665 di_prom_handle_t 666 topo_mod_prominfo(topo_mod_t *mod) 667 { 668 return (topo_hdl_prominfo(mod->tm_hdl)); 669 } 670 671 void 672 topo_mod_clrdebug(topo_mod_t *mod) 673 { 674 mod->tm_debug = 0; 675 } 676 677 /*PRINTFLIKE2*/ 678 void 679 topo_mod_dprintf(topo_mod_t *mod, const char *format, ...) 680 { 681 va_list alist; 682 683 if (mod->tm_debug == 0) 684 return; 685 686 va_start(alist, format); 687 topo_vdprintf(mod->tm_hdl, TOPO_DBG_MOD, (const char *)mod->tm_name, 688 format, alist); 689 va_end(alist); 690 } 691 692 static char * 693 topo_mod_product(topo_mod_t *mod) 694 { 695 return (topo_mod_strdup(mod, mod->tm_hdl->th_product)); 696 } 697 698 static char * 699 topo_mod_server(topo_mod_t *mod) 700 { 701 static struct utsname uts; 702 703 (void) uname(&uts); 704 return (topo_mod_strdup(mod, uts.nodename)); 705 } 706 707 static char * 708 topo_mod_psn(topo_mod_t *mod) 709 { 710 smbios_hdl_t *shp; 711 const char *psn; 712 713 if ((shp = topo_mod_smbios(mod)) == NULL || 714 (psn = smbios_psn(shp)) == NULL) 715 return (NULL); 716 717 return (topo_cleanup_auth_str(mod->tm_hdl, psn)); 718 } 719 720 static char * 721 topo_mod_csn(topo_mod_t *mod) 722 { 723 char csn[MAXNAMELEN]; 724 smbios_hdl_t *shp; 725 di_prom_handle_t promh = DI_PROM_HANDLE_NIL; 726 di_node_t rooth = DI_NODE_NIL; 727 const char *bufp; 728 729 if ((shp = topo_mod_smbios(mod)) != NULL) { 730 bufp = smbios_csn(shp); 731 if (bufp != NULL) 732 (void) strlcpy(csn, bufp, MAXNAMELEN); 733 else 734 return (NULL); 735 } else if ((rooth = topo_mod_devinfo(mod)) != DI_NODE_NIL && 736 (promh = topo_mod_prominfo(mod)) != DI_PROM_HANDLE_NIL) { 737 if (di_prom_prop_lookup_bytes(promh, rooth, "chassis-sn", 738 (unsigned char **)&bufp) != -1) { 739 (void) strlcpy(csn, bufp, MAXNAMELEN); 740 } else { 741 return (NULL); 742 } 743 } else { 744 return (NULL); 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 *psn = NULL; 757 char *server = NULL; 758 nvlist_t *auth; 759 760 if ((err = topo_mod_nvalloc(mod, &auth, NV_UNIQUE_NAME)) != 0) { 761 (void) topo_mod_seterrno(mod, EMOD_FMRI_NVL); 762 return (NULL); 763 } 764 765 (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY, 766 FM_FMRI_AUTH_PRODUCT, &prod, &err); 767 (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY, 768 FM_FMRI_AUTH_PRODUCT_SN, &psn, &err); 769 (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY, 770 FM_FMRI_AUTH_CHASSIS, &csn, &err); 771 (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY, 772 FM_FMRI_AUTH_SERVER, &server, &err); 773 774 /* 775 * Let's do this the hard way 776 */ 777 if (prod == NULL) 778 prod = topo_mod_product(mod); 779 if (csn == NULL) 780 csn = topo_mod_csn(mod); 781 if (psn == NULL) 782 psn = topo_mod_psn(mod); 783 if (server == NULL) { 784 server = topo_mod_server(mod); 785 } 786 787 /* 788 * No luck, return NULL 789 */ 790 if (!prod && !server && !csn && !psn) { 791 nvlist_free(auth); 792 return (NULL); 793 } 794 795 err = 0; 796 if (prod != NULL) { 797 err |= nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT, prod); 798 topo_mod_strfree(mod, prod); 799 } 800 if (psn != NULL) { 801 err |= nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT_SN, psn); 802 topo_mod_strfree(mod, psn); 803 } 804 if (server != NULL) { 805 err |= nvlist_add_string(auth, FM_FMRI_AUTH_SERVER, server); 806 topo_mod_strfree(mod, server); 807 } 808 if (csn != NULL) { 809 err |= nvlist_add_string(auth, FM_FMRI_AUTH_CHASSIS, csn); 810 topo_mod_strfree(mod, csn); 811 } 812 813 if (err != 0) { 814 nvlist_free(auth); 815 (void) topo_mod_seterrno(mod, EMOD_NVL_INVAL); 816 return (NULL); 817 } 818 819 return (auth); 820 } 821 822 topo_walk_t * 823 topo_mod_walk_init(topo_mod_t *mod, tnode_t *node, topo_mod_walk_cb_t cb_f, 824 void *pdata, int *errp) 825 { 826 topo_walk_t *wp; 827 topo_hdl_t *thp = mod->tm_hdl; 828 829 if ((wp = topo_node_walk_init(thp, mod, node, (int (*)())cb_f, pdata, 830 errp)) == NULL) 831 return (NULL); 832 833 return (wp); 834 } 835