docs: Style the command and its options in the synopsis
[qemu/ar7.git] / hw / ipmi / ipmi_bmc_sim.c
blob0a59e539f5495cc904cc1f7509f0c3635d9fcef1
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 <stdio.h>
26 #include <string.h>
27 #include <stdint.h>
28 #include "qemu/timer.h"
29 #include "hw/ipmi/ipmi.h"
30 #include "qemu/error-report.h"
32 #define IPMI_NETFN_CHASSIS 0x00
33 #define IPMI_NETFN_CHASSIS_MAXCMD 0x03
35 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
36 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
37 #define IPMI_CMD_CHASSIS_CONTROL 0x02
39 #define IPMI_NETFN_SENSOR_EVENT 0x04
40 #define IPMI_NETFN_SENSOR_EVENT_MAXCMD 0x2e
42 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
43 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
44 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
45 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
46 #define IPMI_CMD_GET_SENSOR_READING 0x2d
48 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
49 #define IPMI_NETFN_APP_MAXCMD 0x36
51 #define IPMI_CMD_GET_DEVICE_ID 0x01
52 #define IPMI_CMD_COLD_RESET 0x02
53 #define IPMI_CMD_WARM_RESET 0x03
54 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
55 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
56 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
57 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
58 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
59 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
60 #define IPMI_CMD_GET_MSG_FLAGS 0x31
61 #define IPMI_CMD_GET_MSG 0x33
62 #define IPMI_CMD_SEND_MSG 0x34
63 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
65 #define IPMI_NETFN_STORAGE 0x0a
66 #define IPMI_NETFN_STORAGE_MAXCMD 0x4a
68 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
69 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
70 #define IPMI_CMD_RESERVE_SDR_REP 0x22
71 #define IPMI_CMD_GET_SDR 0x23
72 #define IPMI_CMD_ADD_SDR 0x24
73 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
74 #define IPMI_CMD_DELETE_SDR 0x26
75 #define IPMI_CMD_CLEAR_SDR_REP 0x27
76 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
77 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
78 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
79 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
80 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
81 #define IPMI_CMD_GET_SEL_INFO 0x40
82 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
83 #define IPMI_CMD_RESERVE_SEL 0x42
84 #define IPMI_CMD_GET_SEL_ENTRY 0x43
85 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
86 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
87 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
88 #define IPMI_CMD_CLEAR_SEL 0x47
89 #define IPMI_CMD_GET_SEL_TIME 0x48
90 #define IPMI_CMD_SET_SEL_TIME 0x49
93 /* Same as a timespec struct. */
94 struct ipmi_time {
95 long tv_sec;
96 long tv_nsec;
99 #define MAX_SEL_SIZE 128
101 typedef struct IPMISel {
102 uint8_t sel[MAX_SEL_SIZE][16];
103 unsigned int next_free;
104 long time_offset;
105 uint16_t reservation;
106 uint8_t last_addition[4];
107 uint8_t last_clear[4];
108 uint8_t overflow;
109 } IPMISel;
111 #define MAX_SDR_SIZE 16384
113 typedef struct IPMISdr {
114 uint8_t sdr[MAX_SDR_SIZE];
115 unsigned int next_free;
116 uint16_t next_rec_id;
117 uint16_t reservation;
118 uint8_t last_addition[4];
119 uint8_t last_clear[4];
120 uint8_t overflow;
121 } IPMISdr;
123 typedef struct IPMISensor {
124 uint8_t status;
125 uint8_t reading;
126 uint16_t states_suppt;
127 uint16_t assert_suppt;
128 uint16_t deassert_suppt;
129 uint16_t states;
130 uint16_t assert_states;
131 uint16_t deassert_states;
132 uint16_t assert_enable;
133 uint16_t deassert_enable;
134 uint8_t sensor_type;
135 uint8_t evt_reading_type_code;
136 } IPMISensor;
137 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
138 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
139 !!(v))
140 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
141 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
142 ((!!(v)) << 6))
143 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
144 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
145 ((!!(v)) << 7))
146 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
147 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
148 (v & 0xc0))
149 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
151 #define MAX_SENSORS 20
152 #define IPMI_WATCHDOG_SENSOR 0
154 typedef struct IPMIBmcSim IPMIBmcSim;
156 #define MAX_NETFNS 64
157 typedef void (*IPMICmdHandler)(IPMIBmcSim *s,
158 uint8_t *cmd, unsigned int cmd_len,
159 uint8_t *rsp, unsigned int *rsp_len,
160 unsigned int max_rsp_len);
161 typedef struct IPMINetfn {
162 unsigned int cmd_nums;
163 const IPMICmdHandler *cmd_handlers;
164 } IPMINetfn;
166 typedef struct IPMIRcvBufEntry {
167 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
168 uint8_t len;
169 uint8_t buf[MAX_IPMI_MSG_SIZE];
170 } IPMIRcvBufEntry;
172 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
173 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
174 TYPE_IPMI_BMC_SIMULATOR)
175 struct IPMIBmcSim {
176 IPMIBmc parent;
178 QEMUTimer *timer;
180 uint8_t bmc_global_enables;
181 uint8_t msg_flags;
183 bool watchdog_initialized;
184 uint8_t watchdog_use;
185 uint8_t watchdog_action;
186 uint8_t watchdog_pretimeout; /* In seconds */
187 bool watchdog_expired;
188 uint16_t watchdog_timeout; /* in 100's of milliseconds */
190 bool watchdog_running;
191 bool watchdog_preaction_ran;
192 int64_t watchdog_expiry;
194 uint8_t device_id;
195 uint8_t ipmi_version;
196 uint8_t device_rev;
197 uint8_t fwrev1;
198 uint8_t fwrev2;
199 uint8_t mfg_id[3];
200 uint8_t product_id[2];
202 IPMISel sel;
203 IPMISdr sdr;
204 IPMISensor sensors[MAX_SENSORS];
206 /* Odd netfns are for responses, so we only need the even ones. */
207 const IPMINetfn *netfns[MAX_NETFNS / 2];
209 QemuMutex lock;
210 /* We allow one event in the buffer */
211 uint8_t evtbuf[16];
213 QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
216 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
217 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
218 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
219 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
220 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
221 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
222 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
223 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
224 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
226 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
227 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
228 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
229 #define IPMI_BMC_EVENT_LOG_BIT 3
230 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
231 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
232 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
233 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
234 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
235 (1 << IPMI_BMC_EVENT_LOG_BIT))
236 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
237 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
239 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
240 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
241 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
242 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
243 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
244 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
245 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
246 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
247 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
248 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
249 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
250 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
251 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
252 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
253 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
256 /* Add a byte to the response. */
257 #define IPMI_ADD_RSP_DATA(b) \
258 do { \
259 if (*rsp_len >= max_rsp_len) { \
260 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED; \
261 goto out; \
263 rsp[(*rsp_len)++] = (b); \
264 } while (0)
266 /* Verify that the received command is a certain length. */
267 #define IPMI_CHECK_CMD_LEN(l) \
268 if (cmd_len < l) { \
269 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID; \
270 goto out; \
273 /* Check that the reservation in the command is valid. */
274 #define IPMI_CHECK_RESERVATION(off, r) \
275 do { \
276 if ((cmd[off] | (cmd[off + 1] << 8)) != r) { \
277 rsp[2] = IPMI_CC_INVALID_RESERVATION; \
278 goto out; \
280 } while (0)
283 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
285 static void ipmi_gettime(struct ipmi_time *time)
287 int64_t stime;
289 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
290 time->tv_sec = stime / 1000000000LL;
291 time->tv_nsec = stime % 1000000000LL;
294 static int64_t ipmi_getmonotime(void)
296 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
299 static void ipmi_timeout(void *opaque)
301 IPMIBmcSim *ibs = opaque;
303 ipmi_sim_handle_timeout(ibs);
306 static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
308 unsigned int val;
309 struct ipmi_time now;
311 ipmi_gettime(&now);
312 val = now.tv_sec + ibs->sel.time_offset;
313 ts[0] = val & 0xff;
314 ts[1] = (val >> 8) & 0xff;
315 ts[2] = (val >> 16) & 0xff;
316 ts[3] = (val >> 24) & 0xff;
319 static void sdr_inc_reservation(IPMISdr *sdr)
321 sdr->reservation++;
322 if (sdr->reservation == 0) {
323 sdr->reservation = 1;
327 static int sdr_add_entry(IPMIBmcSim *ibs, const uint8_t *entry,
328 unsigned int len, uint16_t *recid)
330 if ((len < 5) || (len > 255)) {
331 return 1;
334 if (entry[4] != len - 5) {
335 return 1;
338 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
339 ibs->sdr.overflow = 1;
340 return 1;
343 memcpy(ibs->sdr.sdr + ibs->sdr.next_free, entry, len);
344 ibs->sdr.sdr[ibs->sdr.next_free] = ibs->sdr.next_rec_id & 0xff;
345 ibs->sdr.sdr[ibs->sdr.next_free+1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
346 ibs->sdr.sdr[ibs->sdr.next_free+2] = 0x51; /* Conform to IPMI 1.5 spec */
348 if (recid) {
349 *recid = ibs->sdr.next_rec_id;
351 ibs->sdr.next_rec_id++;
352 set_timestamp(ibs, ibs->sdr.last_addition);
353 ibs->sdr.next_free += len;
354 sdr_inc_reservation(&ibs->sdr);
355 return 0;
358 static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
359 unsigned int *retpos, uint16_t *nextrec)
361 unsigned int pos = *retpos;
363 while (pos < sdr->next_free) {
364 uint16_t trec = sdr->sdr[pos] | (sdr->sdr[pos + 1] << 8);
365 unsigned int nextpos = pos + sdr->sdr[pos + 4];
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 goto out;
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));
462 out:
463 return;
466 static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
467 unsigned int bit, unsigned int val,
468 uint8_t evd1, uint8_t evd2, uint8_t evd3)
470 IPMISensor *sens;
471 uint16_t mask;
473 if (sensor >= MAX_SENSORS) {
474 return;
476 if (bit >= 16) {
477 return;
480 mask = (1 << bit);
481 sens = ibs->sensors + sensor;
482 if (val) {
483 sens->states |= mask & sens->states_suppt;
484 if (sens->assert_states & mask) {
485 return; /* Already asserted */
487 sens->assert_states |= mask & sens->assert_suppt;
488 if (sens->assert_enable & mask & sens->assert_states) {
489 /* Send an event on assert */
490 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
492 } else {
493 sens->states &= ~(mask & sens->states_suppt);
494 if (sens->deassert_states & mask) {
495 return; /* Already deasserted */
497 sens->deassert_states |= mask & sens->deassert_suppt;
498 if (sens->deassert_enable & mask & sens->deassert_states) {
499 /* Send an event on deassert */
500 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
505 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
507 unsigned int i, pos;
508 IPMISensor *sens;
510 for (i = 0; i < MAX_SENSORS; i++) {
511 memset(s->sensors + i, 0, sizeof(*sens));
514 pos = 0;
515 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
516 uint8_t *sdr = s->sdr.sdr + pos;
517 unsigned int len = sdr[4];
519 if (len < 20) {
520 continue;
522 if ((sdr[3] < 1) || (sdr[3] > 2)) {
523 continue; /* Not a sensor SDR we set from */
526 if (sdr[7] > MAX_SENSORS) {
527 continue;
529 sens = s->sensors + sdr[7];
531 IPMI_SENSOR_SET_PRESENT(sens, 1);
532 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr[10] >> 6) & 1);
533 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr[10] >> 5) & 1);
534 sens->assert_suppt = sdr[14] | (sdr[15] << 8);
535 sens->deassert_suppt = sdr[16] | (sdr[17] << 8);
536 sens->states_suppt = sdr[18] | (sdr[19] << 8);
537 sens->sensor_type = sdr[12];
538 sens->evt_reading_type_code = sdr[13] & 0x7f;
540 /* Enable all the events that are supported. */
541 sens->assert_enable = sens->assert_suppt;
542 sens->deassert_enable = sens->deassert_suppt;
546 static int ipmi_register_netfn(IPMIBmcSim *s, unsigned int netfn,
547 const IPMINetfn *netfnd)
549 if ((netfn & 1) || (netfn > MAX_NETFNS) || (s->netfns[netfn / 2])) {
550 return -1;
552 s->netfns[netfn / 2] = netfnd;
553 return 0;
556 static void next_timeout(IPMIBmcSim *ibs)
558 int64_t next;
559 if (ibs->watchdog_running) {
560 next = ibs->watchdog_expiry;
561 } else {
562 /* Wait a minute */
563 next = ipmi_getmonotime() + 60 * 1000000000LL;
565 timer_mod_ns(ibs->timer, next);
568 static void ipmi_sim_handle_command(IPMIBmc *b,
569 uint8_t *cmd, unsigned int cmd_len,
570 unsigned int max_cmd_len,
571 uint8_t msg_id)
573 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
574 IPMIInterface *s = ibs->parent.intf;
575 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
576 unsigned int netfn;
577 uint8_t rsp[MAX_IPMI_MSG_SIZE];
578 unsigned int rsp_len_holder = 0;
579 unsigned int *rsp_len = &rsp_len_holder;
580 unsigned int max_rsp_len = sizeof(rsp);
582 /* Set up the response, set the low bit of NETFN. */
583 /* Note that max_rsp_len must be at least 3 */
584 IPMI_ADD_RSP_DATA(cmd[0] | 0x04);
585 IPMI_ADD_RSP_DATA(cmd[1]);
586 IPMI_ADD_RSP_DATA(0); /* Assume success */
588 /* If it's too short or it was truncated, return an error. */
589 if (cmd_len < 2) {
590 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
591 goto out;
593 if (cmd_len > max_cmd_len) {
594 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
595 goto out;
598 if ((cmd[0] & 0x03) != 0) {
599 /* Only have stuff on LUN 0 */
600 rsp[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
601 goto out;
604 netfn = cmd[0] >> 2;
606 /* Odd netfns are not valid, make sure the command is registered */
607 if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
608 (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
609 (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
610 rsp[2] = IPMI_CC_INVALID_CMD;
611 goto out;
614 ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
615 max_rsp_len);
617 out:
618 k->handle_rsp(s, msg_id, rsp, *rsp_len);
620 next_timeout(ibs);
623 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
625 IPMIInterface *s = ibs->parent.intf;
626 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
628 if (!ibs->watchdog_running) {
629 goto out;
632 if (!ibs->watchdog_preaction_ran) {
633 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
634 case IPMI_BMC_WATCHDOG_PRE_NMI:
635 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
636 k->do_hw_op(s, IPMI_SEND_NMI, 0);
637 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
638 0xc8, (2 << 4) | 0xf, 0xff);
639 break;
641 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
642 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
643 k->set_atn(s, 1, attn_irq_enabled(ibs));
644 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
645 0xc8, (3 << 4) | 0xf, 0xff);
646 break;
648 default:
649 goto do_full_expiry;
652 ibs->watchdog_preaction_ran = 1;
653 /* Issued the pretimeout, do the rest of the timeout now. */
654 ibs->watchdog_expiry = ipmi_getmonotime();
655 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
656 goto out;
659 do_full_expiry:
660 ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
661 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
662 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
663 case IPMI_BMC_WATCHDOG_ACTION_NONE:
664 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
665 0xc0, ibs->watchdog_use & 0xf, 0xff);
666 break;
668 case IPMI_BMC_WATCHDOG_ACTION_RESET:
669 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
670 0xc1, ibs->watchdog_use & 0xf, 0xff);
671 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
672 break;
674 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
675 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
676 0xc2, ibs->watchdog_use & 0xf, 0xff);
677 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
678 break;
680 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
681 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
682 0xc3, ibs->watchdog_use & 0xf, 0xff);
683 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
684 break;
687 out:
688 next_timeout(ibs);
691 static void chassis_capabilities(IPMIBmcSim *ibs,
692 uint8_t *cmd, unsigned int cmd_len,
693 uint8_t *rsp, unsigned int *rsp_len,
694 unsigned int max_rsp_len)
696 IPMI_ADD_RSP_DATA(0);
697 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
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 out:
702 return;
705 static void chassis_status(IPMIBmcSim *ibs,
706 uint8_t *cmd, unsigned int cmd_len,
707 uint8_t *rsp, unsigned int *rsp_len,
708 unsigned int max_rsp_len)
710 IPMI_ADD_RSP_DATA(0x61); /* Unknown power restore, power is on */
711 IPMI_ADD_RSP_DATA(0);
712 IPMI_ADD_RSP_DATA(0);
713 IPMI_ADD_RSP_DATA(0);
714 out:
715 return;
718 static void chassis_control(IPMIBmcSim *ibs,
719 uint8_t *cmd, unsigned int cmd_len,
720 uint8_t *rsp, unsigned int *rsp_len,
721 unsigned int max_rsp_len)
723 IPMIInterface *s = ibs->parent.intf;
724 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
726 IPMI_CHECK_CMD_LEN(3);
727 switch (cmd[2] & 0xf) {
728 case 0: /* power down */
729 rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
730 break;
731 case 1: /* power up */
732 rsp[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
733 break;
734 case 2: /* power cycle */
735 rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
736 break;
737 case 3: /* hard reset */
738 rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
739 break;
740 case 4: /* pulse diagnostic interrupt */
741 rsp[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
742 break;
743 case 5: /* soft shutdown via ACPI by overtemp emulation */
744 rsp[2] = k->do_hw_op(s,
745 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0);
746 break;
747 default:
748 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
749 goto out;
751 out:
752 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]);
771 out:
772 return;
775 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
777 IPMIInterface *s = ibs->parent.intf;
778 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
779 bool irqs_on;
781 ibs->bmc_global_enables = val;
783 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
784 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
786 k->set_irq_enable(s, irqs_on);
789 static void cold_reset(IPMIBmcSim *ibs,
790 uint8_t *cmd, unsigned int cmd_len,
791 uint8_t *rsp, unsigned int *rsp_len,
792 unsigned int max_rsp_len)
794 IPMIInterface *s = ibs->parent.intf;
795 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
797 /* Disable all interrupts */
798 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
800 if (k->reset) {
801 k->reset(s, true);
805 static void warm_reset(IPMIBmcSim *ibs,
806 uint8_t *cmd, unsigned int cmd_len,
807 uint8_t *rsp, unsigned int *rsp_len,
808 unsigned int max_rsp_len)
810 IPMIInterface *s = ibs->parent.intf;
811 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
813 if (k->reset) {
814 k->reset(s, false);
818 static void set_bmc_global_enables(IPMIBmcSim *ibs,
819 uint8_t *cmd, unsigned int cmd_len,
820 uint8_t *rsp, unsigned int *rsp_len,
821 unsigned int max_rsp_len)
823 IPMI_CHECK_CMD_LEN(3);
824 set_global_enables(ibs, cmd[2]);
825 out:
826 return;
829 static void get_bmc_global_enables(IPMIBmcSim *ibs,
830 uint8_t *cmd, unsigned int cmd_len,
831 uint8_t *rsp, unsigned int *rsp_len,
832 unsigned int max_rsp_len)
834 IPMI_ADD_RSP_DATA(ibs->bmc_global_enables);
835 out:
836 return;
839 static void clr_msg_flags(IPMIBmcSim *ibs,
840 uint8_t *cmd, unsigned int cmd_len,
841 uint8_t *rsp, unsigned int *rsp_len,
842 unsigned int max_rsp_len)
844 IPMIInterface *s = ibs->parent.intf;
845 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
847 IPMI_CHECK_CMD_LEN(3);
848 ibs->msg_flags &= ~cmd[2];
849 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
850 out:
851 return;
854 static void get_msg_flags(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 IPMI_ADD_RSP_DATA(ibs->msg_flags);
860 out:
861 return;
864 static void read_evt_msg_buf(IPMIBmcSim *ibs,
865 uint8_t *cmd, unsigned int cmd_len,
866 uint8_t *rsp, unsigned int *rsp_len,
867 unsigned int max_rsp_len)
869 IPMIInterface *s = ibs->parent.intf;
870 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
871 unsigned int i;
873 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
874 rsp[2] = 0x80;
875 goto out;
877 for (i = 0; i < 16; i++) {
878 IPMI_ADD_RSP_DATA(ibs->evtbuf[i]);
880 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
881 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
882 out:
883 return;
886 static void get_msg(IPMIBmcSim *ibs,
887 uint8_t *cmd, unsigned int cmd_len,
888 uint8_t *rsp, unsigned int *rsp_len,
889 unsigned int max_rsp_len)
891 IPMIRcvBufEntry *msg;
893 qemu_mutex_lock(&ibs->lock);
894 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
895 rsp[2] = 0x80; /* Queue empty */
896 goto out;
898 rsp[3] = 0; /* Channel 0 */
899 *rsp_len += 1;
900 msg = QTAILQ_FIRST(&ibs->rcvbufs);
901 memcpy(rsp + 4, msg->buf, msg->len);
902 *rsp_len += msg->len;
903 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
904 g_free(msg);
906 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
907 IPMIInterface *s = ibs->parent.intf;
908 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
910 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
911 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
914 out:
915 qemu_mutex_unlock(&ibs->lock);
916 return;
919 static unsigned char
920 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
922 for (; size > 0; size--, data++) {
923 csum += *data;
926 return -csum;
929 static void send_msg(IPMIBmcSim *ibs,
930 uint8_t *cmd, unsigned int cmd_len,
931 uint8_t *rsp, unsigned int *rsp_len,
932 unsigned int max_rsp_len)
934 IPMIInterface *s = ibs->parent.intf;
935 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
936 IPMIRcvBufEntry *msg;
937 uint8_t *buf;
938 uint8_t netfn, rqLun, rsLun, rqSeq;
940 IPMI_CHECK_CMD_LEN(3);
942 if (cmd[2] != 0) {
943 /* We only handle channel 0 with no options */
944 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
945 goto out;
948 IPMI_CHECK_CMD_LEN(10);
949 if (cmd[3] != 0x40) {
950 /* We only emulate a MC at address 0x40. */
951 rsp[2] = 0x83; /* NAK on write */
952 goto out;
955 cmd += 3; /* Skip the header. */
956 cmd_len -= 3;
959 * At this point we "send" the message successfully. Any error will
960 * be returned in the response.
962 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
963 cmd[3] != 0x20) { /* Improper response address */
964 goto out; /* No response */
967 netfn = cmd[1] >> 2;
968 rqLun = cmd[4] & 0x3;
969 rsLun = cmd[1] & 0x3;
970 rqSeq = cmd[4] >> 2;
972 if (rqLun != 2) {
973 /* We only support LUN 2 coming back to us. */
974 goto out;
977 msg = g_malloc(sizeof(*msg));
978 msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
979 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
980 msg->buf[2] = cmd[0]; /* rsSA */
981 msg->buf[3] = (rqSeq << 2) | rsLun;
982 msg->buf[4] = cmd[5]; /* Cmd */
983 msg->buf[5] = 0; /* Completion Code */
984 msg->len = 6;
986 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
987 /* Not a command we handle. */
988 msg->buf[5] = IPMI_CC_INVALID_CMD;
989 goto end_msg;
992 buf = msg->buf + msg->len; /* After the CC */
993 buf[0] = 0;
994 buf[1] = 0;
995 buf[2] = 0;
996 buf[3] = 0;
997 buf[4] = 0x51;
998 buf[5] = 0;
999 buf[6] = 0;
1000 buf[7] = 0;
1001 buf[8] = 0;
1002 buf[9] = 0;
1003 buf[10] = 0;
1004 msg->len += 11;
1006 end_msg:
1007 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1008 msg->len++;
1009 qemu_mutex_lock(&ibs->lock);
1010 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1011 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1012 k->set_atn(s, 1, attn_irq_enabled(ibs));
1013 qemu_mutex_unlock(&ibs->lock);
1015 out:
1016 return;
1019 static void do_watchdog_reset(IPMIBmcSim *ibs)
1021 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1022 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1023 ibs->watchdog_running = 0;
1024 return;
1026 ibs->watchdog_preaction_ran = 0;
1029 /* Timeout is in tenths of a second, offset is in seconds */
1030 ibs->watchdog_expiry = ipmi_getmonotime();
1031 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1032 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1033 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1035 ibs->watchdog_running = 1;
1038 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1039 uint8_t *cmd, unsigned int cmd_len,
1040 uint8_t *rsp, unsigned int *rsp_len,
1041 unsigned int max_rsp_len)
1043 if (!ibs->watchdog_initialized) {
1044 rsp[2] = 0x80;
1045 goto out;
1047 do_watchdog_reset(ibs);
1048 out:
1049 return;
1052 static void set_watchdog_timer(IPMIBmcSim *ibs,
1053 uint8_t *cmd, unsigned int cmd_len,
1054 uint8_t *rsp, unsigned int *rsp_len,
1055 unsigned int max_rsp_len)
1057 IPMIInterface *s = ibs->parent.intf;
1058 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1059 unsigned int val;
1061 IPMI_CHECK_CMD_LEN(8);
1062 val = cmd[2] & 0x7; /* Validate use */
1063 if (val == 0 || val > 5) {
1064 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1065 goto out;
1067 val = cmd[3] & 0x7; /* Validate action */
1068 switch (val) {
1069 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1070 break;
1072 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1073 rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
1074 break;
1076 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1077 rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
1078 break;
1080 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1081 rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
1082 break;
1084 default:
1085 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1087 if (rsp[2]) {
1088 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1089 goto out;
1092 val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1093 switch (val) {
1094 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1095 case IPMI_BMC_WATCHDOG_PRE_NONE:
1096 break;
1098 case IPMI_BMC_WATCHDOG_PRE_NMI:
1099 if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1100 /* NMI not supported. */
1101 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1102 goto out;
1104 default:
1105 /* We don't support PRE_SMI */
1106 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1107 goto out;
1110 ibs->watchdog_initialized = 1;
1111 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1112 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1113 ibs->watchdog_pretimeout = cmd[4];
1114 ibs->watchdog_expired &= ~cmd[5];
1115 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1116 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1117 do_watchdog_reset(ibs);
1118 } else {
1119 ibs->watchdog_running = 0;
1121 out:
1122 return;
1125 static void get_watchdog_timer(IPMIBmcSim *ibs,
1126 uint8_t *cmd, unsigned int cmd_len,
1127 uint8_t *rsp, unsigned int *rsp_len,
1128 unsigned int max_rsp_len)
1130 IPMI_ADD_RSP_DATA(ibs->watchdog_use);
1131 IPMI_ADD_RSP_DATA(ibs->watchdog_action);
1132 IPMI_ADD_RSP_DATA(ibs->watchdog_pretimeout);
1133 IPMI_ADD_RSP_DATA(ibs->watchdog_expired);
1134 if (ibs->watchdog_running) {
1135 long timeout;
1136 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1137 / 100000000);
1138 IPMI_ADD_RSP_DATA(timeout & 0xff);
1139 IPMI_ADD_RSP_DATA((timeout >> 8) & 0xff);
1140 } else {
1141 IPMI_ADD_RSP_DATA(0);
1142 IPMI_ADD_RSP_DATA(0);
1144 out:
1145 return;
1148 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1149 uint8_t *cmd, unsigned int cmd_len,
1150 uint8_t *rsp, unsigned int *rsp_len,
1151 unsigned int max_rsp_len)
1153 unsigned int i;
1155 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 spec */
1156 IPMI_ADD_RSP_DATA(ibs->sdr.next_rec_id & 0xff);
1157 IPMI_ADD_RSP_DATA((ibs->sdr.next_rec_id >> 8) & 0xff);
1158 IPMI_ADD_RSP_DATA((MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1159 IPMI_ADD_RSP_DATA(((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1160 for (i = 0; i < 4; i++) {
1161 IPMI_ADD_RSP_DATA(ibs->sdr.last_addition[i]);
1163 for (i = 0; i < 4; i++) {
1164 IPMI_ADD_RSP_DATA(ibs->sdr.last_clear[i]);
1166 /* Only modal support, reserve supported */
1167 IPMI_ADD_RSP_DATA((ibs->sdr.overflow << 7) | 0x22);
1168 out:
1169 return;
1172 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1173 uint8_t *cmd, unsigned int cmd_len,
1174 uint8_t *rsp, unsigned int *rsp_len,
1175 unsigned int max_rsp_len)
1177 IPMI_ADD_RSP_DATA(ibs->sdr.reservation & 0xff);
1178 IPMI_ADD_RSP_DATA((ibs->sdr.reservation >> 8) & 0xff);
1179 out:
1180 return;
1183 static void get_sdr(IPMIBmcSim *ibs,
1184 uint8_t *cmd, unsigned int cmd_len,
1185 uint8_t *rsp, unsigned int *rsp_len,
1186 unsigned int max_rsp_len)
1188 unsigned int pos;
1189 uint16_t nextrec;
1191 IPMI_CHECK_CMD_LEN(8);
1192 if (cmd[6]) {
1193 IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
1195 pos = 0;
1196 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1197 &pos, &nextrec)) {
1198 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1199 goto out;
1201 if (cmd[6] > (ibs->sdr.sdr[pos + 4])) {
1202 rsp[2] = IPMI_CC_PARM_OUT_OF_RANGE;
1203 goto out;
1206 IPMI_ADD_RSP_DATA(nextrec & 0xff);
1207 IPMI_ADD_RSP_DATA((nextrec >> 8) & 0xff);
1209 if (cmd[7] == 0xff) {
1210 cmd[7] = ibs->sdr.sdr[pos + 4] - cmd[6];
1213 if ((cmd[7] + *rsp_len) > max_rsp_len) {
1214 rsp[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
1215 goto out;
1217 memcpy(rsp + *rsp_len, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1218 *rsp_len += cmd[7];
1219 out:
1220 return;
1223 static void add_sdr(IPMIBmcSim *ibs,
1224 uint8_t *cmd, unsigned int cmd_len,
1225 uint8_t *rsp, unsigned int *rsp_len,
1226 unsigned int max_rsp_len)
1228 uint16_t recid;
1230 if (sdr_add_entry(ibs, cmd + 2, cmd_len - 2, &recid)) {
1231 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1232 goto out;
1234 IPMI_ADD_RSP_DATA(recid & 0xff);
1235 IPMI_ADD_RSP_DATA((recid >> 8) & 0xff);
1236 out:
1237 return;
1240 static void clear_sdr_rep(IPMIBmcSim *ibs,
1241 uint8_t *cmd, unsigned int cmd_len,
1242 uint8_t *rsp, unsigned int *rsp_len,
1243 unsigned int max_rsp_len)
1245 IPMI_CHECK_CMD_LEN(8);
1246 IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
1247 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1248 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1249 goto out;
1251 if (cmd[7] == 0xaa) {
1252 ibs->sdr.next_free = 0;
1253 ibs->sdr.overflow = 0;
1254 set_timestamp(ibs, ibs->sdr.last_clear);
1255 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1256 sdr_inc_reservation(&ibs->sdr);
1257 } else if (cmd[7] == 0) {
1258 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1259 } else {
1260 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1261 goto out;
1263 out:
1264 return;
1267 static void get_sel_info(IPMIBmcSim *ibs,
1268 uint8_t *cmd, unsigned int cmd_len,
1269 uint8_t *rsp, unsigned int *rsp_len,
1270 unsigned int max_rsp_len)
1272 unsigned int i, val;
1274 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 */
1275 IPMI_ADD_RSP_DATA(ibs->sel.next_free & 0xff);
1276 IPMI_ADD_RSP_DATA((ibs->sel.next_free >> 8) & 0xff);
1277 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1278 IPMI_ADD_RSP_DATA(val & 0xff);
1279 IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
1280 for (i = 0; i < 4; i++) {
1281 IPMI_ADD_RSP_DATA(ibs->sel.last_addition[i]);
1283 for (i = 0; i < 4; i++) {
1284 IPMI_ADD_RSP_DATA(ibs->sel.last_clear[i]);
1286 /* Only support Reserve SEL */
1287 IPMI_ADD_RSP_DATA((ibs->sel.overflow << 7) | 0x02);
1288 out:
1289 return;
1292 static void reserve_sel(IPMIBmcSim *ibs,
1293 uint8_t *cmd, unsigned int cmd_len,
1294 uint8_t *rsp, unsigned int *rsp_len,
1295 unsigned int max_rsp_len)
1297 IPMI_ADD_RSP_DATA(ibs->sel.reservation & 0xff);
1298 IPMI_ADD_RSP_DATA((ibs->sel.reservation >> 8) & 0xff);
1299 out:
1300 return;
1303 static void get_sel_entry(IPMIBmcSim *ibs,
1304 uint8_t *cmd, unsigned int cmd_len,
1305 uint8_t *rsp, unsigned int *rsp_len,
1306 unsigned int max_rsp_len)
1308 unsigned int val;
1310 IPMI_CHECK_CMD_LEN(8);
1311 if (cmd[6]) {
1312 IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
1314 if (ibs->sel.next_free == 0) {
1315 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1316 goto out;
1318 if (cmd[6] > 15) {
1319 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1320 goto out;
1322 if (cmd[7] == 0xff) {
1323 cmd[7] = 16;
1324 } else if ((cmd[7] + cmd[6]) > 16) {
1325 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1326 goto out;
1327 } else {
1328 cmd[7] += cmd[6];
1331 val = cmd[4] | (cmd[5] << 8);
1332 if (val == 0xffff) {
1333 val = ibs->sel.next_free - 1;
1334 } else if (val >= ibs->sel.next_free) {
1335 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1336 goto out;
1338 if ((val + 1) == ibs->sel.next_free) {
1339 IPMI_ADD_RSP_DATA(0xff);
1340 IPMI_ADD_RSP_DATA(0xff);
1341 } else {
1342 IPMI_ADD_RSP_DATA((val + 1) & 0xff);
1343 IPMI_ADD_RSP_DATA(((val + 1) >> 8) & 0xff);
1345 for (; cmd[6] < cmd[7]; cmd[6]++) {
1346 IPMI_ADD_RSP_DATA(ibs->sel.sel[val][cmd[6]]);
1348 out:
1349 return;
1352 static void add_sel_entry(IPMIBmcSim *ibs,
1353 uint8_t *cmd, unsigned int cmd_len,
1354 uint8_t *rsp, unsigned int *rsp_len,
1355 unsigned int max_rsp_len)
1357 IPMI_CHECK_CMD_LEN(18);
1358 if (sel_add_event(ibs, cmd + 2)) {
1359 rsp[2] = IPMI_CC_OUT_OF_SPACE;
1360 goto out;
1362 /* sel_add_event fills in the record number. */
1363 IPMI_ADD_RSP_DATA(cmd[2]);
1364 IPMI_ADD_RSP_DATA(cmd[3]);
1365 out:
1366 return;
1369 static void clear_sel(IPMIBmcSim *ibs,
1370 uint8_t *cmd, unsigned int cmd_len,
1371 uint8_t *rsp, unsigned int *rsp_len,
1372 unsigned int max_rsp_len)
1374 IPMI_CHECK_CMD_LEN(8);
1375 IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
1376 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1377 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1378 goto out;
1380 if (cmd[7] == 0xaa) {
1381 ibs->sel.next_free = 0;
1382 ibs->sel.overflow = 0;
1383 set_timestamp(ibs, ibs->sdr.last_clear);
1384 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1385 sel_inc_reservation(&ibs->sel);
1386 } else if (cmd[7] == 0) {
1387 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1388 } else {
1389 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1390 goto out;
1392 out:
1393 return;
1396 static void get_sel_time(IPMIBmcSim *ibs,
1397 uint8_t *cmd, unsigned int cmd_len,
1398 uint8_t *rsp, unsigned int *rsp_len,
1399 unsigned int max_rsp_len)
1401 uint32_t val;
1402 struct ipmi_time now;
1404 ipmi_gettime(&now);
1405 val = now.tv_sec + ibs->sel.time_offset;
1406 IPMI_ADD_RSP_DATA(val & 0xff);
1407 IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
1408 IPMI_ADD_RSP_DATA((val >> 16) & 0xff);
1409 IPMI_ADD_RSP_DATA((val >> 24) & 0xff);
1410 out:
1411 return;
1414 static void set_sel_time(IPMIBmcSim *ibs,
1415 uint8_t *cmd, unsigned int cmd_len,
1416 uint8_t *rsp, unsigned int *rsp_len,
1417 unsigned int max_rsp_len)
1419 uint32_t val;
1420 struct ipmi_time now;
1422 IPMI_CHECK_CMD_LEN(6);
1423 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1424 ipmi_gettime(&now);
1425 ibs->sel.time_offset = now.tv_sec - ((long) val);
1426 out:
1427 return;
1430 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1431 uint8_t *cmd, unsigned int cmd_len,
1432 uint8_t *rsp, unsigned int *rsp_len,
1433 unsigned int max_rsp_len)
1435 IPMISensor *sens;
1437 IPMI_CHECK_CMD_LEN(4);
1438 if ((cmd[2] > MAX_SENSORS) ||
1439 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1440 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1441 goto out;
1443 sens = ibs->sensors + cmd[2];
1444 switch ((cmd[3] >> 4) & 0x3) {
1445 case 0: /* Do not change */
1446 break;
1447 case 1: /* Enable bits */
1448 if (cmd_len > 4) {
1449 sens->assert_enable |= cmd[4];
1451 if (cmd_len > 5) {
1452 sens->assert_enable |= cmd[5] << 8;
1454 if (cmd_len > 6) {
1455 sens->deassert_enable |= cmd[6];
1457 if (cmd_len > 7) {
1458 sens->deassert_enable |= cmd[7] << 8;
1460 break;
1461 case 2: /* Disable bits */
1462 if (cmd_len > 4) {
1463 sens->assert_enable &= ~cmd[4];
1465 if (cmd_len > 5) {
1466 sens->assert_enable &= ~(cmd[5] << 8);
1468 if (cmd_len > 6) {
1469 sens->deassert_enable &= ~cmd[6];
1471 if (cmd_len > 7) {
1472 sens->deassert_enable &= ~(cmd[7] << 8);
1474 break;
1475 case 3:
1476 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1477 goto out;
1479 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1480 out:
1481 return;
1484 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1485 uint8_t *cmd, unsigned int cmd_len,
1486 uint8_t *rsp, unsigned int *rsp_len,
1487 unsigned int max_rsp_len)
1489 IPMISensor *sens;
1491 IPMI_CHECK_CMD_LEN(3);
1492 if ((cmd[2] > MAX_SENSORS) ||
1493 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1494 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1495 goto out;
1497 sens = ibs->sensors + cmd[2];
1498 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1499 IPMI_ADD_RSP_DATA(sens->assert_enable & 0xff);
1500 IPMI_ADD_RSP_DATA((sens->assert_enable >> 8) & 0xff);
1501 IPMI_ADD_RSP_DATA(sens->deassert_enable & 0xff);
1502 IPMI_ADD_RSP_DATA((sens->deassert_enable >> 8) & 0xff);
1503 out:
1504 return;
1507 static void rearm_sensor_evts(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(4);
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 goto out;
1520 sens = ibs->sensors + cmd[2];
1522 if ((cmd[3] & 0x80) == 0) {
1523 /* Just clear everything */
1524 sens->states = 0;
1525 goto out;
1527 out:
1528 return;
1531 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1532 uint8_t *cmd, unsigned int cmd_len,
1533 uint8_t *rsp, unsigned int *rsp_len,
1534 unsigned int max_rsp_len)
1536 IPMISensor *sens;
1538 IPMI_CHECK_CMD_LEN(3);
1539 if ((cmd[2] > MAX_SENSORS) ||
1540 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1541 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1542 goto out;
1544 sens = ibs->sensors + cmd[2];
1545 IPMI_ADD_RSP_DATA(sens->reading);
1546 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1547 IPMI_ADD_RSP_DATA(sens->assert_states & 0xff);
1548 IPMI_ADD_RSP_DATA((sens->assert_states >> 8) & 0xff);
1549 IPMI_ADD_RSP_DATA(sens->deassert_states & 0xff);
1550 IPMI_ADD_RSP_DATA((sens->deassert_states >> 8) & 0xff);
1551 out:
1552 return;
1555 static void get_sensor_reading(IPMIBmcSim *ibs,
1556 uint8_t *cmd, unsigned int cmd_len,
1557 uint8_t *rsp, unsigned int *rsp_len,
1558 unsigned int max_rsp_len)
1560 IPMISensor *sens;
1562 IPMI_CHECK_CMD_LEN(3);
1563 if ((cmd[2] > MAX_SENSORS) ||
1564 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1565 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1566 goto out;
1568 sens = ibs->sensors + cmd[2];
1569 IPMI_ADD_RSP_DATA(sens->reading);
1570 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1571 IPMI_ADD_RSP_DATA(sens->states & 0xff);
1572 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1573 IPMI_ADD_RSP_DATA((sens->states >> 8) & 0xff);
1575 out:
1576 return;
1579 static const IPMICmdHandler chassis_cmds[IPMI_NETFN_CHASSIS_MAXCMD] = {
1580 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = chassis_capabilities,
1581 [IPMI_CMD_GET_CHASSIS_STATUS] = chassis_status,
1582 [IPMI_CMD_CHASSIS_CONTROL] = chassis_control
1584 static const IPMINetfn chassis_netfn = {
1585 .cmd_nums = IPMI_NETFN_CHASSIS_MAXCMD,
1586 .cmd_handlers = chassis_cmds
1589 static const IPMICmdHandler
1590 sensor_event_cmds[IPMI_NETFN_SENSOR_EVENT_MAXCMD] = {
1591 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = set_sensor_evt_enable,
1592 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = get_sensor_evt_enable,
1593 [IPMI_CMD_REARM_SENSOR_EVTS] = rearm_sensor_evts,
1594 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = get_sensor_evt_status,
1595 [IPMI_CMD_GET_SENSOR_READING] = get_sensor_reading
1597 static const IPMINetfn sensor_event_netfn = {
1598 .cmd_nums = IPMI_NETFN_SENSOR_EVENT_MAXCMD,
1599 .cmd_handlers = sensor_event_cmds
1602 static const IPMICmdHandler app_cmds[IPMI_NETFN_APP_MAXCMD] = {
1603 [IPMI_CMD_GET_DEVICE_ID] = get_device_id,
1604 [IPMI_CMD_COLD_RESET] = cold_reset,
1605 [IPMI_CMD_WARM_RESET] = warm_reset,
1606 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = set_bmc_global_enables,
1607 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = get_bmc_global_enables,
1608 [IPMI_CMD_CLR_MSG_FLAGS] = clr_msg_flags,
1609 [IPMI_CMD_GET_MSG_FLAGS] = get_msg_flags,
1610 [IPMI_CMD_GET_MSG] = get_msg,
1611 [IPMI_CMD_SEND_MSG] = send_msg,
1612 [IPMI_CMD_READ_EVT_MSG_BUF] = read_evt_msg_buf,
1613 [IPMI_CMD_RESET_WATCHDOG_TIMER] = reset_watchdog_timer,
1614 [IPMI_CMD_SET_WATCHDOG_TIMER] = set_watchdog_timer,
1615 [IPMI_CMD_GET_WATCHDOG_TIMER] = get_watchdog_timer,
1617 static const IPMINetfn app_netfn = {
1618 .cmd_nums = IPMI_NETFN_APP_MAXCMD,
1619 .cmd_handlers = app_cmds
1622 static const IPMICmdHandler storage_cmds[IPMI_NETFN_STORAGE_MAXCMD] = {
1623 [IPMI_CMD_GET_SDR_REP_INFO] = get_sdr_rep_info,
1624 [IPMI_CMD_RESERVE_SDR_REP] = reserve_sdr_rep,
1625 [IPMI_CMD_GET_SDR] = get_sdr,
1626 [IPMI_CMD_ADD_SDR] = add_sdr,
1627 [IPMI_CMD_CLEAR_SDR_REP] = clear_sdr_rep,
1628 [IPMI_CMD_GET_SEL_INFO] = get_sel_info,
1629 [IPMI_CMD_RESERVE_SEL] = reserve_sel,
1630 [IPMI_CMD_GET_SEL_ENTRY] = get_sel_entry,
1631 [IPMI_CMD_ADD_SEL_ENTRY] = add_sel_entry,
1632 [IPMI_CMD_CLEAR_SEL] = clear_sel,
1633 [IPMI_CMD_GET_SEL_TIME] = get_sel_time,
1634 [IPMI_CMD_SET_SEL_TIME] = set_sel_time,
1637 static const IPMINetfn storage_netfn = {
1638 .cmd_nums = IPMI_NETFN_STORAGE_MAXCMD,
1639 .cmd_handlers = storage_cmds
1642 static void register_cmds(IPMIBmcSim *s)
1644 ipmi_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
1645 ipmi_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
1646 ipmi_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
1647 ipmi_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
1650 static const uint8_t init_sdrs[] = {
1651 /* Watchdog device */
1652 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1653 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1656 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1657 /* End */
1658 0xff, 0xff, 0x00, 0x00, 0x00
1661 static const VMStateDescription vmstate_ipmi_sim = {
1662 .name = TYPE_IPMI_BMC_SIMULATOR,
1663 .version_id = 1,
1664 .minimum_version_id = 1,
1665 .fields = (VMStateField[]) {
1666 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
1667 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
1668 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
1669 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
1670 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
1671 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
1672 VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
1673 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
1674 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
1675 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
1676 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
1677 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
1678 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
1679 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
1680 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
1681 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
1682 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
1683 IPMIBmcSim),
1684 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
1685 VMSTATE_END_OF_LIST()
1689 static void ipmi_sim_init(Object *obj)
1691 IPMIBmc *b = IPMI_BMC(obj);
1692 unsigned int i;
1693 unsigned int recid;
1694 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
1696 qemu_mutex_init(&ibs->lock);
1697 QTAILQ_INIT(&ibs->rcvbufs);
1699 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
1700 ibs->device_id = 0x20;
1701 ibs->ipmi_version = 0x02; /* IPMI 2.0 */
1702 for (i = 0; i < 4; i++) {
1703 ibs->sel.last_addition[i] = 0xff;
1704 ibs->sel.last_clear[i] = 0xff;
1705 ibs->sdr.last_addition[i] = 0xff;
1706 ibs->sdr.last_clear[i] = 0xff;
1709 for (i = 0;;) {
1710 int len;
1711 if ((i + 5) > sizeof(init_sdrs)) {
1712 error_report("Problem with recid 0x%4.4x: \n", i);
1713 return;
1715 len = init_sdrs[i + 4];
1716 recid = init_sdrs[i] | (init_sdrs[i + 1] << 8);
1717 if (recid == 0xffff) {
1718 break;
1720 if ((i + len + 5) > sizeof(init_sdrs)) {
1721 error_report("Problem with recid 0x%4.4x\n", i);
1722 return;
1724 sdr_add_entry(ibs, init_sdrs + i, len, NULL);
1725 i += len + 5;
1728 ipmi_init_sensors_from_sdrs(ibs);
1729 register_cmds(ibs);
1731 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
1733 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
1736 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
1738 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
1740 bk->handle_command = ipmi_sim_handle_command;
1743 static const TypeInfo ipmi_sim_type = {
1744 .name = TYPE_IPMI_BMC_SIMULATOR,
1745 .parent = TYPE_IPMI_BMC,
1746 .instance_size = sizeof(IPMIBmcSim),
1747 .instance_init = ipmi_sim_init,
1748 .class_init = ipmi_sim_class_init,
1751 static void ipmi_sim_register_types(void)
1753 type_register_static(&ipmi_sim_type);
1756 type_init(ipmi_sim_register_types)