spapr: Simplify spapr_qirq() handling
[qemu/ar7.git] / hw / ipmi / ipmi_bmc_sim.c
blob71e56f3b13d153c73d49ff7d48f5de347e45a768
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 QemuUUID uuid;
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) &&
481 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs) ||
482 IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs)))
483 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
484 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
487 void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log)
489 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
490 IPMIInterface *s = ibs->parent.intf;
491 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
493 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
494 return;
497 if (log && IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
498 sel_add_event(ibs, evt);
501 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
502 goto out;
505 memcpy(ibs->evtbuf, evt, 16);
506 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
507 k->set_atn(s, 1, attn_irq_enabled(ibs));
508 out:
509 return;
511 static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
512 uint8_t evd1, uint8_t evd2, uint8_t evd3)
514 IPMIInterface *s = ibs->parent.intf;
515 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
516 uint8_t evt[16];
517 IPMISensor *sens = ibs->sensors + sens_num;
519 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
520 return;
522 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
523 return;
526 evt[2] = 0x2; /* System event record */
527 evt[7] = ibs->parent.slave_addr;
528 evt[8] = 0;
529 evt[9] = 0x04; /* Format version */
530 evt[10] = sens->sensor_type;
531 evt[11] = sens_num;
532 evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
533 evt[13] = evd1;
534 evt[14] = evd2;
535 evt[15] = evd3;
537 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
538 sel_add_event(ibs, evt);
541 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
542 return;
545 memcpy(ibs->evtbuf, evt, 16);
546 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
547 k->set_atn(s, 1, attn_irq_enabled(ibs));
550 static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
551 unsigned int bit, unsigned int val,
552 uint8_t evd1, uint8_t evd2, uint8_t evd3)
554 IPMISensor *sens;
555 uint16_t mask;
557 if (sensor >= MAX_SENSORS) {
558 return;
560 if (bit >= 16) {
561 return;
564 mask = (1 << bit);
565 sens = ibs->sensors + sensor;
566 if (val) {
567 sens->states |= mask & sens->states_suppt;
568 if (sens->assert_states & mask) {
569 return; /* Already asserted */
571 sens->assert_states |= mask & sens->assert_suppt;
572 if (sens->assert_enable & mask & sens->assert_states) {
573 /* Send an event on assert */
574 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
576 } else {
577 sens->states &= ~(mask & sens->states_suppt);
578 if (sens->deassert_states & mask) {
579 return; /* Already deasserted */
581 sens->deassert_states |= mask & sens->deassert_suppt;
582 if (sens->deassert_enable & mask & sens->deassert_states) {
583 /* Send an event on deassert */
584 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
589 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
591 unsigned int i, pos;
592 IPMISensor *sens;
594 for (i = 0; i < MAX_SENSORS; i++) {
595 memset(s->sensors + i, 0, sizeof(*sens));
598 pos = 0;
599 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
600 struct ipmi_sdr_compact *sdr =
601 (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
602 unsigned int len = sdr->header.rec_length;
604 if (len < 20) {
605 continue;
607 if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
608 continue; /* Not a sensor SDR we set from */
611 if (sdr->sensor_owner_number >= MAX_SENSORS) {
612 continue;
614 sens = s->sensors + sdr->sensor_owner_number;
616 IPMI_SENSOR_SET_PRESENT(sens, 1);
617 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
618 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
619 sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
620 sens->deassert_suppt =
621 sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
622 sens->states_suppt =
623 sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
624 sens->sensor_type = sdr->sensor_type;
625 sens->evt_reading_type_code = sdr->reading_type & 0x7f;
627 /* Enable all the events that are supported. */
628 sens->assert_enable = sens->assert_suppt;
629 sens->deassert_enable = sens->deassert_suppt;
633 static int ipmi_register_netfn(IPMIBmcSim *s, unsigned int netfn,
634 const IPMINetfn *netfnd)
636 if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
637 return -1;
639 s->netfns[netfn / 2] = netfnd;
640 return 0;
643 static const IPMICmdHandler *ipmi_get_handler(IPMIBmcSim *ibs,
644 unsigned int netfn,
645 unsigned int cmd)
647 const IPMICmdHandler *hdl;
649 if (netfn & 1 || netfn >= MAX_NETFNS || !ibs->netfns[netfn / 2]) {
650 return NULL;
653 if (cmd >= ibs->netfns[netfn / 2]->cmd_nums) {
654 return NULL;
657 hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd];
658 if (!hdl->cmd_handler) {
659 return NULL;
662 return hdl;
665 static void next_timeout(IPMIBmcSim *ibs)
667 int64_t next;
668 if (ibs->watchdog_running) {
669 next = ibs->watchdog_expiry;
670 } else {
671 /* Wait a minute */
672 next = ipmi_getmonotime() + 60 * 1000000000LL;
674 timer_mod_ns(ibs->timer, next);
677 static void ipmi_sim_handle_command(IPMIBmc *b,
678 uint8_t *cmd, unsigned int cmd_len,
679 unsigned int max_cmd_len,
680 uint8_t msg_id)
682 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
683 IPMIInterface *s = ibs->parent.intf;
684 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
685 const IPMICmdHandler *hdl;
686 RspBuffer rsp = RSP_BUFFER_INITIALIZER;
688 /* Set up the response, set the low bit of NETFN. */
689 /* Note that max_rsp_len must be at least 3 */
690 if (sizeof(rsp.buffer) < 3) {
691 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
692 goto out;
695 rsp_buffer_push(&rsp, cmd[0] | 0x04);
696 rsp_buffer_push(&rsp, cmd[1]);
697 rsp_buffer_push(&rsp, 0); /* Assume success */
699 /* If it's too short or it was truncated, return an error. */
700 if (cmd_len < 2) {
701 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
702 goto out;
704 if (cmd_len > max_cmd_len) {
705 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
706 goto out;
709 if ((cmd[0] & 0x03) != 0) {
710 /* Only have stuff on LUN 0 */
711 rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN);
712 goto out;
715 hdl = ipmi_get_handler(ibs, cmd[0] >> 2, cmd[1]);
716 if (!hdl) {
717 rsp_buffer_set_error(&rsp, IPMI_CC_INVALID_CMD);
718 goto out;
721 if (cmd_len < hdl->cmd_len_min) {
722 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
723 goto out;
726 hdl->cmd_handler(ibs, cmd, cmd_len, &rsp);
728 out:
729 k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
731 next_timeout(ibs);
734 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
736 IPMIInterface *s = ibs->parent.intf;
737 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
739 if (!ibs->watchdog_running) {
740 goto out;
743 if (!ibs->watchdog_preaction_ran) {
744 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
745 case IPMI_BMC_WATCHDOG_PRE_NMI:
746 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
747 k->do_hw_op(s, IPMI_SEND_NMI, 0);
748 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
749 0xc8, (2 << 4) | 0xf, 0xff);
750 break;
752 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
753 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
754 k->set_atn(s, 1, attn_irq_enabled(ibs));
755 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
756 0xc8, (3 << 4) | 0xf, 0xff);
757 break;
759 default:
760 goto do_full_expiry;
763 ibs->watchdog_preaction_ran = 1;
764 /* Issued the pretimeout, do the rest of the timeout now. */
765 ibs->watchdog_expiry = ipmi_getmonotime();
766 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
767 goto out;
770 do_full_expiry:
771 ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
772 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
773 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
774 case IPMI_BMC_WATCHDOG_ACTION_NONE:
775 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
776 0xc0, ibs->watchdog_use & 0xf, 0xff);
777 break;
779 case IPMI_BMC_WATCHDOG_ACTION_RESET:
780 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
781 0xc1, ibs->watchdog_use & 0xf, 0xff);
782 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
783 break;
785 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
786 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
787 0xc2, ibs->watchdog_use & 0xf, 0xff);
788 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
789 break;
791 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
792 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
793 0xc3, ibs->watchdog_use & 0xf, 0xff);
794 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
795 break;
798 out:
799 next_timeout(ibs);
802 static void chassis_capabilities(IPMIBmcSim *ibs,
803 uint8_t *cmd, unsigned int cmd_len,
804 RspBuffer *rsp)
806 rsp_buffer_push(rsp, 0);
807 rsp_buffer_push(rsp, ibs->parent.slave_addr);
808 rsp_buffer_push(rsp, ibs->parent.slave_addr);
809 rsp_buffer_push(rsp, ibs->parent.slave_addr);
810 rsp_buffer_push(rsp, ibs->parent.slave_addr);
813 static void chassis_status(IPMIBmcSim *ibs,
814 uint8_t *cmd, unsigned int cmd_len,
815 RspBuffer *rsp)
817 rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */
818 rsp_buffer_push(rsp, 0);
819 rsp_buffer_push(rsp, 0);
820 rsp_buffer_push(rsp, 0);
823 static void chassis_control(IPMIBmcSim *ibs,
824 uint8_t *cmd, unsigned int cmd_len,
825 RspBuffer *rsp)
827 IPMIInterface *s = ibs->parent.intf;
828 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
830 switch (cmd[2] & 0xf) {
831 case 0: /* power down */
832 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0));
833 break;
834 case 1: /* power up */
835 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0));
836 break;
837 case 2: /* power cycle */
838 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0));
839 break;
840 case 3: /* hard reset */
841 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0));
842 break;
843 case 4: /* pulse diagnostic interrupt */
844 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0));
845 break;
846 case 5: /* soft shutdown via ACPI by overtemp emulation */
847 rsp_buffer_set_error(rsp, k->do_hw_op(s,
848 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0));
849 break;
850 default:
851 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
852 return;
856 static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
857 uint8_t *cmd, unsigned int cmd_len,
858 RspBuffer *rsp)
861 rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */
862 rsp_buffer_push(rsp, 0); /* Channel 0 */
865 static void get_device_id(IPMIBmcSim *ibs,
866 uint8_t *cmd, unsigned int cmd_len,
867 RspBuffer *rsp)
869 rsp_buffer_push(rsp, ibs->device_id);
870 rsp_buffer_push(rsp, ibs->device_rev & 0xf);
871 rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
872 rsp_buffer_push(rsp, ibs->fwrev2);
873 rsp_buffer_push(rsp, ibs->ipmi_version);
874 rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */
875 rsp_buffer_push(rsp, ibs->mfg_id & 0xff);
876 rsp_buffer_push(rsp, (ibs->mfg_id >> 8) & 0xff);
877 rsp_buffer_push(rsp, (ibs->mfg_id >> 16) & 0xff);
878 rsp_buffer_push(rsp, ibs->product_id & 0xff);
879 rsp_buffer_push(rsp, (ibs->product_id >> 8) & 0xff);
882 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
884 IPMIInterface *s = ibs->parent.intf;
885 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
886 bool irqs_on;
888 ibs->bmc_global_enables = val;
890 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
891 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
893 k->set_irq_enable(s, irqs_on);
896 static void cold_reset(IPMIBmcSim *ibs,
897 uint8_t *cmd, unsigned int cmd_len,
898 RspBuffer *rsp)
900 IPMIInterface *s = ibs->parent.intf;
901 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
903 /* Disable all interrupts */
904 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
906 if (k->reset) {
907 k->reset(s, true);
911 static void warm_reset(IPMIBmcSim *ibs,
912 uint8_t *cmd, unsigned int cmd_len,
913 RspBuffer *rsp)
915 IPMIInterface *s = ibs->parent.intf;
916 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
918 if (k->reset) {
919 k->reset(s, false);
922 static void set_acpi_power_state(IPMIBmcSim *ibs,
923 uint8_t *cmd, unsigned int cmd_len,
924 RspBuffer *rsp)
926 ibs->acpi_power_state[0] = cmd[2];
927 ibs->acpi_power_state[1] = cmd[3];
930 static void get_acpi_power_state(IPMIBmcSim *ibs,
931 uint8_t *cmd, unsigned int cmd_len,
932 RspBuffer *rsp)
934 rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
935 rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
938 static void get_device_guid(IPMIBmcSim *ibs,
939 uint8_t *cmd, unsigned int cmd_len,
940 RspBuffer *rsp)
942 unsigned int i;
944 /* An uninitialized uuid is all zeros, use that to know if it is set. */
945 for (i = 0; i < 16; i++) {
946 if (ibs->uuid.data[i]) {
947 goto uuid_set;
950 /* No uuid is set, return an error. */
951 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_CMD);
952 return;
954 uuid_set:
955 for (i = 0; i < 16; i++) {
956 rsp_buffer_push(rsp, ibs->uuid.data[i]);
960 static void set_bmc_global_enables(IPMIBmcSim *ibs,
961 uint8_t *cmd, unsigned int cmd_len,
962 RspBuffer *rsp)
964 set_global_enables(ibs, cmd[2]);
967 static void get_bmc_global_enables(IPMIBmcSim *ibs,
968 uint8_t *cmd, unsigned int cmd_len,
969 RspBuffer *rsp)
971 rsp_buffer_push(rsp, ibs->bmc_global_enables);
974 static void clr_msg_flags(IPMIBmcSim *ibs,
975 uint8_t *cmd, unsigned int cmd_len,
976 RspBuffer *rsp)
978 IPMIInterface *s = ibs->parent.intf;
979 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
981 ibs->msg_flags &= ~cmd[2];
982 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
985 static void get_msg_flags(IPMIBmcSim *ibs,
986 uint8_t *cmd, unsigned int cmd_len,
987 RspBuffer *rsp)
989 rsp_buffer_push(rsp, ibs->msg_flags);
992 static void read_evt_msg_buf(IPMIBmcSim *ibs,
993 uint8_t *cmd, unsigned int cmd_len,
994 RspBuffer *rsp)
996 IPMIInterface *s = ibs->parent.intf;
997 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
998 unsigned int i;
1000 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
1001 rsp_buffer_set_error(rsp, 0x80);
1002 return;
1004 for (i = 0; i < 16; i++) {
1005 rsp_buffer_push(rsp, ibs->evtbuf[i]);
1007 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
1008 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
1011 static void get_msg(IPMIBmcSim *ibs,
1012 uint8_t *cmd, unsigned int cmd_len,
1013 RspBuffer *rsp)
1015 IPMIRcvBufEntry *msg;
1017 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
1018 rsp_buffer_set_error(rsp, 0x80); /* Queue empty */
1019 goto out;
1021 rsp_buffer_push(rsp, 0); /* Channel 0 */
1022 msg = QTAILQ_FIRST(&ibs->rcvbufs);
1023 rsp_buffer_pushmore(rsp, msg->buf, msg->len);
1024 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
1025 g_free(msg);
1027 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
1028 IPMIInterface *s = ibs->parent.intf;
1029 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1031 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1032 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
1035 out:
1036 return;
1039 static unsigned char
1040 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
1042 for (; size > 0; size--, data++) {
1043 csum += *data;
1046 return -csum;
1049 static void send_msg(IPMIBmcSim *ibs,
1050 uint8_t *cmd, unsigned int cmd_len,
1051 RspBuffer *rsp)
1053 IPMIInterface *s = ibs->parent.intf;
1054 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1055 IPMIRcvBufEntry *msg;
1056 uint8_t *buf;
1057 uint8_t netfn, rqLun, rsLun, rqSeq;
1059 if (cmd[2] != 0) {
1060 /* We only handle channel 0 with no options */
1061 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1062 return;
1065 if (cmd_len < 10) {
1066 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
1067 return;
1070 if (cmd[3] != 0x40) {
1071 /* We only emulate a MC at address 0x40. */
1072 rsp_buffer_set_error(rsp, 0x83); /* NAK on write */
1073 return;
1076 cmd += 3; /* Skip the header. */
1077 cmd_len -= 3;
1080 * At this point we "send" the message successfully. Any error will
1081 * be returned in the response.
1083 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
1084 cmd[3] != 0x20) { /* Improper response address */
1085 return; /* No response */
1088 netfn = cmd[1] >> 2;
1089 rqLun = cmd[4] & 0x3;
1090 rsLun = cmd[1] & 0x3;
1091 rqSeq = cmd[4] >> 2;
1093 if (rqLun != 2) {
1094 /* We only support LUN 2 coming back to us. */
1095 return;
1098 msg = g_malloc(sizeof(*msg));
1099 msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
1100 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
1101 msg->buf[2] = cmd[0]; /* rsSA */
1102 msg->buf[3] = (rqSeq << 2) | rsLun;
1103 msg->buf[4] = cmd[5]; /* Cmd */
1104 msg->buf[5] = 0; /* Completion Code */
1105 msg->len = 6;
1107 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
1108 /* Not a command we handle. */
1109 msg->buf[5] = IPMI_CC_INVALID_CMD;
1110 goto end_msg;
1113 buf = msg->buf + msg->len; /* After the CC */
1114 buf[0] = 0;
1115 buf[1] = 0;
1116 buf[2] = 0;
1117 buf[3] = 0;
1118 buf[4] = 0x51;
1119 buf[5] = 0;
1120 buf[6] = 0;
1121 buf[7] = 0;
1122 buf[8] = 0;
1123 buf[9] = 0;
1124 buf[10] = 0;
1125 msg->len += 11;
1127 end_msg:
1128 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1129 msg->len++;
1130 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1131 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1132 k->set_atn(s, 1, attn_irq_enabled(ibs));
1135 static void do_watchdog_reset(IPMIBmcSim *ibs)
1137 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1138 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1139 ibs->watchdog_running = 0;
1140 return;
1142 ibs->watchdog_preaction_ran = 0;
1145 /* Timeout is in tenths of a second, offset is in seconds */
1146 ibs->watchdog_expiry = ipmi_getmonotime();
1147 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1148 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1149 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1151 ibs->watchdog_running = 1;
1154 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1155 uint8_t *cmd, unsigned int cmd_len,
1156 RspBuffer *rsp)
1158 if (!ibs->watchdog_initialized) {
1159 rsp_buffer_set_error(rsp, 0x80);
1160 return;
1162 do_watchdog_reset(ibs);
1165 static void set_watchdog_timer(IPMIBmcSim *ibs,
1166 uint8_t *cmd, unsigned int cmd_len,
1167 RspBuffer *rsp)
1169 IPMIInterface *s = ibs->parent.intf;
1170 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1171 unsigned int val;
1173 val = cmd[2] & 0x7; /* Validate use */
1174 if (val == 0 || val > 5) {
1175 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1176 return;
1178 val = cmd[3] & 0x7; /* Validate action */
1179 switch (val) {
1180 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1181 break;
1183 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1184 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1));
1185 break;
1187 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1188 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1));
1189 break;
1191 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1192 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1));
1193 break;
1195 default:
1196 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1198 if (rsp->buffer[2]) {
1199 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1200 return;
1203 val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1204 switch (val) {
1205 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1206 case IPMI_BMC_WATCHDOG_PRE_NONE:
1207 break;
1209 case IPMI_BMC_WATCHDOG_PRE_NMI:
1210 if (k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1211 /* NMI not supported. */
1212 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1213 return;
1215 break;
1217 default:
1218 /* We don't support PRE_SMI */
1219 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1220 return;
1223 ibs->watchdog_initialized = 1;
1224 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1225 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1226 ibs->watchdog_pretimeout = cmd[4];
1227 ibs->watchdog_expired &= ~cmd[5];
1228 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1229 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1230 do_watchdog_reset(ibs);
1231 } else {
1232 ibs->watchdog_running = 0;
1236 static void get_watchdog_timer(IPMIBmcSim *ibs,
1237 uint8_t *cmd, unsigned int cmd_len,
1238 RspBuffer *rsp)
1240 rsp_buffer_push(rsp, ibs->watchdog_use);
1241 rsp_buffer_push(rsp, ibs->watchdog_action);
1242 rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
1243 rsp_buffer_push(rsp, ibs->watchdog_expired);
1244 rsp_buffer_push(rsp, ibs->watchdog_timeout & 0xff);
1245 rsp_buffer_push(rsp, (ibs->watchdog_timeout >> 8) & 0xff);
1246 if (ibs->watchdog_running) {
1247 long timeout;
1248 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1249 / 100000000);
1250 rsp_buffer_push(rsp, timeout & 0xff);
1251 rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
1252 } else {
1253 rsp_buffer_push(rsp, 0);
1254 rsp_buffer_push(rsp, 0);
1258 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1259 uint8_t *cmd, unsigned int cmd_len,
1260 RspBuffer *rsp)
1262 unsigned int i;
1264 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */
1265 rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
1266 rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
1267 rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1268 rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1269 for (i = 0; i < 4; i++) {
1270 rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
1272 for (i = 0; i < 4; i++) {
1273 rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
1275 /* Only modal support, reserve supported */
1276 rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
1279 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1280 uint8_t *cmd, unsigned int cmd_len,
1281 RspBuffer *rsp)
1283 rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
1284 rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
1287 static void get_sdr(IPMIBmcSim *ibs,
1288 uint8_t *cmd, unsigned int cmd_len,
1289 RspBuffer *rsp)
1291 unsigned int pos;
1292 uint16_t nextrec;
1293 struct ipmi_sdr_header *sdrh;
1295 if (cmd[6]) {
1296 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1297 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1298 return;
1302 pos = 0;
1303 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1304 &pos, &nextrec)) {
1305 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1306 return;
1309 sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1311 if (cmd[6] > ipmi_sdr_length(sdrh)) {
1312 rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE);
1313 return;
1316 rsp_buffer_push(rsp, nextrec & 0xff);
1317 rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
1319 if (cmd[7] == 0xff) {
1320 cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1323 if ((cmd[7] + rsp->len) > sizeof(rsp->buffer)) {
1324 rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES);
1325 return;
1328 rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1331 static void add_sdr(IPMIBmcSim *ibs,
1332 uint8_t *cmd, unsigned int cmd_len,
1333 RspBuffer *rsp)
1335 uint16_t recid;
1336 struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1338 if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1339 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1340 return;
1342 rsp_buffer_push(rsp, recid & 0xff);
1343 rsp_buffer_push(rsp, (recid >> 8) & 0xff);
1346 static void clear_sdr_rep(IPMIBmcSim *ibs,
1347 uint8_t *cmd, unsigned int cmd_len,
1348 RspBuffer *rsp)
1350 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1351 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1352 return;
1355 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1356 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1357 return;
1359 if (cmd[7] == 0xaa) {
1360 ibs->sdr.next_free = 0;
1361 ibs->sdr.overflow = 0;
1362 set_timestamp(ibs, ibs->sdr.last_clear);
1363 rsp_buffer_push(rsp, 1); /* Erasure complete */
1364 sdr_inc_reservation(&ibs->sdr);
1365 } else if (cmd[7] == 0) {
1366 rsp_buffer_push(rsp, 1); /* Erasure complete */
1367 } else {
1368 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1369 return;
1373 static void get_sel_info(IPMIBmcSim *ibs,
1374 uint8_t *cmd, unsigned int cmd_len,
1375 RspBuffer *rsp)
1377 unsigned int i, val;
1379 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */
1380 rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
1381 rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
1382 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1383 rsp_buffer_push(rsp, val & 0xff);
1384 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1385 for (i = 0; i < 4; i++) {
1386 rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
1388 for (i = 0; i < 4; i++) {
1389 rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
1391 /* Only support Reserve SEL */
1392 rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
1395 static void get_fru_area_info(IPMIBmcSim *ibs,
1396 uint8_t *cmd, unsigned int cmd_len,
1397 RspBuffer *rsp)
1399 uint8_t fruid;
1400 uint16_t fru_entry_size;
1402 fruid = cmd[2];
1404 if (fruid >= ibs->fru.nentries) {
1405 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1406 return;
1409 fru_entry_size = ibs->fru.areasize;
1411 rsp_buffer_push(rsp, fru_entry_size & 0xff);
1412 rsp_buffer_push(rsp, fru_entry_size >> 8 & 0xff);
1413 rsp_buffer_push(rsp, 0x0);
1416 static void read_fru_data(IPMIBmcSim *ibs,
1417 uint8_t *cmd, unsigned int cmd_len,
1418 RspBuffer *rsp)
1420 uint8_t fruid;
1421 uint16_t offset;
1422 int i;
1423 uint8_t *fru_entry;
1424 unsigned int count;
1426 fruid = cmd[2];
1427 offset = (cmd[3] | cmd[4] << 8);
1429 if (fruid >= ibs->fru.nentries) {
1430 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1431 return;
1434 if (offset >= ibs->fru.areasize - 1) {
1435 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1436 return;
1439 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1441 count = MIN(cmd[5], ibs->fru.areasize - offset);
1443 rsp_buffer_push(rsp, count & 0xff);
1444 for (i = 0; i < count; i++) {
1445 rsp_buffer_push(rsp, fru_entry[offset + i]);
1449 static void write_fru_data(IPMIBmcSim *ibs,
1450 uint8_t *cmd, unsigned int cmd_len,
1451 RspBuffer *rsp)
1453 uint8_t fruid;
1454 uint16_t offset;
1455 uint8_t *fru_entry;
1456 unsigned int count;
1458 fruid = cmd[2];
1459 offset = (cmd[3] | cmd[4] << 8);
1461 if (fruid >= ibs->fru.nentries) {
1462 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1463 return;
1466 if (offset >= ibs->fru.areasize - 1) {
1467 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1468 return;
1471 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1473 count = MIN(cmd_len - 5, ibs->fru.areasize - offset);
1475 memcpy(fru_entry + offset, cmd + 5, count);
1477 rsp_buffer_push(rsp, count & 0xff);
1480 static void reserve_sel(IPMIBmcSim *ibs,
1481 uint8_t *cmd, unsigned int cmd_len,
1482 RspBuffer *rsp)
1484 rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
1485 rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
1488 static void get_sel_entry(IPMIBmcSim *ibs,
1489 uint8_t *cmd, unsigned int cmd_len,
1490 RspBuffer *rsp)
1492 unsigned int val;
1494 if (cmd[6]) {
1495 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1496 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1497 return;
1500 if (ibs->sel.next_free == 0) {
1501 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1502 return;
1504 if (cmd[6] > 15) {
1505 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1506 return;
1508 if (cmd[7] == 0xff) {
1509 cmd[7] = 16;
1510 } else if ((cmd[7] + cmd[6]) > 16) {
1511 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1512 return;
1513 } else {
1514 cmd[7] += cmd[6];
1517 val = cmd[4] | (cmd[5] << 8);
1518 if (val == 0xffff) {
1519 val = ibs->sel.next_free - 1;
1520 } else if (val >= ibs->sel.next_free) {
1521 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1522 return;
1524 if ((val + 1) == ibs->sel.next_free) {
1525 rsp_buffer_push(rsp, 0xff);
1526 rsp_buffer_push(rsp, 0xff);
1527 } else {
1528 rsp_buffer_push(rsp, (val + 1) & 0xff);
1529 rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
1531 for (; cmd[6] < cmd[7]; cmd[6]++) {
1532 rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
1536 static void add_sel_entry(IPMIBmcSim *ibs,
1537 uint8_t *cmd, unsigned int cmd_len,
1538 RspBuffer *rsp)
1540 if (sel_add_event(ibs, cmd + 2)) {
1541 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1542 return;
1544 /* sel_add_event fills in the record number. */
1545 rsp_buffer_push(rsp, cmd[2]);
1546 rsp_buffer_push(rsp, cmd[3]);
1549 static void clear_sel(IPMIBmcSim *ibs,
1550 uint8_t *cmd, unsigned int cmd_len,
1551 RspBuffer *rsp)
1553 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1554 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1555 return;
1558 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1559 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1560 return;
1562 if (cmd[7] == 0xaa) {
1563 ibs->sel.next_free = 0;
1564 ibs->sel.overflow = 0;
1565 set_timestamp(ibs, ibs->sdr.last_clear);
1566 rsp_buffer_push(rsp, 1); /* Erasure complete */
1567 sel_inc_reservation(&ibs->sel);
1568 } else if (cmd[7] == 0) {
1569 rsp_buffer_push(rsp, 1); /* Erasure complete */
1570 } else {
1571 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1572 return;
1576 static void get_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 ipmi_gettime(&now);
1584 val = now.tv_sec + ibs->sel.time_offset;
1585 rsp_buffer_push(rsp, val & 0xff);
1586 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1587 rsp_buffer_push(rsp, (val >> 16) & 0xff);
1588 rsp_buffer_push(rsp, (val >> 24) & 0xff);
1591 static void set_sel_time(IPMIBmcSim *ibs,
1592 uint8_t *cmd, unsigned int cmd_len,
1593 RspBuffer *rsp)
1595 uint32_t val;
1596 struct ipmi_time now;
1598 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1599 ipmi_gettime(&now);
1600 ibs->sel.time_offset = now.tv_sec - ((long) val);
1603 static void platform_event_msg(IPMIBmcSim *ibs,
1604 uint8_t *cmd, unsigned int cmd_len,
1605 RspBuffer *rsp)
1607 uint8_t event[16];
1609 event[2] = 2; /* System event record */
1610 event[7] = cmd[2]; /* Generator ID */
1611 event[8] = 0;
1612 event[9] = cmd[3]; /* EvMRev */
1613 event[10] = cmd[4]; /* Sensor type */
1614 event[11] = cmd[5]; /* Sensor number */
1615 event[12] = cmd[6]; /* Event dir / Event type */
1616 event[13] = cmd[7]; /* Event data 1 */
1617 event[14] = cmd[8]; /* Event data 2 */
1618 event[15] = cmd[9]; /* Event data 3 */
1620 if (sel_add_event(ibs, event)) {
1621 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1625 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1626 uint8_t *cmd, unsigned int cmd_len,
1627 RspBuffer *rsp)
1629 IPMISensor *sens;
1631 if ((cmd[2] >= MAX_SENSORS) ||
1632 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1633 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1634 return;
1636 sens = ibs->sensors + cmd[2];
1637 switch ((cmd[3] >> 4) & 0x3) {
1638 case 0: /* Do not change */
1639 break;
1640 case 1: /* Enable bits */
1641 if (cmd_len > 4) {
1642 sens->assert_enable |= cmd[4];
1644 if (cmd_len > 5) {
1645 sens->assert_enable |= cmd[5] << 8;
1647 if (cmd_len > 6) {
1648 sens->deassert_enable |= cmd[6];
1650 if (cmd_len > 7) {
1651 sens->deassert_enable |= cmd[7] << 8;
1653 break;
1654 case 2: /* Disable bits */
1655 if (cmd_len > 4) {
1656 sens->assert_enable &= ~cmd[4];
1658 if (cmd_len > 5) {
1659 sens->assert_enable &= ~(cmd[5] << 8);
1661 if (cmd_len > 6) {
1662 sens->deassert_enable &= ~cmd[6];
1664 if (cmd_len > 7) {
1665 sens->deassert_enable &= ~(cmd[7] << 8);
1667 break;
1668 case 3:
1669 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1670 return;
1672 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1675 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1676 uint8_t *cmd, unsigned int cmd_len,
1677 RspBuffer *rsp)
1679 IPMISensor *sens;
1681 if ((cmd[2] >= MAX_SENSORS) ||
1682 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1683 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1684 return;
1686 sens = ibs->sensors + cmd[2];
1687 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1688 rsp_buffer_push(rsp, sens->assert_enable & 0xff);
1689 rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
1690 rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
1691 rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
1694 static void rearm_sensor_evts(IPMIBmcSim *ibs,
1695 uint8_t *cmd, unsigned int cmd_len,
1696 RspBuffer *rsp)
1698 IPMISensor *sens;
1700 if ((cmd[2] >= MAX_SENSORS) ||
1701 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1702 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1703 return;
1705 sens = ibs->sensors + cmd[2];
1707 if ((cmd[3] & 0x80) == 0) {
1708 /* Just clear everything */
1709 sens->states = 0;
1710 return;
1714 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1715 uint8_t *cmd, unsigned int cmd_len,
1716 RspBuffer *rsp)
1718 IPMISensor *sens;
1720 if ((cmd[2] >= MAX_SENSORS) ||
1721 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1722 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1723 return;
1725 sens = ibs->sensors + cmd[2];
1726 rsp_buffer_push(rsp, sens->reading);
1727 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1728 rsp_buffer_push(rsp, sens->assert_states & 0xff);
1729 rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
1730 rsp_buffer_push(rsp, sens->deassert_states & 0xff);
1731 rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
1734 static void get_sensor_reading(IPMIBmcSim *ibs,
1735 uint8_t *cmd, unsigned int cmd_len,
1736 RspBuffer *rsp)
1738 IPMISensor *sens;
1740 if ((cmd[2] >= MAX_SENSORS) ||
1741 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1742 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1743 return;
1745 sens = ibs->sensors + cmd[2];
1746 rsp_buffer_push(rsp, sens->reading);
1747 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1748 rsp_buffer_push(rsp, sens->states & 0xff);
1749 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1750 rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
1754 static void set_sensor_type(IPMIBmcSim *ibs,
1755 uint8_t *cmd, unsigned int cmd_len,
1756 RspBuffer *rsp)
1758 IPMISensor *sens;
1761 if ((cmd[2] >= MAX_SENSORS) ||
1762 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1763 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1764 return;
1766 sens = ibs->sensors + cmd[2];
1767 sens->sensor_type = cmd[3];
1768 sens->evt_reading_type_code = cmd[4] & 0x7f;
1771 static void get_sensor_type(IPMIBmcSim *ibs,
1772 uint8_t *cmd, unsigned int cmd_len,
1773 RspBuffer *rsp)
1775 IPMISensor *sens;
1778 if ((cmd[2] >= MAX_SENSORS) ||
1779 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1780 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1781 return;
1783 sens = ibs->sensors + cmd[2];
1784 rsp_buffer_push(rsp, sens->sensor_type);
1785 rsp_buffer_push(rsp, sens->evt_reading_type_code);
1789 static const IPMICmdHandler chassis_cmds[] = {
1790 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
1791 [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
1792 [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
1793 [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
1795 static const IPMINetfn chassis_netfn = {
1796 .cmd_nums = ARRAY_SIZE(chassis_cmds),
1797 .cmd_handlers = chassis_cmds
1800 static const IPMICmdHandler sensor_event_cmds[] = {
1801 [IPMI_CMD_PLATFORM_EVENT_MSG] = { platform_event_msg, 10 },
1802 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
1803 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
1804 [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
1805 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
1806 [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
1807 [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
1808 [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
1810 static const IPMINetfn sensor_event_netfn = {
1811 .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
1812 .cmd_handlers = sensor_event_cmds
1815 static const IPMICmdHandler app_cmds[] = {
1816 [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
1817 [IPMI_CMD_COLD_RESET] = { cold_reset },
1818 [IPMI_CMD_WARM_RESET] = { warm_reset },
1819 [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
1820 [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
1821 [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
1822 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
1823 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
1824 [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
1825 [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
1826 [IPMI_CMD_GET_MSG] = { get_msg },
1827 [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
1828 [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
1829 [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
1830 [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
1831 [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
1833 static const IPMINetfn app_netfn = {
1834 .cmd_nums = ARRAY_SIZE(app_cmds),
1835 .cmd_handlers = app_cmds
1838 static const IPMICmdHandler storage_cmds[] = {
1839 [IPMI_CMD_GET_FRU_AREA_INFO] = { get_fru_area_info, 3 },
1840 [IPMI_CMD_READ_FRU_DATA] = { read_fru_data, 5 },
1841 [IPMI_CMD_WRITE_FRU_DATA] = { write_fru_data, 5 },
1842 [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
1843 [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
1844 [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
1845 [IPMI_CMD_ADD_SDR] = { add_sdr },
1846 [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
1847 [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
1848 [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
1849 [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
1850 [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
1851 [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
1852 [IPMI_CMD_GET_SEL_TIME] = { get_sel_time },
1853 [IPMI_CMD_SET_SEL_TIME] = { set_sel_time, 6 },
1856 static const IPMINetfn storage_netfn = {
1857 .cmd_nums = ARRAY_SIZE(storage_cmds),
1858 .cmd_handlers = storage_cmds
1861 static void register_cmds(IPMIBmcSim *s)
1863 ipmi_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
1864 ipmi_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
1865 ipmi_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
1866 ipmi_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
1869 static uint8_t init_sdrs[] = {
1870 /* Watchdog device */
1871 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1872 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1873 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1874 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1875 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1878 static void ipmi_sdr_init(IPMIBmcSim *ibs)
1880 unsigned int i;
1881 int len;
1882 size_t sdrs_size;
1883 uint8_t *sdrs;
1885 sdrs_size = sizeof(init_sdrs);
1886 sdrs = init_sdrs;
1887 if (ibs->sdr_filename &&
1888 !g_file_get_contents(ibs->sdr_filename, (gchar **) &sdrs, &sdrs_size,
1889 NULL)) {
1890 error_report("failed to load sdr file '%s'", ibs->sdr_filename);
1891 sdrs_size = sizeof(init_sdrs);
1892 sdrs = init_sdrs;
1895 for (i = 0; i < sdrs_size; i += len) {
1896 struct ipmi_sdr_header *sdrh;
1898 if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
1899 error_report("Problem with recid 0x%4.4x", i);
1900 break;
1902 sdrh = (struct ipmi_sdr_header *) &sdrs[i];
1903 len = ipmi_sdr_length(sdrh);
1904 if (i + len > sdrs_size) {
1905 error_report("Problem with recid 0x%4.4x", i);
1906 break;
1908 sdr_add_entry(ibs, sdrh, len, NULL);
1911 if (sdrs != init_sdrs) {
1912 g_free(sdrs);
1916 static const VMStateDescription vmstate_ipmi_sim = {
1917 .name = TYPE_IPMI_BMC_SIMULATOR,
1918 .version_id = 1,
1919 .minimum_version_id = 1,
1920 .fields = (VMStateField[]) {
1921 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
1922 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
1923 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
1924 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
1925 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
1926 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
1927 VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
1928 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
1929 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
1930 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
1931 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
1932 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
1933 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
1934 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
1935 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
1936 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
1937 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
1938 IPMIBmcSim),
1939 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
1940 VMSTATE_END_OF_LIST()
1944 static void ipmi_fru_init(IPMIFru *fru)
1946 int fsize;
1947 int size = 0;
1949 if (!fru->filename) {
1950 goto out;
1953 fsize = get_image_size(fru->filename);
1954 if (fsize > 0) {
1955 size = QEMU_ALIGN_UP(fsize, fru->areasize);
1956 fru->data = g_malloc0(size);
1957 if (load_image_size(fru->filename, fru->data, fsize) != fsize) {
1958 error_report("Could not load file '%s'", fru->filename);
1959 g_free(fru->data);
1960 fru->data = NULL;
1964 out:
1965 if (!fru->data) {
1966 /* give one default FRU */
1967 size = fru->areasize;
1968 fru->data = g_malloc0(size);
1971 fru->nentries = size / fru->areasize;
1974 static void ipmi_sim_realize(DeviceState *dev, Error **errp)
1976 IPMIBmc *b = IPMI_BMC(dev);
1977 unsigned int i;
1978 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
1980 QTAILQ_INIT(&ibs->rcvbufs);
1982 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
1983 ibs->device_id = 0x20;
1984 ibs->ipmi_version = 0x02; /* IPMI 2.0 */
1985 ibs->restart_cause = 0;
1986 for (i = 0; i < 4; i++) {
1987 ibs->sel.last_addition[i] = 0xff;
1988 ibs->sel.last_clear[i] = 0xff;
1989 ibs->sdr.last_addition[i] = 0xff;
1990 ibs->sdr.last_clear[i] = 0xff;
1993 ipmi_sdr_init(ibs);
1995 ipmi_fru_init(&ibs->fru);
1997 ibs->acpi_power_state[0] = 0;
1998 ibs->acpi_power_state[1] = 0;
2000 ipmi_init_sensors_from_sdrs(ibs);
2001 register_cmds(ibs);
2003 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
2005 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
2008 static Property ipmi_sim_properties[] = {
2009 DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim, fru.areasize, 1024),
2010 DEFINE_PROP_STRING("frudatafile", IPMIBmcSim, fru.filename),
2011 DEFINE_PROP_STRING("sdrfile", IPMIBmcSim, sdr_filename),
2012 DEFINE_PROP_UINT8("device_id", IPMIBmcSim, device_id, 0x20),
2013 DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim, ipmi_version, 0x02),
2014 DEFINE_PROP_UINT8("device_rev", IPMIBmcSim, device_rev, 0),
2015 DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim, fwrev1, 0),
2016 DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim, fwrev2, 0),
2017 DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim, mfg_id, 0),
2018 DEFINE_PROP_UINT16("product_id", IPMIBmcSim, product_id, 0),
2019 DEFINE_PROP_UUID_NODEFAULT("guid", IPMIBmcSim, uuid),
2020 DEFINE_PROP_END_OF_LIST(),
2023 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
2025 DeviceClass *dc = DEVICE_CLASS(oc);
2026 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
2028 dc->hotpluggable = false;
2029 dc->realize = ipmi_sim_realize;
2030 dc->props = ipmi_sim_properties;
2031 bk->handle_command = ipmi_sim_handle_command;
2034 static const TypeInfo ipmi_sim_type = {
2035 .name = TYPE_IPMI_BMC_SIMULATOR,
2036 .parent = TYPE_IPMI_BMC,
2037 .instance_size = sizeof(IPMIBmcSim),
2038 .class_init = ipmi_sim_class_init,
2041 static void ipmi_sim_register_types(void)
2043 type_register_static(&ipmi_sim_type);
2046 type_init(ipmi_sim_register_types)