1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <libipmi.h> 27 #include <stdio.h> 28 #include <string.h> 29 30 #include "ipmi_impl.h" 31 32 ipmi_deviceid_t * 33 ipmi_get_deviceid(ipmi_handle_t *ihp) 34 { 35 ipmi_cmd_t cmd, *resp; 36 uint16_t id_prod; 37 38 if (ihp->ih_deviceid != NULL) 39 return (ihp->ih_deviceid); 40 41 cmd.ic_netfn = IPMI_NETFN_APP; 42 cmd.ic_lun = 0; 43 cmd.ic_cmd = IPMI_CMD_GET_DEVICEID; 44 cmd.ic_data = NULL; 45 cmd.ic_dlen = 0; 46 47 if ((resp = ipmi_send(ihp, &cmd)) == NULL) 48 return (NULL); 49 50 if (resp->ic_dlen < sizeof (ipmi_deviceid_t)) { 51 (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL); 52 return (NULL); 53 } 54 55 /* 56 * The devid response data may include additional data beyond the end of 57 * the normal structure, so we copy the entire response. 58 */ 59 if ((ihp->ih_deviceid = ipmi_alloc(ihp, resp->ic_dlen)) == NULL) 60 return (NULL); 61 62 (void) memcpy(ihp->ih_deviceid, resp->ic_data, resp->ic_dlen); 63 id_prod = LE_IN16(&ihp->ih_deviceid->id_product); 64 (void) memcpy(&ihp->ih_deviceid->id_product, &id_prod, 65 sizeof (id_prod)); 66 ihp->ih_deviceid_len = resp->ic_dlen; 67 68 return (ihp->ih_deviceid); 69 } 70 71 /* 72 * Returns the firmware revision as a string. This does the work of converting 73 * the deviceid data into a human readable string (decoding the BCD values). 74 * It also encodes the fact that Sun ILOM includes the additional micro revision 75 * at the end of the deviceid information. 76 */ 77 const char * 78 ipmi_firmware_version(ipmi_handle_t *ihp) 79 { 80 ipmi_deviceid_t *dp; 81 uint8_t *auxrev; 82 size_t len; 83 char rev[128]; 84 int i; 85 86 if (ihp->ih_firmware_rev != NULL) 87 return (ihp->ih_firmware_rev); 88 89 if ((dp = ipmi_get_deviceid(ihp)) == NULL) 90 return (NULL); 91 92 /* 93 * Start with the major an minor revision numbers 94 */ 95 (void) snprintf(rev, sizeof (rev), "%d.%d", dp->id_firm_major, 96 ipmi_convert_bcd(dp->id_firm_minor)); 97 98 if (ipmi_is_sun_ilom(dp) && 99 ihp->ih_deviceid_len >= sizeof (ipmi_deviceid_t) + 4) { 100 /* 101 * With Sun ILOM we have the micro revision at the end of the 102 * deviceid. The first two bytes of the aux revision field are 103 * the platform version and release version. 104 */ 105 auxrev = (uint8_t *)dp + sizeof (ipmi_deviceid_t); 106 for (i = 0; i < 2; i++) { 107 if (auxrev[i] == 0) 108 continue; 109 110 len = strlen(rev); 111 (void) snprintf(rev + len, sizeof (rev) - len, ".%u", 112 auxrev[i]); 113 } 114 } 115 116 if ((ihp->ih_firmware_rev = ipmi_strdup(ihp, rev)) == NULL) 117 return (NULL); 118 119 return (ihp->ih_firmware_rev); 120 } 121 122 /* 123 * IPMI Get Channel Authentication Capabilities Command 124 * See Section 22.13 125 * 126 * Caller is responsible for free'ing returned ipmi_channel_auth_caps_t 127 */ 128 ipmi_channel_auth_caps_t * 129 ipmi_get_channel_auth_caps(ipmi_handle_t *ihp, uint8_t channel, uint8_t priv) 130 { 131 ipmi_cmd_t cmd, *resp; 132 uint8_t msg_data[2]; 133 ipmi_channel_auth_caps_t *caps; 134 135 if (channel > 0xF) { 136 (void) ipmi_set_error(ihp, EIPMI_INVALID_REQUEST, NULL); 137 return (NULL); 138 } 139 140 msg_data[0] = channel; 141 msg_data[1] = priv; 142 143 cmd.ic_netfn = IPMI_NETFN_APP; 144 cmd.ic_cmd = IPMI_CMD_GET_CHANNEL_AUTH_CAPS; 145 cmd.ic_data = msg_data; 146 cmd.ic_dlen = sizeof (msg_data); 147 cmd.ic_lun = 0; 148 149 if ((resp = ipmi_send(ihp, &cmd)) == NULL) 150 return (NULL); 151 152 if (resp->ic_dlen < sizeof (ipmi_channel_auth_caps_t)) { 153 (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL); 154 return (NULL); 155 } 156 157 if ((caps = ipmi_alloc(ihp, sizeof (ipmi_channel_auth_caps_t))) 158 == NULL) 159 /* ipmi errno set */ 160 return (NULL); 161 162 (void) memcpy(caps, resp->ic_data, sizeof (ipmi_channel_auth_caps_t)); 163 164 return (caps); 165 } 166 167 ipmi_channel_info_t * 168 ipmi_get_channel_info(ipmi_handle_t *ihp, int number) 169 { 170 ipmi_cmd_t cmd, *rsp; 171 uint8_t channel; 172 173 if (number > 0xF) { 174 (void) ipmi_set_error(ihp, EIPMI_INVALID_REQUEST, NULL); 175 return (NULL); 176 } 177 178 channel = (uint8_t)number; 179 180 cmd.ic_netfn = IPMI_NETFN_APP; 181 cmd.ic_lun = 0; 182 cmd.ic_cmd = IPMI_CMD_GET_CHANNEL_INFO; 183 cmd.ic_data = &channel; 184 cmd.ic_dlen = sizeof (channel); 185 186 if ((rsp = ipmi_send(ihp, &cmd)) == NULL) 187 return (NULL); 188 189 if (rsp->ic_dlen < sizeof (ipmi_channel_info_t)) { 190 (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL); 191 return (NULL); 192 } 193 194 return (rsp->ic_data); 195 } 196