slirp: API is extern C
[qemu/ar7.git] / hw / ipmi / ipmi_bmc_sim.c
blob9b509f829b480a4171e7b73225e4757b83d4f64c
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 "hw/loader.h"
32 #define IPMI_NETFN_CHASSIS 0x00
34 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
35 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
36 #define IPMI_CMD_CHASSIS_CONTROL 0x02
37 #define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09
39 #define IPMI_NETFN_SENSOR_EVENT 0x04
41 #define IPMI_CMD_PLATFORM_EVENT_MSG 0x02
42 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
43 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
44 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
45 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
46 #define IPMI_CMD_GET_SENSOR_READING 0x2d
47 #define IPMI_CMD_SET_SENSOR_TYPE 0x2e
48 #define IPMI_CMD_GET_SENSOR_TYPE 0x2f
50 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
52 #define IPMI_CMD_GET_DEVICE_ID 0x01
53 #define IPMI_CMD_COLD_RESET 0x02
54 #define IPMI_CMD_WARM_RESET 0x03
55 #define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
56 #define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
57 #define IPMI_CMD_GET_DEVICE_GUID 0x08
58 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
59 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
60 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
61 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
62 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
63 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
64 #define IPMI_CMD_GET_MSG_FLAGS 0x31
65 #define IPMI_CMD_GET_MSG 0x33
66 #define IPMI_CMD_SEND_MSG 0x34
67 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
69 #define IPMI_NETFN_STORAGE 0x0a
71 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
72 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
73 #define IPMI_CMD_RESERVE_SDR_REP 0x22
74 #define IPMI_CMD_GET_SDR 0x23
75 #define IPMI_CMD_ADD_SDR 0x24
76 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
77 #define IPMI_CMD_DELETE_SDR 0x26
78 #define IPMI_CMD_CLEAR_SDR_REP 0x27
79 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
80 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
81 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
82 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
83 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
84 #define IPMI_CMD_GET_FRU_AREA_INFO 0x10
85 #define IPMI_CMD_READ_FRU_DATA 0x11
86 #define IPMI_CMD_WRITE_FRU_DATA 0x12
87 #define IPMI_CMD_GET_SEL_INFO 0x40
88 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
89 #define IPMI_CMD_RESERVE_SEL 0x42
90 #define IPMI_CMD_GET_SEL_ENTRY 0x43
91 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
92 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
93 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
94 #define IPMI_CMD_CLEAR_SEL 0x47
95 #define IPMI_CMD_GET_SEL_TIME 0x48
96 #define IPMI_CMD_SET_SEL_TIME 0x49
99 /* Same as a timespec struct. */
100 struct ipmi_time {
101 long tv_sec;
102 long tv_nsec;
105 #define MAX_SEL_SIZE 128
107 typedef struct IPMISel {
108 uint8_t sel[MAX_SEL_SIZE][16];
109 unsigned int next_free;
110 long time_offset;
111 uint16_t reservation;
112 uint8_t last_addition[4];
113 uint8_t last_clear[4];
114 uint8_t overflow;
115 } IPMISel;
117 #define MAX_SDR_SIZE 16384
119 typedef struct IPMISdr {
120 uint8_t sdr[MAX_SDR_SIZE];
121 unsigned int next_free;
122 uint16_t next_rec_id;
123 uint16_t reservation;
124 uint8_t last_addition[4];
125 uint8_t last_clear[4];
126 uint8_t overflow;
127 } IPMISdr;
129 typedef struct IPMIFru {
130 char *filename;
131 unsigned int nentries;
132 uint16_t areasize;
133 uint8_t *data;
134 } IPMIFru;
136 typedef struct IPMISensor {
137 uint8_t status;
138 uint8_t reading;
139 uint16_t states_suppt;
140 uint16_t assert_suppt;
141 uint16_t deassert_suppt;
142 uint16_t states;
143 uint16_t assert_states;
144 uint16_t deassert_states;
145 uint16_t assert_enable;
146 uint16_t deassert_enable;
147 uint8_t sensor_type;
148 uint8_t evt_reading_type_code;
149 } IPMISensor;
150 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
151 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
152 !!(v))
153 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
154 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
155 ((!!(v)) << 6))
156 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
157 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
158 ((!!(v)) << 7))
159 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
160 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
161 (v & 0xc0))
162 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
164 #define MAX_SENSORS 20
165 #define IPMI_WATCHDOG_SENSOR 0
167 typedef struct IPMIBmcSim IPMIBmcSim;
168 typedef struct RspBuffer RspBuffer;
170 #define MAX_NETFNS 64
172 typedef struct IPMICmdHandler {
173 void (*cmd_handler)(IPMIBmcSim *s,
174 uint8_t *cmd, unsigned int cmd_len,
175 RspBuffer *rsp);
176 unsigned int cmd_len_min;
177 } IPMICmdHandler;
179 typedef struct IPMINetfn {
180 unsigned int cmd_nums;
181 const IPMICmdHandler *cmd_handlers;
182 } IPMINetfn;
184 typedef struct IPMIRcvBufEntry {
185 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
186 uint8_t len;
187 uint8_t buf[MAX_IPMI_MSG_SIZE];
188 } IPMIRcvBufEntry;
190 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
191 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
192 TYPE_IPMI_BMC_SIMULATOR)
193 struct IPMIBmcSim {
194 IPMIBmc parent;
196 QEMUTimer *timer;
198 uint8_t bmc_global_enables;
199 uint8_t msg_flags;
201 bool watchdog_initialized;
202 uint8_t watchdog_use;
203 uint8_t watchdog_action;
204 uint8_t watchdog_pretimeout; /* In seconds */
205 bool watchdog_expired;
206 uint16_t watchdog_timeout; /* in 100's of milliseconds */
208 bool watchdog_running;
209 bool watchdog_preaction_ran;
210 int64_t watchdog_expiry;
212 uint8_t device_id;
213 uint8_t ipmi_version;
214 uint8_t device_rev;
215 uint8_t fwrev1;
216 uint8_t fwrev2;
217 uint32_t mfg_id;
218 uint16_t product_id;
220 uint8_t restart_cause;
222 uint8_t acpi_power_state[2];
223 uint8_t uuid[16];
225 IPMISel sel;
226 IPMISdr sdr;
227 IPMIFru fru;
228 IPMISensor sensors[MAX_SENSORS];
229 char *sdr_filename;
231 /* Odd netfns are for responses, so we only need the even ones. */
232 const IPMINetfn *netfns[MAX_NETFNS / 2];
234 /* We allow one event in the buffer */
235 uint8_t evtbuf[16];
237 QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
240 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
241 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
242 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
243 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
244 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
245 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
246 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
247 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
248 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
250 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
251 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
252 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
253 #define IPMI_BMC_EVENT_LOG_BIT 3
254 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
255 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
256 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
257 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
258 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
259 (1 << IPMI_BMC_EVENT_LOG_BIT))
260 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
261 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
263 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
264 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
265 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
266 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
267 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
268 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
269 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
270 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
271 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
272 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
273 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
274 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
275 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
276 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
277 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
279 struct RspBuffer {
280 uint8_t buffer[MAX_IPMI_MSG_SIZE];
281 unsigned int len;
284 #define RSP_BUFFER_INITIALIZER { }
286 static inline void rsp_buffer_set_error(RspBuffer *rsp, uint8_t byte)
288 rsp->buffer[2] = byte;
291 /* Add a byte to the response. */
292 static inline void rsp_buffer_push(RspBuffer *rsp, uint8_t byte)
294 if (rsp->len >= sizeof(rsp->buffer)) {
295 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
296 return;
298 rsp->buffer[rsp->len++] = byte;
301 static inline void rsp_buffer_pushmore(RspBuffer *rsp, uint8_t *bytes,
302 unsigned int n)
304 if (rsp->len + n >= sizeof(rsp->buffer)) {
305 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
306 return;
309 memcpy(&rsp->buffer[rsp->len], bytes, n);
310 rsp->len += n;
313 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
315 static void ipmi_gettime(struct ipmi_time *time)
317 int64_t stime;
319 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
320 time->tv_sec = stime / 1000000000LL;
321 time->tv_nsec = stime % 1000000000LL;
324 static int64_t ipmi_getmonotime(void)
326 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
329 static void ipmi_timeout(void *opaque)
331 IPMIBmcSim *ibs = opaque;
333 ipmi_sim_handle_timeout(ibs);
336 static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
338 unsigned int val;
339 struct ipmi_time now;
341 ipmi_gettime(&now);
342 val = now.tv_sec + ibs->sel.time_offset;
343 ts[0] = val & 0xff;
344 ts[1] = (val >> 8) & 0xff;
345 ts[2] = (val >> 16) & 0xff;
346 ts[3] = (val >> 24) & 0xff;
349 static void sdr_inc_reservation(IPMISdr *sdr)
351 sdr->reservation++;
352 if (sdr->reservation == 0) {
353 sdr->reservation = 1;
357 static int sdr_add_entry(IPMIBmcSim *ibs,
358 const struct ipmi_sdr_header *sdrh_entry,
359 unsigned int len, uint16_t *recid)
361 struct ipmi_sdr_header *sdrh =
362 (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
364 if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
365 return 1;
368 if (ipmi_sdr_length(sdrh_entry) != len) {
369 return 1;
372 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
373 ibs->sdr.overflow = 1;
374 return 1;
377 memcpy(sdrh, sdrh_entry, len);
378 sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff;
379 sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
380 sdrh->sdr_version = 0x51; /* Conform to IPMI 1.5 spec */
382 if (recid) {
383 *recid = ibs->sdr.next_rec_id;
385 ibs->sdr.next_rec_id++;
386 set_timestamp(ibs, ibs->sdr.last_addition);
387 ibs->sdr.next_free += len;
388 sdr_inc_reservation(&ibs->sdr);
389 return 0;
392 static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
393 unsigned int *retpos, uint16_t *nextrec)
395 unsigned int pos = *retpos;
397 while (pos < sdr->next_free) {
398 struct ipmi_sdr_header *sdrh =
399 (struct ipmi_sdr_header *) &sdr->sdr[pos];
400 uint16_t trec = ipmi_sdr_recid(sdrh);
401 unsigned int nextpos = pos + ipmi_sdr_length(sdrh);
403 if (trec == recid) {
404 if (nextrec) {
405 if (nextpos >= sdr->next_free) {
406 *nextrec = 0xffff;
407 } else {
408 *nextrec = (sdr->sdr[nextpos] |
409 (sdr->sdr[nextpos + 1] << 8));
412 *retpos = pos;
413 return 0;
415 pos = nextpos;
417 return 1;
420 int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
421 const struct ipmi_sdr_compact **sdr, uint16_t *nextrec)
424 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
425 unsigned int pos;
427 pos = 0;
428 if (sdr_find_entry(&ibs->sdr, recid, &pos, nextrec)) {
429 return -1;
432 *sdr = (const struct ipmi_sdr_compact *) &ibs->sdr.sdr[pos];
433 return 0;
436 static void sel_inc_reservation(IPMISel *sel)
438 sel->reservation++;
439 if (sel->reservation == 0) {
440 sel->reservation = 1;
444 /* Returns 1 if the SEL is full and can't hold the event. */
445 static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
447 uint8_t ts[4];
449 event[0] = 0xff;
450 event[1] = 0xff;
451 set_timestamp(ibs, ts);
452 if (event[2] < 0xe0) { /* Don't set timestamps for type 0xe0-0xff. */
453 memcpy(event + 3, ts, 4);
455 if (ibs->sel.next_free == MAX_SEL_SIZE) {
456 ibs->sel.overflow = 1;
457 return 1;
459 event[0] = ibs->sel.next_free & 0xff;
460 event[1] = (ibs->sel.next_free >> 8) & 0xff;
461 memcpy(ibs->sel.last_addition, ts, 4);
462 memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
463 ibs->sel.next_free++;
464 sel_inc_reservation(&ibs->sel);
465 return 0;
468 static int attn_set(IPMIBmcSim *ibs)
470 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
471 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
472 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
475 static int attn_irq_enabled(IPMIBmcSim *ibs)
477 return (IPMI_BMC_MSG_INTS_ON(ibs) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs))
478 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
479 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
482 void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log)
484 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
485 IPMIInterface *s = ibs->parent.intf;
486 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
488 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
489 return;
492 if (log && IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
493 sel_add_event(ibs, evt);
496 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
497 goto out;
500 memcpy(ibs->evtbuf, evt, 16);
501 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
502 k->set_atn(s, 1, attn_irq_enabled(ibs));
503 out:
504 return;
506 static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
507 uint8_t evd1, uint8_t evd2, uint8_t evd3)
509 IPMIInterface *s = ibs->parent.intf;
510 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
511 uint8_t evt[16];
512 IPMISensor *sens = ibs->sensors + sens_num;
514 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
515 return;
517 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
518 return;
521 evt[2] = 0x2; /* System event record */
522 evt[7] = ibs->parent.slave_addr;
523 evt[8] = 0;
524 evt[9] = 0x04; /* Format version */
525 evt[10] = sens->sensor_type;
526 evt[11] = sens_num;
527 evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
528 evt[13] = evd1;
529 evt[14] = evd2;
530 evt[15] = evd3;
532 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
533 sel_add_event(ibs, evt);
536 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
537 return;
540 memcpy(ibs->evtbuf, evt, 16);
541 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
542 k->set_atn(s, 1, attn_irq_enabled(ibs));
545 static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
546 unsigned int bit, unsigned int val,
547 uint8_t evd1, uint8_t evd2, uint8_t evd3)
549 IPMISensor *sens;
550 uint16_t mask;
552 if (sensor >= MAX_SENSORS) {
553 return;
555 if (bit >= 16) {
556 return;
559 mask = (1 << bit);
560 sens = ibs->sensors + sensor;
561 if (val) {
562 sens->states |= mask & sens->states_suppt;
563 if (sens->assert_states & mask) {
564 return; /* Already asserted */
566 sens->assert_states |= mask & sens->assert_suppt;
567 if (sens->assert_enable & mask & sens->assert_states) {
568 /* Send an event on assert */
569 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
571 } else {
572 sens->states &= ~(mask & sens->states_suppt);
573 if (sens->deassert_states & mask) {
574 return; /* Already deasserted */
576 sens->deassert_states |= mask & sens->deassert_suppt;
577 if (sens->deassert_enable & mask & sens->deassert_states) {
578 /* Send an event on deassert */
579 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
584 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
586 unsigned int i, pos;
587 IPMISensor *sens;
589 for (i = 0; i < MAX_SENSORS; i++) {
590 memset(s->sensors + i, 0, sizeof(*sens));
593 pos = 0;
594 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
595 struct ipmi_sdr_compact *sdr =
596 (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
597 unsigned int len = sdr->header.rec_length;
599 if (len < 20) {
600 continue;
602 if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
603 continue; /* Not a sensor SDR we set from */
606 if (sdr->sensor_owner_number >= MAX_SENSORS) {
607 continue;
609 sens = s->sensors + sdr->sensor_owner_number;
611 IPMI_SENSOR_SET_PRESENT(sens, 1);
612 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
613 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
614 sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
615 sens->deassert_suppt =
616 sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
617 sens->states_suppt =
618 sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
619 sens->sensor_type = sdr->sensor_type;
620 sens->evt_reading_type_code = sdr->reading_type & 0x7f;
622 /* Enable all the events that are supported. */
623 sens->assert_enable = sens->assert_suppt;
624 sens->deassert_enable = sens->deassert_suppt;
628 static int ipmi_register_netfn(IPMIBmcSim *s, unsigned int netfn,
629 const IPMINetfn *netfnd)
631 if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
632 return -1;
634 s->netfns[netfn / 2] = netfnd;
635 return 0;
638 static const IPMICmdHandler *ipmi_get_handler(IPMIBmcSim *ibs,
639 unsigned int netfn,
640 unsigned int cmd)
642 const IPMICmdHandler *hdl;
644 if (netfn & 1 || netfn >= MAX_NETFNS || !ibs->netfns[netfn / 2]) {
645 return NULL;
648 if (cmd >= ibs->netfns[netfn / 2]->cmd_nums) {
649 return NULL;
652 hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd];
653 if (!hdl->cmd_handler) {
654 return NULL;
657 return hdl;
660 static void next_timeout(IPMIBmcSim *ibs)
662 int64_t next;
663 if (ibs->watchdog_running) {
664 next = ibs->watchdog_expiry;
665 } else {
666 /* Wait a minute */
667 next = ipmi_getmonotime() + 60 * 1000000000LL;
669 timer_mod_ns(ibs->timer, next);
672 static void ipmi_sim_handle_command(IPMIBmc *b,
673 uint8_t *cmd, unsigned int cmd_len,
674 unsigned int max_cmd_len,
675 uint8_t msg_id)
677 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
678 IPMIInterface *s = ibs->parent.intf;
679 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
680 const IPMICmdHandler *hdl;
681 RspBuffer rsp = RSP_BUFFER_INITIALIZER;
683 /* Set up the response, set the low bit of NETFN. */
684 /* Note that max_rsp_len must be at least 3 */
685 if (sizeof(rsp.buffer) < 3) {
686 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
687 goto out;
690 rsp_buffer_push(&rsp, cmd[0] | 0x04);
691 rsp_buffer_push(&rsp, cmd[1]);
692 rsp_buffer_push(&rsp, 0); /* Assume success */
694 /* If it's too short or it was truncated, return an error. */
695 if (cmd_len < 2) {
696 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
697 goto out;
699 if (cmd_len > max_cmd_len) {
700 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
701 goto out;
704 if ((cmd[0] & 0x03) != 0) {
705 /* Only have stuff on LUN 0 */
706 rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN);
707 goto out;
710 hdl = ipmi_get_handler(ibs, cmd[0] >> 2, cmd[1]);
711 if (!hdl) {
712 rsp_buffer_set_error(&rsp, IPMI_CC_INVALID_CMD);
713 goto out;
716 if (cmd_len < hdl->cmd_len_min) {
717 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
718 goto out;
721 hdl->cmd_handler(ibs, cmd, cmd_len, &rsp);
723 out:
724 k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
726 next_timeout(ibs);
729 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
731 IPMIInterface *s = ibs->parent.intf;
732 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
734 if (!ibs->watchdog_running) {
735 goto out;
738 if (!ibs->watchdog_preaction_ran) {
739 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
740 case IPMI_BMC_WATCHDOG_PRE_NMI:
741 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
742 k->do_hw_op(s, IPMI_SEND_NMI, 0);
743 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
744 0xc8, (2 << 4) | 0xf, 0xff);
745 break;
747 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
748 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
749 k->set_atn(s, 1, attn_irq_enabled(ibs));
750 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
751 0xc8, (3 << 4) | 0xf, 0xff);
752 break;
754 default:
755 goto do_full_expiry;
758 ibs->watchdog_preaction_ran = 1;
759 /* Issued the pretimeout, do the rest of the timeout now. */
760 ibs->watchdog_expiry = ipmi_getmonotime();
761 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
762 goto out;
765 do_full_expiry:
766 ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
767 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
768 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
769 case IPMI_BMC_WATCHDOG_ACTION_NONE:
770 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
771 0xc0, ibs->watchdog_use & 0xf, 0xff);
772 break;
774 case IPMI_BMC_WATCHDOG_ACTION_RESET:
775 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
776 0xc1, ibs->watchdog_use & 0xf, 0xff);
777 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
778 break;
780 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
781 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
782 0xc2, ibs->watchdog_use & 0xf, 0xff);
783 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
784 break;
786 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
787 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
788 0xc3, ibs->watchdog_use & 0xf, 0xff);
789 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
790 break;
793 out:
794 next_timeout(ibs);
797 static void chassis_capabilities(IPMIBmcSim *ibs,
798 uint8_t *cmd, unsigned int cmd_len,
799 RspBuffer *rsp)
801 rsp_buffer_push(rsp, 0);
802 rsp_buffer_push(rsp, ibs->parent.slave_addr);
803 rsp_buffer_push(rsp, ibs->parent.slave_addr);
804 rsp_buffer_push(rsp, ibs->parent.slave_addr);
805 rsp_buffer_push(rsp, ibs->parent.slave_addr);
808 static void chassis_status(IPMIBmcSim *ibs,
809 uint8_t *cmd, unsigned int cmd_len,
810 RspBuffer *rsp)
812 rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */
813 rsp_buffer_push(rsp, 0);
814 rsp_buffer_push(rsp, 0);
815 rsp_buffer_push(rsp, 0);
818 static void chassis_control(IPMIBmcSim *ibs,
819 uint8_t *cmd, unsigned int cmd_len,
820 RspBuffer *rsp)
822 IPMIInterface *s = ibs->parent.intf;
823 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
825 switch (cmd[2] & 0xf) {
826 case 0: /* power down */
827 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0));
828 break;
829 case 1: /* power up */
830 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0));
831 break;
832 case 2: /* power cycle */
833 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0));
834 break;
835 case 3: /* hard reset */
836 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0));
837 break;
838 case 4: /* pulse diagnostic interrupt */
839 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0));
840 break;
841 case 5: /* soft shutdown via ACPI by overtemp emulation */
842 rsp_buffer_set_error(rsp, k->do_hw_op(s,
843 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0));
844 break;
845 default:
846 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
847 return;
851 static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
852 uint8_t *cmd, unsigned int cmd_len,
853 RspBuffer *rsp)
856 rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */
857 rsp_buffer_push(rsp, 0); /* Channel 0 */
860 static void get_device_id(IPMIBmcSim *ibs,
861 uint8_t *cmd, unsigned int cmd_len,
862 RspBuffer *rsp)
864 rsp_buffer_push(rsp, ibs->device_id);
865 rsp_buffer_push(rsp, ibs->device_rev & 0xf);
866 rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
867 rsp_buffer_push(rsp, ibs->fwrev2);
868 rsp_buffer_push(rsp, ibs->ipmi_version);
869 rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */
870 rsp_buffer_push(rsp, ibs->mfg_id & 0xff);
871 rsp_buffer_push(rsp, (ibs->mfg_id >> 8) & 0xff);
872 rsp_buffer_push(rsp, (ibs->mfg_id >> 16) & 0xff);
873 rsp_buffer_push(rsp, ibs->product_id & 0xff);
874 rsp_buffer_push(rsp, (ibs->product_id >> 8) & 0xff);
877 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
879 IPMIInterface *s = ibs->parent.intf;
880 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
881 bool irqs_on;
883 ibs->bmc_global_enables = val;
885 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
886 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
888 k->set_irq_enable(s, irqs_on);
891 static void cold_reset(IPMIBmcSim *ibs,
892 uint8_t *cmd, unsigned int cmd_len,
893 RspBuffer *rsp)
895 IPMIInterface *s = ibs->parent.intf;
896 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
898 /* Disable all interrupts */
899 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
901 if (k->reset) {
902 k->reset(s, true);
906 static void warm_reset(IPMIBmcSim *ibs,
907 uint8_t *cmd, unsigned int cmd_len,
908 RspBuffer *rsp)
910 IPMIInterface *s = ibs->parent.intf;
911 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
913 if (k->reset) {
914 k->reset(s, false);
917 static void set_acpi_power_state(IPMIBmcSim *ibs,
918 uint8_t *cmd, unsigned int cmd_len,
919 RspBuffer *rsp)
921 ibs->acpi_power_state[0] = cmd[2];
922 ibs->acpi_power_state[1] = cmd[3];
925 static void get_acpi_power_state(IPMIBmcSim *ibs,
926 uint8_t *cmd, unsigned int cmd_len,
927 RspBuffer *rsp)
929 rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
930 rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
933 static void get_device_guid(IPMIBmcSim *ibs,
934 uint8_t *cmd, unsigned int cmd_len,
935 RspBuffer *rsp)
937 unsigned int i;
939 for (i = 0; i < 16; i++) {
940 rsp_buffer_push(rsp, ibs->uuid[i]);
944 static void set_bmc_global_enables(IPMIBmcSim *ibs,
945 uint8_t *cmd, unsigned int cmd_len,
946 RspBuffer *rsp)
948 set_global_enables(ibs, cmd[2]);
951 static void get_bmc_global_enables(IPMIBmcSim *ibs,
952 uint8_t *cmd, unsigned int cmd_len,
953 RspBuffer *rsp)
955 rsp_buffer_push(rsp, ibs->bmc_global_enables);
958 static void clr_msg_flags(IPMIBmcSim *ibs,
959 uint8_t *cmd, unsigned int cmd_len,
960 RspBuffer *rsp)
962 IPMIInterface *s = ibs->parent.intf;
963 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
965 ibs->msg_flags &= ~cmd[2];
966 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
969 static void get_msg_flags(IPMIBmcSim *ibs,
970 uint8_t *cmd, unsigned int cmd_len,
971 RspBuffer *rsp)
973 rsp_buffer_push(rsp, ibs->msg_flags);
976 static void read_evt_msg_buf(IPMIBmcSim *ibs,
977 uint8_t *cmd, unsigned int cmd_len,
978 RspBuffer *rsp)
980 IPMIInterface *s = ibs->parent.intf;
981 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
982 unsigned int i;
984 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
985 rsp_buffer_set_error(rsp, 0x80);
986 return;
988 for (i = 0; i < 16; i++) {
989 rsp_buffer_push(rsp, ibs->evtbuf[i]);
991 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
992 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
995 static void get_msg(IPMIBmcSim *ibs,
996 uint8_t *cmd, unsigned int cmd_len,
997 RspBuffer *rsp)
999 IPMIRcvBufEntry *msg;
1001 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
1002 rsp_buffer_set_error(rsp, 0x80); /* Queue empty */
1003 goto out;
1005 rsp_buffer_push(rsp, 0); /* Channel 0 */
1006 msg = QTAILQ_FIRST(&ibs->rcvbufs);
1007 rsp_buffer_pushmore(rsp, msg->buf, msg->len);
1008 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
1009 g_free(msg);
1011 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
1012 IPMIInterface *s = ibs->parent.intf;
1013 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1015 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1016 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
1019 out:
1020 return;
1023 static unsigned char
1024 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
1026 for (; size > 0; size--, data++) {
1027 csum += *data;
1030 return -csum;
1033 static void send_msg(IPMIBmcSim *ibs,
1034 uint8_t *cmd, unsigned int cmd_len,
1035 RspBuffer *rsp)
1037 IPMIInterface *s = ibs->parent.intf;
1038 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1039 IPMIRcvBufEntry *msg;
1040 uint8_t *buf;
1041 uint8_t netfn, rqLun, rsLun, rqSeq;
1043 if (cmd[2] != 0) {
1044 /* We only handle channel 0 with no options */
1045 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1046 return;
1049 if (cmd_len < 10) {
1050 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
1051 return;
1054 if (cmd[3] != 0x40) {
1055 /* We only emulate a MC at address 0x40. */
1056 rsp_buffer_set_error(rsp, 0x83); /* NAK on write */
1057 return;
1060 cmd += 3; /* Skip the header. */
1061 cmd_len -= 3;
1064 * At this point we "send" the message successfully. Any error will
1065 * be returned in the response.
1067 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
1068 cmd[3] != 0x20) { /* Improper response address */
1069 return; /* No response */
1072 netfn = cmd[1] >> 2;
1073 rqLun = cmd[4] & 0x3;
1074 rsLun = cmd[1] & 0x3;
1075 rqSeq = cmd[4] >> 2;
1077 if (rqLun != 2) {
1078 /* We only support LUN 2 coming back to us. */
1079 return;
1082 msg = g_malloc(sizeof(*msg));
1083 msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
1084 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
1085 msg->buf[2] = cmd[0]; /* rsSA */
1086 msg->buf[3] = (rqSeq << 2) | rsLun;
1087 msg->buf[4] = cmd[5]; /* Cmd */
1088 msg->buf[5] = 0; /* Completion Code */
1089 msg->len = 6;
1091 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
1092 /* Not a command we handle. */
1093 msg->buf[5] = IPMI_CC_INVALID_CMD;
1094 goto end_msg;
1097 buf = msg->buf + msg->len; /* After the CC */
1098 buf[0] = 0;
1099 buf[1] = 0;
1100 buf[2] = 0;
1101 buf[3] = 0;
1102 buf[4] = 0x51;
1103 buf[5] = 0;
1104 buf[6] = 0;
1105 buf[7] = 0;
1106 buf[8] = 0;
1107 buf[9] = 0;
1108 buf[10] = 0;
1109 msg->len += 11;
1111 end_msg:
1112 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1113 msg->len++;
1114 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1115 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1116 k->set_atn(s, 1, attn_irq_enabled(ibs));
1119 static void do_watchdog_reset(IPMIBmcSim *ibs)
1121 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1122 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1123 ibs->watchdog_running = 0;
1124 return;
1126 ibs->watchdog_preaction_ran = 0;
1129 /* Timeout is in tenths of a second, offset is in seconds */
1130 ibs->watchdog_expiry = ipmi_getmonotime();
1131 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1132 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1133 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1135 ibs->watchdog_running = 1;
1138 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1139 uint8_t *cmd, unsigned int cmd_len,
1140 RspBuffer *rsp)
1142 if (!ibs->watchdog_initialized) {
1143 rsp_buffer_set_error(rsp, 0x80);
1144 return;
1146 do_watchdog_reset(ibs);
1149 static void set_watchdog_timer(IPMIBmcSim *ibs,
1150 uint8_t *cmd, unsigned int cmd_len,
1151 RspBuffer *rsp)
1153 IPMIInterface *s = ibs->parent.intf;
1154 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1155 unsigned int val;
1157 val = cmd[2] & 0x7; /* Validate use */
1158 if (val == 0 || val > 5) {
1159 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1160 return;
1162 val = cmd[3] & 0x7; /* Validate action */
1163 switch (val) {
1164 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1165 break;
1167 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1168 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1));
1169 break;
1171 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1172 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1));
1173 break;
1175 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1176 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1));
1177 break;
1179 default:
1180 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1182 if (rsp->buffer[2]) {
1183 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1184 return;
1187 val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1188 switch (val) {
1189 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1190 case IPMI_BMC_WATCHDOG_PRE_NONE:
1191 break;
1193 case IPMI_BMC_WATCHDOG_PRE_NMI:
1194 if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1195 /* NMI not supported. */
1196 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1197 return;
1199 break;
1201 default:
1202 /* We don't support PRE_SMI */
1203 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1204 return;
1207 ibs->watchdog_initialized = 1;
1208 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1209 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1210 ibs->watchdog_pretimeout = cmd[4];
1211 ibs->watchdog_expired &= ~cmd[5];
1212 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1213 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1214 do_watchdog_reset(ibs);
1215 } else {
1216 ibs->watchdog_running = 0;
1220 static void get_watchdog_timer(IPMIBmcSim *ibs,
1221 uint8_t *cmd, unsigned int cmd_len,
1222 RspBuffer *rsp)
1224 rsp_buffer_push(rsp, ibs->watchdog_use);
1225 rsp_buffer_push(rsp, ibs->watchdog_action);
1226 rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
1227 rsp_buffer_push(rsp, ibs->watchdog_expired);
1228 if (ibs->watchdog_running) {
1229 long timeout;
1230 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1231 / 100000000);
1232 rsp_buffer_push(rsp, timeout & 0xff);
1233 rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
1234 } else {
1235 rsp_buffer_push(rsp, 0);
1236 rsp_buffer_push(rsp, 0);
1240 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1241 uint8_t *cmd, unsigned int cmd_len,
1242 RspBuffer *rsp)
1244 unsigned int i;
1246 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */
1247 rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
1248 rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
1249 rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1250 rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1251 for (i = 0; i < 4; i++) {
1252 rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
1254 for (i = 0; i < 4; i++) {
1255 rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
1257 /* Only modal support, reserve supported */
1258 rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
1261 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1262 uint8_t *cmd, unsigned int cmd_len,
1263 RspBuffer *rsp)
1265 rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
1266 rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
1269 static void get_sdr(IPMIBmcSim *ibs,
1270 uint8_t *cmd, unsigned int cmd_len,
1271 RspBuffer *rsp)
1273 unsigned int pos;
1274 uint16_t nextrec;
1275 struct ipmi_sdr_header *sdrh;
1277 if (cmd[6]) {
1278 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1279 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1280 return;
1284 pos = 0;
1285 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1286 &pos, &nextrec)) {
1287 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1288 return;
1291 sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1293 if (cmd[6] > ipmi_sdr_length(sdrh)) {
1294 rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE);
1295 return;
1298 rsp_buffer_push(rsp, nextrec & 0xff);
1299 rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
1301 if (cmd[7] == 0xff) {
1302 cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1305 if ((cmd[7] + rsp->len) > sizeof(rsp->buffer)) {
1306 rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES);
1307 return;
1310 rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1313 static void add_sdr(IPMIBmcSim *ibs,
1314 uint8_t *cmd, unsigned int cmd_len,
1315 RspBuffer *rsp)
1317 uint16_t recid;
1318 struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1320 if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1321 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1322 return;
1324 rsp_buffer_push(rsp, recid & 0xff);
1325 rsp_buffer_push(rsp, (recid >> 8) & 0xff);
1328 static void clear_sdr_rep(IPMIBmcSim *ibs,
1329 uint8_t *cmd, unsigned int cmd_len,
1330 RspBuffer *rsp)
1332 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1333 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1334 return;
1337 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1338 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1339 return;
1341 if (cmd[7] == 0xaa) {
1342 ibs->sdr.next_free = 0;
1343 ibs->sdr.overflow = 0;
1344 set_timestamp(ibs, ibs->sdr.last_clear);
1345 rsp_buffer_push(rsp, 1); /* Erasure complete */
1346 sdr_inc_reservation(&ibs->sdr);
1347 } else if (cmd[7] == 0) {
1348 rsp_buffer_push(rsp, 1); /* Erasure complete */
1349 } else {
1350 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1351 return;
1355 static void get_sel_info(IPMIBmcSim *ibs,
1356 uint8_t *cmd, unsigned int cmd_len,
1357 RspBuffer *rsp)
1359 unsigned int i, val;
1361 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */
1362 rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
1363 rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
1364 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1365 rsp_buffer_push(rsp, val & 0xff);
1366 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1367 for (i = 0; i < 4; i++) {
1368 rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
1370 for (i = 0; i < 4; i++) {
1371 rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
1373 /* Only support Reserve SEL */
1374 rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
1377 static void get_fru_area_info(IPMIBmcSim *ibs,
1378 uint8_t *cmd, unsigned int cmd_len,
1379 RspBuffer *rsp)
1381 uint8_t fruid;
1382 uint16_t fru_entry_size;
1384 fruid = cmd[2];
1386 if (fruid >= ibs->fru.nentries) {
1387 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1388 return;
1391 fru_entry_size = ibs->fru.areasize;
1393 rsp_buffer_push(rsp, fru_entry_size & 0xff);
1394 rsp_buffer_push(rsp, fru_entry_size >> 8 & 0xff);
1395 rsp_buffer_push(rsp, 0x0);
1398 static void read_fru_data(IPMIBmcSim *ibs,
1399 uint8_t *cmd, unsigned int cmd_len,
1400 RspBuffer *rsp)
1402 uint8_t fruid;
1403 uint16_t offset;
1404 int i;
1405 uint8_t *fru_entry;
1406 unsigned int count;
1408 fruid = cmd[2];
1409 offset = (cmd[3] | cmd[4] << 8);
1411 if (fruid >= ibs->fru.nentries) {
1412 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1413 return;
1416 if (offset >= ibs->fru.areasize - 1) {
1417 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1418 return;
1421 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1423 count = MIN(cmd[5], ibs->fru.areasize - offset);
1425 rsp_buffer_push(rsp, count & 0xff);
1426 for (i = 0; i < count; i++) {
1427 rsp_buffer_push(rsp, fru_entry[offset + i]);
1431 static void write_fru_data(IPMIBmcSim *ibs,
1432 uint8_t *cmd, unsigned int cmd_len,
1433 RspBuffer *rsp)
1435 uint8_t fruid;
1436 uint16_t offset;
1437 uint8_t *fru_entry;
1438 unsigned int count;
1440 fruid = cmd[2];
1441 offset = (cmd[3] | cmd[4] << 8);
1443 if (fruid >= ibs->fru.nentries) {
1444 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1445 return;
1448 if (offset >= ibs->fru.areasize - 1) {
1449 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1450 return;
1453 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1455 count = MIN(cmd_len - 5, ibs->fru.areasize - offset);
1457 memcpy(fru_entry + offset, cmd + 5, count);
1459 rsp_buffer_push(rsp, count & 0xff);
1462 static void reserve_sel(IPMIBmcSim *ibs,
1463 uint8_t *cmd, unsigned int cmd_len,
1464 RspBuffer *rsp)
1466 rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
1467 rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
1470 static void get_sel_entry(IPMIBmcSim *ibs,
1471 uint8_t *cmd, unsigned int cmd_len,
1472 RspBuffer *rsp)
1474 unsigned int val;
1476 if (cmd[6]) {
1477 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1478 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1479 return;
1482 if (ibs->sel.next_free == 0) {
1483 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1484 return;
1486 if (cmd[6] > 15) {
1487 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1488 return;
1490 if (cmd[7] == 0xff) {
1491 cmd[7] = 16;
1492 } else if ((cmd[7] + cmd[6]) > 16) {
1493 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1494 return;
1495 } else {
1496 cmd[7] += cmd[6];
1499 val = cmd[4] | (cmd[5] << 8);
1500 if (val == 0xffff) {
1501 val = ibs->sel.next_free - 1;
1502 } else if (val >= ibs->sel.next_free) {
1503 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1504 return;
1506 if ((val + 1) == ibs->sel.next_free) {
1507 rsp_buffer_push(rsp, 0xff);
1508 rsp_buffer_push(rsp, 0xff);
1509 } else {
1510 rsp_buffer_push(rsp, (val + 1) & 0xff);
1511 rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
1513 for (; cmd[6] < cmd[7]; cmd[6]++) {
1514 rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
1518 static void add_sel_entry(IPMIBmcSim *ibs,
1519 uint8_t *cmd, unsigned int cmd_len,
1520 RspBuffer *rsp)
1522 if (sel_add_event(ibs, cmd + 2)) {
1523 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1524 return;
1526 /* sel_add_event fills in the record number. */
1527 rsp_buffer_push(rsp, cmd[2]);
1528 rsp_buffer_push(rsp, cmd[3]);
1531 static void clear_sel(IPMIBmcSim *ibs,
1532 uint8_t *cmd, unsigned int cmd_len,
1533 RspBuffer *rsp)
1535 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1536 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1537 return;
1540 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1541 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1542 return;
1544 if (cmd[7] == 0xaa) {
1545 ibs->sel.next_free = 0;
1546 ibs->sel.overflow = 0;
1547 set_timestamp(ibs, ibs->sdr.last_clear);
1548 rsp_buffer_push(rsp, 1); /* Erasure complete */
1549 sel_inc_reservation(&ibs->sel);
1550 } else if (cmd[7] == 0) {
1551 rsp_buffer_push(rsp, 1); /* Erasure complete */
1552 } else {
1553 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1554 return;
1558 static void get_sel_time(IPMIBmcSim *ibs,
1559 uint8_t *cmd, unsigned int cmd_len,
1560 RspBuffer *rsp)
1562 uint32_t val;
1563 struct ipmi_time now;
1565 ipmi_gettime(&now);
1566 val = now.tv_sec + ibs->sel.time_offset;
1567 rsp_buffer_push(rsp, val & 0xff);
1568 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1569 rsp_buffer_push(rsp, (val >> 16) & 0xff);
1570 rsp_buffer_push(rsp, (val >> 24) & 0xff);
1573 static void set_sel_time(IPMIBmcSim *ibs,
1574 uint8_t *cmd, unsigned int cmd_len,
1575 RspBuffer *rsp)
1577 uint32_t val;
1578 struct ipmi_time now;
1580 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1581 ipmi_gettime(&now);
1582 ibs->sel.time_offset = now.tv_sec - ((long) val);
1585 static void platform_event_msg(IPMIBmcSim *ibs,
1586 uint8_t *cmd, unsigned int cmd_len,
1587 RspBuffer *rsp)
1589 uint8_t event[16];
1591 event[2] = 2; /* System event record */
1592 event[7] = cmd[2]; /* Generator ID */
1593 event[8] = 0;
1594 event[9] = cmd[3]; /* EvMRev */
1595 event[10] = cmd[4]; /* Sensor type */
1596 event[11] = cmd[5]; /* Sensor number */
1597 event[12] = cmd[6]; /* Event dir / Event type */
1598 event[13] = cmd[7]; /* Event data 1 */
1599 event[14] = cmd[8]; /* Event data 2 */
1600 event[15] = cmd[9]; /* Event data 3 */
1602 if (sel_add_event(ibs, event)) {
1603 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1607 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1608 uint8_t *cmd, unsigned int cmd_len,
1609 RspBuffer *rsp)
1611 IPMISensor *sens;
1613 if ((cmd[2] >= MAX_SENSORS) ||
1614 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1615 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1616 return;
1618 sens = ibs->sensors + cmd[2];
1619 switch ((cmd[3] >> 4) & 0x3) {
1620 case 0: /* Do not change */
1621 break;
1622 case 1: /* Enable bits */
1623 if (cmd_len > 4) {
1624 sens->assert_enable |= cmd[4];
1626 if (cmd_len > 5) {
1627 sens->assert_enable |= cmd[5] << 8;
1629 if (cmd_len > 6) {
1630 sens->deassert_enable |= cmd[6];
1632 if (cmd_len > 7) {
1633 sens->deassert_enable |= cmd[7] << 8;
1635 break;
1636 case 2: /* Disable bits */
1637 if (cmd_len > 4) {
1638 sens->assert_enable &= ~cmd[4];
1640 if (cmd_len > 5) {
1641 sens->assert_enable &= ~(cmd[5] << 8);
1643 if (cmd_len > 6) {
1644 sens->deassert_enable &= ~cmd[6];
1646 if (cmd_len > 7) {
1647 sens->deassert_enable &= ~(cmd[7] << 8);
1649 break;
1650 case 3:
1651 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1652 return;
1654 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1657 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1658 uint8_t *cmd, unsigned int cmd_len,
1659 RspBuffer *rsp)
1661 IPMISensor *sens;
1663 if ((cmd[2] >= MAX_SENSORS) ||
1664 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1665 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1666 return;
1668 sens = ibs->sensors + cmd[2];
1669 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1670 rsp_buffer_push(rsp, sens->assert_enable & 0xff);
1671 rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
1672 rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
1673 rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
1676 static void rearm_sensor_evts(IPMIBmcSim *ibs,
1677 uint8_t *cmd, unsigned int cmd_len,
1678 RspBuffer *rsp)
1680 IPMISensor *sens;
1682 if ((cmd[2] >= MAX_SENSORS) ||
1683 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1684 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1685 return;
1687 sens = ibs->sensors + cmd[2];
1689 if ((cmd[3] & 0x80) == 0) {
1690 /* Just clear everything */
1691 sens->states = 0;
1692 return;
1696 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1697 uint8_t *cmd, unsigned int cmd_len,
1698 RspBuffer *rsp)
1700 IPMISensor *sens;
1702 if ((cmd[2] >= MAX_SENSORS) ||
1703 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1704 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1705 return;
1707 sens = ibs->sensors + cmd[2];
1708 rsp_buffer_push(rsp, sens->reading);
1709 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1710 rsp_buffer_push(rsp, sens->assert_states & 0xff);
1711 rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
1712 rsp_buffer_push(rsp, sens->deassert_states & 0xff);
1713 rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
1716 static void get_sensor_reading(IPMIBmcSim *ibs,
1717 uint8_t *cmd, unsigned int cmd_len,
1718 RspBuffer *rsp)
1720 IPMISensor *sens;
1722 if ((cmd[2] >= MAX_SENSORS) ||
1723 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1724 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1725 return;
1727 sens = ibs->sensors + cmd[2];
1728 rsp_buffer_push(rsp, sens->reading);
1729 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1730 rsp_buffer_push(rsp, sens->states & 0xff);
1731 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1732 rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
1736 static void set_sensor_type(IPMIBmcSim *ibs,
1737 uint8_t *cmd, unsigned int cmd_len,
1738 RspBuffer *rsp)
1740 IPMISensor *sens;
1743 if ((cmd[2] >= MAX_SENSORS) ||
1744 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1745 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1746 return;
1748 sens = ibs->sensors + cmd[2];
1749 sens->sensor_type = cmd[3];
1750 sens->evt_reading_type_code = cmd[4] & 0x7f;
1753 static void get_sensor_type(IPMIBmcSim *ibs,
1754 uint8_t *cmd, unsigned int cmd_len,
1755 RspBuffer *rsp)
1757 IPMISensor *sens;
1760 if ((cmd[2] >= MAX_SENSORS) ||
1761 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1762 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1763 return;
1765 sens = ibs->sensors + cmd[2];
1766 rsp_buffer_push(rsp, sens->sensor_type);
1767 rsp_buffer_push(rsp, sens->evt_reading_type_code);
1771 static const IPMICmdHandler chassis_cmds[] = {
1772 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
1773 [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
1774 [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
1775 [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
1777 static const IPMINetfn chassis_netfn = {
1778 .cmd_nums = ARRAY_SIZE(chassis_cmds),
1779 .cmd_handlers = chassis_cmds
1782 static const IPMICmdHandler sensor_event_cmds[] = {
1783 [IPMI_CMD_PLATFORM_EVENT_MSG] = { platform_event_msg, 10 },
1784 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
1785 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
1786 [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
1787 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
1788 [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
1789 [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
1790 [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
1792 static const IPMINetfn sensor_event_netfn = {
1793 .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
1794 .cmd_handlers = sensor_event_cmds
1797 static const IPMICmdHandler app_cmds[] = {
1798 [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
1799 [IPMI_CMD_COLD_RESET] = { cold_reset },
1800 [IPMI_CMD_WARM_RESET] = { warm_reset },
1801 [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
1802 [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
1803 [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
1804 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
1805 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
1806 [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
1807 [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
1808 [IPMI_CMD_GET_MSG] = { get_msg },
1809 [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
1810 [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
1811 [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
1812 [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
1813 [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
1815 static const IPMINetfn app_netfn = {
1816 .cmd_nums = ARRAY_SIZE(app_cmds),
1817 .cmd_handlers = app_cmds
1820 static const IPMICmdHandler storage_cmds[] = {
1821 [IPMI_CMD_GET_FRU_AREA_INFO] = { get_fru_area_info, 3 },
1822 [IPMI_CMD_READ_FRU_DATA] = { read_fru_data, 5 },
1823 [IPMI_CMD_WRITE_FRU_DATA] = { write_fru_data, 5 },
1824 [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
1825 [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
1826 [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
1827 [IPMI_CMD_ADD_SDR] = { add_sdr },
1828 [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
1829 [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
1830 [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
1831 [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
1832 [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
1833 [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
1834 [IPMI_CMD_GET_SEL_TIME] = { get_sel_time },
1835 [IPMI_CMD_SET_SEL_TIME] = { set_sel_time, 6 },
1838 static const IPMINetfn storage_netfn = {
1839 .cmd_nums = ARRAY_SIZE(storage_cmds),
1840 .cmd_handlers = storage_cmds
1843 static void register_cmds(IPMIBmcSim *s)
1845 ipmi_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
1846 ipmi_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
1847 ipmi_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
1848 ipmi_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
1851 static uint8_t init_sdrs[] = {
1852 /* Watchdog device */
1853 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1854 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1855 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1856 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1857 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1860 static void ipmi_sdr_init(IPMIBmcSim *ibs)
1862 unsigned int i;
1863 int len;
1864 size_t sdrs_size;
1865 uint8_t *sdrs;
1867 sdrs_size = sizeof(init_sdrs);
1868 sdrs = init_sdrs;
1869 if (ibs->sdr_filename &&
1870 !g_file_get_contents(ibs->sdr_filename, (gchar **) &sdrs, &sdrs_size,
1871 NULL)) {
1872 error_report("failed to load sdr file '%s'", ibs->sdr_filename);
1873 sdrs_size = sizeof(init_sdrs);
1874 sdrs = init_sdrs;
1877 for (i = 0; i < sdrs_size; i += len) {
1878 struct ipmi_sdr_header *sdrh;
1880 if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
1881 error_report("Problem with recid 0x%4.4x", i);
1882 break;
1884 sdrh = (struct ipmi_sdr_header *) &sdrs[i];
1885 len = ipmi_sdr_length(sdrh);
1886 if (i + len > sdrs_size) {
1887 error_report("Problem with recid 0x%4.4x", i);
1888 break;
1890 sdr_add_entry(ibs, sdrh, len, NULL);
1893 if (sdrs != init_sdrs) {
1894 g_free(sdrs);
1898 static const VMStateDescription vmstate_ipmi_sim = {
1899 .name = TYPE_IPMI_BMC_SIMULATOR,
1900 .version_id = 1,
1901 .minimum_version_id = 1,
1902 .fields = (VMStateField[]) {
1903 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
1904 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
1905 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
1906 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
1907 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
1908 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
1909 VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
1910 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
1911 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
1912 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
1913 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
1914 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
1915 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
1916 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
1917 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
1918 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
1919 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
1920 IPMIBmcSim),
1921 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
1922 VMSTATE_END_OF_LIST()
1926 static void ipmi_fru_init(IPMIFru *fru)
1928 int fsize;
1929 int size = 0;
1931 if (!fru->filename) {
1932 goto out;
1935 fsize = get_image_size(fru->filename);
1936 if (fsize > 0) {
1937 size = QEMU_ALIGN_UP(fsize, fru->areasize);
1938 fru->data = g_malloc0(size);
1939 if (load_image_size(fru->filename, fru->data, fsize) != fsize) {
1940 error_report("Could not load file '%s'", fru->filename);
1941 g_free(fru->data);
1942 fru->data = NULL;
1946 out:
1947 if (!fru->data) {
1948 /* give one default FRU */
1949 size = fru->areasize;
1950 fru->data = g_malloc0(size);
1953 fru->nentries = size / fru->areasize;
1956 static void ipmi_sim_realize(DeviceState *dev, Error **errp)
1958 IPMIBmc *b = IPMI_BMC(dev);
1959 unsigned int i;
1960 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
1962 QTAILQ_INIT(&ibs->rcvbufs);
1964 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
1965 ibs->device_id = 0x20;
1966 ibs->ipmi_version = 0x02; /* IPMI 2.0 */
1967 ibs->restart_cause = 0;
1968 for (i = 0; i < 4; i++) {
1969 ibs->sel.last_addition[i] = 0xff;
1970 ibs->sel.last_clear[i] = 0xff;
1971 ibs->sdr.last_addition[i] = 0xff;
1972 ibs->sdr.last_clear[i] = 0xff;
1975 ipmi_sdr_init(ibs);
1977 ipmi_fru_init(&ibs->fru);
1979 ibs->acpi_power_state[0] = 0;
1980 ibs->acpi_power_state[1] = 0;
1982 if (qemu_uuid_set) {
1983 memcpy(&ibs->uuid, &qemu_uuid, 16);
1984 } else {
1985 memset(&ibs->uuid, 0, 16);
1988 ipmi_init_sensors_from_sdrs(ibs);
1989 register_cmds(ibs);
1991 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
1993 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
1996 static Property ipmi_sim_properties[] = {
1997 DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim, fru.areasize, 1024),
1998 DEFINE_PROP_STRING("frudatafile", IPMIBmcSim, fru.filename),
1999 DEFINE_PROP_STRING("sdrfile", IPMIBmcSim, sdr_filename),
2000 DEFINE_PROP_UINT8("device_id", IPMIBmcSim, device_id, 0x20),
2001 DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim, ipmi_version, 0x02),
2002 DEFINE_PROP_UINT8("device_rev", IPMIBmcSim, device_rev, 0),
2003 DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim, fwrev1, 0),
2004 DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim, fwrev2, 0),
2005 DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim, mfg_id, 0),
2006 DEFINE_PROP_UINT16("product_id", IPMIBmcSim, product_id, 0),
2007 DEFINE_PROP_END_OF_LIST(),
2010 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
2012 DeviceClass *dc = DEVICE_CLASS(oc);
2013 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
2015 dc->hotpluggable = false;
2016 dc->realize = ipmi_sim_realize;
2017 dc->props = ipmi_sim_properties;
2018 bk->handle_command = ipmi_sim_handle_command;
2021 static const TypeInfo ipmi_sim_type = {
2022 .name = TYPE_IPMI_BMC_SIMULATOR,
2023 .parent = TYPE_IPMI_BMC,
2024 .instance_size = sizeof(IPMIBmcSim),
2025 .class_init = ipmi_sim_class_init,
2028 static void ipmi_sim_register_types(void)
2030 type_register_static(&ipmi_sim_type);
2033 type_init(ipmi_sim_register_types)