Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-2016-07-21-1' into...
[qemu/ar7.git] / hw / ipmi / ipmi_bmc_sim.c
blobdc9c14cd29317ce4e3c25657e3c9a5aae3a76268
1 /*
2 * IPMI BMC emulation
4 * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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.
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"
31 #define IPMI_NETFN_CHASSIS 0x00
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
38 #define IPMI_NETFN_SENSOR_EVENT 0x04
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
48 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
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
67 #define IPMI_NETFN_STORAGE 0x0a
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
94 /* Same as a timespec struct. */
95 struct ipmi_time {
96 long tv_sec;
97 long tv_nsec;
100 #define MAX_SEL_SIZE 128
102 typedef 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;
112 #define MAX_SDR_SIZE 16384
114 typedef 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;
124 typedef 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)
152 #define MAX_SENSORS 20
153 #define IPMI_WATCHDOG_SENSOR 0
155 typedef struct IPMIBmcSim IPMIBmcSim;
156 typedef struct RspBuffer RspBuffer;
158 #define MAX_NETFNS 64
160 typedef 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;
167 typedef struct IPMINetfn {
168 unsigned int cmd_nums;
169 const IPMICmdHandler *cmd_handlers;
170 } IPMINetfn;
172 typedef struct IPMIRcvBufEntry {
173 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
174 uint8_t len;
175 uint8_t buf[MAX_IPMI_MSG_SIZE];
176 } IPMIRcvBufEntry;
178 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
179 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
180 TYPE_IPMI_BMC_SIMULATOR)
181 struct IPMIBmcSim {
182 IPMIBmc parent;
184 QEMUTimer *timer;
186 uint8_t bmc_global_enables;
187 uint8_t msg_flags;
189 bool watchdog_initialized;
190 uint8_t watchdog_use;
191 uint8_t watchdog_action;
192 uint8_t watchdog_pretimeout; /* In seconds */
193 bool watchdog_expired;
194 uint16_t watchdog_timeout; /* in 100's of milliseconds */
196 bool watchdog_running;
197 bool watchdog_preaction_ran;
198 int64_t watchdog_expiry;
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];
208 uint8_t restart_cause;
210 uint8_t acpi_power_state[2];
211 uint8_t uuid[16];
213 IPMISel sel;
214 IPMISdr sdr;
215 IPMISensor sensors[MAX_SENSORS];
217 /* Odd netfns are for responses, so we only need the even ones. */
218 const IPMINetfn *netfns[MAX_NETFNS / 2];
220 QemuMutex lock;
221 /* We allow one event in the buffer */
222 uint8_t evtbuf[16];
224 QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
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)
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))
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
266 struct RspBuffer {
267 uint8_t buffer[MAX_IPMI_MSG_SIZE];
268 unsigned int len;
271 #define RSP_BUFFER_INITIALIZER { }
273 static inline void rsp_buffer_set_error(RspBuffer *rsp, uint8_t byte)
275 rsp->buffer[2] = byte;
278 /* Add a byte to the response. */
279 static inline void rsp_buffer_push(RspBuffer *rsp, uint8_t byte)
281 if (rsp->len >= sizeof(rsp->buffer)) {
282 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
283 return;
285 rsp->buffer[rsp->len++] = byte;
288 static inline void rsp_buffer_pushmore(RspBuffer *rsp, uint8_t *bytes,
289 unsigned int n)
291 if (rsp->len + n >= sizeof(rsp->buffer)) {
292 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
293 return;
296 memcpy(&rsp->buffer[rsp->len], bytes, n);
297 rsp->len += n;
300 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
302 static void ipmi_gettime(struct ipmi_time *time)
304 int64_t stime;
306 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
307 time->tv_sec = stime / 1000000000LL;
308 time->tv_nsec = stime % 1000000000LL;
311 static int64_t ipmi_getmonotime(void)
313 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
316 static void ipmi_timeout(void *opaque)
318 IPMIBmcSim *ibs = opaque;
320 ipmi_sim_handle_timeout(ibs);
323 static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
325 unsigned int val;
326 struct ipmi_time now;
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;
336 static void sdr_inc_reservation(IPMISdr *sdr)
338 sdr->reservation++;
339 if (sdr->reservation == 0) {
340 sdr->reservation = 1;
344 static int sdr_add_entry(IPMIBmcSim *ibs,
345 const struct ipmi_sdr_header *sdrh_entry,
346 unsigned int len, uint16_t *recid)
348 struct ipmi_sdr_header *sdrh =
349 (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
351 if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
352 return 1;
355 if (ipmi_sdr_length(sdrh_entry) != len) {
356 return 1;
359 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
360 ibs->sdr.overflow = 1;
361 return 1;
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; /* Conform to IPMI 1.5 spec */
369 if (recid) {
370 *recid = ibs->sdr.next_rec_id;
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;
379 static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
380 unsigned int *retpos, uint16_t *nextrec)
382 unsigned int pos = *retpos;
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);
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));
399 *retpos = pos;
400 return 0;
402 pos = nextpos;
404 return 1;
407 static void sel_inc_reservation(IPMISel *sel)
409 sel->reservation++;
410 if (sel->reservation == 0) {
411 sel->reservation = 1;
415 /* Returns 1 if the SEL is full and can't hold the event. */
416 static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
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;
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;
434 static int attn_set(IPMIBmcSim *ibs)
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);
441 static int attn_irq_enabled(IPMIBmcSim *ibs)
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));
448 static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
449 uint8_t evd1, uint8_t evd2, uint8_t evd3)
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;
456 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
457 return;
459 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
460 return;
463 evt[2] = 0x2; /* System event record */
464 evt[7] = ibs->parent.slave_addr;
465 evt[8] = 0;
466 evt[9] = 0x04; /* Format version */
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;
474 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
475 sel_add_event(ibs, evt);
478 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
479 return;
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));
487 static 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)
491 IPMISensor *sens;
492 uint16_t mask;
494 if (sensor >= MAX_SENSORS) {
495 return;
497 if (bit >= 16) {
498 return;
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; /* Already asserted */
508 sens->assert_states |= mask & sens->assert_suppt;
509 if (sens->assert_enable & mask & sens->assert_states) {
510 /* Send an event on assert */
511 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
513 } else {
514 sens->states &= ~(mask & sens->states_suppt);
515 if (sens->deassert_states & mask) {
516 return; /* Already deasserted */
518 sens->deassert_states |= mask & sens->deassert_suppt;
519 if (sens->deassert_enable & mask & sens->deassert_states) {
520 /* Send an event on deassert */
521 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
526 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
528 unsigned int i, pos;
529 IPMISensor *sens;
531 for (i = 0; i < MAX_SENSORS; i++) {
532 memset(s->sensors + i, 0, sizeof(*sens));
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;
541 if (len < 20) {
542 continue;
544 if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
545 continue; /* Not a sensor SDR we set from */
548 if (sdr->sensor_owner_number >= MAX_SENSORS) {
549 continue;
551 sens = s->sensors + sdr->sensor_owner_number;
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;
564 /* Enable all the events that are supported. */
565 sens->assert_enable = sens->assert_suppt;
566 sens->deassert_enable = sens->deassert_suppt;
570 static int ipmi_register_netfn(IPMIBmcSim *s, unsigned int netfn,
571 const IPMINetfn *netfnd)
573 if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
574 return -1;
576 s->netfns[netfn / 2] = netfnd;
577 return 0;
580 static const IPMICmdHandler *ipmi_get_handler(IPMIBmcSim *ibs,
581 unsigned int netfn,
582 unsigned int cmd)
584 const IPMICmdHandler *hdl;
586 if (netfn & 1 || netfn >= MAX_NETFNS || !ibs->netfns[netfn / 2]) {
587 return NULL;
590 if (cmd >= ibs->netfns[netfn / 2]->cmd_nums) {
591 return NULL;
594 hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd];
595 if (!hdl->cmd_handler) {
596 return NULL;
599 return hdl;
602 static void next_timeout(IPMIBmcSim *ibs)
604 int64_t next;
605 if (ibs->watchdog_running) {
606 next = ibs->watchdog_expiry;
607 } else {
608 /* Wait a minute */
609 next = ipmi_getmonotime() + 60 * 1000000000LL;
611 timer_mod_ns(ibs->timer, next);
614 static 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)
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;
625 /* Set up the response, set the low bit of NETFN. */
626 /* Note that max_rsp_len must be at least 3 */
627 if (sizeof(rsp.buffer) < 3) {
628 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
629 goto out;
632 rsp_buffer_push(&rsp, cmd[0] | 0x04);
633 rsp_buffer_push(&rsp, cmd[1]);
634 rsp_buffer_push(&rsp, 0); /* Assume success */
636 /* If it's too short or it was truncated, return an error. */
637 if (cmd_len < 2) {
638 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
639 goto out;
641 if (cmd_len > max_cmd_len) {
642 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
643 goto out;
646 if ((cmd[0] & 0x03) != 0) {
647 /* Only have stuff on LUN 0 */
648 rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN);
649 goto out;
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;
658 if (cmd_len < hdl->cmd_len_min) {
659 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
660 goto out;
663 hdl->cmd_handler(ibs, cmd, cmd_len, &rsp);
665 out:
666 k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
668 next_timeout(ibs);
671 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
673 IPMIInterface *s = ibs->parent.intf;
674 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
676 if (!ibs->watchdog_running) {
677 goto out;
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;
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;
696 default:
697 goto do_full_expiry;
700 ibs->watchdog_preaction_ran = 1;
701 /* Issued the pretimeout, do the rest of the timeout now. */
702 ibs->watchdog_expiry = ipmi_getmonotime();
703 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
704 goto out;
707 do_full_expiry:
708 ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
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;
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;
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;
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;
735 out:
736 next_timeout(ibs);
739 static void chassis_capabilities(IPMIBmcSim *ibs,
740 uint8_t *cmd, unsigned int cmd_len,
741 RspBuffer *rsp)
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);
750 static void chassis_status(IPMIBmcSim *ibs,
751 uint8_t *cmd, unsigned int cmd_len,
752 RspBuffer *rsp)
754 rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */
755 rsp_buffer_push(rsp, 0);
756 rsp_buffer_push(rsp, 0);
757 rsp_buffer_push(rsp, 0);
760 static void chassis_control(IPMIBmcSim *ibs,
761 uint8_t *cmd, unsigned int cmd_len,
762 RspBuffer *rsp)
764 IPMIInterface *s = ibs->parent.intf;
765 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
767 switch (cmd[2] & 0xf) {
768 case 0: /* power down */
769 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0));
770 break;
771 case 1: /* power up */
772 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0));
773 break;
774 case 2: /* power cycle */
775 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0));
776 break;
777 case 3: /* hard reset */
778 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0));
779 break;
780 case 4: /* pulse diagnostic interrupt */
781 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0));
782 break;
783 case 5: /* soft shutdown via ACPI by overtemp emulation */
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;
793 static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
794 uint8_t *cmd, unsigned int cmd_len,
795 RspBuffer *rsp)
798 rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */
799 rsp_buffer_push(rsp, 0); /* Channel 0 */
802 static void get_device_id(IPMIBmcSim *ibs,
803 uint8_t *cmd, unsigned int cmd_len,
804 RspBuffer *rsp)
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); /* sensor, SDR, and SEL. */
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]);
819 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
821 IPMIInterface *s = ibs->parent.intf;
822 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
823 bool irqs_on;
825 ibs->bmc_global_enables = val;
827 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
828 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
830 k->set_irq_enable(s, irqs_on);
833 static void cold_reset(IPMIBmcSim *ibs,
834 uint8_t *cmd, unsigned int cmd_len,
835 RspBuffer *rsp)
837 IPMIInterface *s = ibs->parent.intf;
838 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
840 /* Disable all interrupts */
841 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
843 if (k->reset) {
844 k->reset(s, true);
848 static void warm_reset(IPMIBmcSim *ibs,
849 uint8_t *cmd, unsigned int cmd_len,
850 RspBuffer *rsp)
852 IPMIInterface *s = ibs->parent.intf;
853 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
855 if (k->reset) {
856 k->reset(s, false);
859 static void set_acpi_power_state(IPMIBmcSim *ibs,
860 uint8_t *cmd, unsigned int cmd_len,
861 RspBuffer *rsp)
863 ibs->acpi_power_state[0] = cmd[2];
864 ibs->acpi_power_state[1] = cmd[3];
867 static void get_acpi_power_state(IPMIBmcSim *ibs,
868 uint8_t *cmd, unsigned int cmd_len,
869 RspBuffer *rsp)
871 rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
872 rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
875 static void get_device_guid(IPMIBmcSim *ibs,
876 uint8_t *cmd, unsigned int cmd_len,
877 RspBuffer *rsp)
879 unsigned int i;
881 for (i = 0; i < 16; i++) {
882 rsp_buffer_push(rsp, ibs->uuid[i]);
886 static void set_bmc_global_enables(IPMIBmcSim *ibs,
887 uint8_t *cmd, unsigned int cmd_len,
888 RspBuffer *rsp)
890 set_global_enables(ibs, cmd[2]);
893 static void get_bmc_global_enables(IPMIBmcSim *ibs,
894 uint8_t *cmd, unsigned int cmd_len,
895 RspBuffer *rsp)
897 rsp_buffer_push(rsp, ibs->bmc_global_enables);
900 static void clr_msg_flags(IPMIBmcSim *ibs,
901 uint8_t *cmd, unsigned int cmd_len,
902 RspBuffer *rsp)
904 IPMIInterface *s = ibs->parent.intf;
905 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
907 ibs->msg_flags &= ~cmd[2];
908 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
911 static void get_msg_flags(IPMIBmcSim *ibs,
912 uint8_t *cmd, unsigned int cmd_len,
913 RspBuffer *rsp)
915 rsp_buffer_push(rsp, ibs->msg_flags);
918 static void read_evt_msg_buf(IPMIBmcSim *ibs,
919 uint8_t *cmd, unsigned int cmd_len,
920 RspBuffer *rsp)
922 IPMIInterface *s = ibs->parent.intf;
923 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
924 unsigned int i;
926 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
927 rsp_buffer_set_error(rsp, 0x80);
928 return;
930 for (i = 0; i < 16; i++) {
931 rsp_buffer_push(rsp, ibs->evtbuf[i]);
933 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
934 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
937 static void get_msg(IPMIBmcSim *ibs,
938 uint8_t *cmd, unsigned int cmd_len,
939 RspBuffer *rsp)
941 IPMIRcvBufEntry *msg;
943 qemu_mutex_lock(&ibs->lock);
944 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
945 rsp_buffer_set_error(rsp, 0x80); /* Queue empty */
946 goto out;
948 rsp_buffer_push(rsp, 0); /* Channel 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);
954 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
955 IPMIInterface *s = ibs->parent.intf;
956 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
958 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
959 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
962 out:
963 qemu_mutex_unlock(&ibs->lock);
964 return;
967 static unsigned char
968 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
970 for (; size > 0; size--, data++) {
971 csum += *data;
974 return -csum;
977 static void send_msg(IPMIBmcSim *ibs,
978 uint8_t *cmd, unsigned int cmd_len,
979 RspBuffer *rsp)
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;
987 if (cmd[2] != 0) {
988 /* We only handle channel 0 with no options */
989 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
990 return;
993 if (cmd_len < 10) {
994 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
995 return;
998 if (cmd[3] != 0x40) {
999 /* We only emulate a MC at address 0x40. */
1000 rsp_buffer_set_error(rsp, 0x83); /* NAK on write */
1001 return;
1004 cmd += 3; /* Skip the header. */
1005 cmd_len -= 3;
1008 * At this point we "send" the message successfully. Any error will
1009 * be returned in the response.
1011 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
1012 cmd[3] != 0x20) { /* Improper response address */
1013 return; /* No response */
1016 netfn = cmd[1] >> 2;
1017 rqLun = cmd[4] & 0x3;
1018 rsLun = cmd[1] & 0x3;
1019 rqSeq = cmd[4] >> 2;
1021 if (rqLun != 2) {
1022 /* We only support LUN 2 coming back to us. */
1023 return;
1026 msg = g_malloc(sizeof(*msg));
1027 msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
1028 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
1029 msg->buf[2] = cmd[0]; /* rsSA */
1030 msg->buf[3] = (rqSeq << 2) | rsLun;
1031 msg->buf[4] = cmd[5]; /* Cmd */
1032 msg->buf[5] = 0; /* Completion Code */
1033 msg->len = 6;
1035 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
1036 /* Not a command we handle. */
1037 msg->buf[5] = IPMI_CC_INVALID_CMD;
1038 goto end_msg;
1041 buf = msg->buf + msg->len; /* After the CC */
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;
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);
1065 static void do_watchdog_reset(IPMIBmcSim *ibs)
1067 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1068 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1069 ibs->watchdog_running = 0;
1070 return;
1072 ibs->watchdog_preaction_ran = 0;
1075 /* Timeout is in tenths of a second, offset is in seconds */
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;
1081 ibs->watchdog_running = 1;
1084 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1085 uint8_t *cmd, unsigned int cmd_len,
1086 RspBuffer *rsp)
1088 if (!ibs->watchdog_initialized) {
1089 rsp_buffer_set_error(rsp, 0x80);
1090 return;
1092 do_watchdog_reset(ibs);
1095 static void set_watchdog_timer(IPMIBmcSim *ibs,
1096 uint8_t *cmd, unsigned int cmd_len,
1097 RspBuffer *rsp)
1099 IPMIInterface *s = ibs->parent.intf;
1100 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1101 unsigned int val;
1103 val = cmd[2] & 0x7; /* Validate use */
1104 if (val == 0 || val > 5) {
1105 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1106 return;
1108 val = cmd[3] & 0x7; /* Validate action */
1109 switch (val) {
1110 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1111 break;
1113 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1114 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1));
1115 break;
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;
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;
1125 default:
1126 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1128 if (rsp->buffer[2]) {
1129 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1130 return;
1133 val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1134 switch (val) {
1135 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1136 case IPMI_BMC_WATCHDOG_PRE_NONE:
1137 break;
1139 case IPMI_BMC_WATCHDOG_PRE_NMI:
1140 if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1141 /* NMI not supported. */
1142 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1143 return;
1145 break;
1147 default:
1148 /* We don't support PRE_SMI */
1149 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1150 return;
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;
1166 static void get_watchdog_timer(IPMIBmcSim *ibs,
1167 uint8_t *cmd, unsigned int cmd_len,
1168 RspBuffer *rsp)
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);
1186 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1187 uint8_t *cmd, unsigned int cmd_len,
1188 RspBuffer *rsp)
1190 unsigned int i;
1192 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */
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]);
1200 for (i = 0; i < 4; i++) {
1201 rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
1203 /* Only modal support, reserve supported */
1204 rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
1207 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1208 uint8_t *cmd, unsigned int cmd_len,
1209 RspBuffer *rsp)
1211 rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
1212 rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
1215 static void get_sdr(IPMIBmcSim *ibs,
1216 uint8_t *cmd, unsigned int cmd_len,
1217 RspBuffer *rsp)
1219 unsigned int pos;
1220 uint16_t nextrec;
1221 struct ipmi_sdr_header *sdrh;
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;
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;
1237 sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1239 if (cmd[6] > ipmi_sdr_length(sdrh)) {
1240 rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE);
1241 return;
1244 rsp_buffer_push(rsp, nextrec & 0xff);
1245 rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
1247 if (cmd[7] == 0xff) {
1248 cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1251 if ((cmd[7] + rsp->len) > sizeof(rsp->buffer)) {
1252 rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES);
1253 return;
1256 rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1259 static void add_sdr(IPMIBmcSim *ibs,
1260 uint8_t *cmd, unsigned int cmd_len,
1261 RspBuffer *rsp)
1263 uint16_t recid;
1264 struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1266 if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1267 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1268 return;
1270 rsp_buffer_push(rsp, recid & 0xff);
1271 rsp_buffer_push(rsp, (recid >> 8) & 0xff);
1274 static void clear_sdr_rep(IPMIBmcSim *ibs,
1275 uint8_t *cmd, unsigned int cmd_len,
1276 RspBuffer *rsp)
1278 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1279 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1280 return;
1283 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1284 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1285 return;
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); /* Erasure complete */
1292 sdr_inc_reservation(&ibs->sdr);
1293 } else if (cmd[7] == 0) {
1294 rsp_buffer_push(rsp, 1); /* Erasure complete */
1295 } else {
1296 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1297 return;
1301 static void get_sel_info(IPMIBmcSim *ibs,
1302 uint8_t *cmd, unsigned int cmd_len,
1303 RspBuffer *rsp)
1305 unsigned int i, val;
1307 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */
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]);
1316 for (i = 0; i < 4; i++) {
1317 rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
1319 /* Only support Reserve SEL */
1320 rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
1323 static void reserve_sel(IPMIBmcSim *ibs,
1324 uint8_t *cmd, unsigned int cmd_len,
1325 RspBuffer *rsp)
1327 rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
1328 rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
1331 static void get_sel_entry(IPMIBmcSim *ibs,
1332 uint8_t *cmd, unsigned int cmd_len,
1333 RspBuffer *rsp)
1335 unsigned int val;
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;
1343 if (ibs->sel.next_free == 0) {
1344 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1345 return;
1347 if (cmd[6] > 15) {
1348 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1349 return;
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];
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;
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);
1374 for (; cmd[6] < cmd[7]; cmd[6]++) {
1375 rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
1379 static void add_sel_entry(IPMIBmcSim *ibs,
1380 uint8_t *cmd, unsigned int cmd_len,
1381 RspBuffer *rsp)
1383 if (sel_add_event(ibs, cmd + 2)) {
1384 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1385 return;
1387 /* sel_add_event fills in the record number. */
1388 rsp_buffer_push(rsp, cmd[2]);
1389 rsp_buffer_push(rsp, cmd[3]);
1392 static void clear_sel(IPMIBmcSim *ibs,
1393 uint8_t *cmd, unsigned int cmd_len,
1394 RspBuffer *rsp)
1396 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1397 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1398 return;
1401 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1402 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1403 return;
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); /* Erasure complete */
1410 sel_inc_reservation(&ibs->sel);
1411 } else if (cmd[7] == 0) {
1412 rsp_buffer_push(rsp, 1); /* Erasure complete */
1413 } else {
1414 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1415 return;
1419 static void get_sel_time(IPMIBmcSim *ibs,
1420 uint8_t *cmd, unsigned int cmd_len,
1421 RspBuffer *rsp)
1423 uint32_t val;
1424 struct ipmi_time now;
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);
1434 static void set_sel_time(IPMIBmcSim *ibs,
1435 uint8_t *cmd, unsigned int cmd_len,
1436 RspBuffer *rsp)
1438 uint32_t val;
1439 struct ipmi_time now;
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);
1446 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1447 uint8_t *cmd, unsigned int cmd_len,
1448 RspBuffer *rsp)
1450 IPMISensor *sens;
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;
1457 sens = ibs->sensors + cmd[2];
1458 switch ((cmd[3] >> 4) & 0x3) {
1459 case 0: /* Do not change */
1460 break;
1461 case 1: /* Enable bits */
1462 if (cmd_len > 4) {
1463 sens->assert_enable |= cmd[4];
1465 if (cmd_len > 5) {
1466 sens->assert_enable |= cmd[5] << 8;
1468 if (cmd_len > 6) {
1469 sens->deassert_enable |= cmd[6];
1471 if (cmd_len > 7) {
1472 sens->deassert_enable |= cmd[7] << 8;
1474 break;
1475 case 2: /* Disable bits */
1476 if (cmd_len > 4) {
1477 sens->assert_enable &= ~cmd[4];
1479 if (cmd_len > 5) {
1480 sens->assert_enable &= ~(cmd[5] << 8);
1482 if (cmd_len > 6) {
1483 sens->deassert_enable &= ~cmd[6];
1485 if (cmd_len > 7) {
1486 sens->deassert_enable &= ~(cmd[7] << 8);
1488 break;
1489 case 3:
1490 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1491 return;
1493 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1496 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1497 uint8_t *cmd, unsigned int cmd_len,
1498 RspBuffer *rsp)
1500 IPMISensor *sens;
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;
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);
1515 static void rearm_sensor_evts(IPMIBmcSim *ibs,
1516 uint8_t *cmd, unsigned int cmd_len,
1517 RspBuffer *rsp)
1519 IPMISensor *sens;
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;
1526 sens = ibs->sensors + cmd[2];
1528 if ((cmd[3] & 0x80) == 0) {
1529 /* Just clear everything */
1530 sens->states = 0;
1531 return;
1535 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1536 uint8_t *cmd, unsigned int cmd_len,
1537 RspBuffer *rsp)
1539 IPMISensor *sens;
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;
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);
1555 static void get_sensor_reading(IPMIBmcSim *ibs,
1556 uint8_t *cmd, unsigned int cmd_len,
1557 RspBuffer *rsp)
1559 IPMISensor *sens;
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;
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);
1575 static void set_sensor_type(IPMIBmcSim *ibs,
1576 uint8_t *cmd, unsigned int cmd_len,
1577 RspBuffer *rsp)
1579 IPMISensor *sens;
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;
1587 sens = ibs->sensors + cmd[2];
1588 sens->sensor_type = cmd[3];
1589 sens->evt_reading_type_code = cmd[4] & 0x7f;
1592 static void get_sensor_type(IPMIBmcSim *ibs,
1593 uint8_t *cmd, unsigned int cmd_len,
1594 RspBuffer *rsp)
1596 IPMISensor *sens;
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;
1604 sens = ibs->sensors + cmd[2];
1605 rsp_buffer_push(rsp, sens->sensor_type);
1606 rsp_buffer_push(rsp, sens->evt_reading_type_code);
1610 static 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 }
1616 static const IPMINetfn chassis_netfn = {
1617 .cmd_nums = ARRAY_SIZE(chassis_cmds),
1618 .cmd_handlers = chassis_cmds
1621 static 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 },
1630 static const IPMINetfn sensor_event_netfn = {
1631 .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
1632 .cmd_handlers = sensor_event_cmds
1635 static 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 },
1653 static const IPMINetfn app_netfn = {
1654 .cmd_nums = ARRAY_SIZE(app_cmds),
1655 .cmd_handlers = app_cmds
1658 static 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 },
1673 static const IPMINetfn storage_netfn = {
1674 .cmd_nums = ARRAY_SIZE(storage_cmds),
1675 .cmd_handlers = storage_cmds
1678 static void register_cmds(IPMIBmcSim *s)
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);
1686 static uint8_t init_sdrs[] = {
1687 /* Watchdog device */
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',
1695 static void ipmi_sdr_init(IPMIBmcSim *ibs)
1697 unsigned int i;
1698 int len;
1699 size_t sdrs_size;
1700 uint8_t *sdrs;
1702 sdrs_size = sizeof(init_sdrs);
1703 sdrs = init_sdrs;
1705 for (i = 0; i < sdrs_size; i += len) {
1706 struct ipmi_sdr_header *sdrh;
1708 if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
1709 error_report("Problem with recid 0x%4.4x", i);
1710 return;
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;
1718 sdr_add_entry(ibs, sdrh, len, NULL);
1722 static 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()
1750 static void ipmi_sim_realize(DeviceState *dev, Error **errp)
1752 IPMIBmc *b = IPMI_BMC(dev);
1753 unsigned int i;
1754 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
1756 qemu_mutex_init(&ibs->lock);
1757 QTAILQ_INIT(&ibs->rcvbufs);
1759 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
1760 ibs->device_id = 0x20;
1761 ibs->ipmi_version = 0x02; /* IPMI 2.0 */
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;
1770 ipmi_sdr_init(ibs);
1772 ibs->acpi_power_state[0] = 0;
1773 ibs->acpi_power_state[1] = 0;
1775 if (qemu_uuid_set) {
1776 memcpy(&ibs->uuid, qemu_uuid, 16);
1777 } else {
1778 memset(&ibs->uuid, 0, 16);
1781 ipmi_init_sensors_from_sdrs(ibs);
1782 register_cmds(ibs);
1784 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
1786 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
1789 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
1791 DeviceClass *dc = DEVICE_CLASS(oc);
1792 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
1794 dc->realize = ipmi_sim_realize;
1795 bk->handle_command = ipmi_sim_handle_command;
1798 static 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,
1805 static void ipmi_sim_register_types(void)
1807 type_register_static(&ipmi_sim_type);
1810 type_init(ipmi_sim_register_types)