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