1 /*
2 * IPMI BMC emulation
3 *
4 * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25 #include "qemu/osdep.h"
26 #include "system/system.h"
27 #include "qemu/timer.h"
28 #include "hw/ipmi/ipmi.h"
29 #include "qemu/error-report.h"
30 #include "qemu/module.h"
31 #include "hw/loader.h"
32 #include "hw/qdev-properties.h"
33 #include "hw/qdev-properties-system.h"
34 #include "migration/vmstate.h"
35
36 #define IPMI_NETFN_CHASSIS 0x00
37
38 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
39 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
40 #define IPMI_CMD_CHASSIS_CONTROL 0x02
41 #define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09
42
43 #define IPMI_NETFN_SENSOR_EVENT 0x04
44
45 #define IPMI_CMD_PLATFORM_EVENT_MSG 0x02
46 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
47 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
48 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
49 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
50 #define IPMI_CMD_GET_SENSOR_READING 0x2d
51 #define IPMI_CMD_SET_SENSOR_TYPE 0x2e
52 #define IPMI_CMD_GET_SENSOR_TYPE 0x2f
53 #define IPMI_CMD_SET_SENSOR_READING 0x30
54
55 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
56
57 #define IPMI_CMD_GET_DEVICE_ID 0x01
58 #define IPMI_CMD_COLD_RESET 0x02
59 #define IPMI_CMD_WARM_RESET 0x03
60 #define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
61 #define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
62 #define IPMI_CMD_GET_DEVICE_GUID 0x08
63 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
64 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
65 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
66 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
67 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
68 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
69 #define IPMI_CMD_GET_MSG_FLAGS 0x31
70 #define IPMI_CMD_GET_MSG 0x33
71 #define IPMI_CMD_SEND_MSG 0x34
72 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
73 #define IPMI_CMD_GET_CHANNEL_INFO 0x42
74
75 #define IPMI_NETFN_STORAGE 0x0a
76
77 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
78 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
79 #define IPMI_CMD_RESERVE_SDR_REP 0x22
80 #define IPMI_CMD_GET_SDR 0x23
81 #define IPMI_CMD_ADD_SDR 0x24
82 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
83 #define IPMI_CMD_DELETE_SDR 0x26
84 #define IPMI_CMD_CLEAR_SDR_REP 0x27
85 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
86 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
87 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
88 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
89 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
90 #define IPMI_CMD_GET_FRU_AREA_INFO 0x10
91 #define IPMI_CMD_READ_FRU_DATA 0x11
92 #define IPMI_CMD_WRITE_FRU_DATA 0x12
93 #define IPMI_CMD_GET_SEL_INFO 0x40
94 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
95 #define IPMI_CMD_RESERVE_SEL 0x42
96 #define IPMI_CMD_GET_SEL_ENTRY 0x43
97 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
98 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
99 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
100 #define IPMI_CMD_CLEAR_SEL 0x47
101 #define IPMI_CMD_GET_SEL_TIME 0x48
102 #define IPMI_CMD_SET_SEL_TIME 0x49
103
104
105 /* Same as a timespec struct. */
106 struct ipmi_time {
107 long tv_sec;
108 long tv_nsec;
109 };
110
111 #define MAX_SEL_SIZE 128
112
113 typedef struct IPMISel {
114 uint8_t sel[MAX_SEL_SIZE][16];
115 unsigned int next_free;
116 long time_offset;
117 uint16_t reservation;
118 uint8_t last_addition[4];
119 uint8_t last_clear[4];
120 uint8_t overflow;
121 } IPMISel;
122
123 #define MAX_SDR_SIZE 16384
124
125 typedef struct IPMISdr {
126 uint8_t sdr[MAX_SDR_SIZE];
127 unsigned int next_free;
128 uint16_t next_rec_id;
129 uint16_t reservation;
130 uint8_t last_addition[4];
131 uint8_t last_clear[4];
132 uint8_t overflow;
133 } IPMISdr;
134
135 typedef struct IPMIFru {
136 char *filename;
137 unsigned int nentries;
138 uint16_t areasize;
139 uint8_t *data;
140 } IPMIFru;
141
142 typedef struct IPMISensor {
143 uint8_t status;
144 uint8_t reading;
145 uint16_t states_suppt;
146 uint16_t assert_suppt;
147 uint16_t deassert_suppt;
148 uint16_t states;
149 uint16_t assert_states;
150 uint16_t deassert_states;
151 uint16_t assert_enable;
152 uint16_t deassert_enable;
153 uint8_t sensor_type;
154 uint8_t evt_reading_type_code;
155 } IPMISensor;
156 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
157 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
158 !!(v))
159 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
160 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
161 ((!!(v)) << 6))
162 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
163 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
164 ((!!(v)) << 7))
165 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
166 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
167 (v & 0xc0))
168 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
169
170 #define MAX_SENSORS 20
171 #define IPMI_WATCHDOG_SENSOR 0
172
173 #define MAX_NETFNS 64
174
175 typedef struct IPMIRcvBufEntry {
176 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
177 uint8_t len;
178 uint8_t buf[MAX_IPMI_MSG_SIZE];
179 } IPMIRcvBufEntry;
180
181 struct IPMIBmcSim {
182 IPMIBmc parent;
183
184 QEMUTimer *timer;
185
186 uint8_t bmc_global_enables;
187 uint8_t msg_flags;
188
189 bool watchdog_initialized;
190 uint8_t watchdog_use;
191 uint8_t watchdog_action;
192 uint8_t watchdog_pretimeout; /* In seconds */
193 uint8_t watchdog_expired;
194 uint16_t watchdog_timeout; /* in 100's of milliseconds */
195
196 bool watchdog_running;
197 bool watchdog_preaction_ran;
198 int64_t watchdog_expiry;
199
200 uint8_t device_id;
201 uint8_t ipmi_version;
202 uint8_t device_rev;
203 uint8_t fwrev1;
204 uint8_t fwrev2;
205 uint32_t mfg_id;
206 uint16_t product_id;
207
208 uint8_t restart_cause;
209
210 uint8_t acpi_power_state[2];
211 QemuUUID uuid;
212
213 IPMISel sel;
214 IPMISdr sdr;
215 IPMIFru fru;
216 IPMISensor sensors[MAX_SENSORS];
217 char *sdr_filename;
218
219 /* Odd netfns are for responses, so we only need the even ones. */
220 const IPMINetfn *netfns[MAX_NETFNS / 2];
221
222 /* We allow one event in the buffer */
223 uint8_t evtbuf[16];
224
225 QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
226 };
227
228 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
229 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
230 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
231 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
232 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
233 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
234 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
235 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
236 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
237
238 #define IPMI_BMC_GLOBAL_ENABLES_SUPPORTED 0x0f
239 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
240 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
241 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
242 #define IPMI_BMC_EVENT_LOG_BIT 3
243 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
244 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
245 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
246 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
247 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
248 (1 << IPMI_BMC_EVENT_LOG_BIT))
249 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
250 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
251
252 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
253 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
254 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
255 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
256 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
257 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
258 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
259 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
260 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
261 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
262 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
263 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
264 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
265 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
266 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
267
268 #define RSP_BUFFER_INITIALIZER { }
269
rsp_buffer_pushmore(RspBuffer * rsp,uint8_t * bytes,unsigned int n)270 static inline void rsp_buffer_pushmore(RspBuffer *rsp, uint8_t *bytes,
271 unsigned int n)
272 {
273 if (rsp->len + n >= sizeof(rsp->buffer)) {
274 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
275 return;
276 }
277
278 memcpy(&rsp->buffer[rsp->len], bytes, n);
279 rsp->len += n;
280 }
281
282 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
283
ipmi_gettime(struct ipmi_time * time)284 static void ipmi_gettime(struct ipmi_time *time)
285 {
286 int64_t stime;
287
288 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
289 time->tv_sec = stime / 1000000000LL;
290 time->tv_nsec = stime % 1000000000LL;
291 }
292
ipmi_getmonotime(void)293 static int64_t ipmi_getmonotime(void)
294 {
295 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
296 }
297
ipmi_timeout(void * opaque)298 static void ipmi_timeout(void *opaque)
299 {
300 IPMIBmcSim *ibs = opaque;
301
302 ipmi_sim_handle_timeout(ibs);
303 }
304
set_timestamp(IPMIBmcSim * ibs,uint8_t * ts)305 static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
306 {
307 unsigned int val;
308 struct ipmi_time now;
309
310 ipmi_gettime(&now);
311 val = now.tv_sec + ibs->sel.time_offset;
312 ts[0] = val & 0xff;
313 ts[1] = (val >> 8) & 0xff;
314 ts[2] = (val >> 16) & 0xff;
315 ts[3] = (val >> 24) & 0xff;
316 }
317
sdr_inc_reservation(IPMISdr * sdr)318 static void sdr_inc_reservation(IPMISdr *sdr)
319 {
320 sdr->reservation++;
321 if (sdr->reservation == 0) {
322 sdr->reservation = 1;
323 }
324 }
325
sdr_add_entry(IPMIBmcSim * ibs,const struct ipmi_sdr_header * sdrh_entry,unsigned int len,uint16_t * recid)326 static int sdr_add_entry(IPMIBmcSim *ibs,
327 const struct ipmi_sdr_header *sdrh_entry,
328 unsigned int len, uint16_t *recid)
329 {
330 struct ipmi_sdr_header *sdrh =
331 (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
332
333 if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
334 return 1;
335 }
336
337 if (ipmi_sdr_length(sdrh_entry) != len) {
338 return 1;
339 }
340
341 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
342 ibs->sdr.overflow = 1;
343 return 1;
344 }
345
346 memcpy(sdrh, sdrh_entry, len);
347 sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff;
348 sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
349 sdrh->sdr_version = 0x51; /* Conform to IPMI 1.5 spec */
350
351 if (recid) {
352 *recid = ibs->sdr.next_rec_id;
353 }
354 ibs->sdr.next_rec_id++;
355 set_timestamp(ibs, ibs->sdr.last_addition);
356 ibs->sdr.next_free += len;
357 sdr_inc_reservation(&ibs->sdr);
358 return 0;
359 }
360
sdr_find_entry(IPMISdr * sdr,uint16_t recid,unsigned int * retpos,uint16_t * nextrec)361 static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
362 unsigned int *retpos, uint16_t *nextrec)
363 {
364 unsigned int pos = *retpos;
365
366 while (pos < sdr->next_free) {
367 struct ipmi_sdr_header *sdrh =
368 (struct ipmi_sdr_header *) &sdr->sdr[pos];
369 uint16_t trec = ipmi_sdr_recid(sdrh);
370 unsigned int nextpos = pos + ipmi_sdr_length(sdrh);
371
372 if (trec == recid) {
373 if (nextrec) {
374 if (nextpos >= sdr->next_free) {
375 *nextrec = 0xffff;
376 } else {
377 *nextrec = (sdr->sdr[nextpos] |
378 (sdr->sdr[nextpos + 1] << 8));
379 }
380 }
381 *retpos = pos;
382 return 0;
383 }
384 pos = nextpos;
385 }
386 return 1;
387 }
388
ipmi_bmc_sdr_find(IPMIBmc * b,uint16_t recid,const struct ipmi_sdr_compact ** sdr,uint16_t * nextrec)389 int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
390 const struct ipmi_sdr_compact **sdr, uint16_t *nextrec)
391
392 {
393 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
394 unsigned int pos;
395
396 pos = 0;
397 if (sdr_find_entry(&ibs->sdr, recid, &pos, nextrec)) {
398 return -1;
399 }
400
401 *sdr = (const struct ipmi_sdr_compact *) &ibs->sdr.sdr[pos];
402 return 0;
403 }
404
sel_inc_reservation(IPMISel * sel)405 static void sel_inc_reservation(IPMISel *sel)
406 {
407 sel->reservation++;
408 if (sel->reservation == 0) {
409 sel->reservation = 1;
410 }
411 }
412
413 /* Returns 1 if the SEL is full and can't hold the event. */
sel_add_event(IPMIBmcSim * ibs,uint8_t * event)414 static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
415 {
416 uint8_t ts[4];
417
418 event[0] = 0xff;
419 event[1] = 0xff;
420 set_timestamp(ibs, ts);
421 if (event[2] < 0xe0) { /* Don't set timestamps for type 0xe0-0xff. */
422 memcpy(event + 3, ts, 4);
423 }
424 if (ibs->sel.next_free == MAX_SEL_SIZE) {
425 ibs->sel.overflow = 1;
426 return 1;
427 }
428 event[0] = ibs->sel.next_free & 0xff;
429 event[1] = (ibs->sel.next_free >> 8) & 0xff;
430 memcpy(ibs->sel.last_addition, ts, 4);
431 memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
432 ibs->sel.next_free++;
433 sel_inc_reservation(&ibs->sel);
434 return 0;
435 }
436
attn_set(IPMIBmcSim * ibs)437 static int attn_set(IPMIBmcSim *ibs)
438 {
439 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
440 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
441 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
442 }
443
attn_irq_enabled(IPMIBmcSim * ibs)444 static int attn_irq_enabled(IPMIBmcSim *ibs)
445 {
446 return (IPMI_BMC_MSG_INTS_ON(ibs) &&
447 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs) ||
448 IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs)))
449 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
450 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
451 }
452
ipmi_bmc_gen_event(IPMIBmc * b,uint8_t * evt,bool log)453 void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log)
454 {
455 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
456 IPMIInterface *s = ibs->parent.intf;
457 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
458
459 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
460 return;
461 }
462
463 if (log && IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
464 sel_add_event(ibs, evt);
465 }
466
467 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
468 return;
469 }
470
471 memcpy(ibs->evtbuf, evt, 16);
472 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
473 k->set_atn(s, 1, attn_irq_enabled(ibs));
474 }
gen_event(IPMIBmcSim * ibs,unsigned int sens_num,uint8_t deassert,uint8_t evd1,uint8_t evd2,uint8_t evd3)475 static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
476 uint8_t evd1, uint8_t evd2, uint8_t evd3)
477 {
478 IPMIInterface *s = ibs->parent.intf;
479 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
480 uint8_t evt[16];
481 IPMISensor *sens = ibs->sensors + sens_num;
482
483 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
484 return;
485 }
486 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
487 return;
488 }
489
490 evt[2] = 0x2; /* System event record */
491 evt[7] = ibs->parent.slave_addr;
492 evt[8] = 0;
493 evt[9] = 0x04; /* Format version */
494 evt[10] = sens->sensor_type;
495 evt[11] = sens_num;
496 evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
497 evt[13] = evd1;
498 evt[14] = evd2;
499 evt[15] = evd3;
500
501 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
502 sel_add_event(ibs, evt);
503 }
504
505 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
506 return;
507 }
508
509 memcpy(ibs->evtbuf, evt, 16);
510 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
511 k->set_atn(s, 1, attn_irq_enabled(ibs));
512 }
513
sensor_set_discrete_bit(IPMIBmcSim * ibs,unsigned int sensor,unsigned int bit,unsigned int val,uint8_t evd1,uint8_t evd2,uint8_t evd3,bool do_log)514 static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
515 unsigned int bit, unsigned int val,
516 uint8_t evd1, uint8_t evd2, uint8_t evd3,
517 bool do_log)
518 {
519 IPMISensor *sens;
520 uint16_t mask;
521
522 if (sensor >= MAX_SENSORS) {
523 return;
524 }
525 if (bit >= 16) {
526 return;
527 }
528
529 mask = (1 << bit);
530 sens = ibs->sensors + sensor;
531 if (val) {
532 sens->states |= mask & sens->states_suppt;
533 if (sens->assert_states & mask) {
534 return; /* Already asserted */
535 }
536 sens->assert_states |= mask & sens->assert_suppt;
537 if (do_log && (sens->assert_enable & mask & sens->assert_states)) {
538 /* Send an event on assert */
539 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
540 }
541 } else {
542 sens->states &= ~(mask & sens->states_suppt);
543 if (sens->deassert_states & mask) {
544 return; /* Already deasserted */
545 }
546 sens->deassert_states |= mask & sens->deassert_suppt;
547 if (do_log && (sens->deassert_enable & mask & sens->deassert_states)) {
548 /* Send an event on deassert */
549 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
550 }
551 }
552 }
553
ipmi_init_sensors_from_sdrs(IPMIBmcSim * s)554 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
555 {
556 unsigned int i, pos;
557 IPMISensor *sens;
558
559 for (i = 0; i < MAX_SENSORS; i++) {
560 memset(s->sensors + i, 0, sizeof(*sens));
561 }
562
563 pos = 0;
564 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
565 struct ipmi_sdr_compact *sdr =
566 (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
567 unsigned int len = sdr->header.rec_length;
568
569 if (len < 20) {
570 continue;
571 }
572 if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
573 continue; /* Not a sensor SDR we set from */
574 }
575
576 if (sdr->sensor_owner_number >= MAX_SENSORS) {
577 continue;
578 }
579 sens = s->sensors + sdr->sensor_owner_number;
580
581 IPMI_SENSOR_SET_PRESENT(sens, 1);
582 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
583 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
584 sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
585 sens->deassert_suppt =
586 sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
587 sens->states_suppt =
588 sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
589 sens->sensor_type = sdr->sensor_type;
590 sens->evt_reading_type_code = sdr->reading_type & 0x7f;
591
592 /* Enable all the events that are supported. */
593 sens->assert_enable = sens->assert_suppt;
594 sens->deassert_enable = sens->deassert_suppt;
595 }
596 }
597
ipmi_sim_register_netfn(IPMIBmcSim * s,unsigned int netfn,const IPMINetfn * netfnd)598 int ipmi_sim_register_netfn(IPMIBmcSim *s, unsigned int netfn,
599 const IPMINetfn *netfnd)
600 {
601 if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
602 return -1;
603 }
604 s->netfns[netfn / 2] = netfnd;
605 return 0;
606 }
607
ipmi_get_handler(IPMIBmcSim * ibs,unsigned int netfn,unsigned int cmd)608 static const IPMICmdHandler *ipmi_get_handler(IPMIBmcSim *ibs,
609 unsigned int netfn,
610 unsigned int cmd)
611 {
612 const IPMICmdHandler *hdl;
613
614 if (netfn & 1 || netfn >= MAX_NETFNS || !ibs->netfns[netfn / 2]) {
615 return NULL;
616 }
617
618 if (cmd >= ibs->netfns[netfn / 2]->cmd_nums) {
619 return NULL;
620 }
621
622 hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd];
623 if (!hdl->cmd_handler) {
624 return NULL;
625 }
626
627 return hdl;
628 }
629
next_timeout(IPMIBmcSim * ibs)630 static void next_timeout(IPMIBmcSim *ibs)
631 {
632 int64_t next;
633 if (ibs->watchdog_running) {
634 next = ibs->watchdog_expiry;
635 } else {
636 /* Wait a minute */
637 next = ipmi_getmonotime() + 60 * 1000000000LL;
638 }
639 timer_mod_ns(ibs->timer, next);
640 }
641
ipmi_sim_handle_command(IPMIBmc * b,uint8_t * cmd,unsigned int cmd_len,unsigned int max_cmd_len,uint8_t msg_id)642 static void ipmi_sim_handle_command(IPMIBmc *b,
643 uint8_t *cmd, unsigned int cmd_len,
644 unsigned int max_cmd_len,
645 uint8_t msg_id)
646 {
647 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
648 IPMIInterface *s = ibs->parent.intf;
649 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
650 const IPMICmdHandler *hdl;
651 RspBuffer rsp = RSP_BUFFER_INITIALIZER;
652
653 /* Set up the response, set the low bit of NETFN. */
654 /* Note that max_rsp_len must be at least 3 */
655 if (sizeof(rsp.buffer) < 3) {
656 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
657 goto out;
658 }
659
660 rsp_buffer_push(&rsp, cmd[0] | 0x04);
661 rsp_buffer_push(&rsp, cmd[1]);
662 rsp_buffer_push(&rsp, 0); /* Assume success */
663
664 /* If it's too short or it was truncated, return an error. */
665 if (cmd_len < 2) {
666 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
667 goto out;
668 }
669 if (cmd_len > max_cmd_len) {
670 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
671 goto out;
672 }
673
674 if ((cmd[0] & 0x03) != 0) {
675 /* Only have stuff on LUN 0 */
676 rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN);
677 goto out;
678 }
679
680 hdl = ipmi_get_handler(ibs, cmd[0] >> 2, cmd[1]);
681 if (!hdl) {
682 rsp_buffer_set_error(&rsp, IPMI_CC_INVALID_CMD);
683 goto out;
684 }
685
686 if (cmd_len < hdl->cmd_len_min) {
687 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
688 goto out;
689 }
690
691 hdl->cmd_handler(ibs, cmd, cmd_len, &rsp);
692
693 out:
694 k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
695
696 next_timeout(ibs);
697 }
698
ipmi_sim_handle_timeout(IPMIBmcSim * ibs)699 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
700 {
701 IPMIInterface *s = ibs->parent.intf;
702 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
703 bool do_log = !IPMI_BMC_WATCHDOG_GET_DONT_LOG(ibs);
704
705 if (!ibs->watchdog_running) {
706 goto out;
707 }
708
709 if (!ibs->watchdog_preaction_ran) {
710 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
711 case IPMI_BMC_WATCHDOG_PRE_NMI:
712 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
713 k->do_hw_op(s, IPMI_SEND_NMI, 0);
714 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
715 0xc8, (2 << 4) | 0xf, 0xff,
716 do_log);
717 break;
718
719 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
720 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
721 k->set_atn(s, 1, attn_irq_enabled(ibs));
722 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
723 0xc8, (3 << 4) | 0xf, 0xff,
724 do_log);
725 break;
726
727 default:
728 goto do_full_expiry;
729 }
730
731 ibs->watchdog_preaction_ran = 1;
732 /* Issued the pretimeout, do the rest of the timeout now. */
733 ibs->watchdog_expiry = ipmi_getmonotime();
734 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
735 goto out;
736 }
737
738 do_full_expiry:
739 ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
740 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
741 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
742 case IPMI_BMC_WATCHDOG_ACTION_NONE:
743 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
744 0xc0, ibs->watchdog_use & 0xf, 0xff,
745 do_log);
746 break;
747
748 case IPMI_BMC_WATCHDOG_ACTION_RESET:
749 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
750 0xc1, ibs->watchdog_use & 0xf, 0xff,
751 do_log);
752 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
753 break;
754
755 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
756 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
757 0xc2, ibs->watchdog_use & 0xf, 0xff,
758 do_log);
759 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
760 break;
761
762 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
763 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
764 0xc3, ibs->watchdog_use & 0xf, 0xff,
765 do_log);
766 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
767 break;
768 }
769
770 out:
771 next_timeout(ibs);
772 }
773
chassis_capabilities(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)774 static void chassis_capabilities(IPMIBmcSim *ibs,
775 uint8_t *cmd, unsigned int cmd_len,
776 RspBuffer *rsp)
777 {
778 rsp_buffer_push(rsp, 0);
779 rsp_buffer_push(rsp, ibs->parent.slave_addr);
780 rsp_buffer_push(rsp, ibs->parent.slave_addr);
781 rsp_buffer_push(rsp, ibs->parent.slave_addr);
782 rsp_buffer_push(rsp, ibs->parent.slave_addr);
783 }
784
chassis_status(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)785 static void chassis_status(IPMIBmcSim *ibs,
786 uint8_t *cmd, unsigned int cmd_len,
787 RspBuffer *rsp)
788 {
789 rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */
790 rsp_buffer_push(rsp, 0);
791 rsp_buffer_push(rsp, 0);
792 rsp_buffer_push(rsp, 0);
793 }
794
chassis_control(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)795 static void chassis_control(IPMIBmcSim *ibs,
796 uint8_t *cmd, unsigned int cmd_len,
797 RspBuffer *rsp)
798 {
799 IPMIInterface *s = ibs->parent.intf;
800 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
801
802 switch (cmd[2] & 0xf) {
803 case 0: /* power down */
804 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0));
805 break;
806 case 1: /* power up */
807 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0));
808 break;
809 case 2: /* power cycle */
810 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0));
811 break;
812 case 3: /* hard reset */
813 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0));
814 break;
815 case 4: /* pulse diagnostic interrupt */
816 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0));
817 break;
818 case 5: /* soft shutdown via ACPI by overtemp emulation */
819 rsp_buffer_set_error(rsp, k->do_hw_op(s,
820 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0));
821 break;
822 default:
823 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
824 return;
825 }
826 }
827
chassis_get_sys_restart_cause(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)828 static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
829 uint8_t *cmd, unsigned int cmd_len,
830 RspBuffer *rsp)
831
832 {
833 rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */
834 rsp_buffer_push(rsp, 0); /* Channel 0 */
835 }
836
get_device_id(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)837 static void get_device_id(IPMIBmcSim *ibs,
838 uint8_t *cmd, unsigned int cmd_len,
839 RspBuffer *rsp)
840 {
841 rsp_buffer_push(rsp, ibs->device_id);
842 rsp_buffer_push(rsp, ibs->device_rev & 0xf);
843 rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
844 rsp_buffer_push(rsp, ibs->fwrev2);
845 rsp_buffer_push(rsp, ibs->ipmi_version);
846 rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */
847 rsp_buffer_push(rsp, ibs->mfg_id & 0xff);
848 rsp_buffer_push(rsp, (ibs->mfg_id >> 8) & 0xff);
849 rsp_buffer_push(rsp, (ibs->mfg_id >> 16) & 0xff);
850 rsp_buffer_push(rsp, ibs->product_id & 0xff);
851 rsp_buffer_push(rsp, (ibs->product_id >> 8) & 0xff);
852 }
853
set_global_enables(IPMIBmcSim * ibs,uint8_t val)854 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
855 {
856 IPMIInterface *s = ibs->parent.intf;
857 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
858 bool irqs_on;
859
860 ibs->bmc_global_enables = val;
861
862 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
863 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
864
865 k->set_irq_enable(s, irqs_on);
866 }
867
cold_reset(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)868 static void cold_reset(IPMIBmcSim *ibs,
869 uint8_t *cmd, unsigned int cmd_len,
870 RspBuffer *rsp)
871 {
872 IPMIInterface *s = ibs->parent.intf;
873 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
874
875 /* Disable all interrupts */
876 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
877
878 if (k->reset) {
879 k->reset(s, true);
880 }
881 }
882
warm_reset(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)883 static void warm_reset(IPMIBmcSim *ibs,
884 uint8_t *cmd, unsigned int cmd_len,
885 RspBuffer *rsp)
886 {
887 IPMIInterface *s = ibs->parent.intf;
888 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
889
890 if (k->reset) {
891 k->reset(s, false);
892 }
893 }
set_acpi_power_state(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)894 static void set_acpi_power_state(IPMIBmcSim *ibs,
895 uint8_t *cmd, unsigned int cmd_len,
896 RspBuffer *rsp)
897 {
898 ibs->acpi_power_state[0] = cmd[2];
899 ibs->acpi_power_state[1] = cmd[3];
900 }
901
get_acpi_power_state(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)902 static void get_acpi_power_state(IPMIBmcSim *ibs,
903 uint8_t *cmd, unsigned int cmd_len,
904 RspBuffer *rsp)
905 {
906 rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
907 rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
908 }
909
get_device_guid(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)910 static void get_device_guid(IPMIBmcSim *ibs,
911 uint8_t *cmd, unsigned int cmd_len,
912 RspBuffer *rsp)
913 {
914 unsigned int i;
915
916 /* An uninitialized uuid is all zeros, use that to know if it is set. */
917 for (i = 0; i < 16; i++) {
918 if (ibs->uuid.data[i]) {
919 goto uuid_set;
920 }
921 }
922 /* No uuid is set, return an error. */
923 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_CMD);
924 return;
925
926 uuid_set:
927 for (i = 0; i < 16; i++) {
928 rsp_buffer_push(rsp, ibs->uuid.data[i]);
929 }
930 }
931
set_bmc_global_enables(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)932 static void set_bmc_global_enables(IPMIBmcSim *ibs,
933 uint8_t *cmd, unsigned int cmd_len,
934 RspBuffer *rsp)
935 {
936 uint8_t val = cmd[2];
937
938 if (val & ~IPMI_BMC_GLOBAL_ENABLES_SUPPORTED) {
939 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
940 return;
941 }
942
943 set_global_enables(ibs, val);
944 }
945
get_bmc_global_enables(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)946 static void get_bmc_global_enables(IPMIBmcSim *ibs,
947 uint8_t *cmd, unsigned int cmd_len,
948 RspBuffer *rsp)
949 {
950 rsp_buffer_push(rsp, ibs->bmc_global_enables);
951 }
952
clr_msg_flags(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)953 static void clr_msg_flags(IPMIBmcSim *ibs,
954 uint8_t *cmd, unsigned int cmd_len,
955 RspBuffer *rsp)
956 {
957 IPMIInterface *s = ibs->parent.intf;
958 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
959
960 ibs->msg_flags &= ~cmd[2];
961 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
962 }
963
get_msg_flags(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)964 static void get_msg_flags(IPMIBmcSim *ibs,
965 uint8_t *cmd, unsigned int cmd_len,
966 RspBuffer *rsp)
967 {
968 rsp_buffer_push(rsp, ibs->msg_flags);
969 }
970
read_evt_msg_buf(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)971 static void read_evt_msg_buf(IPMIBmcSim *ibs,
972 uint8_t *cmd, unsigned int cmd_len,
973 RspBuffer *rsp)
974 {
975 IPMIInterface *s = ibs->parent.intf;
976 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
977 unsigned int i;
978
979 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
980 rsp_buffer_set_error(rsp, 0x80);
981 return;
982 }
983 for (i = 0; i < 16; i++) {
984 rsp_buffer_push(rsp, ibs->evtbuf[i]);
985 }
986 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
987 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
988 }
989
get_msg(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)990 static void get_msg(IPMIBmcSim *ibs,
991 uint8_t *cmd, unsigned int cmd_len,
992 RspBuffer *rsp)
993 {
994 IPMIRcvBufEntry *msg;
995
996 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
997 rsp_buffer_set_error(rsp, 0x80); /* Queue empty */
998 return;
999 }
1000 rsp_buffer_push(rsp, 0); /* Channel 0 */
1001 msg = QTAILQ_FIRST(&ibs->rcvbufs);
1002 rsp_buffer_pushmore(rsp, msg->buf, msg->len);
1003 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
1004 g_free(msg);
1005
1006 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
1007 IPMIInterface *s = ibs->parent.intf;
1008 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1009
1010 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1011 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
1012 }
1013 }
1014
1015 static unsigned char
ipmb_checksum(unsigned char * data,int size,unsigned char csum)1016 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
1017 {
1018 for (; size > 0; size--, data++) {
1019 csum += *data;
1020 }
1021
1022 return -csum;
1023 }
1024
send_msg(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1025 static void send_msg(IPMIBmcSim *ibs,
1026 uint8_t *cmd, unsigned int cmd_len,
1027 RspBuffer *rsp)
1028 {
1029 IPMIInterface *s = ibs->parent.intf;
1030 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1031 IPMIRcvBufEntry *msg;
1032 uint8_t *buf;
1033 uint8_t netfn, rqLun, rsLun, rqSeq;
1034
1035 if (cmd[2] != IPMI_CHANNEL_IPMB) {
1036 /* We only handle channel 0h (IPMB) with no options */
1037 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1038 return;
1039 }
1040
1041 if (cmd_len < 10) {
1042 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
1043 return;
1044 }
1045
1046 if (cmd[3] != 0x40) {
1047 /* We only emulate a MC at address 0x40. */
1048 rsp_buffer_set_error(rsp, 0x83); /* NAK on write */
1049 return;
1050 }
1051
1052 cmd += 3; /* Skip the header. */
1053 cmd_len -= 3;
1054
1055 /*
1056 * At this point we "send" the message successfully. Any error will
1057 * be returned in the response.
1058 */
1059 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
1060 cmd[3] != 0x20) { /* Improper response address */
1061 return; /* No response */
1062 }
1063
1064 netfn = cmd[1] >> 2;
1065 rqLun = cmd[4] & 0x3;
1066 rsLun = cmd[1] & 0x3;
1067 rqSeq = cmd[4] >> 2;
1068
1069 if (rqLun != 2) {
1070 /* We only support LUN 2 coming back to us. */
1071 return;
1072 }
1073
1074 msg = g_malloc(sizeof(*msg));
1075 msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
1076 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
1077 msg->buf[2] = cmd[0]; /* rsSA */
1078 msg->buf[3] = (rqSeq << 2) | rsLun;
1079 msg->buf[4] = cmd[5]; /* Cmd */
1080 msg->buf[5] = 0; /* Completion Code */
1081 msg->len = 6;
1082
1083 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
1084 /* Not a command we handle. */
1085 msg->buf[5] = IPMI_CC_INVALID_CMD;
1086 goto end_msg;
1087 }
1088
1089 buf = msg->buf + msg->len; /* After the CC */
1090 buf[0] = 0;
1091 buf[1] = 0;
1092 buf[2] = 0;
1093 buf[3] = 0;
1094 buf[4] = 0x51;
1095 buf[5] = 0;
1096 buf[6] = 0;
1097 buf[7] = 0;
1098 buf[8] = 0;
1099 buf[9] = 0;
1100 buf[10] = 0;
1101 msg->len += 11;
1102
1103 end_msg:
1104 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1105 msg->len++;
1106 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1107 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1108 k->set_atn(s, 1, attn_irq_enabled(ibs));
1109 }
1110
do_watchdog_reset(IPMIBmcSim * ibs)1111 static void do_watchdog_reset(IPMIBmcSim *ibs)
1112 {
1113 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1114 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1115 ibs->watchdog_running = 0;
1116 return;
1117 }
1118 ibs->watchdog_preaction_ran = 0;
1119
1120
1121 /* Timeout is in tenths of a second, offset is in seconds */
1122 ibs->watchdog_expiry = ipmi_getmonotime();
1123 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1124 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1125 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1126 }
1127 ibs->watchdog_running = 1;
1128 }
1129
reset_watchdog_timer(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1130 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1131 uint8_t *cmd, unsigned int cmd_len,
1132 RspBuffer *rsp)
1133 {
1134 if (!ibs->watchdog_initialized) {
1135 rsp_buffer_set_error(rsp, 0x80);
1136 return;
1137 }
1138 do_watchdog_reset(ibs);
1139 }
1140
set_watchdog_timer(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1141 static void set_watchdog_timer(IPMIBmcSim *ibs,
1142 uint8_t *cmd, unsigned int cmd_len,
1143 RspBuffer *rsp)
1144 {
1145 IPMIInterface *s = ibs->parent.intf;
1146 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1147 unsigned int val;
1148
1149 val = cmd[2] & 0x7; /* Validate use */
1150 if (val == 0 || val > 5) {
1151 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1152 return;
1153 }
1154 val = cmd[3] & 0x7; /* Validate action */
1155 switch (val) {
1156 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1157 break;
1158
1159 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1160 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1));
1161 break;
1162
1163 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1164 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1));
1165 break;
1166
1167 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1168 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1));
1169 break;
1170
1171 default:
1172 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1173 }
1174 if (rsp->buffer[2]) {
1175 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1176 return;
1177 }
1178
1179 val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1180 switch (val) {
1181 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1182 case IPMI_BMC_WATCHDOG_PRE_NONE:
1183 break;
1184
1185 case IPMI_BMC_WATCHDOG_PRE_NMI:
1186 if (k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1187 /* NMI not supported. */
1188 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1189 return;
1190 }
1191 break;
1192
1193 default:
1194 /* We don't support PRE_SMI */
1195 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1196 return;
1197 }
1198
1199 ibs->watchdog_initialized = 1;
1200 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1201 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1202 ibs->watchdog_pretimeout = cmd[4];
1203 ibs->watchdog_expired &= ~cmd[5];
1204 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1205 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1206 do_watchdog_reset(ibs);
1207 } else {
1208 ibs->watchdog_running = 0;
1209 }
1210 }
1211
get_watchdog_timer(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1212 static void get_watchdog_timer(IPMIBmcSim *ibs,
1213 uint8_t *cmd, unsigned int cmd_len,
1214 RspBuffer *rsp)
1215 {
1216 rsp_buffer_push(rsp, ibs->watchdog_use);
1217 rsp_buffer_push(rsp, ibs->watchdog_action);
1218 rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
1219 rsp_buffer_push(rsp, ibs->watchdog_expired);
1220 rsp_buffer_push(rsp, ibs->watchdog_timeout & 0xff);
1221 rsp_buffer_push(rsp, (ibs->watchdog_timeout >> 8) & 0xff);
1222 if (ibs->watchdog_running) {
1223 long timeout;
1224 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1225 / 100000000);
1226 rsp_buffer_push(rsp, timeout & 0xff);
1227 rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
1228 } else {
1229 rsp_buffer_push(rsp, 0);
1230 rsp_buffer_push(rsp, 0);
1231 }
1232 }
1233
get_channel_info(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1234 static void get_channel_info(IPMIBmcSim *ibs,
1235 uint8_t *cmd, unsigned int cmd_len,
1236 RspBuffer *rsp)
1237 {
1238 IPMIInterface *s = ibs->parent.intf;
1239 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1240 IPMIFwInfo info = {};
1241 uint8_t ch = cmd[2] & 0x0f;
1242
1243 /* Only define channel 0h (IPMB) and Fh (system interface) */
1244
1245 if (ch == 0x0e) { /* "This channel" */
1246 ch = IPMI_CHANNEL_SYSTEM;
1247 }
1248 rsp_buffer_push(rsp, ch);
1249
1250 if (ch != IPMI_CHANNEL_IPMB && ch != IPMI_CHANNEL_SYSTEM) {
1251 /* Not a supported channel */
1252 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1253 return;
1254 }
1255
1256 if (k->get_fwinfo) {
1257 k->get_fwinfo(s, &info);
1258 }
1259
1260 if (ch == IPMI_CHANNEL_IPMB) {
1261 rsp_buffer_push(rsp, IPMI_CHANNEL_MEDIUM_IPMB);
1262 rsp_buffer_push(rsp, IPMI_CHANNEL_PROTOCOL_IPMB);
1263 } else { /* IPMI_CHANNEL_SYSTEM */
1264 rsp_buffer_push(rsp, IPMI_CHANNEL_MEDIUM_SYSTEM);
1265 rsp_buffer_push(rsp, info.ipmi_channel_protocol);
1266 }
1267
1268 rsp_buffer_push(rsp, 0x00); /* Session-less */
1269
1270 /* IPMI Enterprise Number for Vendor ID */
1271 rsp_buffer_push(rsp, 0xf2);
1272 rsp_buffer_push(rsp, 0x1b);
1273 rsp_buffer_push(rsp, 0x00);
1274
1275 if (ch == IPMI_CHANNEL_SYSTEM) {
1276 uint8_t irq;
1277
1278 if (info.irq_source == IPMI_ISA_IRQ) {
1279 irq = info.interrupt_number;
1280 } else if (info.irq_source == IPMI_PCI_IRQ) {
1281 irq = 0x10 + info.interrupt_number;
1282 } else {
1283 irq = 0xff; /* no interrupt / unspecified */
1284 }
1285
1286 /* Both interrupts use the same irq number */
1287 rsp_buffer_push(rsp, irq);
1288 rsp_buffer_push(rsp, irq);
1289 } else {
1290 /* Reserved */
1291 rsp_buffer_push(rsp, 0x00);
1292 rsp_buffer_push(rsp, 0x00);
1293 }
1294 }
1295
get_sdr_rep_info(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1296 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1297 uint8_t *cmd, unsigned int cmd_len,
1298 RspBuffer *rsp)
1299 {
1300 unsigned int i;
1301
1302 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */
1303 rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
1304 rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
1305 rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1306 rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1307 for (i = 0; i < 4; i++) {
1308 rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
1309 }
1310 for (i = 0; i < 4; i++) {
1311 rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
1312 }
1313 /* Only modal support, reserve supported */
1314 rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
1315 }
1316
reserve_sdr_rep(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1317 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1318 uint8_t *cmd, unsigned int cmd_len,
1319 RspBuffer *rsp)
1320 {
1321 rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
1322 rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
1323 }
1324
get_sdr(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1325 static void get_sdr(IPMIBmcSim *ibs,
1326 uint8_t *cmd, unsigned int cmd_len,
1327 RspBuffer *rsp)
1328 {
1329 unsigned int pos;
1330 uint16_t nextrec;
1331 struct ipmi_sdr_header *sdrh;
1332
1333 if (cmd[6]) {
1334 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1335 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1336 return;
1337 }
1338 }
1339
1340 pos = 0;
1341 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1342 &pos, &nextrec)) {
1343 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1344 return;
1345 }
1346
1347 sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1348
1349 if (cmd[6] > ipmi_sdr_length(sdrh)) {
1350 rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE);
1351 return;
1352 }
1353
1354 rsp_buffer_push(rsp, nextrec & 0xff);
1355 rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
1356
1357 if (cmd[7] == 0xff) {
1358 cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1359 }
1360
1361 if ((cmd[7] + rsp->len) > sizeof(rsp->buffer)) {
1362 rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES);
1363 return;
1364 }
1365
1366 rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1367 }
1368
add_sdr(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1369 static void add_sdr(IPMIBmcSim *ibs,
1370 uint8_t *cmd, unsigned int cmd_len,
1371 RspBuffer *rsp)
1372 {
1373 uint16_t recid;
1374 struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1375
1376 if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1377 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1378 return;
1379 }
1380 rsp_buffer_push(rsp, recid & 0xff);
1381 rsp_buffer_push(rsp, (recid >> 8) & 0xff);
1382 }
1383
clear_sdr_rep(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1384 static void clear_sdr_rep(IPMIBmcSim *ibs,
1385 uint8_t *cmd, unsigned int cmd_len,
1386 RspBuffer *rsp)
1387 {
1388 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1389 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1390 return;
1391 }
1392
1393 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1394 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1395 return;
1396 }
1397 if (cmd[7] == 0xaa) {
1398 ibs->sdr.next_free = 0;
1399 ibs->sdr.overflow = 0;
1400 set_timestamp(ibs, ibs->sdr.last_clear);
1401 rsp_buffer_push(rsp, 1); /* Erasure complete */
1402 sdr_inc_reservation(&ibs->sdr);
1403 } else if (cmd[7] == 0) {
1404 rsp_buffer_push(rsp, 1); /* Erasure complete */
1405 } else {
1406 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1407 return;
1408 }
1409 }
1410
get_sel_info(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1411 static void get_sel_info(IPMIBmcSim *ibs,
1412 uint8_t *cmd, unsigned int cmd_len,
1413 RspBuffer *rsp)
1414 {
1415 unsigned int i, val;
1416
1417 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */
1418 rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
1419 rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
1420 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1421 rsp_buffer_push(rsp, val & 0xff);
1422 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1423 for (i = 0; i < 4; i++) {
1424 rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
1425 }
1426 for (i = 0; i < 4; i++) {
1427 rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
1428 }
1429 /* Only support Reserve SEL */
1430 rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
1431 }
1432
get_fru_area_info(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1433 static void get_fru_area_info(IPMIBmcSim *ibs,
1434 uint8_t *cmd, unsigned int cmd_len,
1435 RspBuffer *rsp)
1436 {
1437 uint8_t fruid;
1438 uint16_t fru_entry_size;
1439
1440 fruid = cmd[2];
1441
1442 if (fruid >= ibs->fru.nentries) {
1443 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1444 return;
1445 }
1446
1447 fru_entry_size = ibs->fru.areasize;
1448
1449 rsp_buffer_push(rsp, fru_entry_size & 0xff);
1450 rsp_buffer_push(rsp, fru_entry_size >> 8 & 0xff);
1451 rsp_buffer_push(rsp, 0x0);
1452 }
1453
read_fru_data(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1454 static void read_fru_data(IPMIBmcSim *ibs,
1455 uint8_t *cmd, unsigned int cmd_len,
1456 RspBuffer *rsp)
1457 {
1458 uint8_t fruid;
1459 uint16_t offset;
1460 int i;
1461 uint8_t *fru_entry;
1462 unsigned int count;
1463
1464 fruid = cmd[2];
1465 offset = (cmd[3] | cmd[4] << 8);
1466
1467 if (fruid >= ibs->fru.nentries) {
1468 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1469 return;
1470 }
1471
1472 if (offset >= ibs->fru.areasize - 1) {
1473 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1474 return;
1475 }
1476
1477 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1478
1479 count = MIN(cmd[5], ibs->fru.areasize - offset);
1480
1481 rsp_buffer_push(rsp, count & 0xff);
1482 for (i = 0; i < count; i++) {
1483 rsp_buffer_push(rsp, fru_entry[offset + i]);
1484 }
1485 }
1486
write_fru_data(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1487 static void write_fru_data(IPMIBmcSim *ibs,
1488 uint8_t *cmd, unsigned int cmd_len,
1489 RspBuffer *rsp)
1490 {
1491 uint8_t fruid;
1492 uint16_t offset;
1493 uint8_t *fru_entry;
1494 unsigned int count;
1495
1496 fruid = cmd[2];
1497 offset = (cmd[3] | cmd[4] << 8);
1498
1499 if (fruid >= ibs->fru.nentries) {
1500 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1501 return;
1502 }
1503
1504 if (offset >= ibs->fru.areasize - 1) {
1505 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1506 return;
1507 }
1508
1509 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1510
1511 count = MIN(cmd_len - 5, ibs->fru.areasize - offset);
1512
1513 memcpy(fru_entry + offset, cmd + 5, count);
1514
1515 rsp_buffer_push(rsp, count & 0xff);
1516 }
1517
reserve_sel(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1518 static void reserve_sel(IPMIBmcSim *ibs,
1519 uint8_t *cmd, unsigned int cmd_len,
1520 RspBuffer *rsp)
1521 {
1522 rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
1523 rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
1524 }
1525
get_sel_entry(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1526 static void get_sel_entry(IPMIBmcSim *ibs,
1527 uint8_t *cmd, unsigned int cmd_len,
1528 RspBuffer *rsp)
1529 {
1530 unsigned int val;
1531
1532 if (cmd[6]) {
1533 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1534 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1535 return;
1536 }
1537 }
1538 if (ibs->sel.next_free == 0) {
1539 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1540 return;
1541 }
1542 if (cmd[6] > 15) {
1543 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1544 return;
1545 }
1546 if (cmd[7] == 0xff) {
1547 cmd[7] = 16;
1548 } else if ((cmd[7] + cmd[6]) > 16) {
1549 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1550 return;
1551 } else {
1552 cmd[7] += cmd[6];
1553 }
1554
1555 val = cmd[4] | (cmd[5] << 8);
1556 if (val == 0xffff) {
1557 val = ibs->sel.next_free - 1;
1558 } else if (val >= ibs->sel.next_free) {
1559 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1560 return;
1561 }
1562 if ((val + 1) == ibs->sel.next_free) {
1563 rsp_buffer_push(rsp, 0xff);
1564 rsp_buffer_push(rsp, 0xff);
1565 } else {
1566 rsp_buffer_push(rsp, (val + 1) & 0xff);
1567 rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
1568 }
1569 for (; cmd[6] < cmd[7]; cmd[6]++) {
1570 rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
1571 }
1572 }
1573
add_sel_entry(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1574 static void add_sel_entry(IPMIBmcSim *ibs,
1575 uint8_t *cmd, unsigned int cmd_len,
1576 RspBuffer *rsp)
1577 {
1578 if (sel_add_event(ibs, cmd + 2)) {
1579 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1580 return;
1581 }
1582 /* sel_add_event fills in the record number. */
1583 rsp_buffer_push(rsp, cmd[2]);
1584 rsp_buffer_push(rsp, cmd[3]);
1585 }
1586
clear_sel(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1587 static void clear_sel(IPMIBmcSim *ibs,
1588 uint8_t *cmd, unsigned int cmd_len,
1589 RspBuffer *rsp)
1590 {
1591 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1592 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1593 return;
1594 }
1595
1596 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1597 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1598 return;
1599 }
1600 if (cmd[7] == 0xaa) {
1601 ibs->sel.next_free = 0;
1602 ibs->sel.overflow = 0;
1603 set_timestamp(ibs, ibs->sdr.last_clear);
1604 rsp_buffer_push(rsp, 1); /* Erasure complete */
1605 sel_inc_reservation(&ibs->sel);
1606 } else if (cmd[7] == 0) {
1607 rsp_buffer_push(rsp, 1); /* Erasure complete */
1608 } else {
1609 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1610 return;
1611 }
1612 }
1613
get_sel_time(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1614 static void get_sel_time(IPMIBmcSim *ibs,
1615 uint8_t *cmd, unsigned int cmd_len,
1616 RspBuffer *rsp)
1617 {
1618 uint32_t val;
1619 struct ipmi_time now;
1620
1621 ipmi_gettime(&now);
1622 val = now.tv_sec + ibs->sel.time_offset;
1623 rsp_buffer_push(rsp, val & 0xff);
1624 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1625 rsp_buffer_push(rsp, (val >> 16) & 0xff);
1626 rsp_buffer_push(rsp, (val >> 24) & 0xff);
1627 }
1628
set_sel_time(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1629 static void set_sel_time(IPMIBmcSim *ibs,
1630 uint8_t *cmd, unsigned int cmd_len,
1631 RspBuffer *rsp)
1632 {
1633 uint32_t val;
1634 struct ipmi_time now;
1635
1636 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1637 ipmi_gettime(&now);
1638 ibs->sel.time_offset = now.tv_sec - ((long) val);
1639 }
1640
platform_event_msg(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1641 static void platform_event_msg(IPMIBmcSim *ibs,
1642 uint8_t *cmd, unsigned int cmd_len,
1643 RspBuffer *rsp)
1644 {
1645 uint8_t event[16];
1646
1647 event[2] = 2; /* System event record */
1648 event[7] = cmd[2]; /* Generator ID */
1649 event[8] = 0;
1650 event[9] = cmd[3]; /* EvMRev */
1651 event[10] = cmd[4]; /* Sensor type */
1652 event[11] = cmd[5]; /* Sensor number */
1653 event[12] = cmd[6]; /* Event dir / Event type */
1654 event[13] = cmd[7]; /* Event data 1 */
1655 event[14] = cmd[8]; /* Event data 2 */
1656 event[15] = cmd[9]; /* Event data 3 */
1657
1658 if (sel_add_event(ibs, event)) {
1659 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1660 }
1661 }
1662
set_sensor_evt_enable(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1663 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1664 uint8_t *cmd, unsigned int cmd_len,
1665 RspBuffer *rsp)
1666 {
1667 IPMISensor *sens;
1668
1669 if ((cmd[2] >= MAX_SENSORS) ||
1670 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1671 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1672 return;
1673 }
1674 sens = ibs->sensors + cmd[2];
1675 switch ((cmd[3] >> 4) & 0x3) {
1676 case 0: /* Do not change */
1677 break;
1678 case 1: /* Enable bits */
1679 if (cmd_len > 4) {
1680 sens->assert_enable |= cmd[4];
1681 }
1682 if (cmd_len > 5) {
1683 sens->assert_enable |= cmd[5] << 8;
1684 }
1685 if (cmd_len > 6) {
1686 sens->deassert_enable |= cmd[6];
1687 }
1688 if (cmd_len > 7) {
1689 sens->deassert_enable |= cmd[7] << 8;
1690 }
1691 break;
1692 case 2: /* Disable bits */
1693 if (cmd_len > 4) {
1694 sens->assert_enable &= ~cmd[4];
1695 }
1696 if (cmd_len > 5) {
1697 sens->assert_enable &= ~(cmd[5] << 8);
1698 }
1699 if (cmd_len > 6) {
1700 sens->deassert_enable &= ~cmd[6];
1701 }
1702 if (cmd_len > 7) {
1703 sens->deassert_enable &= ~(cmd[7] << 8);
1704 }
1705 break;
1706 case 3:
1707 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1708 return;
1709 }
1710 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1711 }
1712
get_sensor_evt_enable(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1713 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1714 uint8_t *cmd, unsigned int cmd_len,
1715 RspBuffer *rsp)
1716 {
1717 IPMISensor *sens;
1718
1719 if ((cmd[2] >= MAX_SENSORS) ||
1720 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1721 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1722 return;
1723 }
1724 sens = ibs->sensors + cmd[2];
1725 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1726 rsp_buffer_push(rsp, sens->assert_enable & 0xff);
1727 rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
1728 rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
1729 rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
1730 }
1731
rearm_sensor_evts(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1732 static void rearm_sensor_evts(IPMIBmcSim *ibs,
1733 uint8_t *cmd, unsigned int cmd_len,
1734 RspBuffer *rsp)
1735 {
1736 IPMISensor *sens;
1737
1738 if ((cmd[2] >= MAX_SENSORS) ||
1739 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1740 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1741 return;
1742 }
1743 sens = ibs->sensors + cmd[2];
1744
1745 if ((cmd[3] & 0x80) == 0) {
1746 /* Just clear everything */
1747 sens->states = 0;
1748 return;
1749 }
1750 }
1751
get_sensor_evt_status(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1752 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1753 uint8_t *cmd, unsigned int cmd_len,
1754 RspBuffer *rsp)
1755 {
1756 IPMISensor *sens;
1757
1758 if ((cmd[2] >= MAX_SENSORS) ||
1759 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1760 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1761 return;
1762 }
1763 sens = ibs->sensors + cmd[2];
1764 rsp_buffer_push(rsp, sens->reading);
1765 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1766 rsp_buffer_push(rsp, sens->assert_states & 0xff);
1767 rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
1768 rsp_buffer_push(rsp, sens->deassert_states & 0xff);
1769 rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
1770 }
1771
get_sensor_reading(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1772 static void get_sensor_reading(IPMIBmcSim *ibs,
1773 uint8_t *cmd, unsigned int cmd_len,
1774 RspBuffer *rsp)
1775 {
1776 IPMISensor *sens;
1777
1778 if ((cmd[2] >= MAX_SENSORS) ||
1779 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1780 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1781 return;
1782 }
1783 sens = ibs->sensors + cmd[2];
1784 rsp_buffer_push(rsp, sens->reading);
1785 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1786 rsp_buffer_push(rsp, sens->states & 0xff);
1787 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1788 rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
1789 }
1790 }
1791
set_sensor_type(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1792 static void set_sensor_type(IPMIBmcSim *ibs,
1793 uint8_t *cmd, unsigned int cmd_len,
1794 RspBuffer *rsp)
1795 {
1796 IPMISensor *sens;
1797
1798
1799 if ((cmd[2] >= MAX_SENSORS) ||
1800 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1801 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1802 return;
1803 }
1804 sens = ibs->sensors + cmd[2];
1805 sens->sensor_type = cmd[3];
1806 sens->evt_reading_type_code = cmd[4] & 0x7f;
1807 }
1808
get_sensor_type(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1809 static void get_sensor_type(IPMIBmcSim *ibs,
1810 uint8_t *cmd, unsigned int cmd_len,
1811 RspBuffer *rsp)
1812 {
1813 IPMISensor *sens;
1814
1815
1816 if ((cmd[2] >= MAX_SENSORS) ||
1817 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1818 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1819 return;
1820 }
1821 sens = ibs->sensors + cmd[2];
1822 rsp_buffer_push(rsp, sens->sensor_type);
1823 rsp_buffer_push(rsp, sens->evt_reading_type_code);
1824 }
1825
1826 /*
1827 * bytes parameter
1828 * 1 sensor number
1829 * 2 operation (see below for bits meaning)
1830 * 3 sensor reading
1831 * 4:5 assertion states (optional)
1832 * 6:7 deassertion states (optional)
1833 * 8:10 event data 1,2,3 (optional)
1834 */
set_sensor_reading(IPMIBmcSim * ibs,uint8_t * cmd,unsigned int cmd_len,RspBuffer * rsp)1835 static void set_sensor_reading(IPMIBmcSim *ibs,
1836 uint8_t *cmd, unsigned int cmd_len,
1837 RspBuffer *rsp)
1838 {
1839 IPMISensor *sens;
1840 uint8_t evd1 = 0;
1841 uint8_t evd2 = 0;
1842 uint8_t evd3 = 0;
1843 uint8_t new_reading = 0;
1844 uint16_t new_assert_states = 0;
1845 uint16_t new_deassert_states = 0;
1846 bool change_reading = false;
1847 bool change_assert = false;
1848 bool change_deassert = false;
1849 enum {
1850 SENSOR_GEN_EVENT_NONE,
1851 SENSOR_GEN_EVENT_DATA,
1852 SENSOR_GEN_EVENT_BMC,
1853 } do_gen_event = SENSOR_GEN_EVENT_NONE;
1854
1855 if ((cmd[2] >= MAX_SENSORS) ||
1856 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1857 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1858 return;
1859 }
1860
1861 sens = ibs->sensors + cmd[2];
1862
1863 /* [1:0] Sensor Reading operation */
1864 switch ((cmd[3]) & 0x3) {
1865 case 0: /* Do not change */
1866 break;
1867 case 1: /* write given value to sensor reading byte */
1868 new_reading = cmd[4];
1869 if (sens->reading != new_reading) {
1870 change_reading = true;
1871 }
1872 break;
1873 case 2:
1874 case 3:
1875 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1876 return;
1877 }
1878
1879 /* [3:2] Deassertion bits operation */
1880 switch ((cmd[3] >> 2) & 0x3) {
1881 case 0: /* Do not change */
1882 break;
1883 case 1: /* write given value */
1884 if (cmd_len > 7) {
1885 new_deassert_states = cmd[7];
1886 change_deassert = true;
1887 }
1888 if (cmd_len > 8) {
1889 new_deassert_states |= (cmd[8] << 8);
1890 }
1891 break;
1892
1893 case 2: /* mask on */
1894 if (cmd_len > 7) {
1895 new_deassert_states = (sens->deassert_states | cmd[7]);
1896 change_deassert = true;
1897 }
1898 if (cmd_len > 8) {
1899 new_deassert_states |= (sens->deassert_states | (cmd[8] << 8));
1900 }
1901 break;
1902
1903 case 3: /* mask off */
1904 if (cmd_len > 7) {
1905 new_deassert_states = (sens->deassert_states & cmd[7]);
1906 change_deassert = true;
1907 }
1908 if (cmd_len > 8) {
1909 new_deassert_states |= (sens->deassert_states & (cmd[8] << 8));
1910 }
1911 break;
1912 }
1913
1914 if (change_deassert && (new_deassert_states == sens->deassert_states)) {
1915 change_deassert = false;
1916 }
1917
1918 /* [5:4] Assertion bits operation */
1919 switch ((cmd[3] >> 4) & 0x3) {
1920 case 0: /* Do not change */
1921 break;
1922 case 1: /* write given value */
1923 if (cmd_len > 5) {
1924 new_assert_states = cmd[5];
1925 change_assert = true;
1926 }
1927 if (cmd_len > 6) {
1928 new_assert_states |= (cmd[6] << 8);
1929 }
1930 break;
1931
1932 case 2: /* mask on */
1933 if (cmd_len > 5) {
1934 new_assert_states = (sens->assert_states | cmd[5]);
1935 change_assert = true;
1936 }
1937 if (cmd_len > 6) {
1938 new_assert_states |= (sens->assert_states | (cmd[6] << 8));
1939 }
1940 break;
1941
1942 case 3: /* mask off */
1943 if (cmd_len > 5) {
1944 new_assert_states = (sens->assert_states & cmd[5]);
1945 change_assert = true;
1946 }
1947 if (cmd_len > 6) {
1948 new_assert_states |= (sens->assert_states & (cmd[6] << 8));
1949 }
1950 break;
1951 }
1952
1953 if (change_assert && (new_assert_states == sens->assert_states)) {
1954 change_assert = false;
1955 }
1956
1957 if (cmd_len > 9) {
1958 evd1 = cmd[9];
1959 }
1960 if (cmd_len > 10) {
1961 evd2 = cmd[10];
1962 }
1963 if (cmd_len > 11) {
1964 evd3 = cmd[11];
1965 }
1966
1967 /* [7:6] Event Data Bytes operation */
1968 switch ((cmd[3] >> 6) & 0x3) {
1969 case 0: /*
1970 * Don’t use Event Data bytes from this command. BMC will
1971 * generate it's own Event Data bytes based on its sensor
1972 * implementation.
1973 */
1974 evd1 = evd2 = evd3 = 0x0;
1975 do_gen_event = SENSOR_GEN_EVENT_BMC;
1976 break;
1977 case 1: /*
1978 * Write given values to event data bytes including bits
1979 * [3:0] Event Data 1.
1980 */
1981 do_gen_event = SENSOR_GEN_EVENT_DATA;
1982 break;
1983 case 2: /*
1984 * Write given values to event data bytes excluding bits
1985 * [3:0] Event Data 1.
1986 */
1987 evd1 &= 0xf0;
1988 do_gen_event = SENSOR_GEN_EVENT_DATA;
1989 break;
1990 case 3:
1991 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1992 return;
1993 }
1994
1995 /*
1996 * Event Data Bytes operation and parameter are inconsistent. The
1997 * Specs are not clear on that topic but generating an error seems
1998 * correct.
1999 */
2000 if (do_gen_event == SENSOR_GEN_EVENT_DATA && cmd_len < 10) {
2001 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
2002 return;
2003 }
2004
2005 /* commit values */
2006 if (change_reading) {
2007 sens->reading = new_reading;
2008 }
2009
2010 if (change_assert) {
2011 sens->assert_states = new_assert_states;
2012 }
2013
2014 if (change_deassert) {
2015 sens->deassert_states = new_deassert_states;
2016 }
2017
2018 /* TODO: handle threshold sensor */
2019 if (!IPMI_SENSOR_IS_DISCRETE(sens)) {
2020 return;
2021 }
2022
2023 switch (do_gen_event) {
2024 case SENSOR_GEN_EVENT_DATA: {
2025 unsigned int bit = evd1 & 0xf;
2026 uint16_t mask = (1 << bit);
2027
2028 if (sens->assert_states & mask & sens->assert_enable) {
2029 gen_event(ibs, cmd[2], 0, evd1, evd2, evd3);
2030 }
2031
2032 if (sens->deassert_states & mask & sens->deassert_enable) {
2033 gen_event(ibs, cmd[2], 1, evd1, evd2, evd3);
2034 }
2035 break;
2036 }
2037 case SENSOR_GEN_EVENT_BMC:
2038 /*
2039 * TODO: generate event and event data bytes depending on the
2040 * sensor
2041 */
2042 break;
2043 case SENSOR_GEN_EVENT_NONE:
2044 break;
2045 }
2046 }
2047
2048 static const IPMICmdHandler chassis_cmds[] = {
2049 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
2050 [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
2051 [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
2052 [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
2053 };
2054 static const IPMINetfn chassis_netfn = {
2055 .cmd_nums = ARRAY_SIZE(chassis_cmds),
2056 .cmd_handlers = chassis_cmds
2057 };
2058
2059 static const IPMICmdHandler sensor_event_cmds[] = {
2060 [IPMI_CMD_PLATFORM_EVENT_MSG] = { platform_event_msg, 10 },
2061 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
2062 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
2063 [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
2064 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
2065 [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
2066 [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
2067 [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
2068 [IPMI_CMD_SET_SENSOR_READING] = { set_sensor_reading, 5 },
2069 };
2070 static const IPMINetfn sensor_event_netfn = {
2071 .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
2072 .cmd_handlers = sensor_event_cmds
2073 };
2074
2075 static const IPMICmdHandler app_cmds[] = {
2076 [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
2077 [IPMI_CMD_COLD_RESET] = { cold_reset },
2078 [IPMI_CMD_WARM_RESET] = { warm_reset },
2079 [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
2080 [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
2081 [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
2082 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
2083 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
2084 [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
2085 [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
2086 [IPMI_CMD_GET_MSG] = { get_msg },
2087 [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
2088 [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
2089 [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
2090 [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
2091 [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
2092 [IPMI_CMD_GET_CHANNEL_INFO] = { get_channel_info, 3 },
2093 };
2094 static const IPMINetfn app_netfn = {
2095 .cmd_nums = ARRAY_SIZE(app_cmds),
2096 .cmd_handlers = app_cmds
2097 };
2098
2099 static const IPMICmdHandler storage_cmds[] = {
2100 [IPMI_CMD_GET_FRU_AREA_INFO] = { get_fru_area_info, 3 },
2101 [IPMI_CMD_READ_FRU_DATA] = { read_fru_data, 5 },
2102 [IPMI_CMD_WRITE_FRU_DATA] = { write_fru_data, 5 },
2103 [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
2104 [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
2105 [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
2106 [IPMI_CMD_ADD_SDR] = { add_sdr },
2107 [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
2108 [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
2109 [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
2110 [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
2111 [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
2112 [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
2113 [IPMI_CMD_GET_SEL_TIME] = { get_sel_time },
2114 [IPMI_CMD_SET_SEL_TIME] = { set_sel_time, 6 },
2115 };
2116
2117 static const IPMINetfn storage_netfn = {
2118 .cmd_nums = ARRAY_SIZE(storage_cmds),
2119 .cmd_handlers = storage_cmds
2120 };
2121
register_cmds(IPMIBmcSim * s)2122 static void register_cmds(IPMIBmcSim *s)
2123 {
2124 ipmi_sim_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
2125 ipmi_sim_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
2126 ipmi_sim_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
2127 ipmi_sim_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
2128 }
2129
2130 static uint8_t init_sdrs[] = {
2131 /* Watchdog device */
2132 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
2133 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
2134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
2136 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
2137 };
2138
ipmi_sdr_init(IPMIBmcSim * ibs)2139 static void ipmi_sdr_init(IPMIBmcSim *ibs)
2140 {
2141 unsigned int i;
2142 int len;
2143 size_t sdrs_size;
2144 uint8_t *sdrs;
2145
2146 sdrs_size = sizeof(init_sdrs);
2147 sdrs = init_sdrs;
2148 if (ibs->sdr_filename &&
2149 !g_file_get_contents(ibs->sdr_filename, (gchar **) &sdrs, &sdrs_size,
2150 NULL)) {
2151 error_report("failed to load sdr file '%s'", ibs->sdr_filename);
2152 sdrs_size = sizeof(init_sdrs);
2153 sdrs = init_sdrs;
2154 }
2155
2156 for (i = 0; i < sdrs_size; i += len) {
2157 struct ipmi_sdr_header *sdrh;
2158
2159 if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
2160 error_report("Problem with recid 0x%4.4x", i);
2161 break;
2162 }
2163 sdrh = (struct ipmi_sdr_header *) &sdrs[i];
2164 len = ipmi_sdr_length(sdrh);
2165 if (i + len > sdrs_size) {
2166 error_report("Problem with recid 0x%4.4x", i);
2167 break;
2168 }
2169 sdr_add_entry(ibs, sdrh, len, NULL);
2170 }
2171
2172 if (sdrs != init_sdrs) {
2173 g_free(sdrs);
2174 }
2175 }
2176
2177 static const VMStateDescription vmstate_ipmi_sim = {
2178 .name = TYPE_IPMI_BMC_SIMULATOR,
2179 .version_id = 1,
2180 .minimum_version_id = 1,
2181 .fields = (const VMStateField[]) {
2182 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
2183 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
2184 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
2185 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
2186 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
2187 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
2188 VMSTATE_UINT8(watchdog_expired, IPMIBmcSim),
2189 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
2190 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
2191 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
2192 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
2193 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
2194 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
2195 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
2196 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
2197 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
2198 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
2199 IPMIBmcSim),
2200 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
2201 VMSTATE_END_OF_LIST()
2202 }
2203 };
2204
ipmi_fru_init(IPMIFru * fru)2205 static void ipmi_fru_init(IPMIFru *fru)
2206 {
2207 int fsize;
2208 int size = 0;
2209
2210 if (!fru->filename) {
2211 goto out;
2212 }
2213
2214 fsize = get_image_size(fru->filename);
2215 if (fsize > 0) {
2216 size = QEMU_ALIGN_UP(fsize, fru->areasize);
2217 fru->data = g_malloc0(size);
2218 if (load_image_size(fru->filename, fru->data, fsize) != fsize) {
2219 error_report("Could not load file '%s'", fru->filename);
2220 g_free(fru->data);
2221 fru->data = NULL;
2222 }
2223 }
2224
2225 out:
2226 if (!fru->data) {
2227 /* give one default FRU */
2228 size = fru->areasize;
2229 fru->data = g_malloc0(size);
2230 }
2231
2232 fru->nentries = size / fru->areasize;
2233 }
2234
ipmi_sim_realize(DeviceState * dev,Error ** errp)2235 static void ipmi_sim_realize(DeviceState *dev, Error **errp)
2236 {
2237 IPMIBmc *b = IPMI_BMC(dev);
2238 unsigned int i;
2239 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
2240
2241 QTAILQ_INIT(&ibs->rcvbufs);
2242
2243 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
2244 ibs->device_id = 0x20;
2245 ibs->ipmi_version = 0x02; /* IPMI 2.0 */
2246 ibs->restart_cause = 0;
2247 for (i = 0; i < 4; i++) {
2248 ibs->sel.last_addition[i] = 0xff;
2249 ibs->sel.last_clear[i] = 0xff;
2250 ibs->sdr.last_addition[i] = 0xff;
2251 ibs->sdr.last_clear[i] = 0xff;
2252 }
2253
2254 ipmi_sdr_init(ibs);
2255
2256 ipmi_fru_init(&ibs->fru);
2257
2258 ibs->acpi_power_state[0] = 0;
2259 ibs->acpi_power_state[1] = 0;
2260
2261 ipmi_init_sensors_from_sdrs(ibs);
2262 register_cmds(ibs);
2263
2264 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
2265 }
2266
2267 static const Property ipmi_sim_properties[] = {
2268 DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim, fru.areasize, 1024),
2269 DEFINE_PROP_STRING("frudatafile", IPMIBmcSim, fru.filename),
2270 DEFINE_PROP_STRING("sdrfile", IPMIBmcSim, sdr_filename),
2271 DEFINE_PROP_UINT8("device_id", IPMIBmcSim, device_id, 0x20),
2272 DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim, ipmi_version, 0x02),
2273 DEFINE_PROP_UINT8("device_rev", IPMIBmcSim, device_rev, 0),
2274 DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim, fwrev1, 0),
2275 DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim, fwrev2, 0),
2276 DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim, mfg_id, 0),
2277 DEFINE_PROP_UINT16("product_id", IPMIBmcSim, product_id, 0),
2278 DEFINE_PROP_UUID_NODEFAULT("guid", IPMIBmcSim, uuid),
2279 };
2280
ipmi_sim_class_init(ObjectClass * oc,const void * data)2281 static void ipmi_sim_class_init(ObjectClass *oc, const void *data)
2282 {
2283 DeviceClass *dc = DEVICE_CLASS(oc);
2284 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
2285
2286 dc->hotpluggable = false;
2287 dc->realize = ipmi_sim_realize;
2288 dc->vmsd = &vmstate_ipmi_sim;
2289 device_class_set_props(dc, ipmi_sim_properties);
2290 bk->handle_command = ipmi_sim_handle_command;
2291 }
2292
2293 static const TypeInfo ipmi_sim_type = {
2294 .name = TYPE_IPMI_BMC_SIMULATOR,
2295 .parent = TYPE_IPMI_BMC,
2296 .instance_size = sizeof(IPMIBmcSim),
2297 .class_init = ipmi_sim_class_init,
2298 };
2299
ipmi_sim_register_types(void)2300 static void ipmi_sim_register_types(void)
2301 {
2302 type_register_static(&ipmi_sim_type);
2303 }
2304
2305 type_init(ipmi_sim_register_types)
2306