virtio-ccw-input: fix description
[qemu/ar7.git] / hw / ipmi / ipmi_bmc_sim.c
blobf78e92d3d5ab2b52e0a3dde7b3ee87696fc8e06a
1 /*
2 * IPMI BMC emulation
4 * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "qemu/osdep.h"
26 #include "sysemu/sysemu.h"
27 #include "qemu/timer.h"
28 #include "hw/ipmi/ipmi.h"
29 #include "qemu/error-report.h"
30 #include "qemu/module.h"
31 #include "hw/loader.h"
32 #include "hw/qdev-properties.h"
33 #include "migration/vmstate.h"
35 #define IPMI_NETFN_CHASSIS 0x00
37 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
38 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
39 #define IPMI_CMD_CHASSIS_CONTROL 0x02
40 #define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09
42 #define IPMI_NETFN_SENSOR_EVENT 0x04
44 #define IPMI_CMD_PLATFORM_EVENT_MSG 0x02
45 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
46 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
47 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
48 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
49 #define IPMI_CMD_GET_SENSOR_READING 0x2d
50 #define IPMI_CMD_SET_SENSOR_TYPE 0x2e
51 #define IPMI_CMD_GET_SENSOR_TYPE 0x2f
52 #define IPMI_CMD_SET_SENSOR_READING 0x30
54 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
56 #define IPMI_CMD_GET_DEVICE_ID 0x01
57 #define IPMI_CMD_COLD_RESET 0x02
58 #define IPMI_CMD_WARM_RESET 0x03
59 #define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
60 #define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
61 #define IPMI_CMD_GET_DEVICE_GUID 0x08
62 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
63 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
64 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
65 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
66 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
67 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
68 #define IPMI_CMD_GET_MSG_FLAGS 0x31
69 #define IPMI_CMD_GET_MSG 0x33
70 #define IPMI_CMD_SEND_MSG 0x34
71 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
73 #define IPMI_NETFN_STORAGE 0x0a
75 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
76 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
77 #define IPMI_CMD_RESERVE_SDR_REP 0x22
78 #define IPMI_CMD_GET_SDR 0x23
79 #define IPMI_CMD_ADD_SDR 0x24
80 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
81 #define IPMI_CMD_DELETE_SDR 0x26
82 #define IPMI_CMD_CLEAR_SDR_REP 0x27
83 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
84 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
85 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
86 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
87 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
88 #define IPMI_CMD_GET_FRU_AREA_INFO 0x10
89 #define IPMI_CMD_READ_FRU_DATA 0x11
90 #define IPMI_CMD_WRITE_FRU_DATA 0x12
91 #define IPMI_CMD_GET_SEL_INFO 0x40
92 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
93 #define IPMI_CMD_RESERVE_SEL 0x42
94 #define IPMI_CMD_GET_SEL_ENTRY 0x43
95 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
96 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
97 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
98 #define IPMI_CMD_CLEAR_SEL 0x47
99 #define IPMI_CMD_GET_SEL_TIME 0x48
100 #define IPMI_CMD_SET_SEL_TIME 0x49
103 /* Same as a timespec struct. */
104 struct ipmi_time {
105 long tv_sec;
106 long tv_nsec;
109 #define MAX_SEL_SIZE 128
111 typedef struct IPMISel {
112 uint8_t sel[MAX_SEL_SIZE][16];
113 unsigned int next_free;
114 long time_offset;
115 uint16_t reservation;
116 uint8_t last_addition[4];
117 uint8_t last_clear[4];
118 uint8_t overflow;
119 } IPMISel;
121 #define MAX_SDR_SIZE 16384
123 typedef struct IPMISdr {
124 uint8_t sdr[MAX_SDR_SIZE];
125 unsigned int next_free;
126 uint16_t next_rec_id;
127 uint16_t reservation;
128 uint8_t last_addition[4];
129 uint8_t last_clear[4];
130 uint8_t overflow;
131 } IPMISdr;
133 typedef struct IPMIFru {
134 char *filename;
135 unsigned int nentries;
136 uint16_t areasize;
137 uint8_t *data;
138 } IPMIFru;
140 typedef struct IPMISensor {
141 uint8_t status;
142 uint8_t reading;
143 uint16_t states_suppt;
144 uint16_t assert_suppt;
145 uint16_t deassert_suppt;
146 uint16_t states;
147 uint16_t assert_states;
148 uint16_t deassert_states;
149 uint16_t assert_enable;
150 uint16_t deassert_enable;
151 uint8_t sensor_type;
152 uint8_t evt_reading_type_code;
153 } IPMISensor;
154 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
155 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
156 !!(v))
157 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
158 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
159 ((!!(v)) << 6))
160 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
161 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
162 ((!!(v)) << 7))
163 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
164 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
165 (v & 0xc0))
166 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
168 #define MAX_SENSORS 20
169 #define IPMI_WATCHDOG_SENSOR 0
171 #define MAX_NETFNS 64
173 typedef struct IPMIRcvBufEntry {
174 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
175 uint8_t len;
176 uint8_t buf[MAX_IPMI_MSG_SIZE];
177 } IPMIRcvBufEntry;
179 struct IPMIBmcSim {
180 IPMIBmc parent;
182 QEMUTimer *timer;
184 uint8_t bmc_global_enables;
185 uint8_t msg_flags;
187 bool watchdog_initialized;
188 uint8_t watchdog_use;
189 uint8_t watchdog_action;
190 uint8_t watchdog_pretimeout; /* In seconds */
191 bool watchdog_expired;
192 uint16_t watchdog_timeout; /* in 100's of milliseconds */
194 bool watchdog_running;
195 bool watchdog_preaction_ran;
196 int64_t watchdog_expiry;
198 uint8_t device_id;
199 uint8_t ipmi_version;
200 uint8_t device_rev;
201 uint8_t fwrev1;
202 uint8_t fwrev2;
203 uint32_t mfg_id;
204 uint16_t product_id;
206 uint8_t restart_cause;
208 uint8_t acpi_power_state[2];
209 QemuUUID uuid;
211 IPMISel sel;
212 IPMISdr sdr;
213 IPMIFru fru;
214 IPMISensor sensors[MAX_SENSORS];
215 char *sdr_filename;
217 /* Odd netfns are for responses, so we only need the even ones. */
218 const IPMINetfn *netfns[MAX_NETFNS / 2];
220 /* We allow one event in the buffer */
221 uint8_t evtbuf[16];
223 QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
226 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
227 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
228 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
229 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
230 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
231 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
232 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
233 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
234 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
236 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
237 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
238 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
239 #define IPMI_BMC_EVENT_LOG_BIT 3
240 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
241 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
242 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
243 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
244 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
245 (1 << IPMI_BMC_EVENT_LOG_BIT))
246 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
247 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
249 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
250 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
251 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
252 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
253 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
254 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
255 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
256 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
257 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
258 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
259 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
260 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
261 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
262 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
263 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
265 #define RSP_BUFFER_INITIALIZER { }
267 static inline void rsp_buffer_pushmore(RspBuffer *rsp, uint8_t *bytes,
268 unsigned int n)
270 if (rsp->len + n >= sizeof(rsp->buffer)) {
271 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
272 return;
275 memcpy(&rsp->buffer[rsp->len], bytes, n);
276 rsp->len += n;
279 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
281 static void ipmi_gettime(struct ipmi_time *time)
283 int64_t stime;
285 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
286 time->tv_sec = stime / 1000000000LL;
287 time->tv_nsec = stime % 1000000000LL;
290 static int64_t ipmi_getmonotime(void)
292 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
295 static void ipmi_timeout(void *opaque)
297 IPMIBmcSim *ibs = opaque;
299 ipmi_sim_handle_timeout(ibs);
302 static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
304 unsigned int val;
305 struct ipmi_time now;
307 ipmi_gettime(&now);
308 val = now.tv_sec + ibs->sel.time_offset;
309 ts[0] = val & 0xff;
310 ts[1] = (val >> 8) & 0xff;
311 ts[2] = (val >> 16) & 0xff;
312 ts[3] = (val >> 24) & 0xff;
315 static void sdr_inc_reservation(IPMISdr *sdr)
317 sdr->reservation++;
318 if (sdr->reservation == 0) {
319 sdr->reservation = 1;
323 static int sdr_add_entry(IPMIBmcSim *ibs,
324 const struct ipmi_sdr_header *sdrh_entry,
325 unsigned int len, uint16_t *recid)
327 struct ipmi_sdr_header *sdrh =
328 (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
330 if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
331 return 1;
334 if (ipmi_sdr_length(sdrh_entry) != len) {
335 return 1;
338 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
339 ibs->sdr.overflow = 1;
340 return 1;
343 memcpy(sdrh, sdrh_entry, len);
344 sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff;
345 sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
346 sdrh->sdr_version = 0x51; /* Conform to IPMI 1.5 spec */
348 if (recid) {
349 *recid = ibs->sdr.next_rec_id;
351 ibs->sdr.next_rec_id++;
352 set_timestamp(ibs, ibs->sdr.last_addition);
353 ibs->sdr.next_free += len;
354 sdr_inc_reservation(&ibs->sdr);
355 return 0;
358 static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
359 unsigned int *retpos, uint16_t *nextrec)
361 unsigned int pos = *retpos;
363 while (pos < sdr->next_free) {
364 struct ipmi_sdr_header *sdrh =
365 (struct ipmi_sdr_header *) &sdr->sdr[pos];
366 uint16_t trec = ipmi_sdr_recid(sdrh);
367 unsigned int nextpos = pos + ipmi_sdr_length(sdrh);
369 if (trec == recid) {
370 if (nextrec) {
371 if (nextpos >= sdr->next_free) {
372 *nextrec = 0xffff;
373 } else {
374 *nextrec = (sdr->sdr[nextpos] |
375 (sdr->sdr[nextpos + 1] << 8));
378 *retpos = pos;
379 return 0;
381 pos = nextpos;
383 return 1;
386 int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
387 const struct ipmi_sdr_compact **sdr, uint16_t *nextrec)
390 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
391 unsigned int pos;
393 pos = 0;
394 if (sdr_find_entry(&ibs->sdr, recid, &pos, nextrec)) {
395 return -1;
398 *sdr = (const struct ipmi_sdr_compact *) &ibs->sdr.sdr[pos];
399 return 0;
402 static void sel_inc_reservation(IPMISel *sel)
404 sel->reservation++;
405 if (sel->reservation == 0) {
406 sel->reservation = 1;
410 /* Returns 1 if the SEL is full and can't hold the event. */
411 static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
413 uint8_t ts[4];
415 event[0] = 0xff;
416 event[1] = 0xff;
417 set_timestamp(ibs, ts);
418 if (event[2] < 0xe0) { /* Don't set timestamps for type 0xe0-0xff. */
419 memcpy(event + 3, ts, 4);
421 if (ibs->sel.next_free == MAX_SEL_SIZE) {
422 ibs->sel.overflow = 1;
423 return 1;
425 event[0] = ibs->sel.next_free & 0xff;
426 event[1] = (ibs->sel.next_free >> 8) & 0xff;
427 memcpy(ibs->sel.last_addition, ts, 4);
428 memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
429 ibs->sel.next_free++;
430 sel_inc_reservation(&ibs->sel);
431 return 0;
434 static int attn_set(IPMIBmcSim *ibs)
436 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
437 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
438 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
441 static int attn_irq_enabled(IPMIBmcSim *ibs)
443 return (IPMI_BMC_MSG_INTS_ON(ibs) &&
444 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs) ||
445 IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs)))
446 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
447 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
450 void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log)
452 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
453 IPMIInterface *s = ibs->parent.intf;
454 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
456 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
457 return;
460 if (log && IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
461 sel_add_event(ibs, evt);
464 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
465 goto out;
468 memcpy(ibs->evtbuf, evt, 16);
469 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
470 k->set_atn(s, 1, attn_irq_enabled(ibs));
471 out:
472 return;
474 static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
475 uint8_t evd1, uint8_t evd2, uint8_t evd3)
477 IPMIInterface *s = ibs->parent.intf;
478 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
479 uint8_t evt[16];
480 IPMISensor *sens = ibs->sensors + sens_num;
482 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
483 return;
485 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
486 return;
489 evt[2] = 0x2; /* System event record */
490 evt[7] = ibs->parent.slave_addr;
491 evt[8] = 0;
492 evt[9] = 0x04; /* Format version */
493 evt[10] = sens->sensor_type;
494 evt[11] = sens_num;
495 evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
496 evt[13] = evd1;
497 evt[14] = evd2;
498 evt[15] = evd3;
500 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
501 sel_add_event(ibs, evt);
504 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
505 return;
508 memcpy(ibs->evtbuf, evt, 16);
509 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
510 k->set_atn(s, 1, attn_irq_enabled(ibs));
513 static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
514 unsigned int bit, unsigned int val,
515 uint8_t evd1, uint8_t evd2, uint8_t evd3)
517 IPMISensor *sens;
518 uint16_t mask;
520 if (sensor >= MAX_SENSORS) {
521 return;
523 if (bit >= 16) {
524 return;
527 mask = (1 << bit);
528 sens = ibs->sensors + sensor;
529 if (val) {
530 sens->states |= mask & sens->states_suppt;
531 if (sens->assert_states & mask) {
532 return; /* Already asserted */
534 sens->assert_states |= mask & sens->assert_suppt;
535 if (sens->assert_enable & mask & sens->assert_states) {
536 /* Send an event on assert */
537 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
539 } else {
540 sens->states &= ~(mask & sens->states_suppt);
541 if (sens->deassert_states & mask) {
542 return; /* Already deasserted */
544 sens->deassert_states |= mask & sens->deassert_suppt;
545 if (sens->deassert_enable & mask & sens->deassert_states) {
546 /* Send an event on deassert */
547 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
552 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
554 unsigned int i, pos;
555 IPMISensor *sens;
557 for (i = 0; i < MAX_SENSORS; i++) {
558 memset(s->sensors + i, 0, sizeof(*sens));
561 pos = 0;
562 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
563 struct ipmi_sdr_compact *sdr =
564 (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
565 unsigned int len = sdr->header.rec_length;
567 if (len < 20) {
568 continue;
570 if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
571 continue; /* Not a sensor SDR we set from */
574 if (sdr->sensor_owner_number >= MAX_SENSORS) {
575 continue;
577 sens = s->sensors + sdr->sensor_owner_number;
579 IPMI_SENSOR_SET_PRESENT(sens, 1);
580 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
581 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
582 sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
583 sens->deassert_suppt =
584 sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
585 sens->states_suppt =
586 sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
587 sens->sensor_type = sdr->sensor_type;
588 sens->evt_reading_type_code = sdr->reading_type & 0x7f;
590 /* Enable all the events that are supported. */
591 sens->assert_enable = sens->assert_suppt;
592 sens->deassert_enable = sens->deassert_suppt;
596 int ipmi_sim_register_netfn(IPMIBmcSim *s, unsigned int netfn,
597 const IPMINetfn *netfnd)
599 if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
600 return -1;
602 s->netfns[netfn / 2] = netfnd;
603 return 0;
606 static const IPMICmdHandler *ipmi_get_handler(IPMIBmcSim *ibs,
607 unsigned int netfn,
608 unsigned int cmd)
610 const IPMICmdHandler *hdl;
612 if (netfn & 1 || netfn >= MAX_NETFNS || !ibs->netfns[netfn / 2]) {
613 return NULL;
616 if (cmd >= ibs->netfns[netfn / 2]->cmd_nums) {
617 return NULL;
620 hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd];
621 if (!hdl->cmd_handler) {
622 return NULL;
625 return hdl;
628 static void next_timeout(IPMIBmcSim *ibs)
630 int64_t next;
631 if (ibs->watchdog_running) {
632 next = ibs->watchdog_expiry;
633 } else {
634 /* Wait a minute */
635 next = ipmi_getmonotime() + 60 * 1000000000LL;
637 timer_mod_ns(ibs->timer, next);
640 static void ipmi_sim_handle_command(IPMIBmc *b,
641 uint8_t *cmd, unsigned int cmd_len,
642 unsigned int max_cmd_len,
643 uint8_t msg_id)
645 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
646 IPMIInterface *s = ibs->parent.intf;
647 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
648 const IPMICmdHandler *hdl;
649 RspBuffer rsp = RSP_BUFFER_INITIALIZER;
651 /* Set up the response, set the low bit of NETFN. */
652 /* Note that max_rsp_len must be at least 3 */
653 if (sizeof(rsp.buffer) < 3) {
654 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
655 goto out;
658 rsp_buffer_push(&rsp, cmd[0] | 0x04);
659 rsp_buffer_push(&rsp, cmd[1]);
660 rsp_buffer_push(&rsp, 0); /* Assume success */
662 /* If it's too short or it was truncated, return an error. */
663 if (cmd_len < 2) {
664 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
665 goto out;
667 if (cmd_len > max_cmd_len) {
668 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
669 goto out;
672 if ((cmd[0] & 0x03) != 0) {
673 /* Only have stuff on LUN 0 */
674 rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN);
675 goto out;
678 hdl = ipmi_get_handler(ibs, cmd[0] >> 2, cmd[1]);
679 if (!hdl) {
680 rsp_buffer_set_error(&rsp, IPMI_CC_INVALID_CMD);
681 goto out;
684 if (cmd_len < hdl->cmd_len_min) {
685 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
686 goto out;
689 hdl->cmd_handler(ibs, cmd, cmd_len, &rsp);
691 out:
692 k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
694 next_timeout(ibs);
697 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
699 IPMIInterface *s = ibs->parent.intf;
700 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
702 if (!ibs->watchdog_running) {
703 goto out;
706 if (!ibs->watchdog_preaction_ran) {
707 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
708 case IPMI_BMC_WATCHDOG_PRE_NMI:
709 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
710 k->do_hw_op(s, IPMI_SEND_NMI, 0);
711 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
712 0xc8, (2 << 4) | 0xf, 0xff);
713 break;
715 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
716 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
717 k->set_atn(s, 1, attn_irq_enabled(ibs));
718 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
719 0xc8, (3 << 4) | 0xf, 0xff);
720 break;
722 default:
723 goto do_full_expiry;
726 ibs->watchdog_preaction_ran = 1;
727 /* Issued the pretimeout, do the rest of the timeout now. */
728 ibs->watchdog_expiry = ipmi_getmonotime();
729 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
730 goto out;
733 do_full_expiry:
734 ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
735 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
736 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
737 case IPMI_BMC_WATCHDOG_ACTION_NONE:
738 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
739 0xc0, ibs->watchdog_use & 0xf, 0xff);
740 break;
742 case IPMI_BMC_WATCHDOG_ACTION_RESET:
743 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
744 0xc1, ibs->watchdog_use & 0xf, 0xff);
745 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
746 break;
748 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
749 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
750 0xc2, ibs->watchdog_use & 0xf, 0xff);
751 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
752 break;
754 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
755 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
756 0xc3, ibs->watchdog_use & 0xf, 0xff);
757 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
758 break;
761 out:
762 next_timeout(ibs);
765 static void chassis_capabilities(IPMIBmcSim *ibs,
766 uint8_t *cmd, unsigned int cmd_len,
767 RspBuffer *rsp)
769 rsp_buffer_push(rsp, 0);
770 rsp_buffer_push(rsp, ibs->parent.slave_addr);
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);
776 static void chassis_status(IPMIBmcSim *ibs,
777 uint8_t *cmd, unsigned int cmd_len,
778 RspBuffer *rsp)
780 rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */
781 rsp_buffer_push(rsp, 0);
782 rsp_buffer_push(rsp, 0);
783 rsp_buffer_push(rsp, 0);
786 static void chassis_control(IPMIBmcSim *ibs,
787 uint8_t *cmd, unsigned int cmd_len,
788 RspBuffer *rsp)
790 IPMIInterface *s = ibs->parent.intf;
791 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
793 switch (cmd[2] & 0xf) {
794 case 0: /* power down */
795 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0));
796 break;
797 case 1: /* power up */
798 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0));
799 break;
800 case 2: /* power cycle */
801 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0));
802 break;
803 case 3: /* hard reset */
804 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0));
805 break;
806 case 4: /* pulse diagnostic interrupt */
807 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0));
808 break;
809 case 5: /* soft shutdown via ACPI by overtemp emulation */
810 rsp_buffer_set_error(rsp, k->do_hw_op(s,
811 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0));
812 break;
813 default:
814 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
815 return;
819 static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
820 uint8_t *cmd, unsigned int cmd_len,
821 RspBuffer *rsp)
824 rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */
825 rsp_buffer_push(rsp, 0); /* Channel 0 */
828 static void get_device_id(IPMIBmcSim *ibs,
829 uint8_t *cmd, unsigned int cmd_len,
830 RspBuffer *rsp)
832 rsp_buffer_push(rsp, ibs->device_id);
833 rsp_buffer_push(rsp, ibs->device_rev & 0xf);
834 rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
835 rsp_buffer_push(rsp, ibs->fwrev2);
836 rsp_buffer_push(rsp, ibs->ipmi_version);
837 rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */
838 rsp_buffer_push(rsp, ibs->mfg_id & 0xff);
839 rsp_buffer_push(rsp, (ibs->mfg_id >> 8) & 0xff);
840 rsp_buffer_push(rsp, (ibs->mfg_id >> 16) & 0xff);
841 rsp_buffer_push(rsp, ibs->product_id & 0xff);
842 rsp_buffer_push(rsp, (ibs->product_id >> 8) & 0xff);
845 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
847 IPMIInterface *s = ibs->parent.intf;
848 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
849 bool irqs_on;
851 ibs->bmc_global_enables = val;
853 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
854 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
856 k->set_irq_enable(s, irqs_on);
859 static void cold_reset(IPMIBmcSim *ibs,
860 uint8_t *cmd, unsigned int cmd_len,
861 RspBuffer *rsp)
863 IPMIInterface *s = ibs->parent.intf;
864 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
866 /* Disable all interrupts */
867 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
869 if (k->reset) {
870 k->reset(s, true);
874 static void warm_reset(IPMIBmcSim *ibs,
875 uint8_t *cmd, unsigned int cmd_len,
876 RspBuffer *rsp)
878 IPMIInterface *s = ibs->parent.intf;
879 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
881 if (k->reset) {
882 k->reset(s, false);
885 static void set_acpi_power_state(IPMIBmcSim *ibs,
886 uint8_t *cmd, unsigned int cmd_len,
887 RspBuffer *rsp)
889 ibs->acpi_power_state[0] = cmd[2];
890 ibs->acpi_power_state[1] = cmd[3];
893 static void get_acpi_power_state(IPMIBmcSim *ibs,
894 uint8_t *cmd, unsigned int cmd_len,
895 RspBuffer *rsp)
897 rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
898 rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
901 static void get_device_guid(IPMIBmcSim *ibs,
902 uint8_t *cmd, unsigned int cmd_len,
903 RspBuffer *rsp)
905 unsigned int i;
907 /* An uninitialized uuid is all zeros, use that to know if it is set. */
908 for (i = 0; i < 16; i++) {
909 if (ibs->uuid.data[i]) {
910 goto uuid_set;
913 /* No uuid is set, return an error. */
914 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_CMD);
915 return;
917 uuid_set:
918 for (i = 0; i < 16; i++) {
919 rsp_buffer_push(rsp, ibs->uuid.data[i]);
923 static void set_bmc_global_enables(IPMIBmcSim *ibs,
924 uint8_t *cmd, unsigned int cmd_len,
925 RspBuffer *rsp)
927 set_global_enables(ibs, cmd[2]);
930 static void get_bmc_global_enables(IPMIBmcSim *ibs,
931 uint8_t *cmd, unsigned int cmd_len,
932 RspBuffer *rsp)
934 rsp_buffer_push(rsp, ibs->bmc_global_enables);
937 static void clr_msg_flags(IPMIBmcSim *ibs,
938 uint8_t *cmd, unsigned int cmd_len,
939 RspBuffer *rsp)
941 IPMIInterface *s = ibs->parent.intf;
942 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
944 ibs->msg_flags &= ~cmd[2];
945 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
948 static void get_msg_flags(IPMIBmcSim *ibs,
949 uint8_t *cmd, unsigned int cmd_len,
950 RspBuffer *rsp)
952 rsp_buffer_push(rsp, ibs->msg_flags);
955 static void read_evt_msg_buf(IPMIBmcSim *ibs,
956 uint8_t *cmd, unsigned int cmd_len,
957 RspBuffer *rsp)
959 IPMIInterface *s = ibs->parent.intf;
960 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
961 unsigned int i;
963 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
964 rsp_buffer_set_error(rsp, 0x80);
965 return;
967 for (i = 0; i < 16; i++) {
968 rsp_buffer_push(rsp, ibs->evtbuf[i]);
970 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
971 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
974 static void get_msg(IPMIBmcSim *ibs,
975 uint8_t *cmd, unsigned int cmd_len,
976 RspBuffer *rsp)
978 IPMIRcvBufEntry *msg;
980 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
981 rsp_buffer_set_error(rsp, 0x80); /* Queue empty */
982 goto out;
984 rsp_buffer_push(rsp, 0); /* Channel 0 */
985 msg = QTAILQ_FIRST(&ibs->rcvbufs);
986 rsp_buffer_pushmore(rsp, msg->buf, msg->len);
987 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
988 g_free(msg);
990 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
991 IPMIInterface *s = ibs->parent.intf;
992 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
994 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
995 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
998 out:
999 return;
1002 static unsigned char
1003 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
1005 for (; size > 0; size--, data++) {
1006 csum += *data;
1009 return -csum;
1012 static void send_msg(IPMIBmcSim *ibs,
1013 uint8_t *cmd, unsigned int cmd_len,
1014 RspBuffer *rsp)
1016 IPMIInterface *s = ibs->parent.intf;
1017 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1018 IPMIRcvBufEntry *msg;
1019 uint8_t *buf;
1020 uint8_t netfn, rqLun, rsLun, rqSeq;
1022 if (cmd[2] != 0) {
1023 /* We only handle channel 0 with no options */
1024 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1025 return;
1028 if (cmd_len < 10) {
1029 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
1030 return;
1033 if (cmd[3] != 0x40) {
1034 /* We only emulate a MC at address 0x40. */
1035 rsp_buffer_set_error(rsp, 0x83); /* NAK on write */
1036 return;
1039 cmd += 3; /* Skip the header. */
1040 cmd_len -= 3;
1043 * At this point we "send" the message successfully. Any error will
1044 * be returned in the response.
1046 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
1047 cmd[3] != 0x20) { /* Improper response address */
1048 return; /* No response */
1051 netfn = cmd[1] >> 2;
1052 rqLun = cmd[4] & 0x3;
1053 rsLun = cmd[1] & 0x3;
1054 rqSeq = cmd[4] >> 2;
1056 if (rqLun != 2) {
1057 /* We only support LUN 2 coming back to us. */
1058 return;
1061 msg = g_malloc(sizeof(*msg));
1062 msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
1063 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
1064 msg->buf[2] = cmd[0]; /* rsSA */
1065 msg->buf[3] = (rqSeq << 2) | rsLun;
1066 msg->buf[4] = cmd[5]; /* Cmd */
1067 msg->buf[5] = 0; /* Completion Code */
1068 msg->len = 6;
1070 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
1071 /* Not a command we handle. */
1072 msg->buf[5] = IPMI_CC_INVALID_CMD;
1073 goto end_msg;
1076 buf = msg->buf + msg->len; /* After the CC */
1077 buf[0] = 0;
1078 buf[1] = 0;
1079 buf[2] = 0;
1080 buf[3] = 0;
1081 buf[4] = 0x51;
1082 buf[5] = 0;
1083 buf[6] = 0;
1084 buf[7] = 0;
1085 buf[8] = 0;
1086 buf[9] = 0;
1087 buf[10] = 0;
1088 msg->len += 11;
1090 end_msg:
1091 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1092 msg->len++;
1093 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1094 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1095 k->set_atn(s, 1, attn_irq_enabled(ibs));
1098 static void do_watchdog_reset(IPMIBmcSim *ibs)
1100 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1101 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1102 ibs->watchdog_running = 0;
1103 return;
1105 ibs->watchdog_preaction_ran = 0;
1108 /* Timeout is in tenths of a second, offset is in seconds */
1109 ibs->watchdog_expiry = ipmi_getmonotime();
1110 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1111 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1112 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1114 ibs->watchdog_running = 1;
1117 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1118 uint8_t *cmd, unsigned int cmd_len,
1119 RspBuffer *rsp)
1121 if (!ibs->watchdog_initialized) {
1122 rsp_buffer_set_error(rsp, 0x80);
1123 return;
1125 do_watchdog_reset(ibs);
1128 static void set_watchdog_timer(IPMIBmcSim *ibs,
1129 uint8_t *cmd, unsigned int cmd_len,
1130 RspBuffer *rsp)
1132 IPMIInterface *s = ibs->parent.intf;
1133 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1134 unsigned int val;
1136 val = cmd[2] & 0x7; /* Validate use */
1137 if (val == 0 || val > 5) {
1138 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1139 return;
1141 val = cmd[3] & 0x7; /* Validate action */
1142 switch (val) {
1143 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1144 break;
1146 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1147 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1));
1148 break;
1150 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1151 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1));
1152 break;
1154 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1155 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1));
1156 break;
1158 default:
1159 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1161 if (rsp->buffer[2]) {
1162 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1163 return;
1166 val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1167 switch (val) {
1168 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1169 case IPMI_BMC_WATCHDOG_PRE_NONE:
1170 break;
1172 case IPMI_BMC_WATCHDOG_PRE_NMI:
1173 if (k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1174 /* NMI not supported. */
1175 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1176 return;
1178 break;
1180 default:
1181 /* We don't support PRE_SMI */
1182 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1183 return;
1186 ibs->watchdog_initialized = 1;
1187 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1188 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1189 ibs->watchdog_pretimeout = cmd[4];
1190 ibs->watchdog_expired &= ~cmd[5];
1191 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1192 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1193 do_watchdog_reset(ibs);
1194 } else {
1195 ibs->watchdog_running = 0;
1199 static void get_watchdog_timer(IPMIBmcSim *ibs,
1200 uint8_t *cmd, unsigned int cmd_len,
1201 RspBuffer *rsp)
1203 rsp_buffer_push(rsp, ibs->watchdog_use);
1204 rsp_buffer_push(rsp, ibs->watchdog_action);
1205 rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
1206 rsp_buffer_push(rsp, ibs->watchdog_expired);
1207 rsp_buffer_push(rsp, ibs->watchdog_timeout & 0xff);
1208 rsp_buffer_push(rsp, (ibs->watchdog_timeout >> 8) & 0xff);
1209 if (ibs->watchdog_running) {
1210 long timeout;
1211 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1212 / 100000000);
1213 rsp_buffer_push(rsp, timeout & 0xff);
1214 rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
1215 } else {
1216 rsp_buffer_push(rsp, 0);
1217 rsp_buffer_push(rsp, 0);
1221 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1222 uint8_t *cmd, unsigned int cmd_len,
1223 RspBuffer *rsp)
1225 unsigned int i;
1227 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */
1228 rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
1229 rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
1230 rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1231 rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1232 for (i = 0; i < 4; i++) {
1233 rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
1235 for (i = 0; i < 4; i++) {
1236 rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
1238 /* Only modal support, reserve supported */
1239 rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
1242 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1243 uint8_t *cmd, unsigned int cmd_len,
1244 RspBuffer *rsp)
1246 rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
1247 rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
1250 static void get_sdr(IPMIBmcSim *ibs,
1251 uint8_t *cmd, unsigned int cmd_len,
1252 RspBuffer *rsp)
1254 unsigned int pos;
1255 uint16_t nextrec;
1256 struct ipmi_sdr_header *sdrh;
1258 if (cmd[6]) {
1259 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1260 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1261 return;
1265 pos = 0;
1266 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1267 &pos, &nextrec)) {
1268 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1269 return;
1272 sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1274 if (cmd[6] > ipmi_sdr_length(sdrh)) {
1275 rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE);
1276 return;
1279 rsp_buffer_push(rsp, nextrec & 0xff);
1280 rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
1282 if (cmd[7] == 0xff) {
1283 cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1286 if ((cmd[7] + rsp->len) > sizeof(rsp->buffer)) {
1287 rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES);
1288 return;
1291 rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1294 static void add_sdr(IPMIBmcSim *ibs,
1295 uint8_t *cmd, unsigned int cmd_len,
1296 RspBuffer *rsp)
1298 uint16_t recid;
1299 struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1301 if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1302 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1303 return;
1305 rsp_buffer_push(rsp, recid & 0xff);
1306 rsp_buffer_push(rsp, (recid >> 8) & 0xff);
1309 static void clear_sdr_rep(IPMIBmcSim *ibs,
1310 uint8_t *cmd, unsigned int cmd_len,
1311 RspBuffer *rsp)
1313 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1314 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1315 return;
1318 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1319 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1320 return;
1322 if (cmd[7] == 0xaa) {
1323 ibs->sdr.next_free = 0;
1324 ibs->sdr.overflow = 0;
1325 set_timestamp(ibs, ibs->sdr.last_clear);
1326 rsp_buffer_push(rsp, 1); /* Erasure complete */
1327 sdr_inc_reservation(&ibs->sdr);
1328 } else if (cmd[7] == 0) {
1329 rsp_buffer_push(rsp, 1); /* Erasure complete */
1330 } else {
1331 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1332 return;
1336 static void get_sel_info(IPMIBmcSim *ibs,
1337 uint8_t *cmd, unsigned int cmd_len,
1338 RspBuffer *rsp)
1340 unsigned int i, val;
1342 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */
1343 rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
1344 rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
1345 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1346 rsp_buffer_push(rsp, val & 0xff);
1347 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1348 for (i = 0; i < 4; i++) {
1349 rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
1351 for (i = 0; i < 4; i++) {
1352 rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
1354 /* Only support Reserve SEL */
1355 rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
1358 static void get_fru_area_info(IPMIBmcSim *ibs,
1359 uint8_t *cmd, unsigned int cmd_len,
1360 RspBuffer *rsp)
1362 uint8_t fruid;
1363 uint16_t fru_entry_size;
1365 fruid = cmd[2];
1367 if (fruid >= ibs->fru.nentries) {
1368 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1369 return;
1372 fru_entry_size = ibs->fru.areasize;
1374 rsp_buffer_push(rsp, fru_entry_size & 0xff);
1375 rsp_buffer_push(rsp, fru_entry_size >> 8 & 0xff);
1376 rsp_buffer_push(rsp, 0x0);
1379 static void read_fru_data(IPMIBmcSim *ibs,
1380 uint8_t *cmd, unsigned int cmd_len,
1381 RspBuffer *rsp)
1383 uint8_t fruid;
1384 uint16_t offset;
1385 int i;
1386 uint8_t *fru_entry;
1387 unsigned int count;
1389 fruid = cmd[2];
1390 offset = (cmd[3] | cmd[4] << 8);
1392 if (fruid >= ibs->fru.nentries) {
1393 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1394 return;
1397 if (offset >= ibs->fru.areasize - 1) {
1398 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1399 return;
1402 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1404 count = MIN(cmd[5], ibs->fru.areasize - offset);
1406 rsp_buffer_push(rsp, count & 0xff);
1407 for (i = 0; i < count; i++) {
1408 rsp_buffer_push(rsp, fru_entry[offset + i]);
1412 static void write_fru_data(IPMIBmcSim *ibs,
1413 uint8_t *cmd, unsigned int cmd_len,
1414 RspBuffer *rsp)
1416 uint8_t fruid;
1417 uint16_t offset;
1418 uint8_t *fru_entry;
1419 unsigned int count;
1421 fruid = cmd[2];
1422 offset = (cmd[3] | cmd[4] << 8);
1424 if (fruid >= ibs->fru.nentries) {
1425 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1426 return;
1429 if (offset >= ibs->fru.areasize - 1) {
1430 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1431 return;
1434 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1436 count = MIN(cmd_len - 5, ibs->fru.areasize - offset);
1438 memcpy(fru_entry + offset, cmd + 5, count);
1440 rsp_buffer_push(rsp, count & 0xff);
1443 static void reserve_sel(IPMIBmcSim *ibs,
1444 uint8_t *cmd, unsigned int cmd_len,
1445 RspBuffer *rsp)
1447 rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
1448 rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
1451 static void get_sel_entry(IPMIBmcSim *ibs,
1452 uint8_t *cmd, unsigned int cmd_len,
1453 RspBuffer *rsp)
1455 unsigned int val;
1457 if (cmd[6]) {
1458 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1459 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1460 return;
1463 if (ibs->sel.next_free == 0) {
1464 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1465 return;
1467 if (cmd[6] > 15) {
1468 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1469 return;
1471 if (cmd[7] == 0xff) {
1472 cmd[7] = 16;
1473 } else if ((cmd[7] + cmd[6]) > 16) {
1474 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1475 return;
1476 } else {
1477 cmd[7] += cmd[6];
1480 val = cmd[4] | (cmd[5] << 8);
1481 if (val == 0xffff) {
1482 val = ibs->sel.next_free - 1;
1483 } else if (val >= ibs->sel.next_free) {
1484 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1485 return;
1487 if ((val + 1) == ibs->sel.next_free) {
1488 rsp_buffer_push(rsp, 0xff);
1489 rsp_buffer_push(rsp, 0xff);
1490 } else {
1491 rsp_buffer_push(rsp, (val + 1) & 0xff);
1492 rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
1494 for (; cmd[6] < cmd[7]; cmd[6]++) {
1495 rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
1499 static void add_sel_entry(IPMIBmcSim *ibs,
1500 uint8_t *cmd, unsigned int cmd_len,
1501 RspBuffer *rsp)
1503 if (sel_add_event(ibs, cmd + 2)) {
1504 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1505 return;
1507 /* sel_add_event fills in the record number. */
1508 rsp_buffer_push(rsp, cmd[2]);
1509 rsp_buffer_push(rsp, cmd[3]);
1512 static void clear_sel(IPMIBmcSim *ibs,
1513 uint8_t *cmd, unsigned int cmd_len,
1514 RspBuffer *rsp)
1516 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1517 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1518 return;
1521 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1522 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1523 return;
1525 if (cmd[7] == 0xaa) {
1526 ibs->sel.next_free = 0;
1527 ibs->sel.overflow = 0;
1528 set_timestamp(ibs, ibs->sdr.last_clear);
1529 rsp_buffer_push(rsp, 1); /* Erasure complete */
1530 sel_inc_reservation(&ibs->sel);
1531 } else if (cmd[7] == 0) {
1532 rsp_buffer_push(rsp, 1); /* Erasure complete */
1533 } else {
1534 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1535 return;
1539 static void get_sel_time(IPMIBmcSim *ibs,
1540 uint8_t *cmd, unsigned int cmd_len,
1541 RspBuffer *rsp)
1543 uint32_t val;
1544 struct ipmi_time now;
1546 ipmi_gettime(&now);
1547 val = now.tv_sec + ibs->sel.time_offset;
1548 rsp_buffer_push(rsp, val & 0xff);
1549 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1550 rsp_buffer_push(rsp, (val >> 16) & 0xff);
1551 rsp_buffer_push(rsp, (val >> 24) & 0xff);
1554 static void set_sel_time(IPMIBmcSim *ibs,
1555 uint8_t *cmd, unsigned int cmd_len,
1556 RspBuffer *rsp)
1558 uint32_t val;
1559 struct ipmi_time now;
1561 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1562 ipmi_gettime(&now);
1563 ibs->sel.time_offset = now.tv_sec - ((long) val);
1566 static void platform_event_msg(IPMIBmcSim *ibs,
1567 uint8_t *cmd, unsigned int cmd_len,
1568 RspBuffer *rsp)
1570 uint8_t event[16];
1572 event[2] = 2; /* System event record */
1573 event[7] = cmd[2]; /* Generator ID */
1574 event[8] = 0;
1575 event[9] = cmd[3]; /* EvMRev */
1576 event[10] = cmd[4]; /* Sensor type */
1577 event[11] = cmd[5]; /* Sensor number */
1578 event[12] = cmd[6]; /* Event dir / Event type */
1579 event[13] = cmd[7]; /* Event data 1 */
1580 event[14] = cmd[8]; /* Event data 2 */
1581 event[15] = cmd[9]; /* Event data 3 */
1583 if (sel_add_event(ibs, event)) {
1584 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1588 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1589 uint8_t *cmd, unsigned int cmd_len,
1590 RspBuffer *rsp)
1592 IPMISensor *sens;
1594 if ((cmd[2] >= MAX_SENSORS) ||
1595 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1596 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1597 return;
1599 sens = ibs->sensors + cmd[2];
1600 switch ((cmd[3] >> 4) & 0x3) {
1601 case 0: /* Do not change */
1602 break;
1603 case 1: /* Enable bits */
1604 if (cmd_len > 4) {
1605 sens->assert_enable |= cmd[4];
1607 if (cmd_len > 5) {
1608 sens->assert_enable |= cmd[5] << 8;
1610 if (cmd_len > 6) {
1611 sens->deassert_enable |= cmd[6];
1613 if (cmd_len > 7) {
1614 sens->deassert_enable |= cmd[7] << 8;
1616 break;
1617 case 2: /* Disable bits */
1618 if (cmd_len > 4) {
1619 sens->assert_enable &= ~cmd[4];
1621 if (cmd_len > 5) {
1622 sens->assert_enable &= ~(cmd[5] << 8);
1624 if (cmd_len > 6) {
1625 sens->deassert_enable &= ~cmd[6];
1627 if (cmd_len > 7) {
1628 sens->deassert_enable &= ~(cmd[7] << 8);
1630 break;
1631 case 3:
1632 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1633 return;
1635 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1638 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1639 uint8_t *cmd, unsigned int cmd_len,
1640 RspBuffer *rsp)
1642 IPMISensor *sens;
1644 if ((cmd[2] >= MAX_SENSORS) ||
1645 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1646 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1647 return;
1649 sens = ibs->sensors + cmd[2];
1650 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1651 rsp_buffer_push(rsp, sens->assert_enable & 0xff);
1652 rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
1653 rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
1654 rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
1657 static void rearm_sensor_evts(IPMIBmcSim *ibs,
1658 uint8_t *cmd, unsigned int cmd_len,
1659 RspBuffer *rsp)
1661 IPMISensor *sens;
1663 if ((cmd[2] >= MAX_SENSORS) ||
1664 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1665 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1666 return;
1668 sens = ibs->sensors + cmd[2];
1670 if ((cmd[3] & 0x80) == 0) {
1671 /* Just clear everything */
1672 sens->states = 0;
1673 return;
1677 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1678 uint8_t *cmd, unsigned int cmd_len,
1679 RspBuffer *rsp)
1681 IPMISensor *sens;
1683 if ((cmd[2] >= MAX_SENSORS) ||
1684 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1685 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1686 return;
1688 sens = ibs->sensors + cmd[2];
1689 rsp_buffer_push(rsp, sens->reading);
1690 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1691 rsp_buffer_push(rsp, sens->assert_states & 0xff);
1692 rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
1693 rsp_buffer_push(rsp, sens->deassert_states & 0xff);
1694 rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
1697 static void get_sensor_reading(IPMIBmcSim *ibs,
1698 uint8_t *cmd, unsigned int cmd_len,
1699 RspBuffer *rsp)
1701 IPMISensor *sens;
1703 if ((cmd[2] >= MAX_SENSORS) ||
1704 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1705 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1706 return;
1708 sens = ibs->sensors + cmd[2];
1709 rsp_buffer_push(rsp, sens->reading);
1710 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1711 rsp_buffer_push(rsp, sens->states & 0xff);
1712 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1713 rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
1717 static void set_sensor_type(IPMIBmcSim *ibs,
1718 uint8_t *cmd, unsigned int cmd_len,
1719 RspBuffer *rsp)
1721 IPMISensor *sens;
1724 if ((cmd[2] >= MAX_SENSORS) ||
1725 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1726 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1727 return;
1729 sens = ibs->sensors + cmd[2];
1730 sens->sensor_type = cmd[3];
1731 sens->evt_reading_type_code = cmd[4] & 0x7f;
1734 static void get_sensor_type(IPMIBmcSim *ibs,
1735 uint8_t *cmd, unsigned int cmd_len,
1736 RspBuffer *rsp)
1738 IPMISensor *sens;
1741 if ((cmd[2] >= MAX_SENSORS) ||
1742 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1743 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1744 return;
1746 sens = ibs->sensors + cmd[2];
1747 rsp_buffer_push(rsp, sens->sensor_type);
1748 rsp_buffer_push(rsp, sens->evt_reading_type_code);
1752 * bytes parameter
1753 * 1 sensor number
1754 * 2 operation (see below for bits meaning)
1755 * 3 sensor reading
1756 * 4:5 assertion states (optional)
1757 * 6:7 deassertion states (optional)
1758 * 8:10 event data 1,2,3 (optional)
1760 static void set_sensor_reading(IPMIBmcSim *ibs,
1761 uint8_t *cmd, unsigned int cmd_len,
1762 RspBuffer *rsp)
1764 IPMISensor *sens;
1765 uint8_t evd1 = 0;
1766 uint8_t evd2 = 0;
1767 uint8_t evd3 = 0;
1768 uint8_t new_reading = 0;
1769 uint16_t new_assert_states = 0;
1770 uint16_t new_deassert_states = 0;
1771 bool change_reading = false;
1772 bool change_assert = false;
1773 bool change_deassert = false;
1774 enum {
1775 SENSOR_GEN_EVENT_NONE,
1776 SENSOR_GEN_EVENT_DATA,
1777 SENSOR_GEN_EVENT_BMC,
1778 } do_gen_event = SENSOR_GEN_EVENT_NONE;
1780 if ((cmd[2] >= MAX_SENSORS) ||
1781 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1782 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1783 return;
1786 sens = ibs->sensors + cmd[2];
1788 /* [1:0] Sensor Reading operation */
1789 switch ((cmd[3]) & 0x3) {
1790 case 0: /* Do not change */
1791 break;
1792 case 1: /* write given value to sensor reading byte */
1793 new_reading = cmd[4];
1794 if (sens->reading != new_reading) {
1795 change_reading = true;
1797 break;
1798 case 2:
1799 case 3:
1800 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1801 return;
1804 /* [3:2] Deassertion bits operation */
1805 switch ((cmd[3] >> 2) & 0x3) {
1806 case 0: /* Do not change */
1807 break;
1808 case 1: /* write given value */
1809 if (cmd_len > 7) {
1810 new_deassert_states = cmd[7];
1811 change_deassert = true;
1813 if (cmd_len > 8) {
1814 new_deassert_states |= (cmd[8] << 8);
1816 break;
1818 case 2: /* mask on */
1819 if (cmd_len > 7) {
1820 new_deassert_states = (sens->deassert_states | cmd[7]);
1821 change_deassert = true;
1823 if (cmd_len > 8) {
1824 new_deassert_states |= (sens->deassert_states | (cmd[8] << 8));
1826 break;
1828 case 3: /* mask off */
1829 if (cmd_len > 7) {
1830 new_deassert_states = (sens->deassert_states & cmd[7]);
1831 change_deassert = true;
1833 if (cmd_len > 8) {
1834 new_deassert_states |= (sens->deassert_states & (cmd[8] << 8));
1836 break;
1839 if (change_deassert && (new_deassert_states == sens->deassert_states)) {
1840 change_deassert = false;
1843 /* [5:4] Assertion bits operation */
1844 switch ((cmd[3] >> 4) & 0x3) {
1845 case 0: /* Do not change */
1846 break;
1847 case 1: /* write given value */
1848 if (cmd_len > 5) {
1849 new_assert_states = cmd[5];
1850 change_assert = true;
1852 if (cmd_len > 6) {
1853 new_assert_states |= (cmd[6] << 8);
1855 break;
1857 case 2: /* mask on */
1858 if (cmd_len > 5) {
1859 new_assert_states = (sens->assert_states | cmd[5]);
1860 change_assert = true;
1862 if (cmd_len > 6) {
1863 new_assert_states |= (sens->assert_states | (cmd[6] << 8));
1865 break;
1867 case 3: /* mask off */
1868 if (cmd_len > 5) {
1869 new_assert_states = (sens->assert_states & cmd[5]);
1870 change_assert = true;
1872 if (cmd_len > 6) {
1873 new_assert_states |= (sens->assert_states & (cmd[6] << 8));
1875 break;
1878 if (change_assert && (new_assert_states == sens->assert_states)) {
1879 change_assert = false;
1882 if (cmd_len > 9) {
1883 evd1 = cmd[9];
1885 if (cmd_len > 10) {
1886 evd2 = cmd[10];
1888 if (cmd_len > 11) {
1889 evd3 = cmd[11];
1892 /* [7:6] Event Data Bytes operation */
1893 switch ((cmd[3] >> 6) & 0x3) {
1894 case 0: /*
1895 * Don’t use Event Data bytes from this command. BMC will
1896 * generate it's own Event Data bytes based on its sensor
1897 * implementation.
1899 evd1 = evd2 = evd3 = 0x0;
1900 do_gen_event = SENSOR_GEN_EVENT_BMC;
1901 break;
1902 case 1: /*
1903 * Write given values to event data bytes including bits
1904 * [3:0] Event Data 1.
1906 do_gen_event = SENSOR_GEN_EVENT_DATA;
1907 break;
1908 case 2: /*
1909 * Write given values to event data bytes excluding bits
1910 * [3:0] Event Data 1.
1912 evd1 &= 0xf0;
1913 do_gen_event = SENSOR_GEN_EVENT_DATA;
1914 break;
1915 case 3:
1916 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1917 return;
1921 * Event Data Bytes operation and parameter are inconsistent. The
1922 * Specs are not clear on that topic but generating an error seems
1923 * correct.
1925 if (do_gen_event == SENSOR_GEN_EVENT_DATA && cmd_len < 10) {
1926 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1927 return;
1930 /* commit values */
1931 if (change_reading) {
1932 sens->reading = new_reading;
1935 if (change_assert) {
1936 sens->assert_states = new_assert_states;
1939 if (change_deassert) {
1940 sens->deassert_states = new_deassert_states;
1943 /* TODO: handle threshold sensor */
1944 if (!IPMI_SENSOR_IS_DISCRETE(sens)) {
1945 return;
1948 switch (do_gen_event) {
1949 case SENSOR_GEN_EVENT_DATA: {
1950 unsigned int bit = evd1 & 0xf;
1951 uint16_t mask = (1 << bit);
1953 if (sens->assert_states & mask & sens->assert_enable) {
1954 gen_event(ibs, cmd[2], 0, evd1, evd2, evd3);
1957 if (sens->deassert_states & mask & sens->deassert_enable) {
1958 gen_event(ibs, cmd[2], 1, evd1, evd2, evd3);
1960 break;
1962 case SENSOR_GEN_EVENT_BMC:
1964 * TODO: generate event and event data bytes depending on the
1965 * sensor
1967 break;
1968 case SENSOR_GEN_EVENT_NONE:
1969 break;
1973 static const IPMICmdHandler chassis_cmds[] = {
1974 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
1975 [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
1976 [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
1977 [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
1979 static const IPMINetfn chassis_netfn = {
1980 .cmd_nums = ARRAY_SIZE(chassis_cmds),
1981 .cmd_handlers = chassis_cmds
1984 static const IPMICmdHandler sensor_event_cmds[] = {
1985 [IPMI_CMD_PLATFORM_EVENT_MSG] = { platform_event_msg, 10 },
1986 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
1987 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
1988 [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
1989 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
1990 [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
1991 [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
1992 [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
1993 [IPMI_CMD_SET_SENSOR_READING] = { set_sensor_reading, 5 },
1995 static const IPMINetfn sensor_event_netfn = {
1996 .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
1997 .cmd_handlers = sensor_event_cmds
2000 static const IPMICmdHandler app_cmds[] = {
2001 [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
2002 [IPMI_CMD_COLD_RESET] = { cold_reset },
2003 [IPMI_CMD_WARM_RESET] = { warm_reset },
2004 [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
2005 [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
2006 [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
2007 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
2008 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
2009 [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
2010 [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
2011 [IPMI_CMD_GET_MSG] = { get_msg },
2012 [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
2013 [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
2014 [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
2015 [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
2016 [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
2018 static const IPMINetfn app_netfn = {
2019 .cmd_nums = ARRAY_SIZE(app_cmds),
2020 .cmd_handlers = app_cmds
2023 static const IPMICmdHandler storage_cmds[] = {
2024 [IPMI_CMD_GET_FRU_AREA_INFO] = { get_fru_area_info, 3 },
2025 [IPMI_CMD_READ_FRU_DATA] = { read_fru_data, 5 },
2026 [IPMI_CMD_WRITE_FRU_DATA] = { write_fru_data, 5 },
2027 [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
2028 [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
2029 [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
2030 [IPMI_CMD_ADD_SDR] = { add_sdr },
2031 [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
2032 [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
2033 [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
2034 [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
2035 [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
2036 [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
2037 [IPMI_CMD_GET_SEL_TIME] = { get_sel_time },
2038 [IPMI_CMD_SET_SEL_TIME] = { set_sel_time, 6 },
2041 static const IPMINetfn storage_netfn = {
2042 .cmd_nums = ARRAY_SIZE(storage_cmds),
2043 .cmd_handlers = storage_cmds
2046 static void register_cmds(IPMIBmcSim *s)
2048 ipmi_sim_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
2049 ipmi_sim_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
2050 ipmi_sim_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
2051 ipmi_sim_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
2054 static uint8_t init_sdrs[] = {
2055 /* Watchdog device */
2056 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
2057 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
2058 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2059 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
2060 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
2063 static void ipmi_sdr_init(IPMIBmcSim *ibs)
2065 unsigned int i;
2066 int len;
2067 size_t sdrs_size;
2068 uint8_t *sdrs;
2070 sdrs_size = sizeof(init_sdrs);
2071 sdrs = init_sdrs;
2072 if (ibs->sdr_filename &&
2073 !g_file_get_contents(ibs->sdr_filename, (gchar **) &sdrs, &sdrs_size,
2074 NULL)) {
2075 error_report("failed to load sdr file '%s'", ibs->sdr_filename);
2076 sdrs_size = sizeof(init_sdrs);
2077 sdrs = init_sdrs;
2080 for (i = 0; i < sdrs_size; i += len) {
2081 struct ipmi_sdr_header *sdrh;
2083 if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
2084 error_report("Problem with recid 0x%4.4x", i);
2085 break;
2087 sdrh = (struct ipmi_sdr_header *) &sdrs[i];
2088 len = ipmi_sdr_length(sdrh);
2089 if (i + len > sdrs_size) {
2090 error_report("Problem with recid 0x%4.4x", i);
2091 break;
2093 sdr_add_entry(ibs, sdrh, len, NULL);
2096 if (sdrs != init_sdrs) {
2097 g_free(sdrs);
2101 static const VMStateDescription vmstate_ipmi_sim = {
2102 .name = TYPE_IPMI_BMC_SIMULATOR,
2103 .version_id = 1,
2104 .minimum_version_id = 1,
2105 .fields = (VMStateField[]) {
2106 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
2107 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
2108 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
2109 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
2110 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
2111 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
2112 VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
2113 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
2114 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
2115 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
2116 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
2117 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
2118 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
2119 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
2120 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
2121 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
2122 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
2123 IPMIBmcSim),
2124 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
2125 VMSTATE_END_OF_LIST()
2129 static void ipmi_fru_init(IPMIFru *fru)
2131 int fsize;
2132 int size = 0;
2134 if (!fru->filename) {
2135 goto out;
2138 fsize = get_image_size(fru->filename);
2139 if (fsize > 0) {
2140 size = QEMU_ALIGN_UP(fsize, fru->areasize);
2141 fru->data = g_malloc0(size);
2142 if (load_image_size(fru->filename, fru->data, fsize) != fsize) {
2143 error_report("Could not load file '%s'", fru->filename);
2144 g_free(fru->data);
2145 fru->data = NULL;
2149 out:
2150 if (!fru->data) {
2151 /* give one default FRU */
2152 size = fru->areasize;
2153 fru->data = g_malloc0(size);
2156 fru->nentries = size / fru->areasize;
2159 static void ipmi_sim_realize(DeviceState *dev, Error **errp)
2161 IPMIBmc *b = IPMI_BMC(dev);
2162 unsigned int i;
2163 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
2165 QTAILQ_INIT(&ibs->rcvbufs);
2167 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
2168 ibs->device_id = 0x20;
2169 ibs->ipmi_version = 0x02; /* IPMI 2.0 */
2170 ibs->restart_cause = 0;
2171 for (i = 0; i < 4; i++) {
2172 ibs->sel.last_addition[i] = 0xff;
2173 ibs->sel.last_clear[i] = 0xff;
2174 ibs->sdr.last_addition[i] = 0xff;
2175 ibs->sdr.last_clear[i] = 0xff;
2178 ipmi_sdr_init(ibs);
2180 ipmi_fru_init(&ibs->fru);
2182 ibs->acpi_power_state[0] = 0;
2183 ibs->acpi_power_state[1] = 0;
2185 ipmi_init_sensors_from_sdrs(ibs);
2186 register_cmds(ibs);
2188 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
2190 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
2193 static Property ipmi_sim_properties[] = {
2194 DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim, fru.areasize, 1024),
2195 DEFINE_PROP_STRING("frudatafile", IPMIBmcSim, fru.filename),
2196 DEFINE_PROP_STRING("sdrfile", IPMIBmcSim, sdr_filename),
2197 DEFINE_PROP_UINT8("device_id", IPMIBmcSim, device_id, 0x20),
2198 DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim, ipmi_version, 0x02),
2199 DEFINE_PROP_UINT8("device_rev", IPMIBmcSim, device_rev, 0),
2200 DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim, fwrev1, 0),
2201 DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim, fwrev2, 0),
2202 DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim, mfg_id, 0),
2203 DEFINE_PROP_UINT16("product_id", IPMIBmcSim, product_id, 0),
2204 DEFINE_PROP_UUID_NODEFAULT("guid", IPMIBmcSim, uuid),
2205 DEFINE_PROP_END_OF_LIST(),
2208 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
2210 DeviceClass *dc = DEVICE_CLASS(oc);
2211 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
2213 dc->hotpluggable = false;
2214 dc->realize = ipmi_sim_realize;
2215 device_class_set_props(dc, ipmi_sim_properties);
2216 bk->handle_command = ipmi_sim_handle_command;
2219 static const TypeInfo ipmi_sim_type = {
2220 .name = TYPE_IPMI_BMC_SIMULATOR,
2221 .parent = TYPE_IPMI_BMC,
2222 .instance_size = sizeof(IPMIBmcSim),
2223 .class_init = ipmi_sim_class_init,
2226 static void ipmi_sim_register_types(void)
2228 type_register_static(&ipmi_sim_type);
2231 type_init(ipmi_sim_register_types)