19113a79cSeschrock /* 29113a79cSeschrock * CDDL HEADER START 39113a79cSeschrock * 49113a79cSeschrock * The contents of this file are subject to the terms of the 59113a79cSeschrock * Common Development and Distribution License (the "License"). 69113a79cSeschrock * You may not use this file except in compliance with the License. 79113a79cSeschrock * 89113a79cSeschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 99113a79cSeschrock * or http://www.opensolaris.org/os/licensing. 109113a79cSeschrock * See the License for the specific language governing permissions 119113a79cSeschrock * and limitations under the License. 129113a79cSeschrock * 139113a79cSeschrock * When distributing Covered Code, include this CDDL HEADER in each 149113a79cSeschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 159113a79cSeschrock * If applicable, add the following below this CDDL HEADER, with the 169113a79cSeschrock * fields enclosed by brackets "[]" replaced with your own identifying 179113a79cSeschrock * information: Portions Copyright [yyyy] [name of copyright owner] 189113a79cSeschrock * 199113a79cSeschrock * CDDL HEADER END 209113a79cSeschrock */ 219113a79cSeschrock /* 22*aec67356SRobert Johnston * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 239113a79cSeschrock */ 249113a79cSeschrock 259113a79cSeschrock #include <libipmi.h> 262eeaed14Srobj #include <stdio.h> 279113a79cSeschrock #include <string.h> 289113a79cSeschrock 299113a79cSeschrock #include "ipmi_impl.h" 309113a79cSeschrock 319113a79cSeschrock ipmi_deviceid_t * 329113a79cSeschrock ipmi_get_deviceid(ipmi_handle_t *ihp) 339113a79cSeschrock { 349113a79cSeschrock ipmi_cmd_t cmd, *resp; 35918a0d8aSrobj uint16_t id_prod; 369113a79cSeschrock 372eeaed14Srobj if (ihp->ih_deviceid != NULL) 382eeaed14Srobj return (ihp->ih_deviceid); 399113a79cSeschrock 409113a79cSeschrock cmd.ic_netfn = IPMI_NETFN_APP; 419113a79cSeschrock cmd.ic_lun = 0; 429113a79cSeschrock cmd.ic_cmd = IPMI_CMD_GET_DEVICEID; 439113a79cSeschrock cmd.ic_data = NULL; 449113a79cSeschrock cmd.ic_dlen = 0; 459113a79cSeschrock 469113a79cSeschrock if ((resp = ipmi_send(ihp, &cmd)) == NULL) 479113a79cSeschrock return (NULL); 489113a79cSeschrock 499113a79cSeschrock if (resp->ic_dlen < sizeof (ipmi_deviceid_t)) { 509113a79cSeschrock (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL); 519113a79cSeschrock return (NULL); 529113a79cSeschrock } 539113a79cSeschrock 542eeaed14Srobj /* 552eeaed14Srobj * The devid response data may include additional data beyond the end of 562eeaed14Srobj * the normal structure, so we copy the entire response. 572eeaed14Srobj */ 582eeaed14Srobj if ((ihp->ih_deviceid = ipmi_alloc(ihp, resp->ic_dlen)) == NULL) 592eeaed14Srobj return (NULL); 609113a79cSeschrock 612eeaed14Srobj (void) memcpy(ihp->ih_deviceid, resp->ic_data, resp->ic_dlen); 62918a0d8aSrobj id_prod = LE_IN16(&ihp->ih_deviceid->id_product); 63e1a24155Srobj (void) memcpy(&ihp->ih_deviceid->id_product, &id_prod, 64918a0d8aSrobj sizeof (id_prod)); 652eeaed14Srobj ihp->ih_deviceid_len = resp->ic_dlen; 662eeaed14Srobj 672eeaed14Srobj return (ihp->ih_deviceid); 682eeaed14Srobj } 692eeaed14Srobj 702eeaed14Srobj /* 712eeaed14Srobj * Returns the firmware revision as a string. This does the work of converting 722eeaed14Srobj * the deviceid data into a human readable string (decoding the BCD values). 732eeaed14Srobj * It also encodes the fact that Sun ILOM includes the additional micro revision 742eeaed14Srobj * at the end of the deviceid information. 752eeaed14Srobj */ 762eeaed14Srobj const char * 772eeaed14Srobj ipmi_firmware_version(ipmi_handle_t *ihp) 782eeaed14Srobj { 792eeaed14Srobj ipmi_deviceid_t *dp; 802eeaed14Srobj uint8_t *auxrev; 812eeaed14Srobj size_t len; 822eeaed14Srobj char rev[128]; 832eeaed14Srobj int i; 842eeaed14Srobj 852eeaed14Srobj if (ihp->ih_firmware_rev != NULL) 862eeaed14Srobj return (ihp->ih_firmware_rev); 872eeaed14Srobj 882eeaed14Srobj if ((dp = ipmi_get_deviceid(ihp)) == NULL) 892eeaed14Srobj return (NULL); 902eeaed14Srobj 912eeaed14Srobj /* 922eeaed14Srobj * Start with the major an minor revision numbers 932eeaed14Srobj */ 942eeaed14Srobj (void) snprintf(rev, sizeof (rev), "%d.%d", dp->id_firm_major, 952eeaed14Srobj ipmi_convert_bcd(dp->id_firm_minor)); 962eeaed14Srobj 972eeaed14Srobj if (ipmi_is_sun_ilom(dp) && 982eeaed14Srobj ihp->ih_deviceid_len >= sizeof (ipmi_deviceid_t) + 4) { 992eeaed14Srobj /* 1002eeaed14Srobj * With Sun ILOM we have the micro revision at the end of the 1012eeaed14Srobj * deviceid. The first two bytes of the aux revision field are 1022eeaed14Srobj * the platform version and release version. 1032eeaed14Srobj */ 1042eeaed14Srobj auxrev = (uint8_t *)dp + sizeof (ipmi_deviceid_t); 1052eeaed14Srobj for (i = 0; i < 2; i++) { 1062eeaed14Srobj if (auxrev[i] == 0) 1072eeaed14Srobj continue; 1082eeaed14Srobj 1092eeaed14Srobj len = strlen(rev); 1102eeaed14Srobj (void) snprintf(rev + len, sizeof (rev) - len, ".%u", 1112eeaed14Srobj auxrev[i]); 1122eeaed14Srobj } 1132eeaed14Srobj } 1142eeaed14Srobj 1152eeaed14Srobj if ((ihp->ih_firmware_rev = ipmi_strdup(ihp, rev)) == NULL) 1162eeaed14Srobj return (NULL); 1172eeaed14Srobj 1182eeaed14Srobj return (ihp->ih_firmware_rev); 1199113a79cSeschrock } 120283bfb4dSEric Schrock 12181d9f076SRobert Johnston /* 12281d9f076SRobert Johnston * IPMI Get Channel Authentication Capabilities Command 12381d9f076SRobert Johnston * See Section 22.13 12481d9f076SRobert Johnston * 12581d9f076SRobert Johnston * Caller is responsible for free'ing returned ipmi_channel_auth_caps_t 12681d9f076SRobert Johnston */ 12781d9f076SRobert Johnston ipmi_channel_auth_caps_t * 12881d9f076SRobert Johnston ipmi_get_channel_auth_caps(ipmi_handle_t *ihp, uint8_t channel, uint8_t priv) 12981d9f076SRobert Johnston { 13081d9f076SRobert Johnston ipmi_cmd_t cmd, *resp; 13181d9f076SRobert Johnston uint8_t msg_data[2]; 13281d9f076SRobert Johnston ipmi_channel_auth_caps_t *caps; 13381d9f076SRobert Johnston 13481d9f076SRobert Johnston if (channel > 0xF) { 13581d9f076SRobert Johnston (void) ipmi_set_error(ihp, EIPMI_INVALID_REQUEST, NULL); 13681d9f076SRobert Johnston return (NULL); 13781d9f076SRobert Johnston } 13881d9f076SRobert Johnston 13981d9f076SRobert Johnston msg_data[0] = channel; 14081d9f076SRobert Johnston msg_data[1] = priv; 14181d9f076SRobert Johnston 14281d9f076SRobert Johnston cmd.ic_netfn = IPMI_NETFN_APP; 14381d9f076SRobert Johnston cmd.ic_cmd = IPMI_CMD_GET_CHANNEL_AUTH_CAPS; 14481d9f076SRobert Johnston cmd.ic_data = msg_data; 14581d9f076SRobert Johnston cmd.ic_dlen = sizeof (msg_data); 14681d9f076SRobert Johnston cmd.ic_lun = 0; 14781d9f076SRobert Johnston 14881d9f076SRobert Johnston if ((resp = ipmi_send(ihp, &cmd)) == NULL) 14981d9f076SRobert Johnston return (NULL); 15081d9f076SRobert Johnston 15181d9f076SRobert Johnston if (resp->ic_dlen < sizeof (ipmi_channel_auth_caps_t)) { 15281d9f076SRobert Johnston (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL); 15381d9f076SRobert Johnston return (NULL); 15481d9f076SRobert Johnston } 15581d9f076SRobert Johnston 15681d9f076SRobert Johnston if ((caps = ipmi_alloc(ihp, sizeof (ipmi_channel_auth_caps_t))) 15781d9f076SRobert Johnston == NULL) 15881d9f076SRobert Johnston /* ipmi errno set */ 15981d9f076SRobert Johnston return (NULL); 16081d9f076SRobert Johnston 16181d9f076SRobert Johnston (void) memcpy(caps, resp->ic_data, sizeof (ipmi_channel_auth_caps_t)); 16281d9f076SRobert Johnston 16381d9f076SRobert Johnston return (caps); 16481d9f076SRobert Johnston } 16581d9f076SRobert Johnston 166283bfb4dSEric Schrock ipmi_channel_info_t * 167283bfb4dSEric Schrock ipmi_get_channel_info(ipmi_handle_t *ihp, int number) 168283bfb4dSEric Schrock { 169283bfb4dSEric Schrock ipmi_cmd_t cmd, *rsp; 170283bfb4dSEric Schrock uint8_t channel; 171283bfb4dSEric Schrock 172283bfb4dSEric Schrock if (number > 0xF) { 173283bfb4dSEric Schrock (void) ipmi_set_error(ihp, EIPMI_INVALID_REQUEST, NULL); 174283bfb4dSEric Schrock return (NULL); 175283bfb4dSEric Schrock } 176283bfb4dSEric Schrock 177283bfb4dSEric Schrock channel = (uint8_t)number; 178283bfb4dSEric Schrock 179283bfb4dSEric Schrock cmd.ic_netfn = IPMI_NETFN_APP; 180283bfb4dSEric Schrock cmd.ic_lun = 0; 181283bfb4dSEric Schrock cmd.ic_cmd = IPMI_CMD_GET_CHANNEL_INFO; 182283bfb4dSEric Schrock cmd.ic_data = &channel; 183283bfb4dSEric Schrock cmd.ic_dlen = sizeof (channel); 184283bfb4dSEric Schrock 185283bfb4dSEric Schrock if ((rsp = ipmi_send(ihp, &cmd)) == NULL) 186283bfb4dSEric Schrock return (NULL); 187283bfb4dSEric Schrock 188283bfb4dSEric Schrock if (rsp->ic_dlen < sizeof (ipmi_channel_info_t)) { 189283bfb4dSEric Schrock (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL); 190283bfb4dSEric Schrock return (NULL); 191283bfb4dSEric Schrock } 192283bfb4dSEric Schrock 193283bfb4dSEric Schrock return (rsp->ic_data); 194283bfb4dSEric Schrock } 195*aec67356SRobert Johnston 196*aec67356SRobert Johnston /* 197*aec67356SRobert Johnston * IPMI Chassis Identify Command 198*aec67356SRobert Johnston * See Section 28.5 199*aec67356SRobert Johnston */ 200*aec67356SRobert Johnston int 201*aec67356SRobert Johnston ipmi_chassis_identify(ipmi_handle_t *ihp, boolean_t enable) 202*aec67356SRobert Johnston { 203*aec67356SRobert Johnston ipmi_cmd_t cmd; 204*aec67356SRobert Johnston uint8_t msg_data[2]; 205*aec67356SRobert Johnston 206*aec67356SRobert Johnston if (enable) { 207*aec67356SRobert Johnston msg_data[0] = 0; 208*aec67356SRobert Johnston msg_data[1] = 1; 209*aec67356SRobert Johnston } else { 210*aec67356SRobert Johnston msg_data[0] = 0; 211*aec67356SRobert Johnston msg_data[1] = 0; 212*aec67356SRobert Johnston } 213*aec67356SRobert Johnston 214*aec67356SRobert Johnston cmd.ic_netfn = IPMI_NETFN_CHASSIS; 215*aec67356SRobert Johnston cmd.ic_cmd = IPMI_CMD_CHASSIS_IDENTIFY; 216*aec67356SRobert Johnston cmd.ic_data = msg_data; 217*aec67356SRobert Johnston cmd.ic_dlen = sizeof (msg_data); 218*aec67356SRobert Johnston cmd.ic_lun = 0; 219*aec67356SRobert Johnston 220*aec67356SRobert Johnston if (ipmi_send(ihp, &cmd) == NULL) 221*aec67356SRobert Johnston return (-1); 222*aec67356SRobert Johnston 223*aec67356SRobert Johnston return (0); 224*aec67356SRobert Johnston } 225