1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "qemu/osdep.h"
26#include "sysemu/sysemu.h"
27#include "qemu/timer.h"
28#include "hw/ipmi/ipmi.h"
29#include "qemu/error-report.h"
30
31#define IPMI_NETFN_CHASSIS 0x00
32
33#define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
34#define IPMI_CMD_GET_CHASSIS_STATUS 0x01
35#define IPMI_CMD_CHASSIS_CONTROL 0x02
36#define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09
37
38#define IPMI_NETFN_SENSOR_EVENT 0x04
39
40#define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
41#define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
42#define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
43#define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
44#define IPMI_CMD_GET_SENSOR_READING 0x2d
45#define IPMI_CMD_SET_SENSOR_TYPE 0x2e
46#define IPMI_CMD_GET_SENSOR_TYPE 0x2f
47
48
49
50#define IPMI_CMD_GET_DEVICE_ID 0x01
51#define IPMI_CMD_COLD_RESET 0x02
52#define IPMI_CMD_WARM_RESET 0x03
53#define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
54#define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
55#define IPMI_CMD_GET_DEVICE_GUID 0x08
56#define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
57#define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
58#define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
59#define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
60#define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
61#define IPMI_CMD_CLR_MSG_FLAGS 0x30
62#define IPMI_CMD_GET_MSG_FLAGS 0x31
63#define IPMI_CMD_GET_MSG 0x33
64#define IPMI_CMD_SEND_MSG 0x34
65#define IPMI_CMD_READ_EVT_MSG_BUF 0x35
66
67#define IPMI_NETFN_STORAGE 0x0a
68
69#define IPMI_CMD_GET_SDR_REP_INFO 0x20
70#define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
71#define IPMI_CMD_RESERVE_SDR_REP 0x22
72#define IPMI_CMD_GET_SDR 0x23
73#define IPMI_CMD_ADD_SDR 0x24
74#define IPMI_CMD_PARTIAL_ADD_SDR 0x25
75#define IPMI_CMD_DELETE_SDR 0x26
76#define IPMI_CMD_CLEAR_SDR_REP 0x27
77#define IPMI_CMD_GET_SDR_REP_TIME 0x28
78#define IPMI_CMD_SET_SDR_REP_TIME 0x29
79#define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
80#define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
81#define IPMI_CMD_RUN_INIT_AGENT 0x2C
82#define IPMI_CMD_GET_SEL_INFO 0x40
83#define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
84#define IPMI_CMD_RESERVE_SEL 0x42
85#define IPMI_CMD_GET_SEL_ENTRY 0x43
86#define IPMI_CMD_ADD_SEL_ENTRY 0x44
87#define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
88#define IPMI_CMD_DELETE_SEL_ENTRY 0x46
89#define IPMI_CMD_CLEAR_SEL 0x47
90#define IPMI_CMD_GET_SEL_TIME 0x48
91#define IPMI_CMD_SET_SEL_TIME 0x49
92
93
94
95struct ipmi_time {
96 long tv_sec;
97 long tv_nsec;
98};
99
100#define MAX_SEL_SIZE 128
101
102typedef struct IPMISel {
103 uint8_t sel[MAX_SEL_SIZE][16];
104 unsigned int next_free;
105 long time_offset;
106 uint16_t reservation;
107 uint8_t last_addition[4];
108 uint8_t last_clear[4];
109 uint8_t overflow;
110} IPMISel;
111
112#define MAX_SDR_SIZE 16384
113
114typedef struct IPMISdr {
115 uint8_t sdr[MAX_SDR_SIZE];
116 unsigned int next_free;
117 uint16_t next_rec_id;
118 uint16_t reservation;
119 uint8_t last_addition[4];
120 uint8_t last_clear[4];
121 uint8_t overflow;
122} IPMISdr;
123
124typedef struct IPMISensor {
125 uint8_t status;
126 uint8_t reading;
127 uint16_t states_suppt;
128 uint16_t assert_suppt;
129 uint16_t deassert_suppt;
130 uint16_t states;
131 uint16_t assert_states;
132 uint16_t deassert_states;
133 uint16_t assert_enable;
134 uint16_t deassert_enable;
135 uint8_t sensor_type;
136 uint8_t evt_reading_type_code;
137} IPMISensor;
138#define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
139#define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
140 !!(v))
141#define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
142#define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
143 ((!!(v)) << 6))
144#define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
145#define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
146 ((!!(v)) << 7))
147#define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
148#define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
149 (v & 0xc0))
150#define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
151
152#define MAX_SENSORS 20
153#define IPMI_WATCHDOG_SENSOR 0
154
155typedef struct IPMIBmcSim IPMIBmcSim;
156typedef struct RspBuffer RspBuffer;
157
158#define MAX_NETFNS 64
159
160typedef struct IPMICmdHandler {
161 void (*cmd_handler)(IPMIBmcSim *s,
162 uint8_t *cmd, unsigned int cmd_len,
163 RspBuffer *rsp);
164 unsigned int cmd_len_min;
165} IPMICmdHandler;
166
167typedef struct IPMINetfn {
168 unsigned int cmd_nums;
169 const IPMICmdHandler *cmd_handlers;
170} IPMINetfn;
171
172typedef struct IPMIRcvBufEntry {
173 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
174 uint8_t len;
175 uint8_t buf[MAX_IPMI_MSG_SIZE];
176} IPMIRcvBufEntry;
177
178#define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
179#define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
180 TYPE_IPMI_BMC_SIMULATOR)
181struct 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;
193 bool watchdog_expired;
194 uint16_t watchdog_timeout;
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 uint8_t mfg_id[3];
206 uint8_t product_id[2];
207
208 uint8_t restart_cause;
209
210 uint8_t acpi_power_state[2];
211 uint8_t uuid[16];
212
213 IPMISel sel;
214 IPMISdr sdr;
215 IPMISensor sensors[MAX_SENSORS];
216
217
218 const IPMINetfn *netfns[MAX_NETFNS / 2];
219
220 QemuMutex lock;
221
222 uint8_t evtbuf[16];
223
224 QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
225};
226
227#define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
228#define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
229#define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
230#define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
231 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
232#define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
233 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
234#define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
235 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
236
237#define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
238#define IPMI_BMC_EVBUF_FULL_INT_BIT 1
239#define IPMI_BMC_EVENT_MSG_BUF_BIT 2
240#define IPMI_BMC_EVENT_LOG_BIT 3
241#define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
242 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
243#define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
244 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
245#define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
246 (1 << IPMI_BMC_EVENT_LOG_BIT))
247#define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
248 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
249
250#define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
251#define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
252#define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
253#define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
254#define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
255#define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
256#define IPMI_BMC_WATCHDOG_PRE_NONE 0
257#define IPMI_BMC_WATCHDOG_PRE_SMI 1
258#define IPMI_BMC_WATCHDOG_PRE_NMI 2
259#define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
260#define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
261#define IPMI_BMC_WATCHDOG_ACTION_NONE 0
262#define IPMI_BMC_WATCHDOG_ACTION_RESET 1
263#define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
264#define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
265
266struct RspBuffer {
267 uint8_t buffer[MAX_IPMI_MSG_SIZE];
268 unsigned int len;
269};
270
271#define RSP_BUFFER_INITIALIZER { }
272
273static inline void rsp_buffer_set_error(RspBuffer *rsp, uint8_t byte)
274{
275 rsp->buffer[2] = byte;
276}
277
278
279static inline void rsp_buffer_push(RspBuffer *rsp, uint8_t byte)
280{
281 if (rsp->len >= sizeof(rsp->buffer)) {
282 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
283 return;
284 }
285 rsp->buffer[rsp->len++] = byte;
286}
287
288static inline void rsp_buffer_pushmore(RspBuffer *rsp, uint8_t *bytes,
289 unsigned int n)
290{
291 if (rsp->len + n >= sizeof(rsp->buffer)) {
292 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
293 return;
294 }
295
296 memcpy(&rsp->buffer[rsp->len], bytes, n);
297 rsp->len += n;
298}
299
300static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
301
302static void ipmi_gettime(struct ipmi_time *time)
303{
304 int64_t stime;
305
306 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
307 time->tv_sec = stime / 1000000000LL;
308 time->tv_nsec = stime % 1000000000LL;
309}
310
311static int64_t ipmi_getmonotime(void)
312{
313 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
314}
315
316static void ipmi_timeout(void *opaque)
317{
318 IPMIBmcSim *ibs = opaque;
319
320 ipmi_sim_handle_timeout(ibs);
321}
322
323static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
324{
325 unsigned int val;
326 struct ipmi_time now;
327
328 ipmi_gettime(&now);
329 val = now.tv_sec + ibs->sel.time_offset;
330 ts[0] = val & 0xff;
331 ts[1] = (val >> 8) & 0xff;
332 ts[2] = (val >> 16) & 0xff;
333 ts[3] = (val >> 24) & 0xff;
334}
335
336static void sdr_inc_reservation(IPMISdr *sdr)
337{
338 sdr->reservation++;
339 if (sdr->reservation == 0) {
340 sdr->reservation = 1;
341 }
342}
343
344static int sdr_add_entry(IPMIBmcSim *ibs,
345 const struct ipmi_sdr_header *sdrh_entry,
346 unsigned int len, uint16_t *recid)
347{
348 struct ipmi_sdr_header *sdrh =
349 (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
350
351 if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
352 return 1;
353 }
354
355 if (ipmi_sdr_length(sdrh_entry) != len) {
356 return 1;
357 }
358
359 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
360 ibs->sdr.overflow = 1;
361 return 1;
362 }
363
364 memcpy(sdrh, sdrh_entry, len);
365 sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff;
366 sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
367 sdrh->sdr_version = 0x51;
368
369 if (recid) {
370 *recid = ibs->sdr.next_rec_id;
371 }
372 ibs->sdr.next_rec_id++;
373 set_timestamp(ibs, ibs->sdr.last_addition);
374 ibs->sdr.next_free += len;
375 sdr_inc_reservation(&ibs->sdr);
376 return 0;
377}
378
379static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
380 unsigned int *retpos, uint16_t *nextrec)
381{
382 unsigned int pos = *retpos;
383
384 while (pos < sdr->next_free) {
385 struct ipmi_sdr_header *sdrh =
386 (struct ipmi_sdr_header *) &sdr->sdr[pos];
387 uint16_t trec = ipmi_sdr_recid(sdrh);
388 unsigned int nextpos = pos + ipmi_sdr_length(sdrh);
389
390 if (trec == recid) {
391 if (nextrec) {
392 if (nextpos >= sdr->next_free) {
393 *nextrec = 0xffff;
394 } else {
395 *nextrec = (sdr->sdr[nextpos] |
396 (sdr->sdr[nextpos + 1] << 8));
397 }
398 }
399 *retpos = pos;
400 return 0;
401 }
402 pos = nextpos;
403 }
404 return 1;
405}
406
407static void sel_inc_reservation(IPMISel *sel)
408{
409 sel->reservation++;
410 if (sel->reservation == 0) {
411 sel->reservation = 1;
412 }
413}
414
415
416static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
417{
418 event[0] = 0xff;
419 event[1] = 0xff;
420 set_timestamp(ibs, event + 3);
421 if (ibs->sel.next_free == MAX_SEL_SIZE) {
422 ibs->sel.overflow = 1;
423 return 1;
424 }
425 event[0] = ibs->sel.next_free & 0xff;
426 event[1] = (ibs->sel.next_free >> 8) & 0xff;
427 memcpy(ibs->sel.last_addition, event + 3, 4);
428 memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
429 ibs->sel.next_free++;
430 sel_inc_reservation(&ibs->sel);
431 return 0;
432}
433
434static int attn_set(IPMIBmcSim *ibs)
435{
436 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
437 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
438 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
439}
440
441static int attn_irq_enabled(IPMIBmcSim *ibs)
442{
443 return (IPMI_BMC_MSG_INTS_ON(ibs) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs))
444 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
445 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
446}
447
448static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
449 uint8_t evd1, uint8_t evd2, uint8_t evd3)
450{
451 IPMIInterface *s = ibs->parent.intf;
452 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
453 uint8_t evt[16];
454 IPMISensor *sens = ibs->sensors + sens_num;
455
456 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
457 return;
458 }
459 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
460 return;
461 }
462
463 evt[2] = 0x2;
464 evt[7] = ibs->parent.slave_addr;
465 evt[8] = 0;
466 evt[9] = 0x04;
467 evt[10] = sens->sensor_type;
468 evt[11] = sens_num;
469 evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
470 evt[13] = evd1;
471 evt[14] = evd2;
472 evt[15] = evd3;
473
474 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
475 sel_add_event(ibs, evt);
476 }
477
478 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
479 return;
480 }
481
482 memcpy(ibs->evtbuf, evt, 16);
483 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
484 k->set_atn(s, 1, attn_irq_enabled(ibs));
485}
486
487static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
488 unsigned int bit, unsigned int val,
489 uint8_t evd1, uint8_t evd2, uint8_t evd3)
490{
491 IPMISensor *sens;
492 uint16_t mask;
493
494 if (sensor >= MAX_SENSORS) {
495 return;
496 }
497 if (bit >= 16) {
498 return;
499 }
500
501 mask = (1 << bit);
502 sens = ibs->sensors + sensor;
503 if (val) {
504 sens->states |= mask & sens->states_suppt;
505 if (sens->assert_states & mask) {
506 return;
507 }
508 sens->assert_states |= mask & sens->assert_suppt;
509 if (sens->assert_enable & mask & sens->assert_states) {
510
511 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
512 }
513 } else {
514 sens->states &= ~(mask & sens->states_suppt);
515 if (sens->deassert_states & mask) {
516 return;
517 }
518 sens->deassert_states |= mask & sens->deassert_suppt;
519 if (sens->deassert_enable & mask & sens->deassert_states) {
520
521 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
522 }
523 }
524}
525
526static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
527{
528 unsigned int i, pos;
529 IPMISensor *sens;
530
531 for (i = 0; i < MAX_SENSORS; i++) {
532 memset(s->sensors + i, 0, sizeof(*sens));
533 }
534
535 pos = 0;
536 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
537 struct ipmi_sdr_compact *sdr =
538 (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
539 unsigned int len = sdr->header.rec_length;
540
541 if (len < 20) {
542 continue;
543 }
544 if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
545 continue;
546 }
547
548 if (sdr->sensor_owner_number >= MAX_SENSORS) {
549 continue;
550 }
551 sens = s->sensors + sdr->sensor_owner_number;
552
553 IPMI_SENSOR_SET_PRESENT(sens, 1);
554 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
555 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
556 sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
557 sens->deassert_suppt =
558 sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
559 sens->states_suppt =
560 sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
561 sens->sensor_type = sdr->sensor_type;
562 sens->evt_reading_type_code = sdr->reading_type & 0x7f;
563
564
565 sens->assert_enable = sens->assert_suppt;
566 sens->deassert_enable = sens->deassert_suppt;
567 }
568}
569
570static int ipmi_register_netfn(IPMIBmcSim *s, unsigned int netfn,
571 const IPMINetfn *netfnd)
572{
573 if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
574 return -1;
575 }
576 s->netfns[netfn / 2] = netfnd;
577 return 0;
578}
579
580static const IPMICmdHandler *ipmi_get_handler(IPMIBmcSim *ibs,
581 unsigned int netfn,
582 unsigned int cmd)
583{
584 const IPMICmdHandler *hdl;
585
586 if (netfn & 1 || netfn >= MAX_NETFNS || !ibs->netfns[netfn / 2]) {
587 return NULL;
588 }
589
590 if (cmd >= ibs->netfns[netfn / 2]->cmd_nums) {
591 return NULL;
592 }
593
594 hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd];
595 if (!hdl->cmd_handler) {
596 return NULL;
597 }
598
599 return hdl;
600}
601
602static void next_timeout(IPMIBmcSim *ibs)
603{
604 int64_t next;
605 if (ibs->watchdog_running) {
606 next = ibs->watchdog_expiry;
607 } else {
608
609 next = ipmi_getmonotime() + 60 * 1000000000LL;
610 }
611 timer_mod_ns(ibs->timer, next);
612}
613
614static void ipmi_sim_handle_command(IPMIBmc *b,
615 uint8_t *cmd, unsigned int cmd_len,
616 unsigned int max_cmd_len,
617 uint8_t msg_id)
618{
619 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
620 IPMIInterface *s = ibs->parent.intf;
621 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
622 const IPMICmdHandler *hdl;
623 RspBuffer rsp = RSP_BUFFER_INITIALIZER;
624
625
626
627 if (sizeof(rsp.buffer) < 3) {
628 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
629 goto out;
630 }
631
632 rsp_buffer_push(&rsp, cmd[0] | 0x04);
633 rsp_buffer_push(&rsp, cmd[1]);
634 rsp_buffer_push(&rsp, 0);
635
636
637 if (cmd_len < 2) {
638 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
639 goto out;
640 }
641 if (cmd_len > max_cmd_len) {
642 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
643 goto out;
644 }
645
646 if ((cmd[0] & 0x03) != 0) {
647
648 rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN);
649 goto out;
650 }
651
652 hdl = ipmi_get_handler(ibs, cmd[0] >> 2, cmd[1]);
653 if (!hdl) {
654 rsp_buffer_set_error(&rsp, IPMI_CC_INVALID_CMD);
655 goto out;
656 }
657
658 if (cmd_len < hdl->cmd_len_min) {
659 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
660 goto out;
661 }
662
663 hdl->cmd_handler(ibs, cmd, cmd_len, &rsp);
664
665 out:
666 k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
667
668 next_timeout(ibs);
669}
670
671static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
672{
673 IPMIInterface *s = ibs->parent.intf;
674 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
675
676 if (!ibs->watchdog_running) {
677 goto out;
678 }
679
680 if (!ibs->watchdog_preaction_ran) {
681 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
682 case IPMI_BMC_WATCHDOG_PRE_NMI:
683 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
684 k->do_hw_op(s, IPMI_SEND_NMI, 0);
685 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
686 0xc8, (2 << 4) | 0xf, 0xff);
687 break;
688
689 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
690 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
691 k->set_atn(s, 1, attn_irq_enabled(ibs));
692 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
693 0xc8, (3 << 4) | 0xf, 0xff);
694 break;
695
696 default:
697 goto do_full_expiry;
698 }
699
700 ibs->watchdog_preaction_ran = 1;
701
702 ibs->watchdog_expiry = ipmi_getmonotime();
703 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
704 goto out;
705 }
706
707 do_full_expiry:
708 ibs->watchdog_running = 0;
709 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
710 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
711 case IPMI_BMC_WATCHDOG_ACTION_NONE:
712 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
713 0xc0, ibs->watchdog_use & 0xf, 0xff);
714 break;
715
716 case IPMI_BMC_WATCHDOG_ACTION_RESET:
717 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
718 0xc1, ibs->watchdog_use & 0xf, 0xff);
719 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
720 break;
721
722 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
723 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
724 0xc2, ibs->watchdog_use & 0xf, 0xff);
725 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
726 break;
727
728 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
729 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
730 0xc3, ibs->watchdog_use & 0xf, 0xff);
731 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
732 break;
733 }
734
735 out:
736 next_timeout(ibs);
737}
738
739static void chassis_capabilities(IPMIBmcSim *ibs,
740 uint8_t *cmd, unsigned int cmd_len,
741 RspBuffer *rsp)
742{
743 rsp_buffer_push(rsp, 0);
744 rsp_buffer_push(rsp, ibs->parent.slave_addr);
745 rsp_buffer_push(rsp, ibs->parent.slave_addr);
746 rsp_buffer_push(rsp, ibs->parent.slave_addr);
747 rsp_buffer_push(rsp, ibs->parent.slave_addr);
748}
749
750static void chassis_status(IPMIBmcSim *ibs,
751 uint8_t *cmd, unsigned int cmd_len,
752 RspBuffer *rsp)
753{
754 rsp_buffer_push(rsp, 0x61);
755 rsp_buffer_push(rsp, 0);
756 rsp_buffer_push(rsp, 0);
757 rsp_buffer_push(rsp, 0);
758}
759
760static void chassis_control(IPMIBmcSim *ibs,
761 uint8_t *cmd, unsigned int cmd_len,
762 RspBuffer *rsp)
763{
764 IPMIInterface *s = ibs->parent.intf;
765 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
766
767 switch (cmd[2] & 0xf) {
768 case 0:
769 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0));
770 break;
771 case 1:
772 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0));
773 break;
774 case 2:
775 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0));
776 break;
777 case 3:
778 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0));
779 break;
780 case 4:
781 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0));
782 break;
783 case 5:
784 rsp_buffer_set_error(rsp, k->do_hw_op(s,
785 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0));
786 break;
787 default:
788 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
789 return;
790 }
791}
792
793static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
794 uint8_t *cmd, unsigned int cmd_len,
795 RspBuffer *rsp)
796
797{
798 rsp_buffer_push(rsp, ibs->restart_cause & 0xf);
799 rsp_buffer_push(rsp, 0);
800}
801
802static void get_device_id(IPMIBmcSim *ibs,
803 uint8_t *cmd, unsigned int cmd_len,
804 RspBuffer *rsp)
805{
806 rsp_buffer_push(rsp, ibs->device_id);
807 rsp_buffer_push(rsp, ibs->device_rev & 0xf);
808 rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
809 rsp_buffer_push(rsp, ibs->fwrev2);
810 rsp_buffer_push(rsp, ibs->ipmi_version);
811 rsp_buffer_push(rsp, 0x07);
812 rsp_buffer_push(rsp, ibs->mfg_id[0]);
813 rsp_buffer_push(rsp, ibs->mfg_id[1]);
814 rsp_buffer_push(rsp, ibs->mfg_id[2]);
815 rsp_buffer_push(rsp, ibs->product_id[0]);
816 rsp_buffer_push(rsp, ibs->product_id[1]);
817}
818
819static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
820{
821 IPMIInterface *s = ibs->parent.intf;
822 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
823 bool irqs_on;
824
825 ibs->bmc_global_enables = val;
826
827 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
828 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
829
830 k->set_irq_enable(s, irqs_on);
831}
832
833static void cold_reset(IPMIBmcSim *ibs,
834 uint8_t *cmd, unsigned int cmd_len,
835 RspBuffer *rsp)
836{
837 IPMIInterface *s = ibs->parent.intf;
838 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
839
840
841 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
842
843 if (k->reset) {
844 k->reset(s, true);
845 }
846}
847
848static void warm_reset(IPMIBmcSim *ibs,
849 uint8_t *cmd, unsigned int cmd_len,
850 RspBuffer *rsp)
851{
852 IPMIInterface *s = ibs->parent.intf;
853 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
854
855 if (k->reset) {
856 k->reset(s, false);
857 }
858}
859static void set_acpi_power_state(IPMIBmcSim *ibs,
860 uint8_t *cmd, unsigned int cmd_len,
861 RspBuffer *rsp)
862{
863 ibs->acpi_power_state[0] = cmd[2];
864 ibs->acpi_power_state[1] = cmd[3];
865}
866
867static void get_acpi_power_state(IPMIBmcSim *ibs,
868 uint8_t *cmd, unsigned int cmd_len,
869 RspBuffer *rsp)
870{
871 rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
872 rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
873}
874
875static void get_device_guid(IPMIBmcSim *ibs,
876 uint8_t *cmd, unsigned int cmd_len,
877 RspBuffer *rsp)
878{
879 unsigned int i;
880
881 for (i = 0; i < 16; i++) {
882 rsp_buffer_push(rsp, ibs->uuid[i]);
883 }
884}
885
886static void set_bmc_global_enables(IPMIBmcSim *ibs,
887 uint8_t *cmd, unsigned int cmd_len,
888 RspBuffer *rsp)
889{
890 set_global_enables(ibs, cmd[2]);
891}
892
893static void get_bmc_global_enables(IPMIBmcSim *ibs,
894 uint8_t *cmd, unsigned int cmd_len,
895 RspBuffer *rsp)
896{
897 rsp_buffer_push(rsp, ibs->bmc_global_enables);
898}
899
900static void clr_msg_flags(IPMIBmcSim *ibs,
901 uint8_t *cmd, unsigned int cmd_len,
902 RspBuffer *rsp)
903{
904 IPMIInterface *s = ibs->parent.intf;
905 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
906
907 ibs->msg_flags &= ~cmd[2];
908 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
909}
910
911static void get_msg_flags(IPMIBmcSim *ibs,
912 uint8_t *cmd, unsigned int cmd_len,
913 RspBuffer *rsp)
914{
915 rsp_buffer_push(rsp, ibs->msg_flags);
916}
917
918static void read_evt_msg_buf(IPMIBmcSim *ibs,
919 uint8_t *cmd, unsigned int cmd_len,
920 RspBuffer *rsp)
921{
922 IPMIInterface *s = ibs->parent.intf;
923 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
924 unsigned int i;
925
926 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
927 rsp_buffer_set_error(rsp, 0x80);
928 return;
929 }
930 for (i = 0; i < 16; i++) {
931 rsp_buffer_push(rsp, ibs->evtbuf[i]);
932 }
933 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
934 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
935}
936
937static void get_msg(IPMIBmcSim *ibs,
938 uint8_t *cmd, unsigned int cmd_len,
939 RspBuffer *rsp)
940{
941 IPMIRcvBufEntry *msg;
942
943 qemu_mutex_lock(&ibs->lock);
944 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
945 rsp_buffer_set_error(rsp, 0x80);
946 goto out;
947 }
948 rsp_buffer_push(rsp, 0);
949 msg = QTAILQ_FIRST(&ibs->rcvbufs);
950 rsp_buffer_pushmore(rsp, msg->buf, msg->len);
951 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
952 g_free(msg);
953
954 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
955 IPMIInterface *s = ibs->parent.intf;
956 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
957
958 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
959 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
960 }
961
962out:
963 qemu_mutex_unlock(&ibs->lock);
964 return;
965}
966
967static unsigned char
968ipmb_checksum(unsigned char *data, int size, unsigned char csum)
969{
970 for (; size > 0; size--, data++) {
971 csum += *data;
972 }
973
974 return -csum;
975}
976
977static void send_msg(IPMIBmcSim *ibs,
978 uint8_t *cmd, unsigned int cmd_len,
979 RspBuffer *rsp)
980{
981 IPMIInterface *s = ibs->parent.intf;
982 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
983 IPMIRcvBufEntry *msg;
984 uint8_t *buf;
985 uint8_t netfn, rqLun, rsLun, rqSeq;
986
987 if (cmd[2] != 0) {
988
989 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
990 return;
991 }
992
993 if (cmd_len < 10) {
994 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
995 return;
996 }
997
998 if (cmd[3] != 0x40) {
999
1000 rsp_buffer_set_error(rsp, 0x83);
1001 return;
1002 }
1003
1004 cmd += 3;
1005 cmd_len -= 3;
1006
1007
1008
1009
1010
1011 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
1012 cmd[3] != 0x20) {
1013 return;
1014 }
1015
1016 netfn = cmd[1] >> 2;
1017 rqLun = cmd[4] & 0x3;
1018 rsLun = cmd[1] & 0x3;
1019 rqSeq = cmd[4] >> 2;
1020
1021 if (rqLun != 2) {
1022
1023 return;
1024 }
1025
1026 msg = g_malloc(sizeof(*msg));
1027 msg->buf[0] = ((netfn | 1) << 2) | rqLun;
1028 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
1029 msg->buf[2] = cmd[0];
1030 msg->buf[3] = (rqSeq << 2) | rsLun;
1031 msg->buf[4] = cmd[5];
1032 msg->buf[5] = 0;
1033 msg->len = 6;
1034
1035 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
1036
1037 msg->buf[5] = IPMI_CC_INVALID_CMD;
1038 goto end_msg;
1039 }
1040
1041 buf = msg->buf + msg->len;
1042 buf[0] = 0;
1043 buf[1] = 0;
1044 buf[2] = 0;
1045 buf[3] = 0;
1046 buf[4] = 0x51;
1047 buf[5] = 0;
1048 buf[6] = 0;
1049 buf[7] = 0;
1050 buf[8] = 0;
1051 buf[9] = 0;
1052 buf[10] = 0;
1053 msg->len += 11;
1054
1055 end_msg:
1056 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1057 msg->len++;
1058 qemu_mutex_lock(&ibs->lock);
1059 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1060 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1061 k->set_atn(s, 1, attn_irq_enabled(ibs));
1062 qemu_mutex_unlock(&ibs->lock);
1063}
1064
1065static void do_watchdog_reset(IPMIBmcSim *ibs)
1066{
1067 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1068 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1069 ibs->watchdog_running = 0;
1070 return;
1071 }
1072 ibs->watchdog_preaction_ran = 0;
1073
1074
1075
1076 ibs->watchdog_expiry = ipmi_getmonotime();
1077 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1078 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1079 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1080 }
1081 ibs->watchdog_running = 1;
1082}
1083
1084static void reset_watchdog_timer(IPMIBmcSim *ibs,
1085 uint8_t *cmd, unsigned int cmd_len,
1086 RspBuffer *rsp)
1087{
1088 if (!ibs->watchdog_initialized) {
1089 rsp_buffer_set_error(rsp, 0x80);
1090 return;
1091 }
1092 do_watchdog_reset(ibs);
1093}
1094
1095static void set_watchdog_timer(IPMIBmcSim *ibs,
1096 uint8_t *cmd, unsigned int cmd_len,
1097 RspBuffer *rsp)
1098{
1099 IPMIInterface *s = ibs->parent.intf;
1100 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1101 unsigned int val;
1102
1103 val = cmd[2] & 0x7;
1104 if (val == 0 || val > 5) {
1105 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1106 return;
1107 }
1108 val = cmd[3] & 0x7;
1109 switch (val) {
1110 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1111 break;
1112
1113 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1114 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1));
1115 break;
1116
1117 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1118 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1));
1119 break;
1120
1121 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1122 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1));
1123 break;
1124
1125 default:
1126 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1127 }
1128 if (rsp->buffer[2]) {
1129 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1130 return;
1131 }
1132
1133 val = (cmd[3] >> 4) & 0x7;
1134 switch (val) {
1135 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1136 case IPMI_BMC_WATCHDOG_PRE_NONE:
1137 break;
1138
1139 case IPMI_BMC_WATCHDOG_PRE_NMI:
1140 if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1141
1142 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1143 return;
1144 }
1145 break;
1146
1147 default:
1148
1149 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1150 return;
1151 }
1152
1153 ibs->watchdog_initialized = 1;
1154 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1155 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1156 ibs->watchdog_pretimeout = cmd[4];
1157 ibs->watchdog_expired &= ~cmd[5];
1158 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1159 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1160 do_watchdog_reset(ibs);
1161 } else {
1162 ibs->watchdog_running = 0;
1163 }
1164}
1165
1166static void get_watchdog_timer(IPMIBmcSim *ibs,
1167 uint8_t *cmd, unsigned int cmd_len,
1168 RspBuffer *rsp)
1169{
1170 rsp_buffer_push(rsp, ibs->watchdog_use);
1171 rsp_buffer_push(rsp, ibs->watchdog_action);
1172 rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
1173 rsp_buffer_push(rsp, ibs->watchdog_expired);
1174 if (ibs->watchdog_running) {
1175 long timeout;
1176 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1177 / 100000000);
1178 rsp_buffer_push(rsp, timeout & 0xff);
1179 rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
1180 } else {
1181 rsp_buffer_push(rsp, 0);
1182 rsp_buffer_push(rsp, 0);
1183 }
1184}
1185
1186static void get_sdr_rep_info(IPMIBmcSim *ibs,
1187 uint8_t *cmd, unsigned int cmd_len,
1188 RspBuffer *rsp)
1189{
1190 unsigned int i;
1191
1192 rsp_buffer_push(rsp, 0x51);
1193 rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
1194 rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
1195 rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1196 rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1197 for (i = 0; i < 4; i++) {
1198 rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
1199 }
1200 for (i = 0; i < 4; i++) {
1201 rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
1202 }
1203
1204 rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
1205}
1206
1207static void reserve_sdr_rep(IPMIBmcSim *ibs,
1208 uint8_t *cmd, unsigned int cmd_len,
1209 RspBuffer *rsp)
1210{
1211 rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
1212 rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
1213}
1214
1215static void get_sdr(IPMIBmcSim *ibs,
1216 uint8_t *cmd, unsigned int cmd_len,
1217 RspBuffer *rsp)
1218{
1219 unsigned int pos;
1220 uint16_t nextrec;
1221 struct ipmi_sdr_header *sdrh;
1222
1223 if (cmd[6]) {
1224 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1225 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1226 return;
1227 }
1228 }
1229
1230 pos = 0;
1231 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1232 &pos, &nextrec)) {
1233 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1234 return;
1235 }
1236
1237 sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1238
1239 if (cmd[6] > ipmi_sdr_length(sdrh)) {
1240 rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE);
1241 return;
1242 }
1243
1244 rsp_buffer_push(rsp, nextrec & 0xff);
1245 rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
1246
1247 if (cmd[7] == 0xff) {
1248 cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1249 }
1250
1251 if ((cmd[7] + rsp->len) > sizeof(rsp->buffer)) {
1252 rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES);
1253 return;
1254 }
1255
1256 rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1257}
1258
1259static void add_sdr(IPMIBmcSim *ibs,
1260 uint8_t *cmd, unsigned int cmd_len,
1261 RspBuffer *rsp)
1262{
1263 uint16_t recid;
1264 struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1265
1266 if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1267 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1268 return;
1269 }
1270 rsp_buffer_push(rsp, recid & 0xff);
1271 rsp_buffer_push(rsp, (recid >> 8) & 0xff);
1272}
1273
1274static void clear_sdr_rep(IPMIBmcSim *ibs,
1275 uint8_t *cmd, unsigned int cmd_len,
1276 RspBuffer *rsp)
1277{
1278 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1279 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1280 return;
1281 }
1282
1283 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1284 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1285 return;
1286 }
1287 if (cmd[7] == 0xaa) {
1288 ibs->sdr.next_free = 0;
1289 ibs->sdr.overflow = 0;
1290 set_timestamp(ibs, ibs->sdr.last_clear);
1291 rsp_buffer_push(rsp, 1);
1292 sdr_inc_reservation(&ibs->sdr);
1293 } else if (cmd[7] == 0) {
1294 rsp_buffer_push(rsp, 1);
1295 } else {
1296 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1297 return;
1298 }
1299}
1300
1301static void get_sel_info(IPMIBmcSim *ibs,
1302 uint8_t *cmd, unsigned int cmd_len,
1303 RspBuffer *rsp)
1304{
1305 unsigned int i, val;
1306
1307 rsp_buffer_push(rsp, 0x51);
1308 rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
1309 rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
1310 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1311 rsp_buffer_push(rsp, val & 0xff);
1312 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1313 for (i = 0; i < 4; i++) {
1314 rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
1315 }
1316 for (i = 0; i < 4; i++) {
1317 rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
1318 }
1319
1320 rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
1321}
1322
1323static void reserve_sel(IPMIBmcSim *ibs,
1324 uint8_t *cmd, unsigned int cmd_len,
1325 RspBuffer *rsp)
1326{
1327 rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
1328 rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
1329}
1330
1331static void get_sel_entry(IPMIBmcSim *ibs,
1332 uint8_t *cmd, unsigned int cmd_len,
1333 RspBuffer *rsp)
1334{
1335 unsigned int val;
1336
1337 if (cmd[6]) {
1338 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1339 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1340 return;
1341 }
1342 }
1343 if (ibs->sel.next_free == 0) {
1344 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1345 return;
1346 }
1347 if (cmd[6] > 15) {
1348 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1349 return;
1350 }
1351 if (cmd[7] == 0xff) {
1352 cmd[7] = 16;
1353 } else if ((cmd[7] + cmd[6]) > 16) {
1354 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1355 return;
1356 } else {
1357 cmd[7] += cmd[6];
1358 }
1359
1360 val = cmd[4] | (cmd[5] << 8);
1361 if (val == 0xffff) {
1362 val = ibs->sel.next_free - 1;
1363 } else if (val >= ibs->sel.next_free) {
1364 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1365 return;
1366 }
1367 if ((val + 1) == ibs->sel.next_free) {
1368 rsp_buffer_push(rsp, 0xff);
1369 rsp_buffer_push(rsp, 0xff);
1370 } else {
1371 rsp_buffer_push(rsp, (val + 1) & 0xff);
1372 rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
1373 }
1374 for (; cmd[6] < cmd[7]; cmd[6]++) {
1375 rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
1376 }
1377}
1378
1379static void add_sel_entry(IPMIBmcSim *ibs,
1380 uint8_t *cmd, unsigned int cmd_len,
1381 RspBuffer *rsp)
1382{
1383 if (sel_add_event(ibs, cmd + 2)) {
1384 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1385 return;
1386 }
1387
1388 rsp_buffer_push(rsp, cmd[2]);
1389 rsp_buffer_push(rsp, cmd[3]);
1390}
1391
1392static void clear_sel(IPMIBmcSim *ibs,
1393 uint8_t *cmd, unsigned int cmd_len,
1394 RspBuffer *rsp)
1395{
1396 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1397 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1398 return;
1399 }
1400
1401 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1402 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1403 return;
1404 }
1405 if (cmd[7] == 0xaa) {
1406 ibs->sel.next_free = 0;
1407 ibs->sel.overflow = 0;
1408 set_timestamp(ibs, ibs->sdr.last_clear);
1409 rsp_buffer_push(rsp, 1);
1410 sel_inc_reservation(&ibs->sel);
1411 } else if (cmd[7] == 0) {
1412 rsp_buffer_push(rsp, 1);
1413 } else {
1414 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1415 return;
1416 }
1417}
1418
1419static void get_sel_time(IPMIBmcSim *ibs,
1420 uint8_t *cmd, unsigned int cmd_len,
1421 RspBuffer *rsp)
1422{
1423 uint32_t val;
1424 struct ipmi_time now;
1425
1426 ipmi_gettime(&now);
1427 val = now.tv_sec + ibs->sel.time_offset;
1428 rsp_buffer_push(rsp, val & 0xff);
1429 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1430 rsp_buffer_push(rsp, (val >> 16) & 0xff);
1431 rsp_buffer_push(rsp, (val >> 24) & 0xff);
1432}
1433
1434static void set_sel_time(IPMIBmcSim *ibs,
1435 uint8_t *cmd, unsigned int cmd_len,
1436 RspBuffer *rsp)
1437{
1438 uint32_t val;
1439 struct ipmi_time now;
1440
1441 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1442 ipmi_gettime(&now);
1443 ibs->sel.time_offset = now.tv_sec - ((long) val);
1444}
1445
1446static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1447 uint8_t *cmd, unsigned int cmd_len,
1448 RspBuffer *rsp)
1449{
1450 IPMISensor *sens;
1451
1452 if ((cmd[2] >= MAX_SENSORS) ||
1453 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1454 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1455 return;
1456 }
1457 sens = ibs->sensors + cmd[2];
1458 switch ((cmd[3] >> 4) & 0x3) {
1459 case 0:
1460 break;
1461 case 1:
1462 if (cmd_len > 4) {
1463 sens->assert_enable |= cmd[4];
1464 }
1465 if (cmd_len > 5) {
1466 sens->assert_enable |= cmd[5] << 8;
1467 }
1468 if (cmd_len > 6) {
1469 sens->deassert_enable |= cmd[6];
1470 }
1471 if (cmd_len > 7) {
1472 sens->deassert_enable |= cmd[7] << 8;
1473 }
1474 break;
1475 case 2:
1476 if (cmd_len > 4) {
1477 sens->assert_enable &= ~cmd[4];
1478 }
1479 if (cmd_len > 5) {
1480 sens->assert_enable &= ~(cmd[5] << 8);
1481 }
1482 if (cmd_len > 6) {
1483 sens->deassert_enable &= ~cmd[6];
1484 }
1485 if (cmd_len > 7) {
1486 sens->deassert_enable &= ~(cmd[7] << 8);
1487 }
1488 break;
1489 case 3:
1490 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1491 return;
1492 }
1493 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1494}
1495
1496static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1497 uint8_t *cmd, unsigned int cmd_len,
1498 RspBuffer *rsp)
1499{
1500 IPMISensor *sens;
1501
1502 if ((cmd[2] >= MAX_SENSORS) ||
1503 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1504 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1505 return;
1506 }
1507 sens = ibs->sensors + cmd[2];
1508 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1509 rsp_buffer_push(rsp, sens->assert_enable & 0xff);
1510 rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
1511 rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
1512 rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
1513}
1514
1515static void rearm_sensor_evts(IPMIBmcSim *ibs,
1516 uint8_t *cmd, unsigned int cmd_len,
1517 RspBuffer *rsp)
1518{
1519 IPMISensor *sens;
1520
1521 if ((cmd[2] >= MAX_SENSORS) ||
1522 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1523 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1524 return;
1525 }
1526 sens = ibs->sensors + cmd[2];
1527
1528 if ((cmd[3] & 0x80) == 0) {
1529
1530 sens->states = 0;
1531 return;
1532 }
1533}
1534
1535static void get_sensor_evt_status(IPMIBmcSim *ibs,
1536 uint8_t *cmd, unsigned int cmd_len,
1537 RspBuffer *rsp)
1538{
1539 IPMISensor *sens;
1540
1541 if ((cmd[2] >= MAX_SENSORS) ||
1542 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1543 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1544 return;
1545 }
1546 sens = ibs->sensors + cmd[2];
1547 rsp_buffer_push(rsp, sens->reading);
1548 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1549 rsp_buffer_push(rsp, sens->assert_states & 0xff);
1550 rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
1551 rsp_buffer_push(rsp, sens->deassert_states & 0xff);
1552 rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
1553}
1554
1555static void get_sensor_reading(IPMIBmcSim *ibs,
1556 uint8_t *cmd, unsigned int cmd_len,
1557 RspBuffer *rsp)
1558{
1559 IPMISensor *sens;
1560
1561 if ((cmd[2] >= MAX_SENSORS) ||
1562 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1563 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1564 return;
1565 }
1566 sens = ibs->sensors + cmd[2];
1567 rsp_buffer_push(rsp, sens->reading);
1568 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1569 rsp_buffer_push(rsp, sens->states & 0xff);
1570 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1571 rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
1572 }
1573}
1574
1575static void set_sensor_type(IPMIBmcSim *ibs,
1576 uint8_t *cmd, unsigned int cmd_len,
1577 RspBuffer *rsp)
1578{
1579 IPMISensor *sens;
1580
1581
1582 if ((cmd[2] >= MAX_SENSORS) ||
1583 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1584 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1585 return;
1586 }
1587 sens = ibs->sensors + cmd[2];
1588 sens->sensor_type = cmd[3];
1589 sens->evt_reading_type_code = cmd[4] & 0x7f;
1590}
1591
1592static void get_sensor_type(IPMIBmcSim *ibs,
1593 uint8_t *cmd, unsigned int cmd_len,
1594 RspBuffer *rsp)
1595{
1596 IPMISensor *sens;
1597
1598
1599 if ((cmd[2] >= MAX_SENSORS) ||
1600 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1601 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1602 return;
1603 }
1604 sens = ibs->sensors + cmd[2];
1605 rsp_buffer_push(rsp, sens->sensor_type);
1606 rsp_buffer_push(rsp, sens->evt_reading_type_code);
1607}
1608
1609
1610static const IPMICmdHandler chassis_cmds[] = {
1611 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
1612 [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
1613 [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
1614 [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
1615};
1616static const IPMINetfn chassis_netfn = {
1617 .cmd_nums = ARRAY_SIZE(chassis_cmds),
1618 .cmd_handlers = chassis_cmds
1619};
1620
1621static const IPMICmdHandler sensor_event_cmds[] = {
1622 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
1623 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
1624 [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
1625 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
1626 [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
1627 [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
1628 [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
1629};
1630static const IPMINetfn sensor_event_netfn = {
1631 .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
1632 .cmd_handlers = sensor_event_cmds
1633};
1634
1635static const IPMICmdHandler app_cmds[] = {
1636 [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
1637 [IPMI_CMD_COLD_RESET] = { cold_reset },
1638 [IPMI_CMD_WARM_RESET] = { warm_reset },
1639 [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
1640 [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
1641 [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
1642 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
1643 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
1644 [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
1645 [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
1646 [IPMI_CMD_GET_MSG] = { get_msg },
1647 [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
1648 [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
1649 [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
1650 [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
1651 [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
1652};
1653static const IPMINetfn app_netfn = {
1654 .cmd_nums = ARRAY_SIZE(app_cmds),
1655 .cmd_handlers = app_cmds
1656};
1657
1658static const IPMICmdHandler storage_cmds[] = {
1659 [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
1660 [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
1661 [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
1662 [IPMI_CMD_ADD_SDR] = { add_sdr },
1663 [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
1664 [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
1665 [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
1666 [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
1667 [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
1668 [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
1669 [IPMI_CMD_GET_SEL_TIME] = { get_sel_time, 6 },
1670 [IPMI_CMD_SET_SEL_TIME] = { set_sel_time },
1671};
1672
1673static const IPMINetfn storage_netfn = {
1674 .cmd_nums = ARRAY_SIZE(storage_cmds),
1675 .cmd_handlers = storage_cmds
1676};
1677
1678static void register_cmds(IPMIBmcSim *s)
1679{
1680 ipmi_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
1681 ipmi_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
1682 ipmi_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
1683 ipmi_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
1684}
1685
1686static uint8_t init_sdrs[] = {
1687
1688 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1689 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1692 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1693};
1694
1695static void ipmi_sdr_init(IPMIBmcSim *ibs)
1696{
1697 unsigned int i;
1698 int len;
1699 size_t sdrs_size;
1700 uint8_t *sdrs;
1701
1702 sdrs_size = sizeof(init_sdrs);
1703 sdrs = init_sdrs;
1704
1705 for (i = 0; i < sdrs_size; i += len) {
1706 struct ipmi_sdr_header *sdrh;
1707
1708 if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
1709 error_report("Problem with recid 0x%4.4x", i);
1710 return;
1711 }
1712 sdrh = (struct ipmi_sdr_header *) &sdrs[i];
1713 len = ipmi_sdr_length(sdrh);
1714 if (i + len > sdrs_size) {
1715 error_report("Problem with recid 0x%4.4x", i);
1716 return;
1717 }
1718 sdr_add_entry(ibs, sdrh, len, NULL);
1719 }
1720}
1721
1722static const VMStateDescription vmstate_ipmi_sim = {
1723 .name = TYPE_IPMI_BMC_SIMULATOR,
1724 .version_id = 1,
1725 .minimum_version_id = 1,
1726 .fields = (VMStateField[]) {
1727 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
1728 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
1729 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
1730 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
1731 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
1732 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
1733 VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
1734 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
1735 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
1736 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
1737 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
1738 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
1739 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
1740 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
1741 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
1742 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
1743 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
1744 IPMIBmcSim),
1745 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
1746 VMSTATE_END_OF_LIST()
1747 }
1748};
1749
1750static void ipmi_sim_realize(DeviceState *dev, Error **errp)
1751{
1752 IPMIBmc *b = IPMI_BMC(dev);
1753 unsigned int i;
1754 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
1755
1756 qemu_mutex_init(&ibs->lock);
1757 QTAILQ_INIT(&ibs->rcvbufs);
1758
1759 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
1760 ibs->device_id = 0x20;
1761 ibs->ipmi_version = 0x02;
1762 ibs->restart_cause = 0;
1763 for (i = 0; i < 4; i++) {
1764 ibs->sel.last_addition[i] = 0xff;
1765 ibs->sel.last_clear[i] = 0xff;
1766 ibs->sdr.last_addition[i] = 0xff;
1767 ibs->sdr.last_clear[i] = 0xff;
1768 }
1769
1770 ipmi_sdr_init(ibs);
1771
1772 ibs->acpi_power_state[0] = 0;
1773 ibs->acpi_power_state[1] = 0;
1774
1775 if (qemu_uuid_set) {
1776 memcpy(&ibs->uuid, qemu_uuid, 16);
1777 } else {
1778 memset(&ibs->uuid, 0, 16);
1779 }
1780
1781 ipmi_init_sensors_from_sdrs(ibs);
1782 register_cmds(ibs);
1783
1784 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
1785
1786 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
1787}
1788
1789static void ipmi_sim_class_init(ObjectClass *oc, void *data)
1790{
1791 DeviceClass *dc = DEVICE_CLASS(oc);
1792 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
1793
1794 dc->realize = ipmi_sim_realize;
1795 bk->handle_command = ipmi_sim_handle_command;
1796}
1797
1798static const TypeInfo ipmi_sim_type = {
1799 .name = TYPE_IPMI_BMC_SIMULATOR,
1800 .parent = TYPE_IPMI_BMC,
1801 .instance_size = sizeof(IPMIBmcSim),
1802 .class_init = ipmi_sim_class_init,
1803};
1804
1805static void ipmi_sim_register_types(void)
1806{
1807 type_register_static(&ipmi_sim_type);
1808}
1809
1810type_init(ipmi_sim_register_types)
1811