ipmi: remove IPMI_CHECK_CMD_LEN() macro
[qemu/ar7.git] / hw / ipmi / ipmi_bmc_sim.c
blobcbf2991e209ac3d5462f9299ced3b5e83e373fe6
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
159 typedef struct IPMICmdHandler {
160 void (*cmd_handler)(IPMIBmcSim *s,
161 uint8_t *cmd, unsigned int cmd_len,
162 uint8_t *rsp, unsigned int *rsp_len,
163 unsigned int max_rsp_len);
164 unsigned int cmd_len_min;
165 } IPMICmdHandler;
167 typedef struct IPMINetfn {
168 unsigned int cmd_nums;
169 const IPMICmdHandler *cmd_handlers;
170 } IPMINetfn;
172 typedef struct IPMIRcvBufEntry {
173 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
174 uint8_t len;
175 uint8_t buf[MAX_IPMI_MSG_SIZE];
176 } IPMIRcvBufEntry;
178 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
179 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
180 TYPE_IPMI_BMC_SIMULATOR)
181 struct IPMIBmcSim {
182 IPMIBmc parent;
184 QEMUTimer *timer;
186 uint8_t bmc_global_enables;
187 uint8_t msg_flags;
189 bool watchdog_initialized;
190 uint8_t watchdog_use;
191 uint8_t watchdog_action;
192 uint8_t watchdog_pretimeout; /* In seconds */
193 bool watchdog_expired;
194 uint16_t watchdog_timeout; /* in 100's of milliseconds */
196 bool watchdog_running;
197 bool watchdog_preaction_ran;
198 int64_t watchdog_expiry;
200 uint8_t device_id;
201 uint8_t ipmi_version;
202 uint8_t device_rev;
203 uint8_t fwrev1;
204 uint8_t fwrev2;
205 uint8_t mfg_id[3];
206 uint8_t product_id[2];
208 uint8_t restart_cause;
210 uint8_t acpi_power_state[2];
211 uint8_t uuid[16];
213 IPMISel sel;
214 IPMISdr sdr;
215 IPMISensor sensors[MAX_SENSORS];
217 /* Odd netfns are for responses, so we only need the even ones. */
218 const IPMINetfn *netfns[MAX_NETFNS / 2];
220 QemuMutex lock;
221 /* We allow one event in the buffer */
222 uint8_t evtbuf[16];
224 QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
227 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
228 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
229 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
230 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
231 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
232 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
233 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
234 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
235 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
237 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
238 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
239 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
240 #define IPMI_BMC_EVENT_LOG_BIT 3
241 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
242 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
243 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
244 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
245 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
246 (1 << IPMI_BMC_EVENT_LOG_BIT))
247 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
248 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
250 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
251 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
252 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
253 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
254 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
255 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
256 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
257 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
258 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
259 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
260 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
261 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
262 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
263 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
264 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
267 /* Add a byte to the response. */
268 #define IPMI_ADD_RSP_DATA(b) \
269 do { \
270 if (*rsp_len >= max_rsp_len) { \
271 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED; \
272 return; \
274 rsp[(*rsp_len)++] = (b); \
275 } while (0)
277 /* Check that the reservation in the command is valid. */
278 #define IPMI_CHECK_RESERVATION(off, r) \
279 do { \
280 if ((cmd[off] | (cmd[off + 1] << 8)) != r) { \
281 rsp[2] = IPMI_CC_INVALID_RESERVATION; \
282 return; \
284 } while (0)
287 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
289 static void ipmi_gettime(struct ipmi_time *time)
291 int64_t stime;
293 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
294 time->tv_sec = stime / 1000000000LL;
295 time->tv_nsec = stime % 1000000000LL;
298 static int64_t ipmi_getmonotime(void)
300 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
303 static void ipmi_timeout(void *opaque)
305 IPMIBmcSim *ibs = opaque;
307 ipmi_sim_handle_timeout(ibs);
310 static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
312 unsigned int val;
313 struct ipmi_time now;
315 ipmi_gettime(&now);
316 val = now.tv_sec + ibs->sel.time_offset;
317 ts[0] = val & 0xff;
318 ts[1] = (val >> 8) & 0xff;
319 ts[2] = (val >> 16) & 0xff;
320 ts[3] = (val >> 24) & 0xff;
323 static void sdr_inc_reservation(IPMISdr *sdr)
325 sdr->reservation++;
326 if (sdr->reservation == 0) {
327 sdr->reservation = 1;
331 static int sdr_add_entry(IPMIBmcSim *ibs,
332 const struct ipmi_sdr_header *sdrh_entry,
333 unsigned int len, uint16_t *recid)
335 struct ipmi_sdr_header *sdrh =
336 (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
338 if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
339 return 1;
342 if (ipmi_sdr_length(sdrh_entry) != len) {
343 return 1;
346 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
347 ibs->sdr.overflow = 1;
348 return 1;
351 memcpy(sdrh, sdrh_entry, len);
352 sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff;
353 sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
354 sdrh->sdr_version = 0x51; /* Conform to IPMI 1.5 spec */
356 if (recid) {
357 *recid = ibs->sdr.next_rec_id;
359 ibs->sdr.next_rec_id++;
360 set_timestamp(ibs, ibs->sdr.last_addition);
361 ibs->sdr.next_free += len;
362 sdr_inc_reservation(&ibs->sdr);
363 return 0;
366 static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
367 unsigned int *retpos, uint16_t *nextrec)
369 unsigned int pos = *retpos;
371 while (pos < sdr->next_free) {
372 struct ipmi_sdr_header *sdrh =
373 (struct ipmi_sdr_header *) &sdr->sdr[pos];
374 uint16_t trec = ipmi_sdr_recid(sdrh);
375 unsigned int nextpos = pos + ipmi_sdr_length(sdrh);
377 if (trec == recid) {
378 if (nextrec) {
379 if (nextpos >= sdr->next_free) {
380 *nextrec = 0xffff;
381 } else {
382 *nextrec = (sdr->sdr[nextpos] |
383 (sdr->sdr[nextpos + 1] << 8));
386 *retpos = pos;
387 return 0;
389 pos = nextpos;
391 return 1;
394 static void sel_inc_reservation(IPMISel *sel)
396 sel->reservation++;
397 if (sel->reservation == 0) {
398 sel->reservation = 1;
402 /* Returns 1 if the SEL is full and can't hold the event. */
403 static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
405 event[0] = 0xff;
406 event[1] = 0xff;
407 set_timestamp(ibs, event + 3);
408 if (ibs->sel.next_free == MAX_SEL_SIZE) {
409 ibs->sel.overflow = 1;
410 return 1;
412 event[0] = ibs->sel.next_free & 0xff;
413 event[1] = (ibs->sel.next_free >> 8) & 0xff;
414 memcpy(ibs->sel.last_addition, event + 3, 4);
415 memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
416 ibs->sel.next_free++;
417 sel_inc_reservation(&ibs->sel);
418 return 0;
421 static int attn_set(IPMIBmcSim *ibs)
423 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
424 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
425 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
428 static int attn_irq_enabled(IPMIBmcSim *ibs)
430 return (IPMI_BMC_MSG_INTS_ON(ibs) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs))
431 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
432 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
435 static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
436 uint8_t evd1, uint8_t evd2, uint8_t evd3)
438 IPMIInterface *s = ibs->parent.intf;
439 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
440 uint8_t evt[16];
441 IPMISensor *sens = ibs->sensors + sens_num;
443 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
444 return;
446 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
447 return;
450 evt[2] = 0x2; /* System event record */
451 evt[7] = ibs->parent.slave_addr;
452 evt[8] = 0;
453 evt[9] = 0x04; /* Format version */
454 evt[10] = sens->sensor_type;
455 evt[11] = sens_num;
456 evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
457 evt[13] = evd1;
458 evt[14] = evd2;
459 evt[15] = evd3;
461 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
462 sel_add_event(ibs, evt);
465 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
466 return;
469 memcpy(ibs->evtbuf, evt, 16);
470 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
471 k->set_atn(s, 1, attn_irq_enabled(ibs));
474 static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
475 unsigned int bit, unsigned int val,
476 uint8_t evd1, uint8_t evd2, uint8_t evd3)
478 IPMISensor *sens;
479 uint16_t mask;
481 if (sensor >= MAX_SENSORS) {
482 return;
484 if (bit >= 16) {
485 return;
488 mask = (1 << bit);
489 sens = ibs->sensors + sensor;
490 if (val) {
491 sens->states |= mask & sens->states_suppt;
492 if (sens->assert_states & mask) {
493 return; /* Already asserted */
495 sens->assert_states |= mask & sens->assert_suppt;
496 if (sens->assert_enable & mask & sens->assert_states) {
497 /* Send an event on assert */
498 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
500 } else {
501 sens->states &= ~(mask & sens->states_suppt);
502 if (sens->deassert_states & mask) {
503 return; /* Already deasserted */
505 sens->deassert_states |= mask & sens->deassert_suppt;
506 if (sens->deassert_enable & mask & sens->deassert_states) {
507 /* Send an event on deassert */
508 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
513 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
515 unsigned int i, pos;
516 IPMISensor *sens;
518 for (i = 0; i < MAX_SENSORS; i++) {
519 memset(s->sensors + i, 0, sizeof(*sens));
522 pos = 0;
523 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
524 struct ipmi_sdr_compact *sdr =
525 (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
526 unsigned int len = sdr->header.rec_length;
528 if (len < 20) {
529 continue;
531 if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
532 continue; /* Not a sensor SDR we set from */
535 if (sdr->sensor_owner_number >= MAX_SENSORS) {
536 continue;
538 sens = s->sensors + sdr->sensor_owner_number;
540 IPMI_SENSOR_SET_PRESENT(sens, 1);
541 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
542 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
543 sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
544 sens->deassert_suppt =
545 sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
546 sens->states_suppt =
547 sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
548 sens->sensor_type = sdr->sensor_type;
549 sens->evt_reading_type_code = sdr->reading_type & 0x7f;
551 /* Enable all the events that are supported. */
552 sens->assert_enable = sens->assert_suppt;
553 sens->deassert_enable = sens->deassert_suppt;
557 static int ipmi_register_netfn(IPMIBmcSim *s, unsigned int netfn,
558 const IPMINetfn *netfnd)
560 if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
561 return -1;
563 s->netfns[netfn / 2] = netfnd;
564 return 0;
567 static const IPMICmdHandler *ipmi_get_handler(IPMIBmcSim *ibs,
568 unsigned int netfn,
569 unsigned int cmd)
571 const IPMICmdHandler *hdl;
573 if (netfn & 1 || netfn >= MAX_NETFNS || !ibs->netfns[netfn / 2]) {
574 return NULL;
577 if (cmd >= ibs->netfns[netfn / 2]->cmd_nums) {
578 return NULL;
581 hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd];
582 if (!hdl->cmd_handler) {
583 return NULL;
586 return hdl;
589 static void next_timeout(IPMIBmcSim *ibs)
591 int64_t next;
592 if (ibs->watchdog_running) {
593 next = ibs->watchdog_expiry;
594 } else {
595 /* Wait a minute */
596 next = ipmi_getmonotime() + 60 * 1000000000LL;
598 timer_mod_ns(ibs->timer, next);
601 static void ipmi_sim_handle_command(IPMIBmc *b,
602 uint8_t *cmd, unsigned int cmd_len,
603 unsigned int max_cmd_len,
604 uint8_t msg_id)
606 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
607 IPMIInterface *s = ibs->parent.intf;
608 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
609 uint8_t rsp[MAX_IPMI_MSG_SIZE];
610 unsigned int rsp_len_holder = 0;
611 unsigned int *rsp_len = &rsp_len_holder;
612 unsigned int max_rsp_len = sizeof(rsp);
613 const IPMICmdHandler *hdl;
615 /* Set up the response, set the low bit of NETFN. */
616 /* Note that max_rsp_len must be at least 3 */
617 if (max_rsp_len < 3) {
618 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
619 goto out;
622 IPMI_ADD_RSP_DATA(cmd[0] | 0x04);
623 IPMI_ADD_RSP_DATA(cmd[1]);
624 IPMI_ADD_RSP_DATA(0); /* Assume success */
626 /* If it's too short or it was truncated, return an error. */
627 if (cmd_len < 2) {
628 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
629 goto out;
631 if (cmd_len > max_cmd_len) {
632 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
633 goto out;
636 if ((cmd[0] & 0x03) != 0) {
637 /* Only have stuff on LUN 0 */
638 rsp[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
639 goto out;
642 hdl = ipmi_get_handler(ibs, cmd[0] >> 2, cmd[1]);
643 if (!hdl) {
644 rsp[2] = IPMI_CC_INVALID_CMD;
645 goto out;
648 if (cmd_len < hdl->cmd_len_min) {
649 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
650 goto out;
653 hdl->cmd_handler(ibs, cmd, cmd_len, rsp, rsp_len, max_rsp_len);
655 out:
656 k->handle_rsp(s, msg_id, rsp, *rsp_len);
658 next_timeout(ibs);
661 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
663 IPMIInterface *s = ibs->parent.intf;
664 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
666 if (!ibs->watchdog_running) {
667 goto out;
670 if (!ibs->watchdog_preaction_ran) {
671 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
672 case IPMI_BMC_WATCHDOG_PRE_NMI:
673 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
674 k->do_hw_op(s, IPMI_SEND_NMI, 0);
675 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
676 0xc8, (2 << 4) | 0xf, 0xff);
677 break;
679 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
680 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
681 k->set_atn(s, 1, attn_irq_enabled(ibs));
682 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
683 0xc8, (3 << 4) | 0xf, 0xff);
684 break;
686 default:
687 goto do_full_expiry;
690 ibs->watchdog_preaction_ran = 1;
691 /* Issued the pretimeout, do the rest of the timeout now. */
692 ibs->watchdog_expiry = ipmi_getmonotime();
693 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
694 goto out;
697 do_full_expiry:
698 ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
699 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
700 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
701 case IPMI_BMC_WATCHDOG_ACTION_NONE:
702 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
703 0xc0, ibs->watchdog_use & 0xf, 0xff);
704 break;
706 case IPMI_BMC_WATCHDOG_ACTION_RESET:
707 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
708 0xc1, ibs->watchdog_use & 0xf, 0xff);
709 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
710 break;
712 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
713 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
714 0xc2, ibs->watchdog_use & 0xf, 0xff);
715 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
716 break;
718 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
719 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
720 0xc3, ibs->watchdog_use & 0xf, 0xff);
721 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
722 break;
725 out:
726 next_timeout(ibs);
729 static void chassis_capabilities(IPMIBmcSim *ibs,
730 uint8_t *cmd, unsigned int cmd_len,
731 uint8_t *rsp, unsigned int *rsp_len,
732 unsigned int max_rsp_len)
734 IPMI_ADD_RSP_DATA(0);
735 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
736 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
737 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
738 IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
741 static void chassis_status(IPMIBmcSim *ibs,
742 uint8_t *cmd, unsigned int cmd_len,
743 uint8_t *rsp, unsigned int *rsp_len,
744 unsigned int max_rsp_len)
746 IPMI_ADD_RSP_DATA(0x61); /* Unknown power restore, power is on */
747 IPMI_ADD_RSP_DATA(0);
748 IPMI_ADD_RSP_DATA(0);
749 IPMI_ADD_RSP_DATA(0);
752 static void chassis_control(IPMIBmcSim *ibs,
753 uint8_t *cmd, unsigned int cmd_len,
754 uint8_t *rsp, unsigned int *rsp_len,
755 unsigned int max_rsp_len)
757 IPMIInterface *s = ibs->parent.intf;
758 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
760 switch (cmd[2] & 0xf) {
761 case 0: /* power down */
762 rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
763 break;
764 case 1: /* power up */
765 rsp[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
766 break;
767 case 2: /* power cycle */
768 rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
769 break;
770 case 3: /* hard reset */
771 rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
772 break;
773 case 4: /* pulse diagnostic interrupt */
774 rsp[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
775 break;
776 case 5: /* soft shutdown via ACPI by overtemp emulation */
777 rsp[2] = k->do_hw_op(s,
778 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0);
779 break;
780 default:
781 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
782 return;
786 static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
787 uint8_t *cmd, unsigned int cmd_len,
788 uint8_t *rsp, unsigned int *rsp_len,
789 unsigned int max_rsp_len)
791 IPMI_ADD_RSP_DATA(ibs->restart_cause & 0xf); /* Restart Cause */
792 IPMI_ADD_RSP_DATA(0); /* Channel 0 */
795 static void get_device_id(IPMIBmcSim *ibs,
796 uint8_t *cmd, unsigned int cmd_len,
797 uint8_t *rsp, unsigned int *rsp_len,
798 unsigned int max_rsp_len)
800 IPMI_ADD_RSP_DATA(ibs->device_id);
801 IPMI_ADD_RSP_DATA(ibs->device_rev & 0xf);
802 IPMI_ADD_RSP_DATA(ibs->fwrev1 & 0x7f);
803 IPMI_ADD_RSP_DATA(ibs->fwrev2);
804 IPMI_ADD_RSP_DATA(ibs->ipmi_version);
805 IPMI_ADD_RSP_DATA(0x07); /* sensor, SDR, and SEL. */
806 IPMI_ADD_RSP_DATA(ibs->mfg_id[0]);
807 IPMI_ADD_RSP_DATA(ibs->mfg_id[1]);
808 IPMI_ADD_RSP_DATA(ibs->mfg_id[2]);
809 IPMI_ADD_RSP_DATA(ibs->product_id[0]);
810 IPMI_ADD_RSP_DATA(ibs->product_id[1]);
813 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
815 IPMIInterface *s = ibs->parent.intf;
816 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
817 bool irqs_on;
819 ibs->bmc_global_enables = val;
821 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
822 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
824 k->set_irq_enable(s, irqs_on);
827 static void cold_reset(IPMIBmcSim *ibs,
828 uint8_t *cmd, unsigned int cmd_len,
829 uint8_t *rsp, unsigned int *rsp_len,
830 unsigned int max_rsp_len)
832 IPMIInterface *s = ibs->parent.intf;
833 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
835 /* Disable all interrupts */
836 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
838 if (k->reset) {
839 k->reset(s, true);
843 static void warm_reset(IPMIBmcSim *ibs,
844 uint8_t *cmd, unsigned int cmd_len,
845 uint8_t *rsp, unsigned int *rsp_len,
846 unsigned int max_rsp_len)
848 IPMIInterface *s = ibs->parent.intf;
849 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
851 if (k->reset) {
852 k->reset(s, false);
855 static void set_acpi_power_state(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 ibs->acpi_power_state[0] = cmd[2];
861 ibs->acpi_power_state[1] = cmd[3];
864 static void get_acpi_power_state(IPMIBmcSim *ibs,
865 uint8_t *cmd, unsigned int cmd_len,
866 uint8_t *rsp, unsigned int *rsp_len,
867 unsigned int max_rsp_len)
869 IPMI_ADD_RSP_DATA(ibs->acpi_power_state[0]);
870 IPMI_ADD_RSP_DATA(ibs->acpi_power_state[1]);
873 static void get_device_guid(IPMIBmcSim *ibs,
874 uint8_t *cmd, unsigned int cmd_len,
875 uint8_t *rsp, unsigned int *rsp_len,
876 unsigned int max_rsp_len)
878 unsigned int i;
880 for (i = 0; i < 16; i++) {
881 IPMI_ADD_RSP_DATA(ibs->uuid[i]);
885 static void set_bmc_global_enables(IPMIBmcSim *ibs,
886 uint8_t *cmd, unsigned int cmd_len,
887 uint8_t *rsp, unsigned int *rsp_len,
888 unsigned int max_rsp_len)
890 set_global_enables(ibs, cmd[2]);
893 static void get_bmc_global_enables(IPMIBmcSim *ibs,
894 uint8_t *cmd, unsigned int cmd_len,
895 uint8_t *rsp, unsigned int *rsp_len,
896 unsigned int max_rsp_len)
898 IPMI_ADD_RSP_DATA(ibs->bmc_global_enables);
901 static void clr_msg_flags(IPMIBmcSim *ibs,
902 uint8_t *cmd, unsigned int cmd_len,
903 uint8_t *rsp, unsigned int *rsp_len,
904 unsigned int max_rsp_len)
906 IPMIInterface *s = ibs->parent.intf;
907 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
909 ibs->msg_flags &= ~cmd[2];
910 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
913 static void get_msg_flags(IPMIBmcSim *ibs,
914 uint8_t *cmd, unsigned int cmd_len,
915 uint8_t *rsp, unsigned int *rsp_len,
916 unsigned int max_rsp_len)
918 IPMI_ADD_RSP_DATA(ibs->msg_flags);
921 static void read_evt_msg_buf(IPMIBmcSim *ibs,
922 uint8_t *cmd, unsigned int cmd_len,
923 uint8_t *rsp, unsigned int *rsp_len,
924 unsigned int max_rsp_len)
926 IPMIInterface *s = ibs->parent.intf;
927 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
928 unsigned int i;
930 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
931 rsp[2] = 0x80;
932 return;
934 for (i = 0; i < 16; i++) {
935 IPMI_ADD_RSP_DATA(ibs->evtbuf[i]);
937 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
938 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
941 static void get_msg(IPMIBmcSim *ibs,
942 uint8_t *cmd, unsigned int cmd_len,
943 uint8_t *rsp, unsigned int *rsp_len,
944 unsigned int max_rsp_len)
946 IPMIRcvBufEntry *msg;
948 qemu_mutex_lock(&ibs->lock);
949 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
950 rsp[2] = 0x80; /* Queue empty */
951 goto out;
953 rsp[3] = 0; /* Channel 0 */
954 *rsp_len += 1;
955 msg = QTAILQ_FIRST(&ibs->rcvbufs);
956 memcpy(rsp + 4, msg->buf, msg->len);
957 *rsp_len += msg->len;
958 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
959 g_free(msg);
961 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
962 IPMIInterface *s = ibs->parent.intf;
963 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
965 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
966 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
969 out:
970 qemu_mutex_unlock(&ibs->lock);
971 return;
974 static unsigned char
975 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
977 for (; size > 0; size--, data++) {
978 csum += *data;
981 return -csum;
984 static void send_msg(IPMIBmcSim *ibs,
985 uint8_t *cmd, unsigned int cmd_len,
986 uint8_t *rsp, unsigned int *rsp_len,
987 unsigned int max_rsp_len)
989 IPMIInterface *s = ibs->parent.intf;
990 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
991 IPMIRcvBufEntry *msg;
992 uint8_t *buf;
993 uint8_t netfn, rqLun, rsLun, rqSeq;
995 if (cmd[2] != 0) {
996 /* We only handle channel 0 with no options */
997 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
998 return;
1001 if (cmd_len < 10) {
1002 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
1003 return;
1006 if (cmd[3] != 0x40) {
1007 /* We only emulate a MC at address 0x40. */
1008 rsp[2] = 0x83; /* NAK on write */
1009 return;
1012 cmd += 3; /* Skip the header. */
1013 cmd_len -= 3;
1016 * At this point we "send" the message successfully. Any error will
1017 * be returned in the response.
1019 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
1020 cmd[3] != 0x20) { /* Improper response address */
1021 return; /* No response */
1024 netfn = cmd[1] >> 2;
1025 rqLun = cmd[4] & 0x3;
1026 rsLun = cmd[1] & 0x3;
1027 rqSeq = cmd[4] >> 2;
1029 if (rqLun != 2) {
1030 /* We only support LUN 2 coming back to us. */
1031 return;
1034 msg = g_malloc(sizeof(*msg));
1035 msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
1036 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
1037 msg->buf[2] = cmd[0]; /* rsSA */
1038 msg->buf[3] = (rqSeq << 2) | rsLun;
1039 msg->buf[4] = cmd[5]; /* Cmd */
1040 msg->buf[5] = 0; /* Completion Code */
1041 msg->len = 6;
1043 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
1044 /* Not a command we handle. */
1045 msg->buf[5] = IPMI_CC_INVALID_CMD;
1046 goto end_msg;
1049 buf = msg->buf + msg->len; /* After the CC */
1050 buf[0] = 0;
1051 buf[1] = 0;
1052 buf[2] = 0;
1053 buf[3] = 0;
1054 buf[4] = 0x51;
1055 buf[5] = 0;
1056 buf[6] = 0;
1057 buf[7] = 0;
1058 buf[8] = 0;
1059 buf[9] = 0;
1060 buf[10] = 0;
1061 msg->len += 11;
1063 end_msg:
1064 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1065 msg->len++;
1066 qemu_mutex_lock(&ibs->lock);
1067 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1068 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1069 k->set_atn(s, 1, attn_irq_enabled(ibs));
1070 qemu_mutex_unlock(&ibs->lock);
1073 static void do_watchdog_reset(IPMIBmcSim *ibs)
1075 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1076 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1077 ibs->watchdog_running = 0;
1078 return;
1080 ibs->watchdog_preaction_ran = 0;
1083 /* Timeout is in tenths of a second, offset is in seconds */
1084 ibs->watchdog_expiry = ipmi_getmonotime();
1085 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1086 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1087 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1089 ibs->watchdog_running = 1;
1092 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1093 uint8_t *cmd, unsigned int cmd_len,
1094 uint8_t *rsp, unsigned int *rsp_len,
1095 unsigned int max_rsp_len)
1097 if (!ibs->watchdog_initialized) {
1098 rsp[2] = 0x80;
1099 return;
1101 do_watchdog_reset(ibs);
1104 static void set_watchdog_timer(IPMIBmcSim *ibs,
1105 uint8_t *cmd, unsigned int cmd_len,
1106 uint8_t *rsp, unsigned int *rsp_len,
1107 unsigned int max_rsp_len)
1109 IPMIInterface *s = ibs->parent.intf;
1110 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1111 unsigned int val;
1113 val = cmd[2] & 0x7; /* Validate use */
1114 if (val == 0 || val > 5) {
1115 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1116 return;
1118 val = cmd[3] & 0x7; /* Validate action */
1119 switch (val) {
1120 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1121 break;
1123 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1124 rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
1125 break;
1127 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1128 rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
1129 break;
1131 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1132 rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
1133 break;
1135 default:
1136 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1138 if (rsp[2]) {
1139 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1140 return;
1143 val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1144 switch (val) {
1145 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1146 case IPMI_BMC_WATCHDOG_PRE_NONE:
1147 break;
1149 case IPMI_BMC_WATCHDOG_PRE_NMI:
1150 if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1151 /* NMI not supported. */
1152 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1153 return;
1155 break;
1157 default:
1158 /* We don't support PRE_SMI */
1159 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1160 return;
1163 ibs->watchdog_initialized = 1;
1164 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1165 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1166 ibs->watchdog_pretimeout = cmd[4];
1167 ibs->watchdog_expired &= ~cmd[5];
1168 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1169 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1170 do_watchdog_reset(ibs);
1171 } else {
1172 ibs->watchdog_running = 0;
1176 static void get_watchdog_timer(IPMIBmcSim *ibs,
1177 uint8_t *cmd, unsigned int cmd_len,
1178 uint8_t *rsp, unsigned int *rsp_len,
1179 unsigned int max_rsp_len)
1181 IPMI_ADD_RSP_DATA(ibs->watchdog_use);
1182 IPMI_ADD_RSP_DATA(ibs->watchdog_action);
1183 IPMI_ADD_RSP_DATA(ibs->watchdog_pretimeout);
1184 IPMI_ADD_RSP_DATA(ibs->watchdog_expired);
1185 if (ibs->watchdog_running) {
1186 long timeout;
1187 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1188 / 100000000);
1189 IPMI_ADD_RSP_DATA(timeout & 0xff);
1190 IPMI_ADD_RSP_DATA((timeout >> 8) & 0xff);
1191 } else {
1192 IPMI_ADD_RSP_DATA(0);
1193 IPMI_ADD_RSP_DATA(0);
1197 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1198 uint8_t *cmd, unsigned int cmd_len,
1199 uint8_t *rsp, unsigned int *rsp_len,
1200 unsigned int max_rsp_len)
1202 unsigned int i;
1204 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 spec */
1205 IPMI_ADD_RSP_DATA(ibs->sdr.next_rec_id & 0xff);
1206 IPMI_ADD_RSP_DATA((ibs->sdr.next_rec_id >> 8) & 0xff);
1207 IPMI_ADD_RSP_DATA((MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1208 IPMI_ADD_RSP_DATA(((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1209 for (i = 0; i < 4; i++) {
1210 IPMI_ADD_RSP_DATA(ibs->sdr.last_addition[i]);
1212 for (i = 0; i < 4; i++) {
1213 IPMI_ADD_RSP_DATA(ibs->sdr.last_clear[i]);
1215 /* Only modal support, reserve supported */
1216 IPMI_ADD_RSP_DATA((ibs->sdr.overflow << 7) | 0x22);
1219 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1220 uint8_t *cmd, unsigned int cmd_len,
1221 uint8_t *rsp, unsigned int *rsp_len,
1222 unsigned int max_rsp_len)
1224 IPMI_ADD_RSP_DATA(ibs->sdr.reservation & 0xff);
1225 IPMI_ADD_RSP_DATA((ibs->sdr.reservation >> 8) & 0xff);
1228 static void get_sdr(IPMIBmcSim *ibs,
1229 uint8_t *cmd, unsigned int cmd_len,
1230 uint8_t *rsp, unsigned int *rsp_len,
1231 unsigned int max_rsp_len)
1233 unsigned int pos;
1234 uint16_t nextrec;
1235 struct ipmi_sdr_header *sdrh;
1237 if (cmd[6]) {
1238 IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
1240 pos = 0;
1241 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1242 &pos, &nextrec)) {
1243 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1244 return;
1247 sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1249 if (cmd[6] > ipmi_sdr_length(sdrh)) {
1250 rsp[2] = IPMI_CC_PARM_OUT_OF_RANGE;
1251 return;
1254 IPMI_ADD_RSP_DATA(nextrec & 0xff);
1255 IPMI_ADD_RSP_DATA((nextrec >> 8) & 0xff);
1257 if (cmd[7] == 0xff) {
1258 cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1261 if ((cmd[7] + *rsp_len) > max_rsp_len) {
1262 rsp[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
1263 return;
1265 memcpy(rsp + *rsp_len, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1266 *rsp_len += cmd[7];
1269 static void add_sdr(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 uint16_t recid;
1275 struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1277 if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1278 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1279 return;
1281 IPMI_ADD_RSP_DATA(recid & 0xff);
1282 IPMI_ADD_RSP_DATA((recid >> 8) & 0xff);
1285 static void clear_sdr_rep(IPMIBmcSim *ibs,
1286 uint8_t *cmd, unsigned int cmd_len,
1287 uint8_t *rsp, unsigned int *rsp_len,
1288 unsigned int max_rsp_len)
1290 IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
1291 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1292 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1293 return;
1295 if (cmd[7] == 0xaa) {
1296 ibs->sdr.next_free = 0;
1297 ibs->sdr.overflow = 0;
1298 set_timestamp(ibs, ibs->sdr.last_clear);
1299 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1300 sdr_inc_reservation(&ibs->sdr);
1301 } else if (cmd[7] == 0) {
1302 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1303 } else {
1304 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1305 return;
1309 static void get_sel_info(IPMIBmcSim *ibs,
1310 uint8_t *cmd, unsigned int cmd_len,
1311 uint8_t *rsp, unsigned int *rsp_len,
1312 unsigned int max_rsp_len)
1314 unsigned int i, val;
1316 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 */
1317 IPMI_ADD_RSP_DATA(ibs->sel.next_free & 0xff);
1318 IPMI_ADD_RSP_DATA((ibs->sel.next_free >> 8) & 0xff);
1319 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1320 IPMI_ADD_RSP_DATA(val & 0xff);
1321 IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
1322 for (i = 0; i < 4; i++) {
1323 IPMI_ADD_RSP_DATA(ibs->sel.last_addition[i]);
1325 for (i = 0; i < 4; i++) {
1326 IPMI_ADD_RSP_DATA(ibs->sel.last_clear[i]);
1328 /* Only support Reserve SEL */
1329 IPMI_ADD_RSP_DATA((ibs->sel.overflow << 7) | 0x02);
1332 static void reserve_sel(IPMIBmcSim *ibs,
1333 uint8_t *cmd, unsigned int cmd_len,
1334 uint8_t *rsp, unsigned int *rsp_len,
1335 unsigned int max_rsp_len)
1337 IPMI_ADD_RSP_DATA(ibs->sel.reservation & 0xff);
1338 IPMI_ADD_RSP_DATA((ibs->sel.reservation >> 8) & 0xff);
1341 static void get_sel_entry(IPMIBmcSim *ibs,
1342 uint8_t *cmd, unsigned int cmd_len,
1343 uint8_t *rsp, unsigned int *rsp_len,
1344 unsigned int max_rsp_len)
1346 unsigned int val;
1348 if (cmd[6]) {
1349 IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
1351 if (ibs->sel.next_free == 0) {
1352 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1353 return;
1355 if (cmd[6] > 15) {
1356 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1357 return;
1359 if (cmd[7] == 0xff) {
1360 cmd[7] = 16;
1361 } else if ((cmd[7] + cmd[6]) > 16) {
1362 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1363 return;
1364 } else {
1365 cmd[7] += cmd[6];
1368 val = cmd[4] | (cmd[5] << 8);
1369 if (val == 0xffff) {
1370 val = ibs->sel.next_free - 1;
1371 } else if (val >= ibs->sel.next_free) {
1372 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1373 return;
1375 if ((val + 1) == ibs->sel.next_free) {
1376 IPMI_ADD_RSP_DATA(0xff);
1377 IPMI_ADD_RSP_DATA(0xff);
1378 } else {
1379 IPMI_ADD_RSP_DATA((val + 1) & 0xff);
1380 IPMI_ADD_RSP_DATA(((val + 1) >> 8) & 0xff);
1382 for (; cmd[6] < cmd[7]; cmd[6]++) {
1383 IPMI_ADD_RSP_DATA(ibs->sel.sel[val][cmd[6]]);
1387 static void add_sel_entry(IPMIBmcSim *ibs,
1388 uint8_t *cmd, unsigned int cmd_len,
1389 uint8_t *rsp, unsigned int *rsp_len,
1390 unsigned int max_rsp_len)
1392 if (sel_add_event(ibs, cmd + 2)) {
1393 rsp[2] = IPMI_CC_OUT_OF_SPACE;
1394 return;
1396 /* sel_add_event fills in the record number. */
1397 IPMI_ADD_RSP_DATA(cmd[2]);
1398 IPMI_ADD_RSP_DATA(cmd[3]);
1401 static void clear_sel(IPMIBmcSim *ibs,
1402 uint8_t *cmd, unsigned int cmd_len,
1403 uint8_t *rsp, unsigned int *rsp_len,
1404 unsigned int max_rsp_len)
1406 IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
1407 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1408 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1409 return;
1411 if (cmd[7] == 0xaa) {
1412 ibs->sel.next_free = 0;
1413 ibs->sel.overflow = 0;
1414 set_timestamp(ibs, ibs->sdr.last_clear);
1415 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1416 sel_inc_reservation(&ibs->sel);
1417 } else if (cmd[7] == 0) {
1418 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1419 } else {
1420 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1421 return;
1425 static void get_sel_time(IPMIBmcSim *ibs,
1426 uint8_t *cmd, unsigned int cmd_len,
1427 uint8_t *rsp, unsigned int *rsp_len,
1428 unsigned int max_rsp_len)
1430 uint32_t val;
1431 struct ipmi_time now;
1433 ipmi_gettime(&now);
1434 val = now.tv_sec + ibs->sel.time_offset;
1435 IPMI_ADD_RSP_DATA(val & 0xff);
1436 IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
1437 IPMI_ADD_RSP_DATA((val >> 16) & 0xff);
1438 IPMI_ADD_RSP_DATA((val >> 24) & 0xff);
1441 static void set_sel_time(IPMIBmcSim *ibs,
1442 uint8_t *cmd, unsigned int cmd_len,
1443 uint8_t *rsp, unsigned int *rsp_len,
1444 unsigned int max_rsp_len)
1446 uint32_t val;
1447 struct ipmi_time now;
1449 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1450 ipmi_gettime(&now);
1451 ibs->sel.time_offset = now.tv_sec - ((long) val);
1454 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1455 uint8_t *cmd, unsigned int cmd_len,
1456 uint8_t *rsp, unsigned int *rsp_len,
1457 unsigned int max_rsp_len)
1459 IPMISensor *sens;
1461 if ((cmd[2] >= MAX_SENSORS) ||
1462 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1463 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1464 return;
1466 sens = ibs->sensors + cmd[2];
1467 switch ((cmd[3] >> 4) & 0x3) {
1468 case 0: /* Do not change */
1469 break;
1470 case 1: /* Enable bits */
1471 if (cmd_len > 4) {
1472 sens->assert_enable |= cmd[4];
1474 if (cmd_len > 5) {
1475 sens->assert_enable |= cmd[5] << 8;
1477 if (cmd_len > 6) {
1478 sens->deassert_enable |= cmd[6];
1480 if (cmd_len > 7) {
1481 sens->deassert_enable |= cmd[7] << 8;
1483 break;
1484 case 2: /* Disable bits */
1485 if (cmd_len > 4) {
1486 sens->assert_enable &= ~cmd[4];
1488 if (cmd_len > 5) {
1489 sens->assert_enable &= ~(cmd[5] << 8);
1491 if (cmd_len > 6) {
1492 sens->deassert_enable &= ~cmd[6];
1494 if (cmd_len > 7) {
1495 sens->deassert_enable &= ~(cmd[7] << 8);
1497 break;
1498 case 3:
1499 rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1500 return;
1502 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1505 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1506 uint8_t *cmd, unsigned int cmd_len,
1507 uint8_t *rsp, unsigned int *rsp_len,
1508 unsigned int max_rsp_len)
1510 IPMISensor *sens;
1512 if ((cmd[2] >= MAX_SENSORS) ||
1513 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1514 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1515 return;
1517 sens = ibs->sensors + cmd[2];
1518 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1519 IPMI_ADD_RSP_DATA(sens->assert_enable & 0xff);
1520 IPMI_ADD_RSP_DATA((sens->assert_enable >> 8) & 0xff);
1521 IPMI_ADD_RSP_DATA(sens->deassert_enable & 0xff);
1522 IPMI_ADD_RSP_DATA((sens->deassert_enable >> 8) & 0xff);
1525 static void rearm_sensor_evts(IPMIBmcSim *ibs,
1526 uint8_t *cmd, unsigned int cmd_len,
1527 uint8_t *rsp, unsigned int *rsp_len,
1528 unsigned int max_rsp_len)
1530 IPMISensor *sens;
1532 if ((cmd[2] >= MAX_SENSORS) ||
1533 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1534 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1535 return;
1537 sens = ibs->sensors + cmd[2];
1539 if ((cmd[3] & 0x80) == 0) {
1540 /* Just clear everything */
1541 sens->states = 0;
1542 return;
1546 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1547 uint8_t *cmd, unsigned int cmd_len,
1548 uint8_t *rsp, unsigned int *rsp_len,
1549 unsigned int max_rsp_len)
1551 IPMISensor *sens;
1553 if ((cmd[2] >= MAX_SENSORS) ||
1554 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1555 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1556 return;
1558 sens = ibs->sensors + cmd[2];
1559 IPMI_ADD_RSP_DATA(sens->reading);
1560 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1561 IPMI_ADD_RSP_DATA(sens->assert_states & 0xff);
1562 IPMI_ADD_RSP_DATA((sens->assert_states >> 8) & 0xff);
1563 IPMI_ADD_RSP_DATA(sens->deassert_states & 0xff);
1564 IPMI_ADD_RSP_DATA((sens->deassert_states >> 8) & 0xff);
1567 static void get_sensor_reading(IPMIBmcSim *ibs,
1568 uint8_t *cmd, unsigned int cmd_len,
1569 uint8_t *rsp, unsigned int *rsp_len,
1570 unsigned int max_rsp_len)
1572 IPMISensor *sens;
1574 if ((cmd[2] >= MAX_SENSORS) ||
1575 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1576 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1577 return;
1579 sens = ibs->sensors + cmd[2];
1580 IPMI_ADD_RSP_DATA(sens->reading);
1581 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1582 IPMI_ADD_RSP_DATA(sens->states & 0xff);
1583 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1584 IPMI_ADD_RSP_DATA((sens->states >> 8) & 0xff);
1588 static void set_sensor_type(IPMIBmcSim *ibs,
1589 uint8_t *cmd, unsigned int cmd_len,
1590 uint8_t *rsp, unsigned int *rsp_len,
1591 unsigned int max_rsp_len)
1593 IPMISensor *sens;
1596 if ((cmd[2] >= MAX_SENSORS) ||
1597 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1598 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1599 return;
1601 sens = ibs->sensors + cmd[2];
1602 sens->sensor_type = cmd[3];
1603 sens->evt_reading_type_code = cmd[4] & 0x7f;
1606 static void get_sensor_type(IPMIBmcSim *ibs,
1607 uint8_t *cmd, unsigned int cmd_len,
1608 uint8_t *rsp, unsigned int *rsp_len,
1609 unsigned int max_rsp_len)
1611 IPMISensor *sens;
1614 if ((cmd[2] >= MAX_SENSORS) ||
1615 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1616 rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1617 return;
1619 sens = ibs->sensors + cmd[2];
1620 IPMI_ADD_RSP_DATA(sens->sensor_type);
1621 IPMI_ADD_RSP_DATA(sens->evt_reading_type_code);
1625 static const IPMICmdHandler chassis_cmds[] = {
1626 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
1627 [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
1628 [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
1629 [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
1631 static const IPMINetfn chassis_netfn = {
1632 .cmd_nums = ARRAY_SIZE(chassis_cmds),
1633 .cmd_handlers = chassis_cmds
1636 static const IPMICmdHandler sensor_event_cmds[] = {
1637 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
1638 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
1639 [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
1640 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
1641 [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
1642 [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
1643 [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
1645 static const IPMINetfn sensor_event_netfn = {
1646 .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
1647 .cmd_handlers = sensor_event_cmds
1650 static const IPMICmdHandler app_cmds[] = {
1651 [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
1652 [IPMI_CMD_COLD_RESET] = { cold_reset },
1653 [IPMI_CMD_WARM_RESET] = { warm_reset },
1654 [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
1655 [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
1656 [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
1657 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
1658 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
1659 [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
1660 [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
1661 [IPMI_CMD_GET_MSG] = { get_msg },
1662 [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
1663 [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
1664 [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
1665 [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
1666 [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
1668 static const IPMINetfn app_netfn = {
1669 .cmd_nums = ARRAY_SIZE(app_cmds),
1670 .cmd_handlers = app_cmds
1673 static const IPMICmdHandler storage_cmds[] = {
1674 [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
1675 [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
1676 [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
1677 [IPMI_CMD_ADD_SDR] = { add_sdr },
1678 [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
1679 [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
1680 [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
1681 [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
1682 [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
1683 [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
1684 [IPMI_CMD_GET_SEL_TIME] = { get_sel_time, 6 },
1685 [IPMI_CMD_SET_SEL_TIME] = { set_sel_time },
1688 static const IPMINetfn storage_netfn = {
1689 .cmd_nums = ARRAY_SIZE(storage_cmds),
1690 .cmd_handlers = storage_cmds
1693 static void register_cmds(IPMIBmcSim *s)
1695 ipmi_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
1696 ipmi_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
1697 ipmi_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
1698 ipmi_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
1701 static const uint8_t init_sdrs[] = {
1702 /* Watchdog device */
1703 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1704 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1707 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1708 /* End */
1709 0xff, 0xff, 0x00, 0x00, 0x00
1712 static const VMStateDescription vmstate_ipmi_sim = {
1713 .name = TYPE_IPMI_BMC_SIMULATOR,
1714 .version_id = 1,
1715 .minimum_version_id = 1,
1716 .fields = (VMStateField[]) {
1717 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
1718 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
1719 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
1720 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
1721 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
1722 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
1723 VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
1724 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
1725 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
1726 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
1727 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
1728 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
1729 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
1730 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
1731 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
1732 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
1733 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
1734 IPMIBmcSim),
1735 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
1736 VMSTATE_END_OF_LIST()
1740 static void ipmi_sim_init(Object *obj)
1742 IPMIBmc *b = IPMI_BMC(obj);
1743 unsigned int i;
1744 unsigned int recid;
1745 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
1747 qemu_mutex_init(&ibs->lock);
1748 QTAILQ_INIT(&ibs->rcvbufs);
1750 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
1751 ibs->device_id = 0x20;
1752 ibs->ipmi_version = 0x02; /* IPMI 2.0 */
1753 ibs->restart_cause = 0;
1754 for (i = 0; i < 4; i++) {
1755 ibs->sel.last_addition[i] = 0xff;
1756 ibs->sel.last_clear[i] = 0xff;
1757 ibs->sdr.last_addition[i] = 0xff;
1758 ibs->sdr.last_clear[i] = 0xff;
1761 for (i = 0;;) {
1762 struct ipmi_sdr_header *sdrh;
1763 int len;
1764 if ((i + IPMI_SDR_HEADER_SIZE) > sizeof(init_sdrs)) {
1765 error_report("Problem with recid 0x%4.4x", i);
1766 return;
1768 sdrh = (struct ipmi_sdr_header *) &init_sdrs[i];
1769 len = ipmi_sdr_length(sdrh);
1770 recid = ipmi_sdr_recid(sdrh);
1771 if (recid == 0xffff) {
1772 break;
1774 if ((i + len) > sizeof(init_sdrs)) {
1775 error_report("Problem with recid 0x%4.4x", i);
1776 return;
1778 sdr_add_entry(ibs, sdrh, len, NULL);
1779 i += len;
1782 ibs->acpi_power_state[0] = 0;
1783 ibs->acpi_power_state[1] = 0;
1785 if (qemu_uuid_set) {
1786 memcpy(&ibs->uuid, qemu_uuid, 16);
1787 } else {
1788 memset(&ibs->uuid, 0, 16);
1791 ipmi_init_sensors_from_sdrs(ibs);
1792 register_cmds(ibs);
1794 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
1796 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
1799 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
1801 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
1803 bk->handle_command = ipmi_sim_handle_command;
1806 static const TypeInfo ipmi_sim_type = {
1807 .name = TYPE_IPMI_BMC_SIMULATOR,
1808 .parent = TYPE_IPMI_BMC,
1809 .instance_size = sizeof(IPMIBmcSim),
1810 .instance_init = ipmi_sim_init,
1811 .class_init = ipmi_sim_class_init,
1814 static void ipmi_sim_register_types(void)
1816 type_register_static(&ipmi_sim_type);
1819 type_init(ipmi_sim_register_types)