11414Scindi /*
21414Scindi * CDDL HEADER START
31414Scindi *
41414Scindi * The contents of this file are subject to the terms of the
53062Scindi * Common Development and Distribution License (the "License").
63062Scindi * You may not use this file except in compliance with the License.
71414Scindi *
81414Scindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91414Scindi * or http://www.opensolaris.org/os/licensing.
101414Scindi * See the License for the specific language governing permissions
111414Scindi * and limitations under the License.
121414Scindi *
131414Scindi * When distributing Covered Code, include this CDDL HEADER in each
141414Scindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151414Scindi * If applicable, add the following below this CDDL HEADER, with the
161414Scindi * fields enclosed by brackets "[]" replaced with your own identifying
171414Scindi * information: Portions Copyright [yyyy] [name of copyright owner]
181414Scindi *
191414Scindi * CDDL HEADER END
201414Scindi */
211414Scindi /*
22*12967Sgavin.maltby@oracle.com * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
231414Scindi */
241414Scindi
251414Scindi /*
261414Scindi * Topology Plugin Modules
271414Scindi *
281414Scindi * Topology plugin modules are shared libraries that are dlopen'd and
294087Scindi * used to enumerate resources in the system and export per-node method
304087Scindi * operations.
314087Scindi *
324087Scindi * They are loaded by our builtin scheme-specific plugins, other modules or
334087Scindi * by processing a topo map XML file to enumerate and create nodes for
344087Scindi * resources that are present in the system. They may also export a set of
354087Scindi * topology node specific methods that can be invoked directly via
364087Scindi * topo_method_invoke() or indirectly via the
374087Scindi * topo_prop_get* family of functions to access dynamic property data.
381414Scindi *
391414Scindi * Module Plugin API
401414Scindi *
414198Seschrock * Enumerators must provide entry points for initialization and clean-up
421414Scindi * (_topo_init() and _topo_fini()). In their _topo_init() function, an
431414Scindi * enumerator should register (topo_mod_register()) its enumeration callback
441414Scindi * and allocate resources required for a subsequent call to the callback.
451414Scindi * Optionally, methods may also be registered with topo_method_register().
461414Scindi *
471414Scindi * In its enumeration callback routine, the module should search for resources
484198Seschrock * within its realm of responsibility and create any node ranges,
494087Scindi * topo_node_range_create() and nodes, topo_node_bind(). The Enumerator
501414Scindi * module is handed a node to which it may begin attaching additional
514087Scindi * topology nodes. The enumerator may only access those nodes within its
524087Scindi * current scope of operation: the node passed into its enumeration op and
534087Scindi * any nodes it creates during enumeration. If the enumerator requires walker-
544087Scindi * style access to these nodes, it must use
554087Scindi * topo_mod_walk_init()/topo_walk_step()/topo_walk_fini().
561414Scindi *
571414Scindi * If additional helper modules need to be loaded to complete the enumeration
581414Scindi * the module may do so by calling topo_mod_load(). Enumeration may then
591414Scindi * continue with the module handing off enumeration to its helper module
604087Scindi * by calling topo_mod_enumerate(). Similarly, a module may call
614087Scindi * topo_mod_enummap() to kick-off enumeration according to a given XML
624087Scindi * topology map file. A module *may* not cause re-entrance to itself
634087Scindi * via either of these interfaces. If re-entry is detected an error
644087Scindi * will be returned (ETOPO_ENUM_RECURS).
651414Scindi *
661414Scindi * If the module registers a release callback, it will be called on a node
671414Scindi * by node basis during topo_snap_rele(). Any private node data may be
681414Scindi * deallocated or methods unregistered at that time. Global module data
694087Scindi * should be cleaned up before or at the time that the module _topo_fini
701414Scindi * entry point is called.
714087Scindi *
724087Scindi * Module entry points and method invocations are guaranteed to be
734087Scindi * single-threaded for a given snapshot handle. Applications may have
744087Scindi * more than one topology snapshot open at a time. This means that the
754087Scindi * module operations and methods may be called for different module handles
764087Scindi * (topo_mod_t) asynchronously. The enumerator should not use static or
774087Scindi * global data structures that may become inconsistent in this situation.
784087Scindi * Method operations may be re-entrant if the module invokes one of its own
794087Scindi * methods directly or via dynamic property access. Caution should be
804087Scindi * exercised with method operations to insure that data remains consistent
814087Scindi * within the module and that deadlocks can not occur.
821414Scindi */
831414Scindi
841414Scindi #include <pthread.h>
851414Scindi #include <assert.h>
861414Scindi #include <errno.h>
871414Scindi #include <dirent.h>
881414Scindi #include <limits.h>
891414Scindi #include <alloca.h>
901414Scindi #include <unistd.h>
911414Scindi #include <stdio.h>
9210462SSean.Ye@Sun.COM #include <ctype.h>
933062Scindi #include <sys/param.h>
943062Scindi #include <sys/utsname.h>
953062Scindi #include <sys/smbios.h>
963062Scindi #include <sys/fm/protocol.h>
971414Scindi
981414Scindi #include <topo_alloc.h>
993062Scindi #include <topo_error.h>
1003062Scindi #include <topo_file.h>
1013323Scindi #include <topo_fmri.h>
1023062Scindi #include <topo_module.h>
1033062Scindi #include <topo_method.h>
1041414Scindi #include <topo_string.h>
1051414Scindi #include <topo_subr.h>
1063062Scindi #include <topo_tree.h>
1073062Scindi
1083062Scindi #define PLUGIN_PATH "plugins"
1093062Scindi #define PLUGIN_PATH_LEN MAXNAMELEN + 5
1101414Scindi
1111414Scindi topo_mod_t *
topo_mod_load(topo_mod_t * pmod,const char * name,topo_version_t version)1123062Scindi topo_mod_load(topo_mod_t *pmod, const char *name,
1133062Scindi topo_version_t version)
1141414Scindi {
1153062Scindi char *path;
1163062Scindi char file[PLUGIN_PATH_LEN];
1171414Scindi topo_mod_t *mod = NULL;
1181414Scindi topo_hdl_t *thp;
1191414Scindi
1201414Scindi thp = pmod->tm_hdl;
1211414Scindi
1221414Scindi /*
1233062Scindi * Already loaded, topo_mod_lookup will bump the ref count
1241414Scindi */
1253062Scindi if ((mod = topo_mod_lookup(thp, name, 1)) != NULL) {
1263062Scindi if (mod->tm_info->tmi_version != version) {
1273062Scindi topo_mod_rele(mod);
1283062Scindi (void) topo_mod_seterrno(pmod, ETOPO_MOD_VER);
1293062Scindi return (NULL);
1303062Scindi }
1311414Scindi return (mod);
1321414Scindi }
1331414Scindi
1343062Scindi (void) snprintf(file, PLUGIN_PATH_LEN, "%s/%s.so",
1353062Scindi PLUGIN_PATH, name);
1363062Scindi path = topo_search_path(pmod, thp->th_rootdir, (const char *)file);
1373062Scindi if (path == NULL ||
1383062Scindi (mod = topo_modhash_load(thp, name, path, &topo_rtld_ops, version))
1393062Scindi == NULL) { /* returned with mod held */
1403062Scindi topo_mod_strfree(pmod, path);
1413062Scindi (void) topo_mod_seterrno(pmod, topo_hdl_errno(thp) ?
1423062Scindi topo_hdl_errno(thp) : ETOPO_MOD_NOENT);
1433062Scindi return (NULL);
1441414Scindi }
1451414Scindi
1463062Scindi topo_mod_strfree(pmod, path);
1471414Scindi
1481414Scindi return (mod);
1491414Scindi }
1501414Scindi
1511414Scindi void
topo_mod_unload(topo_mod_t * mod)1521414Scindi topo_mod_unload(topo_mod_t *mod)
1531414Scindi {
1541414Scindi topo_mod_rele(mod);
1551414Scindi }
1561414Scindi
1571414Scindi static int
set_register_error(topo_mod_t * mod,int err)1581414Scindi set_register_error(topo_mod_t *mod, int err)
1591414Scindi {
1601414Scindi if (mod->tm_info != NULL)
1611414Scindi topo_mod_unregister(mod);
1621414Scindi
1633062Scindi topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR,
1643062Scindi "module registration failed for %s: %s\n",
1651414Scindi mod->tm_name, topo_strerror(err));
1661414Scindi
1671414Scindi return (topo_mod_seterrno(mod, err));
1681414Scindi }
1691414Scindi
1701414Scindi int
topo_mod_register(topo_mod_t * mod,const topo_modinfo_t * mip,topo_version_t version)1713062Scindi topo_mod_register(topo_mod_t *mod, const topo_modinfo_t *mip,
1723062Scindi topo_version_t version)
1731414Scindi {
1741414Scindi
1751414Scindi assert(!(mod->tm_flags & TOPO_MOD_FINI ||
1761414Scindi mod->tm_flags & TOPO_MOD_REG));
1771414Scindi
1783062Scindi if (version != TOPO_VERSION)
1793062Scindi return (set_register_error(mod, EMOD_VER_ABI));
1801414Scindi
1814087Scindi if ((mod->tm_info = topo_mod_zalloc(mod, sizeof (topo_imodinfo_t)))
1821414Scindi == NULL)
1833062Scindi return (set_register_error(mod, EMOD_NOMEM));
1843062Scindi if ((mod->tm_info->tmi_ops = topo_mod_alloc(mod,
1853062Scindi sizeof (topo_modops_t))) == NULL)
1863062Scindi return (set_register_error(mod, EMOD_NOMEM));
1871414Scindi
1881414Scindi mod->tm_info->tmi_desc = topo_mod_strdup(mod, mip->tmi_desc);
1891414Scindi if (mod->tm_info->tmi_desc == NULL)
1903062Scindi return (set_register_error(mod, EMOD_NOMEM));
1913062Scindi
1923062Scindi mod->tm_info->tmi_scheme = topo_mod_strdup(mod, mip->tmi_scheme);
1933062Scindi if (mod->tm_info->tmi_scheme == NULL)
1943062Scindi return (set_register_error(mod, EMOD_NOMEM));
1953062Scindi
1961414Scindi
1971414Scindi mod->tm_info->tmi_version = (topo_version_t)mip->tmi_version;
1983062Scindi mod->tm_info->tmi_ops->tmo_enum = mip->tmi_ops->tmo_enum;
1993062Scindi mod->tm_info->tmi_ops->tmo_release = mip->tmi_ops->tmo_release;
2001414Scindi
2011414Scindi mod->tm_flags |= TOPO_MOD_REG;
2021414Scindi
2033062Scindi topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC,
2043062Scindi "registration succeeded for %s\n", mod->tm_name);
2051414Scindi
2061414Scindi return (0);
2071414Scindi }
2081414Scindi
2091414Scindi void
topo_mod_unregister(topo_mod_t * mod)2101414Scindi topo_mod_unregister(topo_mod_t *mod)
2111414Scindi {
2121414Scindi if (mod->tm_info == NULL)
2131414Scindi return;
2141414Scindi
2151414Scindi assert(!(mod->tm_flags & TOPO_MOD_FINI));
2161414Scindi
2171414Scindi mod->tm_flags &= ~TOPO_MOD_REG;
2181414Scindi
2191414Scindi if (mod->tm_info == NULL)
2201414Scindi return;
2211414Scindi
2223062Scindi if (mod->tm_info->tmi_ops != NULL)
2233062Scindi topo_mod_free(mod, mod->tm_info->tmi_ops,
2243062Scindi sizeof (topo_modops_t));
2251414Scindi if (mod->tm_info->tmi_desc != NULL)
2261414Scindi topo_mod_strfree(mod, mod->tm_info->tmi_desc);
2273062Scindi if (mod->tm_info->tmi_scheme != NULL)
2283062Scindi topo_mod_strfree(mod, mod->tm_info->tmi_scheme);
2291414Scindi
2303062Scindi topo_mod_free(mod, mod->tm_info, sizeof (topo_imodinfo_t));
2311414Scindi
2321414Scindi mod->tm_info = NULL;
2331414Scindi }
2341414Scindi
2351414Scindi int
topo_mod_enumerate(topo_mod_t * mod,tnode_t * node,const char * enum_name,const char * name,topo_instance_t min,topo_instance_t max,void * data)2361414Scindi topo_mod_enumerate(topo_mod_t *mod, tnode_t *node, const char *enum_name,
2373062Scindi const char *name, topo_instance_t min, topo_instance_t max, void *data)
2381414Scindi {
2391414Scindi int err = 0;
2401414Scindi topo_mod_t *enum_mod;
2411414Scindi
2421414Scindi assert(mod->tm_flags & TOPO_MOD_REG);
2431414Scindi
2443062Scindi if ((enum_mod = topo_mod_lookup(mod->tm_hdl, enum_name, 0)) == NULL)
2453062Scindi return (topo_mod_seterrno(mod, EMOD_MOD_NOENT));
2461414Scindi
2471414Scindi topo_node_hold(node);
2481414Scindi
2493062Scindi topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC, "module %s enumerating "
2503062Scindi "node %s=%d\n", (char *)mod->tm_name, (char *)node->tn_name,
2513062Scindi node->tn_instance);
2521414Scindi
2531414Scindi topo_mod_enter(enum_mod);
2543062Scindi err = enum_mod->tm_info->tmi_ops->tmo_enum(enum_mod, node, name, min,
2553062Scindi max, enum_mod->tm_priv, data);
2561414Scindi topo_mod_exit(enum_mod);
2571414Scindi
2581414Scindi if (err != 0) {
2593062Scindi (void) topo_mod_seterrno(mod, EMOD_UKNOWN_ENUM);
2601414Scindi
2613062Scindi topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR,
2623062Scindi "module %s failed enumeration for "
2631414Scindi " node %s=%d\n", (char *)mod->tm_name,
2641414Scindi (char *)node->tn_name, node->tn_instance);
2651414Scindi
2661414Scindi topo_node_rele(node);
2671414Scindi return (-1);
2681414Scindi }
2691414Scindi
2701414Scindi topo_node_rele(node);
2711414Scindi
2721414Scindi return (0);
2731414Scindi }
2741414Scindi
2753062Scindi int
topo_mod_enummap(topo_mod_t * mod,tnode_t * node,const char * name,const char * scheme)2763062Scindi topo_mod_enummap(topo_mod_t *mod, tnode_t *node, const char *name,
2773062Scindi const char *scheme)
2783062Scindi {
2795068Srobj return (topo_file_load(mod, node, (char *)name, (char *)scheme, 0));
2803062Scindi }
2813062Scindi
2823062Scindi static nvlist_t *
set_fmri_err(topo_mod_t * mod,int err)2833062Scindi set_fmri_err(topo_mod_t *mod, int err)
2843062Scindi {
2853062Scindi (void) topo_mod_seterrno(mod, err);
2863062Scindi return (NULL);
2873062Scindi }
2883062Scindi
2893062Scindi nvlist_t *
topo_mod_hcfmri(topo_mod_t * mod,tnode_t * pnode,int version,const char * name,topo_instance_t inst,nvlist_t * hc_specific,nvlist_t * auth,const char * part,const char * rev,const char * serial)2903062Scindi topo_mod_hcfmri(topo_mod_t *mod, tnode_t *pnode, int version, const char *name,
2913062Scindi topo_instance_t inst, nvlist_t *hc_specific, nvlist_t *auth,
2923062Scindi const char *part, const char *rev, const char *serial)
2931414Scindi {
2943062Scindi int err;
2953062Scindi nvlist_t *pfmri = NULL, *fmri = NULL, *args = NULL;
2963062Scindi nvlist_t *nfp = NULL;
2977349SAdrian.Frost@Sun.COM char *lpart, *lrev, *lserial;
2983062Scindi
2993062Scindi if (version != FM_HC_SCHEME_VERSION)
3003062Scindi return (set_fmri_err(mod, EMOD_FMRI_VERSION));
3013062Scindi
3023062Scindi /*
3033062Scindi * Do we have any args to pass?
3043062Scindi */
3053062Scindi if (pnode != NULL || auth != NULL || part != NULL || rev != NULL ||
3063062Scindi serial != NULL || hc_specific != NULL) {
3073062Scindi if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
3084198Seschrock return (set_fmri_err(mod, EMOD_FMRI_NVL));
3093062Scindi }
3103062Scindi
3113062Scindi if (pnode != NULL) {
3124328Scindi if (topo_node_resource(pnode, &pfmri, &err) < 0) {
3134328Scindi nvlist_free(args);
3143062Scindi return (set_fmri_err(mod, EMOD_NVL_INVAL));
3154328Scindi }
3163062Scindi
3173062Scindi if (nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT,
3183062Scindi pfmri) != 0) {
3193062Scindi nvlist_free(pfmri);
3203062Scindi nvlist_free(args);
3213062Scindi return (set_fmri_err(mod, EMOD_FMRI_NVL));
3223062Scindi }
3233062Scindi nvlist_free(pfmri);
3243062Scindi }
3253062Scindi
3263062Scindi /*
3273062Scindi * Add optional payload
3283062Scindi */
3293062Scindi if (auth != NULL)
3303062Scindi (void) nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_AUTH, auth);
3317349SAdrian.Frost@Sun.COM if (part != NULL) {
3327349SAdrian.Frost@Sun.COM lpart = topo_cleanup_auth_str(mod->tm_hdl, part);
3337349SAdrian.Frost@Sun.COM if (lpart != NULL) {
3347349SAdrian.Frost@Sun.COM (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_PART,
3357349SAdrian.Frost@Sun.COM lpart);
3367349SAdrian.Frost@Sun.COM topo_hdl_free(mod->tm_hdl, lpart, strlen(lpart) + 1);
3377349SAdrian.Frost@Sun.COM } else {
3387349SAdrian.Frost@Sun.COM (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_PART,
3399104SAdrian.Frost@Sun.COM "");
3407349SAdrian.Frost@Sun.COM }
3417349SAdrian.Frost@Sun.COM }
3427349SAdrian.Frost@Sun.COM if (rev != NULL) {
3437349SAdrian.Frost@Sun.COM lrev = topo_cleanup_auth_str(mod->tm_hdl, rev);
3447349SAdrian.Frost@Sun.COM if (lrev != NULL) {
3457349SAdrian.Frost@Sun.COM (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_REV,
3467349SAdrian.Frost@Sun.COM lrev);
3477349SAdrian.Frost@Sun.COM topo_hdl_free(mod->tm_hdl, lrev, strlen(lrev) + 1);
3487349SAdrian.Frost@Sun.COM } else {
3497349SAdrian.Frost@Sun.COM (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_REV,
3509104SAdrian.Frost@Sun.COM "");
3517349SAdrian.Frost@Sun.COM }
3527349SAdrian.Frost@Sun.COM }
3537349SAdrian.Frost@Sun.COM if (serial != NULL) {
3547349SAdrian.Frost@Sun.COM lserial = topo_cleanup_auth_str(mod->tm_hdl, serial);
3557349SAdrian.Frost@Sun.COM if (lserial != NULL) {
3567349SAdrian.Frost@Sun.COM (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_SER,
3577349SAdrian.Frost@Sun.COM lserial);
3587349SAdrian.Frost@Sun.COM topo_hdl_free(mod->tm_hdl, lserial,
3597349SAdrian.Frost@Sun.COM strlen(lserial) + 1);
3607349SAdrian.Frost@Sun.COM } else {
3617349SAdrian.Frost@Sun.COM (void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_SER,
3629104SAdrian.Frost@Sun.COM "");
3637349SAdrian.Frost@Sun.COM }
3647349SAdrian.Frost@Sun.COM }
3653062Scindi if (hc_specific != NULL)
3663062Scindi (void) nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_HCS,
3673062Scindi hc_specific);
3683062Scindi
3693062Scindi if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_HC, name, inst,
3703062Scindi args, &err)) == NULL) {
3713062Scindi nvlist_free(args);
3723062Scindi return (set_fmri_err(mod, err));
3733062Scindi }
3743062Scindi
3753062Scindi nvlist_free(args);
3763062Scindi
3773062Scindi (void) topo_mod_nvdup(mod, fmri, &nfp);
3783062Scindi nvlist_free(fmri);
3793062Scindi
3803062Scindi return (nfp);
3813062Scindi }
3823062Scindi
3833062Scindi nvlist_t *
topo_mod_devfmri(topo_mod_t * mod,int version,const char * dev_path,const char * devid)3843062Scindi topo_mod_devfmri(topo_mod_t *mod, int version, const char *dev_path,
3853062Scindi const char *devid)
3863062Scindi {
3873062Scindi int err;
3883062Scindi nvlist_t *fmri, *args;
3893062Scindi nvlist_t *nfp = NULL;
3903062Scindi
3913062Scindi if (version != FM_DEV_SCHEME_VERSION)
3923062Scindi return (set_fmri_err(mod, EMOD_FMRI_VERSION));
3933062Scindi
3943062Scindi if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
3953062Scindi return (set_fmri_err(mod, EMOD_FMRI_NVL));
3963062Scindi
3973062Scindi if (nvlist_add_string(args, FM_FMRI_DEV_PATH, dev_path) != 0) {
3983062Scindi nvlist_free(args);
3993062Scindi return (set_fmri_err(mod, EMOD_FMRI_NVL));
4003062Scindi }
4013062Scindi
4023062Scindi (void) nvlist_add_string(args, FM_FMRI_DEV_ID, devid);
4033062Scindi
4043062Scindi if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_DEV,
4053062Scindi FM_FMRI_SCHEME_DEV, 0, args, &err)) == NULL) {
4063062Scindi nvlist_free(args);
4073062Scindi return (set_fmri_err(mod, err));
4083062Scindi }
4093062Scindi
4103062Scindi nvlist_free(args);
4113062Scindi
4123062Scindi (void) topo_mod_nvdup(mod, fmri, &nfp);
4133062Scindi nvlist_free(fmri);
4143062Scindi
4153062Scindi return (nfp);
4161414Scindi }
4171414Scindi
4183062Scindi nvlist_t *
topo_mod_cpufmri(topo_mod_t * mod,int version,uint32_t cpu_id,uint8_t cpumask,const char * serial)4193062Scindi topo_mod_cpufmri(topo_mod_t *mod, int version, uint32_t cpu_id, uint8_t cpumask,
4203062Scindi const char *serial)
4213062Scindi {
4223062Scindi int err;
4233062Scindi nvlist_t *fmri = NULL, *args = NULL;
4243062Scindi nvlist_t *nfp = NULL;
4253062Scindi
4263062Scindi if (version != FM_CPU_SCHEME_VERSION)
4273062Scindi return (set_fmri_err(mod, EMOD_FMRI_VERSION));
4283062Scindi
4293062Scindi if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
4303062Scindi return (set_fmri_err(mod, EMOD_FMRI_NVL));
4313062Scindi
4323062Scindi if (nvlist_add_uint32(args, FM_FMRI_CPU_ID, cpu_id) != 0) {
4333062Scindi nvlist_free(args);
4343062Scindi return (set_fmri_err(mod, EMOD_FMRI_NVL));
4353062Scindi }
4363062Scindi
4373062Scindi /*
4383062Scindi * Add optional payload
4393062Scindi */
4403062Scindi (void) nvlist_add_uint8(args, FM_FMRI_CPU_MASK, cpumask);
4413062Scindi (void) nvlist_add_string(args, FM_FMRI_CPU_SERIAL_ID, serial);
4423062Scindi
4433062Scindi if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_CPU,
4443062Scindi FM_FMRI_SCHEME_CPU, 0, args, &err)) == NULL) {
4453062Scindi nvlist_free(args);
4463062Scindi return (set_fmri_err(mod, err));
4473062Scindi }
4483062Scindi
4493062Scindi nvlist_free(args);
4503062Scindi
4513062Scindi (void) topo_mod_nvdup(mod, fmri, &nfp);
4523062Scindi nvlist_free(fmri);
4533062Scindi
4543062Scindi return (nfp);
4553062Scindi }
4563062Scindi
4573062Scindi nvlist_t *
topo_mod_memfmri(topo_mod_t * mod,int version,uint64_t pa,uint64_t offset,const char * unum,int flags)4583062Scindi topo_mod_memfmri(topo_mod_t *mod, int version, uint64_t pa, uint64_t offset,
4593062Scindi const char *unum, int flags)
4603062Scindi {
4613062Scindi int err;
4623062Scindi nvlist_t *args = NULL, *fmri = NULL;
4633062Scindi nvlist_t *nfp = NULL;
4643062Scindi
4653062Scindi if (version != FM_MEM_SCHEME_VERSION)
4663062Scindi return (set_fmri_err(mod, EMOD_FMRI_VERSION));
4673062Scindi
4683062Scindi if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
4693062Scindi return (set_fmri_err(mod, EMOD_FMRI_NVL));
4703062Scindi
4713062Scindi err = nvlist_add_string(args, FM_FMRI_MEM_UNUM, unum);
4723062Scindi nvlist_free(args);
4733062Scindi if (flags & TOPO_MEMFMRI_PA)
4743062Scindi err |= nvlist_add_uint64(args, FM_FMRI_MEM_PHYSADDR, pa);
4753062Scindi if (flags & TOPO_MEMFMRI_OFFSET)
4763062Scindi err |= nvlist_add_uint64(args, FM_FMRI_MEM_OFFSET, offset);
4773062Scindi
4783062Scindi if (err != 0) {
4793062Scindi nvlist_free(args);
4803062Scindi return (set_fmri_err(mod, EMOD_FMRI_NVL));
4813062Scindi }
4823062Scindi
4833062Scindi if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_MEM,
4843062Scindi FM_FMRI_SCHEME_MEM, 0, args, &err)) == NULL) {
4853062Scindi nvlist_free(args);
4863062Scindi return (set_fmri_err(mod, err));
4873062Scindi }
4883062Scindi
4893062Scindi nvlist_free(args);
4903062Scindi
4913062Scindi (void) topo_mod_nvdup(mod, fmri, &nfp);
4923062Scindi nvlist_free(fmri);
4933062Scindi
4943062Scindi return (nfp);
4953062Scindi
4963062Scindi }
4973062Scindi
4983062Scindi nvlist_t *
topo_mod_pkgfmri(topo_mod_t * mod,int version,const char * path)4993062Scindi topo_mod_pkgfmri(topo_mod_t *mod, int version, const char *path)
5001414Scindi {
5013062Scindi int err;
5023062Scindi nvlist_t *fmri = NULL, *args = NULL;
5033062Scindi nvlist_t *nfp = NULL;
5043062Scindi
5053062Scindi if (version != FM_PKG_SCHEME_VERSION)
5063062Scindi return (set_fmri_err(mod, EMOD_FMRI_VERSION));
5073062Scindi
5083062Scindi if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
5093062Scindi return (set_fmri_err(mod, EMOD_FMRI_NVL));
5103062Scindi
5113062Scindi if (nvlist_add_string(args, "path", path) != 0) {
5123062Scindi nvlist_free(args);
5133062Scindi return (set_fmri_err(mod, EMOD_FMRI_NVL));
5143062Scindi }
5153062Scindi
5163323Scindi if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_PKG,
5173323Scindi FM_FMRI_SCHEME_PKG, 0, args, &err)) == NULL) {
5183062Scindi nvlist_free(args);
5193062Scindi return (set_fmri_err(mod, err));
5203062Scindi }
5213062Scindi
5223062Scindi nvlist_free(args);
5233062Scindi
5243062Scindi (void) topo_mod_nvdup(mod, fmri, &nfp);
5253062Scindi nvlist_free(fmri);
5263062Scindi
5273062Scindi return (nfp);
5283062Scindi }
5293062Scindi
5303062Scindi nvlist_t *
topo_mod_modfmri(topo_mod_t * mod,int version,const char * driver)5313062Scindi topo_mod_modfmri(topo_mod_t *mod, int version, const char *driver)
5323062Scindi {
5333062Scindi int err;
5343062Scindi nvlist_t *fmri = NULL, *args = NULL;
5353062Scindi nvlist_t *nfp = NULL;
5363062Scindi
5373062Scindi if (version != FM_MOD_SCHEME_VERSION)
5383062Scindi return (set_fmri_err(mod, EMOD_FMRI_VERSION));
5393062Scindi
5403062Scindi if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
5413062Scindi return (set_fmri_err(mod, EMOD_FMRI_NVL));
5423062Scindi
5433062Scindi if (nvlist_add_string(args, "DRIVER", driver) != 0) {
5443062Scindi nvlist_free(args);
5453062Scindi return (set_fmri_err(mod, EMOD_FMRI_NVL));
5463062Scindi }
5473062Scindi
5483323Scindi if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_MOD,
5493323Scindi FM_FMRI_SCHEME_MOD, 0, args, &err)) == NULL) {
5503062Scindi nvlist_free(args);
5513062Scindi return (set_fmri_err(mod, err));
5523062Scindi }
5533062Scindi
5543062Scindi nvlist_free(args);
5553062Scindi
5563062Scindi (void) topo_mod_nvdup(mod, fmri, &nfp);
5573062Scindi nvlist_free(fmri);
5583062Scindi
5593062Scindi return (nfp);
5603062Scindi }
5613062Scindi
562*12967Sgavin.maltby@oracle.com #define _SWFMRI_ADD_STRING(nvl, name, val) \
563*12967Sgavin.maltby@oracle.com ((val) ? (nvlist_add_string(nvl, name, val) != 0) : 0)
564*12967Sgavin.maltby@oracle.com
565*12967Sgavin.maltby@oracle.com nvlist_t *
topo_mod_swfmri(topo_mod_t * mod,int version,char * obj_path,char * obj_root,nvlist_t * obj_pkg,char * site_token,char * site_module,char * site_file,char * site_func,int64_t site_line,char * ctxt_origin,char * ctxt_execname,int64_t ctxt_pid,char * ctxt_zone,int64_t ctxt_ctid,char ** ctxt_stack,uint_t ctxt_stackdepth)566*12967Sgavin.maltby@oracle.com topo_mod_swfmri(topo_mod_t *mod, int version,
567*12967Sgavin.maltby@oracle.com char *obj_path, char *obj_root, nvlist_t *obj_pkg,
568*12967Sgavin.maltby@oracle.com char *site_token, char *site_module, char *site_file, char *site_func,
569*12967Sgavin.maltby@oracle.com int64_t site_line, char *ctxt_origin, char *ctxt_execname,
570*12967Sgavin.maltby@oracle.com int64_t ctxt_pid, char *ctxt_zone, int64_t ctxt_ctid,
571*12967Sgavin.maltby@oracle.com char **ctxt_stack, uint_t ctxt_stackdepth)
572*12967Sgavin.maltby@oracle.com {
573*12967Sgavin.maltby@oracle.com nvlist_t *fmri, *args;
574*12967Sgavin.maltby@oracle.com nvlist_t *nfp = NULL;
575*12967Sgavin.maltby@oracle.com int err;
576*12967Sgavin.maltby@oracle.com
577*12967Sgavin.maltby@oracle.com if (version != FM_SW_SCHEME_VERSION)
578*12967Sgavin.maltby@oracle.com return (set_fmri_err(mod, EMOD_FMRI_VERSION));
579*12967Sgavin.maltby@oracle.com
580*12967Sgavin.maltby@oracle.com if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
581*12967Sgavin.maltby@oracle.com return (set_fmri_err(mod, EMOD_FMRI_NVL));
582*12967Sgavin.maltby@oracle.com
583*12967Sgavin.maltby@oracle.com err = 0;
584*12967Sgavin.maltby@oracle.com err |= _SWFMRI_ADD_STRING(args, "obj_path", obj_path);
585*12967Sgavin.maltby@oracle.com err |= _SWFMRI_ADD_STRING(args, "obj_root", obj_root);
586*12967Sgavin.maltby@oracle.com if (obj_pkg)
587*12967Sgavin.maltby@oracle.com err |= nvlist_add_nvlist(args, "obj_pkg", obj_pkg);
588*12967Sgavin.maltby@oracle.com
589*12967Sgavin.maltby@oracle.com err |= _SWFMRI_ADD_STRING(args, "site_token", site_token);
590*12967Sgavin.maltby@oracle.com err |= _SWFMRI_ADD_STRING(args, "site_module", site_module);
591*12967Sgavin.maltby@oracle.com err |= _SWFMRI_ADD_STRING(args, "site_file", site_file);
592*12967Sgavin.maltby@oracle.com err |= _SWFMRI_ADD_STRING(args, "site_func", site_func);
593*12967Sgavin.maltby@oracle.com if (site_line != -1)
594*12967Sgavin.maltby@oracle.com err |= nvlist_add_int64(args, "site_line", site_line);
595*12967Sgavin.maltby@oracle.com
596*12967Sgavin.maltby@oracle.com err |= _SWFMRI_ADD_STRING(args, "ctxt_origin", ctxt_origin);
597*12967Sgavin.maltby@oracle.com err |= _SWFMRI_ADD_STRING(args, "ctxt_execname", ctxt_execname);
598*12967Sgavin.maltby@oracle.com if (ctxt_pid != -1)
599*12967Sgavin.maltby@oracle.com err |= nvlist_add_int64(args, "ctxt_pid", ctxt_pid);
600*12967Sgavin.maltby@oracle.com err |= _SWFMRI_ADD_STRING(args, "ctxt_zone", ctxt_zone);
601*12967Sgavin.maltby@oracle.com if (ctxt_ctid != -1)
602*12967Sgavin.maltby@oracle.com err |= nvlist_add_int64(args, "ctxt_ctid", ctxt_ctid);
603*12967Sgavin.maltby@oracle.com if (ctxt_stack != NULL && ctxt_stackdepth != 0)
604*12967Sgavin.maltby@oracle.com err |= nvlist_add_string_array(args, "stack", ctxt_stack,
605*12967Sgavin.maltby@oracle.com ctxt_stackdepth);
606*12967Sgavin.maltby@oracle.com
607*12967Sgavin.maltby@oracle.com if (err) {
608*12967Sgavin.maltby@oracle.com nvlist_free(args);
609*12967Sgavin.maltby@oracle.com return (set_fmri_err(mod, EMOD_FMRI_NVL));
610*12967Sgavin.maltby@oracle.com }
611*12967Sgavin.maltby@oracle.com
612*12967Sgavin.maltby@oracle.com if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_SW,
613*12967Sgavin.maltby@oracle.com FM_FMRI_SCHEME_SW, 0, args, &err)) == NULL) {
614*12967Sgavin.maltby@oracle.com nvlist_free(args);
615*12967Sgavin.maltby@oracle.com return (set_fmri_err(mod, err));
616*12967Sgavin.maltby@oracle.com }
617*12967Sgavin.maltby@oracle.com
618*12967Sgavin.maltby@oracle.com nvlist_free(args);
619*12967Sgavin.maltby@oracle.com
620*12967Sgavin.maltby@oracle.com (void) topo_mod_nvdup(mod, fmri, &nfp);
621*12967Sgavin.maltby@oracle.com nvlist_free(fmri);
622*12967Sgavin.maltby@oracle.com
623*12967Sgavin.maltby@oracle.com return (nfp);
624*12967Sgavin.maltby@oracle.com }
625*12967Sgavin.maltby@oracle.com
6263062Scindi int
topo_mod_str2nvl(topo_mod_t * mod,const char * fmristr,nvlist_t ** fmri)6273062Scindi topo_mod_str2nvl(topo_mod_t *mod, const char *fmristr, nvlist_t **fmri)
6283062Scindi {
6293062Scindi int err;
6303062Scindi nvlist_t *np = NULL;
6313062Scindi
6323062Scindi if (topo_fmri_str2nvl(mod->tm_hdl, fmristr, &np, &err) < 0)
6333062Scindi return (topo_mod_seterrno(mod, err));
6343062Scindi
6353062Scindi if (topo_mod_nvdup(mod, np, fmri) < 0) {
6363062Scindi nvlist_free(np);
6373062Scindi return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
6383062Scindi }
6393062Scindi
6403062Scindi nvlist_free(np);
6413062Scindi
6423062Scindi return (0);
6433062Scindi }
6443062Scindi
6453062Scindi int
topo_mod_nvl2str(topo_mod_t * mod,nvlist_t * fmri,char ** fmristr)6463062Scindi topo_mod_nvl2str(topo_mod_t *mod, nvlist_t *fmri, char **fmristr)
6473062Scindi {
6483062Scindi int err;
6493062Scindi char *sp;
6503062Scindi
6513062Scindi if (topo_fmri_nvl2str(mod->tm_hdl, fmri, &sp, &err) < 0)
6523062Scindi return (topo_mod_seterrno(mod, err));
6533062Scindi
6543062Scindi if ((*fmristr = topo_mod_strdup(mod, sp)) == NULL) {
6553062Scindi topo_hdl_strfree(mod->tm_hdl, sp);
6563062Scindi return (topo_mod_seterrno(mod, EMOD_NOMEM));
6573062Scindi }
6583062Scindi
6593062Scindi topo_hdl_strfree(mod->tm_hdl, sp);
6603062Scindi
6613062Scindi return (0);
6621414Scindi }
6631414Scindi
6641414Scindi void *
topo_mod_getspecific(topo_mod_t * mod)6653062Scindi topo_mod_getspecific(topo_mod_t *mod)
6661414Scindi {
6671414Scindi return (mod->tm_priv);
6681414Scindi }
6691414Scindi
6701414Scindi void
topo_mod_setspecific(topo_mod_t * mod,void * data)6713062Scindi topo_mod_setspecific(topo_mod_t *mod, void *data)
6723062Scindi {
6733062Scindi mod->tm_priv = data;
6743062Scindi }
6753062Scindi
6763062Scindi void
topo_mod_setdebug(topo_mod_t * mod)6773062Scindi topo_mod_setdebug(topo_mod_t *mod)
6783062Scindi {
6793062Scindi mod->tm_debug = 1;
6803062Scindi }
6813062Scindi
6826070Srobj ipmi_handle_t *
topo_mod_ipmi_hold(topo_mod_t * mod)6837462SEric.Schrock@Sun.COM topo_mod_ipmi_hold(topo_mod_t *mod)
6846070Srobj {
6856070Srobj topo_hdl_t *thp = mod->tm_hdl;
6866070Srobj int err;
6876070Srobj char *errmsg;
6886070Srobj
6897462SEric.Schrock@Sun.COM (void) pthread_mutex_lock(&thp->th_ipmi_lock);
6907462SEric.Schrock@Sun.COM if (thp->th_ipmi == NULL) {
69111756SRobert.Johnston@Sun.COM if ((thp->th_ipmi = ipmi_open(&err, &errmsg, IPMI_TRANSPORT_BMC,
69211756SRobert.Johnston@Sun.COM NULL)) == NULL) {
6936070Srobj topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR,
6946070Srobj "ipmi_open() failed: %s (ipmi errno=%d)", errmsg,
6956070Srobj err);
6967462SEric.Schrock@Sun.COM (void) pthread_mutex_unlock(&thp->th_ipmi_lock);
6977462SEric.Schrock@Sun.COM }
6987462SEric.Schrock@Sun.COM }
6997462SEric.Schrock@Sun.COM
7006070Srobj
7016070Srobj return (thp->th_ipmi);
7026070Srobj }
7036070Srobj
7047462SEric.Schrock@Sun.COM void
topo_mod_ipmi_rele(topo_mod_t * mod)7057462SEric.Schrock@Sun.COM topo_mod_ipmi_rele(topo_mod_t *mod)
7067462SEric.Schrock@Sun.COM {
7077462SEric.Schrock@Sun.COM topo_hdl_t *thp = mod->tm_hdl;
7087462SEric.Schrock@Sun.COM
7097462SEric.Schrock@Sun.COM (void) pthread_mutex_unlock(&thp->th_ipmi_lock);
7107462SEric.Schrock@Sun.COM }
7117462SEric.Schrock@Sun.COM
7128740SSean.Ye@Sun.COM di_node_t
topo_mod_devinfo(topo_mod_t * mod)7138740SSean.Ye@Sun.COM topo_mod_devinfo(topo_mod_t *mod)
7148740SSean.Ye@Sun.COM {
7158740SSean.Ye@Sun.COM return (topo_hdl_devinfo(mod->tm_hdl));
7168740SSean.Ye@Sun.COM }
7178740SSean.Ye@Sun.COM
7189632SEric.Schrock@Sun.COM smbios_hdl_t *
topo_mod_smbios(topo_mod_t * mod)7199632SEric.Schrock@Sun.COM topo_mod_smbios(topo_mod_t *mod)
7209632SEric.Schrock@Sun.COM {
7219632SEric.Schrock@Sun.COM topo_hdl_t *thp = mod->tm_hdl;
7229632SEric.Schrock@Sun.COM
7239632SEric.Schrock@Sun.COM if (thp->th_smbios == NULL)
7249632SEric.Schrock@Sun.COM thp->th_smbios = smbios_open(NULL, SMB_VERSION, 0, NULL);
7259632SEric.Schrock@Sun.COM
7269632SEric.Schrock@Sun.COM return (thp->th_smbios);
7279632SEric.Schrock@Sun.COM }
7289632SEric.Schrock@Sun.COM
7293062Scindi di_prom_handle_t
topo_mod_prominfo(topo_mod_t * mod)7303062Scindi topo_mod_prominfo(topo_mod_t *mod)
7313062Scindi {
7328740SSean.Ye@Sun.COM return (topo_hdl_prominfo(mod->tm_hdl));
7331414Scindi }
7341414Scindi
7351414Scindi void
topo_mod_clrdebug(topo_mod_t * mod)7361414Scindi topo_mod_clrdebug(topo_mod_t *mod)
7371414Scindi {
7381414Scindi mod->tm_debug = 0;
7391414Scindi }
7401414Scindi
7411414Scindi /*PRINTFLIKE2*/
7421414Scindi void
topo_mod_dprintf(topo_mod_t * mod,const char * format,...)7431414Scindi topo_mod_dprintf(topo_mod_t *mod, const char *format, ...)
7441414Scindi {
7453062Scindi va_list alist;
7463062Scindi
7473062Scindi if (mod->tm_debug == 0)
7483062Scindi return;
7493062Scindi
7503062Scindi va_start(alist, format);
7513062Scindi topo_vdprintf(mod->tm_hdl, TOPO_DBG_MOD, (const char *)mod->tm_name,
7523062Scindi format, alist);
7533062Scindi va_end(alist);
7543062Scindi }
7553062Scindi
7563062Scindi static char *
topo_mod_product(topo_mod_t * mod)7573062Scindi topo_mod_product(topo_mod_t *mod)
7583062Scindi {
7593062Scindi return (topo_mod_strdup(mod, mod->tm_hdl->th_product));
7603062Scindi }
7613062Scindi
7623062Scindi static char *
topo_mod_server(topo_mod_t * mod)7633062Scindi topo_mod_server(topo_mod_t *mod)
7643062Scindi {
7653062Scindi static struct utsname uts;
7663062Scindi
7673062Scindi (void) uname(&uts);
7683062Scindi return (topo_mod_strdup(mod, uts.nodename));
7693062Scindi }
7703062Scindi
7713062Scindi static char *
topo_mod_psn(topo_mod_t * mod)77210462SSean.Ye@Sun.COM topo_mod_psn(topo_mod_t *mod)
77310462SSean.Ye@Sun.COM {
77410462SSean.Ye@Sun.COM smbios_hdl_t *shp;
77510462SSean.Ye@Sun.COM const char *psn;
77610462SSean.Ye@Sun.COM
77710462SSean.Ye@Sun.COM if ((shp = topo_mod_smbios(mod)) == NULL ||
77810462SSean.Ye@Sun.COM (psn = smbios_psn(shp)) == NULL)
77910462SSean.Ye@Sun.COM return (NULL);
78010462SSean.Ye@Sun.COM
78110462SSean.Ye@Sun.COM return (topo_cleanup_auth_str(mod->tm_hdl, psn));
78210462SSean.Ye@Sun.COM }
78310462SSean.Ye@Sun.COM
78410462SSean.Ye@Sun.COM static char *
topo_mod_csn(topo_mod_t * mod)7853062Scindi topo_mod_csn(topo_mod_t *mod)
7863062Scindi {
7873062Scindi char csn[MAXNAMELEN];
78810462SSean.Ye@Sun.COM smbios_hdl_t *shp;
7893062Scindi di_prom_handle_t promh = DI_PROM_HANDLE_NIL;
7903062Scindi di_node_t rooth = DI_NODE_NIL;
79110462SSean.Ye@Sun.COM const char *bufp;
7923062Scindi
7939632SEric.Schrock@Sun.COM if ((shp = topo_mod_smbios(mod)) != NULL) {
79410462SSean.Ye@Sun.COM bufp = smbios_csn(shp);
79510462SSean.Ye@Sun.COM if (bufp != NULL)
79610462SSean.Ye@Sun.COM (void) strlcpy(csn, bufp, MAXNAMELEN);
79710462SSean.Ye@Sun.COM else
7983062Scindi return (NULL);
7993062Scindi } else if ((rooth = topo_mod_devinfo(mod)) != DI_NODE_NIL &&
8003062Scindi (promh = topo_mod_prominfo(mod)) != DI_PROM_HANDLE_NIL) {
8013062Scindi if (di_prom_prop_lookup_bytes(promh, rooth, "chassis-sn",
8023062Scindi (unsigned char **)&bufp) != -1) {
8033062Scindi (void) strlcpy(csn, bufp, MAXNAMELEN);
8043062Scindi } else {
8053062Scindi return (NULL);
8063062Scindi }
8073062Scindi } else {
8083062Scindi return (NULL);
8091414Scindi }
8103062Scindi
8114198Seschrock return (topo_cleanup_auth_str(mod->tm_hdl, csn));
8121414Scindi }
8133062Scindi
8143062Scindi nvlist_t *
topo_mod_auth(topo_mod_t * mod,tnode_t * pnode)8153062Scindi topo_mod_auth(topo_mod_t *mod, tnode_t *pnode)
8163062Scindi {
8173062Scindi int err;
8183062Scindi char *prod = NULL;
8193062Scindi char *csn = NULL;
82010462SSean.Ye@Sun.COM char *psn = NULL;
8213062Scindi char *server = NULL;
8223062Scindi nvlist_t *auth;
8233062Scindi
8244328Scindi if ((err = topo_mod_nvalloc(mod, &auth, NV_UNIQUE_NAME)) != 0) {
8254328Scindi (void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);
8264328Scindi return (NULL);
8274328Scindi }
8284328Scindi
8293062Scindi (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY,
8303062Scindi FM_FMRI_AUTH_PRODUCT, &prod, &err);
8313062Scindi (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY,
83210462SSean.Ye@Sun.COM FM_FMRI_AUTH_PRODUCT_SN, &psn, &err);
83310462SSean.Ye@Sun.COM (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY,
8343062Scindi FM_FMRI_AUTH_CHASSIS, &csn, &err);
8353062Scindi (void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY,
8363062Scindi FM_FMRI_AUTH_SERVER, &server, &err);
8373062Scindi
8383062Scindi /*
8393062Scindi * Let's do this the hard way
8403062Scindi */
8413062Scindi if (prod == NULL)
8423062Scindi prod = topo_mod_product(mod);
8433062Scindi if (csn == NULL)
8443062Scindi csn = topo_mod_csn(mod);
84510462SSean.Ye@Sun.COM if (psn == NULL)
84610462SSean.Ye@Sun.COM psn = topo_mod_psn(mod);
8473062Scindi if (server == NULL) {
8483062Scindi server = topo_mod_server(mod);
8493062Scindi }
8503062Scindi
8513062Scindi /*
8523062Scindi * No luck, return NULL
8533062Scindi */
85410462SSean.Ye@Sun.COM if (!prod && !server && !csn && !psn) {
8554328Scindi nvlist_free(auth);
8563062Scindi return (NULL);
8573062Scindi }
8583062Scindi
8594328Scindi err = 0;
8603062Scindi if (prod != NULL) {
8613062Scindi err |= nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT, prod);
8623062Scindi topo_mod_strfree(mod, prod);
8633062Scindi }
86410462SSean.Ye@Sun.COM if (psn != NULL) {
86510462SSean.Ye@Sun.COM err |= nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT_SN, psn);
86610462SSean.Ye@Sun.COM topo_mod_strfree(mod, psn);
86710462SSean.Ye@Sun.COM }
8683062Scindi if (server != NULL) {
8693062Scindi err |= nvlist_add_string(auth, FM_FMRI_AUTH_SERVER, server);
8703062Scindi topo_mod_strfree(mod, server);
8713062Scindi }
8723062Scindi if (csn != NULL) {
8733062Scindi err |= nvlist_add_string(auth, FM_FMRI_AUTH_CHASSIS, csn);
8743062Scindi topo_mod_strfree(mod, csn);
8753062Scindi }
8763062Scindi
8773062Scindi if (err != 0) {
8783062Scindi nvlist_free(auth);
8793062Scindi (void) topo_mod_seterrno(mod, EMOD_NVL_INVAL);
8803062Scindi return (NULL);
8813062Scindi }
8823062Scindi
8833062Scindi return (auth);
8843062Scindi }
8854087Scindi
8864087Scindi topo_walk_t *
topo_mod_walk_init(topo_mod_t * mod,tnode_t * node,topo_mod_walk_cb_t cb_f,void * pdata,int * errp)8874087Scindi topo_mod_walk_init(topo_mod_t *mod, tnode_t *node, topo_mod_walk_cb_t cb_f,
8884087Scindi void *pdata, int *errp)
8894087Scindi {
8904087Scindi topo_walk_t *wp;
8914087Scindi topo_hdl_t *thp = mod->tm_hdl;
8924087Scindi
8934087Scindi if ((wp = topo_node_walk_init(thp, mod, node, (int (*)())cb_f, pdata,
8944087Scindi errp)) == NULL)
8954087Scindi return (NULL);
8964087Scindi
8974087Scindi return (wp);
8984087Scindi }
899