hw/isa/Kconfig: Add missing dependency VIA VT82C686 -> APM
[qemu/ar7.git] / hw / ipmi / ipmi_bmc_sim.c
blob55fb81fa5a9bd8a9b18f2de970678bb28fccd1d8
1 /*
2 * IPMI BMC emulation
4 * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "qemu/osdep.h"
26 #include "sysemu/sysemu.h"
27 #include "qemu/timer.h"
28 #include "hw/ipmi/ipmi.h"
29 #include "qemu/error-report.h"
30 #include "qemu/module.h"
31 #include "hw/loader.h"
32 #include "hw/qdev-properties.h"
33 #include "hw/qdev-properties-system.h"
34 #include "migration/vmstate.h"
36 #define IPMI_NETFN_CHASSIS 0x00
38 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
39 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
40 #define IPMI_CMD_CHASSIS_CONTROL 0x02
41 #define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09
43 #define IPMI_NETFN_SENSOR_EVENT 0x04
45 #define IPMI_CMD_PLATFORM_EVENT_MSG 0x02
46 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
47 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
48 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
49 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
50 #define IPMI_CMD_GET_SENSOR_READING 0x2d
51 #define IPMI_CMD_SET_SENSOR_TYPE 0x2e
52 #define IPMI_CMD_GET_SENSOR_TYPE 0x2f
53 #define IPMI_CMD_SET_SENSOR_READING 0x30
55 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
57 #define IPMI_CMD_GET_DEVICE_ID 0x01
58 #define IPMI_CMD_COLD_RESET 0x02
59 #define IPMI_CMD_WARM_RESET 0x03
60 #define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
61 #define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
62 #define IPMI_CMD_GET_DEVICE_GUID 0x08
63 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
64 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
65 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
66 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
67 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
68 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
69 #define IPMI_CMD_GET_MSG_FLAGS 0x31
70 #define IPMI_CMD_GET_MSG 0x33
71 #define IPMI_CMD_SEND_MSG 0x34
72 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
74 #define IPMI_NETFN_STORAGE 0x0a
76 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
77 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
78 #define IPMI_CMD_RESERVE_SDR_REP 0x22
79 #define IPMI_CMD_GET_SDR 0x23
80 #define IPMI_CMD_ADD_SDR 0x24
81 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
82 #define IPMI_CMD_DELETE_SDR 0x26
83 #define IPMI_CMD_CLEAR_SDR_REP 0x27
84 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
85 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
86 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
87 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
88 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
89 #define IPMI_CMD_GET_FRU_AREA_INFO 0x10
90 #define IPMI_CMD_READ_FRU_DATA 0x11
91 #define IPMI_CMD_WRITE_FRU_DATA 0x12
92 #define IPMI_CMD_GET_SEL_INFO 0x40
93 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
94 #define IPMI_CMD_RESERVE_SEL 0x42
95 #define IPMI_CMD_GET_SEL_ENTRY 0x43
96 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
97 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
98 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
99 #define IPMI_CMD_CLEAR_SEL 0x47
100 #define IPMI_CMD_GET_SEL_TIME 0x48
101 #define IPMI_CMD_SET_SEL_TIME 0x49
104 /* Same as a timespec struct. */
105 struct ipmi_time {
106 long tv_sec;
107 long tv_nsec;
110 #define MAX_SEL_SIZE 128
112 typedef struct IPMISel {
113 uint8_t sel[MAX_SEL_SIZE][16];
114 unsigned int next_free;
115 long time_offset;
116 uint16_t reservation;
117 uint8_t last_addition[4];
118 uint8_t last_clear[4];
119 uint8_t overflow;
120 } IPMISel;
122 #define MAX_SDR_SIZE 16384
124 typedef struct IPMISdr {
125 uint8_t sdr[MAX_SDR_SIZE];
126 unsigned int next_free;
127 uint16_t next_rec_id;
128 uint16_t reservation;
129 uint8_t last_addition[4];
130 uint8_t last_clear[4];
131 uint8_t overflow;
132 } IPMISdr;
134 typedef struct IPMIFru {
135 char *filename;
136 unsigned int nentries;
137 uint16_t areasize;
138 uint8_t *data;
139 } IPMIFru;
141 typedef struct IPMISensor {
142 uint8_t status;
143 uint8_t reading;
144 uint16_t states_suppt;
145 uint16_t assert_suppt;
146 uint16_t deassert_suppt;
147 uint16_t states;
148 uint16_t assert_states;
149 uint16_t deassert_states;
150 uint16_t assert_enable;
151 uint16_t deassert_enable;
152 uint8_t sensor_type;
153 uint8_t evt_reading_type_code;
154 } IPMISensor;
155 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
156 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
157 !!(v))
158 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
159 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
160 ((!!(v)) << 6))
161 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
162 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
163 ((!!(v)) << 7))
164 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
165 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
166 (v & 0xc0))
167 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
169 #define MAX_SENSORS 20
170 #define IPMI_WATCHDOG_SENSOR 0
172 #define MAX_NETFNS 64
174 typedef struct IPMIRcvBufEntry {
175 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
176 uint8_t len;
177 uint8_t buf[MAX_IPMI_MSG_SIZE];
178 } IPMIRcvBufEntry;
180 struct IPMIBmcSim {
181 IPMIBmc parent;
183 QEMUTimer *timer;
185 uint8_t bmc_global_enables;
186 uint8_t msg_flags;
188 bool watchdog_initialized;
189 uint8_t watchdog_use;
190 uint8_t watchdog_action;
191 uint8_t watchdog_pretimeout; /* In seconds */
192 bool watchdog_expired;
193 uint16_t watchdog_timeout; /* in 100's of milliseconds */
195 bool watchdog_running;
196 bool watchdog_preaction_ran;
197 int64_t watchdog_expiry;
199 uint8_t device_id;
200 uint8_t ipmi_version;
201 uint8_t device_rev;
202 uint8_t fwrev1;
203 uint8_t fwrev2;
204 uint32_t mfg_id;
205 uint16_t product_id;
207 uint8_t restart_cause;
209 uint8_t acpi_power_state[2];
210 QemuUUID uuid;
212 IPMISel sel;
213 IPMISdr sdr;
214 IPMIFru fru;
215 IPMISensor sensors[MAX_SENSORS];
216 char *sdr_filename;
218 /* Odd netfns are for responses, so we only need the even ones. */
219 const IPMINetfn *netfns[MAX_NETFNS / 2];
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
266 #define RSP_BUFFER_INITIALIZER { }
268 static inline void rsp_buffer_pushmore(RspBuffer *rsp, uint8_t *bytes,
269 unsigned int n)
271 if (rsp->len + n >= sizeof(rsp->buffer)) {
272 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
273 return;
276 memcpy(&rsp->buffer[rsp->len], bytes, n);
277 rsp->len += n;
280 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
282 static void ipmi_gettime(struct ipmi_time *time)
284 int64_t stime;
286 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
287 time->tv_sec = stime / 1000000000LL;
288 time->tv_nsec = stime % 1000000000LL;
291 static int64_t ipmi_getmonotime(void)
293 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
296 static void ipmi_timeout(void *opaque)
298 IPMIBmcSim *ibs = opaque;
300 ipmi_sim_handle_timeout(ibs);
303 static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
305 unsigned int val;
306 struct ipmi_time now;
308 ipmi_gettime(&now);
309 val = now.tv_sec + ibs->sel.time_offset;
310 ts[0] = val & 0xff;
311 ts[1] = (val >> 8) & 0xff;
312 ts[2] = (val >> 16) & 0xff;
313 ts[3] = (val >> 24) & 0xff;
316 static void sdr_inc_reservation(IPMISdr *sdr)
318 sdr->reservation++;
319 if (sdr->reservation == 0) {
320 sdr->reservation = 1;
324 static int sdr_add_entry(IPMIBmcSim *ibs,
325 const struct ipmi_sdr_header *sdrh_entry,
326 unsigned int len, uint16_t *recid)
328 struct ipmi_sdr_header *sdrh =
329 (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
331 if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
332 return 1;
335 if (ipmi_sdr_length(sdrh_entry) != len) {
336 return 1;
339 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
340 ibs->sdr.overflow = 1;
341 return 1;
344 memcpy(sdrh, sdrh_entry, len);
345 sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff;
346 sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
347 sdrh->sdr_version = 0x51; /* Conform to IPMI 1.5 spec */
349 if (recid) {
350 *recid = ibs->sdr.next_rec_id;
352 ibs->sdr.next_rec_id++;
353 set_timestamp(ibs, ibs->sdr.last_addition);
354 ibs->sdr.next_free += len;
355 sdr_inc_reservation(&ibs->sdr);
356 return 0;
359 static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
360 unsigned int *retpos, uint16_t *nextrec)
362 unsigned int pos = *retpos;
364 while (pos < sdr->next_free) {
365 struct ipmi_sdr_header *sdrh =
366 (struct ipmi_sdr_header *) &sdr->sdr[pos];
367 uint16_t trec = ipmi_sdr_recid(sdrh);
368 unsigned int nextpos = pos + ipmi_sdr_length(sdrh);
370 if (trec == recid) {
371 if (nextrec) {
372 if (nextpos >= sdr->next_free) {
373 *nextrec = 0xffff;
374 } else {
375 *nextrec = (sdr->sdr[nextpos] |
376 (sdr->sdr[nextpos + 1] << 8));
379 *retpos = pos;
380 return 0;
382 pos = nextpos;
384 return 1;
387 int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
388 const struct ipmi_sdr_compact **sdr, uint16_t *nextrec)
391 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
392 unsigned int pos;
394 pos = 0;
395 if (sdr_find_entry(&ibs->sdr, recid, &pos, nextrec)) {
396 return -1;
399 *sdr = (const struct ipmi_sdr_compact *) &ibs->sdr.sdr[pos];
400 return 0;
403 static void sel_inc_reservation(IPMISel *sel)
405 sel->reservation++;
406 if (sel->reservation == 0) {
407 sel->reservation = 1;
411 /* Returns 1 if the SEL is full and can't hold the event. */
412 static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
414 uint8_t ts[4];
416 event[0] = 0xff;
417 event[1] = 0xff;
418 set_timestamp(ibs, ts);
419 if (event[2] < 0xe0) { /* Don't set timestamps for type 0xe0-0xff. */
420 memcpy(event + 3, ts, 4);
422 if (ibs->sel.next_free == MAX_SEL_SIZE) {
423 ibs->sel.overflow = 1;
424 return 1;
426 event[0] = ibs->sel.next_free & 0xff;
427 event[1] = (ibs->sel.next_free >> 8) & 0xff;
428 memcpy(ibs->sel.last_addition, ts, 4);
429 memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
430 ibs->sel.next_free++;
431 sel_inc_reservation(&ibs->sel);
432 return 0;
435 static int attn_set(IPMIBmcSim *ibs)
437 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
438 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
439 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
442 static int attn_irq_enabled(IPMIBmcSim *ibs)
444 return (IPMI_BMC_MSG_INTS_ON(ibs) &&
445 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs) ||
446 IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs)))
447 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
448 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
451 void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log)
453 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
454 IPMIInterface *s = ibs->parent.intf;
455 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
457 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
458 return;
461 if (log && 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 goto out;
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));
472 out:
473 return;
475 static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
476 uint8_t evd1, uint8_t evd2, uint8_t evd3)
478 IPMIInterface *s = ibs->parent.intf;
479 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
480 uint8_t evt[16];
481 IPMISensor *sens = ibs->sensors + sens_num;
483 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
484 return;
486 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
487 return;
490 evt[2] = 0x2; /* System event record */
491 evt[7] = ibs->parent.slave_addr;
492 evt[8] = 0;
493 evt[9] = 0x04; /* Format version */
494 evt[10] = sens->sensor_type;
495 evt[11] = sens_num;
496 evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
497 evt[13] = evd1;
498 evt[14] = evd2;
499 evt[15] = evd3;
501 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
502 sel_add_event(ibs, evt);
505 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
506 return;
509 memcpy(ibs->evtbuf, evt, 16);
510 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
511 k->set_atn(s, 1, attn_irq_enabled(ibs));
514 static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
515 unsigned int bit, unsigned int val,
516 uint8_t evd1, uint8_t evd2, uint8_t evd3)
518 IPMISensor *sens;
519 uint16_t mask;
521 if (sensor >= MAX_SENSORS) {
522 return;
524 if (bit >= 16) {
525 return;
528 mask = (1 << bit);
529 sens = ibs->sensors + sensor;
530 if (val) {
531 sens->states |= mask & sens->states_suppt;
532 if (sens->assert_states & mask) {
533 return; /* Already asserted */
535 sens->assert_states |= mask & sens->assert_suppt;
536 if (sens->assert_enable & mask & sens->assert_states) {
537 /* Send an event on assert */
538 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
540 } else {
541 sens->states &= ~(mask & sens->states_suppt);
542 if (sens->deassert_states & mask) {
543 return; /* Already deasserted */
545 sens->deassert_states |= mask & sens->deassert_suppt;
546 if (sens->deassert_enable & mask & sens->deassert_states) {
547 /* Send an event on deassert */
548 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
553 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
555 unsigned int i, pos;
556 IPMISensor *sens;
558 for (i = 0; i < MAX_SENSORS; i++) {
559 memset(s->sensors + i, 0, sizeof(*sens));
562 pos = 0;
563 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
564 struct ipmi_sdr_compact *sdr =
565 (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
566 unsigned int len = sdr->header.rec_length;
568 if (len < 20) {
569 continue;
571 if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
572 continue; /* Not a sensor SDR we set from */
575 if (sdr->sensor_owner_number >= MAX_SENSORS) {
576 continue;
578 sens = s->sensors + sdr->sensor_owner_number;
580 IPMI_SENSOR_SET_PRESENT(sens, 1);
581 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
582 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
583 sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
584 sens->deassert_suppt =
585 sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
586 sens->states_suppt =
587 sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
588 sens->sensor_type = sdr->sensor_type;
589 sens->evt_reading_type_code = sdr->reading_type & 0x7f;
591 /* Enable all the events that are supported. */
592 sens->assert_enable = sens->assert_suppt;
593 sens->deassert_enable = sens->deassert_suppt;
597 int ipmi_sim_register_netfn(IPMIBmcSim *s, unsigned int netfn,
598 const IPMINetfn *netfnd)
600 if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
601 return -1;
603 s->netfns[netfn / 2] = netfnd;
604 return 0;
607 static const IPMICmdHandler *ipmi_get_handler(IPMIBmcSim *ibs,
608 unsigned int netfn,
609 unsigned int cmd)
611 const IPMICmdHandler *hdl;
613 if (netfn & 1 || netfn >= MAX_NETFNS || !ibs->netfns[netfn / 2]) {
614 return NULL;
617 if (cmd >= ibs->netfns[netfn / 2]->cmd_nums) {
618 return NULL;
621 hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd];
622 if (!hdl->cmd_handler) {
623 return NULL;
626 return hdl;
629 static void next_timeout(IPMIBmcSim *ibs)
631 int64_t next;
632 if (ibs->watchdog_running) {
633 next = ibs->watchdog_expiry;
634 } else {
635 /* Wait a minute */
636 next = ipmi_getmonotime() + 60 * 1000000000LL;
638 timer_mod_ns(ibs->timer, next);
641 static void ipmi_sim_handle_command(IPMIBmc *b,
642 uint8_t *cmd, unsigned int cmd_len,
643 unsigned int max_cmd_len,
644 uint8_t msg_id)
646 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
647 IPMIInterface *s = ibs->parent.intf;
648 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
649 const IPMICmdHandler *hdl;
650 RspBuffer rsp = RSP_BUFFER_INITIALIZER;
652 /* Set up the response, set the low bit of NETFN. */
653 /* Note that max_rsp_len must be at least 3 */
654 if (sizeof(rsp.buffer) < 3) {
655 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
656 goto out;
659 rsp_buffer_push(&rsp, cmd[0] | 0x04);
660 rsp_buffer_push(&rsp, cmd[1]);
661 rsp_buffer_push(&rsp, 0); /* Assume success */
663 /* If it's too short or it was truncated, return an error. */
664 if (cmd_len < 2) {
665 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
666 goto out;
668 if (cmd_len > max_cmd_len) {
669 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
670 goto out;
673 if ((cmd[0] & 0x03) != 0) {
674 /* Only have stuff on LUN 0 */
675 rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN);
676 goto out;
679 hdl = ipmi_get_handler(ibs, cmd[0] >> 2, cmd[1]);
680 if (!hdl) {
681 rsp_buffer_set_error(&rsp, IPMI_CC_INVALID_CMD);
682 goto out;
685 if (cmd_len < hdl->cmd_len_min) {
686 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
687 goto out;
690 hdl->cmd_handler(ibs, cmd, cmd_len, &rsp);
692 out:
693 k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
695 next_timeout(ibs);
698 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
700 IPMIInterface *s = ibs->parent.intf;
701 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
703 if (!ibs->watchdog_running) {
704 goto out;
707 if (!ibs->watchdog_preaction_ran) {
708 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
709 case IPMI_BMC_WATCHDOG_PRE_NMI:
710 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
711 k->do_hw_op(s, IPMI_SEND_NMI, 0);
712 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
713 0xc8, (2 << 4) | 0xf, 0xff);
714 break;
716 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
717 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
718 k->set_atn(s, 1, attn_irq_enabled(ibs));
719 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
720 0xc8, (3 << 4) | 0xf, 0xff);
721 break;
723 default:
724 goto do_full_expiry;
727 ibs->watchdog_preaction_ran = 1;
728 /* Issued the pretimeout, do the rest of the timeout now. */
729 ibs->watchdog_expiry = ipmi_getmonotime();
730 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
731 goto out;
734 do_full_expiry:
735 ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
736 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
737 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
738 case IPMI_BMC_WATCHDOG_ACTION_NONE:
739 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
740 0xc0, ibs->watchdog_use & 0xf, 0xff);
741 break;
743 case IPMI_BMC_WATCHDOG_ACTION_RESET:
744 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
745 0xc1, ibs->watchdog_use & 0xf, 0xff);
746 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
747 break;
749 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
750 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
751 0xc2, ibs->watchdog_use & 0xf, 0xff);
752 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
753 break;
755 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
756 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
757 0xc3, ibs->watchdog_use & 0xf, 0xff);
758 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
759 break;
762 out:
763 next_timeout(ibs);
766 static void chassis_capabilities(IPMIBmcSim *ibs,
767 uint8_t *cmd, unsigned int cmd_len,
768 RspBuffer *rsp)
770 rsp_buffer_push(rsp, 0);
771 rsp_buffer_push(rsp, ibs->parent.slave_addr);
772 rsp_buffer_push(rsp, ibs->parent.slave_addr);
773 rsp_buffer_push(rsp, ibs->parent.slave_addr);
774 rsp_buffer_push(rsp, ibs->parent.slave_addr);
777 static void chassis_status(IPMIBmcSim *ibs,
778 uint8_t *cmd, unsigned int cmd_len,
779 RspBuffer *rsp)
781 rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */
782 rsp_buffer_push(rsp, 0);
783 rsp_buffer_push(rsp, 0);
784 rsp_buffer_push(rsp, 0);
787 static void chassis_control(IPMIBmcSim *ibs,
788 uint8_t *cmd, unsigned int cmd_len,
789 RspBuffer *rsp)
791 IPMIInterface *s = ibs->parent.intf;
792 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
794 switch (cmd[2] & 0xf) {
795 case 0: /* power down */
796 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0));
797 break;
798 case 1: /* power up */
799 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0));
800 break;
801 case 2: /* power cycle */
802 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0));
803 break;
804 case 3: /* hard reset */
805 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0));
806 break;
807 case 4: /* pulse diagnostic interrupt */
808 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0));
809 break;
810 case 5: /* soft shutdown via ACPI by overtemp emulation */
811 rsp_buffer_set_error(rsp, k->do_hw_op(s,
812 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0));
813 break;
814 default:
815 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
816 return;
820 static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
821 uint8_t *cmd, unsigned int cmd_len,
822 RspBuffer *rsp)
825 rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */
826 rsp_buffer_push(rsp, 0); /* Channel 0 */
829 static void get_device_id(IPMIBmcSim *ibs,
830 uint8_t *cmd, unsigned int cmd_len,
831 RspBuffer *rsp)
833 rsp_buffer_push(rsp, ibs->device_id);
834 rsp_buffer_push(rsp, ibs->device_rev & 0xf);
835 rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
836 rsp_buffer_push(rsp, ibs->fwrev2);
837 rsp_buffer_push(rsp, ibs->ipmi_version);
838 rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */
839 rsp_buffer_push(rsp, ibs->mfg_id & 0xff);
840 rsp_buffer_push(rsp, (ibs->mfg_id >> 8) & 0xff);
841 rsp_buffer_push(rsp, (ibs->mfg_id >> 16) & 0xff);
842 rsp_buffer_push(rsp, ibs->product_id & 0xff);
843 rsp_buffer_push(rsp, (ibs->product_id >> 8) & 0xff);
846 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
848 IPMIInterface *s = ibs->parent.intf;
849 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
850 bool irqs_on;
852 ibs->bmc_global_enables = val;
854 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
855 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
857 k->set_irq_enable(s, irqs_on);
860 static void cold_reset(IPMIBmcSim *ibs,
861 uint8_t *cmd, unsigned int cmd_len,
862 RspBuffer *rsp)
864 IPMIInterface *s = ibs->parent.intf;
865 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
867 /* Disable all interrupts */
868 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
870 if (k->reset) {
871 k->reset(s, true);
875 static void warm_reset(IPMIBmcSim *ibs,
876 uint8_t *cmd, unsigned int cmd_len,
877 RspBuffer *rsp)
879 IPMIInterface *s = ibs->parent.intf;
880 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
882 if (k->reset) {
883 k->reset(s, false);
886 static void set_acpi_power_state(IPMIBmcSim *ibs,
887 uint8_t *cmd, unsigned int cmd_len,
888 RspBuffer *rsp)
890 ibs->acpi_power_state[0] = cmd[2];
891 ibs->acpi_power_state[1] = cmd[3];
894 static void get_acpi_power_state(IPMIBmcSim *ibs,
895 uint8_t *cmd, unsigned int cmd_len,
896 RspBuffer *rsp)
898 rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
899 rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
902 static void get_device_guid(IPMIBmcSim *ibs,
903 uint8_t *cmd, unsigned int cmd_len,
904 RspBuffer *rsp)
906 unsigned int i;
908 /* An uninitialized uuid is all zeros, use that to know if it is set. */
909 for (i = 0; i < 16; i++) {
910 if (ibs->uuid.data[i]) {
911 goto uuid_set;
914 /* No uuid is set, return an error. */
915 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_CMD);
916 return;
918 uuid_set:
919 for (i = 0; i < 16; i++) {
920 rsp_buffer_push(rsp, ibs->uuid.data[i]);
924 static void set_bmc_global_enables(IPMIBmcSim *ibs,
925 uint8_t *cmd, unsigned int cmd_len,
926 RspBuffer *rsp)
928 set_global_enables(ibs, cmd[2]);
931 static void get_bmc_global_enables(IPMIBmcSim *ibs,
932 uint8_t *cmd, unsigned int cmd_len,
933 RspBuffer *rsp)
935 rsp_buffer_push(rsp, ibs->bmc_global_enables);
938 static void clr_msg_flags(IPMIBmcSim *ibs,
939 uint8_t *cmd, unsigned int cmd_len,
940 RspBuffer *rsp)
942 IPMIInterface *s = ibs->parent.intf;
943 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
945 ibs->msg_flags &= ~cmd[2];
946 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
949 static void get_msg_flags(IPMIBmcSim *ibs,
950 uint8_t *cmd, unsigned int cmd_len,
951 RspBuffer *rsp)
953 rsp_buffer_push(rsp, ibs->msg_flags);
956 static void read_evt_msg_buf(IPMIBmcSim *ibs,
957 uint8_t *cmd, unsigned int cmd_len,
958 RspBuffer *rsp)
960 IPMIInterface *s = ibs->parent.intf;
961 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
962 unsigned int i;
964 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
965 rsp_buffer_set_error(rsp, 0x80);
966 return;
968 for (i = 0; i < 16; i++) {
969 rsp_buffer_push(rsp, ibs->evtbuf[i]);
971 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
972 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
975 static void get_msg(IPMIBmcSim *ibs,
976 uint8_t *cmd, unsigned int cmd_len,
977 RspBuffer *rsp)
979 IPMIRcvBufEntry *msg;
981 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
982 rsp_buffer_set_error(rsp, 0x80); /* Queue empty */
983 goto out;
985 rsp_buffer_push(rsp, 0); /* Channel 0 */
986 msg = QTAILQ_FIRST(&ibs->rcvbufs);
987 rsp_buffer_pushmore(rsp, msg->buf, msg->len);
988 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
989 g_free(msg);
991 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
992 IPMIInterface *s = ibs->parent.intf;
993 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
995 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
996 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
999 out:
1000 return;
1003 static unsigned char
1004 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
1006 for (; size > 0; size--, data++) {
1007 csum += *data;
1010 return -csum;
1013 static void send_msg(IPMIBmcSim *ibs,
1014 uint8_t *cmd, unsigned int cmd_len,
1015 RspBuffer *rsp)
1017 IPMIInterface *s = ibs->parent.intf;
1018 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1019 IPMIRcvBufEntry *msg;
1020 uint8_t *buf;
1021 uint8_t netfn, rqLun, rsLun, rqSeq;
1023 if (cmd[2] != 0) {
1024 /* We only handle channel 0 with no options */
1025 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1026 return;
1029 if (cmd_len < 10) {
1030 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
1031 return;
1034 if (cmd[3] != 0x40) {
1035 /* We only emulate a MC at address 0x40. */
1036 rsp_buffer_set_error(rsp, 0x83); /* NAK on write */
1037 return;
1040 cmd += 3; /* Skip the header. */
1041 cmd_len -= 3;
1044 * At this point we "send" the message successfully. Any error will
1045 * be returned in the response.
1047 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
1048 cmd[3] != 0x20) { /* Improper response address */
1049 return; /* No response */
1052 netfn = cmd[1] >> 2;
1053 rqLun = cmd[4] & 0x3;
1054 rsLun = cmd[1] & 0x3;
1055 rqSeq = cmd[4] >> 2;
1057 if (rqLun != 2) {
1058 /* We only support LUN 2 coming back to us. */
1059 return;
1062 msg = g_malloc(sizeof(*msg));
1063 msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
1064 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
1065 msg->buf[2] = cmd[0]; /* rsSA */
1066 msg->buf[3] = (rqSeq << 2) | rsLun;
1067 msg->buf[4] = cmd[5]; /* Cmd */
1068 msg->buf[5] = 0; /* Completion Code */
1069 msg->len = 6;
1071 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
1072 /* Not a command we handle. */
1073 msg->buf[5] = IPMI_CC_INVALID_CMD;
1074 goto end_msg;
1077 buf = msg->buf + msg->len; /* After the CC */
1078 buf[0] = 0;
1079 buf[1] = 0;
1080 buf[2] = 0;
1081 buf[3] = 0;
1082 buf[4] = 0x51;
1083 buf[5] = 0;
1084 buf[6] = 0;
1085 buf[7] = 0;
1086 buf[8] = 0;
1087 buf[9] = 0;
1088 buf[10] = 0;
1089 msg->len += 11;
1091 end_msg:
1092 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1093 msg->len++;
1094 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1095 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1096 k->set_atn(s, 1, attn_irq_enabled(ibs));
1099 static void do_watchdog_reset(IPMIBmcSim *ibs)
1101 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1102 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1103 ibs->watchdog_running = 0;
1104 return;
1106 ibs->watchdog_preaction_ran = 0;
1109 /* Timeout is in tenths of a second, offset is in seconds */
1110 ibs->watchdog_expiry = ipmi_getmonotime();
1111 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1112 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1113 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1115 ibs->watchdog_running = 1;
1118 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1119 uint8_t *cmd, unsigned int cmd_len,
1120 RspBuffer *rsp)
1122 if (!ibs->watchdog_initialized) {
1123 rsp_buffer_set_error(rsp, 0x80);
1124 return;
1126 do_watchdog_reset(ibs);
1129 static void set_watchdog_timer(IPMIBmcSim *ibs,
1130 uint8_t *cmd, unsigned int cmd_len,
1131 RspBuffer *rsp)
1133 IPMIInterface *s = ibs->parent.intf;
1134 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1135 unsigned int val;
1137 val = cmd[2] & 0x7; /* Validate use */
1138 if (val == 0 || val > 5) {
1139 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1140 return;
1142 val = cmd[3] & 0x7; /* Validate action */
1143 switch (val) {
1144 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1145 break;
1147 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1148 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1));
1149 break;
1151 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1152 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1));
1153 break;
1155 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1156 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1));
1157 break;
1159 default:
1160 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1162 if (rsp->buffer[2]) {
1163 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1164 return;
1167 val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1168 switch (val) {
1169 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1170 case IPMI_BMC_WATCHDOG_PRE_NONE:
1171 break;
1173 case IPMI_BMC_WATCHDOG_PRE_NMI:
1174 if (k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1175 /* NMI not supported. */
1176 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1177 return;
1179 break;
1181 default:
1182 /* We don't support PRE_SMI */
1183 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1184 return;
1187 ibs->watchdog_initialized = 1;
1188 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1189 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1190 ibs->watchdog_pretimeout = cmd[4];
1191 ibs->watchdog_expired &= ~cmd[5];
1192 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1193 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1194 do_watchdog_reset(ibs);
1195 } else {
1196 ibs->watchdog_running = 0;
1200 static void get_watchdog_timer(IPMIBmcSim *ibs,
1201 uint8_t *cmd, unsigned int cmd_len,
1202 RspBuffer *rsp)
1204 rsp_buffer_push(rsp, ibs->watchdog_use);
1205 rsp_buffer_push(rsp, ibs->watchdog_action);
1206 rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
1207 rsp_buffer_push(rsp, ibs->watchdog_expired);
1208 rsp_buffer_push(rsp, ibs->watchdog_timeout & 0xff);
1209 rsp_buffer_push(rsp, (ibs->watchdog_timeout >> 8) & 0xff);
1210 if (ibs->watchdog_running) {
1211 long timeout;
1212 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1213 / 100000000);
1214 rsp_buffer_push(rsp, timeout & 0xff);
1215 rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
1216 } else {
1217 rsp_buffer_push(rsp, 0);
1218 rsp_buffer_push(rsp, 0);
1222 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1223 uint8_t *cmd, unsigned int cmd_len,
1224 RspBuffer *rsp)
1226 unsigned int i;
1228 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */
1229 rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
1230 rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
1231 rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1232 rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1233 for (i = 0; i < 4; i++) {
1234 rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
1236 for (i = 0; i < 4; i++) {
1237 rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
1239 /* Only modal support, reserve supported */
1240 rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
1243 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1244 uint8_t *cmd, unsigned int cmd_len,
1245 RspBuffer *rsp)
1247 rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
1248 rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
1251 static void get_sdr(IPMIBmcSim *ibs,
1252 uint8_t *cmd, unsigned int cmd_len,
1253 RspBuffer *rsp)
1255 unsigned int pos;
1256 uint16_t nextrec;
1257 struct ipmi_sdr_header *sdrh;
1259 if (cmd[6]) {
1260 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1261 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1262 return;
1266 pos = 0;
1267 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1268 &pos, &nextrec)) {
1269 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1270 return;
1273 sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1275 if (cmd[6] > ipmi_sdr_length(sdrh)) {
1276 rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE);
1277 return;
1280 rsp_buffer_push(rsp, nextrec & 0xff);
1281 rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
1283 if (cmd[7] == 0xff) {
1284 cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1287 if ((cmd[7] + rsp->len) > sizeof(rsp->buffer)) {
1288 rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES);
1289 return;
1292 rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1295 static void add_sdr(IPMIBmcSim *ibs,
1296 uint8_t *cmd, unsigned int cmd_len,
1297 RspBuffer *rsp)
1299 uint16_t recid;
1300 struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1302 if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1303 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1304 return;
1306 rsp_buffer_push(rsp, recid & 0xff);
1307 rsp_buffer_push(rsp, (recid >> 8) & 0xff);
1310 static void clear_sdr_rep(IPMIBmcSim *ibs,
1311 uint8_t *cmd, unsigned int cmd_len,
1312 RspBuffer *rsp)
1314 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1315 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1316 return;
1319 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1320 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1321 return;
1323 if (cmd[7] == 0xaa) {
1324 ibs->sdr.next_free = 0;
1325 ibs->sdr.overflow = 0;
1326 set_timestamp(ibs, ibs->sdr.last_clear);
1327 rsp_buffer_push(rsp, 1); /* Erasure complete */
1328 sdr_inc_reservation(&ibs->sdr);
1329 } else if (cmd[7] == 0) {
1330 rsp_buffer_push(rsp, 1); /* Erasure complete */
1331 } else {
1332 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1333 return;
1337 static void get_sel_info(IPMIBmcSim *ibs,
1338 uint8_t *cmd, unsigned int cmd_len,
1339 RspBuffer *rsp)
1341 unsigned int i, val;
1343 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */
1344 rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
1345 rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
1346 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1347 rsp_buffer_push(rsp, val & 0xff);
1348 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1349 for (i = 0; i < 4; i++) {
1350 rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
1352 for (i = 0; i < 4; i++) {
1353 rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
1355 /* Only support Reserve SEL */
1356 rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
1359 static void get_fru_area_info(IPMIBmcSim *ibs,
1360 uint8_t *cmd, unsigned int cmd_len,
1361 RspBuffer *rsp)
1363 uint8_t fruid;
1364 uint16_t fru_entry_size;
1366 fruid = cmd[2];
1368 if (fruid >= ibs->fru.nentries) {
1369 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1370 return;
1373 fru_entry_size = ibs->fru.areasize;
1375 rsp_buffer_push(rsp, fru_entry_size & 0xff);
1376 rsp_buffer_push(rsp, fru_entry_size >> 8 & 0xff);
1377 rsp_buffer_push(rsp, 0x0);
1380 static void read_fru_data(IPMIBmcSim *ibs,
1381 uint8_t *cmd, unsigned int cmd_len,
1382 RspBuffer *rsp)
1384 uint8_t fruid;
1385 uint16_t offset;
1386 int i;
1387 uint8_t *fru_entry;
1388 unsigned int count;
1390 fruid = cmd[2];
1391 offset = (cmd[3] | cmd[4] << 8);
1393 if (fruid >= ibs->fru.nentries) {
1394 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1395 return;
1398 if (offset >= ibs->fru.areasize - 1) {
1399 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1400 return;
1403 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1405 count = MIN(cmd[5], ibs->fru.areasize - offset);
1407 rsp_buffer_push(rsp, count & 0xff);
1408 for (i = 0; i < count; i++) {
1409 rsp_buffer_push(rsp, fru_entry[offset + i]);
1413 static void write_fru_data(IPMIBmcSim *ibs,
1414 uint8_t *cmd, unsigned int cmd_len,
1415 RspBuffer *rsp)
1417 uint8_t fruid;
1418 uint16_t offset;
1419 uint8_t *fru_entry;
1420 unsigned int count;
1422 fruid = cmd[2];
1423 offset = (cmd[3] | cmd[4] << 8);
1425 if (fruid >= ibs->fru.nentries) {
1426 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1427 return;
1430 if (offset >= ibs->fru.areasize - 1) {
1431 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1432 return;
1435 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1437 count = MIN(cmd_len - 5, ibs->fru.areasize - offset);
1439 memcpy(fru_entry + offset, cmd + 5, count);
1441 rsp_buffer_push(rsp, count & 0xff);
1444 static void reserve_sel(IPMIBmcSim *ibs,
1445 uint8_t *cmd, unsigned int cmd_len,
1446 RspBuffer *rsp)
1448 rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
1449 rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
1452 static void get_sel_entry(IPMIBmcSim *ibs,
1453 uint8_t *cmd, unsigned int cmd_len,
1454 RspBuffer *rsp)
1456 unsigned int val;
1458 if (cmd[6]) {
1459 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1460 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1461 return;
1464 if (ibs->sel.next_free == 0) {
1465 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1466 return;
1468 if (cmd[6] > 15) {
1469 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1470 return;
1472 if (cmd[7] == 0xff) {
1473 cmd[7] = 16;
1474 } else if ((cmd[7] + cmd[6]) > 16) {
1475 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1476 return;
1477 } else {
1478 cmd[7] += cmd[6];
1481 val = cmd[4] | (cmd[5] << 8);
1482 if (val == 0xffff) {
1483 val = ibs->sel.next_free - 1;
1484 } else if (val >= ibs->sel.next_free) {
1485 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1486 return;
1488 if ((val + 1) == ibs->sel.next_free) {
1489 rsp_buffer_push(rsp, 0xff);
1490 rsp_buffer_push(rsp, 0xff);
1491 } else {
1492 rsp_buffer_push(rsp, (val + 1) & 0xff);
1493 rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
1495 for (; cmd[6] < cmd[7]; cmd[6]++) {
1496 rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
1500 static void add_sel_entry(IPMIBmcSim *ibs,
1501 uint8_t *cmd, unsigned int cmd_len,
1502 RspBuffer *rsp)
1504 if (sel_add_event(ibs, cmd + 2)) {
1505 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1506 return;
1508 /* sel_add_event fills in the record number. */
1509 rsp_buffer_push(rsp, cmd[2]);
1510 rsp_buffer_push(rsp, cmd[3]);
1513 static void clear_sel(IPMIBmcSim *ibs,
1514 uint8_t *cmd, unsigned int cmd_len,
1515 RspBuffer *rsp)
1517 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1518 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1519 return;
1522 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1523 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1524 return;
1526 if (cmd[7] == 0xaa) {
1527 ibs->sel.next_free = 0;
1528 ibs->sel.overflow = 0;
1529 set_timestamp(ibs, ibs->sdr.last_clear);
1530 rsp_buffer_push(rsp, 1); /* Erasure complete */
1531 sel_inc_reservation(&ibs->sel);
1532 } else if (cmd[7] == 0) {
1533 rsp_buffer_push(rsp, 1); /* Erasure complete */
1534 } else {
1535 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1536 return;
1540 static void get_sel_time(IPMIBmcSim *ibs,
1541 uint8_t *cmd, unsigned int cmd_len,
1542 RspBuffer *rsp)
1544 uint32_t val;
1545 struct ipmi_time now;
1547 ipmi_gettime(&now);
1548 val = now.tv_sec + ibs->sel.time_offset;
1549 rsp_buffer_push(rsp, val & 0xff);
1550 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1551 rsp_buffer_push(rsp, (val >> 16) & 0xff);
1552 rsp_buffer_push(rsp, (val >> 24) & 0xff);
1555 static void set_sel_time(IPMIBmcSim *ibs,
1556 uint8_t *cmd, unsigned int cmd_len,
1557 RspBuffer *rsp)
1559 uint32_t val;
1560 struct ipmi_time now;
1562 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1563 ipmi_gettime(&now);
1564 ibs->sel.time_offset = now.tv_sec - ((long) val);
1567 static void platform_event_msg(IPMIBmcSim *ibs,
1568 uint8_t *cmd, unsigned int cmd_len,
1569 RspBuffer *rsp)
1571 uint8_t event[16];
1573 event[2] = 2; /* System event record */
1574 event[7] = cmd[2]; /* Generator ID */
1575 event[8] = 0;
1576 event[9] = cmd[3]; /* EvMRev */
1577 event[10] = cmd[4]; /* Sensor type */
1578 event[11] = cmd[5]; /* Sensor number */
1579 event[12] = cmd[6]; /* Event dir / Event type */
1580 event[13] = cmd[7]; /* Event data 1 */
1581 event[14] = cmd[8]; /* Event data 2 */
1582 event[15] = cmd[9]; /* Event data 3 */
1584 if (sel_add_event(ibs, event)) {
1585 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1589 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1590 uint8_t *cmd, unsigned int cmd_len,
1591 RspBuffer *rsp)
1593 IPMISensor *sens;
1595 if ((cmd[2] >= MAX_SENSORS) ||
1596 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1597 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1598 return;
1600 sens = ibs->sensors + cmd[2];
1601 switch ((cmd[3] >> 4) & 0x3) {
1602 case 0: /* Do not change */
1603 break;
1604 case 1: /* Enable bits */
1605 if (cmd_len > 4) {
1606 sens->assert_enable |= cmd[4];
1608 if (cmd_len > 5) {
1609 sens->assert_enable |= cmd[5] << 8;
1611 if (cmd_len > 6) {
1612 sens->deassert_enable |= cmd[6];
1614 if (cmd_len > 7) {
1615 sens->deassert_enable |= cmd[7] << 8;
1617 break;
1618 case 2: /* Disable bits */
1619 if (cmd_len > 4) {
1620 sens->assert_enable &= ~cmd[4];
1622 if (cmd_len > 5) {
1623 sens->assert_enable &= ~(cmd[5] << 8);
1625 if (cmd_len > 6) {
1626 sens->deassert_enable &= ~cmd[6];
1628 if (cmd_len > 7) {
1629 sens->deassert_enable &= ~(cmd[7] << 8);
1631 break;
1632 case 3:
1633 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1634 return;
1636 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1639 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1640 uint8_t *cmd, unsigned int cmd_len,
1641 RspBuffer *rsp)
1643 IPMISensor *sens;
1645 if ((cmd[2] >= MAX_SENSORS) ||
1646 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1647 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1648 return;
1650 sens = ibs->sensors + cmd[2];
1651 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1652 rsp_buffer_push(rsp, sens->assert_enable & 0xff);
1653 rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
1654 rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
1655 rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
1658 static void rearm_sensor_evts(IPMIBmcSim *ibs,
1659 uint8_t *cmd, unsigned int cmd_len,
1660 RspBuffer *rsp)
1662 IPMISensor *sens;
1664 if ((cmd[2] >= MAX_SENSORS) ||
1665 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1666 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1667 return;
1669 sens = ibs->sensors + cmd[2];
1671 if ((cmd[3] & 0x80) == 0) {
1672 /* Just clear everything */
1673 sens->states = 0;
1674 return;
1678 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1679 uint8_t *cmd, unsigned int cmd_len,
1680 RspBuffer *rsp)
1682 IPMISensor *sens;
1684 if ((cmd[2] >= MAX_SENSORS) ||
1685 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1686 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1687 return;
1689 sens = ibs->sensors + cmd[2];
1690 rsp_buffer_push(rsp, sens->reading);
1691 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1692 rsp_buffer_push(rsp, sens->assert_states & 0xff);
1693 rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
1694 rsp_buffer_push(rsp, sens->deassert_states & 0xff);
1695 rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
1698 static void get_sensor_reading(IPMIBmcSim *ibs,
1699 uint8_t *cmd, unsigned int cmd_len,
1700 RspBuffer *rsp)
1702 IPMISensor *sens;
1704 if ((cmd[2] >= MAX_SENSORS) ||
1705 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1706 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1707 return;
1709 sens = ibs->sensors + cmd[2];
1710 rsp_buffer_push(rsp, sens->reading);
1711 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1712 rsp_buffer_push(rsp, sens->states & 0xff);
1713 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1714 rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
1718 static void set_sensor_type(IPMIBmcSim *ibs,
1719 uint8_t *cmd, unsigned int cmd_len,
1720 RspBuffer *rsp)
1722 IPMISensor *sens;
1725 if ((cmd[2] >= MAX_SENSORS) ||
1726 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1727 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1728 return;
1730 sens = ibs->sensors + cmd[2];
1731 sens->sensor_type = cmd[3];
1732 sens->evt_reading_type_code = cmd[4] & 0x7f;
1735 static void get_sensor_type(IPMIBmcSim *ibs,
1736 uint8_t *cmd, unsigned int cmd_len,
1737 RspBuffer *rsp)
1739 IPMISensor *sens;
1742 if ((cmd[2] >= MAX_SENSORS) ||
1743 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1744 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1745 return;
1747 sens = ibs->sensors + cmd[2];
1748 rsp_buffer_push(rsp, sens->sensor_type);
1749 rsp_buffer_push(rsp, sens->evt_reading_type_code);
1753 * bytes parameter
1754 * 1 sensor number
1755 * 2 operation (see below for bits meaning)
1756 * 3 sensor reading
1757 * 4:5 assertion states (optional)
1758 * 6:7 deassertion states (optional)
1759 * 8:10 event data 1,2,3 (optional)
1761 static void set_sensor_reading(IPMIBmcSim *ibs,
1762 uint8_t *cmd, unsigned int cmd_len,
1763 RspBuffer *rsp)
1765 IPMISensor *sens;
1766 uint8_t evd1 = 0;
1767 uint8_t evd2 = 0;
1768 uint8_t evd3 = 0;
1769 uint8_t new_reading = 0;
1770 uint16_t new_assert_states = 0;
1771 uint16_t new_deassert_states = 0;
1772 bool change_reading = false;
1773 bool change_assert = false;
1774 bool change_deassert = false;
1775 enum {
1776 SENSOR_GEN_EVENT_NONE,
1777 SENSOR_GEN_EVENT_DATA,
1778 SENSOR_GEN_EVENT_BMC,
1779 } do_gen_event = SENSOR_GEN_EVENT_NONE;
1781 if ((cmd[2] >= MAX_SENSORS) ||
1782 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1783 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1784 return;
1787 sens = ibs->sensors + cmd[2];
1789 /* [1:0] Sensor Reading operation */
1790 switch ((cmd[3]) & 0x3) {
1791 case 0: /* Do not change */
1792 break;
1793 case 1: /* write given value to sensor reading byte */
1794 new_reading = cmd[4];
1795 if (sens->reading != new_reading) {
1796 change_reading = true;
1798 break;
1799 case 2:
1800 case 3:
1801 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1802 return;
1805 /* [3:2] Deassertion bits operation */
1806 switch ((cmd[3] >> 2) & 0x3) {
1807 case 0: /* Do not change */
1808 break;
1809 case 1: /* write given value */
1810 if (cmd_len > 7) {
1811 new_deassert_states = cmd[7];
1812 change_deassert = true;
1814 if (cmd_len > 8) {
1815 new_deassert_states |= (cmd[8] << 8);
1817 break;
1819 case 2: /* mask on */
1820 if (cmd_len > 7) {
1821 new_deassert_states = (sens->deassert_states | cmd[7]);
1822 change_deassert = true;
1824 if (cmd_len > 8) {
1825 new_deassert_states |= (sens->deassert_states | (cmd[8] << 8));
1827 break;
1829 case 3: /* mask off */
1830 if (cmd_len > 7) {
1831 new_deassert_states = (sens->deassert_states & cmd[7]);
1832 change_deassert = true;
1834 if (cmd_len > 8) {
1835 new_deassert_states |= (sens->deassert_states & (cmd[8] << 8));
1837 break;
1840 if (change_deassert && (new_deassert_states == sens->deassert_states)) {
1841 change_deassert = false;
1844 /* [5:4] Assertion bits operation */
1845 switch ((cmd[3] >> 4) & 0x3) {
1846 case 0: /* Do not change */
1847 break;
1848 case 1: /* write given value */
1849 if (cmd_len > 5) {
1850 new_assert_states = cmd[5];
1851 change_assert = true;
1853 if (cmd_len > 6) {
1854 new_assert_states |= (cmd[6] << 8);
1856 break;
1858 case 2: /* mask on */
1859 if (cmd_len > 5) {
1860 new_assert_states = (sens->assert_states | cmd[5]);
1861 change_assert = true;
1863 if (cmd_len > 6) {
1864 new_assert_states |= (sens->assert_states | (cmd[6] << 8));
1866 break;
1868 case 3: /* mask off */
1869 if (cmd_len > 5) {
1870 new_assert_states = (sens->assert_states & cmd[5]);
1871 change_assert = true;
1873 if (cmd_len > 6) {
1874 new_assert_states |= (sens->assert_states & (cmd[6] << 8));
1876 break;
1879 if (change_assert && (new_assert_states == sens->assert_states)) {
1880 change_assert = false;
1883 if (cmd_len > 9) {
1884 evd1 = cmd[9];
1886 if (cmd_len > 10) {
1887 evd2 = cmd[10];
1889 if (cmd_len > 11) {
1890 evd3 = cmd[11];
1893 /* [7:6] Event Data Bytes operation */
1894 switch ((cmd[3] >> 6) & 0x3) {
1895 case 0: /*
1896 * Don’t use Event Data bytes from this command. BMC will
1897 * generate it's own Event Data bytes based on its sensor
1898 * implementation.
1900 evd1 = evd2 = evd3 = 0x0;
1901 do_gen_event = SENSOR_GEN_EVENT_BMC;
1902 break;
1903 case 1: /*
1904 * Write given values to event data bytes including bits
1905 * [3:0] Event Data 1.
1907 do_gen_event = SENSOR_GEN_EVENT_DATA;
1908 break;
1909 case 2: /*
1910 * Write given values to event data bytes excluding bits
1911 * [3:0] Event Data 1.
1913 evd1 &= 0xf0;
1914 do_gen_event = SENSOR_GEN_EVENT_DATA;
1915 break;
1916 case 3:
1917 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1918 return;
1922 * Event Data Bytes operation and parameter are inconsistent. The
1923 * Specs are not clear on that topic but generating an error seems
1924 * correct.
1926 if (do_gen_event == SENSOR_GEN_EVENT_DATA && cmd_len < 10) {
1927 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1928 return;
1931 /* commit values */
1932 if (change_reading) {
1933 sens->reading = new_reading;
1936 if (change_assert) {
1937 sens->assert_states = new_assert_states;
1940 if (change_deassert) {
1941 sens->deassert_states = new_deassert_states;
1944 /* TODO: handle threshold sensor */
1945 if (!IPMI_SENSOR_IS_DISCRETE(sens)) {
1946 return;
1949 switch (do_gen_event) {
1950 case SENSOR_GEN_EVENT_DATA: {
1951 unsigned int bit = evd1 & 0xf;
1952 uint16_t mask = (1 << bit);
1954 if (sens->assert_states & mask & sens->assert_enable) {
1955 gen_event(ibs, cmd[2], 0, evd1, evd2, evd3);
1958 if (sens->deassert_states & mask & sens->deassert_enable) {
1959 gen_event(ibs, cmd[2], 1, evd1, evd2, evd3);
1961 break;
1963 case SENSOR_GEN_EVENT_BMC:
1965 * TODO: generate event and event data bytes depending on the
1966 * sensor
1968 break;
1969 case SENSOR_GEN_EVENT_NONE:
1970 break;
1974 static const IPMICmdHandler chassis_cmds[] = {
1975 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
1976 [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
1977 [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
1978 [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
1980 static const IPMINetfn chassis_netfn = {
1981 .cmd_nums = ARRAY_SIZE(chassis_cmds),
1982 .cmd_handlers = chassis_cmds
1985 static const IPMICmdHandler sensor_event_cmds[] = {
1986 [IPMI_CMD_PLATFORM_EVENT_MSG] = { platform_event_msg, 10 },
1987 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
1988 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
1989 [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
1990 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
1991 [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
1992 [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
1993 [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
1994 [IPMI_CMD_SET_SENSOR_READING] = { set_sensor_reading, 5 },
1996 static const IPMINetfn sensor_event_netfn = {
1997 .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
1998 .cmd_handlers = sensor_event_cmds
2001 static const IPMICmdHandler app_cmds[] = {
2002 [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
2003 [IPMI_CMD_COLD_RESET] = { cold_reset },
2004 [IPMI_CMD_WARM_RESET] = { warm_reset },
2005 [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
2006 [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
2007 [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
2008 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
2009 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
2010 [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
2011 [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
2012 [IPMI_CMD_GET_MSG] = { get_msg },
2013 [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
2014 [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
2015 [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
2016 [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
2017 [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
2019 static const IPMINetfn app_netfn = {
2020 .cmd_nums = ARRAY_SIZE(app_cmds),
2021 .cmd_handlers = app_cmds
2024 static const IPMICmdHandler storage_cmds[] = {
2025 [IPMI_CMD_GET_FRU_AREA_INFO] = { get_fru_area_info, 3 },
2026 [IPMI_CMD_READ_FRU_DATA] = { read_fru_data, 5 },
2027 [IPMI_CMD_WRITE_FRU_DATA] = { write_fru_data, 5 },
2028 [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
2029 [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
2030 [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
2031 [IPMI_CMD_ADD_SDR] = { add_sdr },
2032 [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
2033 [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
2034 [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
2035 [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
2036 [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
2037 [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
2038 [IPMI_CMD_GET_SEL_TIME] = { get_sel_time },
2039 [IPMI_CMD_SET_SEL_TIME] = { set_sel_time, 6 },
2042 static const IPMINetfn storage_netfn = {
2043 .cmd_nums = ARRAY_SIZE(storage_cmds),
2044 .cmd_handlers = storage_cmds
2047 static void register_cmds(IPMIBmcSim *s)
2049 ipmi_sim_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
2050 ipmi_sim_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
2051 ipmi_sim_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
2052 ipmi_sim_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
2055 static uint8_t init_sdrs[] = {
2056 /* Watchdog device */
2057 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
2058 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
2059 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2060 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
2061 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
2064 static void ipmi_sdr_init(IPMIBmcSim *ibs)
2066 unsigned int i;
2067 int len;
2068 size_t sdrs_size;
2069 uint8_t *sdrs;
2071 sdrs_size = sizeof(init_sdrs);
2072 sdrs = init_sdrs;
2073 if (ibs->sdr_filename &&
2074 !g_file_get_contents(ibs->sdr_filename, (gchar **) &sdrs, &sdrs_size,
2075 NULL)) {
2076 error_report("failed to load sdr file '%s'", ibs->sdr_filename);
2077 sdrs_size = sizeof(init_sdrs);
2078 sdrs = init_sdrs;
2081 for (i = 0; i < sdrs_size; i += len) {
2082 struct ipmi_sdr_header *sdrh;
2084 if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
2085 error_report("Problem with recid 0x%4.4x", i);
2086 break;
2088 sdrh = (struct ipmi_sdr_header *) &sdrs[i];
2089 len = ipmi_sdr_length(sdrh);
2090 if (i + len > sdrs_size) {
2091 error_report("Problem with recid 0x%4.4x", i);
2092 break;
2094 sdr_add_entry(ibs, sdrh, len, NULL);
2097 if (sdrs != init_sdrs) {
2098 g_free(sdrs);
2102 static const VMStateDescription vmstate_ipmi_sim = {
2103 .name = TYPE_IPMI_BMC_SIMULATOR,
2104 .version_id = 1,
2105 .minimum_version_id = 1,
2106 .fields = (VMStateField[]) {
2107 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
2108 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
2109 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
2110 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
2111 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
2112 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
2113 VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
2114 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
2115 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
2116 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
2117 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
2118 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
2119 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
2120 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
2121 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
2122 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
2123 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
2124 IPMIBmcSim),
2125 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
2126 VMSTATE_END_OF_LIST()
2130 static void ipmi_fru_init(IPMIFru *fru)
2132 int fsize;
2133 int size = 0;
2135 if (!fru->filename) {
2136 goto out;
2139 fsize = get_image_size(fru->filename);
2140 if (fsize > 0) {
2141 size = QEMU_ALIGN_UP(fsize, fru->areasize);
2142 fru->data = g_malloc0(size);
2143 if (load_image_size(fru->filename, fru->data, fsize) != fsize) {
2144 error_report("Could not load file '%s'", fru->filename);
2145 g_free(fru->data);
2146 fru->data = NULL;
2150 out:
2151 if (!fru->data) {
2152 /* give one default FRU */
2153 size = fru->areasize;
2154 fru->data = g_malloc0(size);
2157 fru->nentries = size / fru->areasize;
2160 static void ipmi_sim_realize(DeviceState *dev, Error **errp)
2162 IPMIBmc *b = IPMI_BMC(dev);
2163 unsigned int i;
2164 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
2166 QTAILQ_INIT(&ibs->rcvbufs);
2168 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
2169 ibs->device_id = 0x20;
2170 ibs->ipmi_version = 0x02; /* IPMI 2.0 */
2171 ibs->restart_cause = 0;
2172 for (i = 0; i < 4; i++) {
2173 ibs->sel.last_addition[i] = 0xff;
2174 ibs->sel.last_clear[i] = 0xff;
2175 ibs->sdr.last_addition[i] = 0xff;
2176 ibs->sdr.last_clear[i] = 0xff;
2179 ipmi_sdr_init(ibs);
2181 ipmi_fru_init(&ibs->fru);
2183 ibs->acpi_power_state[0] = 0;
2184 ibs->acpi_power_state[1] = 0;
2186 ipmi_init_sensors_from_sdrs(ibs);
2187 register_cmds(ibs);
2189 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
2191 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
2194 static Property ipmi_sim_properties[] = {
2195 DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim, fru.areasize, 1024),
2196 DEFINE_PROP_STRING("frudatafile", IPMIBmcSim, fru.filename),
2197 DEFINE_PROP_STRING("sdrfile", IPMIBmcSim, sdr_filename),
2198 DEFINE_PROP_UINT8("device_id", IPMIBmcSim, device_id, 0x20),
2199 DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim, ipmi_version, 0x02),
2200 DEFINE_PROP_UINT8("device_rev", IPMIBmcSim, device_rev, 0),
2201 DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim, fwrev1, 0),
2202 DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim, fwrev2, 0),
2203 DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim, mfg_id, 0),
2204 DEFINE_PROP_UINT16("product_id", IPMIBmcSim, product_id, 0),
2205 DEFINE_PROP_UUID_NODEFAULT("guid", IPMIBmcSim, uuid),
2206 DEFINE_PROP_END_OF_LIST(),
2209 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
2211 DeviceClass *dc = DEVICE_CLASS(oc);
2212 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
2214 dc->hotpluggable = false;
2215 dc->realize = ipmi_sim_realize;
2216 device_class_set_props(dc, ipmi_sim_properties);
2217 bk->handle_command = ipmi_sim_handle_command;
2220 static const TypeInfo ipmi_sim_type = {
2221 .name = TYPE_IPMI_BMC_SIMULATOR,
2222 .parent = TYPE_IPMI_BMC,
2223 .instance_size = sizeof(IPMIBmcSim),
2224 .class_init = ipmi_sim_class_init,
2227 static void ipmi_sim_register_types(void)
2229 type_register_static(&ipmi_sim_type);
2232 type_init(ipmi_sim_register_types)