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.
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.
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]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Logical Domains System Agent
40 #include <sys/utsname.h>
41 #include <sys/mdesc.h>
42 #include <sys/mdesc_impl.h>
47 #define LDMA_MODULE LDMA_NAME_SYSTEM
49 #define LDMA_NVERSIONS (sizeof (ldma_versions) / sizeof (ds_ver_t))
50 #define LDMA_NHANDLERS (sizeof (ldma_handlers) / sizeof (ldma_msg_handler_t))
52 static ldm_msg_func_t ldma_sys_get_sysinfo
;
53 static ldm_msg_func_t ldma_sys_get_chassisno
;
55 /* ptr to cached value of chassisno */
56 static char *ldma_sys_chassisno
= NULL
;
57 mutex_t ldma_chassisno_lock
= DEFAULTMUTEX
;
59 static ds_ver_t ldma_versions
[] = { { 1, 0 } };
61 static ldma_msg_handler_t ldma_handlers
[] = {
62 { LDMA_MSGSYS_GET_SYSINFO
, LDMA_MSGFLG_ACCESS_ANY
,
63 ldma_sys_get_sysinfo
},
64 { LDMA_MSGSYS_GET_CHASSISNO
, LDMA_MSGFLG_ACCESS_ANY
,
65 ldma_sys_get_chassisno
}
68 ldma_agent_info_t ldma_system_info
= {
70 ldma_versions
, LDMA_NVERSIONS
,
71 ldma_handlers
, LDMA_NHANDLERS
75 static ldma_request_status_t
76 ldma_sys_get_sysinfo(ds_ver_t
*ver
, ldma_message_header_t
*request
,
77 size_t request_dlen
, ldma_message_header_t
**replyp
, size_t *reply_dlenp
)
79 ldma_message_header_t
*reply
;
81 size_t syslen
, nodlen
, rellen
, maclen
, verlen
;
86 LDMA_DBG("GET_SYSINFO");
88 if (request
->msg_info
!= 0 || request_dlen
!= 0) {
89 status
= LDMA_REQ_INVALID
;
93 if (uname(&name
) == -1) {
94 LDMA_DBG("GET_SYSINFO: uname failed with error %d", errno
);
95 status
= LDMA_REQ_FAILED
;
99 syslen
= strlen(name
.sysname
) + 1;
100 nodlen
= strlen(name
.nodename
) + 1;
101 rellen
= strlen(name
.release
) + 1;
102 verlen
= strlen(name
.version
) + 1;
103 maclen
= strlen(name
.machine
) + 1;
105 rlen
= syslen
+ nodlen
+ rellen
+ verlen
+ maclen
;
107 reply
= ldma_alloc_result_msg(request
, rlen
);
110 status
= LDMA_REQ_FAILED
;
114 reply
->msg_info
= rlen
;
116 data
= LDMA_HDR2DATA(reply
);
118 (void) strcpy(data
, name
.sysname
);
121 (void) strcpy(data
, name
.nodename
);
124 (void) strcpy(data
, name
.release
);
127 (void) strcpy(data
, name
.version
);
130 (void) strcpy(data
, name
.machine
);
132 LDMA_DBG("GET_SYSINFO: return info=%u, {%s, %s, %s, %s, %s}", rlen
,
133 name
.sysname
, name
.nodename
, name
.release
, name
.version
,
139 return (LDMA_REQ_COMPLETED
);
142 LDMA_DBG("GET_SYSINFO: return error %d", status
);
147 * Wrapper for MD free: need unused size argument.
151 ldma_md_free(void *buf
, size_t n
)
157 * Wrapper for MD init: read PRI MD and invoke md_init_intern.
163 uint64_t *buf
= NULL
;
167 if (pri_init() == -1)
170 status
= pri_get(PRI_GET
, &token
, &buf
, malloc
, ldma_md_free
);
173 if (status
== (ssize_t
)(-1))
176 mdp
= md_init_intern(buf
, malloc
, ldma_md_free
);
182 * Wrapper for md_fini. Allow NULL md ptr and free MD buffer.
185 ldma_md_fini(void *md
)
187 md_impl_t
*mdp
= (md_impl_t
*)md
;
196 ldma_get_chassis_serialno(char **strp
)
199 mde_cookie_t
*component_nodes
, rootnode
;
200 int list_size
, ncomponents
, num_nodes
, i
;
201 char *component_type
, *serialno
;
204 (void) mutex_lock(&ldma_chassisno_lock
);
205 if (ldma_sys_chassisno
!= NULL
) {
206 *strp
= ldma_sys_chassisno
;
207 (void) mutex_unlock(&ldma_chassisno_lock
);
211 mdp
= ldma_md_init();
213 (void) mutex_unlock(&ldma_chassisno_lock
);
217 num_nodes
= md_node_count(mdp
);
218 list_size
= num_nodes
* sizeof (mde_cookie_t
);
219 component_nodes
= malloc(list_size
);
220 if (component_nodes
== NULL
) {
221 (void) mutex_unlock(&ldma_chassisno_lock
);
226 rootnode
= md_root_node(mdp
);
228 ncomponents
= md_scan_dag(mdp
, rootnode
, md_find_name(mdp
, "component"),
229 md_find_name(mdp
, "fwd"), component_nodes
);
231 for (i
= 0; i
< ncomponents
; i
++) {
232 if (md_get_prop_str(mdp
, component_nodes
[i
], "type",
235 if (strcmp(component_type
, "chassis") != 0)
237 if (md_get_prop_str(mdp
, component_nodes
[i
],
238 "serial_number", &serialno
) == 0) {
239 ldma_sys_chassisno
= strdup(serialno
);
240 *strp
= ldma_sys_chassisno
;
245 (void) mutex_unlock(&ldma_chassisno_lock
);
246 free(component_nodes
);
252 static ldma_request_status_t
253 ldma_sys_get_chassisno(ds_ver_t
*ver
, ldma_message_header_t
*request
,
254 size_t request_dlen
, ldma_message_header_t
**replyp
, size_t *reply_dlenp
)
256 ldma_message_header_t
*reply
;
262 LDMA_DBG("GET_CHASSISNO");
264 if (request
->msg_info
!= 0 || request_dlen
!= 0) {
265 status
= LDMA_REQ_INVALID
;
269 if (ldma_get_chassis_serialno(&str
) == 0) {
270 LDMA_DBG("GET_CHASSISNO: ldma_get_chassisno failed "
271 "with error %d", errno
);
272 status
= LDMA_REQ_FAILED
;
276 rlen
= strlen(str
) + 1;
278 reply
= ldma_alloc_result_msg(request
, rlen
);
281 status
= LDMA_REQ_FAILED
;
285 reply
->msg_info
= rlen
;
287 data
= LDMA_HDR2DATA(reply
);
289 (void) strcpy(data
, str
);
291 LDMA_DBG("GET_CHASSISNO: return info=%u, {%s}", rlen
, str
);
296 return (LDMA_REQ_COMPLETED
);
299 LDMA_DBG("GET_CHASSISNO: return error %d", status
);