block/backup: avoid copying less than full target clusters
[qemu/rayw.git] / hw / ipmi / ipmi_bmc_sim.c
blob51d234aa1bf280ea1b6c560b49fafe8616fe1cac
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"
31 #define IPMI_NETFN_CHASSIS 0x00
33 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
34 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
35 #define IPMI_CMD_CHASSIS_CONTROL 0x02
36 #define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09
38 #define IPMI_NETFN_SENSOR_EVENT 0x04
40 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
41 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
42 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
43 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
44 #define IPMI_CMD_GET_SENSOR_READING 0x2d
45 #define IPMI_CMD_SET_SENSOR_TYPE 0x2e
46 #define IPMI_CMD_GET_SENSOR_TYPE 0x2f
48 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
50 #define IPMI_CMD_GET_DEVICE_ID 0x01
51 #define IPMI_CMD_COLD_RESET 0x02
52 #define IPMI_CMD_WARM_RESET 0x03
53 #define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
54 #define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
55 #define IPMI_CMD_GET_DEVICE_GUID 0x08
56 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
57 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
58 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
59 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
60 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
61 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
62 #define IPMI_CMD_GET_MSG_FLAGS 0x31
63 #define IPMI_CMD_GET_MSG 0x33
64 #define IPMI_CMD_SEND_MSG 0x34
65 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
67 #define IPMI_NETFN_STORAGE 0x0a
69 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
70 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
71 #define IPMI_CMD_RESERVE_SDR_REP 0x22
72 #define IPMI_CMD_GET_SDR 0x23
73 #define IPMI_CMD_ADD_SDR 0x24
74 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
75 #define IPMI_CMD_DELETE_SDR 0x26
76 #define IPMI_CMD_CLEAR_SDR_REP 0x27
77 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
78 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
79 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
80 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
81 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
82 #define IPMI_CMD_GET_SEL_INFO 0x40
83 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
84 #define IPMI_CMD_RESERVE_SEL 0x42
85 #define IPMI_CMD_GET_SEL_ENTRY 0x43
86 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
87 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
88 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
89 #define IPMI_CMD_CLEAR_SEL 0x47
90 #define IPMI_CMD_GET_SEL_TIME 0x48
91 #define IPMI_CMD_SET_SEL_TIME 0x49
94 /* Same as a timespec struct. */
95 struct ipmi_time {
96 long tv_sec;
97 long tv_nsec;
100 #define MAX_SEL_SIZE 128
102 typedef struct IPMISel {
103 uint8_t sel[MAX_SEL_SIZE][16];
104 unsigned int next_free;
105 long time_offset;
106 uint16_t reservation;
107 uint8_t last_addition[4];
108 uint8_t last_clear[4];
109 uint8_t overflow;
110 } IPMISel;
112 #define MAX_SDR_SIZE 16384
114 typedef struct IPMISdr {
115 uint8_t sdr[MAX_SDR_SIZE];
116 unsigned int next_free;
117 uint16_t next_rec_id;
118 uint16_t reservation;
119 uint8_t last_addition[4];
120 uint8_t last_clear[4];
121 uint8_t overflow;
122 } IPMISdr;
124 typedef struct IPMISensor {
125 uint8_t status;
126 uint8_t reading;
127 uint16_t states_suppt;
128 uint16_t assert_suppt;
129 uint16_t deassert_suppt;
130 uint16_t states;
131 uint16_t assert_states;
132 uint16_t deassert_states;
133 uint16_t assert_enable;
134 uint16_t deassert_enable;
135 uint8_t sensor_type;
136 uint8_t evt_reading_type_code;
137 } IPMISensor;
138 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
139 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
140 !!(v))
141 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
142 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
143 ((!!(v)) << 6))
144 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
145 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
146 ((!!(v)) << 7))
147 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
148 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
149 (v & 0xc0))
150 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
152 #define MAX_SENSORS 20
153 #define IPMI_WATCHDOG_SENSOR 0
155 typedef struct IPMIBmcSim IPMIBmcSim;
157 #define MAX_NETFNS 64
158 typedef void (*IPMICmdHandler)(IPMIBmcSim *s,
159 uint8_t *cmd, unsigned int cmd_len,
160 uint8_t *rsp, unsigned int *rsp_len,
161 unsigned int max_rsp_len);
162 typedef struct IPMINetfn {
163 unsigned int cmd_nums;
164 const IPMICmdHandler *cmd_handlers;
165 } IPMINetfn;
167 typedef struct IPMIRcvBufEntry {
168 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
169 uint8_t len;
170 uint8_t buf[MAX_IPMI_MSG_SIZE];
171 } IPMIRcvBufEntry;
173 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
174 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
175 TYPE_IPMI_BMC_SIMULATOR)
176 struct IPMIBmcSim {
177 IPMIBmc parent;
179 QEMUTimer *timer;
181 uint8_t bmc_global_enables;
182 uint8_t msg_flags;
184 bool watchdog_initialized;
185 uint8_t watchdog_use;
186 uint8_t watchdog_action;
187 uint8_t watchdog_pretimeout; /* In seconds */
188 bool watchdog_expired;
189 uint16_t watchdog_timeout; /* in 100's of milliseconds */
191 bool watchdog_running;
192 bool watchdog_preaction_ran;
193 int64_t watchdog_expiry;
195 uint8_t device_id;
196 uint8_t ipmi_version;
197 uint8_t device_rev;
198 uint8_t fwrev1;
199 uint8_t fwrev2;
200 uint8_t mfg_id[3];
201 uint8_t product_id[2];
203 uint8_t restart_cause;
205 uint8_t acpi_power_state[2];
206 uint8_t uuid[16];
208 IPMISel sel;
209 IPMISdr sdr;
210 IPMISensor sensors[MAX_SENSORS];
212 /* Odd netfns are for responses, so we only need the even ones. */
213 const IPMINetfn *netfns[MAX_NETFNS / 2];
215 QemuMutex lock;
216 /* We allow one event in the buffer */
217 uint8_t evtbuf[16];
219 QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
222 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
223 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
224 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
225 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
226 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
227 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
228 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
229 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
230 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
232 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
233 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
234 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
235 #define IPMI_BMC_EVENT_LOG_BIT 3
236 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
237 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
238 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
239 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
240 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
241 (1 << IPMI_BMC_EVENT_LOG_BIT))
242 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
243 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
245 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
246 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
247 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
248 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
249 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
250 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
251 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
252 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
253 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
254 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
255 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
256 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
257 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
258 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
259 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
262 /* Add a byte to the response. */
263 #define IPMI_ADD_RSP_DATA(b) \
264 do { \
265 if (*rsp_len >= max_rsp_len) { \
266 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED; \
267 return; \
269 rsp[(*rsp_len)++] = (b); \
270 } while (0)
272 /* Verify that the received command is a certain length. */
273 #define IPMI_CHECK_CMD_LEN(l) \
274 if (cmd_len < l) { \
275 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID; \
276 return; \
279 /* Check that the reservation in the command is valid. */
280 #define IPMI_CHECK_RESERVATION(off, r) \
281 do { \
282 if ((cmd[off] | (cmd[off + 1] << 8)) != r) { \
283 rsp[2] = IPMI_CC_INVALID_RESERVATION; \
284 return; \
286 } while (0)
289 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
291 static void ipmi_gettime(struct ipmi_time *time)
293 int64_t stime;
295 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
296 time->tv_sec = stime / 1000000000LL;
297 time->tv_nsec = stime % 1000000000LL;
300 static int64_t ipmi_getmonotime(void)
302 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
305 static void ipmi_timeout(void *opaque)
307 IPMIBmcSim *ibs = opaque;
309 ipmi_sim_handle_timeout(ibs);
312 static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
314 unsigned int val;
315 struct ipmi_time now;
317 ipmi_gettime(&now);
318 val = now.tv_sec + ibs->sel.time_offset;
319 ts[0] = val & 0xff;
320 ts[1] = (val >> 8) & 0xff;
321 ts[2] = (val >> 16) & 0xff;
322 ts[3] = (val >> 24) & 0xff;
325 static void sdr_inc_reservation(IPMISdr *sdr)
327 sdr->reservation++;
328 if (sdr->reservation == 0) {
329 sdr->reservation = 1;
333 static int sdr_add_entry(IPMIBmcSim *ibs,
334 const struct ipmi_sdr_header *sdrh_entry,
335 unsigned int len, uint16_t *recid)
337 struct ipmi_sdr_header *sdrh =
338 (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
340 if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
341 return 1;
344 if (ipmi_sdr_length(sdrh_entry) != len) {
345 return 1;
348 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
349 ibs->sdr.overflow = 1;
350 return 1;
353 memcpy(sdrh, sdrh_entry, len);
354 sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff;
355 sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
356 sdrh->sdr_version = 0x51; /* Conform to IPMI 1.5 spec */
358 if (recid) {
359 *recid = ibs->sdr.next_rec_id;
361 ibs->sdr.next_rec_id++;
362 set_timestamp(ibs, ibs->sdr.last_addition);
363 ibs->sdr.next_free += len;
364 sdr_inc_reservation(&ibs->sdr);
365 return 0;
368 static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
369 unsigned int *retpos, uint16_t *nextrec)
371 unsigned int pos = *retpos;
373 while (pos < sdr->next_free) {
374 struct ipmi_sdr_header *sdrh =
375 (struct ipmi_sdr_header *) &sdr->sdr[pos];
376 uint16_t trec = ipmi_sdr_recid(sdrh);
377 unsigned int nextpos = pos + ipmi_sdr_length(sdrh);
379 if (trec == recid) {
380 if (nextrec) {
381 if (nextpos >= sdr->next_free) {
382 *nextrec = 0xffff;
383 } else {
384 *nextrec = (sdr->sdr[nextpos] |
385 (sdr->sdr[nextpos + 1] << 8));
388 *retpos = pos;
389 return 0;
391 pos = nextpos;
393 return 1;
396 static void sel_inc_reservation(IPMISel *sel)
398 sel->reservation++;
399 if (sel->reservation == 0) {
400 sel->reservation = 1;
404 /* Returns 1 if the SEL is full and can't hold the event. */
405 static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
407 event[0] = 0xff;
408 event[1] = 0xff;
409 set_timestamp(ibs, event + 3);
410 if (ibs->sel.next_free == MAX_SEL_SIZE) {
411 ibs->sel.overflow = 1;
412 return 1;
414 event[0] = ibs->sel.next_free & 0xff;
415 event[1] = (ibs->sel.next_free >> 8) & 0xff;
416 memcpy(ibs->sel.last_addition, event + 3, 4);
417 memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
418 ibs->sel.next_free++;
419 sel_inc_reservation(&ibs->sel);
420 return 0;
423 static int attn_set(IPMIBmcSim *ibs)
425 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
426 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
427 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
430 static int attn_irq_enabled(IPMIBmcSim *ibs)
432 return (IPMI_BMC_MSG_INTS_ON(ibs) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs))
433 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
434 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
437 static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
438 uint8_t evd1, uint8_t evd2, uint8_t evd3)
440 IPMIInterface *s = ibs->parent.intf;
441 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
442 uint8_t evt[16];
443 IPMISensor *sens = ibs->sensors + sens_num;
445 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
446 return;
448 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
449 return;
452 evt[2] = 0x2; /* System event record */
453 evt[7] = ibs->parent.slave_addr;
454 evt[8] = 0;
455 evt[9] = 0x04; /* Format version */
456 evt[10] = sens->sensor_type;
457 evt[11] = sens_num;
458 evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
459 evt[13] = evd1;
460 evt[14] = evd2;
461 evt[15] = evd3;
463 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
464 sel_add_event(ibs, evt);
467 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
468 return;
471 memcpy(ibs->evtbuf, evt, 16);
472 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
473 k->set_atn(s, 1, attn_irq_enabled(ibs));
476 static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
477 unsigned int bit, unsigned int val,
478 uint8_t evd1, uint8_t evd2, uint8_t evd3)
480 IPMISensor *sens;
481 uint16_t mask;
483 if (sensor >= MAX_SENSORS) {
484 return;
486 if (bit >= 16) {
487 return;
490 mask = (1 << bit);
491 sens = ibs->sensors + sensor;
492 if (val) {
493 sens->states |= mask & sens->states_suppt;
494 if (sens->assert_states & mask) {
495 return; /* Already asserted */
497 sens->assert_states |= mask & sens->assert_suppt;
498 if (sens->assert_enable & mask & sens->assert_states) {
499 /* Send an event on assert */
500 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
502 } else {
503 sens->states &= ~(mask & sens->states_suppt);
504 if (sens->deassert_states & mask) {
505 return; /* Already deasserted */
507 sens->deassert_states |= mask & sens->deassert_suppt;
508 if (sens->deassert_enable & mask & sens->deassert_states) {
509 /* Send an event on deassert */
510 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
515 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
517 unsigned int i, pos;
518 IPMISensor *sens;
520 for (i = 0; i < MAX_SENSORS; i++) {
521 memset(s->sensors + i, 0, sizeof(*sens));
524 pos = 0;
525 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
526 struct ipmi_sdr_compact *sdr =
527 (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
528 unsigned int len = sdr->header.rec_length;
530 if (len < 20) {
531 continue;
533 if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
534 continue; /* Not a sensor SDR we set from */
537 if (sdr->sensor_owner_number >= MAX_SENSORS) {
538 continue;
540 sens = s->sensors + sdr->sensor_owner_number;
542 IPMI_SENSOR_SET_PRESENT(sens, 1);
543 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
544 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
545 sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
546 sens->deassert_suppt =
547 sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
548 sens->states_suppt =
549 sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
550 sens->sensor_type = sdr->sensor_type;
551 sens->evt_reading_type_code = sdr->reading_type & 0x7f;
553 /* Enable all the events that are supported. */
554 sens->assert_enable = sens->assert_suppt;
555 sens->deassert_enable = sens->deassert_suppt;
559 static int ipmi_register_netfn(IPMIBmcSim *s, unsigned int netfn,
560 const IPMINetfn *netfnd)
562 if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
563 return -1;
565 s->netfns[netfn / 2] = netfnd;
566 return 0;
569 static void next_timeout(IPMIBmcSim *ibs)
571 int64_t next;
572 if (ibs->watchdog_running) {
573 next = ibs->watchdog_expiry;
574 } else {
575 /* Wait a minute */
576 next = ipmi_getmonotime() + 60 * 1000000000LL;
578 timer_mod_ns(ibs->timer, next);
581 static void ipmi_sim_handle_command(IPMIBmc *b,
582 uint8_t *cmd, unsigned int cmd_len,
583 unsigned int max_cmd_len,
584 uint8_t msg_id)
586 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
587 IPMIInterface *s = ibs->parent.intf;
588 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
589 unsigned int netfn;
590 uint8_t rsp[MAX_IPMI_MSG_SIZE];
591 unsigned int rsp_len_holder = 0;
592 unsigned int *rsp_len = &rsp_len_holder;
593 unsigned int max_rsp_len = sizeof(rsp);
595 /* Set up the response, set the low bit of NETFN. */
596 /* Note that max_rsp_len must be at least 3 */
597 if (max_rsp_len < 3) {
598 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
599 goto out;
602 IPMI_ADD_RSP_DATA(cmd[0] | 0x04);
603 IPMI_ADD_RSP_DATA(cmd[1]);
604 IPMI_ADD_RSP_DATA(0); /* Assume success */
606 /* If it's too short or it was truncated, return an error. */
607 if (cmd_len < 2) {
608 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
609 goto out;
611 if (cmd_len > max_cmd_len) {
612 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
613 goto out;
616 if ((cmd[0] & 0x03) != 0) {
617 /* Only have stuff on LUN 0 */
618 rsp[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
619 goto out;
622 netfn = cmd[0] >> 2;
624 /* Odd netfns are not valid, make sure the command is registered */
625 if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
626 (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
627 (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
628 rsp[2] = IPMI_CC_INVALID_CMD;
629 goto out;
632 ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
633 max_rsp_len);
635 out:
636 k->handle_rsp(s, msg_id, rsp, *rsp_len);
638 next_timeout(ibs);
641 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
643 IPMIInterface *s = ibs->parent.intf;
644 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
646 if (!ibs->watchdog_running) {
647 goto out;
650 if (!ibs->watchdog_preaction_ran) {
651 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
652 case IPMI_BMC_WATCHDOG_PRE_NMI:
653 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
654 k->do_hw_op(s, IPMI_SEND_NMI, 0);
655 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
656 0xc8, (2 << 4) | 0xf, 0xff);
657 break;
659 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
660 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
661 k->set_atn(s, 1, attn_irq_enabled(ibs));
662 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
663 0xc8, (3 << 4) | 0xf, 0xff);
664 break;
666 default:
667 goto do_full_expiry;
670 ibs->watchdog_preaction_ran = 1;
671 /* Issued the pretimeout, do the rest of the timeout now. */
672 ibs->watchdog_expiry = ipmi_getmonotime();
673 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
674 goto out;
677 do_full_expiry:
678 ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
679 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
680 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
681 case IPMI_BMC_WATCHDOG_ACTION_NONE:
682 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
683 0xc0, ibs->watchdog_use & 0xf, 0xff);
684 break;
686 case IPMI_BMC_WATCHDOG_ACTION_RESET:
687 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
688 0xc1, ibs->watchdog_use & 0xf, 0xff);
689 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
690 break;
692 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
693 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
694 0xc2, ibs->watchdog_use & 0xf, 0xff);
695 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
696 break;
698 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
699 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
700 0xc3, ibs->watchdog_use & 0xf, 0xff);
701 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
702 break;
705 out:
706 next_timeout(ibs);
709 static void chassis_capabilities(IPMIBmcSim *ibs,
710 uint8_t *cmd, unsigned int cmd_len,
711 uint8_t *rsp, unsigned int *rsp_len,
712 unsigned int max_rsp_len)
714 IPMI_ADD_RSP_DATA(0);
715 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
716 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
717 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
718 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
721 static void chassis_status(IPMIBmcSim *ibs,
722 uint8_t *cmd, unsigned int cmd_len,
723 uint8_t *rsp, unsigned int *rsp_len,
724 unsigned int max_rsp_len)
726 IPMI_ADD_RSP_DATA(0x61); /* Unknown power restore, power is on */
727 IPMI_ADD_RSP_DATA(0);
728 IPMI_ADD_RSP_DATA(0);
729 IPMI_ADD_RSP_DATA(0);
732 static void chassis_control(IPMIBmcSim *ibs,
733 uint8_t *cmd, unsigned int cmd_len,
734 uint8_t *rsp, unsigned int *rsp_len,
735 unsigned int max_rsp_len)
737 IPMIInterface *s = ibs->parent.intf;
738 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
740 IPMI_CHECK_CMD_LEN(3);
741 switch (cmd[2] & 0xf) {
742 case 0: /* power down */
743 rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
744 break;
745 case 1: /* power up */
746 rsp[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
747 break;
748 case 2: /* power cycle */
749 rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
750 break;
751 case 3: /* hard reset */
752 rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
753 break;
754 case 4: /* pulse diagnostic interrupt */
755 rsp[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
756 break;
757 case 5: /* soft shutdown via ACPI by overtemp emulation */
758 rsp[2] = k->do_hw_op(s,
759 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0);
760 break;
761 default:
762 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
763 return;
767 static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
768 uint8_t *cmd, unsigned int cmd_len,
769 uint8_t *rsp, unsigned int *rsp_len,
770 unsigned int max_rsp_len)
772 IPMI_ADD_RSP_DATA(ibs->restart_cause & 0xf); /* Restart Cause */
773 IPMI_ADD_RSP_DATA(0); /* Channel 0 */
776 static void get_device_id(IPMIBmcSim *ibs,
777 uint8_t *cmd, unsigned int cmd_len,
778 uint8_t *rsp, unsigned int *rsp_len,
779 unsigned int max_rsp_len)
781 IPMI_ADD_RSP_DATA(ibs->device_id);
782 IPMI_ADD_RSP_DATA(ibs->device_rev & 0xf);
783 IPMI_ADD_RSP_DATA(ibs->fwrev1 & 0x7f);
784 IPMI_ADD_RSP_DATA(ibs->fwrev2);
785 IPMI_ADD_RSP_DATA(ibs->ipmi_version);
786 IPMI_ADD_RSP_DATA(0x07); /* sensor, SDR, and SEL. */
787 IPMI_ADD_RSP_DATA(ibs->mfg_id[0]);
788 IPMI_ADD_RSP_DATA(ibs->mfg_id[1]);
789 IPMI_ADD_RSP_DATA(ibs->mfg_id[2]);
790 IPMI_ADD_RSP_DATA(ibs->product_id[0]);
791 IPMI_ADD_RSP_DATA(ibs->product_id[1]);
794 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
796 IPMIInterface *s = ibs->parent.intf;
797 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
798 bool irqs_on;
800 ibs->bmc_global_enables = val;
802 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
803 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
805 k->set_irq_enable(s, irqs_on);
808 static void cold_reset(IPMIBmcSim *ibs,
809 uint8_t *cmd, unsigned int cmd_len,
810 uint8_t *rsp, unsigned int *rsp_len,
811 unsigned int max_rsp_len)
813 IPMIInterface *s = ibs->parent.intf;
814 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
816 /* Disable all interrupts */
817 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
819 if (k->reset) {
820 k->reset(s, true);
824 static void warm_reset(IPMIBmcSim *ibs,
825 uint8_t *cmd, unsigned int cmd_len,
826 uint8_t *rsp, unsigned int *rsp_len,
827 unsigned int max_rsp_len)
829 IPMIInterface *s = ibs->parent.intf;
830 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
832 if (k->reset) {
833 k->reset(s, false);
836 static void set_acpi_power_state(IPMIBmcSim *ibs,
837 uint8_t *cmd, unsigned int cmd_len,
838 uint8_t *rsp, unsigned int *rsp_len,
839 unsigned int max_rsp_len)
841 IPMI_CHECK_CMD_LEN(4);
842 ibs->acpi_power_state[0] = cmd[2];
843 ibs->acpi_power_state[1] = cmd[3];
846 static void get_acpi_power_state(IPMIBmcSim *ibs,
847 uint8_t *cmd, unsigned int cmd_len,
848 uint8_t *rsp, unsigned int *rsp_len,
849 unsigned int max_rsp_len)
851 IPMI_ADD_RSP_DATA(ibs->acpi_power_state[0]);
852 IPMI_ADD_RSP_DATA(ibs->acpi_power_state[1]);
855 static void get_device_guid(IPMIBmcSim *ibs,
856 uint8_t *cmd, unsigned int cmd_len,
857 uint8_t *rsp, unsigned int *rsp_len,
858 unsigned int max_rsp_len)
860 unsigned int i;
862 for (i = 0; i < 16; i++) {
863 IPMI_ADD_RSP_DATA(ibs->uuid[i]);
867 static void set_bmc_global_enables(IPMIBmcSim *ibs,
868 uint8_t *cmd, unsigned int cmd_len,
869 uint8_t *rsp, unsigned int *rsp_len,
870 unsigned int max_rsp_len)
872 IPMI_CHECK_CMD_LEN(3);
873 set_global_enables(ibs, cmd[2]);
876 static void get_bmc_global_enables(IPMIBmcSim *ibs,
877 uint8_t *cmd, unsigned int cmd_len,
878 uint8_t *rsp, unsigned int *rsp_len,
879 unsigned int max_rsp_len)
881 IPMI_ADD_RSP_DATA(ibs->bmc_global_enables);
884 static void clr_msg_flags(IPMIBmcSim *ibs,
885 uint8_t *cmd, unsigned int cmd_len,
886 uint8_t *rsp, unsigned int *rsp_len,
887 unsigned int max_rsp_len)
889 IPMIInterface *s = ibs->parent.intf;
890 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
892 IPMI_CHECK_CMD_LEN(3);
893 ibs->msg_flags &= ~cmd[2];
894 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
897 static void get_msg_flags(IPMIBmcSim *ibs,
898 uint8_t *cmd, unsigned int cmd_len,
899 uint8_t *rsp, unsigned int *rsp_len,
900 unsigned int max_rsp_len)
902 IPMI_ADD_RSP_DATA(ibs->msg_flags);
905 static void read_evt_msg_buf(IPMIBmcSim *ibs,
906 uint8_t *cmd, unsigned int cmd_len,
907 uint8_t *rsp, unsigned int *rsp_len,
908 unsigned int max_rsp_len)
910 IPMIInterface *s = ibs->parent.intf;
911 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
912 unsigned int i;
914 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
915 rsp[2] = 0x80;
916 return;
918 for (i = 0; i < 16; i++) {
919 IPMI_ADD_RSP_DATA(ibs->evtbuf[i]);
921 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
922 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
925 static void get_msg(IPMIBmcSim *ibs,
926 uint8_t *cmd, unsigned int cmd_len,
927 uint8_t *rsp, unsigned int *rsp_len,
928 unsigned int max_rsp_len)
930 IPMIRcvBufEntry *msg;
932 qemu_mutex_lock(&ibs->lock);
933 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
934 rsp[2] = 0x80; /* Queue empty */
935 goto out;
937 rsp[3] = 0; /* Channel 0 */
938 *rsp_len += 1;
939 msg = QTAILQ_FIRST(&ibs->rcvbufs);
940 memcpy(rsp + 4, msg->buf, msg->len);
941 *rsp_len += msg->len;
942 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
943 g_free(msg);
945 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
946 IPMIInterface *s = ibs->parent.intf;
947 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
949 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
950 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
953 out:
954 qemu_mutex_unlock(&ibs->lock);
955 return;
958 static unsigned char
959 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
961 for (; size > 0; size--, data++) {
962 csum += *data;
965 return -csum;
968 static void send_msg(IPMIBmcSim *ibs,
969 uint8_t *cmd, unsigned int cmd_len,
970 uint8_t *rsp, unsigned int *rsp_len,
971 unsigned int max_rsp_len)
973 IPMIInterface *s = ibs->parent.intf;
974 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
975 IPMIRcvBufEntry *msg;
976 uint8_t *buf;
977 uint8_t netfn, rqLun, rsLun, rqSeq;
979 IPMI_CHECK_CMD_LEN(3);
981 if (cmd[2] != 0) {
982 /* We only handle channel 0 with no options */
983 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
984 return;
987 IPMI_CHECK_CMD_LEN(10);
988 if (cmd[3] != 0x40) {
989 /* We only emulate a MC at address 0x40. */
990 rsp[2] = 0x83; /* NAK on write */
991 return;
994 cmd += 3; /* Skip the header. */
995 cmd_len -= 3;
998 * At this point we "send" the message successfully. Any error will
999 * be returned in the response.
1001 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
1002 cmd[3] != 0x20) { /* Improper response address */
1003 return; /* No response */
1006 netfn = cmd[1] >> 2;
1007 rqLun = cmd[4] & 0x3;
1008 rsLun = cmd[1] & 0x3;
1009 rqSeq = cmd[4] >> 2;
1011 if (rqLun != 2) {
1012 /* We only support LUN 2 coming back to us. */
1013 return;
1016 msg = g_malloc(sizeof(*msg));
1017 msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
1018 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
1019 msg->buf[2] = cmd[0]; /* rsSA */
1020 msg->buf[3] = (rqSeq << 2) | rsLun;
1021 msg->buf[4] = cmd[5]; /* Cmd */
1022 msg->buf[5] = 0; /* Completion Code */
1023 msg->len = 6;
1025 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
1026 /* Not a command we handle. */
1027 msg->buf[5] = IPMI_CC_INVALID_CMD;
1028 goto end_msg;
1031 buf = msg->buf + msg->len; /* After the CC */
1032 buf[0] = 0;
1033 buf[1] = 0;
1034 buf[2] = 0;
1035 buf[3] = 0;
1036 buf[4] = 0x51;
1037 buf[5] = 0;
1038 buf[6] = 0;
1039 buf[7] = 0;
1040 buf[8] = 0;
1041 buf[9] = 0;
1042 buf[10] = 0;
1043 msg->len += 11;
1045 end_msg:
1046 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1047 msg->len++;
1048 qemu_mutex_lock(&ibs->lock);
1049 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1050 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1051 k->set_atn(s, 1, attn_irq_enabled(ibs));
1052 qemu_mutex_unlock(&ibs->lock);
1055 static void do_watchdog_reset(IPMIBmcSim *ibs)
1057 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1058 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1059 ibs->watchdog_running = 0;
1060 return;
1062 ibs->watchdog_preaction_ran = 0;
1065 /* Timeout is in tenths of a second, offset is in seconds */
1066 ibs->watchdog_expiry = ipmi_getmonotime();
1067 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1068 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1069 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1071 ibs->watchdog_running = 1;
1074 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1075 uint8_t *cmd, unsigned int cmd_len,
1076 uint8_t *rsp, unsigned int *rsp_len,
1077 unsigned int max_rsp_len)
1079 if (!ibs->watchdog_initialized) {
1080 rsp[2] = 0x80;
1081 return;
1083 do_watchdog_reset(ibs);
1086 static void set_watchdog_timer(IPMIBmcSim *ibs,
1087 uint8_t *cmd, unsigned int cmd_len,
1088 uint8_t *rsp, unsigned int *rsp_len,
1089 unsigned int max_rsp_len)
1091 IPMIInterface *s = ibs->parent.intf;
1092 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1093 unsigned int val;
1095 IPMI_CHECK_CMD_LEN(8);
1096 val = cmd[2] & 0x7; /* Validate use */
1097 if (val == 0 || val > 5) {
1098 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1099 return;
1101 val = cmd[3] & 0x7; /* Validate action */
1102 switch (val) {
1103 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1104 break;
1106 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1107 rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
1108 break;
1110 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1111 rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
1112 break;
1114 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1115 rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
1116 break;
1118 default:
1119 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1121 if (rsp[2]) {
1122 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1123 return;
1126 val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1127 switch (val) {
1128 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1129 case IPMI_BMC_WATCHDOG_PRE_NONE:
1130 break;
1132 case IPMI_BMC_WATCHDOG_PRE_NMI:
1133 if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1134 /* NMI not supported. */
1135 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1136 return;
1138 break;
1140 default:
1141 /* We don't support PRE_SMI */
1142 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1143 return;
1146 ibs->watchdog_initialized = 1;
1147 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1148 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1149 ibs->watchdog_pretimeout = cmd[4];
1150 ibs->watchdog_expired &= ~cmd[5];
1151 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1152 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1153 do_watchdog_reset(ibs);
1154 } else {
1155 ibs->watchdog_running = 0;
1159 static void get_watchdog_timer(IPMIBmcSim *ibs,
1160 uint8_t *cmd, unsigned int cmd_len,
1161 uint8_t *rsp, unsigned int *rsp_len,
1162 unsigned int max_rsp_len)
1164 IPMI_ADD_RSP_DATA(ibs->watchdog_use);
1165 IPMI_ADD_RSP_DATA(ibs->watchdog_action);
1166 IPMI_ADD_RSP_DATA(ibs->watchdog_pretimeout);
1167 IPMI_ADD_RSP_DATA(ibs->watchdog_expired);
1168 if (ibs->watchdog_running) {
1169 long timeout;
1170 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1171 / 100000000);
1172 IPMI_ADD_RSP_DATA(timeout & 0xff);
1173 IPMI_ADD_RSP_DATA((timeout >> 8) & 0xff);
1174 } else {
1175 IPMI_ADD_RSP_DATA(0);
1176 IPMI_ADD_RSP_DATA(0);
1180 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1181 uint8_t *cmd, unsigned int cmd_len,
1182 uint8_t *rsp, unsigned int *rsp_len,
1183 unsigned int max_rsp_len)
1185 unsigned int i;
1187 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 spec */
1188 IPMI_ADD_RSP_DATA(ibs->sdr.next_rec_id & 0xff);
1189 IPMI_ADD_RSP_DATA((ibs->sdr.next_rec_id >> 8) & 0xff);
1190 IPMI_ADD_RSP_DATA((MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1191 IPMI_ADD_RSP_DATA(((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1192 for (i = 0; i < 4; i++) {
1193 IPMI_ADD_RSP_DATA(ibs->sdr.last_addition[i]);
1195 for (i = 0; i < 4; i++) {
1196 IPMI_ADD_RSP_DATA(ibs->sdr.last_clear[i]);
1198 /* Only modal support, reserve supported */
1199 IPMI_ADD_RSP_DATA((ibs->sdr.overflow << 7) | 0x22);
1202 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1203 uint8_t *cmd, unsigned int cmd_len,
1204 uint8_t *rsp, unsigned int *rsp_len,
1205 unsigned int max_rsp_len)
1207 IPMI_ADD_RSP_DATA(ibs->sdr.reservation & 0xff);
1208 IPMI_ADD_RSP_DATA((ibs->sdr.reservation >> 8) & 0xff);
1211 static void get_sdr(IPMIBmcSim *ibs,
1212 uint8_t *cmd, unsigned int cmd_len,
1213 uint8_t *rsp, unsigned int *rsp_len,
1214 unsigned int max_rsp_len)
1216 unsigned int pos;
1217 uint16_t nextrec;
1218 struct ipmi_sdr_header *sdrh;
1220 IPMI_CHECK_CMD_LEN(8);
1221 if (cmd[6]) {
1222 IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
1224 pos = 0;
1225 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1226 &pos, &nextrec)) {
1227 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1228 return;
1231 sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1233 if (cmd[6] > ipmi_sdr_length(sdrh)) {
1234 rsp[2] = IPMI_CC_PARM_OUT_OF_RANGE;
1235 return;
1238 IPMI_ADD_RSP_DATA(nextrec & 0xff);
1239 IPMI_ADD_RSP_DATA((nextrec >> 8) & 0xff);
1241 if (cmd[7] == 0xff) {
1242 cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1245 if ((cmd[7] + *rsp_len) > max_rsp_len) {
1246 rsp[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
1247 return;
1249 memcpy(rsp + *rsp_len, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1250 *rsp_len += cmd[7];
1253 static void add_sdr(IPMIBmcSim *ibs,
1254 uint8_t *cmd, unsigned int cmd_len,
1255 uint8_t *rsp, unsigned int *rsp_len,
1256 unsigned int max_rsp_len)
1258 uint16_t recid;
1259 struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1261 if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1262 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1263 return;
1265 IPMI_ADD_RSP_DATA(recid & 0xff);
1266 IPMI_ADD_RSP_DATA((recid >> 8) & 0xff);
1269 static void clear_sdr_rep(IPMIBmcSim *ibs,
1270 uint8_t *cmd, unsigned int cmd_len,
1271 uint8_t *rsp, unsigned int *rsp_len,
1272 unsigned int max_rsp_len)
1274 IPMI_CHECK_CMD_LEN(8);
1275 IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
1276 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1277 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1278 return;
1280 if (cmd[7] == 0xaa) {
1281 ibs->sdr.next_free = 0;
1282 ibs->sdr.overflow = 0;
1283 set_timestamp(ibs, ibs->sdr.last_clear);
1284 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1285 sdr_inc_reservation(&ibs->sdr);
1286 } else if (cmd[7] == 0) {
1287 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1288 } else {
1289 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1290 return;
1294 static void get_sel_info(IPMIBmcSim *ibs,
1295 uint8_t *cmd, unsigned int cmd_len,
1296 uint8_t *rsp, unsigned int *rsp_len,
1297 unsigned int max_rsp_len)
1299 unsigned int i, val;
1301 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 */
1302 IPMI_ADD_RSP_DATA(ibs->sel.next_free & 0xff);
1303 IPMI_ADD_RSP_DATA((ibs->sel.next_free >> 8) & 0xff);
1304 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1305 IPMI_ADD_RSP_DATA(val & 0xff);
1306 IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
1307 for (i = 0; i < 4; i++) {
1308 IPMI_ADD_RSP_DATA(ibs->sel.last_addition[i]);
1310 for (i = 0; i < 4; i++) {
1311 IPMI_ADD_RSP_DATA(ibs->sel.last_clear[i]);
1313 /* Only support Reserve SEL */
1314 IPMI_ADD_RSP_DATA((ibs->sel.overflow << 7) | 0x02);
1317 static void reserve_sel(IPMIBmcSim *ibs,
1318 uint8_t *cmd, unsigned int cmd_len,
1319 uint8_t *rsp, unsigned int *rsp_len,
1320 unsigned int max_rsp_len)
1322 IPMI_ADD_RSP_DATA(ibs->sel.reservation & 0xff);
1323 IPMI_ADD_RSP_DATA((ibs->sel.reservation >> 8) & 0xff);
1326 static void get_sel_entry(IPMIBmcSim *ibs,
1327 uint8_t *cmd, unsigned int cmd_len,
1328 uint8_t *rsp, unsigned int *rsp_len,
1329 unsigned int max_rsp_len)
1331 unsigned int val;
1333 IPMI_CHECK_CMD_LEN(8);
1334 if (cmd[6]) {
1335 IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
1337 if (ibs->sel.next_free == 0) {
1338 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1339 return;
1341 if (cmd[6] > 15) {
1342 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1343 return;
1345 if (cmd[7] == 0xff) {
1346 cmd[7] = 16;
1347 } else if ((cmd[7] + cmd[6]) > 16) {
1348 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1349 return;
1350 } else {
1351 cmd[7] += cmd[6];
1354 val = cmd[4] | (cmd[5] << 8);
1355 if (val == 0xffff) {
1356 val = ibs->sel.next_free - 1;
1357 } else if (val >= ibs->sel.next_free) {
1358 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1359 return;
1361 if ((val + 1) == ibs->sel.next_free) {
1362 IPMI_ADD_RSP_DATA(0xff);
1363 IPMI_ADD_RSP_DATA(0xff);
1364 } else {
1365 IPMI_ADD_RSP_DATA((val + 1) & 0xff);
1366 IPMI_ADD_RSP_DATA(((val + 1) >> 8) & 0xff);
1368 for (; cmd[6] < cmd[7]; cmd[6]++) {
1369 IPMI_ADD_RSP_DATA(ibs->sel.sel[val][cmd[6]]);
1373 static void add_sel_entry(IPMIBmcSim *ibs,
1374 uint8_t *cmd, unsigned int cmd_len,
1375 uint8_t *rsp, unsigned int *rsp_len,
1376 unsigned int max_rsp_len)
1378 IPMI_CHECK_CMD_LEN(18);
1379 if (sel_add_event(ibs, cmd + 2)) {
1380 rsp[2] = IPMI_CC_OUT_OF_SPACE;
1381 return;
1383 /* sel_add_event fills in the record number. */
1384 IPMI_ADD_RSP_DATA(cmd[2]);
1385 IPMI_ADD_RSP_DATA(cmd[3]);
1388 static void clear_sel(IPMIBmcSim *ibs,
1389 uint8_t *cmd, unsigned int cmd_len,
1390 uint8_t *rsp, unsigned int *rsp_len,
1391 unsigned int max_rsp_len)
1393 IPMI_CHECK_CMD_LEN(8);
1394 IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
1395 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1396 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1397 return;
1399 if (cmd[7] == 0xaa) {
1400 ibs->sel.next_free = 0;
1401 ibs->sel.overflow = 0;
1402 set_timestamp(ibs, ibs->sdr.last_clear);
1403 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1404 sel_inc_reservation(&ibs->sel);
1405 } else if (cmd[7] == 0) {
1406 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1407 } else {
1408 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1409 return;
1413 static void get_sel_time(IPMIBmcSim *ibs,
1414 uint8_t *cmd, unsigned int cmd_len,
1415 uint8_t *rsp, unsigned int *rsp_len,
1416 unsigned int max_rsp_len)
1418 uint32_t val;
1419 struct ipmi_time now;
1421 ipmi_gettime(&now);
1422 val = now.tv_sec + ibs->sel.time_offset;
1423 IPMI_ADD_RSP_DATA(val & 0xff);
1424 IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
1425 IPMI_ADD_RSP_DATA((val >> 16) & 0xff);
1426 IPMI_ADD_RSP_DATA((val >> 24) & 0xff);
1429 static void set_sel_time(IPMIBmcSim *ibs,
1430 uint8_t *cmd, unsigned int cmd_len,
1431 uint8_t *rsp, unsigned int *rsp_len,
1432 unsigned int max_rsp_len)
1434 uint32_t val;
1435 struct ipmi_time now;
1437 IPMI_CHECK_CMD_LEN(6);
1438 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1439 ipmi_gettime(&now);
1440 ibs->sel.time_offset = now.tv_sec - ((long) val);
1443 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1444 uint8_t *cmd, unsigned int cmd_len,
1445 uint8_t *rsp, unsigned int *rsp_len,
1446 unsigned int max_rsp_len)
1448 IPMISensor *sens;
1450 IPMI_CHECK_CMD_LEN(4);
1451 if ((cmd[2] >= MAX_SENSORS) ||
1452 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1453 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1454 return;
1456 sens = ibs->sensors + cmd[2];
1457 switch ((cmd[3] >> 4) & 0x3) {
1458 case 0: /* Do not change */
1459 break;
1460 case 1: /* Enable bits */
1461 if (cmd_len > 4) {
1462 sens->assert_enable |= cmd[4];
1464 if (cmd_len > 5) {
1465 sens->assert_enable |= cmd[5] << 8;
1467 if (cmd_len > 6) {
1468 sens->deassert_enable |= cmd[6];
1470 if (cmd_len > 7) {
1471 sens->deassert_enable |= cmd[7] << 8;
1473 break;
1474 case 2: /* Disable bits */
1475 if (cmd_len > 4) {
1476 sens->assert_enable &= ~cmd[4];
1478 if (cmd_len > 5) {
1479 sens->assert_enable &= ~(cmd[5] << 8);
1481 if (cmd_len > 6) {
1482 sens->deassert_enable &= ~cmd[6];
1484 if (cmd_len > 7) {
1485 sens->deassert_enable &= ~(cmd[7] << 8);
1487 break;
1488 case 3:
1489 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1490 return;
1492 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1495 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1496 uint8_t *cmd, unsigned int cmd_len,
1497 uint8_t *rsp, unsigned int *rsp_len,
1498 unsigned int max_rsp_len)
1500 IPMISensor *sens;
1502 IPMI_CHECK_CMD_LEN(3);
1503 if ((cmd[2] >= MAX_SENSORS) ||
1504 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1505 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1506 return;
1508 sens = ibs->sensors + cmd[2];
1509 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1510 IPMI_ADD_RSP_DATA(sens->assert_enable & 0xff);
1511 IPMI_ADD_RSP_DATA((sens->assert_enable >> 8) & 0xff);
1512 IPMI_ADD_RSP_DATA(sens->deassert_enable & 0xff);
1513 IPMI_ADD_RSP_DATA((sens->deassert_enable >> 8) & 0xff);
1516 static void rearm_sensor_evts(IPMIBmcSim *ibs,
1517 uint8_t *cmd, unsigned int cmd_len,
1518 uint8_t *rsp, unsigned int *rsp_len,
1519 unsigned int max_rsp_len)
1521 IPMISensor *sens;
1523 IPMI_CHECK_CMD_LEN(4);
1524 if ((cmd[2] >= MAX_SENSORS) ||
1525 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1526 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1527 return;
1529 sens = ibs->sensors + cmd[2];
1531 if ((cmd[3] & 0x80) == 0) {
1532 /* Just clear everything */
1533 sens->states = 0;
1534 return;
1538 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1539 uint8_t *cmd, unsigned int cmd_len,
1540 uint8_t *rsp, unsigned int *rsp_len,
1541 unsigned int max_rsp_len)
1543 IPMISensor *sens;
1545 IPMI_CHECK_CMD_LEN(3);
1546 if ((cmd[2] >= MAX_SENSORS) ||
1547 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1548 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1549 return;
1551 sens = ibs->sensors + cmd[2];
1552 IPMI_ADD_RSP_DATA(sens->reading);
1553 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1554 IPMI_ADD_RSP_DATA(sens->assert_states & 0xff);
1555 IPMI_ADD_RSP_DATA((sens->assert_states >> 8) & 0xff);
1556 IPMI_ADD_RSP_DATA(sens->deassert_states & 0xff);
1557 IPMI_ADD_RSP_DATA((sens->deassert_states >> 8) & 0xff);
1560 static void get_sensor_reading(IPMIBmcSim *ibs,
1561 uint8_t *cmd, unsigned int cmd_len,
1562 uint8_t *rsp, unsigned int *rsp_len,
1563 unsigned int max_rsp_len)
1565 IPMISensor *sens;
1567 IPMI_CHECK_CMD_LEN(3);
1568 if ((cmd[2] >= MAX_SENSORS) ||
1569 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1570 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1571 return;
1573 sens = ibs->sensors + cmd[2];
1574 IPMI_ADD_RSP_DATA(sens->reading);
1575 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1576 IPMI_ADD_RSP_DATA(sens->states & 0xff);
1577 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1578 IPMI_ADD_RSP_DATA((sens->states >> 8) & 0xff);
1582 static void set_sensor_type(IPMIBmcSim *ibs,
1583 uint8_t *cmd, unsigned int cmd_len,
1584 uint8_t *rsp, unsigned int *rsp_len,
1585 unsigned int max_rsp_len)
1587 IPMISensor *sens;
1590 IPMI_CHECK_CMD_LEN(5);
1591 if ((cmd[2] >= MAX_SENSORS) ||
1592 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1593 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1594 return;
1596 sens = ibs->sensors + cmd[2];
1597 sens->sensor_type = cmd[3];
1598 sens->evt_reading_type_code = cmd[4] & 0x7f;
1601 static void get_sensor_type(IPMIBmcSim *ibs,
1602 uint8_t *cmd, unsigned int cmd_len,
1603 uint8_t *rsp, unsigned int *rsp_len,
1604 unsigned int max_rsp_len)
1606 IPMISensor *sens;
1609 IPMI_CHECK_CMD_LEN(3);
1610 if ((cmd[2] >= MAX_SENSORS) ||
1611 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1612 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1613 return;
1615 sens = ibs->sensors + cmd[2];
1616 IPMI_ADD_RSP_DATA(sens->sensor_type);
1617 IPMI_ADD_RSP_DATA(sens->evt_reading_type_code);
1621 static const IPMICmdHandler chassis_cmds[] = {
1622 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = chassis_capabilities,
1623 [IPMI_CMD_GET_CHASSIS_STATUS] = chassis_status,
1624 [IPMI_CMD_CHASSIS_CONTROL] = chassis_control,
1625 [IPMI_CMD_GET_SYS_RESTART_CAUSE] = chassis_get_sys_restart_cause
1627 static const IPMINetfn chassis_netfn = {
1628 .cmd_nums = ARRAY_SIZE(chassis_cmds),
1629 .cmd_handlers = chassis_cmds
1632 static const IPMICmdHandler sensor_event_cmds[] = {
1633 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = set_sensor_evt_enable,
1634 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = get_sensor_evt_enable,
1635 [IPMI_CMD_REARM_SENSOR_EVTS] = rearm_sensor_evts,
1636 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = get_sensor_evt_status,
1637 [IPMI_CMD_GET_SENSOR_READING] = get_sensor_reading,
1638 [IPMI_CMD_SET_SENSOR_TYPE] = set_sensor_type,
1639 [IPMI_CMD_GET_SENSOR_TYPE] = get_sensor_type,
1641 static const IPMINetfn sensor_event_netfn = {
1642 .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
1643 .cmd_handlers = sensor_event_cmds
1646 static const IPMICmdHandler app_cmds[] = {
1647 [IPMI_CMD_GET_DEVICE_ID] = get_device_id,
1648 [IPMI_CMD_COLD_RESET] = cold_reset,
1649 [IPMI_CMD_WARM_RESET] = warm_reset,
1650 [IPMI_CMD_SET_ACPI_POWER_STATE] = set_acpi_power_state,
1651 [IPMI_CMD_GET_ACPI_POWER_STATE] = get_acpi_power_state,
1652 [IPMI_CMD_GET_DEVICE_GUID] = get_device_guid,
1653 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = set_bmc_global_enables,
1654 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = get_bmc_global_enables,
1655 [IPMI_CMD_CLR_MSG_FLAGS] = clr_msg_flags,
1656 [IPMI_CMD_GET_MSG_FLAGS] = get_msg_flags,
1657 [IPMI_CMD_GET_MSG] = get_msg,
1658 [IPMI_CMD_SEND_MSG] = send_msg,
1659 [IPMI_CMD_READ_EVT_MSG_BUF] = read_evt_msg_buf,
1660 [IPMI_CMD_RESET_WATCHDOG_TIMER] = reset_watchdog_timer,
1661 [IPMI_CMD_SET_WATCHDOG_TIMER] = set_watchdog_timer,
1662 [IPMI_CMD_GET_WATCHDOG_TIMER] = get_watchdog_timer,
1664 static const IPMINetfn app_netfn = {
1665 .cmd_nums = ARRAY_SIZE(app_cmds),
1666 .cmd_handlers = app_cmds
1669 static const IPMICmdHandler storage_cmds[] = {
1670 [IPMI_CMD_GET_SDR_REP_INFO] = get_sdr_rep_info,
1671 [IPMI_CMD_RESERVE_SDR_REP] = reserve_sdr_rep,
1672 [IPMI_CMD_GET_SDR] = get_sdr,
1673 [IPMI_CMD_ADD_SDR] = add_sdr,
1674 [IPMI_CMD_CLEAR_SDR_REP] = clear_sdr_rep,
1675 [IPMI_CMD_GET_SEL_INFO] = get_sel_info,
1676 [IPMI_CMD_RESERVE_SEL] = reserve_sel,
1677 [IPMI_CMD_GET_SEL_ENTRY] = get_sel_entry,
1678 [IPMI_CMD_ADD_SEL_ENTRY] = add_sel_entry,
1679 [IPMI_CMD_CLEAR_SEL] = clear_sel,
1680 [IPMI_CMD_GET_SEL_TIME] = get_sel_time,
1681 [IPMI_CMD_SET_SEL_TIME] = set_sel_time,
1684 static const IPMINetfn storage_netfn = {
1685 .cmd_nums = ARRAY_SIZE(storage_cmds),
1686 .cmd_handlers = storage_cmds
1689 static void register_cmds(IPMIBmcSim *s)
1691 ipmi_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
1692 ipmi_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
1693 ipmi_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
1694 ipmi_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
1697 static const uint8_t init_sdrs[] = {
1698 /* Watchdog device */
1699 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1700 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1703 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1704 /* End */
1705 0xff, 0xff, 0x00, 0x00, 0x00
1708 static const VMStateDescription vmstate_ipmi_sim = {
1709 .name = TYPE_IPMI_BMC_SIMULATOR,
1710 .version_id = 1,
1711 .minimum_version_id = 1,
1712 .fields = (VMStateField[]) {
1713 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
1714 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
1715 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
1716 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
1717 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
1718 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
1719 VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
1720 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
1721 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
1722 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
1723 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
1724 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
1725 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
1726 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
1727 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
1728 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
1729 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
1730 IPMIBmcSim),
1731 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
1732 VMSTATE_END_OF_LIST()
1736 static void ipmi_sim_init(Object *obj)
1738 IPMIBmc *b = IPMI_BMC(obj);
1739 unsigned int i;
1740 unsigned int recid;
1741 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
1743 qemu_mutex_init(&ibs->lock);
1744 QTAILQ_INIT(&ibs->rcvbufs);
1746 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
1747 ibs->device_id = 0x20;
1748 ibs->ipmi_version = 0x02; /* IPMI 2.0 */
1749 ibs->restart_cause = 0;
1750 for (i = 0; i < 4; i++) {
1751 ibs->sel.last_addition[i] = 0xff;
1752 ibs->sel.last_clear[i] = 0xff;
1753 ibs->sdr.last_addition[i] = 0xff;
1754 ibs->sdr.last_clear[i] = 0xff;
1757 for (i = 0;;) {
1758 struct ipmi_sdr_header *sdrh;
1759 int len;
1760 if ((i + IPMI_SDR_HEADER_SIZE) > sizeof(init_sdrs)) {
1761 error_report("Problem with recid 0x%4.4x", i);
1762 return;
1764 sdrh = (struct ipmi_sdr_header *) &init_sdrs[i];
1765 len = ipmi_sdr_length(sdrh);
1766 recid = ipmi_sdr_recid(sdrh);
1767 if (recid == 0xffff) {
1768 break;
1770 if ((i + len) > sizeof(init_sdrs)) {
1771 error_report("Problem with recid 0x%4.4x", i);
1772 return;
1774 sdr_add_entry(ibs, sdrh, len, NULL);
1775 i += len;
1778 ibs->acpi_power_state[0] = 0;
1779 ibs->acpi_power_state[1] = 0;
1781 if (qemu_uuid_set) {
1782 memcpy(&ibs->uuid, qemu_uuid, 16);
1783 } else {
1784 memset(&ibs->uuid, 0, 16);
1787 ipmi_init_sensors_from_sdrs(ibs);
1788 register_cmds(ibs);
1790 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
1792 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
1795 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
1797 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
1799 bk->handle_command = ipmi_sim_handle_command;
1802 static const TypeInfo ipmi_sim_type = {
1803 .name = TYPE_IPMI_BMC_SIMULATOR,
1804 .parent = TYPE_IPMI_BMC,
1805 .instance_size = sizeof(IPMIBmcSim),
1806 .instance_init = ipmi_sim_init,
1807 .class_init = ipmi_sim_class_init,
1810 static void ipmi_sim_register_types(void)
1812 type_register_static(&ipmi_sim_type);
1815 type_init(ipmi_sim_register_types)