hw/arm/smmuv3: Remove spurious error messages on IOVA invalidations
[qemu/ar7.git] / hw / ipmi / ipmi_bmc_sim.c
blob246a6d390c17776ac8207ccfe629d67d382baed3
1 /*
2 * IPMI BMC emulation
4 * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "qemu/osdep.h"
26 #include "sysemu/sysemu.h"
27 #include "qemu/timer.h"
28 #include "hw/ipmi/ipmi.h"
29 #include "qemu/error-report.h"
30 #include "qemu/module.h"
31 #include "hw/loader.h"
32 #include "hw/qdev-properties.h"
33 #include "migration/vmstate.h"
35 #define IPMI_NETFN_CHASSIS 0x00
37 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
38 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
39 #define IPMI_CMD_CHASSIS_CONTROL 0x02
40 #define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09
42 #define IPMI_NETFN_SENSOR_EVENT 0x04
44 #define IPMI_CMD_PLATFORM_EVENT_MSG 0x02
45 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
46 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
47 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
48 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
49 #define IPMI_CMD_GET_SENSOR_READING 0x2d
50 #define IPMI_CMD_SET_SENSOR_TYPE 0x2e
51 #define IPMI_CMD_GET_SENSOR_TYPE 0x2f
53 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
55 #define IPMI_CMD_GET_DEVICE_ID 0x01
56 #define IPMI_CMD_COLD_RESET 0x02
57 #define IPMI_CMD_WARM_RESET 0x03
58 #define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
59 #define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
60 #define IPMI_CMD_GET_DEVICE_GUID 0x08
61 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
62 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
63 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
64 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
65 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
66 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
67 #define IPMI_CMD_GET_MSG_FLAGS 0x31
68 #define IPMI_CMD_GET_MSG 0x33
69 #define IPMI_CMD_SEND_MSG 0x34
70 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
72 #define IPMI_NETFN_STORAGE 0x0a
74 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
75 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
76 #define IPMI_CMD_RESERVE_SDR_REP 0x22
77 #define IPMI_CMD_GET_SDR 0x23
78 #define IPMI_CMD_ADD_SDR 0x24
79 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
80 #define IPMI_CMD_DELETE_SDR 0x26
81 #define IPMI_CMD_CLEAR_SDR_REP 0x27
82 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
83 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
84 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
85 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
86 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
87 #define IPMI_CMD_GET_FRU_AREA_INFO 0x10
88 #define IPMI_CMD_READ_FRU_DATA 0x11
89 #define IPMI_CMD_WRITE_FRU_DATA 0x12
90 #define IPMI_CMD_GET_SEL_INFO 0x40
91 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
92 #define IPMI_CMD_RESERVE_SEL 0x42
93 #define IPMI_CMD_GET_SEL_ENTRY 0x43
94 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
95 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
96 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
97 #define IPMI_CMD_CLEAR_SEL 0x47
98 #define IPMI_CMD_GET_SEL_TIME 0x48
99 #define IPMI_CMD_SET_SEL_TIME 0x49
102 /* Same as a timespec struct. */
103 struct ipmi_time {
104 long tv_sec;
105 long tv_nsec;
108 #define MAX_SEL_SIZE 128
110 typedef struct IPMISel {
111 uint8_t sel[MAX_SEL_SIZE][16];
112 unsigned int next_free;
113 long time_offset;
114 uint16_t reservation;
115 uint8_t last_addition[4];
116 uint8_t last_clear[4];
117 uint8_t overflow;
118 } IPMISel;
120 #define MAX_SDR_SIZE 16384
122 typedef struct IPMISdr {
123 uint8_t sdr[MAX_SDR_SIZE];
124 unsigned int next_free;
125 uint16_t next_rec_id;
126 uint16_t reservation;
127 uint8_t last_addition[4];
128 uint8_t last_clear[4];
129 uint8_t overflow;
130 } IPMISdr;
132 typedef struct IPMIFru {
133 char *filename;
134 unsigned int nentries;
135 uint16_t areasize;
136 uint8_t *data;
137 } IPMIFru;
139 typedef struct IPMISensor {
140 uint8_t status;
141 uint8_t reading;
142 uint16_t states_suppt;
143 uint16_t assert_suppt;
144 uint16_t deassert_suppt;
145 uint16_t states;
146 uint16_t assert_states;
147 uint16_t deassert_states;
148 uint16_t assert_enable;
149 uint16_t deassert_enable;
150 uint8_t sensor_type;
151 uint8_t evt_reading_type_code;
152 } IPMISensor;
153 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
154 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
155 !!(v))
156 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
157 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
158 ((!!(v)) << 6))
159 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
160 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
161 ((!!(v)) << 7))
162 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
163 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
164 (v & 0xc0))
165 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
167 #define MAX_SENSORS 20
168 #define IPMI_WATCHDOG_SENSOR 0
170 typedef struct IPMIBmcSim IPMIBmcSim;
171 typedef struct RspBuffer RspBuffer;
173 #define MAX_NETFNS 64
175 typedef struct IPMICmdHandler {
176 void (*cmd_handler)(IPMIBmcSim *s,
177 uint8_t *cmd, unsigned int cmd_len,
178 RspBuffer *rsp);
179 unsigned int cmd_len_min;
180 } IPMICmdHandler;
182 typedef struct IPMINetfn {
183 unsigned int cmd_nums;
184 const IPMICmdHandler *cmd_handlers;
185 } IPMINetfn;
187 typedef struct IPMIRcvBufEntry {
188 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
189 uint8_t len;
190 uint8_t buf[MAX_IPMI_MSG_SIZE];
191 } IPMIRcvBufEntry;
193 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
194 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
195 TYPE_IPMI_BMC_SIMULATOR)
196 struct IPMIBmcSim {
197 IPMIBmc parent;
199 QEMUTimer *timer;
201 uint8_t bmc_global_enables;
202 uint8_t msg_flags;
204 bool watchdog_initialized;
205 uint8_t watchdog_use;
206 uint8_t watchdog_action;
207 uint8_t watchdog_pretimeout; /* In seconds */
208 bool watchdog_expired;
209 uint16_t watchdog_timeout; /* in 100's of milliseconds */
211 bool watchdog_running;
212 bool watchdog_preaction_ran;
213 int64_t watchdog_expiry;
215 uint8_t device_id;
216 uint8_t ipmi_version;
217 uint8_t device_rev;
218 uint8_t fwrev1;
219 uint8_t fwrev2;
220 uint32_t mfg_id;
221 uint16_t product_id;
223 uint8_t restart_cause;
225 uint8_t acpi_power_state[2];
226 uint8_t uuid[16];
228 IPMISel sel;
229 IPMISdr sdr;
230 IPMIFru fru;
231 IPMISensor sensors[MAX_SENSORS];
232 char *sdr_filename;
234 /* Odd netfns are for responses, so we only need the even ones. */
235 const IPMINetfn *netfns[MAX_NETFNS / 2];
237 /* We allow one event in the buffer */
238 uint8_t evtbuf[16];
240 QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
243 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
244 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
245 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
246 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
247 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
248 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
249 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
250 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
251 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
253 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
254 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
255 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
256 #define IPMI_BMC_EVENT_LOG_BIT 3
257 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
258 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
259 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
260 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
261 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
262 (1 << IPMI_BMC_EVENT_LOG_BIT))
263 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
264 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
266 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
267 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
268 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
269 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
270 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
271 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
272 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
273 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
274 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
275 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
276 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
277 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
278 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
279 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
280 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
282 struct RspBuffer {
283 uint8_t buffer[MAX_IPMI_MSG_SIZE];
284 unsigned int len;
287 #define RSP_BUFFER_INITIALIZER { }
289 static inline void rsp_buffer_set_error(RspBuffer *rsp, uint8_t byte)
291 rsp->buffer[2] = byte;
294 /* Add a byte to the response. */
295 static inline void rsp_buffer_push(RspBuffer *rsp, uint8_t byte)
297 if (rsp->len >= sizeof(rsp->buffer)) {
298 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
299 return;
301 rsp->buffer[rsp->len++] = byte;
304 static inline void rsp_buffer_pushmore(RspBuffer *rsp, uint8_t *bytes,
305 unsigned int n)
307 if (rsp->len + n >= sizeof(rsp->buffer)) {
308 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
309 return;
312 memcpy(&rsp->buffer[rsp->len], bytes, n);
313 rsp->len += n;
316 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
318 static void ipmi_gettime(struct ipmi_time *time)
320 int64_t stime;
322 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
323 time->tv_sec = stime / 1000000000LL;
324 time->tv_nsec = stime % 1000000000LL;
327 static int64_t ipmi_getmonotime(void)
329 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
332 static void ipmi_timeout(void *opaque)
334 IPMIBmcSim *ibs = opaque;
336 ipmi_sim_handle_timeout(ibs);
339 static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
341 unsigned int val;
342 struct ipmi_time now;
344 ipmi_gettime(&now);
345 val = now.tv_sec + ibs->sel.time_offset;
346 ts[0] = val & 0xff;
347 ts[1] = (val >> 8) & 0xff;
348 ts[2] = (val >> 16) & 0xff;
349 ts[3] = (val >> 24) & 0xff;
352 static void sdr_inc_reservation(IPMISdr *sdr)
354 sdr->reservation++;
355 if (sdr->reservation == 0) {
356 sdr->reservation = 1;
360 static int sdr_add_entry(IPMIBmcSim *ibs,
361 const struct ipmi_sdr_header *sdrh_entry,
362 unsigned int len, uint16_t *recid)
364 struct ipmi_sdr_header *sdrh =
365 (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
367 if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
368 return 1;
371 if (ipmi_sdr_length(sdrh_entry) != len) {
372 return 1;
375 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
376 ibs->sdr.overflow = 1;
377 return 1;
380 memcpy(sdrh, sdrh_entry, len);
381 sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff;
382 sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
383 sdrh->sdr_version = 0x51; /* Conform to IPMI 1.5 spec */
385 if (recid) {
386 *recid = ibs->sdr.next_rec_id;
388 ibs->sdr.next_rec_id++;
389 set_timestamp(ibs, ibs->sdr.last_addition);
390 ibs->sdr.next_free += len;
391 sdr_inc_reservation(&ibs->sdr);
392 return 0;
395 static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
396 unsigned int *retpos, uint16_t *nextrec)
398 unsigned int pos = *retpos;
400 while (pos < sdr->next_free) {
401 struct ipmi_sdr_header *sdrh =
402 (struct ipmi_sdr_header *) &sdr->sdr[pos];
403 uint16_t trec = ipmi_sdr_recid(sdrh);
404 unsigned int nextpos = pos + ipmi_sdr_length(sdrh);
406 if (trec == recid) {
407 if (nextrec) {
408 if (nextpos >= sdr->next_free) {
409 *nextrec = 0xffff;
410 } else {
411 *nextrec = (sdr->sdr[nextpos] |
412 (sdr->sdr[nextpos + 1] << 8));
415 *retpos = pos;
416 return 0;
418 pos = nextpos;
420 return 1;
423 int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
424 const struct ipmi_sdr_compact **sdr, uint16_t *nextrec)
427 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
428 unsigned int pos;
430 pos = 0;
431 if (sdr_find_entry(&ibs->sdr, recid, &pos, nextrec)) {
432 return -1;
435 *sdr = (const struct ipmi_sdr_compact *) &ibs->sdr.sdr[pos];
436 return 0;
439 static void sel_inc_reservation(IPMISel *sel)
441 sel->reservation++;
442 if (sel->reservation == 0) {
443 sel->reservation = 1;
447 /* Returns 1 if the SEL is full and can't hold the event. */
448 static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
450 uint8_t ts[4];
452 event[0] = 0xff;
453 event[1] = 0xff;
454 set_timestamp(ibs, ts);
455 if (event[2] < 0xe0) { /* Don't set timestamps for type 0xe0-0xff. */
456 memcpy(event + 3, ts, 4);
458 if (ibs->sel.next_free == MAX_SEL_SIZE) {
459 ibs->sel.overflow = 1;
460 return 1;
462 event[0] = ibs->sel.next_free & 0xff;
463 event[1] = (ibs->sel.next_free >> 8) & 0xff;
464 memcpy(ibs->sel.last_addition, ts, 4);
465 memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
466 ibs->sel.next_free++;
467 sel_inc_reservation(&ibs->sel);
468 return 0;
471 static int attn_set(IPMIBmcSim *ibs)
473 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
474 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
475 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
478 static int attn_irq_enabled(IPMIBmcSim *ibs)
480 return (IPMI_BMC_MSG_INTS_ON(ibs) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs))
481 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
482 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
485 void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log)
487 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
488 IPMIInterface *s = ibs->parent.intf;
489 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
491 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
492 return;
495 if (log && IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
496 sel_add_event(ibs, evt);
499 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
500 goto out;
503 memcpy(ibs->evtbuf, evt, 16);
504 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
505 k->set_atn(s, 1, attn_irq_enabled(ibs));
506 out:
507 return;
509 static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
510 uint8_t evd1, uint8_t evd2, uint8_t evd3)
512 IPMIInterface *s = ibs->parent.intf;
513 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
514 uint8_t evt[16];
515 IPMISensor *sens = ibs->sensors + sens_num;
517 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
518 return;
520 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
521 return;
524 evt[2] = 0x2; /* System event record */
525 evt[7] = ibs->parent.slave_addr;
526 evt[8] = 0;
527 evt[9] = 0x04; /* Format version */
528 evt[10] = sens->sensor_type;
529 evt[11] = sens_num;
530 evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
531 evt[13] = evd1;
532 evt[14] = evd2;
533 evt[15] = evd3;
535 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
536 sel_add_event(ibs, evt);
539 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
540 return;
543 memcpy(ibs->evtbuf, evt, 16);
544 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
545 k->set_atn(s, 1, attn_irq_enabled(ibs));
548 static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
549 unsigned int bit, unsigned int val,
550 uint8_t evd1, uint8_t evd2, uint8_t evd3)
552 IPMISensor *sens;
553 uint16_t mask;
555 if (sensor >= MAX_SENSORS) {
556 return;
558 if (bit >= 16) {
559 return;
562 mask = (1 << bit);
563 sens = ibs->sensors + sensor;
564 if (val) {
565 sens->states |= mask & sens->states_suppt;
566 if (sens->assert_states & mask) {
567 return; /* Already asserted */
569 sens->assert_states |= mask & sens->assert_suppt;
570 if (sens->assert_enable & mask & sens->assert_states) {
571 /* Send an event on assert */
572 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
574 } else {
575 sens->states &= ~(mask & sens->states_suppt);
576 if (sens->deassert_states & mask) {
577 return; /* Already deasserted */
579 sens->deassert_states |= mask & sens->deassert_suppt;
580 if (sens->deassert_enable & mask & sens->deassert_states) {
581 /* Send an event on deassert */
582 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
587 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
589 unsigned int i, pos;
590 IPMISensor *sens;
592 for (i = 0; i < MAX_SENSORS; i++) {
593 memset(s->sensors + i, 0, sizeof(*sens));
596 pos = 0;
597 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
598 struct ipmi_sdr_compact *sdr =
599 (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
600 unsigned int len = sdr->header.rec_length;
602 if (len < 20) {
603 continue;
605 if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
606 continue; /* Not a sensor SDR we set from */
609 if (sdr->sensor_owner_number >= MAX_SENSORS) {
610 continue;
612 sens = s->sensors + sdr->sensor_owner_number;
614 IPMI_SENSOR_SET_PRESENT(sens, 1);
615 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
616 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
617 sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
618 sens->deassert_suppt =
619 sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
620 sens->states_suppt =
621 sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
622 sens->sensor_type = sdr->sensor_type;
623 sens->evt_reading_type_code = sdr->reading_type & 0x7f;
625 /* Enable all the events that are supported. */
626 sens->assert_enable = sens->assert_suppt;
627 sens->deassert_enable = sens->deassert_suppt;
631 static int ipmi_register_netfn(IPMIBmcSim *s, unsigned int netfn,
632 const IPMINetfn *netfnd)
634 if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
635 return -1;
637 s->netfns[netfn / 2] = netfnd;
638 return 0;
641 static const IPMICmdHandler *ipmi_get_handler(IPMIBmcSim *ibs,
642 unsigned int netfn,
643 unsigned int cmd)
645 const IPMICmdHandler *hdl;
647 if (netfn & 1 || netfn >= MAX_NETFNS || !ibs->netfns[netfn / 2]) {
648 return NULL;
651 if (cmd >= ibs->netfns[netfn / 2]->cmd_nums) {
652 return NULL;
655 hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd];
656 if (!hdl->cmd_handler) {
657 return NULL;
660 return hdl;
663 static void next_timeout(IPMIBmcSim *ibs)
665 int64_t next;
666 if (ibs->watchdog_running) {
667 next = ibs->watchdog_expiry;
668 } else {
669 /* Wait a minute */
670 next = ipmi_getmonotime() + 60 * 1000000000LL;
672 timer_mod_ns(ibs->timer, next);
675 static void ipmi_sim_handle_command(IPMIBmc *b,
676 uint8_t *cmd, unsigned int cmd_len,
677 unsigned int max_cmd_len,
678 uint8_t msg_id)
680 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
681 IPMIInterface *s = ibs->parent.intf;
682 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
683 const IPMICmdHandler *hdl;
684 RspBuffer rsp = RSP_BUFFER_INITIALIZER;
686 /* Set up the response, set the low bit of NETFN. */
687 /* Note that max_rsp_len must be at least 3 */
688 if (sizeof(rsp.buffer) < 3) {
689 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
690 goto out;
693 rsp_buffer_push(&rsp, cmd[0] | 0x04);
694 rsp_buffer_push(&rsp, cmd[1]);
695 rsp_buffer_push(&rsp, 0); /* Assume success */
697 /* If it's too short or it was truncated, return an error. */
698 if (cmd_len < 2) {
699 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
700 goto out;
702 if (cmd_len > max_cmd_len) {
703 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
704 goto out;
707 if ((cmd[0] & 0x03) != 0) {
708 /* Only have stuff on LUN 0 */
709 rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN);
710 goto out;
713 hdl = ipmi_get_handler(ibs, cmd[0] >> 2, cmd[1]);
714 if (!hdl) {
715 rsp_buffer_set_error(&rsp, IPMI_CC_INVALID_CMD);
716 goto out;
719 if (cmd_len < hdl->cmd_len_min) {
720 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
721 goto out;
724 hdl->cmd_handler(ibs, cmd, cmd_len, &rsp);
726 out:
727 k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
729 next_timeout(ibs);
732 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
734 IPMIInterface *s = ibs->parent.intf;
735 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
737 if (!ibs->watchdog_running) {
738 goto out;
741 if (!ibs->watchdog_preaction_ran) {
742 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
743 case IPMI_BMC_WATCHDOG_PRE_NMI:
744 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
745 k->do_hw_op(s, IPMI_SEND_NMI, 0);
746 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
747 0xc8, (2 << 4) | 0xf, 0xff);
748 break;
750 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
751 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
752 k->set_atn(s, 1, attn_irq_enabled(ibs));
753 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
754 0xc8, (3 << 4) | 0xf, 0xff);
755 break;
757 default:
758 goto do_full_expiry;
761 ibs->watchdog_preaction_ran = 1;
762 /* Issued the pretimeout, do the rest of the timeout now. */
763 ibs->watchdog_expiry = ipmi_getmonotime();
764 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
765 goto out;
768 do_full_expiry:
769 ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
770 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
771 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
772 case IPMI_BMC_WATCHDOG_ACTION_NONE:
773 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
774 0xc0, ibs->watchdog_use & 0xf, 0xff);
775 break;
777 case IPMI_BMC_WATCHDOG_ACTION_RESET:
778 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
779 0xc1, ibs->watchdog_use & 0xf, 0xff);
780 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
781 break;
783 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
784 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
785 0xc2, ibs->watchdog_use & 0xf, 0xff);
786 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
787 break;
789 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
790 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
791 0xc3, ibs->watchdog_use & 0xf, 0xff);
792 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
793 break;
796 out:
797 next_timeout(ibs);
800 static void chassis_capabilities(IPMIBmcSim *ibs,
801 uint8_t *cmd, unsigned int cmd_len,
802 RspBuffer *rsp)
804 rsp_buffer_push(rsp, 0);
805 rsp_buffer_push(rsp, ibs->parent.slave_addr);
806 rsp_buffer_push(rsp, ibs->parent.slave_addr);
807 rsp_buffer_push(rsp, ibs->parent.slave_addr);
808 rsp_buffer_push(rsp, ibs->parent.slave_addr);
811 static void chassis_status(IPMIBmcSim *ibs,
812 uint8_t *cmd, unsigned int cmd_len,
813 RspBuffer *rsp)
815 rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */
816 rsp_buffer_push(rsp, 0);
817 rsp_buffer_push(rsp, 0);
818 rsp_buffer_push(rsp, 0);
821 static void chassis_control(IPMIBmcSim *ibs,
822 uint8_t *cmd, unsigned int cmd_len,
823 RspBuffer *rsp)
825 IPMIInterface *s = ibs->parent.intf;
826 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
828 switch (cmd[2] & 0xf) {
829 case 0: /* power down */
830 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0));
831 break;
832 case 1: /* power up */
833 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0));
834 break;
835 case 2: /* power cycle */
836 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0));
837 break;
838 case 3: /* hard reset */
839 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0));
840 break;
841 case 4: /* pulse diagnostic interrupt */
842 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0));
843 break;
844 case 5: /* soft shutdown via ACPI by overtemp emulation */
845 rsp_buffer_set_error(rsp, k->do_hw_op(s,
846 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0));
847 break;
848 default:
849 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
850 return;
854 static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
855 uint8_t *cmd, unsigned int cmd_len,
856 RspBuffer *rsp)
859 rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */
860 rsp_buffer_push(rsp, 0); /* Channel 0 */
863 static void get_device_id(IPMIBmcSim *ibs,
864 uint8_t *cmd, unsigned int cmd_len,
865 RspBuffer *rsp)
867 rsp_buffer_push(rsp, ibs->device_id);
868 rsp_buffer_push(rsp, ibs->device_rev & 0xf);
869 rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
870 rsp_buffer_push(rsp, ibs->fwrev2);
871 rsp_buffer_push(rsp, ibs->ipmi_version);
872 rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */
873 rsp_buffer_push(rsp, ibs->mfg_id & 0xff);
874 rsp_buffer_push(rsp, (ibs->mfg_id >> 8) & 0xff);
875 rsp_buffer_push(rsp, (ibs->mfg_id >> 16) & 0xff);
876 rsp_buffer_push(rsp, ibs->product_id & 0xff);
877 rsp_buffer_push(rsp, (ibs->product_id >> 8) & 0xff);
880 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
882 IPMIInterface *s = ibs->parent.intf;
883 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
884 bool irqs_on;
886 ibs->bmc_global_enables = val;
888 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
889 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
891 k->set_irq_enable(s, irqs_on);
894 static void cold_reset(IPMIBmcSim *ibs,
895 uint8_t *cmd, unsigned int cmd_len,
896 RspBuffer *rsp)
898 IPMIInterface *s = ibs->parent.intf;
899 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
901 /* Disable all interrupts */
902 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
904 if (k->reset) {
905 k->reset(s, true);
909 static void warm_reset(IPMIBmcSim *ibs,
910 uint8_t *cmd, unsigned int cmd_len,
911 RspBuffer *rsp)
913 IPMIInterface *s = ibs->parent.intf;
914 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
916 if (k->reset) {
917 k->reset(s, false);
920 static void set_acpi_power_state(IPMIBmcSim *ibs,
921 uint8_t *cmd, unsigned int cmd_len,
922 RspBuffer *rsp)
924 ibs->acpi_power_state[0] = cmd[2];
925 ibs->acpi_power_state[1] = cmd[3];
928 static void get_acpi_power_state(IPMIBmcSim *ibs,
929 uint8_t *cmd, unsigned int cmd_len,
930 RspBuffer *rsp)
932 rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
933 rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
936 static void get_device_guid(IPMIBmcSim *ibs,
937 uint8_t *cmd, unsigned int cmd_len,
938 RspBuffer *rsp)
940 unsigned int i;
942 for (i = 0; i < 16; i++) {
943 rsp_buffer_push(rsp, ibs->uuid[i]);
947 static void set_bmc_global_enables(IPMIBmcSim *ibs,
948 uint8_t *cmd, unsigned int cmd_len,
949 RspBuffer *rsp)
951 set_global_enables(ibs, cmd[2]);
954 static void get_bmc_global_enables(IPMIBmcSim *ibs,
955 uint8_t *cmd, unsigned int cmd_len,
956 RspBuffer *rsp)
958 rsp_buffer_push(rsp, ibs->bmc_global_enables);
961 static void clr_msg_flags(IPMIBmcSim *ibs,
962 uint8_t *cmd, unsigned int cmd_len,
963 RspBuffer *rsp)
965 IPMIInterface *s = ibs->parent.intf;
966 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
968 ibs->msg_flags &= ~cmd[2];
969 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
972 static void get_msg_flags(IPMIBmcSim *ibs,
973 uint8_t *cmd, unsigned int cmd_len,
974 RspBuffer *rsp)
976 rsp_buffer_push(rsp, ibs->msg_flags);
979 static void read_evt_msg_buf(IPMIBmcSim *ibs,
980 uint8_t *cmd, unsigned int cmd_len,
981 RspBuffer *rsp)
983 IPMIInterface *s = ibs->parent.intf;
984 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
985 unsigned int i;
987 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
988 rsp_buffer_set_error(rsp, 0x80);
989 return;
991 for (i = 0; i < 16; i++) {
992 rsp_buffer_push(rsp, ibs->evtbuf[i]);
994 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
995 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
998 static void get_msg(IPMIBmcSim *ibs,
999 uint8_t *cmd, unsigned int cmd_len,
1000 RspBuffer *rsp)
1002 IPMIRcvBufEntry *msg;
1004 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
1005 rsp_buffer_set_error(rsp, 0x80); /* Queue empty */
1006 goto out;
1008 rsp_buffer_push(rsp, 0); /* Channel 0 */
1009 msg = QTAILQ_FIRST(&ibs->rcvbufs);
1010 rsp_buffer_pushmore(rsp, msg->buf, msg->len);
1011 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
1012 g_free(msg);
1014 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
1015 IPMIInterface *s = ibs->parent.intf;
1016 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1018 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1019 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
1022 out:
1023 return;
1026 static unsigned char
1027 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
1029 for (; size > 0; size--, data++) {
1030 csum += *data;
1033 return -csum;
1036 static void send_msg(IPMIBmcSim *ibs,
1037 uint8_t *cmd, unsigned int cmd_len,
1038 RspBuffer *rsp)
1040 IPMIInterface *s = ibs->parent.intf;
1041 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1042 IPMIRcvBufEntry *msg;
1043 uint8_t *buf;
1044 uint8_t netfn, rqLun, rsLun, rqSeq;
1046 if (cmd[2] != 0) {
1047 /* We only handle channel 0 with no options */
1048 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1049 return;
1052 if (cmd_len < 10) {
1053 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
1054 return;
1057 if (cmd[3] != 0x40) {
1058 /* We only emulate a MC at address 0x40. */
1059 rsp_buffer_set_error(rsp, 0x83); /* NAK on write */
1060 return;
1063 cmd += 3; /* Skip the header. */
1064 cmd_len -= 3;
1067 * At this point we "send" the message successfully. Any error will
1068 * be returned in the response.
1070 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
1071 cmd[3] != 0x20) { /* Improper response address */
1072 return; /* No response */
1075 netfn = cmd[1] >> 2;
1076 rqLun = cmd[4] & 0x3;
1077 rsLun = cmd[1] & 0x3;
1078 rqSeq = cmd[4] >> 2;
1080 if (rqLun != 2) {
1081 /* We only support LUN 2 coming back to us. */
1082 return;
1085 msg = g_malloc(sizeof(*msg));
1086 msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
1087 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
1088 msg->buf[2] = cmd[0]; /* rsSA */
1089 msg->buf[3] = (rqSeq << 2) | rsLun;
1090 msg->buf[4] = cmd[5]; /* Cmd */
1091 msg->buf[5] = 0; /* Completion Code */
1092 msg->len = 6;
1094 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
1095 /* Not a command we handle. */
1096 msg->buf[5] = IPMI_CC_INVALID_CMD;
1097 goto end_msg;
1100 buf = msg->buf + msg->len; /* After the CC */
1101 buf[0] = 0;
1102 buf[1] = 0;
1103 buf[2] = 0;
1104 buf[3] = 0;
1105 buf[4] = 0x51;
1106 buf[5] = 0;
1107 buf[6] = 0;
1108 buf[7] = 0;
1109 buf[8] = 0;
1110 buf[9] = 0;
1111 buf[10] = 0;
1112 msg->len += 11;
1114 end_msg:
1115 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1116 msg->len++;
1117 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1118 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1119 k->set_atn(s, 1, attn_irq_enabled(ibs));
1122 static void do_watchdog_reset(IPMIBmcSim *ibs)
1124 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1125 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1126 ibs->watchdog_running = 0;
1127 return;
1129 ibs->watchdog_preaction_ran = 0;
1132 /* Timeout is in tenths of a second, offset is in seconds */
1133 ibs->watchdog_expiry = ipmi_getmonotime();
1134 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1135 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1136 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1138 ibs->watchdog_running = 1;
1141 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1142 uint8_t *cmd, unsigned int cmd_len,
1143 RspBuffer *rsp)
1145 if (!ibs->watchdog_initialized) {
1146 rsp_buffer_set_error(rsp, 0x80);
1147 return;
1149 do_watchdog_reset(ibs);
1152 static void set_watchdog_timer(IPMIBmcSim *ibs,
1153 uint8_t *cmd, unsigned int cmd_len,
1154 RspBuffer *rsp)
1156 IPMIInterface *s = ibs->parent.intf;
1157 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1158 unsigned int val;
1160 val = cmd[2] & 0x7; /* Validate use */
1161 if (val == 0 || val > 5) {
1162 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1163 return;
1165 val = cmd[3] & 0x7; /* Validate action */
1166 switch (val) {
1167 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1168 break;
1170 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1171 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1));
1172 break;
1174 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1175 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1));
1176 break;
1178 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1179 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1));
1180 break;
1182 default:
1183 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1185 if (rsp->buffer[2]) {
1186 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1187 return;
1190 val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1191 switch (val) {
1192 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1193 case IPMI_BMC_WATCHDOG_PRE_NONE:
1194 break;
1196 case IPMI_BMC_WATCHDOG_PRE_NMI:
1197 if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1198 /* NMI not supported. */
1199 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1200 return;
1202 break;
1204 default:
1205 /* We don't support PRE_SMI */
1206 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1207 return;
1210 ibs->watchdog_initialized = 1;
1211 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1212 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1213 ibs->watchdog_pretimeout = cmd[4];
1214 ibs->watchdog_expired &= ~cmd[5];
1215 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1216 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1217 do_watchdog_reset(ibs);
1218 } else {
1219 ibs->watchdog_running = 0;
1223 static void get_watchdog_timer(IPMIBmcSim *ibs,
1224 uint8_t *cmd, unsigned int cmd_len,
1225 RspBuffer *rsp)
1227 rsp_buffer_push(rsp, ibs->watchdog_use);
1228 rsp_buffer_push(rsp, ibs->watchdog_action);
1229 rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
1230 rsp_buffer_push(rsp, ibs->watchdog_expired);
1231 if (ibs->watchdog_running) {
1232 long timeout;
1233 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1234 / 100000000);
1235 rsp_buffer_push(rsp, timeout & 0xff);
1236 rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
1237 } else {
1238 rsp_buffer_push(rsp, 0);
1239 rsp_buffer_push(rsp, 0);
1243 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1244 uint8_t *cmd, unsigned int cmd_len,
1245 RspBuffer *rsp)
1247 unsigned int i;
1249 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */
1250 rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
1251 rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
1252 rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1253 rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1254 for (i = 0; i < 4; i++) {
1255 rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
1257 for (i = 0; i < 4; i++) {
1258 rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
1260 /* Only modal support, reserve supported */
1261 rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
1264 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1265 uint8_t *cmd, unsigned int cmd_len,
1266 RspBuffer *rsp)
1268 rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
1269 rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
1272 static void get_sdr(IPMIBmcSim *ibs,
1273 uint8_t *cmd, unsigned int cmd_len,
1274 RspBuffer *rsp)
1276 unsigned int pos;
1277 uint16_t nextrec;
1278 struct ipmi_sdr_header *sdrh;
1280 if (cmd[6]) {
1281 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1282 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1283 return;
1287 pos = 0;
1288 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1289 &pos, &nextrec)) {
1290 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1291 return;
1294 sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1296 if (cmd[6] > ipmi_sdr_length(sdrh)) {
1297 rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE);
1298 return;
1301 rsp_buffer_push(rsp, nextrec & 0xff);
1302 rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
1304 if (cmd[7] == 0xff) {
1305 cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1308 if ((cmd[7] + rsp->len) > sizeof(rsp->buffer)) {
1309 rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES);
1310 return;
1313 rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1316 static void add_sdr(IPMIBmcSim *ibs,
1317 uint8_t *cmd, unsigned int cmd_len,
1318 RspBuffer *rsp)
1320 uint16_t recid;
1321 struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1323 if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1324 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1325 return;
1327 rsp_buffer_push(rsp, recid & 0xff);
1328 rsp_buffer_push(rsp, (recid >> 8) & 0xff);
1331 static void clear_sdr_rep(IPMIBmcSim *ibs,
1332 uint8_t *cmd, unsigned int cmd_len,
1333 RspBuffer *rsp)
1335 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1336 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1337 return;
1340 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1341 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1342 return;
1344 if (cmd[7] == 0xaa) {
1345 ibs->sdr.next_free = 0;
1346 ibs->sdr.overflow = 0;
1347 set_timestamp(ibs, ibs->sdr.last_clear);
1348 rsp_buffer_push(rsp, 1); /* Erasure complete */
1349 sdr_inc_reservation(&ibs->sdr);
1350 } else if (cmd[7] == 0) {
1351 rsp_buffer_push(rsp, 1); /* Erasure complete */
1352 } else {
1353 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1354 return;
1358 static void get_sel_info(IPMIBmcSim *ibs,
1359 uint8_t *cmd, unsigned int cmd_len,
1360 RspBuffer *rsp)
1362 unsigned int i, val;
1364 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */
1365 rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
1366 rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
1367 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1368 rsp_buffer_push(rsp, val & 0xff);
1369 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1370 for (i = 0; i < 4; i++) {
1371 rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
1373 for (i = 0; i < 4; i++) {
1374 rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
1376 /* Only support Reserve SEL */
1377 rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
1380 static void get_fru_area_info(IPMIBmcSim *ibs,
1381 uint8_t *cmd, unsigned int cmd_len,
1382 RspBuffer *rsp)
1384 uint8_t fruid;
1385 uint16_t fru_entry_size;
1387 fruid = cmd[2];
1389 if (fruid >= ibs->fru.nentries) {
1390 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1391 return;
1394 fru_entry_size = ibs->fru.areasize;
1396 rsp_buffer_push(rsp, fru_entry_size & 0xff);
1397 rsp_buffer_push(rsp, fru_entry_size >> 8 & 0xff);
1398 rsp_buffer_push(rsp, 0x0);
1401 static void read_fru_data(IPMIBmcSim *ibs,
1402 uint8_t *cmd, unsigned int cmd_len,
1403 RspBuffer *rsp)
1405 uint8_t fruid;
1406 uint16_t offset;
1407 int i;
1408 uint8_t *fru_entry;
1409 unsigned int count;
1411 fruid = cmd[2];
1412 offset = (cmd[3] | cmd[4] << 8);
1414 if (fruid >= ibs->fru.nentries) {
1415 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1416 return;
1419 if (offset >= ibs->fru.areasize - 1) {
1420 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1421 return;
1424 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1426 count = MIN(cmd[5], ibs->fru.areasize - offset);
1428 rsp_buffer_push(rsp, count & 0xff);
1429 for (i = 0; i < count; i++) {
1430 rsp_buffer_push(rsp, fru_entry[offset + i]);
1434 static void write_fru_data(IPMIBmcSim *ibs,
1435 uint8_t *cmd, unsigned int cmd_len,
1436 RspBuffer *rsp)
1438 uint8_t fruid;
1439 uint16_t offset;
1440 uint8_t *fru_entry;
1441 unsigned int count;
1443 fruid = cmd[2];
1444 offset = (cmd[3] | cmd[4] << 8);
1446 if (fruid >= ibs->fru.nentries) {
1447 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1448 return;
1451 if (offset >= ibs->fru.areasize - 1) {
1452 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1453 return;
1456 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1458 count = MIN(cmd_len - 5, ibs->fru.areasize - offset);
1460 memcpy(fru_entry + offset, cmd + 5, count);
1462 rsp_buffer_push(rsp, count & 0xff);
1465 static void reserve_sel(IPMIBmcSim *ibs,
1466 uint8_t *cmd, unsigned int cmd_len,
1467 RspBuffer *rsp)
1469 rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
1470 rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
1473 static void get_sel_entry(IPMIBmcSim *ibs,
1474 uint8_t *cmd, unsigned int cmd_len,
1475 RspBuffer *rsp)
1477 unsigned int val;
1479 if (cmd[6]) {
1480 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1481 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1482 return;
1485 if (ibs->sel.next_free == 0) {
1486 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1487 return;
1489 if (cmd[6] > 15) {
1490 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1491 return;
1493 if (cmd[7] == 0xff) {
1494 cmd[7] = 16;
1495 } else if ((cmd[7] + cmd[6]) > 16) {
1496 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1497 return;
1498 } else {
1499 cmd[7] += cmd[6];
1502 val = cmd[4] | (cmd[5] << 8);
1503 if (val == 0xffff) {
1504 val = ibs->sel.next_free - 1;
1505 } else if (val >= ibs->sel.next_free) {
1506 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1507 return;
1509 if ((val + 1) == ibs->sel.next_free) {
1510 rsp_buffer_push(rsp, 0xff);
1511 rsp_buffer_push(rsp, 0xff);
1512 } else {
1513 rsp_buffer_push(rsp, (val + 1) & 0xff);
1514 rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
1516 for (; cmd[6] < cmd[7]; cmd[6]++) {
1517 rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
1521 static void add_sel_entry(IPMIBmcSim *ibs,
1522 uint8_t *cmd, unsigned int cmd_len,
1523 RspBuffer *rsp)
1525 if (sel_add_event(ibs, cmd + 2)) {
1526 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1527 return;
1529 /* sel_add_event fills in the record number. */
1530 rsp_buffer_push(rsp, cmd[2]);
1531 rsp_buffer_push(rsp, cmd[3]);
1534 static void clear_sel(IPMIBmcSim *ibs,
1535 uint8_t *cmd, unsigned int cmd_len,
1536 RspBuffer *rsp)
1538 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1539 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1540 return;
1543 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1544 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1545 return;
1547 if (cmd[7] == 0xaa) {
1548 ibs->sel.next_free = 0;
1549 ibs->sel.overflow = 0;
1550 set_timestamp(ibs, ibs->sdr.last_clear);
1551 rsp_buffer_push(rsp, 1); /* Erasure complete */
1552 sel_inc_reservation(&ibs->sel);
1553 } else if (cmd[7] == 0) {
1554 rsp_buffer_push(rsp, 1); /* Erasure complete */
1555 } else {
1556 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1557 return;
1561 static void get_sel_time(IPMIBmcSim *ibs,
1562 uint8_t *cmd, unsigned int cmd_len,
1563 RspBuffer *rsp)
1565 uint32_t val;
1566 struct ipmi_time now;
1568 ipmi_gettime(&now);
1569 val = now.tv_sec + ibs->sel.time_offset;
1570 rsp_buffer_push(rsp, val & 0xff);
1571 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1572 rsp_buffer_push(rsp, (val >> 16) & 0xff);
1573 rsp_buffer_push(rsp, (val >> 24) & 0xff);
1576 static void set_sel_time(IPMIBmcSim *ibs,
1577 uint8_t *cmd, unsigned int cmd_len,
1578 RspBuffer *rsp)
1580 uint32_t val;
1581 struct ipmi_time now;
1583 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1584 ipmi_gettime(&now);
1585 ibs->sel.time_offset = now.tv_sec - ((long) val);
1588 static void platform_event_msg(IPMIBmcSim *ibs,
1589 uint8_t *cmd, unsigned int cmd_len,
1590 RspBuffer *rsp)
1592 uint8_t event[16];
1594 event[2] = 2; /* System event record */
1595 event[7] = cmd[2]; /* Generator ID */
1596 event[8] = 0;
1597 event[9] = cmd[3]; /* EvMRev */
1598 event[10] = cmd[4]; /* Sensor type */
1599 event[11] = cmd[5]; /* Sensor number */
1600 event[12] = cmd[6]; /* Event dir / Event type */
1601 event[13] = cmd[7]; /* Event data 1 */
1602 event[14] = cmd[8]; /* Event data 2 */
1603 event[15] = cmd[9]; /* Event data 3 */
1605 if (sel_add_event(ibs, event)) {
1606 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1610 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1611 uint8_t *cmd, unsigned int cmd_len,
1612 RspBuffer *rsp)
1614 IPMISensor *sens;
1616 if ((cmd[2] >= MAX_SENSORS) ||
1617 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1618 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1619 return;
1621 sens = ibs->sensors + cmd[2];
1622 switch ((cmd[3] >> 4) & 0x3) {
1623 case 0: /* Do not change */
1624 break;
1625 case 1: /* Enable bits */
1626 if (cmd_len > 4) {
1627 sens->assert_enable |= cmd[4];
1629 if (cmd_len > 5) {
1630 sens->assert_enable |= cmd[5] << 8;
1632 if (cmd_len > 6) {
1633 sens->deassert_enable |= cmd[6];
1635 if (cmd_len > 7) {
1636 sens->deassert_enable |= cmd[7] << 8;
1638 break;
1639 case 2: /* Disable bits */
1640 if (cmd_len > 4) {
1641 sens->assert_enable &= ~cmd[4];
1643 if (cmd_len > 5) {
1644 sens->assert_enable &= ~(cmd[5] << 8);
1646 if (cmd_len > 6) {
1647 sens->deassert_enable &= ~cmd[6];
1649 if (cmd_len > 7) {
1650 sens->deassert_enable &= ~(cmd[7] << 8);
1652 break;
1653 case 3:
1654 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1655 return;
1657 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1660 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1661 uint8_t *cmd, unsigned int cmd_len,
1662 RspBuffer *rsp)
1664 IPMISensor *sens;
1666 if ((cmd[2] >= MAX_SENSORS) ||
1667 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1668 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1669 return;
1671 sens = ibs->sensors + cmd[2];
1672 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1673 rsp_buffer_push(rsp, sens->assert_enable & 0xff);
1674 rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
1675 rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
1676 rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
1679 static void rearm_sensor_evts(IPMIBmcSim *ibs,
1680 uint8_t *cmd, unsigned int cmd_len,
1681 RspBuffer *rsp)
1683 IPMISensor *sens;
1685 if ((cmd[2] >= MAX_SENSORS) ||
1686 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1687 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1688 return;
1690 sens = ibs->sensors + cmd[2];
1692 if ((cmd[3] & 0x80) == 0) {
1693 /* Just clear everything */
1694 sens->states = 0;
1695 return;
1699 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1700 uint8_t *cmd, unsigned int cmd_len,
1701 RspBuffer *rsp)
1703 IPMISensor *sens;
1705 if ((cmd[2] >= MAX_SENSORS) ||
1706 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1707 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1708 return;
1710 sens = ibs->sensors + cmd[2];
1711 rsp_buffer_push(rsp, sens->reading);
1712 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1713 rsp_buffer_push(rsp, sens->assert_states & 0xff);
1714 rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
1715 rsp_buffer_push(rsp, sens->deassert_states & 0xff);
1716 rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
1719 static void get_sensor_reading(IPMIBmcSim *ibs,
1720 uint8_t *cmd, unsigned int cmd_len,
1721 RspBuffer *rsp)
1723 IPMISensor *sens;
1725 if ((cmd[2] >= MAX_SENSORS) ||
1726 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1727 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1728 return;
1730 sens = ibs->sensors + cmd[2];
1731 rsp_buffer_push(rsp, sens->reading);
1732 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1733 rsp_buffer_push(rsp, sens->states & 0xff);
1734 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1735 rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
1739 static void set_sensor_type(IPMIBmcSim *ibs,
1740 uint8_t *cmd, unsigned int cmd_len,
1741 RspBuffer *rsp)
1743 IPMISensor *sens;
1746 if ((cmd[2] >= MAX_SENSORS) ||
1747 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1748 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1749 return;
1751 sens = ibs->sensors + cmd[2];
1752 sens->sensor_type = cmd[3];
1753 sens->evt_reading_type_code = cmd[4] & 0x7f;
1756 static void get_sensor_type(IPMIBmcSim *ibs,
1757 uint8_t *cmd, unsigned int cmd_len,
1758 RspBuffer *rsp)
1760 IPMISensor *sens;
1763 if ((cmd[2] >= MAX_SENSORS) ||
1764 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1765 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1766 return;
1768 sens = ibs->sensors + cmd[2];
1769 rsp_buffer_push(rsp, sens->sensor_type);
1770 rsp_buffer_push(rsp, sens->evt_reading_type_code);
1774 static const IPMICmdHandler chassis_cmds[] = {
1775 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
1776 [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
1777 [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
1778 [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
1780 static const IPMINetfn chassis_netfn = {
1781 .cmd_nums = ARRAY_SIZE(chassis_cmds),
1782 .cmd_handlers = chassis_cmds
1785 static const IPMICmdHandler sensor_event_cmds[] = {
1786 [IPMI_CMD_PLATFORM_EVENT_MSG] = { platform_event_msg, 10 },
1787 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
1788 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
1789 [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
1790 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
1791 [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
1792 [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
1793 [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
1795 static const IPMINetfn sensor_event_netfn = {
1796 .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
1797 .cmd_handlers = sensor_event_cmds
1800 static const IPMICmdHandler app_cmds[] = {
1801 [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
1802 [IPMI_CMD_COLD_RESET] = { cold_reset },
1803 [IPMI_CMD_WARM_RESET] = { warm_reset },
1804 [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
1805 [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
1806 [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
1807 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
1808 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
1809 [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
1810 [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
1811 [IPMI_CMD_GET_MSG] = { get_msg },
1812 [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
1813 [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
1814 [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
1815 [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
1816 [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
1818 static const IPMINetfn app_netfn = {
1819 .cmd_nums = ARRAY_SIZE(app_cmds),
1820 .cmd_handlers = app_cmds
1823 static const IPMICmdHandler storage_cmds[] = {
1824 [IPMI_CMD_GET_FRU_AREA_INFO] = { get_fru_area_info, 3 },
1825 [IPMI_CMD_READ_FRU_DATA] = { read_fru_data, 5 },
1826 [IPMI_CMD_WRITE_FRU_DATA] = { write_fru_data, 5 },
1827 [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
1828 [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
1829 [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
1830 [IPMI_CMD_ADD_SDR] = { add_sdr },
1831 [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
1832 [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
1833 [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
1834 [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
1835 [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
1836 [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
1837 [IPMI_CMD_GET_SEL_TIME] = { get_sel_time },
1838 [IPMI_CMD_SET_SEL_TIME] = { set_sel_time, 6 },
1841 static const IPMINetfn storage_netfn = {
1842 .cmd_nums = ARRAY_SIZE(storage_cmds),
1843 .cmd_handlers = storage_cmds
1846 static void register_cmds(IPMIBmcSim *s)
1848 ipmi_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
1849 ipmi_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
1850 ipmi_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
1851 ipmi_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
1854 static uint8_t init_sdrs[] = {
1855 /* Watchdog device */
1856 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1857 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1858 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1859 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1860 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1863 static void ipmi_sdr_init(IPMIBmcSim *ibs)
1865 unsigned int i;
1866 int len;
1867 size_t sdrs_size;
1868 uint8_t *sdrs;
1870 sdrs_size = sizeof(init_sdrs);
1871 sdrs = init_sdrs;
1872 if (ibs->sdr_filename &&
1873 !g_file_get_contents(ibs->sdr_filename, (gchar **) &sdrs, &sdrs_size,
1874 NULL)) {
1875 error_report("failed to load sdr file '%s'", ibs->sdr_filename);
1876 sdrs_size = sizeof(init_sdrs);
1877 sdrs = init_sdrs;
1880 for (i = 0; i < sdrs_size; i += len) {
1881 struct ipmi_sdr_header *sdrh;
1883 if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
1884 error_report("Problem with recid 0x%4.4x", i);
1885 break;
1887 sdrh = (struct ipmi_sdr_header *) &sdrs[i];
1888 len = ipmi_sdr_length(sdrh);
1889 if (i + len > sdrs_size) {
1890 error_report("Problem with recid 0x%4.4x", i);
1891 break;
1893 sdr_add_entry(ibs, sdrh, len, NULL);
1896 if (sdrs != init_sdrs) {
1897 g_free(sdrs);
1901 static const VMStateDescription vmstate_ipmi_sim = {
1902 .name = TYPE_IPMI_BMC_SIMULATOR,
1903 .version_id = 1,
1904 .minimum_version_id = 1,
1905 .fields = (VMStateField[]) {
1906 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
1907 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
1908 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
1909 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
1910 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
1911 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
1912 VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
1913 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
1914 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
1915 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
1916 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
1917 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
1918 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
1919 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
1920 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
1921 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
1922 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
1923 IPMIBmcSim),
1924 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
1925 VMSTATE_END_OF_LIST()
1929 static void ipmi_fru_init(IPMIFru *fru)
1931 int fsize;
1932 int size = 0;
1934 if (!fru->filename) {
1935 goto out;
1938 fsize = get_image_size(fru->filename);
1939 if (fsize > 0) {
1940 size = QEMU_ALIGN_UP(fsize, fru->areasize);
1941 fru->data = g_malloc0(size);
1942 if (load_image_size(fru->filename, fru->data, fsize) != fsize) {
1943 error_report("Could not load file '%s'", fru->filename);
1944 g_free(fru->data);
1945 fru->data = NULL;
1949 out:
1950 if (!fru->data) {
1951 /* give one default FRU */
1952 size = fru->areasize;
1953 fru->data = g_malloc0(size);
1956 fru->nentries = size / fru->areasize;
1959 static void ipmi_sim_realize(DeviceState *dev, Error **errp)
1961 IPMIBmc *b = IPMI_BMC(dev);
1962 unsigned int i;
1963 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
1965 QTAILQ_INIT(&ibs->rcvbufs);
1967 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
1968 ibs->device_id = 0x20;
1969 ibs->ipmi_version = 0x02; /* IPMI 2.0 */
1970 ibs->restart_cause = 0;
1971 for (i = 0; i < 4; i++) {
1972 ibs->sel.last_addition[i] = 0xff;
1973 ibs->sel.last_clear[i] = 0xff;
1974 ibs->sdr.last_addition[i] = 0xff;
1975 ibs->sdr.last_clear[i] = 0xff;
1978 ipmi_sdr_init(ibs);
1980 ipmi_fru_init(&ibs->fru);
1982 ibs->acpi_power_state[0] = 0;
1983 ibs->acpi_power_state[1] = 0;
1985 if (qemu_uuid_set) {
1986 memcpy(&ibs->uuid, &qemu_uuid, 16);
1987 } else {
1988 memset(&ibs->uuid, 0, 16);
1991 ipmi_init_sensors_from_sdrs(ibs);
1992 register_cmds(ibs);
1994 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
1996 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
1999 static Property ipmi_sim_properties[] = {
2000 DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim, fru.areasize, 1024),
2001 DEFINE_PROP_STRING("frudatafile", IPMIBmcSim, fru.filename),
2002 DEFINE_PROP_STRING("sdrfile", IPMIBmcSim, sdr_filename),
2003 DEFINE_PROP_UINT8("device_id", IPMIBmcSim, device_id, 0x20),
2004 DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim, ipmi_version, 0x02),
2005 DEFINE_PROP_UINT8("device_rev", IPMIBmcSim, device_rev, 0),
2006 DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim, fwrev1, 0),
2007 DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim, fwrev2, 0),
2008 DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim, mfg_id, 0),
2009 DEFINE_PROP_UINT16("product_id", IPMIBmcSim, product_id, 0),
2010 DEFINE_PROP_END_OF_LIST(),
2013 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
2015 DeviceClass *dc = DEVICE_CLASS(oc);
2016 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
2018 dc->hotpluggable = false;
2019 dc->realize = ipmi_sim_realize;
2020 dc->props = ipmi_sim_properties;
2021 bk->handle_command = ipmi_sim_handle_command;
2024 static const TypeInfo ipmi_sim_type = {
2025 .name = TYPE_IPMI_BMC_SIMULATOR,
2026 .parent = TYPE_IPMI_BMC,
2027 .instance_size = sizeof(IPMIBmcSim),
2028 .class_init = ipmi_sim_class_init,
2031 static void ipmi_sim_register_types(void)
2033 type_register_static(&ipmi_sim_type);
2036 type_init(ipmi_sim_register_types)