1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <ctype.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <macros.h>
32 #include <libdevinfo.h>
33 #define	CFGA_PLUGIN_LIB
34 #include <config_admin.h>
35 #include "ap.h"
36 
37 int cfga_version = CFGA_HSL_V2;
38 
39 /*ARGSUSED*/
40 cfga_err_t
cfga_change_state(cfga_cmd_t cfga_cmd,const char * ap_id,const char * options,struct cfga_confirm * confp,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)41 cfga_change_state(
42 	cfga_cmd_t cfga_cmd,
43 	const char *ap_id,
44 	const char *options,
45 	struct cfga_confirm *confp,
46 	struct cfga_msg *msgp,
47 	char **errstring,
48 	cfga_flags_t flags)
49 {
50 	int cmd;
51 	const char *name;
52 	apd_t *a;
53 	cfga_err_t rc;
54 
55 	if ((rc = ap_state_cmd(cfga_cmd, &cmd)) != CFGA_OK)
56 		return (rc);
57 
58 	rc = CFGA_LIB_ERROR;
59 
60 	if ((a = apd_alloc(ap_id, flags, errstring, msgp, confp)) == NULL)
61 		return (rc);
62 
63 	name = ap_cmd_name(cmd);
64 
65 	if ((rc = ap_cmd_parse(a, name, options, NULL)) == CFGA_OK)
66 		rc = ap_cmd_seq(a, cmd);
67 
68 	apd_free(a);
69 
70 	return (rc);
71 }
72 
73 /*
74  * Check if this is a valid -x command.
75  */
76 static int
private_func(const char * function)77 private_func(const char *function)
78 {
79 	char **f;
80 	static char *
81 	private_funcs[] = {
82 		"assign",
83 		"unassign",
84 		"poweron",
85 		"poweroff",
86 		"passthru",
87 		"errtest",
88 		NULL
89 	};
90 
91 	for (f = private_funcs; *f != NULL; f++)
92 		if (strcmp(*f, function) == 0)
93 			break;
94 
95 	return (*f == NULL ? CFGA_INVAL : CFGA_OK);
96 }
97 
98 /*ARGSUSED*/
99 cfga_err_t
cfga_private_func(const char * function,const char * ap_id,const char * options,struct cfga_confirm * confp,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)100 cfga_private_func(
101 	const char *function,
102 	const char *ap_id,
103 	const char *options,
104 	struct cfga_confirm *confp,
105 	struct cfga_msg *msgp,
106 	char **errstring,
107 	cfga_flags_t flags)
108 {
109 	int cmd;
110 	apd_t *a;
111 	cfga_err_t rc;
112 
113 	DBG("cfga_private_func(%s)\n", ap_id);
114 
115 	rc = CFGA_LIB_ERROR;
116 
117 	if ((a = apd_alloc(ap_id, flags, errstring, msgp, confp)) == NULL)
118 		return (rc);
119 	else if ((rc = private_func(function)) != CFGA_OK)  {
120 		ap_err(a, ERR_CMD_INVAL, function);
121 		goto done;
122 	} else if ((rc = ap_cmd_parse(a, function, options, &cmd)) != CFGA_OK)
123 		goto done;
124 	else if (cmd == CMD_ERRTEST)
125 		rc = ap_test_err(a, options);
126 	else
127 		rc = ap_cmd_exec(a, cmd);
128 done:
129 	apd_free(a);
130 	return (rc);
131 }
132 
133 
134 /*ARGSUSED*/
135 cfga_err_t
cfga_test(const char * ap_id,const char * options,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)136 cfga_test(
137 	const char *ap_id,
138 	const char *options,
139 	struct cfga_msg *msgp,
140 	char **errstring,
141 	cfga_flags_t flags)
142 {
143 	int cmd;
144 	const char *f;
145 	apd_t *a;
146 	cfga_err_t rc;
147 
148 	DBG("cfga_test(%s)\n", ap_id);
149 
150 	f = "test";
151 	rc = CFGA_LIB_ERROR;
152 
153 	/*
154 	 * A test that is not sequenced by a change
155 	 * state operation should be forced.
156 	 */
157 	flags |= CFGA_FLAG_FORCE;
158 
159 	if ((a = apd_alloc(ap_id, flags, errstring, msgp, NULL)) == NULL)
160 		return (rc);
161 	else if ((rc = ap_cmd_parse(a, f, options, &cmd)) != CFGA_OK)
162 		goto done;
163 	else
164 		rc = ap_cmd_exec(a, cmd);
165 done:
166 	apd_free(a);
167 	return (rc);
168 }
169 
170 /*ARGSUSED*/
171 cfga_err_t
cfga_list_ext(const char * ap_id,cfga_list_data_t ** ap_id_list,int * nlist,const char * options,const char * listopts,char ** errstring,cfga_flags_t flags)172 cfga_list_ext(
173 	const char *ap_id,
174 	cfga_list_data_t **ap_id_list,
175 	int *nlist,
176 	const char *options,
177 	const char *listopts,
178 	char **errstring,
179 	cfga_flags_t flags)
180 {
181 	int i;
182 	int apcnt;
183 	const char *f;
184 	apd_t *a;
185 	size_t szl, szp;
186 	cfga_list_data_t *aplist, *ap;
187 	cfga_err_t rc;
188 
189 	rc = CFGA_LIB_ERROR;
190 
191 	aplist = NULL;
192 	f = ap_cmd_name(CMD_STATUS);
193 
194 	DBG("cfga_list_ext(%s %x)\n", ap_id, flags);
195 
196 	if ((a = apd_alloc(ap_id, flags, errstring, NULL, NULL)) == NULL)
197 		return (rc);
198 	else if ((rc = ap_cmd_parse(a, f, options, NULL)) != CFGA_OK)
199 		goto done;
200 
201 	apcnt = ap_cnt(a);
202 
203 	DBG("apcnt=%d\n", apcnt);
204 
205 	if ((aplist = calloc(apcnt, sizeof (*aplist))) == NULL) {
206 		rc = CFGA_LIB_ERROR;
207 		ap_err(a, ERR_CMD_FAIL, CMD_STATUS);
208 		goto done;
209 	}
210 
211 	ap = aplist;
212 	szl = sizeof (ap->ap_log_id);
213 	szp = sizeof (ap->ap_phys_id);
214 
215 	/*
216 	 * Initialize the AP specified directly by the caller.
217 	 * The target ID for the 0th element already includes
218 	 * the (potential) dynamic portion. The dynamic portion
219 	 * does need to be appended to the path to form the
220 	 * physical apid for components.
221 	 */
222 	(void) strncpy(ap->ap_log_id, a->target, szl - 1);
223 	(void) snprintf(ap->ap_phys_id, szp, "%s%s%s", a->path,
224 	    a->tgt != AP_BOARD ? "::" : "",
225 	    a->tgt != AP_BOARD ? a->cid : "");
226 
227 
228 	DBG("ap_phys_id=%s ap_log_id=%s\n", ap->ap_phys_id, ap->ap_log_id);
229 
230 	if (a->tgt == AP_BOARD) {
231 
232 		ap_init(a, ap++);
233 
234 		/*
235 		 * Initialize the components, if any.
236 		 */
237 		for (i = 0; i < apcnt - 1; i++, ap++) {
238 			char dyn[MAXPATHLEN];
239 
240 			ap_cm_id(a, i, dyn, sizeof (dyn));
241 
242 			(void) snprintf(ap->ap_log_id, szl, "%s::%s",
243 			    a->target, dyn);
244 			(void) snprintf(ap->ap_phys_id, szp, "%s::%s",
245 			    a->path, dyn);
246 
247 			ap_cm_init(a, ap, i);
248 
249 			DBG("ap_phys_id=%s ap_log_id=%s\n",
250 			    ap->ap_phys_id, ap->ap_log_id);
251 		}
252 
253 	} else
254 		ap_cm_init(a, ap, 0);
255 
256 	apd_free(a);
257 	*ap_id_list = aplist;
258 	*nlist = apcnt;
259 	return (CFGA_OK);
260 
261 done:
262 	s_free(aplist);
263 	apd_free(a);
264 	return (rc);
265 }
266 
267 /*ARGSUSED*/
268 cfga_err_t
cfga_help(struct cfga_msg * msgp,const char * options,cfga_flags_t flags)269 cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
270 {
271 	return (ap_help(msgp, options, flags));
272 }
273 
274 
275 /*
276  * cfga_ap_id_cmp -- use default_ap_id_cmp() in libcfgadm
277  */
278