ipmi: replace goto by a return statement
[qemu/cris-port.git] / hw / ipmi / ipmi_bmc_sim.c
blob1f06dfcb8a90f742ffa70f40404c91300cce6ad2
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
31 #define IPMI_NETFN_CHASSIS_MAXCMD 0x03
33 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
34 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
35 #define IPMI_CMD_CHASSIS_CONTROL 0x02
37 #define IPMI_NETFN_SENSOR_EVENT 0x04
38 #define IPMI_NETFN_SENSOR_EVENT_MAXCMD 0x2e
40 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
41 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
42 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
43 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
44 #define IPMI_CMD_GET_SENSOR_READING 0x2d
46 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
47 #define IPMI_NETFN_APP_MAXCMD 0x36
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
64 #define IPMI_NETFN_STORAGE_MAXCMD 0x4a
66 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
67 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
68 #define IPMI_CMD_RESERVE_SDR_REP 0x22
69 #define IPMI_CMD_GET_SDR 0x23
70 #define IPMI_CMD_ADD_SDR 0x24
71 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
72 #define IPMI_CMD_DELETE_SDR 0x26
73 #define IPMI_CMD_CLEAR_SDR_REP 0x27
74 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
75 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
76 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
77 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
78 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
79 #define IPMI_CMD_GET_SEL_INFO 0x40
80 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
81 #define IPMI_CMD_RESERVE_SEL 0x42
82 #define IPMI_CMD_GET_SEL_ENTRY 0x43
83 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
84 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
85 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
86 #define IPMI_CMD_CLEAR_SEL 0x47
87 #define IPMI_CMD_GET_SEL_TIME 0x48
88 #define IPMI_CMD_SET_SEL_TIME 0x49
91 /* Same as a timespec struct. */
92 struct ipmi_time {
93 long tv_sec;
94 long tv_nsec;
97 #define MAX_SEL_SIZE 128
99 typedef struct IPMISel {
100 uint8_t sel[MAX_SEL_SIZE][16];
101 unsigned int next_free;
102 long time_offset;
103 uint16_t reservation;
104 uint8_t last_addition[4];
105 uint8_t last_clear[4];
106 uint8_t overflow;
107 } IPMISel;
109 #define MAX_SDR_SIZE 16384
111 typedef struct IPMISdr {
112 uint8_t sdr[MAX_SDR_SIZE];
113 unsigned int next_free;
114 uint16_t next_rec_id;
115 uint16_t reservation;
116 uint8_t last_addition[4];
117 uint8_t last_clear[4];
118 uint8_t overflow;
119 } IPMISdr;
121 typedef struct IPMISensor {
122 uint8_t status;
123 uint8_t reading;
124 uint16_t states_suppt;
125 uint16_t assert_suppt;
126 uint16_t deassert_suppt;
127 uint16_t states;
128 uint16_t assert_states;
129 uint16_t deassert_states;
130 uint16_t assert_enable;
131 uint16_t deassert_enable;
132 uint8_t sensor_type;
133 uint8_t evt_reading_type_code;
134 } IPMISensor;
135 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
136 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
137 !!(v))
138 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
139 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
140 ((!!(v)) << 6))
141 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
142 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
143 ((!!(v)) << 7))
144 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
145 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
146 (v & 0xc0))
147 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
149 #define MAX_SENSORS 20
150 #define IPMI_WATCHDOG_SENSOR 0
152 typedef struct IPMIBmcSim IPMIBmcSim;
154 #define MAX_NETFNS 64
155 typedef void (*IPMICmdHandler)(IPMIBmcSim *s,
156 uint8_t *cmd, unsigned int cmd_len,
157 uint8_t *rsp, unsigned int *rsp_len,
158 unsigned int max_rsp_len);
159 typedef struct IPMINetfn {
160 unsigned int cmd_nums;
161 const IPMICmdHandler *cmd_handlers;
162 } IPMINetfn;
164 typedef struct IPMIRcvBufEntry {
165 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
166 uint8_t len;
167 uint8_t buf[MAX_IPMI_MSG_SIZE];
168 } IPMIRcvBufEntry;
170 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
171 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
172 TYPE_IPMI_BMC_SIMULATOR)
173 struct IPMIBmcSim {
174 IPMIBmc parent;
176 QEMUTimer *timer;
178 uint8_t bmc_global_enables;
179 uint8_t msg_flags;
181 bool watchdog_initialized;
182 uint8_t watchdog_use;
183 uint8_t watchdog_action;
184 uint8_t watchdog_pretimeout; /* In seconds */
185 bool watchdog_expired;
186 uint16_t watchdog_timeout; /* in 100's of milliseconds */
188 bool watchdog_running;
189 bool watchdog_preaction_ran;
190 int64_t watchdog_expiry;
192 uint8_t device_id;
193 uint8_t ipmi_version;
194 uint8_t device_rev;
195 uint8_t fwrev1;
196 uint8_t fwrev2;
197 uint8_t mfg_id[3];
198 uint8_t product_id[2];
200 IPMISel sel;
201 IPMISdr sdr;
202 IPMISensor sensors[MAX_SENSORS];
204 /* Odd netfns are for responses, so we only need the even ones. */
205 const IPMINetfn *netfns[MAX_NETFNS / 2];
207 QemuMutex lock;
208 /* We allow one event in the buffer */
209 uint8_t evtbuf[16];
211 QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
214 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
215 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
216 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
217 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
218 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
219 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
220 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
221 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
222 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
224 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
225 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
226 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
227 #define IPMI_BMC_EVENT_LOG_BIT 3
228 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
229 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
230 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
231 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
232 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
233 (1 << IPMI_BMC_EVENT_LOG_BIT))
234 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
235 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
237 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
238 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
239 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
240 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
241 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
242 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
243 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
244 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
245 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
246 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
247 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
248 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
249 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
250 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
251 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
254 /* Add a byte to the response. */
255 #define IPMI_ADD_RSP_DATA(b) \
256 do { \
257 if (*rsp_len >= max_rsp_len) { \
258 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED; \
259 return; \
261 rsp[(*rsp_len)++] = (b); \
262 } while (0)
264 /* Verify that the received command is a certain length. */
265 #define IPMI_CHECK_CMD_LEN(l) \
266 if (cmd_len < l) { \
267 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID; \
268 return; \
271 /* Check that the reservation in the command is valid. */
272 #define IPMI_CHECK_RESERVATION(off, r) \
273 do { \
274 if ((cmd[off] | (cmd[off + 1] << 8)) != r) { \
275 rsp[2] = IPMI_CC_INVALID_RESERVATION; \
276 return; \
278 } while (0)
281 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
283 static void ipmi_gettime(struct ipmi_time *time)
285 int64_t stime;
287 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
288 time->tv_sec = stime / 1000000000LL;
289 time->tv_nsec = stime % 1000000000LL;
292 static int64_t ipmi_getmonotime(void)
294 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
297 static void ipmi_timeout(void *opaque)
299 IPMIBmcSim *ibs = opaque;
301 ipmi_sim_handle_timeout(ibs);
304 static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
306 unsigned int val;
307 struct ipmi_time now;
309 ipmi_gettime(&now);
310 val = now.tv_sec + ibs->sel.time_offset;
311 ts[0] = val & 0xff;
312 ts[1] = (val >> 8) & 0xff;
313 ts[2] = (val >> 16) & 0xff;
314 ts[3] = (val >> 24) & 0xff;
317 static void sdr_inc_reservation(IPMISdr *sdr)
319 sdr->reservation++;
320 if (sdr->reservation == 0) {
321 sdr->reservation = 1;
325 static int sdr_add_entry(IPMIBmcSim *ibs, const uint8_t *entry,
326 unsigned int len, uint16_t *recid)
328 if ((len < 5) || (len > 255)) {
329 return 1;
332 if (entry[4] != len - 5) {
333 return 1;
336 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
337 ibs->sdr.overflow = 1;
338 return 1;
341 memcpy(ibs->sdr.sdr + ibs->sdr.next_free, entry, len);
342 ibs->sdr.sdr[ibs->sdr.next_free] = ibs->sdr.next_rec_id & 0xff;
343 ibs->sdr.sdr[ibs->sdr.next_free+1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
344 ibs->sdr.sdr[ibs->sdr.next_free+2] = 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 uint16_t trec = sdr->sdr[pos] | (sdr->sdr[pos + 1] << 8);
363 unsigned int nextpos = pos + sdr->sdr[pos + 4];
365 if (trec == recid) {
366 if (nextrec) {
367 if (nextpos >= sdr->next_free) {
368 *nextrec = 0xffff;
369 } else {
370 *nextrec = (sdr->sdr[nextpos] |
371 (sdr->sdr[nextpos + 1] << 8));
374 *retpos = pos;
375 return 0;
377 pos = nextpos;
379 return 1;
382 static void sel_inc_reservation(IPMISel *sel)
384 sel->reservation++;
385 if (sel->reservation == 0) {
386 sel->reservation = 1;
390 /* Returns 1 if the SEL is full and can't hold the event. */
391 static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
393 event[0] = 0xff;
394 event[1] = 0xff;
395 set_timestamp(ibs, event + 3);
396 if (ibs->sel.next_free == MAX_SEL_SIZE) {
397 ibs->sel.overflow = 1;
398 return 1;
400 event[0] = ibs->sel.next_free & 0xff;
401 event[1] = (ibs->sel.next_free >> 8) & 0xff;
402 memcpy(ibs->sel.last_addition, event + 3, 4);
403 memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
404 ibs->sel.next_free++;
405 sel_inc_reservation(&ibs->sel);
406 return 0;
409 static int attn_set(IPMIBmcSim *ibs)
411 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
412 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
413 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
416 static int attn_irq_enabled(IPMIBmcSim *ibs)
418 return (IPMI_BMC_MSG_INTS_ON(ibs) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs))
419 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
420 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
423 static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
424 uint8_t evd1, uint8_t evd2, uint8_t evd3)
426 IPMIInterface *s = ibs->parent.intf;
427 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
428 uint8_t evt[16];
429 IPMISensor *sens = ibs->sensors + sens_num;
431 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
432 return;
434 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
435 return;
438 evt[2] = 0x2; /* System event record */
439 evt[7] = ibs->parent.slave_addr;
440 evt[8] = 0;
441 evt[9] = 0x04; /* Format version */
442 evt[10] = sens->sensor_type;
443 evt[11] = sens_num;
444 evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
445 evt[13] = evd1;
446 evt[14] = evd2;
447 evt[15] = evd3;
449 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
450 sel_add_event(ibs, evt);
453 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
454 return;
457 memcpy(ibs->evtbuf, evt, 16);
458 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
459 k->set_atn(s, 1, attn_irq_enabled(ibs));
462 static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
463 unsigned int bit, unsigned int val,
464 uint8_t evd1, uint8_t evd2, uint8_t evd3)
466 IPMISensor *sens;
467 uint16_t mask;
469 if (sensor >= MAX_SENSORS) {
470 return;
472 if (bit >= 16) {
473 return;
476 mask = (1 << bit);
477 sens = ibs->sensors + sensor;
478 if (val) {
479 sens->states |= mask & sens->states_suppt;
480 if (sens->assert_states & mask) {
481 return; /* Already asserted */
483 sens->assert_states |= mask & sens->assert_suppt;
484 if (sens->assert_enable & mask & sens->assert_states) {
485 /* Send an event on assert */
486 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
488 } else {
489 sens->states &= ~(mask & sens->states_suppt);
490 if (sens->deassert_states & mask) {
491 return; /* Already deasserted */
493 sens->deassert_states |= mask & sens->deassert_suppt;
494 if (sens->deassert_enable & mask & sens->deassert_states) {
495 /* Send an event on deassert */
496 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
501 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
503 unsigned int i, pos;
504 IPMISensor *sens;
506 for (i = 0; i < MAX_SENSORS; i++) {
507 memset(s->sensors + i, 0, sizeof(*sens));
510 pos = 0;
511 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
512 uint8_t *sdr = s->sdr.sdr + pos;
513 unsigned int len = sdr[4];
515 if (len < 20) {
516 continue;
518 if ((sdr[3] < 1) || (sdr[3] > 2)) {
519 continue; /* Not a sensor SDR we set from */
522 if (sdr[7] > MAX_SENSORS) {
523 continue;
525 sens = s->sensors + sdr[7];
527 IPMI_SENSOR_SET_PRESENT(sens, 1);
528 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr[10] >> 6) & 1);
529 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr[10] >> 5) & 1);
530 sens->assert_suppt = sdr[14] | (sdr[15] << 8);
531 sens->deassert_suppt = sdr[16] | (sdr[17] << 8);
532 sens->states_suppt = sdr[18] | (sdr[19] << 8);
533 sens->sensor_type = sdr[12];
534 sens->evt_reading_type_code = sdr[13] & 0x7f;
536 /* Enable all the events that are supported. */
537 sens->assert_enable = sens->assert_suppt;
538 sens->deassert_enable = sens->deassert_suppt;
542 static int ipmi_register_netfn(IPMIBmcSim *s, unsigned int netfn,
543 const IPMINetfn *netfnd)
545 if ((netfn & 1) || (netfn > MAX_NETFNS) || (s->netfns[netfn / 2])) {
546 return -1;
548 s->netfns[netfn / 2] = netfnd;
549 return 0;
552 static void next_timeout(IPMIBmcSim *ibs)
554 int64_t next;
555 if (ibs->watchdog_running) {
556 next = ibs->watchdog_expiry;
557 } else {
558 /* Wait a minute */
559 next = ipmi_getmonotime() + 60 * 1000000000LL;
561 timer_mod_ns(ibs->timer, next);
564 static void ipmi_sim_handle_command(IPMIBmc *b,
565 uint8_t *cmd, unsigned int cmd_len,
566 unsigned int max_cmd_len,
567 uint8_t msg_id)
569 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
570 IPMIInterface *s = ibs->parent.intf;
571 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
572 unsigned int netfn;
573 uint8_t rsp[MAX_IPMI_MSG_SIZE];
574 unsigned int rsp_len_holder = 0;
575 unsigned int *rsp_len = &rsp_len_holder;
576 unsigned int max_rsp_len = sizeof(rsp);
578 /* Set up the response, set the low bit of NETFN. */
579 /* Note that max_rsp_len must be at least 3 */
580 if (max_rsp_len < 3) {
581 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
582 goto out;
585 IPMI_ADD_RSP_DATA(cmd[0] | 0x04);
586 IPMI_ADD_RSP_DATA(cmd[1]);
587 IPMI_ADD_RSP_DATA(0); /* Assume success */
589 /* If it's too short or it was truncated, return an error. */
590 if (cmd_len < 2) {
591 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
592 goto out;
594 if (cmd_len > max_cmd_len) {
595 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
596 goto out;
599 if ((cmd[0] & 0x03) != 0) {
600 /* Only have stuff on LUN 0 */
601 rsp[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
602 goto out;
605 netfn = cmd[0] >> 2;
607 /* Odd netfns are not valid, make sure the command is registered */
608 if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
609 (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
610 (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
611 rsp[2] = IPMI_CC_INVALID_CMD;
612 goto out;
615 ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
616 max_rsp_len);
618 out:
619 k->handle_rsp(s, msg_id, rsp, *rsp_len);
621 next_timeout(ibs);
624 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
626 IPMIInterface *s = ibs->parent.intf;
627 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
629 if (!ibs->watchdog_running) {
630 goto out;
633 if (!ibs->watchdog_preaction_ran) {
634 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
635 case IPMI_BMC_WATCHDOG_PRE_NMI:
636 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
637 k->do_hw_op(s, IPMI_SEND_NMI, 0);
638 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
639 0xc8, (2 << 4) | 0xf, 0xff);
640 break;
642 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
643 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
644 k->set_atn(s, 1, attn_irq_enabled(ibs));
645 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
646 0xc8, (3 << 4) | 0xf, 0xff);
647 break;
649 default:
650 goto do_full_expiry;
653 ibs->watchdog_preaction_ran = 1;
654 /* Issued the pretimeout, do the rest of the timeout now. */
655 ibs->watchdog_expiry = ipmi_getmonotime();
656 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
657 goto out;
660 do_full_expiry:
661 ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
662 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
663 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
664 case IPMI_BMC_WATCHDOG_ACTION_NONE:
665 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
666 0xc0, ibs->watchdog_use & 0xf, 0xff);
667 break;
669 case IPMI_BMC_WATCHDOG_ACTION_RESET:
670 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
671 0xc1, ibs->watchdog_use & 0xf, 0xff);
672 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
673 break;
675 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
676 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
677 0xc2, ibs->watchdog_use & 0xf, 0xff);
678 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
679 break;
681 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
682 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
683 0xc3, ibs->watchdog_use & 0xf, 0xff);
684 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
685 break;
688 out:
689 next_timeout(ibs);
692 static void chassis_capabilities(IPMIBmcSim *ibs,
693 uint8_t *cmd, unsigned int cmd_len,
694 uint8_t *rsp, unsigned int *rsp_len,
695 unsigned int max_rsp_len)
697 IPMI_ADD_RSP_DATA(0);
698 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
699 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
700 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
701 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
704 static void chassis_status(IPMIBmcSim *ibs,
705 uint8_t *cmd, unsigned int cmd_len,
706 uint8_t *rsp, unsigned int *rsp_len,
707 unsigned int max_rsp_len)
709 IPMI_ADD_RSP_DATA(0x61); /* Unknown power restore, power is on */
710 IPMI_ADD_RSP_DATA(0);
711 IPMI_ADD_RSP_DATA(0);
712 IPMI_ADD_RSP_DATA(0);
715 static void chassis_control(IPMIBmcSim *ibs,
716 uint8_t *cmd, unsigned int cmd_len,
717 uint8_t *rsp, unsigned int *rsp_len,
718 unsigned int max_rsp_len)
720 IPMIInterface *s = ibs->parent.intf;
721 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
723 IPMI_CHECK_CMD_LEN(3);
724 switch (cmd[2] & 0xf) {
725 case 0: /* power down */
726 rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
727 break;
728 case 1: /* power up */
729 rsp[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
730 break;
731 case 2: /* power cycle */
732 rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
733 break;
734 case 3: /* hard reset */
735 rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
736 break;
737 case 4: /* pulse diagnostic interrupt */
738 rsp[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
739 break;
740 case 5: /* soft shutdown via ACPI by overtemp emulation */
741 rsp[2] = k->do_hw_op(s,
742 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0);
743 break;
744 default:
745 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
746 return;
750 static void get_device_id(IPMIBmcSim *ibs,
751 uint8_t *cmd, unsigned int cmd_len,
752 uint8_t *rsp, unsigned int *rsp_len,
753 unsigned int max_rsp_len)
755 IPMI_ADD_RSP_DATA(ibs->device_id);
756 IPMI_ADD_RSP_DATA(ibs->device_rev & 0xf);
757 IPMI_ADD_RSP_DATA(ibs->fwrev1 & 0x7f);
758 IPMI_ADD_RSP_DATA(ibs->fwrev2);
759 IPMI_ADD_RSP_DATA(ibs->ipmi_version);
760 IPMI_ADD_RSP_DATA(0x07); /* sensor, SDR, and SEL. */
761 IPMI_ADD_RSP_DATA(ibs->mfg_id[0]);
762 IPMI_ADD_RSP_DATA(ibs->mfg_id[1]);
763 IPMI_ADD_RSP_DATA(ibs->mfg_id[2]);
764 IPMI_ADD_RSP_DATA(ibs->product_id[0]);
765 IPMI_ADD_RSP_DATA(ibs->product_id[1]);
768 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
770 IPMIInterface *s = ibs->parent.intf;
771 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
772 bool irqs_on;
774 ibs->bmc_global_enables = val;
776 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
777 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
779 k->set_irq_enable(s, irqs_on);
782 static void cold_reset(IPMIBmcSim *ibs,
783 uint8_t *cmd, unsigned int cmd_len,
784 uint8_t *rsp, unsigned int *rsp_len,
785 unsigned int max_rsp_len)
787 IPMIInterface *s = ibs->parent.intf;
788 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
790 /* Disable all interrupts */
791 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
793 if (k->reset) {
794 k->reset(s, true);
798 static void warm_reset(IPMIBmcSim *ibs,
799 uint8_t *cmd, unsigned int cmd_len,
800 uint8_t *rsp, unsigned int *rsp_len,
801 unsigned int max_rsp_len)
803 IPMIInterface *s = ibs->parent.intf;
804 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
806 if (k->reset) {
807 k->reset(s, false);
811 static void set_bmc_global_enables(IPMIBmcSim *ibs,
812 uint8_t *cmd, unsigned int cmd_len,
813 uint8_t *rsp, unsigned int *rsp_len,
814 unsigned int max_rsp_len)
816 IPMI_CHECK_CMD_LEN(3);
817 set_global_enables(ibs, cmd[2]);
820 static void get_bmc_global_enables(IPMIBmcSim *ibs,
821 uint8_t *cmd, unsigned int cmd_len,
822 uint8_t *rsp, unsigned int *rsp_len,
823 unsigned int max_rsp_len)
825 IPMI_ADD_RSP_DATA(ibs->bmc_global_enables);
828 static void clr_msg_flags(IPMIBmcSim *ibs,
829 uint8_t *cmd, unsigned int cmd_len,
830 uint8_t *rsp, unsigned int *rsp_len,
831 unsigned int max_rsp_len)
833 IPMIInterface *s = ibs->parent.intf;
834 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
836 IPMI_CHECK_CMD_LEN(3);
837 ibs->msg_flags &= ~cmd[2];
838 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
841 static void get_msg_flags(IPMIBmcSim *ibs,
842 uint8_t *cmd, unsigned int cmd_len,
843 uint8_t *rsp, unsigned int *rsp_len,
844 unsigned int max_rsp_len)
846 IPMI_ADD_RSP_DATA(ibs->msg_flags);
849 static void read_evt_msg_buf(IPMIBmcSim *ibs,
850 uint8_t *cmd, unsigned int cmd_len,
851 uint8_t *rsp, unsigned int *rsp_len,
852 unsigned int max_rsp_len)
854 IPMIInterface *s = ibs->parent.intf;
855 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
856 unsigned int i;
858 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
859 rsp[2] = 0x80;
860 return;
862 for (i = 0; i < 16; i++) {
863 IPMI_ADD_RSP_DATA(ibs->evtbuf[i]);
865 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
866 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
869 static void get_msg(IPMIBmcSim *ibs,
870 uint8_t *cmd, unsigned int cmd_len,
871 uint8_t *rsp, unsigned int *rsp_len,
872 unsigned int max_rsp_len)
874 IPMIRcvBufEntry *msg;
876 qemu_mutex_lock(&ibs->lock);
877 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
878 rsp[2] = 0x80; /* Queue empty */
879 goto out;
881 rsp[3] = 0; /* Channel 0 */
882 *rsp_len += 1;
883 msg = QTAILQ_FIRST(&ibs->rcvbufs);
884 memcpy(rsp + 4, msg->buf, msg->len);
885 *rsp_len += msg->len;
886 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
887 g_free(msg);
889 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
890 IPMIInterface *s = ibs->parent.intf;
891 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
893 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
894 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
897 out:
898 qemu_mutex_unlock(&ibs->lock);
899 return;
902 static unsigned char
903 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
905 for (; size > 0; size--, data++) {
906 csum += *data;
909 return -csum;
912 static void send_msg(IPMIBmcSim *ibs,
913 uint8_t *cmd, unsigned int cmd_len,
914 uint8_t *rsp, unsigned int *rsp_len,
915 unsigned int max_rsp_len)
917 IPMIInterface *s = ibs->parent.intf;
918 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
919 IPMIRcvBufEntry *msg;
920 uint8_t *buf;
921 uint8_t netfn, rqLun, rsLun, rqSeq;
923 IPMI_CHECK_CMD_LEN(3);
925 if (cmd[2] != 0) {
926 /* We only handle channel 0 with no options */
927 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
928 return;
931 IPMI_CHECK_CMD_LEN(10);
932 if (cmd[3] != 0x40) {
933 /* We only emulate a MC at address 0x40. */
934 rsp[2] = 0x83; /* NAK on write */
935 return;
938 cmd += 3; /* Skip the header. */
939 cmd_len -= 3;
942 * At this point we "send" the message successfully. Any error will
943 * be returned in the response.
945 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
946 cmd[3] != 0x20) { /* Improper response address */
947 return; /* No response */
950 netfn = cmd[1] >> 2;
951 rqLun = cmd[4] & 0x3;
952 rsLun = cmd[1] & 0x3;
953 rqSeq = cmd[4] >> 2;
955 if (rqLun != 2) {
956 /* We only support LUN 2 coming back to us. */
957 return;
960 msg = g_malloc(sizeof(*msg));
961 msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
962 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
963 msg->buf[2] = cmd[0]; /* rsSA */
964 msg->buf[3] = (rqSeq << 2) | rsLun;
965 msg->buf[4] = cmd[5]; /* Cmd */
966 msg->buf[5] = 0; /* Completion Code */
967 msg->len = 6;
969 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
970 /* Not a command we handle. */
971 msg->buf[5] = IPMI_CC_INVALID_CMD;
972 goto end_msg;
975 buf = msg->buf + msg->len; /* After the CC */
976 buf[0] = 0;
977 buf[1] = 0;
978 buf[2] = 0;
979 buf[3] = 0;
980 buf[4] = 0x51;
981 buf[5] = 0;
982 buf[6] = 0;
983 buf[7] = 0;
984 buf[8] = 0;
985 buf[9] = 0;
986 buf[10] = 0;
987 msg->len += 11;
989 end_msg:
990 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
991 msg->len++;
992 qemu_mutex_lock(&ibs->lock);
993 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
994 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
995 k->set_atn(s, 1, attn_irq_enabled(ibs));
996 qemu_mutex_unlock(&ibs->lock);
999 static void do_watchdog_reset(IPMIBmcSim *ibs)
1001 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1002 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1003 ibs->watchdog_running = 0;
1004 return;
1006 ibs->watchdog_preaction_ran = 0;
1009 /* Timeout is in tenths of a second, offset is in seconds */
1010 ibs->watchdog_expiry = ipmi_getmonotime();
1011 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1012 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1013 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1015 ibs->watchdog_running = 1;
1018 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1019 uint8_t *cmd, unsigned int cmd_len,
1020 uint8_t *rsp, unsigned int *rsp_len,
1021 unsigned int max_rsp_len)
1023 if (!ibs->watchdog_initialized) {
1024 rsp[2] = 0x80;
1025 return;
1027 do_watchdog_reset(ibs);
1030 static void set_watchdog_timer(IPMIBmcSim *ibs,
1031 uint8_t *cmd, unsigned int cmd_len,
1032 uint8_t *rsp, unsigned int *rsp_len,
1033 unsigned int max_rsp_len)
1035 IPMIInterface *s = ibs->parent.intf;
1036 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1037 unsigned int val;
1039 IPMI_CHECK_CMD_LEN(8);
1040 val = cmd[2] & 0x7; /* Validate use */
1041 if (val == 0 || val > 5) {
1042 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1043 return;
1045 val = cmd[3] & 0x7; /* Validate action */
1046 switch (val) {
1047 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1048 break;
1050 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1051 rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
1052 break;
1054 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1055 rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
1056 break;
1058 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1059 rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
1060 break;
1062 default:
1063 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1065 if (rsp[2]) {
1066 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1067 return;
1070 val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1071 switch (val) {
1072 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1073 case IPMI_BMC_WATCHDOG_PRE_NONE:
1074 break;
1076 case IPMI_BMC_WATCHDOG_PRE_NMI:
1077 if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1078 /* NMI not supported. */
1079 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1080 return;
1082 default:
1083 /* We don't support PRE_SMI */
1084 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1085 return;
1088 ibs->watchdog_initialized = 1;
1089 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1090 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1091 ibs->watchdog_pretimeout = cmd[4];
1092 ibs->watchdog_expired &= ~cmd[5];
1093 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1094 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1095 do_watchdog_reset(ibs);
1096 } else {
1097 ibs->watchdog_running = 0;
1101 static void get_watchdog_timer(IPMIBmcSim *ibs,
1102 uint8_t *cmd, unsigned int cmd_len,
1103 uint8_t *rsp, unsigned int *rsp_len,
1104 unsigned int max_rsp_len)
1106 IPMI_ADD_RSP_DATA(ibs->watchdog_use);
1107 IPMI_ADD_RSP_DATA(ibs->watchdog_action);
1108 IPMI_ADD_RSP_DATA(ibs->watchdog_pretimeout);
1109 IPMI_ADD_RSP_DATA(ibs->watchdog_expired);
1110 if (ibs->watchdog_running) {
1111 long timeout;
1112 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1113 / 100000000);
1114 IPMI_ADD_RSP_DATA(timeout & 0xff);
1115 IPMI_ADD_RSP_DATA((timeout >> 8) & 0xff);
1116 } else {
1117 IPMI_ADD_RSP_DATA(0);
1118 IPMI_ADD_RSP_DATA(0);
1122 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1123 uint8_t *cmd, unsigned int cmd_len,
1124 uint8_t *rsp, unsigned int *rsp_len,
1125 unsigned int max_rsp_len)
1127 unsigned int i;
1129 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 spec */
1130 IPMI_ADD_RSP_DATA(ibs->sdr.next_rec_id & 0xff);
1131 IPMI_ADD_RSP_DATA((ibs->sdr.next_rec_id >> 8) & 0xff);
1132 IPMI_ADD_RSP_DATA((MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1133 IPMI_ADD_RSP_DATA(((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1134 for (i = 0; i < 4; i++) {
1135 IPMI_ADD_RSP_DATA(ibs->sdr.last_addition[i]);
1137 for (i = 0; i < 4; i++) {
1138 IPMI_ADD_RSP_DATA(ibs->sdr.last_clear[i]);
1140 /* Only modal support, reserve supported */
1141 IPMI_ADD_RSP_DATA((ibs->sdr.overflow << 7) | 0x22);
1144 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1145 uint8_t *cmd, unsigned int cmd_len,
1146 uint8_t *rsp, unsigned int *rsp_len,
1147 unsigned int max_rsp_len)
1149 IPMI_ADD_RSP_DATA(ibs->sdr.reservation & 0xff);
1150 IPMI_ADD_RSP_DATA((ibs->sdr.reservation >> 8) & 0xff);
1153 static void get_sdr(IPMIBmcSim *ibs,
1154 uint8_t *cmd, unsigned int cmd_len,
1155 uint8_t *rsp, unsigned int *rsp_len,
1156 unsigned int max_rsp_len)
1158 unsigned int pos;
1159 uint16_t nextrec;
1161 IPMI_CHECK_CMD_LEN(8);
1162 if (cmd[6]) {
1163 IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
1165 pos = 0;
1166 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1167 &pos, &nextrec)) {
1168 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1169 return;
1171 if (cmd[6] > (ibs->sdr.sdr[pos + 4])) {
1172 rsp[2] = IPMI_CC_PARM_OUT_OF_RANGE;
1173 return;
1176 IPMI_ADD_RSP_DATA(nextrec & 0xff);
1177 IPMI_ADD_RSP_DATA((nextrec >> 8) & 0xff);
1179 if (cmd[7] == 0xff) {
1180 cmd[7] = ibs->sdr.sdr[pos + 4] - cmd[6];
1183 if ((cmd[7] + *rsp_len) > max_rsp_len) {
1184 rsp[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
1185 return;
1187 memcpy(rsp + *rsp_len, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1188 *rsp_len += cmd[7];
1191 static void add_sdr(IPMIBmcSim *ibs,
1192 uint8_t *cmd, unsigned int cmd_len,
1193 uint8_t *rsp, unsigned int *rsp_len,
1194 unsigned int max_rsp_len)
1196 uint16_t recid;
1198 if (sdr_add_entry(ibs, cmd + 2, cmd_len - 2, &recid)) {
1199 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1200 return;
1202 IPMI_ADD_RSP_DATA(recid & 0xff);
1203 IPMI_ADD_RSP_DATA((recid >> 8) & 0xff);
1206 static void clear_sdr_rep(IPMIBmcSim *ibs,
1207 uint8_t *cmd, unsigned int cmd_len,
1208 uint8_t *rsp, unsigned int *rsp_len,
1209 unsigned int max_rsp_len)
1211 IPMI_CHECK_CMD_LEN(8);
1212 IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
1213 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1214 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1215 return;
1217 if (cmd[7] == 0xaa) {
1218 ibs->sdr.next_free = 0;
1219 ibs->sdr.overflow = 0;
1220 set_timestamp(ibs, ibs->sdr.last_clear);
1221 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1222 sdr_inc_reservation(&ibs->sdr);
1223 } else if (cmd[7] == 0) {
1224 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1225 } else {
1226 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1227 return;
1231 static void get_sel_info(IPMIBmcSim *ibs,
1232 uint8_t *cmd, unsigned int cmd_len,
1233 uint8_t *rsp, unsigned int *rsp_len,
1234 unsigned int max_rsp_len)
1236 unsigned int i, val;
1238 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 */
1239 IPMI_ADD_RSP_DATA(ibs->sel.next_free & 0xff);
1240 IPMI_ADD_RSP_DATA((ibs->sel.next_free >> 8) & 0xff);
1241 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1242 IPMI_ADD_RSP_DATA(val & 0xff);
1243 IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
1244 for (i = 0; i < 4; i++) {
1245 IPMI_ADD_RSP_DATA(ibs->sel.last_addition[i]);
1247 for (i = 0; i < 4; i++) {
1248 IPMI_ADD_RSP_DATA(ibs->sel.last_clear[i]);
1250 /* Only support Reserve SEL */
1251 IPMI_ADD_RSP_DATA((ibs->sel.overflow << 7) | 0x02);
1254 static void reserve_sel(IPMIBmcSim *ibs,
1255 uint8_t *cmd, unsigned int cmd_len,
1256 uint8_t *rsp, unsigned int *rsp_len,
1257 unsigned int max_rsp_len)
1259 IPMI_ADD_RSP_DATA(ibs->sel.reservation & 0xff);
1260 IPMI_ADD_RSP_DATA((ibs->sel.reservation >> 8) & 0xff);
1263 static void get_sel_entry(IPMIBmcSim *ibs,
1264 uint8_t *cmd, unsigned int cmd_len,
1265 uint8_t *rsp, unsigned int *rsp_len,
1266 unsigned int max_rsp_len)
1268 unsigned int val;
1270 IPMI_CHECK_CMD_LEN(8);
1271 if (cmd[6]) {
1272 IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
1274 if (ibs->sel.next_free == 0) {
1275 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1276 return;
1278 if (cmd[6] > 15) {
1279 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1280 return;
1282 if (cmd[7] == 0xff) {
1283 cmd[7] = 16;
1284 } else if ((cmd[7] + cmd[6]) > 16) {
1285 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1286 return;
1287 } else {
1288 cmd[7] += cmd[6];
1291 val = cmd[4] | (cmd[5] << 8);
1292 if (val == 0xffff) {
1293 val = ibs->sel.next_free - 1;
1294 } else if (val >= ibs->sel.next_free) {
1295 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1296 return;
1298 if ((val + 1) == ibs->sel.next_free) {
1299 IPMI_ADD_RSP_DATA(0xff);
1300 IPMI_ADD_RSP_DATA(0xff);
1301 } else {
1302 IPMI_ADD_RSP_DATA((val + 1) & 0xff);
1303 IPMI_ADD_RSP_DATA(((val + 1) >> 8) & 0xff);
1305 for (; cmd[6] < cmd[7]; cmd[6]++) {
1306 IPMI_ADD_RSP_DATA(ibs->sel.sel[val][cmd[6]]);
1310 static void add_sel_entry(IPMIBmcSim *ibs,
1311 uint8_t *cmd, unsigned int cmd_len,
1312 uint8_t *rsp, unsigned int *rsp_len,
1313 unsigned int max_rsp_len)
1315 IPMI_CHECK_CMD_LEN(18);
1316 if (sel_add_event(ibs, cmd + 2)) {
1317 rsp[2] = IPMI_CC_OUT_OF_SPACE;
1318 return;
1320 /* sel_add_event fills in the record number. */
1321 IPMI_ADD_RSP_DATA(cmd[2]);
1322 IPMI_ADD_RSP_DATA(cmd[3]);
1325 static void clear_sel(IPMIBmcSim *ibs,
1326 uint8_t *cmd, unsigned int cmd_len,
1327 uint8_t *rsp, unsigned int *rsp_len,
1328 unsigned int max_rsp_len)
1330 IPMI_CHECK_CMD_LEN(8);
1331 IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
1332 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1333 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1334 return;
1336 if (cmd[7] == 0xaa) {
1337 ibs->sel.next_free = 0;
1338 ibs->sel.overflow = 0;
1339 set_timestamp(ibs, ibs->sdr.last_clear);
1340 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1341 sel_inc_reservation(&ibs->sel);
1342 } else if (cmd[7] == 0) {
1343 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1344 } else {
1345 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1346 return;
1350 static void get_sel_time(IPMIBmcSim *ibs,
1351 uint8_t *cmd, unsigned int cmd_len,
1352 uint8_t *rsp, unsigned int *rsp_len,
1353 unsigned int max_rsp_len)
1355 uint32_t val;
1356 struct ipmi_time now;
1358 ipmi_gettime(&now);
1359 val = now.tv_sec + ibs->sel.time_offset;
1360 IPMI_ADD_RSP_DATA(val & 0xff);
1361 IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
1362 IPMI_ADD_RSP_DATA((val >> 16) & 0xff);
1363 IPMI_ADD_RSP_DATA((val >> 24) & 0xff);
1366 static void set_sel_time(IPMIBmcSim *ibs,
1367 uint8_t *cmd, unsigned int cmd_len,
1368 uint8_t *rsp, unsigned int *rsp_len,
1369 unsigned int max_rsp_len)
1371 uint32_t val;
1372 struct ipmi_time now;
1374 IPMI_CHECK_CMD_LEN(6);
1375 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1376 ipmi_gettime(&now);
1377 ibs->sel.time_offset = now.tv_sec - ((long) val);
1380 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1381 uint8_t *cmd, unsigned int cmd_len,
1382 uint8_t *rsp, unsigned int *rsp_len,
1383 unsigned int max_rsp_len)
1385 IPMISensor *sens;
1387 IPMI_CHECK_CMD_LEN(4);
1388 if ((cmd[2] > MAX_SENSORS) ||
1389 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1390 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1391 return;
1393 sens = ibs->sensors + cmd[2];
1394 switch ((cmd[3] >> 4) & 0x3) {
1395 case 0: /* Do not change */
1396 break;
1397 case 1: /* Enable bits */
1398 if (cmd_len > 4) {
1399 sens->assert_enable |= cmd[4];
1401 if (cmd_len > 5) {
1402 sens->assert_enable |= cmd[5] << 8;
1404 if (cmd_len > 6) {
1405 sens->deassert_enable |= cmd[6];
1407 if (cmd_len > 7) {
1408 sens->deassert_enable |= cmd[7] << 8;
1410 break;
1411 case 2: /* Disable bits */
1412 if (cmd_len > 4) {
1413 sens->assert_enable &= ~cmd[4];
1415 if (cmd_len > 5) {
1416 sens->assert_enable &= ~(cmd[5] << 8);
1418 if (cmd_len > 6) {
1419 sens->deassert_enable &= ~cmd[6];
1421 if (cmd_len > 7) {
1422 sens->deassert_enable &= ~(cmd[7] << 8);
1424 break;
1425 case 3:
1426 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1427 return;
1429 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1432 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1433 uint8_t *cmd, unsigned int cmd_len,
1434 uint8_t *rsp, unsigned int *rsp_len,
1435 unsigned int max_rsp_len)
1437 IPMISensor *sens;
1439 IPMI_CHECK_CMD_LEN(3);
1440 if ((cmd[2] > MAX_SENSORS) ||
1441 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1442 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1443 return;
1445 sens = ibs->sensors + cmd[2];
1446 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1447 IPMI_ADD_RSP_DATA(sens->assert_enable & 0xff);
1448 IPMI_ADD_RSP_DATA((sens->assert_enable >> 8) & 0xff);
1449 IPMI_ADD_RSP_DATA(sens->deassert_enable & 0xff);
1450 IPMI_ADD_RSP_DATA((sens->deassert_enable >> 8) & 0xff);
1453 static void rearm_sensor_evts(IPMIBmcSim *ibs,
1454 uint8_t *cmd, unsigned int cmd_len,
1455 uint8_t *rsp, unsigned int *rsp_len,
1456 unsigned int max_rsp_len)
1458 IPMISensor *sens;
1460 IPMI_CHECK_CMD_LEN(4);
1461 if ((cmd[2] > MAX_SENSORS) ||
1462 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1463 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1464 return;
1466 sens = ibs->sensors + cmd[2];
1468 if ((cmd[3] & 0x80) == 0) {
1469 /* Just clear everything */
1470 sens->states = 0;
1471 return;
1475 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1476 uint8_t *cmd, unsigned int cmd_len,
1477 uint8_t *rsp, unsigned int *rsp_len,
1478 unsigned int max_rsp_len)
1480 IPMISensor *sens;
1482 IPMI_CHECK_CMD_LEN(3);
1483 if ((cmd[2] > MAX_SENSORS) ||
1484 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1485 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1486 return;
1488 sens = ibs->sensors + cmd[2];
1489 IPMI_ADD_RSP_DATA(sens->reading);
1490 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1491 IPMI_ADD_RSP_DATA(sens->assert_states & 0xff);
1492 IPMI_ADD_RSP_DATA((sens->assert_states >> 8) & 0xff);
1493 IPMI_ADD_RSP_DATA(sens->deassert_states & 0xff);
1494 IPMI_ADD_RSP_DATA((sens->deassert_states >> 8) & 0xff);
1497 static void get_sensor_reading(IPMIBmcSim *ibs,
1498 uint8_t *cmd, unsigned int cmd_len,
1499 uint8_t *rsp, unsigned int *rsp_len,
1500 unsigned int max_rsp_len)
1502 IPMISensor *sens;
1504 IPMI_CHECK_CMD_LEN(3);
1505 if ((cmd[2] > MAX_SENSORS) ||
1506 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1507 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1508 return;
1510 sens = ibs->sensors + cmd[2];
1511 IPMI_ADD_RSP_DATA(sens->reading);
1512 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1513 IPMI_ADD_RSP_DATA(sens->states & 0xff);
1514 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1515 IPMI_ADD_RSP_DATA((sens->states >> 8) & 0xff);
1519 static const IPMICmdHandler chassis_cmds[IPMI_NETFN_CHASSIS_MAXCMD] = {
1520 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = chassis_capabilities,
1521 [IPMI_CMD_GET_CHASSIS_STATUS] = chassis_status,
1522 [IPMI_CMD_CHASSIS_CONTROL] = chassis_control
1524 static const IPMINetfn chassis_netfn = {
1525 .cmd_nums = IPMI_NETFN_CHASSIS_MAXCMD,
1526 .cmd_handlers = chassis_cmds
1529 static const IPMICmdHandler
1530 sensor_event_cmds[IPMI_NETFN_SENSOR_EVENT_MAXCMD] = {
1531 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = set_sensor_evt_enable,
1532 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = get_sensor_evt_enable,
1533 [IPMI_CMD_REARM_SENSOR_EVTS] = rearm_sensor_evts,
1534 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = get_sensor_evt_status,
1535 [IPMI_CMD_GET_SENSOR_READING] = get_sensor_reading
1537 static const IPMINetfn sensor_event_netfn = {
1538 .cmd_nums = IPMI_NETFN_SENSOR_EVENT_MAXCMD,
1539 .cmd_handlers = sensor_event_cmds
1542 static const IPMICmdHandler app_cmds[IPMI_NETFN_APP_MAXCMD] = {
1543 [IPMI_CMD_GET_DEVICE_ID] = get_device_id,
1544 [IPMI_CMD_COLD_RESET] = cold_reset,
1545 [IPMI_CMD_WARM_RESET] = warm_reset,
1546 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = set_bmc_global_enables,
1547 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = get_bmc_global_enables,
1548 [IPMI_CMD_CLR_MSG_FLAGS] = clr_msg_flags,
1549 [IPMI_CMD_GET_MSG_FLAGS] = get_msg_flags,
1550 [IPMI_CMD_GET_MSG] = get_msg,
1551 [IPMI_CMD_SEND_MSG] = send_msg,
1552 [IPMI_CMD_READ_EVT_MSG_BUF] = read_evt_msg_buf,
1553 [IPMI_CMD_RESET_WATCHDOG_TIMER] = reset_watchdog_timer,
1554 [IPMI_CMD_SET_WATCHDOG_TIMER] = set_watchdog_timer,
1555 [IPMI_CMD_GET_WATCHDOG_TIMER] = get_watchdog_timer,
1557 static const IPMINetfn app_netfn = {
1558 .cmd_nums = IPMI_NETFN_APP_MAXCMD,
1559 .cmd_handlers = app_cmds
1562 static const IPMICmdHandler storage_cmds[IPMI_NETFN_STORAGE_MAXCMD] = {
1563 [IPMI_CMD_GET_SDR_REP_INFO] = get_sdr_rep_info,
1564 [IPMI_CMD_RESERVE_SDR_REP] = reserve_sdr_rep,
1565 [IPMI_CMD_GET_SDR] = get_sdr,
1566 [IPMI_CMD_ADD_SDR] = add_sdr,
1567 [IPMI_CMD_CLEAR_SDR_REP] = clear_sdr_rep,
1568 [IPMI_CMD_GET_SEL_INFO] = get_sel_info,
1569 [IPMI_CMD_RESERVE_SEL] = reserve_sel,
1570 [IPMI_CMD_GET_SEL_ENTRY] = get_sel_entry,
1571 [IPMI_CMD_ADD_SEL_ENTRY] = add_sel_entry,
1572 [IPMI_CMD_CLEAR_SEL] = clear_sel,
1573 [IPMI_CMD_GET_SEL_TIME] = get_sel_time,
1574 [IPMI_CMD_SET_SEL_TIME] = set_sel_time,
1577 static const IPMINetfn storage_netfn = {
1578 .cmd_nums = IPMI_NETFN_STORAGE_MAXCMD,
1579 .cmd_handlers = storage_cmds
1582 static void register_cmds(IPMIBmcSim *s)
1584 ipmi_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
1585 ipmi_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
1586 ipmi_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
1587 ipmi_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
1590 static const uint8_t init_sdrs[] = {
1591 /* Watchdog device */
1592 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1593 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1596 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1597 /* End */
1598 0xff, 0xff, 0x00, 0x00, 0x00
1601 static const VMStateDescription vmstate_ipmi_sim = {
1602 .name = TYPE_IPMI_BMC_SIMULATOR,
1603 .version_id = 1,
1604 .minimum_version_id = 1,
1605 .fields = (VMStateField[]) {
1606 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
1607 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
1608 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
1609 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
1610 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
1611 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
1612 VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
1613 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
1614 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
1615 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
1616 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
1617 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
1618 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
1619 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
1620 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
1621 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
1622 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
1623 IPMIBmcSim),
1624 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
1625 VMSTATE_END_OF_LIST()
1629 static void ipmi_sim_init(Object *obj)
1631 IPMIBmc *b = IPMI_BMC(obj);
1632 unsigned int i;
1633 unsigned int recid;
1634 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
1636 qemu_mutex_init(&ibs->lock);
1637 QTAILQ_INIT(&ibs->rcvbufs);
1639 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
1640 ibs->device_id = 0x20;
1641 ibs->ipmi_version = 0x02; /* IPMI 2.0 */
1642 for (i = 0; i < 4; i++) {
1643 ibs->sel.last_addition[i] = 0xff;
1644 ibs->sel.last_clear[i] = 0xff;
1645 ibs->sdr.last_addition[i] = 0xff;
1646 ibs->sdr.last_clear[i] = 0xff;
1649 for (i = 0;;) {
1650 int len;
1651 if ((i + 5) > sizeof(init_sdrs)) {
1652 error_report("Problem with recid 0x%4.4x: \n", i);
1653 return;
1655 len = init_sdrs[i + 4];
1656 recid = init_sdrs[i] | (init_sdrs[i + 1] << 8);
1657 if (recid == 0xffff) {
1658 break;
1660 if ((i + len + 5) > sizeof(init_sdrs)) {
1661 error_report("Problem with recid 0x%4.4x\n", i);
1662 return;
1664 sdr_add_entry(ibs, init_sdrs + i, len, NULL);
1665 i += len + 5;
1668 ipmi_init_sensors_from_sdrs(ibs);
1669 register_cmds(ibs);
1671 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
1673 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
1676 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
1678 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
1680 bk->handle_command = ipmi_sim_handle_command;
1683 static const TypeInfo ipmi_sim_type = {
1684 .name = TYPE_IPMI_BMC_SIMULATOR,
1685 .parent = TYPE_IPMI_BMC,
1686 .instance_size = sizeof(IPMIBmcSim),
1687 .instance_init = ipmi_sim_init,
1688 .class_init = ipmi_sim_class_init,
1691 static void ipmi_sim_register_types(void)
1693 type_register_static(&ipmi_sim_type);
1696 type_init(ipmi_sim_register_types)