xref: /onnv-gate/usr/src/lib/scsi/libsmp/common/smp_plugin.c (revision 13093:48f2dbca79a2)
112126SHyon.Kim@Sun.COM /*
212126SHyon.Kim@Sun.COM  * CDDL HEADER START
312126SHyon.Kim@Sun.COM  *
412126SHyon.Kim@Sun.COM  * The contents of this file are subject to the terms of the
512126SHyon.Kim@Sun.COM  * Common Development and Distribution License (the "License").
612126SHyon.Kim@Sun.COM  * You may not use this file except in compliance with the License.
712126SHyon.Kim@Sun.COM  *
812126SHyon.Kim@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
912126SHyon.Kim@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1012126SHyon.Kim@Sun.COM  * See the License for the specific language governing permissions
1112126SHyon.Kim@Sun.COM  * and limitations under the License.
1212126SHyon.Kim@Sun.COM  *
1312126SHyon.Kim@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1412126SHyon.Kim@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1512126SHyon.Kim@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1612126SHyon.Kim@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1712126SHyon.Kim@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1812126SHyon.Kim@Sun.COM  *
1912126SHyon.Kim@Sun.COM  * CDDL HEADER END
2012126SHyon.Kim@Sun.COM  */
2112126SHyon.Kim@Sun.COM 
2212126SHyon.Kim@Sun.COM /*
2312126SHyon.Kim@Sun.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2412126SHyon.Kim@Sun.COM  */
2512126SHyon.Kim@Sun.COM 
2612126SHyon.Kim@Sun.COM #include <sys/types.h>
2712126SHyon.Kim@Sun.COM #include <sys/systeminfo.h>
2812126SHyon.Kim@Sun.COM #include <sys/scsi/generic/commands.h>
2912126SHyon.Kim@Sun.COM #include <sys/scsi/impl/commands.h>
3012126SHyon.Kim@Sun.COM 
3112126SHyon.Kim@Sun.COM #include <scsi/libsmp.h>
3212126SHyon.Kim@Sun.COM #include <scsi/libsmp_plugin.h>
3312126SHyon.Kim@Sun.COM 
3412126SHyon.Kim@Sun.COM #include <dlfcn.h>
3512126SHyon.Kim@Sun.COM #include <link.h>
3612126SHyon.Kim@Sun.COM #include <dirent.h>
3712126SHyon.Kim@Sun.COM #include <string.h>
3812126SHyon.Kim@Sun.COM #include <strings.h>
3912126SHyon.Kim@Sun.COM #include <limits.h>
4012126SHyon.Kim@Sun.COM 
4112126SHyon.Kim@Sun.COM #include "smp_impl.h"
4212126SHyon.Kim@Sun.COM 
4312126SHyon.Kim@Sun.COM static boolean_t _libsmp_plugin_dlclose;
4412126SHyon.Kim@Sun.COM 
4512126SHyon.Kim@Sun.COM /*
4612126SHyon.Kim@Sun.COM  * As part of basic initialization, we always retrieve the REPORT GENERAL
4712126SHyon.Kim@Sun.COM  * data so that we will know whether this target supports the long response
4812126SHyon.Kim@Sun.COM  * format.
4912126SHyon.Kim@Sun.COM  */
5012126SHyon.Kim@Sun.COM static int
smp_report_general(smp_target_t * tp)5112126SHyon.Kim@Sun.COM smp_report_general(smp_target_t *tp)
5212126SHyon.Kim@Sun.COM {
5312126SHyon.Kim@Sun.COM 	smp_action_t *ap;
5412126SHyon.Kim@Sun.COM 	smp_report_general_resp_t *rp;
5512126SHyon.Kim@Sun.COM 	smp_result_t result;
5612126SHyon.Kim@Sun.COM 	size_t len;
5712126SHyon.Kim@Sun.COM 
5812126SHyon.Kim@Sun.COM 	if ((ap = smp_action_alloc(SMP_FUNC_REPORT_GENERAL, tp, 0)) == NULL)
5912126SHyon.Kim@Sun.COM 		return (-1);
6012126SHyon.Kim@Sun.COM 
6112126SHyon.Kim@Sun.COM 	if (smp_exec(ap, tp) != 0) {
6212126SHyon.Kim@Sun.COM 		smp_action_free(ap);
6312126SHyon.Kim@Sun.COM 		return (smp_set_errno(ESMP_REPGEN_FAILED));
6412126SHyon.Kim@Sun.COM 	}
6512126SHyon.Kim@Sun.COM 
6612126SHyon.Kim@Sun.COM 	smp_action_get_response(ap, &result, (void **)&rp, &len);
6712126SHyon.Kim@Sun.COM 
6812126SHyon.Kim@Sun.COM 	if (result != SMP_RES_FUNCTION_ACCEPTED || len < 24) {
6912126SHyon.Kim@Sun.COM 		smp_action_free(ap);
7012126SHyon.Kim@Sun.COM 		return (smp_set_errno(ESMP_REPGEN_FAILED));
7112126SHyon.Kim@Sun.COM 	}
7212126SHyon.Kim@Sun.COM 
7312126SHyon.Kim@Sun.COM 	bcopy(rp, &tp->st_repgen, sizeof (tp->st_repgen));
7412126SHyon.Kim@Sun.COM 
7512126SHyon.Kim@Sun.COM 	smp_action_free(ap);
7612126SHyon.Kim@Sun.COM 
7712126SHyon.Kim@Sun.COM 	return (0);
7812126SHyon.Kim@Sun.COM }
7912126SHyon.Kim@Sun.COM 
8012126SHyon.Kim@Sun.COM static int
smp_report_manufacturer_information(smp_target_t * tp)8112126SHyon.Kim@Sun.COM smp_report_manufacturer_information(smp_target_t *tp)
8212126SHyon.Kim@Sun.COM {
8312126SHyon.Kim@Sun.COM 	smp_action_t *ap;
8412126SHyon.Kim@Sun.COM 	smp_report_manufacturer_info_resp_t *rp;
8512126SHyon.Kim@Sun.COM 	smp_result_t result;
8612126SHyon.Kim@Sun.COM 	size_t len;
8712126SHyon.Kim@Sun.COM 
8812126SHyon.Kim@Sun.COM 	ap = smp_action_alloc(SMP_FUNC_REPORT_MANUFACTURER_INFO, tp, 0);
8912126SHyon.Kim@Sun.COM 	if (ap == NULL)
9012126SHyon.Kim@Sun.COM 		return (-1);
9112126SHyon.Kim@Sun.COM 
9212126SHyon.Kim@Sun.COM 	if (smp_exec(ap, tp) != 0) {
9312126SHyon.Kim@Sun.COM 		smp_action_free(ap);
9412126SHyon.Kim@Sun.COM 		return (smp_set_errno(ESMP_REPGEN_FAILED));
9512126SHyon.Kim@Sun.COM 	}
9612126SHyon.Kim@Sun.COM 
9712126SHyon.Kim@Sun.COM 	smp_action_get_response(ap, &result, (void **)&rp, &len);
9812126SHyon.Kim@Sun.COM 
9912126SHyon.Kim@Sun.COM 	if (result != SMP_RES_FUNCTION_ACCEPTED ||
10012126SHyon.Kim@Sun.COM 	    len != sizeof (smp_report_manufacturer_info_resp_t)) {
10112126SHyon.Kim@Sun.COM 		smp_action_free(ap);
10212126SHyon.Kim@Sun.COM 		return (0);	/* Not supported */
10312126SHyon.Kim@Sun.COM 	}
10412126SHyon.Kim@Sun.COM 
10512126SHyon.Kim@Sun.COM 	tp->st_vendor = smp_trim_strdup(rp->srmir_vendor_identification,
10612126SHyon.Kim@Sun.COM 	    sizeof (rp->srmir_vendor_identification));
10712126SHyon.Kim@Sun.COM 	tp->st_product = smp_trim_strdup(rp->srmir_product_identification,
10812126SHyon.Kim@Sun.COM 	    sizeof (rp->srmir_product_identification));
10912126SHyon.Kim@Sun.COM 	tp->st_revision = smp_trim_strdup(rp->srmir_product_revision_level,
11012126SHyon.Kim@Sun.COM 	    sizeof (rp->srmir_product_revision_level));
11112126SHyon.Kim@Sun.COM 
11212126SHyon.Kim@Sun.COM 	if (rp->srmir_sas_1_1_format) {
11312126SHyon.Kim@Sun.COM 		tp->st_component_vendor =
11412126SHyon.Kim@Sun.COM 		    smp_trim_strdup(rp->srmir_component_vendor_identification,
11512126SHyon.Kim@Sun.COM 		    sizeof (rp->srmir_component_vendor_identification));
11612126SHyon.Kim@Sun.COM 
11712126SHyon.Kim@Sun.COM 		tp->st_component_id = SCSI_READ16(&rp->srmir_component_id);
11812126SHyon.Kim@Sun.COM 		tp->st_component_revision = rp->srmir_component_revision_level;
11912126SHyon.Kim@Sun.COM 	}
12012126SHyon.Kim@Sun.COM 
12112126SHyon.Kim@Sun.COM 	if (tp->st_vendor == NULL || tp->st_product == NULL ||
12212126SHyon.Kim@Sun.COM 	    tp->st_revision == NULL ||
12312126SHyon.Kim@Sun.COM 	    (rp->srmir_sas_1_1_format && tp->st_component_vendor == NULL)) {
12412126SHyon.Kim@Sun.COM 		smp_action_free(ap);
12512126SHyon.Kim@Sun.COM 		return (smp_set_errno(ESMP_NOMEM));
12612126SHyon.Kim@Sun.COM 	}
12712126SHyon.Kim@Sun.COM 
12812126SHyon.Kim@Sun.COM 	smp_action_free(ap);
12912126SHyon.Kim@Sun.COM 
13012126SHyon.Kim@Sun.COM 	return (0);
13112126SHyon.Kim@Sun.COM }
13212126SHyon.Kim@Sun.COM 
13312126SHyon.Kim@Sun.COM static int
smp_target_fill(smp_target_t * tp)13412126SHyon.Kim@Sun.COM smp_target_fill(smp_target_t *tp)
13512126SHyon.Kim@Sun.COM {
13612126SHyon.Kim@Sun.COM 	if (smp_report_general(tp) != 0 ||
13712126SHyon.Kim@Sun.COM 	    smp_report_manufacturer_information(tp) != 0)
13812126SHyon.Kim@Sun.COM 		return (-1);
13912126SHyon.Kim@Sun.COM 
14012126SHyon.Kim@Sun.COM 	return (0);
14112126SHyon.Kim@Sun.COM }
14212126SHyon.Kim@Sun.COM 
14312126SHyon.Kim@Sun.COM const smp_function_def_t *
smp_get_funcdef(smp_target_t * tp,int fn)14412126SHyon.Kim@Sun.COM smp_get_funcdef(smp_target_t *tp, int fn)
14512126SHyon.Kim@Sun.COM {
14612126SHyon.Kim@Sun.COM 	smp_plugin_t *pp;
14712126SHyon.Kim@Sun.COM 	const smp_function_def_t *dp;
14812126SHyon.Kim@Sun.COM 
14912126SHyon.Kim@Sun.COM 	for (pp = tp->st_plugin_first; pp != NULL; pp = pp->sp_next) {
15012126SHyon.Kim@Sun.COM 		if (pp->sp_functions == NULL)
15112126SHyon.Kim@Sun.COM 			continue;
15212126SHyon.Kim@Sun.COM 
15312126SHyon.Kim@Sun.COM 		for (dp = &pp->sp_functions[0]; dp->sfd_rq_len != NULL; dp++) {
15412126SHyon.Kim@Sun.COM 			if (dp->sfd_function == fn)
15512126SHyon.Kim@Sun.COM 				return (dp);
15612126SHyon.Kim@Sun.COM 		}
15712126SHyon.Kim@Sun.COM 	}
15812126SHyon.Kim@Sun.COM 
15912126SHyon.Kim@Sun.COM 	(void) smp_error(ESMP_BADFUNC, "failed to find function 0x%x", fn);
16012126SHyon.Kim@Sun.COM 	return (NULL);
16112126SHyon.Kim@Sun.COM }
16212126SHyon.Kim@Sun.COM 
16312126SHyon.Kim@Sun.COM int
smp_plugin_register(smp_plugin_t * pp,int version,const smp_plugin_config_t * pcp)16412126SHyon.Kim@Sun.COM smp_plugin_register(smp_plugin_t *pp, int version,
16512126SHyon.Kim@Sun.COM     const smp_plugin_config_t *pcp)
16612126SHyon.Kim@Sun.COM {
16712126SHyon.Kim@Sun.COM 	if (version != LIBSMP_PLUGIN_VERSION)
16812126SHyon.Kim@Sun.COM 		return (smp_set_errno(ESMP_VERSION));
16912126SHyon.Kim@Sun.COM 
17012126SHyon.Kim@Sun.COM 	pp->sp_functions = pcp->spc_functions;
17112126SHyon.Kim@Sun.COM 
17212126SHyon.Kim@Sun.COM 	return (0);
17312126SHyon.Kim@Sun.COM }
17412126SHyon.Kim@Sun.COM 
17512126SHyon.Kim@Sun.COM void
smp_plugin_setspecific(smp_plugin_t * pp,void * data)17612126SHyon.Kim@Sun.COM smp_plugin_setspecific(smp_plugin_t *pp, void *data)
17712126SHyon.Kim@Sun.COM {
17812126SHyon.Kim@Sun.COM 	pp->sp_data = data;
17912126SHyon.Kim@Sun.COM }
18012126SHyon.Kim@Sun.COM 
18112126SHyon.Kim@Sun.COM void *
smp_plugin_getspecific(smp_plugin_t * pp)18212126SHyon.Kim@Sun.COM smp_plugin_getspecific(smp_plugin_t *pp)
18312126SHyon.Kim@Sun.COM {
18412126SHyon.Kim@Sun.COM 	return (pp->sp_data);
18512126SHyon.Kim@Sun.COM }
18612126SHyon.Kim@Sun.COM 
18712126SHyon.Kim@Sun.COM static void
smp_plugin_cleanstr(char * s)18812126SHyon.Kim@Sun.COM smp_plugin_cleanstr(char *s)
18912126SHyon.Kim@Sun.COM {
19012126SHyon.Kim@Sun.COM 	while (*s != '\0') {
19112126SHyon.Kim@Sun.COM 		if (*s == ' ' || *s == '/')
19212126SHyon.Kim@Sun.COM 			*s = '-';
19312126SHyon.Kim@Sun.COM 		s++;
19412126SHyon.Kim@Sun.COM 	}
19512126SHyon.Kim@Sun.COM }
19612126SHyon.Kim@Sun.COM 
19712126SHyon.Kim@Sun.COM static void
smp_plugin_destroy(smp_plugin_t * pp)19812126SHyon.Kim@Sun.COM smp_plugin_destroy(smp_plugin_t *pp)
19912126SHyon.Kim@Sun.COM {
20012126SHyon.Kim@Sun.COM 	if (pp->sp_initialized && pp->sp_fini != NULL)
20112126SHyon.Kim@Sun.COM 		pp->sp_fini(pp);
20212126SHyon.Kim@Sun.COM 
20312126SHyon.Kim@Sun.COM 	if (_libsmp_plugin_dlclose)
20412126SHyon.Kim@Sun.COM 		(void) dlclose(pp->sp_object);
20512126SHyon.Kim@Sun.COM 
20612126SHyon.Kim@Sun.COM 	smp_free(pp);
20712126SHyon.Kim@Sun.COM }
20812126SHyon.Kim@Sun.COM 
20912126SHyon.Kim@Sun.COM static int
smp_plugin_loadone(smp_target_t * tp,const char * path,uint32_t pass)21012126SHyon.Kim@Sun.COM smp_plugin_loadone(smp_target_t *tp, const char *path, uint32_t pass)
21112126SHyon.Kim@Sun.COM {
21212126SHyon.Kim@Sun.COM 	smp_plugin_t *pp, **loc;
21312126SHyon.Kim@Sun.COM 	void *obj;
21412126SHyon.Kim@Sun.COM 	int (*smp_priority)(void);
21512126SHyon.Kim@Sun.COM 
21612126SHyon.Kim@Sun.COM 	if ((obj = dlopen(path, RTLD_PARENT | RTLD_LOCAL | RTLD_LAZY)) == NULL)
21712126SHyon.Kim@Sun.COM 		return (0);
21812126SHyon.Kim@Sun.COM 
21912126SHyon.Kim@Sun.COM 	if ((pp = smp_zalloc(sizeof (smp_plugin_t))) == NULL) {
22012126SHyon.Kim@Sun.COM 		(void) dlclose(obj);
22112126SHyon.Kim@Sun.COM 		return (-1);
22212126SHyon.Kim@Sun.COM 	}
22312126SHyon.Kim@Sun.COM 
22412126SHyon.Kim@Sun.COM 	pp->sp_object = obj;
22512126SHyon.Kim@Sun.COM 	pp->sp_init = (int (*)())dlsym(obj, "_smp_init");
22612126SHyon.Kim@Sun.COM 	pp->sp_fini = (void (*)())dlsym(obj, "_smp_fini");
22712126SHyon.Kim@Sun.COM 	pp->sp_target = tp;
22812126SHyon.Kim@Sun.COM 
22912126SHyon.Kim@Sun.COM 	if (pp->sp_init == NULL) {
23012126SHyon.Kim@Sun.COM 		smp_plugin_destroy(pp);
23112126SHyon.Kim@Sun.COM 		return (0);
23212126SHyon.Kim@Sun.COM 	}
23312126SHyon.Kim@Sun.COM 
23412126SHyon.Kim@Sun.COM 	/*
23512126SHyon.Kim@Sun.COM 	 * Framework modules can establish an explicit prioritying by declaring
23612126SHyon.Kim@Sun.COM 	 * the '_smp_priority' symbol, which returns an integer used to create
23712126SHyon.Kim@Sun.COM 	 * an explicit ordering between plugins.
23812126SHyon.Kim@Sun.COM 	 */
23912126SHyon.Kim@Sun.COM 	if ((smp_priority = (int (*)())dlsym(obj, "_smp_priority")) != NULL)
24012126SHyon.Kim@Sun.COM 		pp->sp_priority = smp_priority();
24112126SHyon.Kim@Sun.COM 
24212126SHyon.Kim@Sun.COM 	pp->sp_priority |= (uint64_t)pass << 32;
24312126SHyon.Kim@Sun.COM 
24412126SHyon.Kim@Sun.COM 	for (loc = &tp->st_plugin_first; *loc != NULL; loc = &(*loc)->sp_next) {
24512126SHyon.Kim@Sun.COM 		if ((*loc)->sp_priority > pp->sp_priority)
24612126SHyon.Kim@Sun.COM 			break;
24712126SHyon.Kim@Sun.COM 	}
24812126SHyon.Kim@Sun.COM 
24912126SHyon.Kim@Sun.COM 	if (*loc != NULL)
25012126SHyon.Kim@Sun.COM 		(*loc)->sp_prev = pp;
25112126SHyon.Kim@Sun.COM 	else
25212126SHyon.Kim@Sun.COM 		tp->st_plugin_last = pp;
25312126SHyon.Kim@Sun.COM 
25412126SHyon.Kim@Sun.COM 	pp->sp_next = *loc;
25512126SHyon.Kim@Sun.COM 	*loc = pp;
25612126SHyon.Kim@Sun.COM 
25712126SHyon.Kim@Sun.COM 	if (pp->sp_init(pp) != 0)
25812126SHyon.Kim@Sun.COM 		return (-1);
25912126SHyon.Kim@Sun.COM 	pp->sp_initialized = B_TRUE;
26012126SHyon.Kim@Sun.COM 
26112126SHyon.Kim@Sun.COM 	return (0);
26212126SHyon.Kim@Sun.COM }
26312126SHyon.Kim@Sun.COM 
26412126SHyon.Kim@Sun.COM static int
smp_plugin_load_dir(smp_target_t * tp,const char * pluginroot)26512126SHyon.Kim@Sun.COM smp_plugin_load_dir(smp_target_t *tp, const char *pluginroot)
26612126SHyon.Kim@Sun.COM {
26712126SHyon.Kim@Sun.COM 	char path[PATH_MAX];
26812126SHyon.Kim@Sun.COM 	DIR *dirp;
26912126SHyon.Kim@Sun.COM 	struct dirent64 *dp;
27012126SHyon.Kim@Sun.COM 	char *c_vendor, *vendor, *product, *revision;
27112126SHyon.Kim@Sun.COM 	char isa[257];
27212126SHyon.Kim@Sun.COM 
27312126SHyon.Kim@Sun.COM 	(void) snprintf(path, sizeof (path), "%s/%s",
27412126SHyon.Kim@Sun.COM 	    pluginroot, LIBSMP_PLUGIN_FRAMEWORK);
27512126SHyon.Kim@Sun.COM 
27612126SHyon.Kim@Sun.COM #if defined(_LP64)
27712126SHyon.Kim@Sun.COM 	if (sysinfo(SI_ARCHITECTURE_64, isa, sizeof (isa)) < 0)
27812126SHyon.Kim@Sun.COM 		isa[0] = '\0';
27912126SHyon.Kim@Sun.COM #else
28012126SHyon.Kim@Sun.COM 	isa[0] = '\0';
28112126SHyon.Kim@Sun.COM #endif
28212126SHyon.Kim@Sun.COM 
28312126SHyon.Kim@Sun.COM 	if ((dirp = opendir(path)) != NULL) {
28412126SHyon.Kim@Sun.COM 		while ((dp = readdir64(dirp)) != NULL) {
28512126SHyon.Kim@Sun.COM 			if (strcmp(dp->d_name, ".") == 0 ||
28612126SHyon.Kim@Sun.COM 			    strcmp(dp->d_name, "..") == 0)
28712126SHyon.Kim@Sun.COM 				continue;
28812126SHyon.Kim@Sun.COM 
28912126SHyon.Kim@Sun.COM 			(void) snprintf(path, sizeof (path), "%s/%s/%s/%s",
29012126SHyon.Kim@Sun.COM 			    pluginroot, LIBSMP_PLUGIN_FRAMEWORK,
29112126SHyon.Kim@Sun.COM 			    isa, dp->d_name);
29212126SHyon.Kim@Sun.COM 
29312126SHyon.Kim@Sun.COM 			if (smp_plugin_loadone(tp, path, 0) != 0) {
29412126SHyon.Kim@Sun.COM 				(void) closedir(dirp);
29512126SHyon.Kim@Sun.COM 				return (-1);
29612126SHyon.Kim@Sun.COM 			}
29712126SHyon.Kim@Sun.COM 		}
29812126SHyon.Kim@Sun.COM 
29912126SHyon.Kim@Sun.COM 		(void) closedir(dirp);
30012126SHyon.Kim@Sun.COM 	}
30112126SHyon.Kim@Sun.COM 
30212126SHyon.Kim@Sun.COM 	/*
30312126SHyon.Kim@Sun.COM 	 * Now attempt to load platform-specific plugins.  The framework
30412126SHyon.Kim@Sun.COM 	 * plugins had better give us the ability to perform basic SMP
30512126SHyon.Kim@Sun.COM 	 * functions like REPORT GENERAL and REPORT MANUFACTURER INFORMATION;
30612126SHyon.Kim@Sun.COM 	 * if not, we're toast anyway.  If the latter is not supported, we
30712126SHyon.Kim@Sun.COM 	 * will not be able to use any vendor-specific plugins.  Note that
30812126SHyon.Kim@Sun.COM 	 * there are actually two possible specifications for vendor plugins:
30912126SHyon.Kim@Sun.COM 	 * those matching the vendor/product/revision fields, and those
31012126SHyon.Kim@Sun.COM 	 * matching the component vendor/id/revision fields.  The component is
31112126SHyon.Kim@Sun.COM 	 * less specific, so we try to load those first.
31212126SHyon.Kim@Sun.COM 	 */
31312126SHyon.Kim@Sun.COM 
31412126SHyon.Kim@Sun.COM 	if (smp_target_fill(tp) != 0)
31512126SHyon.Kim@Sun.COM 		return (-1);
31612126SHyon.Kim@Sun.COM 
31712126SHyon.Kim@Sun.COM 	if (tp->st_vendor == NULL)
31812126SHyon.Kim@Sun.COM 		return (0);
31912126SHyon.Kim@Sun.COM 
32012126SHyon.Kim@Sun.COM 	if (tp->st_component_vendor != NULL) {
321*13093SRoger.Faulkner@Oracle.COM 		c_vendor = strdupa(tp->st_component_vendor);
32212126SHyon.Kim@Sun.COM 		smp_plugin_cleanstr(c_vendor);
32312126SHyon.Kim@Sun.COM 	}
32412126SHyon.Kim@Sun.COM 
325*13093SRoger.Faulkner@Oracle.COM 	vendor = strdupa(tp->st_vendor);
326*13093SRoger.Faulkner@Oracle.COM 	product = strdupa(tp->st_product);
327*13093SRoger.Faulkner@Oracle.COM 	revision = strdupa(tp->st_revision);
32812126SHyon.Kim@Sun.COM 
32912126SHyon.Kim@Sun.COM 	smp_plugin_cleanstr(vendor);
33012126SHyon.Kim@Sun.COM 	smp_plugin_cleanstr(product);
33112126SHyon.Kim@Sun.COM 	smp_plugin_cleanstr(revision);
33212126SHyon.Kim@Sun.COM 
33312126SHyon.Kim@Sun.COM 	if (tp->st_component_vendor != NULL) {
33412126SHyon.Kim@Sun.COM 		(void) snprintf(path, sizeof (path), "%s/%s/%s/component_%s%s",
33512126SHyon.Kim@Sun.COM 		    pluginroot, LIBSMP_PLUGIN_VENDOR, isa, c_vendor,
33612126SHyon.Kim@Sun.COM 		    LIBSMP_PLUGIN_EXT);
33712126SHyon.Kim@Sun.COM 		if (smp_plugin_loadone(tp, path, 1) != 0)
33812126SHyon.Kim@Sun.COM 			return (-1);
33912126SHyon.Kim@Sun.COM 
34012126SHyon.Kim@Sun.COM 		(void) snprintf(path, sizeof (path),
34112126SHyon.Kim@Sun.COM 		    "%s/%s/%s/component_%s-%04x%s",
34212126SHyon.Kim@Sun.COM 		    pluginroot, LIBSMP_PLUGIN_VENDOR, isa, c_vendor,
34312126SHyon.Kim@Sun.COM 		    tp->st_component_id, LIBSMP_PLUGIN_EXT);
34412126SHyon.Kim@Sun.COM 		if (smp_plugin_loadone(tp, path, 2) != 0)
34512126SHyon.Kim@Sun.COM 			return (-1);
34612126SHyon.Kim@Sun.COM 
34712126SHyon.Kim@Sun.COM 		(void) snprintf(path, sizeof (path),
34812126SHyon.Kim@Sun.COM 		    "%s/%s/%s/component_%s-%04x-%02x%s",
34912126SHyon.Kim@Sun.COM 		    pluginroot, LIBSMP_PLUGIN_VENDOR, isa, c_vendor,
35012126SHyon.Kim@Sun.COM 		    tp->st_component_id, tp->st_component_revision,
35112126SHyon.Kim@Sun.COM 		    LIBSMP_PLUGIN_EXT);
35212126SHyon.Kim@Sun.COM 		if (smp_plugin_loadone(tp, path, 3) != 0)
35312126SHyon.Kim@Sun.COM 			return (-1);
35412126SHyon.Kim@Sun.COM 	}
35512126SHyon.Kim@Sun.COM 
35612126SHyon.Kim@Sun.COM 	(void) snprintf(path, sizeof (path), "%s/%s/%s/%s%s", pluginroot,
35712126SHyon.Kim@Sun.COM 	    LIBSMP_PLUGIN_VENDOR, isa, vendor, LIBSMP_PLUGIN_EXT);
35812126SHyon.Kim@Sun.COM 	if (smp_plugin_loadone(tp, path, 4) != 0)
35912126SHyon.Kim@Sun.COM 		return (-1);
36012126SHyon.Kim@Sun.COM 
36112126SHyon.Kim@Sun.COM 	(void) snprintf(path, sizeof (path), "%s/%s/%s/%s-%s%s", pluginroot,
36212126SHyon.Kim@Sun.COM 	    LIBSMP_PLUGIN_VENDOR, isa, vendor, product, LIBSMP_PLUGIN_EXT);
36312126SHyon.Kim@Sun.COM 	if (smp_plugin_loadone(tp, path, 5) != 0)
36412126SHyon.Kim@Sun.COM 		return (-1);
36512126SHyon.Kim@Sun.COM 
36612126SHyon.Kim@Sun.COM 	(void) snprintf(path, sizeof (path), "%s/%s/%s/%s-%s-%s%s", pluginroot,
36712126SHyon.Kim@Sun.COM 	    LIBSMP_PLUGIN_VENDOR, isa, vendor, product,
36812126SHyon.Kim@Sun.COM 	    revision, LIBSMP_PLUGIN_EXT);
36912126SHyon.Kim@Sun.COM 	if (smp_plugin_loadone(tp, path, 6) != 0)
37012126SHyon.Kim@Sun.COM 		return (-1);
37112126SHyon.Kim@Sun.COM 
37212126SHyon.Kim@Sun.COM 	return (0);
37312126SHyon.Kim@Sun.COM }
37412126SHyon.Kim@Sun.COM 
37512126SHyon.Kim@Sun.COM int
smp_plugin_load(smp_target_t * tp)37612126SHyon.Kim@Sun.COM smp_plugin_load(smp_target_t *tp)
37712126SHyon.Kim@Sun.COM {
37812126SHyon.Kim@Sun.COM 	char pluginroot[PATH_MAX];
37912126SHyon.Kim@Sun.COM 	const char *pluginpath, *p, *q;
38012126SHyon.Kim@Sun.COM 
38112126SHyon.Kim@Sun.COM 	if ((pluginpath = getenv("SMP_PLUGINPATH")) == NULL)
38212126SHyon.Kim@Sun.COM 		pluginpath = LIBSMP_DEFAULT_PLUGINDIR;
38312126SHyon.Kim@Sun.COM 	_libsmp_plugin_dlclose = (getenv("SMP_NODLCLOSE") == NULL);
38412126SHyon.Kim@Sun.COM 
38512126SHyon.Kim@Sun.COM 	for (p = pluginpath; p != NULL; p = q) {
38612126SHyon.Kim@Sun.COM 		if ((q = strchr(p, ':')) != NULL) {
38712126SHyon.Kim@Sun.COM 			ptrdiff_t len = q - p;
38812126SHyon.Kim@Sun.COM 			(void) strncpy(pluginroot, p, len);
38912126SHyon.Kim@Sun.COM 			pluginroot[len] = '\0';
39012126SHyon.Kim@Sun.COM 			while (*q == ':')
39112126SHyon.Kim@Sun.COM 				++q;
39212126SHyon.Kim@Sun.COM 			if (*q == '\0')
39312126SHyon.Kim@Sun.COM 				q = NULL;
39412126SHyon.Kim@Sun.COM 			if (len == 0)
39512126SHyon.Kim@Sun.COM 				continue;
39612126SHyon.Kim@Sun.COM 		} else {
39712126SHyon.Kim@Sun.COM 			(void) strcpy(pluginroot, p);
39812126SHyon.Kim@Sun.COM 		}
39912126SHyon.Kim@Sun.COM 
40012126SHyon.Kim@Sun.COM 		if (pluginroot[0] != '/')
40112126SHyon.Kim@Sun.COM 			continue;
40212126SHyon.Kim@Sun.COM 
40312126SHyon.Kim@Sun.COM 		if (smp_plugin_load_dir(tp, pluginroot) != 0)
40412126SHyon.Kim@Sun.COM 			return (-1);
40512126SHyon.Kim@Sun.COM 	}
40612126SHyon.Kim@Sun.COM 
40712126SHyon.Kim@Sun.COM 	if (tp->st_plugin_first == NULL)
40812126SHyon.Kim@Sun.COM 		return (smp_error(ESMP_PLUGIN, "no plugins found"));
40912126SHyon.Kim@Sun.COM 
41012126SHyon.Kim@Sun.COM 	return (0);
41112126SHyon.Kim@Sun.COM }
41212126SHyon.Kim@Sun.COM 
41312126SHyon.Kim@Sun.COM void
smp_plugin_unload(smp_target_t * tp)41412126SHyon.Kim@Sun.COM smp_plugin_unload(smp_target_t *tp)
41512126SHyon.Kim@Sun.COM {
41612126SHyon.Kim@Sun.COM 	smp_plugin_t *pp;
41712126SHyon.Kim@Sun.COM 
41812126SHyon.Kim@Sun.COM 	while ((pp = tp->st_plugin_first) != NULL) {
41912126SHyon.Kim@Sun.COM 		tp->st_plugin_first = pp->sp_next;
42012126SHyon.Kim@Sun.COM 		smp_plugin_destroy(pp);
42112126SHyon.Kim@Sun.COM 	}
42212126SHyon.Kim@Sun.COM }
423