4018 mpt_sas: allow physical topology enumeration in libtopo
[illumos-gate.git] / usr / src / lib / fm / topo / libtopo / common / topo_mod.c
blob295054dc5ea759a0563375e577fad233c987bdee
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
26 * Topology Plugin Modules
28 * Topology plugin modules are shared libraries that are dlopen'd and
29 * used to enumerate resources in the system and export per-node method
30 * operations.
32 * They are loaded by our builtin scheme-specific plugins, other modules or
33 * by processing a topo map XML file to enumerate and create nodes for
34 * resources that are present in the system. They may also export a set of
35 * topology node specific methods that can be invoked directly via
36 * topo_method_invoke() or indirectly via the
37 * topo_prop_get* family of functions to access dynamic property data.
39 * Module Plugin API
41 * Enumerators must provide entry points for initialization and clean-up
42 * (_topo_init() and _topo_fini()). In their _topo_init() function, an
43 * enumerator should register (topo_mod_register()) its enumeration callback
44 * and allocate resources required for a subsequent call to the callback.
45 * Optionally, methods may also be registered with topo_method_register().
47 * In its enumeration callback routine, the module should search for resources
48 * within its realm of responsibility and create any node ranges,
49 * topo_node_range_create() and nodes, topo_node_bind(). The Enumerator
50 * module is handed a node to which it may begin attaching additional
51 * topology nodes. The enumerator may only access those nodes within its
52 * current scope of operation: the node passed into its enumeration op and
53 * any nodes it creates during enumeration. If the enumerator requires walker-
54 * style access to these nodes, it must use
55 * topo_mod_walk_init()/topo_walk_step()/topo_walk_fini().
57 * If additional helper modules need to be loaded to complete the enumeration
58 * the module may do so by calling topo_mod_load(). Enumeration may then
59 * continue with the module handing off enumeration to its helper module
60 * by calling topo_mod_enumerate(). Similarly, a module may call
61 * topo_mod_enummap() to kick-off enumeration according to a given XML
62 * topology map file. A module *may* not cause re-entrance to itself
63 * via either of these interfaces. If re-entry is detected an error
64 * will be returned (ETOPO_ENUM_RECURS).
66 * If the module registers a release callback, it will be called on a node
67 * by node basis during topo_snap_rele(). Any private node data may be
68 * deallocated or methods unregistered at that time. Global module data
69 * should be cleaned up before or at the time that the module _topo_fini
70 * entry point is called.
72 * Module entry points and method invocations are guaranteed to be
73 * single-threaded for a given snapshot handle. Applications may have
74 * more than one topology snapshot open at a time. This means that the
75 * module operations and methods may be called for different module handles
76 * (topo_mod_t) asynchronously. The enumerator should not use static or
77 * global data structures that may become inconsistent in this situation.
78 * Method operations may be re-entrant if the module invokes one of its own
79 * methods directly or via dynamic property access. Caution should be
80 * exercised with method operations to insure that data remains consistent
81 * within the module and that deadlocks can not occur.
84 #include <pthread.h>
85 #include <assert.h>
86 #include <errno.h>
87 #include <dirent.h>
88 #include <limits.h>
89 #include <alloca.h>
90 #include <unistd.h>
91 #include <stdio.h>
92 #include <ctype.h>
93 #include <sys/param.h>
94 #include <sys/utsname.h>
95 #include <sys/smbios.h>
96 #include <sys/fm/protocol.h>
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>
108 #define PLUGIN_PATH "plugins"
109 #define PLUGIN_PATH_LEN MAXNAMELEN + 5
111 topo_mod_t *
112 topo_mod_load(topo_mod_t *pmod, const char *name,
113 topo_version_t version)
115 char *path;
116 char file[PLUGIN_PATH_LEN];
117 topo_mod_t *mod = NULL;
118 topo_hdl_t *thp;
120 thp = pmod->tm_hdl;
123 * Already loaded, topo_mod_lookup will bump the ref count
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);
131 return (mod);
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);
146 topo_mod_strfree(pmod, path);
148 return (mod);
151 void
152 topo_mod_unload(topo_mod_t *mod)
154 topo_mod_rele(mod);
157 static int
158 set_register_error(topo_mod_t *mod, int err)
160 if (mod->tm_info != NULL)
161 topo_mod_unregister(mod);
163 topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR,
164 "module registration failed for %s: %s\n",
165 mod->tm_name, topo_strerror(err));
167 return (topo_mod_seterrno(mod, err));
171 topo_mod_register(topo_mod_t *mod, const topo_modinfo_t *mip,
172 topo_version_t version)
175 assert(!(mod->tm_flags & TOPO_MOD_FINI ||
176 mod->tm_flags & TOPO_MOD_REG));
178 if (version != TOPO_VERSION)
179 return (set_register_error(mod, EMOD_VER_ABI));
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));
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));
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));
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;
201 mod->tm_flags |= TOPO_MOD_REG;
203 topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC,
204 "registration succeeded for %s\n", mod->tm_name);
206 return (0);
209 void
210 topo_mod_unregister(topo_mod_t *mod)
212 if (mod->tm_info == NULL)
213 return;
215 assert(!(mod->tm_flags & TOPO_MOD_FINI));
217 mod->tm_flags &= ~TOPO_MOD_REG;
219 if (mod->tm_info == NULL)
220 return;
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);
230 topo_mod_free(mod, mod->tm_info, sizeof (topo_imodinfo_t));
232 mod->tm_info = NULL;
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)
239 int err = 0;
240 topo_mod_t *enum_mod;
242 assert(mod->tm_flags & TOPO_MOD_REG);
244 if ((enum_mod = topo_mod_lookup(mod->tm_hdl, enum_name, 0)) == NULL)
245 return (topo_mod_seterrno(mod, EMOD_MOD_NOENT));
247 topo_node_hold(node);
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);
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);
258 if (err != 0) {
259 (void) topo_mod_seterrno(mod, EMOD_UKNOWN_ENUM);
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);
266 topo_node_rele(node);
267 return (-1);
270 topo_node_rele(node);
272 return (0);
276 topo_mod_enummap(topo_mod_t *mod, tnode_t *node, const char *name,
277 const char *scheme)
279 return (topo_file_load(mod, node, (char *)name, (char *)scheme, 0));
282 static nvlist_t *
283 set_fmri_err(topo_mod_t *mod, int err)
285 (void) topo_mod_seterrno(mod, err);
286 return (NULL);
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)
294 int err;
295 nvlist_t *pfmri = NULL, *fmri = NULL, *args = NULL;
296 nvlist_t *nfp = NULL;
297 char *lpart, *lrev, *lserial;
299 if (version != FM_HC_SCHEME_VERSION)
300 return (set_fmri_err(mod, EMOD_FMRI_VERSION));
303 * Do we have any args to pass?
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));
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));
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));
323 nvlist_free(pfmri);
327 * Add optional payload
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 "");
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 "");
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 "");
365 if (hc_specific != NULL)
366 (void) nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_HCS,
367 hc_specific);
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));
375 nvlist_free(args);
377 (void) topo_mod_nvdup(mod, fmri, &nfp);
378 nvlist_free(fmri);
380 return (nfp);
383 nvlist_t *
384 topo_mod_devfmri(topo_mod_t *mod, int version, const char *dev_path,
385 const char *devid)
387 int err;
388 nvlist_t *fmri, *args;
389 nvlist_t *nfp = NULL;
391 if (version != FM_DEV_SCHEME_VERSION)
392 return (set_fmri_err(mod, EMOD_FMRI_VERSION));
394 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
395 return (set_fmri_err(mod, EMOD_FMRI_NVL));
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));
402 (void) nvlist_add_string(args, FM_FMRI_DEV_ID, devid);
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));
410 nvlist_free(args);
412 (void) topo_mod_nvdup(mod, fmri, &nfp);
413 nvlist_free(fmri);
415 return (nfp);
418 nvlist_t *
419 topo_mod_cpufmri(topo_mod_t *mod, int version, uint32_t cpu_id, uint8_t cpumask,
420 const char *serial)
422 int err;
423 nvlist_t *fmri = NULL, *args = NULL;
424 nvlist_t *nfp = NULL;
426 if (version != FM_CPU_SCHEME_VERSION)
427 return (set_fmri_err(mod, EMOD_FMRI_VERSION));
429 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
430 return (set_fmri_err(mod, EMOD_FMRI_NVL));
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));
438 * Add optional payload
440 (void) nvlist_add_uint8(args, FM_FMRI_CPU_MASK, cpumask);
441 (void) nvlist_add_string(args, FM_FMRI_CPU_SERIAL_ID, serial);
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));
449 nvlist_free(args);
451 (void) topo_mod_nvdup(mod, fmri, &nfp);
452 nvlist_free(fmri);
454 return (nfp);
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)
461 int err;
462 nvlist_t *args = NULL, *fmri = NULL;
463 nvlist_t *nfp = NULL;
465 if (version != FM_MEM_SCHEME_VERSION)
466 return (set_fmri_err(mod, EMOD_FMRI_VERSION));
468 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
469 return (set_fmri_err(mod, EMOD_FMRI_NVL));
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);
478 if (err != 0) {
479 nvlist_free(args);
480 return (set_fmri_err(mod, EMOD_FMRI_NVL));
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));
489 nvlist_free(args);
491 (void) topo_mod_nvdup(mod, fmri, &nfp);
492 nvlist_free(fmri);
494 return (nfp);
498 nvlist_t *
499 topo_mod_pkgfmri(topo_mod_t *mod, int version, const char *path)
501 int err;
502 nvlist_t *fmri = NULL, *args = NULL;
503 nvlist_t *nfp = NULL;
505 if (version != FM_PKG_SCHEME_VERSION)
506 return (set_fmri_err(mod, EMOD_FMRI_VERSION));
508 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
509 return (set_fmri_err(mod, EMOD_FMRI_NVL));
511 if (nvlist_add_string(args, "path", path) != 0) {
512 nvlist_free(args);
513 return (set_fmri_err(mod, EMOD_FMRI_NVL));
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));
522 nvlist_free(args);
524 (void) topo_mod_nvdup(mod, fmri, &nfp);
525 nvlist_free(fmri);
527 return (nfp);
530 nvlist_t *
531 topo_mod_modfmri(topo_mod_t *mod, int version, const char *driver)
533 int err;
534 nvlist_t *fmri = NULL, *args = NULL;
535 nvlist_t *nfp = NULL;
537 if (version != FM_MOD_SCHEME_VERSION)
538 return (set_fmri_err(mod, EMOD_FMRI_VERSION));
540 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
541 return (set_fmri_err(mod, EMOD_FMRI_NVL));
543 if (nvlist_add_string(args, "DRIVER", driver) != 0) {
544 nvlist_free(args);
545 return (set_fmri_err(mod, EMOD_FMRI_NVL));
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));
554 nvlist_free(args);
556 (void) topo_mod_nvdup(mod, fmri, &nfp);
557 nvlist_free(fmri);
559 return (nfp);
562 #define _SWFMRI_ADD_STRING(nvl, name, val) \
563 ((val) ? (nvlist_add_string(nvl, name, val) != 0) : 0)
565 nvlist_t *
566 topo_mod_swfmri(topo_mod_t *mod, int version,
567 char *obj_path, char *obj_root, nvlist_t *obj_pkg,
568 char *site_token, char *site_module, char *site_file, char *site_func,
569 int64_t site_line, char *ctxt_origin, char *ctxt_execname,
570 int64_t ctxt_pid, char *ctxt_zone, int64_t ctxt_ctid,
571 char **ctxt_stack, uint_t ctxt_stackdepth)
573 nvlist_t *fmri, *args;
574 nvlist_t *nfp = NULL;
575 int err;
577 if (version != FM_SW_SCHEME_VERSION)
578 return (set_fmri_err(mod, EMOD_FMRI_VERSION));
580 if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
581 return (set_fmri_err(mod, EMOD_FMRI_NVL));
583 err = 0;
584 err |= _SWFMRI_ADD_STRING(args, "obj_path", obj_path);
585 err |= _SWFMRI_ADD_STRING(args, "obj_root", obj_root);
586 if (obj_pkg)
587 err |= nvlist_add_nvlist(args, "obj_pkg", obj_pkg);
589 err |= _SWFMRI_ADD_STRING(args, "site_token", site_token);
590 err |= _SWFMRI_ADD_STRING(args, "site_module", site_module);
591 err |= _SWFMRI_ADD_STRING(args, "site_file", site_file);
592 err |= _SWFMRI_ADD_STRING(args, "site_func", site_func);
593 if (site_line != -1)
594 err |= nvlist_add_int64(args, "site_line", site_line);
596 err |= _SWFMRI_ADD_STRING(args, "ctxt_origin", ctxt_origin);
597 err |= _SWFMRI_ADD_STRING(args, "ctxt_execname", ctxt_execname);
598 if (ctxt_pid != -1)
599 err |= nvlist_add_int64(args, "ctxt_pid", ctxt_pid);
600 err |= _SWFMRI_ADD_STRING(args, "ctxt_zone", ctxt_zone);
601 if (ctxt_ctid != -1)
602 err |= nvlist_add_int64(args, "ctxt_ctid", ctxt_ctid);
603 if (ctxt_stack != NULL && ctxt_stackdepth != 0)
604 err |= nvlist_add_string_array(args, "stack", ctxt_stack,
605 ctxt_stackdepth);
607 if (err) {
608 nvlist_free(args);
609 return (set_fmri_err(mod, EMOD_FMRI_NVL));
612 if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_SW,
613 FM_FMRI_SCHEME_SW, 0, args, &err)) == NULL) {
614 nvlist_free(args);
615 return (set_fmri_err(mod, err));
618 nvlist_free(args);
620 (void) topo_mod_nvdup(mod, fmri, &nfp);
621 nvlist_free(fmri);
623 return (nfp);
627 topo_mod_str2nvl(topo_mod_t *mod, const char *fmristr, nvlist_t **fmri)
629 int err;
630 nvlist_t *np = NULL;
632 if (topo_fmri_str2nvl(mod->tm_hdl, fmristr, &np, &err) < 0)
633 return (topo_mod_seterrno(mod, err));
635 if (topo_mod_nvdup(mod, np, fmri) < 0) {
636 nvlist_free(np);
637 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
640 nvlist_free(np);
642 return (0);
646 topo_mod_nvl2str(topo_mod_t *mod, nvlist_t *fmri, char **fmristr)
648 int err;
649 char *sp;
651 if (topo_fmri_nvl2str(mod->tm_hdl, fmri, &sp, &err) < 0)
652 return (topo_mod_seterrno(mod, err));
654 if ((*fmristr = topo_mod_strdup(mod, sp)) == NULL) {
655 topo_hdl_strfree(mod->tm_hdl, sp);
656 return (topo_mod_seterrno(mod, EMOD_NOMEM));
659 topo_hdl_strfree(mod->tm_hdl, sp);
661 return (0);
664 void *
665 topo_mod_getspecific(topo_mod_t *mod)
667 return (mod->tm_priv);
670 void
671 topo_mod_setspecific(topo_mod_t *mod, void *data)
673 mod->tm_priv = data;
676 void
677 topo_mod_setdebug(topo_mod_t *mod)
679 mod->tm_debug = 1;
682 ipmi_handle_t *
683 topo_mod_ipmi_hold(topo_mod_t *mod)
685 topo_hdl_t *thp = mod->tm_hdl;
686 int err;
687 char *errmsg;
689 (void) pthread_mutex_lock(&thp->th_ipmi_lock);
690 if (thp->th_ipmi == NULL) {
691 if ((thp->th_ipmi = ipmi_open(&err, &errmsg, IPMI_TRANSPORT_BMC,
692 NULL)) == NULL) {
693 topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR,
694 "ipmi_open() failed: %s (ipmi errno=%d)", errmsg,
695 err);
696 (void) pthread_mutex_unlock(&thp->th_ipmi_lock);
701 return (thp->th_ipmi);
704 void
705 topo_mod_ipmi_rele(topo_mod_t *mod)
707 topo_hdl_t *thp = mod->tm_hdl;
709 (void) pthread_mutex_unlock(&thp->th_ipmi_lock);
712 di_node_t
713 topo_mod_devinfo(topo_mod_t *mod)
715 return (topo_hdl_devinfo(mod->tm_hdl));
718 smbios_hdl_t *
719 topo_mod_smbios(topo_mod_t *mod)
721 topo_hdl_t *thp = mod->tm_hdl;
723 if (thp->th_smbios == NULL)
724 thp->th_smbios = smbios_open(NULL, SMB_VERSION, 0, NULL);
726 return (thp->th_smbios);
729 di_prom_handle_t
730 topo_mod_prominfo(topo_mod_t *mod)
732 return (topo_hdl_prominfo(mod->tm_hdl));
735 void
736 topo_mod_clrdebug(topo_mod_t *mod)
738 mod->tm_debug = 0;
741 /*PRINTFLIKE2*/
742 void
743 topo_mod_dprintf(topo_mod_t *mod, const char *format, ...)
745 va_list alist;
747 if (mod->tm_debug == 0)
748 return;
750 va_start(alist, format);
751 topo_vdprintf(mod->tm_hdl, TOPO_DBG_MOD, (const char *)mod->tm_name,
752 format, alist);
753 va_end(alist);
756 static char *
757 topo_mod_product(topo_mod_t *mod)
759 return (topo_mod_strdup(mod, mod->tm_hdl->th_product));
762 static char *
763 topo_mod_server(topo_mod_t *mod)
765 static struct utsname uts;
767 (void) uname(&uts);
768 return (topo_mod_strdup(mod, uts.nodename));
771 static char *
772 topo_mod_psn(topo_mod_t *mod)
774 smbios_hdl_t *shp;
775 const char *psn;
777 if ((shp = topo_mod_smbios(mod)) == NULL ||
778 (psn = smbios_psn(shp)) == NULL)
779 return (NULL);
781 return (topo_cleanup_auth_str(mod->tm_hdl, psn));
784 static char *
785 topo_mod_csn(topo_mod_t *mod)
787 char csn[MAXNAMELEN];
788 smbios_hdl_t *shp;
789 di_prom_handle_t promh = DI_PROM_HANDLE_NIL;
790 di_node_t rooth = DI_NODE_NIL;
791 const char *bufp;
793 if ((shp = topo_mod_smbios(mod)) != NULL) {
794 bufp = smbios_csn(shp);
795 if (bufp != NULL)
796 (void) strlcpy(csn, bufp, MAXNAMELEN);
797 else
798 return (NULL);
799 } else if ((rooth = topo_mod_devinfo(mod)) != DI_NODE_NIL &&
800 (promh = topo_mod_prominfo(mod)) != DI_PROM_HANDLE_NIL) {
801 if (di_prom_prop_lookup_bytes(promh, rooth, "chassis-sn",
802 (unsigned char **)&bufp) != -1) {
803 (void) strlcpy(csn, bufp, MAXNAMELEN);
804 } else {
805 return (NULL);
807 } else {
808 return (NULL);
811 return (topo_cleanup_auth_str(mod->tm_hdl, csn));
814 nvlist_t *
815 topo_mod_auth(topo_mod_t *mod, tnode_t *pnode)
817 int err;
818 char *prod = NULL;
819 char *csn = NULL;
820 char *psn = NULL;
821 char *server = NULL;
822 nvlist_t *auth;
824 if ((err = topo_mod_nvalloc(mod, &auth, NV_UNIQUE_NAME)) != 0) {
825 (void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);
826 return (NULL);
829 (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY,
830 FM_FMRI_AUTH_PRODUCT, &prod, &err);
831 (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY,
832 FM_FMRI_AUTH_PRODUCT_SN, &psn, &err);
833 (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY,
834 FM_FMRI_AUTH_CHASSIS, &csn, &err);
835 (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY,
836 FM_FMRI_AUTH_SERVER, &server, &err);
839 * Let's do this the hard way
841 if (prod == NULL)
842 prod = topo_mod_product(mod);
843 if (csn == NULL)
844 csn = topo_mod_csn(mod);
845 if (psn == NULL)
846 psn = topo_mod_psn(mod);
847 if (server == NULL) {
848 server = topo_mod_server(mod);
852 * No luck, return NULL
854 if (!prod && !server && !csn && !psn) {
855 nvlist_free(auth);
856 return (NULL);
859 err = 0;
860 if (prod != NULL) {
861 err |= nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT, prod);
862 topo_mod_strfree(mod, prod);
864 if (psn != NULL) {
865 err |= nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT_SN, psn);
866 topo_mod_strfree(mod, psn);
868 if (server != NULL) {
869 err |= nvlist_add_string(auth, FM_FMRI_AUTH_SERVER, server);
870 topo_mod_strfree(mod, server);
872 if (csn != NULL) {
873 err |= nvlist_add_string(auth, FM_FMRI_AUTH_CHASSIS, csn);
874 topo_mod_strfree(mod, csn);
877 if (err != 0) {
878 nvlist_free(auth);
879 (void) topo_mod_seterrno(mod, EMOD_NVL_INVAL);
880 return (NULL);
883 return (auth);
886 topo_walk_t *
887 topo_mod_walk_init(topo_mod_t *mod, tnode_t *node, topo_mod_walk_cb_t cb_f,
888 void *pdata, int *errp)
890 topo_walk_t *wp;
891 topo_hdl_t *thp = mod->tm_hdl;
893 if ((wp = topo_node_walk_init(thp, mod, node, (int (*)())cb_f, pdata,
894 errp)) == NULL)
895 return (NULL);
897 return (wp);