blob: 3b64a35a7568b46027ed4b21b74841aefad9cddc [file] [log] [blame]
Patrick Venture7dc46702018-08-08 09:43:33 -07001/*
2Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions
6are met:
7
8Redistribution of source code must retain the above copyright
9notice, this list of conditions and the following disclaimer.
10
11Redistribution in binary form must reproduce the above copyright
12notice, this list of conditions and the following disclaimer in the
13documentation and/or other materials provided with the distribution.
14
15Neither the name of Sun Microsystems, Inc. or the names of
16contributors may be used to endorse or promote products derived
17from this software without specific prior written permission.
18
19This software is provided "AS IS," without a warranty of any kind.
20ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
26SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30EVEN 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 */
39static IPMI_OEM sel_iana = IPMI_OEM_UNKNOWN;
40
41const 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
69const 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
86void ipmi_intf_session_set_timeout(struct ipmi_intf* intf, uint32_t timeout)
87{
88 intf->ssn_params.timeout = timeout;
89}
90
91void 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. */
97void lprintf(int level, const char* format, ...)
98{
99 return;
100}
101void lperror(int level, const char* format, ...)
102{
103 return;
104}
105
106int verbose = 0;
107
108const 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
160const char* buf2str(const uint8_t* buf, int len)
161{
162 return buf2str_extended(buf, len, NULL);
163}
164
165uint8_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
173void 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
193IPMI_OEM
194ipmi_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}