Patrick Venture | 7dc4670 | 2018-08-08 09:43:33 -0700 | [diff] [blame] | 1 | /* |
| 2 | Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. |
| 3 | |
| 4 | Redistribution and use in source and binary forms, with or without |
| 5 | modification, are permitted provided that the following conditions |
| 6 | are met: |
| 7 | |
| 8 | Redistribution of source code must retain the above copyright |
| 9 | notice, this list of conditions and the following disclaimer. |
| 10 | |
| 11 | Redistribution in binary form must reproduce the above copyright |
| 12 | notice, this list of conditions and the following disclaimer in the |
| 13 | documentation and/or other materials provided with the distribution. |
| 14 | |
| 15 | Neither the name of Sun Microsystems, Inc. or the names of |
| 16 | contributors may be used to endorse or promote products derived |
| 17 | from this software without specific prior written permission. |
| 18 | |
| 19 | This software is provided "AS IS," without a warranty of any kind. |
| 20 | ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, |
| 21 | INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A |
| 22 | PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. |
| 23 | SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE |
| 24 | FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING |
| 25 | OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL |
| 26 | SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, |
| 27 | OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR |
| 28 | PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF |
| 29 | LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, |
| 30 | EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. |
| 31 | */ |
| 32 | #include <ipmitool/ipmi_intf.h> |
| 33 | #include <ipmitool/ipmi_mc.h> |
| 34 | #include <ipmitool/log.h> |
| 35 | |
| 36 | /* Duplicate this into our memory space. Nothing in our code path calls this |
| 37 | * in a critical path. |
| 38 | */ |
| 39 | static IPMI_OEM sel_iana = IPMI_OEM_UNKNOWN; |
| 40 | |
| 41 | const struct valstr completion_code_vals[] = { |
| 42 | {0x00, "Command completed normally"}, |
| 43 | {0xc0, "Node busy"}, |
| 44 | {0xc1, "Invalid command"}, |
| 45 | {0xc2, "Invalid command on LUN"}, |
| 46 | {0xc3, "Timeout"}, |
| 47 | {0xc4, "Out of space"}, |
| 48 | {0xc5, "Reservation cancelled or invalid"}, |
| 49 | {0xc6, "Request data truncated"}, |
| 50 | {0xc7, "Request data length invalid"}, |
| 51 | {0xc8, "Request data field length limit exceeded"}, |
| 52 | {0xc9, "Parameter out of range"}, |
| 53 | {0xca, "Cannot return number of requested data bytes"}, |
| 54 | {0xcb, "Requested sensor, data, or record not found"}, |
| 55 | {0xcc, "Invalid data field in request"}, |
| 56 | {0xcd, "Command illegal for specified sensor or record type"}, |
| 57 | {0xce, "Command response could not be provided"}, |
| 58 | {0xcf, "Cannot execute duplicated request"}, |
| 59 | {0xd0, "SDR Repository in update mode"}, |
| 60 | {0xd1, "Device firmeware in update mode"}, |
| 61 | {0xd2, "BMC initialization in progress"}, |
| 62 | {0xd3, "Destination unavailable"}, |
| 63 | {0xd4, "Insufficient privilege level"}, |
| 64 | {0xd5, "Command not supported in present state"}, |
| 65 | {0xd6, "Cannot execute command, command disabled"}, |
| 66 | {0xff, "Unspecified error"}, |
| 67 | {0x00, NULL}}; |
| 68 | |
| 69 | const char* val2str(uint16_t val, const struct valstr* vs) |
| 70 | { |
| 71 | static char un_str[32]; |
| 72 | int i; |
| 73 | |
| 74 | for (i = 0; vs[i].str != NULL; i++) |
| 75 | { |
| 76 | if (vs[i].val == val) |
| 77 | return vs[i].str; |
| 78 | } |
| 79 | |
| 80 | memset(un_str, 0, 32); |
| 81 | snprintf(un_str, 32, "Unknown (0x%02X)", val); |
| 82 | |
| 83 | return un_str; |
| 84 | } |
| 85 | |
| 86 | void ipmi_intf_session_set_timeout(struct ipmi_intf* intf, uint32_t timeout) |
| 87 | { |
| 88 | intf->ssn_params.timeout = timeout; |
| 89 | } |
| 90 | |
| 91 | void ipmi_intf_session_set_retry(struct ipmi_intf* intf, int retry) |
| 92 | { |
| 93 | intf->ssn_params.retry = retry; |
| 94 | } |
| 95 | |
| 96 | /* Nullify the methods we don't care about. */ |
| 97 | void lprintf(int level, const char* format, ...) |
| 98 | { |
| 99 | return; |
| 100 | } |
| 101 | void lperror(int level, const char* format, ...) |
| 102 | { |
| 103 | return; |
| 104 | } |
| 105 | |
| 106 | int verbose = 0; |
| 107 | |
| 108 | const char* buf2str_extended(const uint8_t* buf, int len, const char* sep) |
| 109 | { |
| 110 | static char str[BUF2STR_MAXIMUM_OUTPUT_SIZE]; |
| 111 | char* cur; |
| 112 | int i; |
| 113 | int sz; |
| 114 | int left; |
| 115 | int sep_len; |
| 116 | |
| 117 | if (buf == NULL) |
| 118 | { |
| 119 | snprintf(str, sizeof(str), "<NULL>"); |
| 120 | return (const char*)str; |
| 121 | } |
| 122 | cur = str; |
| 123 | left = sizeof(str); |
| 124 | if (sep) |
| 125 | { |
| 126 | sep_len = strlen(sep); |
| 127 | } |
| 128 | else |
| 129 | { |
| 130 | sep_len = 0; |
| 131 | } |
| 132 | for (i = 0; i < len; i++) |
| 133 | { |
| 134 | /* may return more than 2, depending on locale */ |
| 135 | sz = snprintf(cur, left, "%2.2x", buf[i]); |
| 136 | if (sz >= left) |
| 137 | { |
| 138 | /* buffer overflow, truncate */ |
| 139 | break; |
| 140 | } |
| 141 | cur += sz; |
| 142 | left -= sz; |
| 143 | /* do not write separator after last byte */ |
| 144 | if (sep && i != (len - 1)) |
| 145 | { |
| 146 | if (sep_len >= left) |
| 147 | { |
| 148 | break; |
| 149 | } |
| 150 | strncpy(cur, sep, left - sz); |
| 151 | cur += sep_len; |
| 152 | left -= sep_len; |
| 153 | } |
| 154 | } |
| 155 | *cur = '\0'; |
| 156 | |
| 157 | return (const char*)str; |
| 158 | } |
| 159 | |
| 160 | const char* buf2str(const uint8_t* buf, int len) |
| 161 | { |
| 162 | return buf2str_extended(buf, len, NULL); |
| 163 | } |
| 164 | |
| 165 | uint8_t ipmi_csum(uint8_t* d, int s) |
| 166 | { |
| 167 | uint8_t c = 0; |
| 168 | for (; s > 0; s--, d++) |
| 169 | c += *d; |
| 170 | return -c; |
| 171 | } |
| 172 | |
| 173 | void printbuf(const uint8_t* buf, int len, const char* desc) |
| 174 | { |
| 175 | int i; |
| 176 | |
| 177 | if (len <= 0) |
| 178 | return; |
| 179 | |
| 180 | if (verbose < 1) |
| 181 | return; |
| 182 | |
| 183 | fprintf(stderr, "%s (%d bytes)\n", desc, len); |
| 184 | for (i = 0; i < len; i++) |
| 185 | { |
| 186 | if (((i % 16) == 0) && (i != 0)) |
| 187 | fprintf(stderr, "\n"); |
| 188 | fprintf(stderr, " %2.2x", buf[i]); |
| 189 | } |
| 190 | fprintf(stderr, "\n"); |
| 191 | } |
| 192 | |
| 193 | IPMI_OEM |
| 194 | ipmi_get_oem(struct ipmi_intf* intf) |
| 195 | { |
| 196 | /* Execute a Get Device ID command to determine the OEM */ |
| 197 | struct ipmi_rs* rsp; |
| 198 | struct ipmi_rq req; |
| 199 | struct ipm_devid_rsp* devid; |
| 200 | |
| 201 | if (intf->fd == 0) |
| 202 | { |
| 203 | if (sel_iana != IPMI_OEM_UNKNOWN) |
| 204 | { |
| 205 | return sel_iana; |
| 206 | } |
| 207 | return IPMI_OEM_UNKNOWN; |
| 208 | } |
| 209 | |
| 210 | /* |
| 211 | * Return the cached manufacturer id if the device is open and |
| 212 | * we got an identified OEM owner. Otherwise just attempt to read |
| 213 | * it. |
| 214 | */ |
| 215 | if (intf->opened && intf->manufacturer_id != IPMI_OEM_UNKNOWN) |
| 216 | { |
| 217 | return intf->manufacturer_id; |
| 218 | } |
| 219 | |
| 220 | memset(&req, 0, sizeof(req)); |
| 221 | req.msg.netfn = IPMI_NETFN_APP; |
| 222 | req.msg.cmd = BMC_GET_DEVICE_ID; |
| 223 | req.msg.data_len = 0; |
| 224 | |
| 225 | rsp = intf->sendrecv(intf, &req); |
| 226 | if (rsp == NULL) |
| 227 | { |
| 228 | lprintf(LOG_ERR, "Get Device ID command failed"); |
| 229 | return IPMI_OEM_UNKNOWN; |
| 230 | } |
| 231 | if (rsp->ccode > 0) |
| 232 | { |
| 233 | lprintf(LOG_ERR, "Get Device ID command failed: %#x %s", rsp->ccode, |
| 234 | val2str(rsp->ccode, completion_code_vals)); |
| 235 | return IPMI_OEM_UNKNOWN; |
| 236 | } |
| 237 | |
| 238 | devid = (struct ipm_devid_rsp*)rsp->data; |
| 239 | |
| 240 | lprintf(LOG_DEBUG, "Iana: %u", |
| 241 | IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id)); |
| 242 | |
| 243 | return IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id); |
| 244 | } |