xref: /illumos-gate/usr/src/cmd/ldmad/ldma_system.c (revision 82629e30)
149bfb42bSAlexandre Chartre /*
249bfb42bSAlexandre Chartre  * CDDL HEADER START
349bfb42bSAlexandre Chartre  *
449bfb42bSAlexandre Chartre  * The contents of this file are subject to the terms of the
549bfb42bSAlexandre Chartre  * Common Development and Distribution License (the "License").
649bfb42bSAlexandre Chartre  * You may not use this file except in compliance with the License.
749bfb42bSAlexandre Chartre  *
849bfb42bSAlexandre Chartre  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
949bfb42bSAlexandre Chartre  * or http://www.opensolaris.org/os/licensing.
1049bfb42bSAlexandre Chartre  * See the License for the specific language governing permissions
1149bfb42bSAlexandre Chartre  * and limitations under the License.
1249bfb42bSAlexandre Chartre  *
1349bfb42bSAlexandre Chartre  * When distributing Covered Code, include this CDDL HEADER in each
1449bfb42bSAlexandre Chartre  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1549bfb42bSAlexandre Chartre  * If applicable, add the following below this CDDL HEADER, with the
1649bfb42bSAlexandre Chartre  * fields enclosed by brackets "[]" replaced with your own identifying
1749bfb42bSAlexandre Chartre  * information: Portions Copyright [yyyy] [name of copyright owner]
1849bfb42bSAlexandre Chartre  *
1949bfb42bSAlexandre Chartre  * CDDL HEADER END
2049bfb42bSAlexandre Chartre  */
2149bfb42bSAlexandre Chartre 
2249bfb42bSAlexandre Chartre /*
23*82629e30SMike Christensen  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2449bfb42bSAlexandre Chartre  * Use is subject to license terms.
2549bfb42bSAlexandre Chartre  */
2649bfb42bSAlexandre Chartre 
2749bfb42bSAlexandre Chartre /*
2849bfb42bSAlexandre Chartre  * Logical Domains System Agent
2949bfb42bSAlexandre Chartre  */
3049bfb42bSAlexandre Chartre 
3149bfb42bSAlexandre Chartre #include <errno.h>
32*82629e30SMike Christensen #include <fcntl.h>
3349bfb42bSAlexandre Chartre #include <libds.h>
3449bfb42bSAlexandre Chartre #include <stdio.h>
35*82629e30SMike Christensen #include <stdlib.h>
3649bfb42bSAlexandre Chartre #include <strings.h>
37*82629e30SMike Christensen #include <synch.h>
38*82629e30SMike Christensen #include <thread.h>
39*82629e30SMike Christensen #include <unistd.h>
4049bfb42bSAlexandre Chartre #include <sys/utsname.h>
41*82629e30SMike Christensen #include <sys/mdesc.h>
42*82629e30SMike Christensen #include <sys/mdesc_impl.h>
4349bfb42bSAlexandre Chartre 
4449bfb42bSAlexandre Chartre #include "ldma.h"
45*82629e30SMike Christensen #include "pri.h"
4649bfb42bSAlexandre Chartre 
4749bfb42bSAlexandre Chartre #define	LDMA_MODULE	LDMA_NAME_SYSTEM
4849bfb42bSAlexandre Chartre 
4949bfb42bSAlexandre Chartre #define	LDMA_NVERSIONS	(sizeof (ldma_versions) / sizeof (ds_ver_t))
5049bfb42bSAlexandre Chartre #define	LDMA_NHANDLERS	(sizeof (ldma_handlers) / sizeof (ldma_msg_handler_t))
5149bfb42bSAlexandre Chartre 
5249bfb42bSAlexandre Chartre static ldm_msg_func_t ldma_sys_get_sysinfo;
53*82629e30SMike Christensen static ldm_msg_func_t ldma_sys_get_chassisno;
54*82629e30SMike Christensen 
55*82629e30SMike Christensen /* ptr to cached value of chassisno */
56*82629e30SMike Christensen static char *ldma_sys_chassisno = NULL;
57*82629e30SMike Christensen mutex_t ldma_chassisno_lock = DEFAULTMUTEX;
5849bfb42bSAlexandre Chartre 
5949bfb42bSAlexandre Chartre static ds_ver_t ldma_versions[] = { { 1, 0 } };
6049bfb42bSAlexandre Chartre 
6149bfb42bSAlexandre Chartre static ldma_msg_handler_t ldma_handlers[] = {
62*82629e30SMike Christensen 	{ LDMA_MSGSYS_GET_SYSINFO,   LDMA_MSGFLG_ACCESS_ANY,
63*82629e30SMike Christensen 	    ldma_sys_get_sysinfo },
64*82629e30SMike Christensen 	{ LDMA_MSGSYS_GET_CHASSISNO, LDMA_MSGFLG_ACCESS_ANY,
65*82629e30SMike Christensen 	    ldma_sys_get_chassisno }
6649bfb42bSAlexandre Chartre };
6749bfb42bSAlexandre Chartre 
6849bfb42bSAlexandre Chartre ldma_agent_info_t ldma_system_info = {
6949bfb42bSAlexandre Chartre 	LDMA_NAME_SYSTEM,
7049bfb42bSAlexandre Chartre 	ldma_versions, LDMA_NVERSIONS,
7149bfb42bSAlexandre Chartre 	ldma_handlers, LDMA_NHANDLERS
7249bfb42bSAlexandre Chartre };
7349bfb42bSAlexandre Chartre 
7449bfb42bSAlexandre Chartre /*ARGSUSED*/
7549bfb42bSAlexandre Chartre static ldma_request_status_t
ldma_sys_get_sysinfo(ds_ver_t * ver,ldma_message_header_t * request,size_t request_dlen,ldma_message_header_t ** replyp,size_t * reply_dlenp)7649bfb42bSAlexandre Chartre ldma_sys_get_sysinfo(ds_ver_t *ver, ldma_message_header_t *request,
7749bfb42bSAlexandre Chartre     size_t request_dlen, ldma_message_header_t **replyp, size_t *reply_dlenp)
7849bfb42bSAlexandre Chartre {
7949bfb42bSAlexandre Chartre 	ldma_message_header_t *reply;
8049bfb42bSAlexandre Chartre 	struct utsname name;
8149bfb42bSAlexandre Chartre 	size_t syslen, nodlen, rellen, maclen, verlen;
8249bfb42bSAlexandre Chartre 	size_t rlen;
8349bfb42bSAlexandre Chartre 	char *data;
8449bfb42bSAlexandre Chartre 	int status;
8549bfb42bSAlexandre Chartre 
8649bfb42bSAlexandre Chartre 	LDMA_DBG("GET_SYSINFO");
8749bfb42bSAlexandre Chartre 
8849bfb42bSAlexandre Chartre 	if (request->msg_info != 0 || request_dlen != 0) {
8949bfb42bSAlexandre Chartre 		status = LDMA_REQ_INVALID;
9049bfb42bSAlexandre Chartre 		goto done;
9149bfb42bSAlexandre Chartre 	}
9249bfb42bSAlexandre Chartre 
9349bfb42bSAlexandre Chartre 	if (uname(&name) == -1) {
9449bfb42bSAlexandre Chartre 		LDMA_DBG("GET_SYSINFO: uname failed with error %d", errno);
9549bfb42bSAlexandre Chartre 		status = LDMA_REQ_FAILED;
9649bfb42bSAlexandre Chartre 		goto done;
9749bfb42bSAlexandre Chartre 	}
9849bfb42bSAlexandre Chartre 
9949bfb42bSAlexandre Chartre 	syslen = strlen(name.sysname) + 1;
10049bfb42bSAlexandre Chartre 	nodlen = strlen(name.nodename) + 1;
10149bfb42bSAlexandre Chartre 	rellen = strlen(name.release) + 1;
10249bfb42bSAlexandre Chartre 	verlen = strlen(name.version) + 1;
10349bfb42bSAlexandre Chartre 	maclen = strlen(name.machine) + 1;
10449bfb42bSAlexandre Chartre 
10549bfb42bSAlexandre Chartre 	rlen = syslen + nodlen + rellen + verlen + maclen;
10649bfb42bSAlexandre Chartre 
10749bfb42bSAlexandre Chartre 	reply = ldma_alloc_result_msg(request, rlen);
10849bfb42bSAlexandre Chartre 
10949bfb42bSAlexandre Chartre 	if (reply == NULL) {
11049bfb42bSAlexandre Chartre 		status = LDMA_REQ_FAILED;
11149bfb42bSAlexandre Chartre 		goto done;
11249bfb42bSAlexandre Chartre 	}
11349bfb42bSAlexandre Chartre 
11449bfb42bSAlexandre Chartre 	reply->msg_info = rlen;
11549bfb42bSAlexandre Chartre 
11649bfb42bSAlexandre Chartre 	data = LDMA_HDR2DATA(reply);
11749bfb42bSAlexandre Chartre 
11849bfb42bSAlexandre Chartre 	(void) strcpy(data, name.sysname);
11949bfb42bSAlexandre Chartre 	data += syslen;
12049bfb42bSAlexandre Chartre 
12149bfb42bSAlexandre Chartre 	(void) strcpy(data, name.nodename);
12249bfb42bSAlexandre Chartre 	data += nodlen;
12349bfb42bSAlexandre Chartre 
12449bfb42bSAlexandre Chartre 	(void) strcpy(data, name.release);
12549bfb42bSAlexandre Chartre 	data += rellen;
12649bfb42bSAlexandre Chartre 
12749bfb42bSAlexandre Chartre 	(void) strcpy(data, name.version);
12849bfb42bSAlexandre Chartre 	data += verlen;
12949bfb42bSAlexandre Chartre 
13049bfb42bSAlexandre Chartre 	(void) strcpy(data, name.machine);
13149bfb42bSAlexandre Chartre 
13249bfb42bSAlexandre Chartre 	LDMA_DBG("GET_SYSINFO: return info=%u, {%s, %s, %s, %s, %s}", rlen,
13349bfb42bSAlexandre Chartre 	    name.sysname, name.nodename, name.release, name.version,
13449bfb42bSAlexandre Chartre 	    name.machine);
13549bfb42bSAlexandre Chartre 
13649bfb42bSAlexandre Chartre 	*replyp = reply;
13749bfb42bSAlexandre Chartre 	*reply_dlenp = rlen;
13849bfb42bSAlexandre Chartre 
13949bfb42bSAlexandre Chartre 	return (LDMA_REQ_COMPLETED);
14049bfb42bSAlexandre Chartre 
14149bfb42bSAlexandre Chartre done:
14249bfb42bSAlexandre Chartre 	LDMA_DBG("GET_SYSINFO: return error %d", status);
14349bfb42bSAlexandre Chartre 	return (status);
14449bfb42bSAlexandre Chartre }
145*82629e30SMike Christensen 
146*82629e30SMike Christensen /*
147*82629e30SMike Christensen  * Wrapper for MD free: need unused size argument.
148*82629e30SMike Christensen  */
149*82629e30SMike Christensen /* ARGSUSED */
150*82629e30SMike Christensen static void
ldma_md_free(void * buf,size_t n)151*82629e30SMike Christensen ldma_md_free(void *buf, size_t n)
152*82629e30SMike Christensen {
153*82629e30SMike Christensen 	free(buf);
154*82629e30SMike Christensen }
155*82629e30SMike Christensen 
156*82629e30SMike Christensen /*
157*82629e30SMike Christensen  * Wrapper for MD init: read PRI MD and invoke md_init_intern.
158*82629e30SMike Christensen  */
159*82629e30SMike Christensen static md_t *
ldma_md_init()160*82629e30SMike Christensen ldma_md_init()
161*82629e30SMike Christensen {
162*82629e30SMike Christensen 	md_t *mdp;
163*82629e30SMike Christensen 	uint64_t *buf = NULL;
164*82629e30SMike Christensen 	uint64_t token;
165*82629e30SMike Christensen 	ssize_t status;
166*82629e30SMike Christensen 
167*82629e30SMike Christensen 	if (pri_init() == -1)
168*82629e30SMike Christensen 		return (NULL);
169*82629e30SMike Christensen 
170*82629e30SMike Christensen 	status = pri_get(PRI_GET, &token, &buf, malloc, ldma_md_free);
171*82629e30SMike Christensen 	pri_fini();
172*82629e30SMike Christensen 
173*82629e30SMike Christensen 	if (status == (ssize_t)(-1))
174*82629e30SMike Christensen 		return (NULL);
175*82629e30SMike Christensen 
176*82629e30SMike Christensen 	mdp = md_init_intern(buf, malloc, ldma_md_free);
177*82629e30SMike Christensen 
178*82629e30SMike Christensen 	return (mdp);
179*82629e30SMike Christensen }
180*82629e30SMike Christensen 
181*82629e30SMike Christensen /*
182*82629e30SMike Christensen  * Wrapper for md_fini.  Allow NULL md ptr and free MD buffer.
183*82629e30SMike Christensen  */
184*82629e30SMike Christensen static void
ldma_md_fini(void * md)185*82629e30SMike Christensen ldma_md_fini(void *md)
186*82629e30SMike Christensen {
187*82629e30SMike Christensen 	md_impl_t *mdp = (md_impl_t *)md;
188*82629e30SMike Christensen 
189*82629e30SMike Christensen 	if (mdp) {
190*82629e30SMike Christensen 		free(mdp->caddr);
191*82629e30SMike Christensen 		(void) md_fini(md);
192*82629e30SMike Christensen 	}
193*82629e30SMike Christensen }
194*82629e30SMike Christensen 
195*82629e30SMike Christensen static int
ldma_get_chassis_serialno(char ** strp)196*82629e30SMike Christensen ldma_get_chassis_serialno(char **strp)
197*82629e30SMike Christensen {
198*82629e30SMike Christensen 	md_t *mdp;
199*82629e30SMike Christensen 	mde_cookie_t *component_nodes, rootnode;
200*82629e30SMike Christensen 	int list_size, ncomponents, num_nodes, i;
201*82629e30SMike Christensen 	char *component_type, *serialno;
202*82629e30SMike Christensen 	int rv = 0;
203*82629e30SMike Christensen 
204*82629e30SMike Christensen 	(void) mutex_lock(&ldma_chassisno_lock);
205*82629e30SMike Christensen 	if (ldma_sys_chassisno != NULL) {
206*82629e30SMike Christensen 		*strp = ldma_sys_chassisno;
207*82629e30SMike Christensen 		(void) mutex_unlock(&ldma_chassisno_lock);
208*82629e30SMike Christensen 		return (1);
209*82629e30SMike Christensen 	}
210*82629e30SMike Christensen 
211*82629e30SMike Christensen 	mdp = ldma_md_init();
212*82629e30SMike Christensen 	if (mdp == NULL) {
213*82629e30SMike Christensen 		(void) mutex_unlock(&ldma_chassisno_lock);
214*82629e30SMike Christensen 		return (0);
215*82629e30SMike Christensen 	}
216*82629e30SMike Christensen 
217*82629e30SMike Christensen 	num_nodes = md_node_count(mdp);
218*82629e30SMike Christensen 	list_size = num_nodes * sizeof (mde_cookie_t);
219*82629e30SMike Christensen 	component_nodes = malloc(list_size);
220*82629e30SMike Christensen 	if (component_nodes == NULL) {
221*82629e30SMike Christensen 		(void) mutex_unlock(&ldma_chassisno_lock);
222*82629e30SMike Christensen 		ldma_md_fini(mdp);
223*82629e30SMike Christensen 		return (0);
224*82629e30SMike Christensen 	}
225*82629e30SMike Christensen 
226*82629e30SMike Christensen 	rootnode = md_root_node(mdp);
227*82629e30SMike Christensen 
228*82629e30SMike Christensen 	ncomponents = md_scan_dag(mdp, rootnode, md_find_name(mdp, "component"),
229*82629e30SMike Christensen 	    md_find_name(mdp, "fwd"), component_nodes);
230*82629e30SMike Christensen 
231*82629e30SMike Christensen 	for (i = 0; i < ncomponents; i++) {
232*82629e30SMike Christensen 		if (md_get_prop_str(mdp, component_nodes[i], "type",
233*82629e30SMike Christensen 		    &component_type))
234*82629e30SMike Christensen 			continue;
235*82629e30SMike Christensen 		if (strcmp(component_type, "chassis") != 0)
236*82629e30SMike Christensen 			continue;
237*82629e30SMike Christensen 		if (md_get_prop_str(mdp, component_nodes[i],
238*82629e30SMike Christensen 		    "serial_number", &serialno) == 0) {
239*82629e30SMike Christensen 			ldma_sys_chassisno = strdup(serialno);
240*82629e30SMike Christensen 			*strp = ldma_sys_chassisno;
241*82629e30SMike Christensen 			rv = 1;
242*82629e30SMike Christensen 			break;
243*82629e30SMike Christensen 		}
244*82629e30SMike Christensen 	}
245*82629e30SMike Christensen 	(void) mutex_unlock(&ldma_chassisno_lock);
246*82629e30SMike Christensen 	free(component_nodes);
247*82629e30SMike Christensen 	ldma_md_fini(mdp);
248*82629e30SMike Christensen 	return (rv);
249*82629e30SMike Christensen }
250*82629e30SMike Christensen 
251*82629e30SMike Christensen /*ARGSUSED*/
252*82629e30SMike Christensen static ldma_request_status_t
ldma_sys_get_chassisno(ds_ver_t * ver,ldma_message_header_t * request,size_t request_dlen,ldma_message_header_t ** replyp,size_t * reply_dlenp)253*82629e30SMike Christensen ldma_sys_get_chassisno(ds_ver_t *ver, ldma_message_header_t *request,
254*82629e30SMike Christensen     size_t request_dlen, ldma_message_header_t **replyp, size_t *reply_dlenp)
255*82629e30SMike Christensen {
256*82629e30SMike Christensen 	ldma_message_header_t *reply;
257*82629e30SMike Christensen 	char *str;
258*82629e30SMike Christensen 	size_t rlen;
259*82629e30SMike Christensen 	char *data;
260*82629e30SMike Christensen 	int status;
261*82629e30SMike Christensen 
262*82629e30SMike Christensen 	LDMA_DBG("GET_CHASSISNO");
263*82629e30SMike Christensen 
264*82629e30SMike Christensen 	if (request->msg_info != 0 || request_dlen != 0) {
265*82629e30SMike Christensen 		status = LDMA_REQ_INVALID;
266*82629e30SMike Christensen 		goto done;
267*82629e30SMike Christensen 	}
268*82629e30SMike Christensen 
269*82629e30SMike Christensen 	if (ldma_get_chassis_serialno(&str) == 0) {
270*82629e30SMike Christensen 		LDMA_DBG("GET_CHASSISNO: ldma_get_chassisno failed "
271*82629e30SMike Christensen 		    "with error %d", errno);
272*82629e30SMike Christensen 		status = LDMA_REQ_FAILED;
273*82629e30SMike Christensen 		goto done;
274*82629e30SMike Christensen 	}
275*82629e30SMike Christensen 
276*82629e30SMike Christensen 	rlen = strlen(str) + 1;
277*82629e30SMike Christensen 
278*82629e30SMike Christensen 	reply = ldma_alloc_result_msg(request, rlen);
279*82629e30SMike Christensen 
280*82629e30SMike Christensen 	if (reply == NULL) {
281*82629e30SMike Christensen 		status = LDMA_REQ_FAILED;
282*82629e30SMike Christensen 		goto done;
283*82629e30SMike Christensen 	}
284*82629e30SMike Christensen 
285*82629e30SMike Christensen 	reply->msg_info = rlen;
286*82629e30SMike Christensen 
287*82629e30SMike Christensen 	data = LDMA_HDR2DATA(reply);
288*82629e30SMike Christensen 
289*82629e30SMike Christensen 	(void) strcpy(data, str);
290*82629e30SMike Christensen 
291*82629e30SMike Christensen 	LDMA_DBG("GET_CHASSISNO: return info=%u, {%s}", rlen, str);
292*82629e30SMike Christensen 
293*82629e30SMike Christensen 	*replyp = reply;
294*82629e30SMike Christensen 	*reply_dlenp = rlen;
295*82629e30SMike Christensen 
296*82629e30SMike Christensen 	return (LDMA_REQ_COMPLETED);
297*82629e30SMike Christensen 
298*82629e30SMike Christensen done:
299*82629e30SMike Christensen 	LDMA_DBG("GET_CHASSISNO: return error %d", status);
300*82629e30SMike Christensen 	return (status);
301*82629e30SMike Christensen }
302