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 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 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 * 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 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 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 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