ipmi: introduce a struct ipmi_sdr_compact
[qemu/cris-port.git] / hw / ipmi / ipmi_bmc_sim.c
blob84fbcd26383dfb592427ec2de0bc3a1ccf193293
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
36 #define IPMI_NETFN_SENSOR_EVENT 0x04
38 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
39 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
40 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
41 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
42 #define IPMI_CMD_GET_SENSOR_READING 0x2d
44 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
46 #define IPMI_CMD_GET_DEVICE_ID 0x01
47 #define IPMI_CMD_COLD_RESET 0x02
48 #define IPMI_CMD_WARM_RESET 0x03
49 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
50 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
51 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
52 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
53 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
54 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
55 #define IPMI_CMD_GET_MSG_FLAGS 0x31
56 #define IPMI_CMD_GET_MSG 0x33
57 #define IPMI_CMD_SEND_MSG 0x34
58 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
60 #define IPMI_NETFN_STORAGE 0x0a
62 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
63 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
64 #define IPMI_CMD_RESERVE_SDR_REP 0x22
65 #define IPMI_CMD_GET_SDR 0x23
66 #define IPMI_CMD_ADD_SDR 0x24
67 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
68 #define IPMI_CMD_DELETE_SDR 0x26
69 #define IPMI_CMD_CLEAR_SDR_REP 0x27
70 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
71 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
72 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
73 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
74 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
75 #define IPMI_CMD_GET_SEL_INFO 0x40
76 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
77 #define IPMI_CMD_RESERVE_SEL 0x42
78 #define IPMI_CMD_GET_SEL_ENTRY 0x43
79 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
80 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
81 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
82 #define IPMI_CMD_CLEAR_SEL 0x47
83 #define IPMI_CMD_GET_SEL_TIME 0x48
84 #define IPMI_CMD_SET_SEL_TIME 0x49
87 /* Same as a timespec struct. */
88 struct ipmi_time {
89 long tv_sec;
90 long tv_nsec;
93 #define MAX_SEL_SIZE 128
95 typedef struct IPMISel {
96 uint8_t sel[MAX_SEL_SIZE][16];
97 unsigned int next_free;
98 long time_offset;
99 uint16_t reservation;
100 uint8_t last_addition[4];
101 uint8_t last_clear[4];
102 uint8_t overflow;
103 } IPMISel;
105 #define MAX_SDR_SIZE 16384
107 typedef struct IPMISdr {
108 uint8_t sdr[MAX_SDR_SIZE];
109 unsigned int next_free;
110 uint16_t next_rec_id;
111 uint16_t reservation;
112 uint8_t last_addition[4];
113 uint8_t last_clear[4];
114 uint8_t overflow;
115 } IPMISdr;
117 typedef struct IPMISensor {
118 uint8_t status;
119 uint8_t reading;
120 uint16_t states_suppt;
121 uint16_t assert_suppt;
122 uint16_t deassert_suppt;
123 uint16_t states;
124 uint16_t assert_states;
125 uint16_t deassert_states;
126 uint16_t assert_enable;
127 uint16_t deassert_enable;
128 uint8_t sensor_type;
129 uint8_t evt_reading_type_code;
130 } IPMISensor;
131 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
132 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
133 !!(v))
134 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
135 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
136 ((!!(v)) << 6))
137 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
138 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
139 ((!!(v)) << 7))
140 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
141 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
142 (v & 0xc0))
143 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
145 #define MAX_SENSORS 20
146 #define IPMI_WATCHDOG_SENSOR 0
148 typedef struct IPMIBmcSim IPMIBmcSim;
150 #define MAX_NETFNS 64
151 typedef void (*IPMICmdHandler)(IPMIBmcSim *s,
152 uint8_t *cmd, unsigned int cmd_len,
153 uint8_t *rsp, unsigned int *rsp_len,
154 unsigned int max_rsp_len);
155 typedef struct IPMINetfn {
156 unsigned int cmd_nums;
157 const IPMICmdHandler *cmd_handlers;
158 } IPMINetfn;
160 typedef struct IPMIRcvBufEntry {
161 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
162 uint8_t len;
163 uint8_t buf[MAX_IPMI_MSG_SIZE];
164 } IPMIRcvBufEntry;
166 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
167 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
168 TYPE_IPMI_BMC_SIMULATOR)
169 struct IPMIBmcSim {
170 IPMIBmc parent;
172 QEMUTimer *timer;
174 uint8_t bmc_global_enables;
175 uint8_t msg_flags;
177 bool watchdog_initialized;
178 uint8_t watchdog_use;
179 uint8_t watchdog_action;
180 uint8_t watchdog_pretimeout; /* In seconds */
181 bool watchdog_expired;
182 uint16_t watchdog_timeout; /* in 100's of milliseconds */
184 bool watchdog_running;
185 bool watchdog_preaction_ran;
186 int64_t watchdog_expiry;
188 uint8_t device_id;
189 uint8_t ipmi_version;
190 uint8_t device_rev;
191 uint8_t fwrev1;
192 uint8_t fwrev2;
193 uint8_t mfg_id[3];
194 uint8_t product_id[2];
196 IPMISel sel;
197 IPMISdr sdr;
198 IPMISensor sensors[MAX_SENSORS];
200 /* Odd netfns are for responses, so we only need the even ones. */
201 const IPMINetfn *netfns[MAX_NETFNS / 2];
203 QemuMutex lock;
204 /* We allow one event in the buffer */
205 uint8_t evtbuf[16];
207 QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
210 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
211 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
212 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
213 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
214 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
215 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
216 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
217 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
218 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
220 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
221 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
222 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
223 #define IPMI_BMC_EVENT_LOG_BIT 3
224 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
225 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
226 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
227 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
228 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
229 (1 << IPMI_BMC_EVENT_LOG_BIT))
230 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
231 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
233 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
234 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
235 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
236 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
237 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
238 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
239 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
240 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
241 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
242 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
243 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
244 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
245 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
246 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
247 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
250 /* Add a byte to the response. */
251 #define IPMI_ADD_RSP_DATA(b) \
252 do { \
253 if (*rsp_len >= max_rsp_len) { \
254 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED; \
255 return; \
257 rsp[(*rsp_len)++] = (b); \
258 } while (0)
260 /* Verify that the received command is a certain length. */
261 #define IPMI_CHECK_CMD_LEN(l) \
262 if (cmd_len < l) { \
263 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID; \
264 return; \
267 /* Check that the reservation in the command is valid. */
268 #define IPMI_CHECK_RESERVATION(off, r) \
269 do { \
270 if ((cmd[off] | (cmd[off + 1] << 8)) != r) { \
271 rsp[2] = IPMI_CC_INVALID_RESERVATION; \
272 return; \
274 } while (0)
277 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
279 static void ipmi_gettime(struct ipmi_time *time)
281 int64_t stime;
283 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
284 time->tv_sec = stime / 1000000000LL;
285 time->tv_nsec = stime % 1000000000LL;
288 static int64_t ipmi_getmonotime(void)
290 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
293 static void ipmi_timeout(void *opaque)
295 IPMIBmcSim *ibs = opaque;
297 ipmi_sim_handle_timeout(ibs);
300 static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
302 unsigned int val;
303 struct ipmi_time now;
305 ipmi_gettime(&now);
306 val = now.tv_sec + ibs->sel.time_offset;
307 ts[0] = val & 0xff;
308 ts[1] = (val >> 8) & 0xff;
309 ts[2] = (val >> 16) & 0xff;
310 ts[3] = (val >> 24) & 0xff;
313 static void sdr_inc_reservation(IPMISdr *sdr)
315 sdr->reservation++;
316 if (sdr->reservation == 0) {
317 sdr->reservation = 1;
321 static int sdr_add_entry(IPMIBmcSim *ibs,
322 const struct ipmi_sdr_header *sdrh_entry,
323 unsigned int len, uint16_t *recid)
325 struct ipmi_sdr_header *sdrh =
326 (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
328 if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
329 return 1;
332 if (ipmi_sdr_length(sdrh_entry) != len) {
333 return 1;
336 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
337 ibs->sdr.overflow = 1;
338 return 1;
341 memcpy(sdrh, sdrh_entry, len);
342 sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff;
343 sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
344 sdrh->sdr_version = 0x51; /* Conform to IPMI 1.5 spec */
346 if (recid) {
347 *recid = ibs->sdr.next_rec_id;
349 ibs->sdr.next_rec_id++;
350 set_timestamp(ibs, ibs->sdr.last_addition);
351 ibs->sdr.next_free += len;
352 sdr_inc_reservation(&ibs->sdr);
353 return 0;
356 static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
357 unsigned int *retpos, uint16_t *nextrec)
359 unsigned int pos = *retpos;
361 while (pos < sdr->next_free) {
362 struct ipmi_sdr_header *sdrh =
363 (struct ipmi_sdr_header *) &sdr->sdr[pos];
364 uint16_t trec = ipmi_sdr_recid(sdrh);
365 unsigned int nextpos = pos + ipmi_sdr_length(sdrh);
367 if (trec == recid) {
368 if (nextrec) {
369 if (nextpos >= sdr->next_free) {
370 *nextrec = 0xffff;
371 } else {
372 *nextrec = (sdr->sdr[nextpos] |
373 (sdr->sdr[nextpos + 1] << 8));
376 *retpos = pos;
377 return 0;
379 pos = nextpos;
381 return 1;
384 static void sel_inc_reservation(IPMISel *sel)
386 sel->reservation++;
387 if (sel->reservation == 0) {
388 sel->reservation = 1;
392 /* Returns 1 if the SEL is full and can't hold the event. */
393 static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
395 event[0] = 0xff;
396 event[1] = 0xff;
397 set_timestamp(ibs, event + 3);
398 if (ibs->sel.next_free == MAX_SEL_SIZE) {
399 ibs->sel.overflow = 1;
400 return 1;
402 event[0] = ibs->sel.next_free & 0xff;
403 event[1] = (ibs->sel.next_free >> 8) & 0xff;
404 memcpy(ibs->sel.last_addition, event + 3, 4);
405 memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
406 ibs->sel.next_free++;
407 sel_inc_reservation(&ibs->sel);
408 return 0;
411 static int attn_set(IPMIBmcSim *ibs)
413 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
414 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
415 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
418 static int attn_irq_enabled(IPMIBmcSim *ibs)
420 return (IPMI_BMC_MSG_INTS_ON(ibs) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs))
421 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
422 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
425 static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
426 uint8_t evd1, uint8_t evd2, uint8_t evd3)
428 IPMIInterface *s = ibs->parent.intf;
429 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
430 uint8_t evt[16];
431 IPMISensor *sens = ibs->sensors + sens_num;
433 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
434 return;
436 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
437 return;
440 evt[2] = 0x2; /* System event record */
441 evt[7] = ibs->parent.slave_addr;
442 evt[8] = 0;
443 evt[9] = 0x04; /* Format version */
444 evt[10] = sens->sensor_type;
445 evt[11] = sens_num;
446 evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
447 evt[13] = evd1;
448 evt[14] = evd2;
449 evt[15] = evd3;
451 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
452 sel_add_event(ibs, evt);
455 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
456 return;
459 memcpy(ibs->evtbuf, evt, 16);
460 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
461 k->set_atn(s, 1, attn_irq_enabled(ibs));
464 static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
465 unsigned int bit, unsigned int val,
466 uint8_t evd1, uint8_t evd2, uint8_t evd3)
468 IPMISensor *sens;
469 uint16_t mask;
471 if (sensor >= MAX_SENSORS) {
472 return;
474 if (bit >= 16) {
475 return;
478 mask = (1 << bit);
479 sens = ibs->sensors + sensor;
480 if (val) {
481 sens->states |= mask & sens->states_suppt;
482 if (sens->assert_states & mask) {
483 return; /* Already asserted */
485 sens->assert_states |= mask & sens->assert_suppt;
486 if (sens->assert_enable & mask & sens->assert_states) {
487 /* Send an event on assert */
488 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
490 } else {
491 sens->states &= ~(mask & sens->states_suppt);
492 if (sens->deassert_states & mask) {
493 return; /* Already deasserted */
495 sens->deassert_states |= mask & sens->deassert_suppt;
496 if (sens->deassert_enable & mask & sens->deassert_states) {
497 /* Send an event on deassert */
498 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
503 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
505 unsigned int i, pos;
506 IPMISensor *sens;
508 for (i = 0; i < MAX_SENSORS; i++) {
509 memset(s->sensors + i, 0, sizeof(*sens));
512 pos = 0;
513 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
514 struct ipmi_sdr_compact *sdr =
515 (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
516 unsigned int len = sdr->header.rec_length;
518 if (len < 20) {
519 continue;
521 if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
522 continue; /* Not a sensor SDR we set from */
525 if (sdr->sensor_owner_number > MAX_SENSORS) {
526 continue;
528 sens = s->sensors + sdr->sensor_owner_number;
530 IPMI_SENSOR_SET_PRESENT(sens, 1);
531 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
532 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
533 sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
534 sens->deassert_suppt =
535 sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
536 sens->states_suppt =
537 sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
538 sens->sensor_type = sdr->sensor_type;
539 sens->evt_reading_type_code = sdr->reading_type & 0x7f;
541 /* Enable all the events that are supported. */
542 sens->assert_enable = sens->assert_suppt;
543 sens->deassert_enable = sens->deassert_suppt;
547 static int ipmi_register_netfn(IPMIBmcSim *s, unsigned int netfn,
548 const IPMINetfn *netfnd)
550 if ((netfn & 1) || (netfn > MAX_NETFNS) || (s->netfns[netfn / 2])) {
551 return -1;
553 s->netfns[netfn / 2] = netfnd;
554 return 0;
557 static void next_timeout(IPMIBmcSim *ibs)
559 int64_t next;
560 if (ibs->watchdog_running) {
561 next = ibs->watchdog_expiry;
562 } else {
563 /* Wait a minute */
564 next = ipmi_getmonotime() + 60 * 1000000000LL;
566 timer_mod_ns(ibs->timer, next);
569 static void ipmi_sim_handle_command(IPMIBmc *b,
570 uint8_t *cmd, unsigned int cmd_len,
571 unsigned int max_cmd_len,
572 uint8_t msg_id)
574 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
575 IPMIInterface *s = ibs->parent.intf;
576 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
577 unsigned int netfn;
578 uint8_t rsp[MAX_IPMI_MSG_SIZE];
579 unsigned int rsp_len_holder = 0;
580 unsigned int *rsp_len = &rsp_len_holder;
581 unsigned int max_rsp_len = sizeof(rsp);
583 /* Set up the response, set the low bit of NETFN. */
584 /* Note that max_rsp_len must be at least 3 */
585 if (max_rsp_len < 3) {
586 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
587 goto out;
590 IPMI_ADD_RSP_DATA(cmd[0] | 0x04);
591 IPMI_ADD_RSP_DATA(cmd[1]);
592 IPMI_ADD_RSP_DATA(0); /* Assume success */
594 /* If it's too short or it was truncated, return an error. */
595 if (cmd_len < 2) {
596 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
597 goto out;
599 if (cmd_len > max_cmd_len) {
600 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
601 goto out;
604 if ((cmd[0] & 0x03) != 0) {
605 /* Only have stuff on LUN 0 */
606 rsp[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
607 goto out;
610 netfn = cmd[0] >> 2;
612 /* Odd netfns are not valid, make sure the command is registered */
613 if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
614 (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
615 (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
616 rsp[2] = IPMI_CC_INVALID_CMD;
617 goto out;
620 ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
621 max_rsp_len);
623 out:
624 k->handle_rsp(s, msg_id, rsp, *rsp_len);
626 next_timeout(ibs);
629 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
631 IPMIInterface *s = ibs->parent.intf;
632 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
634 if (!ibs->watchdog_running) {
635 goto out;
638 if (!ibs->watchdog_preaction_ran) {
639 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
640 case IPMI_BMC_WATCHDOG_PRE_NMI:
641 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
642 k->do_hw_op(s, IPMI_SEND_NMI, 0);
643 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
644 0xc8, (2 << 4) | 0xf, 0xff);
645 break;
647 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
648 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
649 k->set_atn(s, 1, attn_irq_enabled(ibs));
650 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
651 0xc8, (3 << 4) | 0xf, 0xff);
652 break;
654 default:
655 goto do_full_expiry;
658 ibs->watchdog_preaction_ran = 1;
659 /* Issued the pretimeout, do the rest of the timeout now. */
660 ibs->watchdog_expiry = ipmi_getmonotime();
661 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
662 goto out;
665 do_full_expiry:
666 ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
667 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
668 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
669 case IPMI_BMC_WATCHDOG_ACTION_NONE:
670 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
671 0xc0, ibs->watchdog_use & 0xf, 0xff);
672 break;
674 case IPMI_BMC_WATCHDOG_ACTION_RESET:
675 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
676 0xc1, ibs->watchdog_use & 0xf, 0xff);
677 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
678 break;
680 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
681 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
682 0xc2, ibs->watchdog_use & 0xf, 0xff);
683 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
684 break;
686 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
687 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
688 0xc3, ibs->watchdog_use & 0xf, 0xff);
689 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
690 break;
693 out:
694 next_timeout(ibs);
697 static void chassis_capabilities(IPMIBmcSim *ibs,
698 uint8_t *cmd, unsigned int cmd_len,
699 uint8_t *rsp, unsigned int *rsp_len,
700 unsigned int max_rsp_len)
702 IPMI_ADD_RSP_DATA(0);
703 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
704 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
705 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
706 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
709 static void chassis_status(IPMIBmcSim *ibs,
710 uint8_t *cmd, unsigned int cmd_len,
711 uint8_t *rsp, unsigned int *rsp_len,
712 unsigned int max_rsp_len)
714 IPMI_ADD_RSP_DATA(0x61); /* Unknown power restore, power is on */
715 IPMI_ADD_RSP_DATA(0);
716 IPMI_ADD_RSP_DATA(0);
717 IPMI_ADD_RSP_DATA(0);
720 static void chassis_control(IPMIBmcSim *ibs,
721 uint8_t *cmd, unsigned int cmd_len,
722 uint8_t *rsp, unsigned int *rsp_len,
723 unsigned int max_rsp_len)
725 IPMIInterface *s = ibs->parent.intf;
726 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
728 IPMI_CHECK_CMD_LEN(3);
729 switch (cmd[2] & 0xf) {
730 case 0: /* power down */
731 rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
732 break;
733 case 1: /* power up */
734 rsp[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
735 break;
736 case 2: /* power cycle */
737 rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
738 break;
739 case 3: /* hard reset */
740 rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
741 break;
742 case 4: /* pulse diagnostic interrupt */
743 rsp[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
744 break;
745 case 5: /* soft shutdown via ACPI by overtemp emulation */
746 rsp[2] = k->do_hw_op(s,
747 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0);
748 break;
749 default:
750 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
751 return;
755 static void get_device_id(IPMIBmcSim *ibs,
756 uint8_t *cmd, unsigned int cmd_len,
757 uint8_t *rsp, unsigned int *rsp_len,
758 unsigned int max_rsp_len)
760 IPMI_ADD_RSP_DATA(ibs->device_id);
761 IPMI_ADD_RSP_DATA(ibs->device_rev & 0xf);
762 IPMI_ADD_RSP_DATA(ibs->fwrev1 & 0x7f);
763 IPMI_ADD_RSP_DATA(ibs->fwrev2);
764 IPMI_ADD_RSP_DATA(ibs->ipmi_version);
765 IPMI_ADD_RSP_DATA(0x07); /* sensor, SDR, and SEL. */
766 IPMI_ADD_RSP_DATA(ibs->mfg_id[0]);
767 IPMI_ADD_RSP_DATA(ibs->mfg_id[1]);
768 IPMI_ADD_RSP_DATA(ibs->mfg_id[2]);
769 IPMI_ADD_RSP_DATA(ibs->product_id[0]);
770 IPMI_ADD_RSP_DATA(ibs->product_id[1]);
773 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
775 IPMIInterface *s = ibs->parent.intf;
776 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
777 bool irqs_on;
779 ibs->bmc_global_enables = val;
781 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
782 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
784 k->set_irq_enable(s, irqs_on);
787 static void cold_reset(IPMIBmcSim *ibs,
788 uint8_t *cmd, unsigned int cmd_len,
789 uint8_t *rsp, unsigned int *rsp_len,
790 unsigned int max_rsp_len)
792 IPMIInterface *s = ibs->parent.intf;
793 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
795 /* Disable all interrupts */
796 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
798 if (k->reset) {
799 k->reset(s, true);
803 static void warm_reset(IPMIBmcSim *ibs,
804 uint8_t *cmd, unsigned int cmd_len,
805 uint8_t *rsp, unsigned int *rsp_len,
806 unsigned int max_rsp_len)
808 IPMIInterface *s = ibs->parent.intf;
809 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
811 if (k->reset) {
812 k->reset(s, false);
816 static void set_bmc_global_enables(IPMIBmcSim *ibs,
817 uint8_t *cmd, unsigned int cmd_len,
818 uint8_t *rsp, unsigned int *rsp_len,
819 unsigned int max_rsp_len)
821 IPMI_CHECK_CMD_LEN(3);
822 set_global_enables(ibs, cmd[2]);
825 static void get_bmc_global_enables(IPMIBmcSim *ibs,
826 uint8_t *cmd, unsigned int cmd_len,
827 uint8_t *rsp, unsigned int *rsp_len,
828 unsigned int max_rsp_len)
830 IPMI_ADD_RSP_DATA(ibs->bmc_global_enables);
833 static void clr_msg_flags(IPMIBmcSim *ibs,
834 uint8_t *cmd, unsigned int cmd_len,
835 uint8_t *rsp, unsigned int *rsp_len,
836 unsigned int max_rsp_len)
838 IPMIInterface *s = ibs->parent.intf;
839 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
841 IPMI_CHECK_CMD_LEN(3);
842 ibs->msg_flags &= ~cmd[2];
843 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
846 static void get_msg_flags(IPMIBmcSim *ibs,
847 uint8_t *cmd, unsigned int cmd_len,
848 uint8_t *rsp, unsigned int *rsp_len,
849 unsigned int max_rsp_len)
851 IPMI_ADD_RSP_DATA(ibs->msg_flags);
854 static void read_evt_msg_buf(IPMIBmcSim *ibs,
855 uint8_t *cmd, unsigned int cmd_len,
856 uint8_t *rsp, unsigned int *rsp_len,
857 unsigned int max_rsp_len)
859 IPMIInterface *s = ibs->parent.intf;
860 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
861 unsigned int i;
863 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
864 rsp[2] = 0x80;
865 return;
867 for (i = 0; i < 16; i++) {
868 IPMI_ADD_RSP_DATA(ibs->evtbuf[i]);
870 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
871 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
874 static void get_msg(IPMIBmcSim *ibs,
875 uint8_t *cmd, unsigned int cmd_len,
876 uint8_t *rsp, unsigned int *rsp_len,
877 unsigned int max_rsp_len)
879 IPMIRcvBufEntry *msg;
881 qemu_mutex_lock(&ibs->lock);
882 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
883 rsp[2] = 0x80; /* Queue empty */
884 goto out;
886 rsp[3] = 0; /* Channel 0 */
887 *rsp_len += 1;
888 msg = QTAILQ_FIRST(&ibs->rcvbufs);
889 memcpy(rsp + 4, msg->buf, msg->len);
890 *rsp_len += msg->len;
891 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
892 g_free(msg);
894 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
895 IPMIInterface *s = ibs->parent.intf;
896 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
898 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
899 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
902 out:
903 qemu_mutex_unlock(&ibs->lock);
904 return;
907 static unsigned char
908 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
910 for (; size > 0; size--, data++) {
911 csum += *data;
914 return -csum;
917 static void send_msg(IPMIBmcSim *ibs,
918 uint8_t *cmd, unsigned int cmd_len,
919 uint8_t *rsp, unsigned int *rsp_len,
920 unsigned int max_rsp_len)
922 IPMIInterface *s = ibs->parent.intf;
923 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
924 IPMIRcvBufEntry *msg;
925 uint8_t *buf;
926 uint8_t netfn, rqLun, rsLun, rqSeq;
928 IPMI_CHECK_CMD_LEN(3);
930 if (cmd[2] != 0) {
931 /* We only handle channel 0 with no options */
932 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
933 return;
936 IPMI_CHECK_CMD_LEN(10);
937 if (cmd[3] != 0x40) {
938 /* We only emulate a MC at address 0x40. */
939 rsp[2] = 0x83; /* NAK on write */
940 return;
943 cmd += 3; /* Skip the header. */
944 cmd_len -= 3;
947 * At this point we "send" the message successfully. Any error will
948 * be returned in the response.
950 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
951 cmd[3] != 0x20) { /* Improper response address */
952 return; /* No response */
955 netfn = cmd[1] >> 2;
956 rqLun = cmd[4] & 0x3;
957 rsLun = cmd[1] & 0x3;
958 rqSeq = cmd[4] >> 2;
960 if (rqLun != 2) {
961 /* We only support LUN 2 coming back to us. */
962 return;
965 msg = g_malloc(sizeof(*msg));
966 msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
967 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
968 msg->buf[2] = cmd[0]; /* rsSA */
969 msg->buf[3] = (rqSeq << 2) | rsLun;
970 msg->buf[4] = cmd[5]; /* Cmd */
971 msg->buf[5] = 0; /* Completion Code */
972 msg->len = 6;
974 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
975 /* Not a command we handle. */
976 msg->buf[5] = IPMI_CC_INVALID_CMD;
977 goto end_msg;
980 buf = msg->buf + msg->len; /* After the CC */
981 buf[0] = 0;
982 buf[1] = 0;
983 buf[2] = 0;
984 buf[3] = 0;
985 buf[4] = 0x51;
986 buf[5] = 0;
987 buf[6] = 0;
988 buf[7] = 0;
989 buf[8] = 0;
990 buf[9] = 0;
991 buf[10] = 0;
992 msg->len += 11;
994 end_msg:
995 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
996 msg->len++;
997 qemu_mutex_lock(&ibs->lock);
998 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
999 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1000 k->set_atn(s, 1, attn_irq_enabled(ibs));
1001 qemu_mutex_unlock(&ibs->lock);
1004 static void do_watchdog_reset(IPMIBmcSim *ibs)
1006 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1007 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1008 ibs->watchdog_running = 0;
1009 return;
1011 ibs->watchdog_preaction_ran = 0;
1014 /* Timeout is in tenths of a second, offset is in seconds */
1015 ibs->watchdog_expiry = ipmi_getmonotime();
1016 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1017 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1018 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1020 ibs->watchdog_running = 1;
1023 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1024 uint8_t *cmd, unsigned int cmd_len,
1025 uint8_t *rsp, unsigned int *rsp_len,
1026 unsigned int max_rsp_len)
1028 if (!ibs->watchdog_initialized) {
1029 rsp[2] = 0x80;
1030 return;
1032 do_watchdog_reset(ibs);
1035 static void set_watchdog_timer(IPMIBmcSim *ibs,
1036 uint8_t *cmd, unsigned int cmd_len,
1037 uint8_t *rsp, unsigned int *rsp_len,
1038 unsigned int max_rsp_len)
1040 IPMIInterface *s = ibs->parent.intf;
1041 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1042 unsigned int val;
1044 IPMI_CHECK_CMD_LEN(8);
1045 val = cmd[2] & 0x7; /* Validate use */
1046 if (val == 0 || val > 5) {
1047 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1048 return;
1050 val = cmd[3] & 0x7; /* Validate action */
1051 switch (val) {
1052 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1053 break;
1055 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1056 rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
1057 break;
1059 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1060 rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
1061 break;
1063 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1064 rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
1065 break;
1067 default:
1068 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1070 if (rsp[2]) {
1071 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1072 return;
1075 val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1076 switch (val) {
1077 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1078 case IPMI_BMC_WATCHDOG_PRE_NONE:
1079 break;
1081 case IPMI_BMC_WATCHDOG_PRE_NMI:
1082 if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1083 /* NMI not supported. */
1084 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1085 return;
1087 default:
1088 /* We don't support PRE_SMI */
1089 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1090 return;
1093 ibs->watchdog_initialized = 1;
1094 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1095 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1096 ibs->watchdog_pretimeout = cmd[4];
1097 ibs->watchdog_expired &= ~cmd[5];
1098 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1099 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1100 do_watchdog_reset(ibs);
1101 } else {
1102 ibs->watchdog_running = 0;
1106 static void get_watchdog_timer(IPMIBmcSim *ibs,
1107 uint8_t *cmd, unsigned int cmd_len,
1108 uint8_t *rsp, unsigned int *rsp_len,
1109 unsigned int max_rsp_len)
1111 IPMI_ADD_RSP_DATA(ibs->watchdog_use);
1112 IPMI_ADD_RSP_DATA(ibs->watchdog_action);
1113 IPMI_ADD_RSP_DATA(ibs->watchdog_pretimeout);
1114 IPMI_ADD_RSP_DATA(ibs->watchdog_expired);
1115 if (ibs->watchdog_running) {
1116 long timeout;
1117 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1118 / 100000000);
1119 IPMI_ADD_RSP_DATA(timeout & 0xff);
1120 IPMI_ADD_RSP_DATA((timeout >> 8) & 0xff);
1121 } else {
1122 IPMI_ADD_RSP_DATA(0);
1123 IPMI_ADD_RSP_DATA(0);
1127 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1128 uint8_t *cmd, unsigned int cmd_len,
1129 uint8_t *rsp, unsigned int *rsp_len,
1130 unsigned int max_rsp_len)
1132 unsigned int i;
1134 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 spec */
1135 IPMI_ADD_RSP_DATA(ibs->sdr.next_rec_id & 0xff);
1136 IPMI_ADD_RSP_DATA((ibs->sdr.next_rec_id >> 8) & 0xff);
1137 IPMI_ADD_RSP_DATA((MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1138 IPMI_ADD_RSP_DATA(((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1139 for (i = 0; i < 4; i++) {
1140 IPMI_ADD_RSP_DATA(ibs->sdr.last_addition[i]);
1142 for (i = 0; i < 4; i++) {
1143 IPMI_ADD_RSP_DATA(ibs->sdr.last_clear[i]);
1145 /* Only modal support, reserve supported */
1146 IPMI_ADD_RSP_DATA((ibs->sdr.overflow << 7) | 0x22);
1149 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1150 uint8_t *cmd, unsigned int cmd_len,
1151 uint8_t *rsp, unsigned int *rsp_len,
1152 unsigned int max_rsp_len)
1154 IPMI_ADD_RSP_DATA(ibs->sdr.reservation & 0xff);
1155 IPMI_ADD_RSP_DATA((ibs->sdr.reservation >> 8) & 0xff);
1158 static void get_sdr(IPMIBmcSim *ibs,
1159 uint8_t *cmd, unsigned int cmd_len,
1160 uint8_t *rsp, unsigned int *rsp_len,
1161 unsigned int max_rsp_len)
1163 unsigned int pos;
1164 uint16_t nextrec;
1165 struct ipmi_sdr_header *sdrh;
1167 IPMI_CHECK_CMD_LEN(8);
1168 if (cmd[6]) {
1169 IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
1171 pos = 0;
1172 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1173 &pos, &nextrec)) {
1174 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1175 return;
1178 sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1180 if (cmd[6] > ipmi_sdr_length(sdrh)) {
1181 rsp[2] = IPMI_CC_PARM_OUT_OF_RANGE;
1182 return;
1185 IPMI_ADD_RSP_DATA(nextrec & 0xff);
1186 IPMI_ADD_RSP_DATA((nextrec >> 8) & 0xff);
1188 if (cmd[7] == 0xff) {
1189 cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1192 if ((cmd[7] + *rsp_len) > max_rsp_len) {
1193 rsp[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
1194 return;
1196 memcpy(rsp + *rsp_len, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1197 *rsp_len += cmd[7];
1200 static void add_sdr(IPMIBmcSim *ibs,
1201 uint8_t *cmd, unsigned int cmd_len,
1202 uint8_t *rsp, unsigned int *rsp_len,
1203 unsigned int max_rsp_len)
1205 uint16_t recid;
1206 struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1208 if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1209 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1210 return;
1212 IPMI_ADD_RSP_DATA(recid & 0xff);
1213 IPMI_ADD_RSP_DATA((recid >> 8) & 0xff);
1216 static void clear_sdr_rep(IPMIBmcSim *ibs,
1217 uint8_t *cmd, unsigned int cmd_len,
1218 uint8_t *rsp, unsigned int *rsp_len,
1219 unsigned int max_rsp_len)
1221 IPMI_CHECK_CMD_LEN(8);
1222 IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
1223 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1224 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1225 return;
1227 if (cmd[7] == 0xaa) {
1228 ibs->sdr.next_free = 0;
1229 ibs->sdr.overflow = 0;
1230 set_timestamp(ibs, ibs->sdr.last_clear);
1231 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1232 sdr_inc_reservation(&ibs->sdr);
1233 } else if (cmd[7] == 0) {
1234 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1235 } else {
1236 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1237 return;
1241 static void get_sel_info(IPMIBmcSim *ibs,
1242 uint8_t *cmd, unsigned int cmd_len,
1243 uint8_t *rsp, unsigned int *rsp_len,
1244 unsigned int max_rsp_len)
1246 unsigned int i, val;
1248 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 */
1249 IPMI_ADD_RSP_DATA(ibs->sel.next_free & 0xff);
1250 IPMI_ADD_RSP_DATA((ibs->sel.next_free >> 8) & 0xff);
1251 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1252 IPMI_ADD_RSP_DATA(val & 0xff);
1253 IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
1254 for (i = 0; i < 4; i++) {
1255 IPMI_ADD_RSP_DATA(ibs->sel.last_addition[i]);
1257 for (i = 0; i < 4; i++) {
1258 IPMI_ADD_RSP_DATA(ibs->sel.last_clear[i]);
1260 /* Only support Reserve SEL */
1261 IPMI_ADD_RSP_DATA((ibs->sel.overflow << 7) | 0x02);
1264 static void reserve_sel(IPMIBmcSim *ibs,
1265 uint8_t *cmd, unsigned int cmd_len,
1266 uint8_t *rsp, unsigned int *rsp_len,
1267 unsigned int max_rsp_len)
1269 IPMI_ADD_RSP_DATA(ibs->sel.reservation & 0xff);
1270 IPMI_ADD_RSP_DATA((ibs->sel.reservation >> 8) & 0xff);
1273 static void get_sel_entry(IPMIBmcSim *ibs,
1274 uint8_t *cmd, unsigned int cmd_len,
1275 uint8_t *rsp, unsigned int *rsp_len,
1276 unsigned int max_rsp_len)
1278 unsigned int val;
1280 IPMI_CHECK_CMD_LEN(8);
1281 if (cmd[6]) {
1282 IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
1284 if (ibs->sel.next_free == 0) {
1285 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1286 return;
1288 if (cmd[6] > 15) {
1289 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1290 return;
1292 if (cmd[7] == 0xff) {
1293 cmd[7] = 16;
1294 } else if ((cmd[7] + cmd[6]) > 16) {
1295 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1296 return;
1297 } else {
1298 cmd[7] += cmd[6];
1301 val = cmd[4] | (cmd[5] << 8);
1302 if (val == 0xffff) {
1303 val = ibs->sel.next_free - 1;
1304 } else if (val >= ibs->sel.next_free) {
1305 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1306 return;
1308 if ((val + 1) == ibs->sel.next_free) {
1309 IPMI_ADD_RSP_DATA(0xff);
1310 IPMI_ADD_RSP_DATA(0xff);
1311 } else {
1312 IPMI_ADD_RSP_DATA((val + 1) & 0xff);
1313 IPMI_ADD_RSP_DATA(((val + 1) >> 8) & 0xff);
1315 for (; cmd[6] < cmd[7]; cmd[6]++) {
1316 IPMI_ADD_RSP_DATA(ibs->sel.sel[val][cmd[6]]);
1320 static void add_sel_entry(IPMIBmcSim *ibs,
1321 uint8_t *cmd, unsigned int cmd_len,
1322 uint8_t *rsp, unsigned int *rsp_len,
1323 unsigned int max_rsp_len)
1325 IPMI_CHECK_CMD_LEN(18);
1326 if (sel_add_event(ibs, cmd + 2)) {
1327 rsp[2] = IPMI_CC_OUT_OF_SPACE;
1328 return;
1330 /* sel_add_event fills in the record number. */
1331 IPMI_ADD_RSP_DATA(cmd[2]);
1332 IPMI_ADD_RSP_DATA(cmd[3]);
1335 static void clear_sel(IPMIBmcSim *ibs,
1336 uint8_t *cmd, unsigned int cmd_len,
1337 uint8_t *rsp, unsigned int *rsp_len,
1338 unsigned int max_rsp_len)
1340 IPMI_CHECK_CMD_LEN(8);
1341 IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
1342 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1343 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1344 return;
1346 if (cmd[7] == 0xaa) {
1347 ibs->sel.next_free = 0;
1348 ibs->sel.overflow = 0;
1349 set_timestamp(ibs, ibs->sdr.last_clear);
1350 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1351 sel_inc_reservation(&ibs->sel);
1352 } else if (cmd[7] == 0) {
1353 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1354 } else {
1355 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1356 return;
1360 static void get_sel_time(IPMIBmcSim *ibs,
1361 uint8_t *cmd, unsigned int cmd_len,
1362 uint8_t *rsp, unsigned int *rsp_len,
1363 unsigned int max_rsp_len)
1365 uint32_t val;
1366 struct ipmi_time now;
1368 ipmi_gettime(&now);
1369 val = now.tv_sec + ibs->sel.time_offset;
1370 IPMI_ADD_RSP_DATA(val & 0xff);
1371 IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
1372 IPMI_ADD_RSP_DATA((val >> 16) & 0xff);
1373 IPMI_ADD_RSP_DATA((val >> 24) & 0xff);
1376 static void set_sel_time(IPMIBmcSim *ibs,
1377 uint8_t *cmd, unsigned int cmd_len,
1378 uint8_t *rsp, unsigned int *rsp_len,
1379 unsigned int max_rsp_len)
1381 uint32_t val;
1382 struct ipmi_time now;
1384 IPMI_CHECK_CMD_LEN(6);
1385 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1386 ipmi_gettime(&now);
1387 ibs->sel.time_offset = now.tv_sec - ((long) val);
1390 static void set_sensor_evt_enable(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 IPMISensor *sens;
1397 IPMI_CHECK_CMD_LEN(4);
1398 if ((cmd[2] > MAX_SENSORS) ||
1399 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1400 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1401 return;
1403 sens = ibs->sensors + cmd[2];
1404 switch ((cmd[3] >> 4) & 0x3) {
1405 case 0: /* Do not change */
1406 break;
1407 case 1: /* Enable bits */
1408 if (cmd_len > 4) {
1409 sens->assert_enable |= cmd[4];
1411 if (cmd_len > 5) {
1412 sens->assert_enable |= cmd[5] << 8;
1414 if (cmd_len > 6) {
1415 sens->deassert_enable |= cmd[6];
1417 if (cmd_len > 7) {
1418 sens->deassert_enable |= cmd[7] << 8;
1420 break;
1421 case 2: /* Disable 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 3:
1436 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1437 return;
1439 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1442 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1443 uint8_t *cmd, unsigned int cmd_len,
1444 uint8_t *rsp, unsigned int *rsp_len,
1445 unsigned int max_rsp_len)
1447 IPMISensor *sens;
1449 IPMI_CHECK_CMD_LEN(3);
1450 if ((cmd[2] > MAX_SENSORS) ||
1451 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1452 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1453 return;
1455 sens = ibs->sensors + cmd[2];
1456 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1457 IPMI_ADD_RSP_DATA(sens->assert_enable & 0xff);
1458 IPMI_ADD_RSP_DATA((sens->assert_enable >> 8) & 0xff);
1459 IPMI_ADD_RSP_DATA(sens->deassert_enable & 0xff);
1460 IPMI_ADD_RSP_DATA((sens->deassert_enable >> 8) & 0xff);
1463 static void rearm_sensor_evts(IPMIBmcSim *ibs,
1464 uint8_t *cmd, unsigned int cmd_len,
1465 uint8_t *rsp, unsigned int *rsp_len,
1466 unsigned int max_rsp_len)
1468 IPMISensor *sens;
1470 IPMI_CHECK_CMD_LEN(4);
1471 if ((cmd[2] > MAX_SENSORS) ||
1472 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1473 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1474 return;
1476 sens = ibs->sensors + cmd[2];
1478 if ((cmd[3] & 0x80) == 0) {
1479 /* Just clear everything */
1480 sens->states = 0;
1481 return;
1485 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1486 uint8_t *cmd, unsigned int cmd_len,
1487 uint8_t *rsp, unsigned int *rsp_len,
1488 unsigned int max_rsp_len)
1490 IPMISensor *sens;
1492 IPMI_CHECK_CMD_LEN(3);
1493 if ((cmd[2] > MAX_SENSORS) ||
1494 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1495 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1496 return;
1498 sens = ibs->sensors + cmd[2];
1499 IPMI_ADD_RSP_DATA(sens->reading);
1500 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1501 IPMI_ADD_RSP_DATA(sens->assert_states & 0xff);
1502 IPMI_ADD_RSP_DATA((sens->assert_states >> 8) & 0xff);
1503 IPMI_ADD_RSP_DATA(sens->deassert_states & 0xff);
1504 IPMI_ADD_RSP_DATA((sens->deassert_states >> 8) & 0xff);
1507 static void get_sensor_reading(IPMIBmcSim *ibs,
1508 uint8_t *cmd, unsigned int cmd_len,
1509 uint8_t *rsp, unsigned int *rsp_len,
1510 unsigned int max_rsp_len)
1512 IPMISensor *sens;
1514 IPMI_CHECK_CMD_LEN(3);
1515 if ((cmd[2] > MAX_SENSORS) ||
1516 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1517 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1518 return;
1520 sens = ibs->sensors + cmd[2];
1521 IPMI_ADD_RSP_DATA(sens->reading);
1522 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1523 IPMI_ADD_RSP_DATA(sens->states & 0xff);
1524 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1525 IPMI_ADD_RSP_DATA((sens->states >> 8) & 0xff);
1529 static const IPMICmdHandler chassis_cmds[] = {
1530 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = chassis_capabilities,
1531 [IPMI_CMD_GET_CHASSIS_STATUS] = chassis_status,
1532 [IPMI_CMD_CHASSIS_CONTROL] = chassis_control
1534 static const IPMINetfn chassis_netfn = {
1535 .cmd_nums = ARRAY_SIZE(chassis_cmds),
1536 .cmd_handlers = chassis_cmds
1539 static const IPMICmdHandler sensor_event_cmds[] = {
1540 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = set_sensor_evt_enable,
1541 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = get_sensor_evt_enable,
1542 [IPMI_CMD_REARM_SENSOR_EVTS] = rearm_sensor_evts,
1543 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = get_sensor_evt_status,
1544 [IPMI_CMD_GET_SENSOR_READING] = get_sensor_reading
1546 static const IPMINetfn sensor_event_netfn = {
1547 .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
1548 .cmd_handlers = sensor_event_cmds
1551 static const IPMICmdHandler app_cmds[] = {
1552 [IPMI_CMD_GET_DEVICE_ID] = get_device_id,
1553 [IPMI_CMD_COLD_RESET] = cold_reset,
1554 [IPMI_CMD_WARM_RESET] = warm_reset,
1555 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = set_bmc_global_enables,
1556 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = get_bmc_global_enables,
1557 [IPMI_CMD_CLR_MSG_FLAGS] = clr_msg_flags,
1558 [IPMI_CMD_GET_MSG_FLAGS] = get_msg_flags,
1559 [IPMI_CMD_GET_MSG] = get_msg,
1560 [IPMI_CMD_SEND_MSG] = send_msg,
1561 [IPMI_CMD_READ_EVT_MSG_BUF] = read_evt_msg_buf,
1562 [IPMI_CMD_RESET_WATCHDOG_TIMER] = reset_watchdog_timer,
1563 [IPMI_CMD_SET_WATCHDOG_TIMER] = set_watchdog_timer,
1564 [IPMI_CMD_GET_WATCHDOG_TIMER] = get_watchdog_timer,
1566 static const IPMINetfn app_netfn = {
1567 .cmd_nums = ARRAY_SIZE(app_cmds),
1568 .cmd_handlers = app_cmds
1571 static const IPMICmdHandler storage_cmds[] = {
1572 [IPMI_CMD_GET_SDR_REP_INFO] = get_sdr_rep_info,
1573 [IPMI_CMD_RESERVE_SDR_REP] = reserve_sdr_rep,
1574 [IPMI_CMD_GET_SDR] = get_sdr,
1575 [IPMI_CMD_ADD_SDR] = add_sdr,
1576 [IPMI_CMD_CLEAR_SDR_REP] = clear_sdr_rep,
1577 [IPMI_CMD_GET_SEL_INFO] = get_sel_info,
1578 [IPMI_CMD_RESERVE_SEL] = reserve_sel,
1579 [IPMI_CMD_GET_SEL_ENTRY] = get_sel_entry,
1580 [IPMI_CMD_ADD_SEL_ENTRY] = add_sel_entry,
1581 [IPMI_CMD_CLEAR_SEL] = clear_sel,
1582 [IPMI_CMD_GET_SEL_TIME] = get_sel_time,
1583 [IPMI_CMD_SET_SEL_TIME] = set_sel_time,
1586 static const IPMINetfn storage_netfn = {
1587 .cmd_nums = ARRAY_SIZE(storage_cmds),
1588 .cmd_handlers = storage_cmds
1591 static void register_cmds(IPMIBmcSim *s)
1593 ipmi_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
1594 ipmi_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
1595 ipmi_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
1596 ipmi_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
1599 static const uint8_t init_sdrs[] = {
1600 /* Watchdog device */
1601 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1602 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1605 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1606 /* End */
1607 0xff, 0xff, 0x00, 0x00, 0x00
1610 static const VMStateDescription vmstate_ipmi_sim = {
1611 .name = TYPE_IPMI_BMC_SIMULATOR,
1612 .version_id = 1,
1613 .minimum_version_id = 1,
1614 .fields = (VMStateField[]) {
1615 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
1616 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
1617 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
1618 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
1619 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
1620 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
1621 VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
1622 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
1623 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
1624 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
1625 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
1626 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
1627 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
1628 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
1629 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
1630 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
1631 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
1632 IPMIBmcSim),
1633 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
1634 VMSTATE_END_OF_LIST()
1638 static void ipmi_sim_init(Object *obj)
1640 IPMIBmc *b = IPMI_BMC(obj);
1641 unsigned int i;
1642 unsigned int recid;
1643 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
1645 qemu_mutex_init(&ibs->lock);
1646 QTAILQ_INIT(&ibs->rcvbufs);
1648 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
1649 ibs->device_id = 0x20;
1650 ibs->ipmi_version = 0x02; /* IPMI 2.0 */
1651 for (i = 0; i < 4; i++) {
1652 ibs->sel.last_addition[i] = 0xff;
1653 ibs->sel.last_clear[i] = 0xff;
1654 ibs->sdr.last_addition[i] = 0xff;
1655 ibs->sdr.last_clear[i] = 0xff;
1658 for (i = 0;;) {
1659 struct ipmi_sdr_header *sdrh;
1660 int len;
1661 if ((i + IPMI_SDR_HEADER_SIZE) > sizeof(init_sdrs)) {
1662 error_report("Problem with recid 0x%4.4x", i);
1663 return;
1665 sdrh = (struct ipmi_sdr_header *) &init_sdrs[i];
1666 len = ipmi_sdr_length(sdrh);
1667 recid = ipmi_sdr_recid(sdrh);
1668 if (recid == 0xffff) {
1669 break;
1671 if ((i + len) > sizeof(init_sdrs)) {
1672 error_report("Problem with recid 0x%4.4x", i);
1673 return;
1675 sdr_add_entry(ibs, sdrh, len, NULL);
1676 i += len;
1679 ipmi_init_sensors_from_sdrs(ibs);
1680 register_cmds(ibs);
1682 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
1684 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
1687 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
1689 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
1691 bk->handle_command = ipmi_sim_handle_command;
1694 static const TypeInfo ipmi_sim_type = {
1695 .name = TYPE_IPMI_BMC_SIMULATOR,
1696 .parent = TYPE_IPMI_BMC,
1697 .instance_size = sizeof(IPMIBmcSim),
1698 .instance_init = ipmi_sim_init,
1699 .class_init = ipmi_sim_class_init,
1702 static void ipmi_sim_register_types(void)
1704 type_register_static(&ipmi_sim_type);
1707 type_init(ipmi_sim_register_types)