xref: /onnv-gate/usr/src/lib/fm/topo/libtopo/common/topo_mod.c (revision 12967:ab9ae749152f)
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