ipmi: add GET_SYS_RESTART_CAUSE chassis command
[qemu/ar7.git] / hw / ipmi / ipmi_bmc_sim.c
blob29224ddd89179524e0e11344f2fef8fca012e397
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 "qemu/timer.h"
27 #include "hw/ipmi/ipmi.h"
28 #include "qemu/error-report.h"
30 #define IPMI_NETFN_CHASSIS 0x00
32 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
33 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
34 #define IPMI_CMD_CHASSIS_CONTROL 0x02
35 #define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09
37 #define IPMI_NETFN_SENSOR_EVENT 0x04
39 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
40 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
41 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
42 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
43 #define IPMI_CMD_GET_SENSOR_READING 0x2d
44 #define IPMI_CMD_SET_SENSOR_TYPE 0x2e
45 #define IPMI_CMD_GET_SENSOR_TYPE 0x2f
47 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
49 #define IPMI_CMD_GET_DEVICE_ID 0x01
50 #define IPMI_CMD_COLD_RESET 0x02
51 #define IPMI_CMD_WARM_RESET 0x03
52 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
53 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
54 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
55 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
56 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
57 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
58 #define IPMI_CMD_GET_MSG_FLAGS 0x31
59 #define IPMI_CMD_GET_MSG 0x33
60 #define IPMI_CMD_SEND_MSG 0x34
61 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
63 #define IPMI_NETFN_STORAGE 0x0a
65 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
66 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
67 #define IPMI_CMD_RESERVE_SDR_REP 0x22
68 #define IPMI_CMD_GET_SDR 0x23
69 #define IPMI_CMD_ADD_SDR 0x24
70 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
71 #define IPMI_CMD_DELETE_SDR 0x26
72 #define IPMI_CMD_CLEAR_SDR_REP 0x27
73 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
74 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
75 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
76 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
77 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
78 #define IPMI_CMD_GET_SEL_INFO 0x40
79 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
80 #define IPMI_CMD_RESERVE_SEL 0x42
81 #define IPMI_CMD_GET_SEL_ENTRY 0x43
82 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
83 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
84 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
85 #define IPMI_CMD_CLEAR_SEL 0x47
86 #define IPMI_CMD_GET_SEL_TIME 0x48
87 #define IPMI_CMD_SET_SEL_TIME 0x49
90 /* Same as a timespec struct. */
91 struct ipmi_time {
92 long tv_sec;
93 long tv_nsec;
96 #define MAX_SEL_SIZE 128
98 typedef struct IPMISel {
99 uint8_t sel[MAX_SEL_SIZE][16];
100 unsigned int next_free;
101 long time_offset;
102 uint16_t reservation;
103 uint8_t last_addition[4];
104 uint8_t last_clear[4];
105 uint8_t overflow;
106 } IPMISel;
108 #define MAX_SDR_SIZE 16384
110 typedef struct IPMISdr {
111 uint8_t sdr[MAX_SDR_SIZE];
112 unsigned int next_free;
113 uint16_t next_rec_id;
114 uint16_t reservation;
115 uint8_t last_addition[4];
116 uint8_t last_clear[4];
117 uint8_t overflow;
118 } IPMISdr;
120 typedef struct IPMISensor {
121 uint8_t status;
122 uint8_t reading;
123 uint16_t states_suppt;
124 uint16_t assert_suppt;
125 uint16_t deassert_suppt;
126 uint16_t states;
127 uint16_t assert_states;
128 uint16_t deassert_states;
129 uint16_t assert_enable;
130 uint16_t deassert_enable;
131 uint8_t sensor_type;
132 uint8_t evt_reading_type_code;
133 } IPMISensor;
134 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
135 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
136 !!(v))
137 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
138 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
139 ((!!(v)) << 6))
140 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
141 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
142 ((!!(v)) << 7))
143 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
144 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
145 (v & 0xc0))
146 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
148 #define MAX_SENSORS 20
149 #define IPMI_WATCHDOG_SENSOR 0
151 typedef struct IPMIBmcSim IPMIBmcSim;
153 #define MAX_NETFNS 64
154 typedef void (*IPMICmdHandler)(IPMIBmcSim *s,
155 uint8_t *cmd, unsigned int cmd_len,
156 uint8_t *rsp, unsigned int *rsp_len,
157 unsigned int max_rsp_len);
158 typedef struct IPMINetfn {
159 unsigned int cmd_nums;
160 const IPMICmdHandler *cmd_handlers;
161 } IPMINetfn;
163 typedef struct IPMIRcvBufEntry {
164 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
165 uint8_t len;
166 uint8_t buf[MAX_IPMI_MSG_SIZE];
167 } IPMIRcvBufEntry;
169 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
170 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
171 TYPE_IPMI_BMC_SIMULATOR)
172 struct IPMIBmcSim {
173 IPMIBmc parent;
175 QEMUTimer *timer;
177 uint8_t bmc_global_enables;
178 uint8_t msg_flags;
180 bool watchdog_initialized;
181 uint8_t watchdog_use;
182 uint8_t watchdog_action;
183 uint8_t watchdog_pretimeout; /* In seconds */
184 bool watchdog_expired;
185 uint16_t watchdog_timeout; /* in 100's of milliseconds */
187 bool watchdog_running;
188 bool watchdog_preaction_ran;
189 int64_t watchdog_expiry;
191 uint8_t device_id;
192 uint8_t ipmi_version;
193 uint8_t device_rev;
194 uint8_t fwrev1;
195 uint8_t fwrev2;
196 uint8_t mfg_id[3];
197 uint8_t product_id[2];
199 uint8_t restart_cause;
201 IPMISel sel;
202 IPMISdr sdr;
203 IPMISensor sensors[MAX_SENSORS];
205 /* Odd netfns are for responses, so we only need the even ones. */
206 const IPMINetfn *netfns[MAX_NETFNS / 2];
208 QemuMutex lock;
209 /* We allow one event in the buffer */
210 uint8_t evtbuf[16];
212 QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
215 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
216 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
217 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
218 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
219 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
220 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
221 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
222 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
223 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
225 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
226 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
227 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
228 #define IPMI_BMC_EVENT_LOG_BIT 3
229 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
230 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
231 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
232 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
233 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
234 (1 << IPMI_BMC_EVENT_LOG_BIT))
235 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
236 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
238 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
239 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
240 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
241 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
242 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
243 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
244 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
245 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
246 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
247 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
248 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
249 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
250 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
251 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
252 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
255 /* Add a byte to the response. */
256 #define IPMI_ADD_RSP_DATA(b) \
257 do { \
258 if (*rsp_len >= max_rsp_len) { \
259 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED; \
260 return; \
262 rsp[(*rsp_len)++] = (b); \
263 } while (0)
265 /* Verify that the received command is a certain length. */
266 #define IPMI_CHECK_CMD_LEN(l) \
267 if (cmd_len < l) { \
268 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID; \
269 return; \
272 /* Check that the reservation in the command is valid. */
273 #define IPMI_CHECK_RESERVATION(off, r) \
274 do { \
275 if ((cmd[off] | (cmd[off + 1] << 8)) != r) { \
276 rsp[2] = IPMI_CC_INVALID_RESERVATION; \
277 return; \
279 } while (0)
282 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
284 static void ipmi_gettime(struct ipmi_time *time)
286 int64_t stime;
288 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
289 time->tv_sec = stime / 1000000000LL;
290 time->tv_nsec = stime % 1000000000LL;
293 static int64_t ipmi_getmonotime(void)
295 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
298 static void ipmi_timeout(void *opaque)
300 IPMIBmcSim *ibs = opaque;
302 ipmi_sim_handle_timeout(ibs);
305 static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
307 unsigned int val;
308 struct ipmi_time now;
310 ipmi_gettime(&now);
311 val = now.tv_sec + ibs->sel.time_offset;
312 ts[0] = val & 0xff;
313 ts[1] = (val >> 8) & 0xff;
314 ts[2] = (val >> 16) & 0xff;
315 ts[3] = (val >> 24) & 0xff;
318 static void sdr_inc_reservation(IPMISdr *sdr)
320 sdr->reservation++;
321 if (sdr->reservation == 0) {
322 sdr->reservation = 1;
326 static int sdr_add_entry(IPMIBmcSim *ibs,
327 const struct ipmi_sdr_header *sdrh_entry,
328 unsigned int len, uint16_t *recid)
330 struct ipmi_sdr_header *sdrh =
331 (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
333 if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
334 return 1;
337 if (ipmi_sdr_length(sdrh_entry) != len) {
338 return 1;
341 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
342 ibs->sdr.overflow = 1;
343 return 1;
346 memcpy(sdrh, sdrh_entry, len);
347 sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff;
348 sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
349 sdrh->sdr_version = 0x51; /* Conform to IPMI 1.5 spec */
351 if (recid) {
352 *recid = ibs->sdr.next_rec_id;
354 ibs->sdr.next_rec_id++;
355 set_timestamp(ibs, ibs->sdr.last_addition);
356 ibs->sdr.next_free += len;
357 sdr_inc_reservation(&ibs->sdr);
358 return 0;
361 static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
362 unsigned int *retpos, uint16_t *nextrec)
364 unsigned int pos = *retpos;
366 while (pos < sdr->next_free) {
367 struct ipmi_sdr_header *sdrh =
368 (struct ipmi_sdr_header *) &sdr->sdr[pos];
369 uint16_t trec = ipmi_sdr_recid(sdrh);
370 unsigned int nextpos = pos + ipmi_sdr_length(sdrh);
372 if (trec == recid) {
373 if (nextrec) {
374 if (nextpos >= sdr->next_free) {
375 *nextrec = 0xffff;
376 } else {
377 *nextrec = (sdr->sdr[nextpos] |
378 (sdr->sdr[nextpos + 1] << 8));
381 *retpos = pos;
382 return 0;
384 pos = nextpos;
386 return 1;
389 static void sel_inc_reservation(IPMISel *sel)
391 sel->reservation++;
392 if (sel->reservation == 0) {
393 sel->reservation = 1;
397 /* Returns 1 if the SEL is full and can't hold the event. */
398 static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
400 event[0] = 0xff;
401 event[1] = 0xff;
402 set_timestamp(ibs, event + 3);
403 if (ibs->sel.next_free == MAX_SEL_SIZE) {
404 ibs->sel.overflow = 1;
405 return 1;
407 event[0] = ibs->sel.next_free & 0xff;
408 event[1] = (ibs->sel.next_free >> 8) & 0xff;
409 memcpy(ibs->sel.last_addition, event + 3, 4);
410 memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
411 ibs->sel.next_free++;
412 sel_inc_reservation(&ibs->sel);
413 return 0;
416 static int attn_set(IPMIBmcSim *ibs)
418 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
419 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
420 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
423 static int attn_irq_enabled(IPMIBmcSim *ibs)
425 return (IPMI_BMC_MSG_INTS_ON(ibs) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs))
426 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
427 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
430 static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
431 uint8_t evd1, uint8_t evd2, uint8_t evd3)
433 IPMIInterface *s = ibs->parent.intf;
434 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
435 uint8_t evt[16];
436 IPMISensor *sens = ibs->sensors + sens_num;
438 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
439 return;
441 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
442 return;
445 evt[2] = 0x2; /* System event record */
446 evt[7] = ibs->parent.slave_addr;
447 evt[8] = 0;
448 evt[9] = 0x04; /* Format version */
449 evt[10] = sens->sensor_type;
450 evt[11] = sens_num;
451 evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
452 evt[13] = evd1;
453 evt[14] = evd2;
454 evt[15] = evd3;
456 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
457 sel_add_event(ibs, evt);
460 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
461 return;
464 memcpy(ibs->evtbuf, evt, 16);
465 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
466 k->set_atn(s, 1, attn_irq_enabled(ibs));
469 static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
470 unsigned int bit, unsigned int val,
471 uint8_t evd1, uint8_t evd2, uint8_t evd3)
473 IPMISensor *sens;
474 uint16_t mask;
476 if (sensor >= MAX_SENSORS) {
477 return;
479 if (bit >= 16) {
480 return;
483 mask = (1 << bit);
484 sens = ibs->sensors + sensor;
485 if (val) {
486 sens->states |= mask & sens->states_suppt;
487 if (sens->assert_states & mask) {
488 return; /* Already asserted */
490 sens->assert_states |= mask & sens->assert_suppt;
491 if (sens->assert_enable & mask & sens->assert_states) {
492 /* Send an event on assert */
493 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
495 } else {
496 sens->states &= ~(mask & sens->states_suppt);
497 if (sens->deassert_states & mask) {
498 return; /* Already deasserted */
500 sens->deassert_states |= mask & sens->deassert_suppt;
501 if (sens->deassert_enable & mask & sens->deassert_states) {
502 /* Send an event on deassert */
503 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
508 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
510 unsigned int i, pos;
511 IPMISensor *sens;
513 for (i = 0; i < MAX_SENSORS; i++) {
514 memset(s->sensors + i, 0, sizeof(*sens));
517 pos = 0;
518 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
519 struct ipmi_sdr_compact *sdr =
520 (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
521 unsigned int len = sdr->header.rec_length;
523 if (len < 20) {
524 continue;
526 if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
527 continue; /* Not a sensor SDR we set from */
530 if (sdr->sensor_owner_number > MAX_SENSORS) {
531 continue;
533 sens = s->sensors + sdr->sensor_owner_number;
535 IPMI_SENSOR_SET_PRESENT(sens, 1);
536 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
537 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
538 sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
539 sens->deassert_suppt =
540 sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
541 sens->states_suppt =
542 sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
543 sens->sensor_type = sdr->sensor_type;
544 sens->evt_reading_type_code = sdr->reading_type & 0x7f;
546 /* Enable all the events that are supported. */
547 sens->assert_enable = sens->assert_suppt;
548 sens->deassert_enable = sens->deassert_suppt;
552 static int ipmi_register_netfn(IPMIBmcSim *s, unsigned int netfn,
553 const IPMINetfn *netfnd)
555 if ((netfn & 1) || (netfn > MAX_NETFNS) || (s->netfns[netfn / 2])) {
556 return -1;
558 s->netfns[netfn / 2] = netfnd;
559 return 0;
562 static void next_timeout(IPMIBmcSim *ibs)
564 int64_t next;
565 if (ibs->watchdog_running) {
566 next = ibs->watchdog_expiry;
567 } else {
568 /* Wait a minute */
569 next = ipmi_getmonotime() + 60 * 1000000000LL;
571 timer_mod_ns(ibs->timer, next);
574 static void ipmi_sim_handle_command(IPMIBmc *b,
575 uint8_t *cmd, unsigned int cmd_len,
576 unsigned int max_cmd_len,
577 uint8_t msg_id)
579 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
580 IPMIInterface *s = ibs->parent.intf;
581 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
582 unsigned int netfn;
583 uint8_t rsp[MAX_IPMI_MSG_SIZE];
584 unsigned int rsp_len_holder = 0;
585 unsigned int *rsp_len = &rsp_len_holder;
586 unsigned int max_rsp_len = sizeof(rsp);
588 /* Set up the response, set the low bit of NETFN. */
589 /* Note that max_rsp_len must be at least 3 */
590 if (max_rsp_len < 3) {
591 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
592 goto out;
595 IPMI_ADD_RSP_DATA(cmd[0] | 0x04);
596 IPMI_ADD_RSP_DATA(cmd[1]);
597 IPMI_ADD_RSP_DATA(0); /* Assume success */
599 /* If it's too short or it was truncated, return an error. */
600 if (cmd_len < 2) {
601 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
602 goto out;
604 if (cmd_len > max_cmd_len) {
605 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
606 goto out;
609 if ((cmd[0] & 0x03) != 0) {
610 /* Only have stuff on LUN 0 */
611 rsp[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
612 goto out;
615 netfn = cmd[0] >> 2;
617 /* Odd netfns are not valid, make sure the command is registered */
618 if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
619 (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
620 (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
621 rsp[2] = IPMI_CC_INVALID_CMD;
622 goto out;
625 ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
626 max_rsp_len);
628 out:
629 k->handle_rsp(s, msg_id, rsp, *rsp_len);
631 next_timeout(ibs);
634 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
636 IPMIInterface *s = ibs->parent.intf;
637 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
639 if (!ibs->watchdog_running) {
640 goto out;
643 if (!ibs->watchdog_preaction_ran) {
644 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
645 case IPMI_BMC_WATCHDOG_PRE_NMI:
646 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
647 k->do_hw_op(s, IPMI_SEND_NMI, 0);
648 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
649 0xc8, (2 << 4) | 0xf, 0xff);
650 break;
652 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
653 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
654 k->set_atn(s, 1, attn_irq_enabled(ibs));
655 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
656 0xc8, (3 << 4) | 0xf, 0xff);
657 break;
659 default:
660 goto do_full_expiry;
663 ibs->watchdog_preaction_ran = 1;
664 /* Issued the pretimeout, do the rest of the timeout now. */
665 ibs->watchdog_expiry = ipmi_getmonotime();
666 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
667 goto out;
670 do_full_expiry:
671 ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
672 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
673 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
674 case IPMI_BMC_WATCHDOG_ACTION_NONE:
675 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
676 0xc0, ibs->watchdog_use & 0xf, 0xff);
677 break;
679 case IPMI_BMC_WATCHDOG_ACTION_RESET:
680 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
681 0xc1, ibs->watchdog_use & 0xf, 0xff);
682 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
683 break;
685 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
686 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
687 0xc2, ibs->watchdog_use & 0xf, 0xff);
688 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
689 break;
691 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
692 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
693 0xc3, ibs->watchdog_use & 0xf, 0xff);
694 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
695 break;
698 out:
699 next_timeout(ibs);
702 static void chassis_capabilities(IPMIBmcSim *ibs,
703 uint8_t *cmd, unsigned int cmd_len,
704 uint8_t *rsp, unsigned int *rsp_len,
705 unsigned int max_rsp_len)
707 IPMI_ADD_RSP_DATA(0);
708 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
709 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
710 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
711 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
714 static void chassis_status(IPMIBmcSim *ibs,
715 uint8_t *cmd, unsigned int cmd_len,
716 uint8_t *rsp, unsigned int *rsp_len,
717 unsigned int max_rsp_len)
719 IPMI_ADD_RSP_DATA(0x61); /* Unknown power restore, power is on */
720 IPMI_ADD_RSP_DATA(0);
721 IPMI_ADD_RSP_DATA(0);
722 IPMI_ADD_RSP_DATA(0);
725 static void chassis_control(IPMIBmcSim *ibs,
726 uint8_t *cmd, unsigned int cmd_len,
727 uint8_t *rsp, unsigned int *rsp_len,
728 unsigned int max_rsp_len)
730 IPMIInterface *s = ibs->parent.intf;
731 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
733 IPMI_CHECK_CMD_LEN(3);
734 switch (cmd[2] & 0xf) {
735 case 0: /* power down */
736 rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
737 break;
738 case 1: /* power up */
739 rsp[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
740 break;
741 case 2: /* power cycle */
742 rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
743 break;
744 case 3: /* hard reset */
745 rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
746 break;
747 case 4: /* pulse diagnostic interrupt */
748 rsp[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
749 break;
750 case 5: /* soft shutdown via ACPI by overtemp emulation */
751 rsp[2] = k->do_hw_op(s,
752 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0);
753 break;
754 default:
755 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
756 return;
760 static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
761 uint8_t *cmd, unsigned int cmd_len,
762 uint8_t *rsp, unsigned int *rsp_len,
763 unsigned int max_rsp_len)
765 IPMI_ADD_RSP_DATA(ibs->restart_cause & 0xf); /* Restart Cause */
766 IPMI_ADD_RSP_DATA(0); /* Channel 0 */
769 static void get_device_id(IPMIBmcSim *ibs,
770 uint8_t *cmd, unsigned int cmd_len,
771 uint8_t *rsp, unsigned int *rsp_len,
772 unsigned int max_rsp_len)
774 IPMI_ADD_RSP_DATA(ibs->device_id);
775 IPMI_ADD_RSP_DATA(ibs->device_rev & 0xf);
776 IPMI_ADD_RSP_DATA(ibs->fwrev1 & 0x7f);
777 IPMI_ADD_RSP_DATA(ibs->fwrev2);
778 IPMI_ADD_RSP_DATA(ibs->ipmi_version);
779 IPMI_ADD_RSP_DATA(0x07); /* sensor, SDR, and SEL. */
780 IPMI_ADD_RSP_DATA(ibs->mfg_id[0]);
781 IPMI_ADD_RSP_DATA(ibs->mfg_id[1]);
782 IPMI_ADD_RSP_DATA(ibs->mfg_id[2]);
783 IPMI_ADD_RSP_DATA(ibs->product_id[0]);
784 IPMI_ADD_RSP_DATA(ibs->product_id[1]);
787 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
789 IPMIInterface *s = ibs->parent.intf;
790 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
791 bool irqs_on;
793 ibs->bmc_global_enables = val;
795 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
796 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
798 k->set_irq_enable(s, irqs_on);
801 static void cold_reset(IPMIBmcSim *ibs,
802 uint8_t *cmd, unsigned int cmd_len,
803 uint8_t *rsp, unsigned int *rsp_len,
804 unsigned int max_rsp_len)
806 IPMIInterface *s = ibs->parent.intf;
807 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
809 /* Disable all interrupts */
810 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
812 if (k->reset) {
813 k->reset(s, true);
817 static void warm_reset(IPMIBmcSim *ibs,
818 uint8_t *cmd, unsigned int cmd_len,
819 uint8_t *rsp, unsigned int *rsp_len,
820 unsigned int max_rsp_len)
822 IPMIInterface *s = ibs->parent.intf;
823 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
825 if (k->reset) {
826 k->reset(s, false);
830 static void set_bmc_global_enables(IPMIBmcSim *ibs,
831 uint8_t *cmd, unsigned int cmd_len,
832 uint8_t *rsp, unsigned int *rsp_len,
833 unsigned int max_rsp_len)
835 IPMI_CHECK_CMD_LEN(3);
836 set_global_enables(ibs, cmd[2]);
839 static void get_bmc_global_enables(IPMIBmcSim *ibs,
840 uint8_t *cmd, unsigned int cmd_len,
841 uint8_t *rsp, unsigned int *rsp_len,
842 unsigned int max_rsp_len)
844 IPMI_ADD_RSP_DATA(ibs->bmc_global_enables);
847 static void clr_msg_flags(IPMIBmcSim *ibs,
848 uint8_t *cmd, unsigned int cmd_len,
849 uint8_t *rsp, unsigned int *rsp_len,
850 unsigned int max_rsp_len)
852 IPMIInterface *s = ibs->parent.intf;
853 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
855 IPMI_CHECK_CMD_LEN(3);
856 ibs->msg_flags &= ~cmd[2];
857 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
860 static void get_msg_flags(IPMIBmcSim *ibs,
861 uint8_t *cmd, unsigned int cmd_len,
862 uint8_t *rsp, unsigned int *rsp_len,
863 unsigned int max_rsp_len)
865 IPMI_ADD_RSP_DATA(ibs->msg_flags);
868 static void read_evt_msg_buf(IPMIBmcSim *ibs,
869 uint8_t *cmd, unsigned int cmd_len,
870 uint8_t *rsp, unsigned int *rsp_len,
871 unsigned int max_rsp_len)
873 IPMIInterface *s = ibs->parent.intf;
874 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
875 unsigned int i;
877 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
878 rsp[2] = 0x80;
879 return;
881 for (i = 0; i < 16; i++) {
882 IPMI_ADD_RSP_DATA(ibs->evtbuf[i]);
884 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
885 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
888 static void get_msg(IPMIBmcSim *ibs,
889 uint8_t *cmd, unsigned int cmd_len,
890 uint8_t *rsp, unsigned int *rsp_len,
891 unsigned int max_rsp_len)
893 IPMIRcvBufEntry *msg;
895 qemu_mutex_lock(&ibs->lock);
896 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
897 rsp[2] = 0x80; /* Queue empty */
898 goto out;
900 rsp[3] = 0; /* Channel 0 */
901 *rsp_len += 1;
902 msg = QTAILQ_FIRST(&ibs->rcvbufs);
903 memcpy(rsp + 4, msg->buf, msg->len);
904 *rsp_len += msg->len;
905 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
906 g_free(msg);
908 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
909 IPMIInterface *s = ibs->parent.intf;
910 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
912 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
913 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
916 out:
917 qemu_mutex_unlock(&ibs->lock);
918 return;
921 static unsigned char
922 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
924 for (; size > 0; size--, data++) {
925 csum += *data;
928 return -csum;
931 static void send_msg(IPMIBmcSim *ibs,
932 uint8_t *cmd, unsigned int cmd_len,
933 uint8_t *rsp, unsigned int *rsp_len,
934 unsigned int max_rsp_len)
936 IPMIInterface *s = ibs->parent.intf;
937 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
938 IPMIRcvBufEntry *msg;
939 uint8_t *buf;
940 uint8_t netfn, rqLun, rsLun, rqSeq;
942 IPMI_CHECK_CMD_LEN(3);
944 if (cmd[2] != 0) {
945 /* We only handle channel 0 with no options */
946 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
947 return;
950 IPMI_CHECK_CMD_LEN(10);
951 if (cmd[3] != 0x40) {
952 /* We only emulate a MC at address 0x40. */
953 rsp[2] = 0x83; /* NAK on write */
954 return;
957 cmd += 3; /* Skip the header. */
958 cmd_len -= 3;
961 * At this point we "send" the message successfully. Any error will
962 * be returned in the response.
964 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
965 cmd[3] != 0x20) { /* Improper response address */
966 return; /* No response */
969 netfn = cmd[1] >> 2;
970 rqLun = cmd[4] & 0x3;
971 rsLun = cmd[1] & 0x3;
972 rqSeq = cmd[4] >> 2;
974 if (rqLun != 2) {
975 /* We only support LUN 2 coming back to us. */
976 return;
979 msg = g_malloc(sizeof(*msg));
980 msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
981 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
982 msg->buf[2] = cmd[0]; /* rsSA */
983 msg->buf[3] = (rqSeq << 2) | rsLun;
984 msg->buf[4] = cmd[5]; /* Cmd */
985 msg->buf[5] = 0; /* Completion Code */
986 msg->len = 6;
988 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
989 /* Not a command we handle. */
990 msg->buf[5] = IPMI_CC_INVALID_CMD;
991 goto end_msg;
994 buf = msg->buf + msg->len; /* After the CC */
995 buf[0] = 0;
996 buf[1] = 0;
997 buf[2] = 0;
998 buf[3] = 0;
999 buf[4] = 0x51;
1000 buf[5] = 0;
1001 buf[6] = 0;
1002 buf[7] = 0;
1003 buf[8] = 0;
1004 buf[9] = 0;
1005 buf[10] = 0;
1006 msg->len += 11;
1008 end_msg:
1009 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1010 msg->len++;
1011 qemu_mutex_lock(&ibs->lock);
1012 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1013 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1014 k->set_atn(s, 1, attn_irq_enabled(ibs));
1015 qemu_mutex_unlock(&ibs->lock);
1018 static void do_watchdog_reset(IPMIBmcSim *ibs)
1020 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1021 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1022 ibs->watchdog_running = 0;
1023 return;
1025 ibs->watchdog_preaction_ran = 0;
1028 /* Timeout is in tenths of a second, offset is in seconds */
1029 ibs->watchdog_expiry = ipmi_getmonotime();
1030 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1031 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1032 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1034 ibs->watchdog_running = 1;
1037 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1038 uint8_t *cmd, unsigned int cmd_len,
1039 uint8_t *rsp, unsigned int *rsp_len,
1040 unsigned int max_rsp_len)
1042 if (!ibs->watchdog_initialized) {
1043 rsp[2] = 0x80;
1044 return;
1046 do_watchdog_reset(ibs);
1049 static void set_watchdog_timer(IPMIBmcSim *ibs,
1050 uint8_t *cmd, unsigned int cmd_len,
1051 uint8_t *rsp, unsigned int *rsp_len,
1052 unsigned int max_rsp_len)
1054 IPMIInterface *s = ibs->parent.intf;
1055 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1056 unsigned int val;
1058 IPMI_CHECK_CMD_LEN(8);
1059 val = cmd[2] & 0x7; /* Validate use */
1060 if (val == 0 || val > 5) {
1061 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1062 return;
1064 val = cmd[3] & 0x7; /* Validate action */
1065 switch (val) {
1066 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1067 break;
1069 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1070 rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
1071 break;
1073 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1074 rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
1075 break;
1077 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1078 rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
1079 break;
1081 default:
1082 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1084 if (rsp[2]) {
1085 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1086 return;
1089 val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1090 switch (val) {
1091 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1092 case IPMI_BMC_WATCHDOG_PRE_NONE:
1093 break;
1095 case IPMI_BMC_WATCHDOG_PRE_NMI:
1096 if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1097 /* NMI not supported. */
1098 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1099 return;
1101 default:
1102 /* We don't support PRE_SMI */
1103 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1104 return;
1107 ibs->watchdog_initialized = 1;
1108 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1109 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1110 ibs->watchdog_pretimeout = cmd[4];
1111 ibs->watchdog_expired &= ~cmd[5];
1112 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1113 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1114 do_watchdog_reset(ibs);
1115 } else {
1116 ibs->watchdog_running = 0;
1120 static void get_watchdog_timer(IPMIBmcSim *ibs,
1121 uint8_t *cmd, unsigned int cmd_len,
1122 uint8_t *rsp, unsigned int *rsp_len,
1123 unsigned int max_rsp_len)
1125 IPMI_ADD_RSP_DATA(ibs->watchdog_use);
1126 IPMI_ADD_RSP_DATA(ibs->watchdog_action);
1127 IPMI_ADD_RSP_DATA(ibs->watchdog_pretimeout);
1128 IPMI_ADD_RSP_DATA(ibs->watchdog_expired);
1129 if (ibs->watchdog_running) {
1130 long timeout;
1131 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1132 / 100000000);
1133 IPMI_ADD_RSP_DATA(timeout & 0xff);
1134 IPMI_ADD_RSP_DATA((timeout >> 8) & 0xff);
1135 } else {
1136 IPMI_ADD_RSP_DATA(0);
1137 IPMI_ADD_RSP_DATA(0);
1141 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1142 uint8_t *cmd, unsigned int cmd_len,
1143 uint8_t *rsp, unsigned int *rsp_len,
1144 unsigned int max_rsp_len)
1146 unsigned int i;
1148 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 spec */
1149 IPMI_ADD_RSP_DATA(ibs->sdr.next_rec_id & 0xff);
1150 IPMI_ADD_RSP_DATA((ibs->sdr.next_rec_id >> 8) & 0xff);
1151 IPMI_ADD_RSP_DATA((MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1152 IPMI_ADD_RSP_DATA(((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1153 for (i = 0; i < 4; i++) {
1154 IPMI_ADD_RSP_DATA(ibs->sdr.last_addition[i]);
1156 for (i = 0; i < 4; i++) {
1157 IPMI_ADD_RSP_DATA(ibs->sdr.last_clear[i]);
1159 /* Only modal support, reserve supported */
1160 IPMI_ADD_RSP_DATA((ibs->sdr.overflow << 7) | 0x22);
1163 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1164 uint8_t *cmd, unsigned int cmd_len,
1165 uint8_t *rsp, unsigned int *rsp_len,
1166 unsigned int max_rsp_len)
1168 IPMI_ADD_RSP_DATA(ibs->sdr.reservation & 0xff);
1169 IPMI_ADD_RSP_DATA((ibs->sdr.reservation >> 8) & 0xff);
1172 static void get_sdr(IPMIBmcSim *ibs,
1173 uint8_t *cmd, unsigned int cmd_len,
1174 uint8_t *rsp, unsigned int *rsp_len,
1175 unsigned int max_rsp_len)
1177 unsigned int pos;
1178 uint16_t nextrec;
1179 struct ipmi_sdr_header *sdrh;
1181 IPMI_CHECK_CMD_LEN(8);
1182 if (cmd[6]) {
1183 IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
1185 pos = 0;
1186 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1187 &pos, &nextrec)) {
1188 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1189 return;
1192 sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1194 if (cmd[6] > ipmi_sdr_length(sdrh)) {
1195 rsp[2] = IPMI_CC_PARM_OUT_OF_RANGE;
1196 return;
1199 IPMI_ADD_RSP_DATA(nextrec & 0xff);
1200 IPMI_ADD_RSP_DATA((nextrec >> 8) & 0xff);
1202 if (cmd[7] == 0xff) {
1203 cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1206 if ((cmd[7] + *rsp_len) > max_rsp_len) {
1207 rsp[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
1208 return;
1210 memcpy(rsp + *rsp_len, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1211 *rsp_len += cmd[7];
1214 static void add_sdr(IPMIBmcSim *ibs,
1215 uint8_t *cmd, unsigned int cmd_len,
1216 uint8_t *rsp, unsigned int *rsp_len,
1217 unsigned int max_rsp_len)
1219 uint16_t recid;
1220 struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1222 if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1223 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1224 return;
1226 IPMI_ADD_RSP_DATA(recid & 0xff);
1227 IPMI_ADD_RSP_DATA((recid >> 8) & 0xff);
1230 static void clear_sdr_rep(IPMIBmcSim *ibs,
1231 uint8_t *cmd, unsigned int cmd_len,
1232 uint8_t *rsp, unsigned int *rsp_len,
1233 unsigned int max_rsp_len)
1235 IPMI_CHECK_CMD_LEN(8);
1236 IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
1237 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1238 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1239 return;
1241 if (cmd[7] == 0xaa) {
1242 ibs->sdr.next_free = 0;
1243 ibs->sdr.overflow = 0;
1244 set_timestamp(ibs, ibs->sdr.last_clear);
1245 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1246 sdr_inc_reservation(&ibs->sdr);
1247 } else if (cmd[7] == 0) {
1248 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1249 } else {
1250 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1251 return;
1255 static void get_sel_info(IPMIBmcSim *ibs,
1256 uint8_t *cmd, unsigned int cmd_len,
1257 uint8_t *rsp, unsigned int *rsp_len,
1258 unsigned int max_rsp_len)
1260 unsigned int i, val;
1262 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 */
1263 IPMI_ADD_RSP_DATA(ibs->sel.next_free & 0xff);
1264 IPMI_ADD_RSP_DATA((ibs->sel.next_free >> 8) & 0xff);
1265 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1266 IPMI_ADD_RSP_DATA(val & 0xff);
1267 IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
1268 for (i = 0; i < 4; i++) {
1269 IPMI_ADD_RSP_DATA(ibs->sel.last_addition[i]);
1271 for (i = 0; i < 4; i++) {
1272 IPMI_ADD_RSP_DATA(ibs->sel.last_clear[i]);
1274 /* Only support Reserve SEL */
1275 IPMI_ADD_RSP_DATA((ibs->sel.overflow << 7) | 0x02);
1278 static void reserve_sel(IPMIBmcSim *ibs,
1279 uint8_t *cmd, unsigned int cmd_len,
1280 uint8_t *rsp, unsigned int *rsp_len,
1281 unsigned int max_rsp_len)
1283 IPMI_ADD_RSP_DATA(ibs->sel.reservation & 0xff);
1284 IPMI_ADD_RSP_DATA((ibs->sel.reservation >> 8) & 0xff);
1287 static void get_sel_entry(IPMIBmcSim *ibs,
1288 uint8_t *cmd, unsigned int cmd_len,
1289 uint8_t *rsp, unsigned int *rsp_len,
1290 unsigned int max_rsp_len)
1292 unsigned int val;
1294 IPMI_CHECK_CMD_LEN(8);
1295 if (cmd[6]) {
1296 IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
1298 if (ibs->sel.next_free == 0) {
1299 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1300 return;
1302 if (cmd[6] > 15) {
1303 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1304 return;
1306 if (cmd[7] == 0xff) {
1307 cmd[7] = 16;
1308 } else if ((cmd[7] + cmd[6]) > 16) {
1309 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1310 return;
1311 } else {
1312 cmd[7] += cmd[6];
1315 val = cmd[4] | (cmd[5] << 8);
1316 if (val == 0xffff) {
1317 val = ibs->sel.next_free - 1;
1318 } else if (val >= ibs->sel.next_free) {
1319 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1320 return;
1322 if ((val + 1) == ibs->sel.next_free) {
1323 IPMI_ADD_RSP_DATA(0xff);
1324 IPMI_ADD_RSP_DATA(0xff);
1325 } else {
1326 IPMI_ADD_RSP_DATA((val + 1) & 0xff);
1327 IPMI_ADD_RSP_DATA(((val + 1) >> 8) & 0xff);
1329 for (; cmd[6] < cmd[7]; cmd[6]++) {
1330 IPMI_ADD_RSP_DATA(ibs->sel.sel[val][cmd[6]]);
1334 static void add_sel_entry(IPMIBmcSim *ibs,
1335 uint8_t *cmd, unsigned int cmd_len,
1336 uint8_t *rsp, unsigned int *rsp_len,
1337 unsigned int max_rsp_len)
1339 IPMI_CHECK_CMD_LEN(18);
1340 if (sel_add_event(ibs, cmd + 2)) {
1341 rsp[2] = IPMI_CC_OUT_OF_SPACE;
1342 return;
1344 /* sel_add_event fills in the record number. */
1345 IPMI_ADD_RSP_DATA(cmd[2]);
1346 IPMI_ADD_RSP_DATA(cmd[3]);
1349 static void clear_sel(IPMIBmcSim *ibs,
1350 uint8_t *cmd, unsigned int cmd_len,
1351 uint8_t *rsp, unsigned int *rsp_len,
1352 unsigned int max_rsp_len)
1354 IPMI_CHECK_CMD_LEN(8);
1355 IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
1356 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1357 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1358 return;
1360 if (cmd[7] == 0xaa) {
1361 ibs->sel.next_free = 0;
1362 ibs->sel.overflow = 0;
1363 set_timestamp(ibs, ibs->sdr.last_clear);
1364 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1365 sel_inc_reservation(&ibs->sel);
1366 } else if (cmd[7] == 0) {
1367 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1368 } else {
1369 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1370 return;
1374 static void get_sel_time(IPMIBmcSim *ibs,
1375 uint8_t *cmd, unsigned int cmd_len,
1376 uint8_t *rsp, unsigned int *rsp_len,
1377 unsigned int max_rsp_len)
1379 uint32_t val;
1380 struct ipmi_time now;
1382 ipmi_gettime(&now);
1383 val = now.tv_sec + ibs->sel.time_offset;
1384 IPMI_ADD_RSP_DATA(val & 0xff);
1385 IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
1386 IPMI_ADD_RSP_DATA((val >> 16) & 0xff);
1387 IPMI_ADD_RSP_DATA((val >> 24) & 0xff);
1390 static void set_sel_time(IPMIBmcSim *ibs,
1391 uint8_t *cmd, unsigned int cmd_len,
1392 uint8_t *rsp, unsigned int *rsp_len,
1393 unsigned int max_rsp_len)
1395 uint32_t val;
1396 struct ipmi_time now;
1398 IPMI_CHECK_CMD_LEN(6);
1399 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1400 ipmi_gettime(&now);
1401 ibs->sel.time_offset = now.tv_sec - ((long) val);
1404 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1405 uint8_t *cmd, unsigned int cmd_len,
1406 uint8_t *rsp, unsigned int *rsp_len,
1407 unsigned int max_rsp_len)
1409 IPMISensor *sens;
1411 IPMI_CHECK_CMD_LEN(4);
1412 if ((cmd[2] > MAX_SENSORS) ||
1413 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1414 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1415 return;
1417 sens = ibs->sensors + cmd[2];
1418 switch ((cmd[3] >> 4) & 0x3) {
1419 case 0: /* Do not change */
1420 break;
1421 case 1: /* Enable bits */
1422 if (cmd_len > 4) {
1423 sens->assert_enable |= cmd[4];
1425 if (cmd_len > 5) {
1426 sens->assert_enable |= cmd[5] << 8;
1428 if (cmd_len > 6) {
1429 sens->deassert_enable |= cmd[6];
1431 if (cmd_len > 7) {
1432 sens->deassert_enable |= cmd[7] << 8;
1434 break;
1435 case 2: /* Disable bits */
1436 if (cmd_len > 4) {
1437 sens->assert_enable &= ~cmd[4];
1439 if (cmd_len > 5) {
1440 sens->assert_enable &= ~(cmd[5] << 8);
1442 if (cmd_len > 6) {
1443 sens->deassert_enable &= ~cmd[6];
1445 if (cmd_len > 7) {
1446 sens->deassert_enable &= ~(cmd[7] << 8);
1448 break;
1449 case 3:
1450 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1451 return;
1453 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1456 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1457 uint8_t *cmd, unsigned int cmd_len,
1458 uint8_t *rsp, unsigned int *rsp_len,
1459 unsigned int max_rsp_len)
1461 IPMISensor *sens;
1463 IPMI_CHECK_CMD_LEN(3);
1464 if ((cmd[2] > MAX_SENSORS) ||
1465 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1466 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1467 return;
1469 sens = ibs->sensors + cmd[2];
1470 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1471 IPMI_ADD_RSP_DATA(sens->assert_enable & 0xff);
1472 IPMI_ADD_RSP_DATA((sens->assert_enable >> 8) & 0xff);
1473 IPMI_ADD_RSP_DATA(sens->deassert_enable & 0xff);
1474 IPMI_ADD_RSP_DATA((sens->deassert_enable >> 8) & 0xff);
1477 static void rearm_sensor_evts(IPMIBmcSim *ibs,
1478 uint8_t *cmd, unsigned int cmd_len,
1479 uint8_t *rsp, unsigned int *rsp_len,
1480 unsigned int max_rsp_len)
1482 IPMISensor *sens;
1484 IPMI_CHECK_CMD_LEN(4);
1485 if ((cmd[2] > MAX_SENSORS) ||
1486 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1487 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1488 return;
1490 sens = ibs->sensors + cmd[2];
1492 if ((cmd[3] & 0x80) == 0) {
1493 /* Just clear everything */
1494 sens->states = 0;
1495 return;
1499 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1500 uint8_t *cmd, unsigned int cmd_len,
1501 uint8_t *rsp, unsigned int *rsp_len,
1502 unsigned int max_rsp_len)
1504 IPMISensor *sens;
1506 IPMI_CHECK_CMD_LEN(3);
1507 if ((cmd[2] > MAX_SENSORS) ||
1508 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1509 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1510 return;
1512 sens = ibs->sensors + cmd[2];
1513 IPMI_ADD_RSP_DATA(sens->reading);
1514 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1515 IPMI_ADD_RSP_DATA(sens->assert_states & 0xff);
1516 IPMI_ADD_RSP_DATA((sens->assert_states >> 8) & 0xff);
1517 IPMI_ADD_RSP_DATA(sens->deassert_states & 0xff);
1518 IPMI_ADD_RSP_DATA((sens->deassert_states >> 8) & 0xff);
1521 static void get_sensor_reading(IPMIBmcSim *ibs,
1522 uint8_t *cmd, unsigned int cmd_len,
1523 uint8_t *rsp, unsigned int *rsp_len,
1524 unsigned int max_rsp_len)
1526 IPMISensor *sens;
1528 IPMI_CHECK_CMD_LEN(3);
1529 if ((cmd[2] > MAX_SENSORS) ||
1530 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1531 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1532 return;
1534 sens = ibs->sensors + cmd[2];
1535 IPMI_ADD_RSP_DATA(sens->reading);
1536 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1537 IPMI_ADD_RSP_DATA(sens->states & 0xff);
1538 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1539 IPMI_ADD_RSP_DATA((sens->states >> 8) & 0xff);
1543 static void set_sensor_type(IPMIBmcSim *ibs,
1544 uint8_t *cmd, unsigned int cmd_len,
1545 uint8_t *rsp, unsigned int *rsp_len,
1546 unsigned int max_rsp_len)
1548 IPMISensor *sens;
1551 IPMI_CHECK_CMD_LEN(5);
1552 if ((cmd[2] > MAX_SENSORS) ||
1553 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1554 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1555 return;
1557 sens = ibs->sensors + cmd[2];
1558 sens->sensor_type = cmd[3];
1559 sens->evt_reading_type_code = cmd[4] & 0x7f;
1562 static void get_sensor_type(IPMIBmcSim *ibs,
1563 uint8_t *cmd, unsigned int cmd_len,
1564 uint8_t *rsp, unsigned int *rsp_len,
1565 unsigned int max_rsp_len)
1567 IPMISensor *sens;
1570 IPMI_CHECK_CMD_LEN(3);
1571 if ((cmd[2] > MAX_SENSORS) ||
1572 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1573 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1574 return;
1576 sens = ibs->sensors + cmd[2];
1577 IPMI_ADD_RSP_DATA(sens->sensor_type);
1578 IPMI_ADD_RSP_DATA(sens->evt_reading_type_code);
1582 static const IPMICmdHandler chassis_cmds[] = {
1583 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = chassis_capabilities,
1584 [IPMI_CMD_GET_CHASSIS_STATUS] = chassis_status,
1585 [IPMI_CMD_CHASSIS_CONTROL] = chassis_control,
1586 [IPMI_CMD_GET_SYS_RESTART_CAUSE] = chassis_get_sys_restart_cause
1588 static const IPMINetfn chassis_netfn = {
1589 .cmd_nums = ARRAY_SIZE(chassis_cmds),
1590 .cmd_handlers = chassis_cmds
1593 static const IPMICmdHandler sensor_event_cmds[] = {
1594 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = set_sensor_evt_enable,
1595 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = get_sensor_evt_enable,
1596 [IPMI_CMD_REARM_SENSOR_EVTS] = rearm_sensor_evts,
1597 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = get_sensor_evt_status,
1598 [IPMI_CMD_GET_SENSOR_READING] = get_sensor_reading,
1599 [IPMI_CMD_SET_SENSOR_TYPE] = set_sensor_type,
1600 [IPMI_CMD_GET_SENSOR_TYPE] = get_sensor_type,
1602 static const IPMINetfn sensor_event_netfn = {
1603 .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
1604 .cmd_handlers = sensor_event_cmds
1607 static const IPMICmdHandler app_cmds[] = {
1608 [IPMI_CMD_GET_DEVICE_ID] = get_device_id,
1609 [IPMI_CMD_COLD_RESET] = cold_reset,
1610 [IPMI_CMD_WARM_RESET] = warm_reset,
1611 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = set_bmc_global_enables,
1612 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = get_bmc_global_enables,
1613 [IPMI_CMD_CLR_MSG_FLAGS] = clr_msg_flags,
1614 [IPMI_CMD_GET_MSG_FLAGS] = get_msg_flags,
1615 [IPMI_CMD_GET_MSG] = get_msg,
1616 [IPMI_CMD_SEND_MSG] = send_msg,
1617 [IPMI_CMD_READ_EVT_MSG_BUF] = read_evt_msg_buf,
1618 [IPMI_CMD_RESET_WATCHDOG_TIMER] = reset_watchdog_timer,
1619 [IPMI_CMD_SET_WATCHDOG_TIMER] = set_watchdog_timer,
1620 [IPMI_CMD_GET_WATCHDOG_TIMER] = get_watchdog_timer,
1622 static const IPMINetfn app_netfn = {
1623 .cmd_nums = ARRAY_SIZE(app_cmds),
1624 .cmd_handlers = app_cmds
1627 static const IPMICmdHandler storage_cmds[] = {
1628 [IPMI_CMD_GET_SDR_REP_INFO] = get_sdr_rep_info,
1629 [IPMI_CMD_RESERVE_SDR_REP] = reserve_sdr_rep,
1630 [IPMI_CMD_GET_SDR] = get_sdr,
1631 [IPMI_CMD_ADD_SDR] = add_sdr,
1632 [IPMI_CMD_CLEAR_SDR_REP] = clear_sdr_rep,
1633 [IPMI_CMD_GET_SEL_INFO] = get_sel_info,
1634 [IPMI_CMD_RESERVE_SEL] = reserve_sel,
1635 [IPMI_CMD_GET_SEL_ENTRY] = get_sel_entry,
1636 [IPMI_CMD_ADD_SEL_ENTRY] = add_sel_entry,
1637 [IPMI_CMD_CLEAR_SEL] = clear_sel,
1638 [IPMI_CMD_GET_SEL_TIME] = get_sel_time,
1639 [IPMI_CMD_SET_SEL_TIME] = set_sel_time,
1642 static const IPMINetfn storage_netfn = {
1643 .cmd_nums = ARRAY_SIZE(storage_cmds),
1644 .cmd_handlers = storage_cmds
1647 static void register_cmds(IPMIBmcSim *s)
1649 ipmi_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
1650 ipmi_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
1651 ipmi_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
1652 ipmi_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
1655 static const uint8_t init_sdrs[] = {
1656 /* Watchdog device */
1657 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1658 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1661 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1662 /* End */
1663 0xff, 0xff, 0x00, 0x00, 0x00
1666 static const VMStateDescription vmstate_ipmi_sim = {
1667 .name = TYPE_IPMI_BMC_SIMULATOR,
1668 .version_id = 1,
1669 .minimum_version_id = 1,
1670 .fields = (VMStateField[]) {
1671 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
1672 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
1673 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
1674 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
1675 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
1676 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
1677 VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
1678 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
1679 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
1680 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
1681 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
1682 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
1683 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
1684 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
1685 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
1686 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
1687 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
1688 IPMIBmcSim),
1689 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
1690 VMSTATE_END_OF_LIST()
1694 static void ipmi_sim_init(Object *obj)
1696 IPMIBmc *b = IPMI_BMC(obj);
1697 unsigned int i;
1698 unsigned int recid;
1699 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
1701 qemu_mutex_init(&ibs->lock);
1702 QTAILQ_INIT(&ibs->rcvbufs);
1704 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
1705 ibs->device_id = 0x20;
1706 ibs->ipmi_version = 0x02; /* IPMI 2.0 */
1707 ibs->restart_cause = 0;
1708 for (i = 0; i < 4; i++) {
1709 ibs->sel.last_addition[i] = 0xff;
1710 ibs->sel.last_clear[i] = 0xff;
1711 ibs->sdr.last_addition[i] = 0xff;
1712 ibs->sdr.last_clear[i] = 0xff;
1715 for (i = 0;;) {
1716 struct ipmi_sdr_header *sdrh;
1717 int len;
1718 if ((i + IPMI_SDR_HEADER_SIZE) > sizeof(init_sdrs)) {
1719 error_report("Problem with recid 0x%4.4x", i);
1720 return;
1722 sdrh = (struct ipmi_sdr_header *) &init_sdrs[i];
1723 len = ipmi_sdr_length(sdrh);
1724 recid = ipmi_sdr_recid(sdrh);
1725 if (recid == 0xffff) {
1726 break;
1728 if ((i + len) > sizeof(init_sdrs)) {
1729 error_report("Problem with recid 0x%4.4x", i);
1730 return;
1732 sdr_add_entry(ibs, sdrh, len, NULL);
1733 i += len;
1736 ipmi_init_sensors_from_sdrs(ibs);
1737 register_cmds(ibs);
1739 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
1741 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
1744 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
1746 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
1748 bk->handle_command = ipmi_sim_handle_command;
1751 static const TypeInfo ipmi_sim_type = {
1752 .name = TYPE_IPMI_BMC_SIMULATOR,
1753 .parent = TYPE_IPMI_BMC,
1754 .instance_size = sizeof(IPMIBmcSim),
1755 .instance_init = ipmi_sim_init,
1756 .class_init = ipmi_sim_class_init,
1759 static void ipmi_sim_register_types(void)
1761 type_register_static(&ipmi_sim_type);
1764 type_init(ipmi_sim_register_types)