Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2019-12-17' into...
[qemu/ar7.git] / hw / ipmi / ipmi_bmc_sim.c
blob6670cf039d1a4b9fce898be306d8e29fcd095821
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
53 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
55 #define IPMI_CMD_GET_DEVICE_ID 0x01
56 #define IPMI_CMD_COLD_RESET 0x02
57 #define IPMI_CMD_WARM_RESET 0x03
58 #define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
59 #define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
60 #define IPMI_CMD_GET_DEVICE_GUID 0x08
61 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
62 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
63 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
64 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
65 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
66 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
67 #define IPMI_CMD_GET_MSG_FLAGS 0x31
68 #define IPMI_CMD_GET_MSG 0x33
69 #define IPMI_CMD_SEND_MSG 0x34
70 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
72 #define IPMI_NETFN_STORAGE 0x0a
74 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
75 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
76 #define IPMI_CMD_RESERVE_SDR_REP 0x22
77 #define IPMI_CMD_GET_SDR 0x23
78 #define IPMI_CMD_ADD_SDR 0x24
79 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
80 #define IPMI_CMD_DELETE_SDR 0x26
81 #define IPMI_CMD_CLEAR_SDR_REP 0x27
82 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
83 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
84 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
85 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
86 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
87 #define IPMI_CMD_GET_FRU_AREA_INFO 0x10
88 #define IPMI_CMD_READ_FRU_DATA 0x11
89 #define IPMI_CMD_WRITE_FRU_DATA 0x12
90 #define IPMI_CMD_GET_SEL_INFO 0x40
91 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
92 #define IPMI_CMD_RESERVE_SEL 0x42
93 #define IPMI_CMD_GET_SEL_ENTRY 0x43
94 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
95 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
96 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
97 #define IPMI_CMD_CLEAR_SEL 0x47
98 #define IPMI_CMD_GET_SEL_TIME 0x48
99 #define IPMI_CMD_SET_SEL_TIME 0x49
102 /* Same as a timespec struct. */
103 struct ipmi_time {
104 long tv_sec;
105 long tv_nsec;
108 #define MAX_SEL_SIZE 128
110 typedef struct IPMISel {
111 uint8_t sel[MAX_SEL_SIZE][16];
112 unsigned int next_free;
113 long time_offset;
114 uint16_t reservation;
115 uint8_t last_addition[4];
116 uint8_t last_clear[4];
117 uint8_t overflow;
118 } IPMISel;
120 #define MAX_SDR_SIZE 16384
122 typedef struct IPMISdr {
123 uint8_t sdr[MAX_SDR_SIZE];
124 unsigned int next_free;
125 uint16_t next_rec_id;
126 uint16_t reservation;
127 uint8_t last_addition[4];
128 uint8_t last_clear[4];
129 uint8_t overflow;
130 } IPMISdr;
132 typedef struct IPMIFru {
133 char *filename;
134 unsigned int nentries;
135 uint16_t areasize;
136 uint8_t *data;
137 } IPMIFru;
139 typedef struct IPMISensor {
140 uint8_t status;
141 uint8_t reading;
142 uint16_t states_suppt;
143 uint16_t assert_suppt;
144 uint16_t deassert_suppt;
145 uint16_t states;
146 uint16_t assert_states;
147 uint16_t deassert_states;
148 uint16_t assert_enable;
149 uint16_t deassert_enable;
150 uint8_t sensor_type;
151 uint8_t evt_reading_type_code;
152 } IPMISensor;
153 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
154 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
155 !!(v))
156 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
157 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
158 ((!!(v)) << 6))
159 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
160 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
161 ((!!(v)) << 7))
162 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
163 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
164 (v & 0xc0))
165 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
167 #define MAX_SENSORS 20
168 #define IPMI_WATCHDOG_SENSOR 0
170 #define MAX_NETFNS 64
172 typedef struct IPMIRcvBufEntry {
173 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
174 uint8_t len;
175 uint8_t buf[MAX_IPMI_MSG_SIZE];
176 } IPMIRcvBufEntry;
178 struct IPMIBmcSim {
179 IPMIBmc parent;
181 QEMUTimer *timer;
183 uint8_t bmc_global_enables;
184 uint8_t msg_flags;
186 bool watchdog_initialized;
187 uint8_t watchdog_use;
188 uint8_t watchdog_action;
189 uint8_t watchdog_pretimeout; /* In seconds */
190 bool watchdog_expired;
191 uint16_t watchdog_timeout; /* in 100's of milliseconds */
193 bool watchdog_running;
194 bool watchdog_preaction_ran;
195 int64_t watchdog_expiry;
197 uint8_t device_id;
198 uint8_t ipmi_version;
199 uint8_t device_rev;
200 uint8_t fwrev1;
201 uint8_t fwrev2;
202 uint32_t mfg_id;
203 uint16_t product_id;
205 uint8_t restart_cause;
207 uint8_t acpi_power_state[2];
208 QemuUUID uuid;
210 IPMISel sel;
211 IPMISdr sdr;
212 IPMIFru fru;
213 IPMISensor sensors[MAX_SENSORS];
214 char *sdr_filename;
216 /* Odd netfns are for responses, so we only need the even ones. */
217 const IPMINetfn *netfns[MAX_NETFNS / 2];
219 /* We allow one event in the buffer */
220 uint8_t evtbuf[16];
222 QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
225 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
226 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
227 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
228 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
229 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
230 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
231 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
232 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
233 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
235 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
236 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
237 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
238 #define IPMI_BMC_EVENT_LOG_BIT 3
239 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
240 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
241 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
242 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
243 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
244 (1 << IPMI_BMC_EVENT_LOG_BIT))
245 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
246 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
248 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
249 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
250 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
251 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
252 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
253 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
254 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
255 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
256 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
257 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
258 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
259 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
260 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
261 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
262 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
264 #define RSP_BUFFER_INITIALIZER { }
266 static inline void rsp_buffer_pushmore(RspBuffer *rsp, uint8_t *bytes,
267 unsigned int n)
269 if (rsp->len + n >= sizeof(rsp->buffer)) {
270 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
271 return;
274 memcpy(&rsp->buffer[rsp->len], bytes, n);
275 rsp->len += n;
278 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
280 static void ipmi_gettime(struct ipmi_time *time)
282 int64_t stime;
284 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
285 time->tv_sec = stime / 1000000000LL;
286 time->tv_nsec = stime % 1000000000LL;
289 static int64_t ipmi_getmonotime(void)
291 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
294 static void ipmi_timeout(void *opaque)
296 IPMIBmcSim *ibs = opaque;
298 ipmi_sim_handle_timeout(ibs);
301 static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
303 unsigned int val;
304 struct ipmi_time now;
306 ipmi_gettime(&now);
307 val = now.tv_sec + ibs->sel.time_offset;
308 ts[0] = val & 0xff;
309 ts[1] = (val >> 8) & 0xff;
310 ts[2] = (val >> 16) & 0xff;
311 ts[3] = (val >> 24) & 0xff;
314 static void sdr_inc_reservation(IPMISdr *sdr)
316 sdr->reservation++;
317 if (sdr->reservation == 0) {
318 sdr->reservation = 1;
322 static int sdr_add_entry(IPMIBmcSim *ibs,
323 const struct ipmi_sdr_header *sdrh_entry,
324 unsigned int len, uint16_t *recid)
326 struct ipmi_sdr_header *sdrh =
327 (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
329 if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
330 return 1;
333 if (ipmi_sdr_length(sdrh_entry) != len) {
334 return 1;
337 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
338 ibs->sdr.overflow = 1;
339 return 1;
342 memcpy(sdrh, sdrh_entry, len);
343 sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff;
344 sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
345 sdrh->sdr_version = 0x51; /* Conform to IPMI 1.5 spec */
347 if (recid) {
348 *recid = ibs->sdr.next_rec_id;
350 ibs->sdr.next_rec_id++;
351 set_timestamp(ibs, ibs->sdr.last_addition);
352 ibs->sdr.next_free += len;
353 sdr_inc_reservation(&ibs->sdr);
354 return 0;
357 static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
358 unsigned int *retpos, uint16_t *nextrec)
360 unsigned int pos = *retpos;
362 while (pos < sdr->next_free) {
363 struct ipmi_sdr_header *sdrh =
364 (struct ipmi_sdr_header *) &sdr->sdr[pos];
365 uint16_t trec = ipmi_sdr_recid(sdrh);
366 unsigned int nextpos = pos + ipmi_sdr_length(sdrh);
368 if (trec == recid) {
369 if (nextrec) {
370 if (nextpos >= sdr->next_free) {
371 *nextrec = 0xffff;
372 } else {
373 *nextrec = (sdr->sdr[nextpos] |
374 (sdr->sdr[nextpos + 1] << 8));
377 *retpos = pos;
378 return 0;
380 pos = nextpos;
382 return 1;
385 int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
386 const struct ipmi_sdr_compact **sdr, uint16_t *nextrec)
389 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
390 unsigned int pos;
392 pos = 0;
393 if (sdr_find_entry(&ibs->sdr, recid, &pos, nextrec)) {
394 return -1;
397 *sdr = (const struct ipmi_sdr_compact *) &ibs->sdr.sdr[pos];
398 return 0;
401 static void sel_inc_reservation(IPMISel *sel)
403 sel->reservation++;
404 if (sel->reservation == 0) {
405 sel->reservation = 1;
409 /* Returns 1 if the SEL is full and can't hold the event. */
410 static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
412 uint8_t ts[4];
414 event[0] = 0xff;
415 event[1] = 0xff;
416 set_timestamp(ibs, ts);
417 if (event[2] < 0xe0) { /* Don't set timestamps for type 0xe0-0xff. */
418 memcpy(event + 3, ts, 4);
420 if (ibs->sel.next_free == MAX_SEL_SIZE) {
421 ibs->sel.overflow = 1;
422 return 1;
424 event[0] = ibs->sel.next_free & 0xff;
425 event[1] = (ibs->sel.next_free >> 8) & 0xff;
426 memcpy(ibs->sel.last_addition, ts, 4);
427 memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
428 ibs->sel.next_free++;
429 sel_inc_reservation(&ibs->sel);
430 return 0;
433 static int attn_set(IPMIBmcSim *ibs)
435 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
436 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
437 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
440 static int attn_irq_enabled(IPMIBmcSim *ibs)
442 return (IPMI_BMC_MSG_INTS_ON(ibs) &&
443 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs) ||
444 IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs)))
445 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
446 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
449 void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log)
451 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
452 IPMIInterface *s = ibs->parent.intf;
453 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
455 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
456 return;
459 if (log && IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
460 sel_add_event(ibs, evt);
463 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
464 goto out;
467 memcpy(ibs->evtbuf, evt, 16);
468 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
469 k->set_atn(s, 1, attn_irq_enabled(ibs));
470 out:
471 return;
473 static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
474 uint8_t evd1, uint8_t evd2, uint8_t evd3)
476 IPMIInterface *s = ibs->parent.intf;
477 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
478 uint8_t evt[16];
479 IPMISensor *sens = ibs->sensors + sens_num;
481 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
482 return;
484 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
485 return;
488 evt[2] = 0x2; /* System event record */
489 evt[7] = ibs->parent.slave_addr;
490 evt[8] = 0;
491 evt[9] = 0x04; /* Format version */
492 evt[10] = sens->sensor_type;
493 evt[11] = sens_num;
494 evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
495 evt[13] = evd1;
496 evt[14] = evd2;
497 evt[15] = evd3;
499 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
500 sel_add_event(ibs, evt);
503 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
504 return;
507 memcpy(ibs->evtbuf, evt, 16);
508 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
509 k->set_atn(s, 1, attn_irq_enabled(ibs));
512 static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
513 unsigned int bit, unsigned int val,
514 uint8_t evd1, uint8_t evd2, uint8_t evd3)
516 IPMISensor *sens;
517 uint16_t mask;
519 if (sensor >= MAX_SENSORS) {
520 return;
522 if (bit >= 16) {
523 return;
526 mask = (1 << bit);
527 sens = ibs->sensors + sensor;
528 if (val) {
529 sens->states |= mask & sens->states_suppt;
530 if (sens->assert_states & mask) {
531 return; /* Already asserted */
533 sens->assert_states |= mask & sens->assert_suppt;
534 if (sens->assert_enable & mask & sens->assert_states) {
535 /* Send an event on assert */
536 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
538 } else {
539 sens->states &= ~(mask & sens->states_suppt);
540 if (sens->deassert_states & mask) {
541 return; /* Already deasserted */
543 sens->deassert_states |= mask & sens->deassert_suppt;
544 if (sens->deassert_enable & mask & sens->deassert_states) {
545 /* Send an event on deassert */
546 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
551 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
553 unsigned int i, pos;
554 IPMISensor *sens;
556 for (i = 0; i < MAX_SENSORS; i++) {
557 memset(s->sensors + i, 0, sizeof(*sens));
560 pos = 0;
561 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
562 struct ipmi_sdr_compact *sdr =
563 (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
564 unsigned int len = sdr->header.rec_length;
566 if (len < 20) {
567 continue;
569 if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
570 continue; /* Not a sensor SDR we set from */
573 if (sdr->sensor_owner_number >= MAX_SENSORS) {
574 continue;
576 sens = s->sensors + sdr->sensor_owner_number;
578 IPMI_SENSOR_SET_PRESENT(sens, 1);
579 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
580 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
581 sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
582 sens->deassert_suppt =
583 sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
584 sens->states_suppt =
585 sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
586 sens->sensor_type = sdr->sensor_type;
587 sens->evt_reading_type_code = sdr->reading_type & 0x7f;
589 /* Enable all the events that are supported. */
590 sens->assert_enable = sens->assert_suppt;
591 sens->deassert_enable = sens->deassert_suppt;
595 int ipmi_sim_register_netfn(IPMIBmcSim *s, unsigned int netfn,
596 const IPMINetfn *netfnd)
598 if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
599 return -1;
601 s->netfns[netfn / 2] = netfnd;
602 return 0;
605 static const IPMICmdHandler *ipmi_get_handler(IPMIBmcSim *ibs,
606 unsigned int netfn,
607 unsigned int cmd)
609 const IPMICmdHandler *hdl;
611 if (netfn & 1 || netfn >= MAX_NETFNS || !ibs->netfns[netfn / 2]) {
612 return NULL;
615 if (cmd >= ibs->netfns[netfn / 2]->cmd_nums) {
616 return NULL;
619 hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd];
620 if (!hdl->cmd_handler) {
621 return NULL;
624 return hdl;
627 static void next_timeout(IPMIBmcSim *ibs)
629 int64_t next;
630 if (ibs->watchdog_running) {
631 next = ibs->watchdog_expiry;
632 } else {
633 /* Wait a minute */
634 next = ipmi_getmonotime() + 60 * 1000000000LL;
636 timer_mod_ns(ibs->timer, next);
639 static void ipmi_sim_handle_command(IPMIBmc *b,
640 uint8_t *cmd, unsigned int cmd_len,
641 unsigned int max_cmd_len,
642 uint8_t msg_id)
644 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
645 IPMIInterface *s = ibs->parent.intf;
646 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
647 const IPMICmdHandler *hdl;
648 RspBuffer rsp = RSP_BUFFER_INITIALIZER;
650 /* Set up the response, set the low bit of NETFN. */
651 /* Note that max_rsp_len must be at least 3 */
652 if (sizeof(rsp.buffer) < 3) {
653 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
654 goto out;
657 rsp_buffer_push(&rsp, cmd[0] | 0x04);
658 rsp_buffer_push(&rsp, cmd[1]);
659 rsp_buffer_push(&rsp, 0); /* Assume success */
661 /* If it's too short or it was truncated, return an error. */
662 if (cmd_len < 2) {
663 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
664 goto out;
666 if (cmd_len > max_cmd_len) {
667 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
668 goto out;
671 if ((cmd[0] & 0x03) != 0) {
672 /* Only have stuff on LUN 0 */
673 rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN);
674 goto out;
677 hdl = ipmi_get_handler(ibs, cmd[0] >> 2, cmd[1]);
678 if (!hdl) {
679 rsp_buffer_set_error(&rsp, IPMI_CC_INVALID_CMD);
680 goto out;
683 if (cmd_len < hdl->cmd_len_min) {
684 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
685 goto out;
688 hdl->cmd_handler(ibs, cmd, cmd_len, &rsp);
690 out:
691 k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
693 next_timeout(ibs);
696 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
698 IPMIInterface *s = ibs->parent.intf;
699 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
701 if (!ibs->watchdog_running) {
702 goto out;
705 if (!ibs->watchdog_preaction_ran) {
706 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
707 case IPMI_BMC_WATCHDOG_PRE_NMI:
708 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
709 k->do_hw_op(s, IPMI_SEND_NMI, 0);
710 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
711 0xc8, (2 << 4) | 0xf, 0xff);
712 break;
714 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
715 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
716 k->set_atn(s, 1, attn_irq_enabled(ibs));
717 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
718 0xc8, (3 << 4) | 0xf, 0xff);
719 break;
721 default:
722 goto do_full_expiry;
725 ibs->watchdog_preaction_ran = 1;
726 /* Issued the pretimeout, do the rest of the timeout now. */
727 ibs->watchdog_expiry = ipmi_getmonotime();
728 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
729 goto out;
732 do_full_expiry:
733 ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
734 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
735 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
736 case IPMI_BMC_WATCHDOG_ACTION_NONE:
737 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
738 0xc0, ibs->watchdog_use & 0xf, 0xff);
739 break;
741 case IPMI_BMC_WATCHDOG_ACTION_RESET:
742 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
743 0xc1, ibs->watchdog_use & 0xf, 0xff);
744 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
745 break;
747 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
748 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
749 0xc2, ibs->watchdog_use & 0xf, 0xff);
750 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
751 break;
753 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
754 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
755 0xc3, ibs->watchdog_use & 0xf, 0xff);
756 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
757 break;
760 out:
761 next_timeout(ibs);
764 static void chassis_capabilities(IPMIBmcSim *ibs,
765 uint8_t *cmd, unsigned int cmd_len,
766 RspBuffer *rsp)
768 rsp_buffer_push(rsp, 0);
769 rsp_buffer_push(rsp, ibs->parent.slave_addr);
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);
775 static void chassis_status(IPMIBmcSim *ibs,
776 uint8_t *cmd, unsigned int cmd_len,
777 RspBuffer *rsp)
779 rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */
780 rsp_buffer_push(rsp, 0);
781 rsp_buffer_push(rsp, 0);
782 rsp_buffer_push(rsp, 0);
785 static void chassis_control(IPMIBmcSim *ibs,
786 uint8_t *cmd, unsigned int cmd_len,
787 RspBuffer *rsp)
789 IPMIInterface *s = ibs->parent.intf;
790 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
792 switch (cmd[2] & 0xf) {
793 case 0: /* power down */
794 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0));
795 break;
796 case 1: /* power up */
797 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0));
798 break;
799 case 2: /* power cycle */
800 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0));
801 break;
802 case 3: /* hard reset */
803 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0));
804 break;
805 case 4: /* pulse diagnostic interrupt */
806 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0));
807 break;
808 case 5: /* soft shutdown via ACPI by overtemp emulation */
809 rsp_buffer_set_error(rsp, k->do_hw_op(s,
810 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0));
811 break;
812 default:
813 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
814 return;
818 static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
819 uint8_t *cmd, unsigned int cmd_len,
820 RspBuffer *rsp)
823 rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */
824 rsp_buffer_push(rsp, 0); /* Channel 0 */
827 static void get_device_id(IPMIBmcSim *ibs,
828 uint8_t *cmd, unsigned int cmd_len,
829 RspBuffer *rsp)
831 rsp_buffer_push(rsp, ibs->device_id);
832 rsp_buffer_push(rsp, ibs->device_rev & 0xf);
833 rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
834 rsp_buffer_push(rsp, ibs->fwrev2);
835 rsp_buffer_push(rsp, ibs->ipmi_version);
836 rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */
837 rsp_buffer_push(rsp, ibs->mfg_id & 0xff);
838 rsp_buffer_push(rsp, (ibs->mfg_id >> 8) & 0xff);
839 rsp_buffer_push(rsp, (ibs->mfg_id >> 16) & 0xff);
840 rsp_buffer_push(rsp, ibs->product_id & 0xff);
841 rsp_buffer_push(rsp, (ibs->product_id >> 8) & 0xff);
844 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
846 IPMIInterface *s = ibs->parent.intf;
847 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
848 bool irqs_on;
850 ibs->bmc_global_enables = val;
852 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
853 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
855 k->set_irq_enable(s, irqs_on);
858 static void cold_reset(IPMIBmcSim *ibs,
859 uint8_t *cmd, unsigned int cmd_len,
860 RspBuffer *rsp)
862 IPMIInterface *s = ibs->parent.intf;
863 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
865 /* Disable all interrupts */
866 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
868 if (k->reset) {
869 k->reset(s, true);
873 static void warm_reset(IPMIBmcSim *ibs,
874 uint8_t *cmd, unsigned int cmd_len,
875 RspBuffer *rsp)
877 IPMIInterface *s = ibs->parent.intf;
878 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
880 if (k->reset) {
881 k->reset(s, false);
884 static void set_acpi_power_state(IPMIBmcSim *ibs,
885 uint8_t *cmd, unsigned int cmd_len,
886 RspBuffer *rsp)
888 ibs->acpi_power_state[0] = cmd[2];
889 ibs->acpi_power_state[1] = cmd[3];
892 static void get_acpi_power_state(IPMIBmcSim *ibs,
893 uint8_t *cmd, unsigned int cmd_len,
894 RspBuffer *rsp)
896 rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
897 rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
900 static void get_device_guid(IPMIBmcSim *ibs,
901 uint8_t *cmd, unsigned int cmd_len,
902 RspBuffer *rsp)
904 unsigned int i;
906 /* An uninitialized uuid is all zeros, use that to know if it is set. */
907 for (i = 0; i < 16; i++) {
908 if (ibs->uuid.data[i]) {
909 goto uuid_set;
912 /* No uuid is set, return an error. */
913 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_CMD);
914 return;
916 uuid_set:
917 for (i = 0; i < 16; i++) {
918 rsp_buffer_push(rsp, ibs->uuid.data[i]);
922 static void set_bmc_global_enables(IPMIBmcSim *ibs,
923 uint8_t *cmd, unsigned int cmd_len,
924 RspBuffer *rsp)
926 set_global_enables(ibs, cmd[2]);
929 static void get_bmc_global_enables(IPMIBmcSim *ibs,
930 uint8_t *cmd, unsigned int cmd_len,
931 RspBuffer *rsp)
933 rsp_buffer_push(rsp, ibs->bmc_global_enables);
936 static void clr_msg_flags(IPMIBmcSim *ibs,
937 uint8_t *cmd, unsigned int cmd_len,
938 RspBuffer *rsp)
940 IPMIInterface *s = ibs->parent.intf;
941 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
943 ibs->msg_flags &= ~cmd[2];
944 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
947 static void get_msg_flags(IPMIBmcSim *ibs,
948 uint8_t *cmd, unsigned int cmd_len,
949 RspBuffer *rsp)
951 rsp_buffer_push(rsp, ibs->msg_flags);
954 static void read_evt_msg_buf(IPMIBmcSim *ibs,
955 uint8_t *cmd, unsigned int cmd_len,
956 RspBuffer *rsp)
958 IPMIInterface *s = ibs->parent.intf;
959 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
960 unsigned int i;
962 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
963 rsp_buffer_set_error(rsp, 0x80);
964 return;
966 for (i = 0; i < 16; i++) {
967 rsp_buffer_push(rsp, ibs->evtbuf[i]);
969 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
970 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
973 static void get_msg(IPMIBmcSim *ibs,
974 uint8_t *cmd, unsigned int cmd_len,
975 RspBuffer *rsp)
977 IPMIRcvBufEntry *msg;
979 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
980 rsp_buffer_set_error(rsp, 0x80); /* Queue empty */
981 goto out;
983 rsp_buffer_push(rsp, 0); /* Channel 0 */
984 msg = QTAILQ_FIRST(&ibs->rcvbufs);
985 rsp_buffer_pushmore(rsp, msg->buf, msg->len);
986 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
987 g_free(msg);
989 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
990 IPMIInterface *s = ibs->parent.intf;
991 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
993 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
994 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
997 out:
998 return;
1001 static unsigned char
1002 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
1004 for (; size > 0; size--, data++) {
1005 csum += *data;
1008 return -csum;
1011 static void send_msg(IPMIBmcSim *ibs,
1012 uint8_t *cmd, unsigned int cmd_len,
1013 RspBuffer *rsp)
1015 IPMIInterface *s = ibs->parent.intf;
1016 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1017 IPMIRcvBufEntry *msg;
1018 uint8_t *buf;
1019 uint8_t netfn, rqLun, rsLun, rqSeq;
1021 if (cmd[2] != 0) {
1022 /* We only handle channel 0 with no options */
1023 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1024 return;
1027 if (cmd_len < 10) {
1028 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
1029 return;
1032 if (cmd[3] != 0x40) {
1033 /* We only emulate a MC at address 0x40. */
1034 rsp_buffer_set_error(rsp, 0x83); /* NAK on write */
1035 return;
1038 cmd += 3; /* Skip the header. */
1039 cmd_len -= 3;
1042 * At this point we "send" the message successfully. Any error will
1043 * be returned in the response.
1045 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
1046 cmd[3] != 0x20) { /* Improper response address */
1047 return; /* No response */
1050 netfn = cmd[1] >> 2;
1051 rqLun = cmd[4] & 0x3;
1052 rsLun = cmd[1] & 0x3;
1053 rqSeq = cmd[4] >> 2;
1055 if (rqLun != 2) {
1056 /* We only support LUN 2 coming back to us. */
1057 return;
1060 msg = g_malloc(sizeof(*msg));
1061 msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
1062 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
1063 msg->buf[2] = cmd[0]; /* rsSA */
1064 msg->buf[3] = (rqSeq << 2) | rsLun;
1065 msg->buf[4] = cmd[5]; /* Cmd */
1066 msg->buf[5] = 0; /* Completion Code */
1067 msg->len = 6;
1069 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
1070 /* Not a command we handle. */
1071 msg->buf[5] = IPMI_CC_INVALID_CMD;
1072 goto end_msg;
1075 buf = msg->buf + msg->len; /* After the CC */
1076 buf[0] = 0;
1077 buf[1] = 0;
1078 buf[2] = 0;
1079 buf[3] = 0;
1080 buf[4] = 0x51;
1081 buf[5] = 0;
1082 buf[6] = 0;
1083 buf[7] = 0;
1084 buf[8] = 0;
1085 buf[9] = 0;
1086 buf[10] = 0;
1087 msg->len += 11;
1089 end_msg:
1090 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1091 msg->len++;
1092 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1093 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1094 k->set_atn(s, 1, attn_irq_enabled(ibs));
1097 static void do_watchdog_reset(IPMIBmcSim *ibs)
1099 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1100 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1101 ibs->watchdog_running = 0;
1102 return;
1104 ibs->watchdog_preaction_ran = 0;
1107 /* Timeout is in tenths of a second, offset is in seconds */
1108 ibs->watchdog_expiry = ipmi_getmonotime();
1109 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1110 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1111 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1113 ibs->watchdog_running = 1;
1116 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1117 uint8_t *cmd, unsigned int cmd_len,
1118 RspBuffer *rsp)
1120 if (!ibs->watchdog_initialized) {
1121 rsp_buffer_set_error(rsp, 0x80);
1122 return;
1124 do_watchdog_reset(ibs);
1127 static void set_watchdog_timer(IPMIBmcSim *ibs,
1128 uint8_t *cmd, unsigned int cmd_len,
1129 RspBuffer *rsp)
1131 IPMIInterface *s = ibs->parent.intf;
1132 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1133 unsigned int val;
1135 val = cmd[2] & 0x7; /* Validate use */
1136 if (val == 0 || val > 5) {
1137 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1138 return;
1140 val = cmd[3] & 0x7; /* Validate action */
1141 switch (val) {
1142 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1143 break;
1145 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1146 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1));
1147 break;
1149 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1150 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1));
1151 break;
1153 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1154 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1));
1155 break;
1157 default:
1158 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1160 if (rsp->buffer[2]) {
1161 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1162 return;
1165 val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1166 switch (val) {
1167 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1168 case IPMI_BMC_WATCHDOG_PRE_NONE:
1169 break;
1171 case IPMI_BMC_WATCHDOG_PRE_NMI:
1172 if (k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1173 /* NMI not supported. */
1174 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1175 return;
1177 break;
1179 default:
1180 /* We don't support PRE_SMI */
1181 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1182 return;
1185 ibs->watchdog_initialized = 1;
1186 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1187 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1188 ibs->watchdog_pretimeout = cmd[4];
1189 ibs->watchdog_expired &= ~cmd[5];
1190 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1191 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1192 do_watchdog_reset(ibs);
1193 } else {
1194 ibs->watchdog_running = 0;
1198 static void get_watchdog_timer(IPMIBmcSim *ibs,
1199 uint8_t *cmd, unsigned int cmd_len,
1200 RspBuffer *rsp)
1202 rsp_buffer_push(rsp, ibs->watchdog_use);
1203 rsp_buffer_push(rsp, ibs->watchdog_action);
1204 rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
1205 rsp_buffer_push(rsp, ibs->watchdog_expired);
1206 rsp_buffer_push(rsp, ibs->watchdog_timeout & 0xff);
1207 rsp_buffer_push(rsp, (ibs->watchdog_timeout >> 8) & 0xff);
1208 if (ibs->watchdog_running) {
1209 long timeout;
1210 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1211 / 100000000);
1212 rsp_buffer_push(rsp, timeout & 0xff);
1213 rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
1214 } else {
1215 rsp_buffer_push(rsp, 0);
1216 rsp_buffer_push(rsp, 0);
1220 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1221 uint8_t *cmd, unsigned int cmd_len,
1222 RspBuffer *rsp)
1224 unsigned int i;
1226 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */
1227 rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
1228 rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
1229 rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1230 rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1231 for (i = 0; i < 4; i++) {
1232 rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
1234 for (i = 0; i < 4; i++) {
1235 rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
1237 /* Only modal support, reserve supported */
1238 rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
1241 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1242 uint8_t *cmd, unsigned int cmd_len,
1243 RspBuffer *rsp)
1245 rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
1246 rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
1249 static void get_sdr(IPMIBmcSim *ibs,
1250 uint8_t *cmd, unsigned int cmd_len,
1251 RspBuffer *rsp)
1253 unsigned int pos;
1254 uint16_t nextrec;
1255 struct ipmi_sdr_header *sdrh;
1257 if (cmd[6]) {
1258 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1259 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1260 return;
1264 pos = 0;
1265 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1266 &pos, &nextrec)) {
1267 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1268 return;
1271 sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1273 if (cmd[6] > ipmi_sdr_length(sdrh)) {
1274 rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE);
1275 return;
1278 rsp_buffer_push(rsp, nextrec & 0xff);
1279 rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
1281 if (cmd[7] == 0xff) {
1282 cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1285 if ((cmd[7] + rsp->len) > sizeof(rsp->buffer)) {
1286 rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES);
1287 return;
1290 rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1293 static void add_sdr(IPMIBmcSim *ibs,
1294 uint8_t *cmd, unsigned int cmd_len,
1295 RspBuffer *rsp)
1297 uint16_t recid;
1298 struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1300 if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1301 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1302 return;
1304 rsp_buffer_push(rsp, recid & 0xff);
1305 rsp_buffer_push(rsp, (recid >> 8) & 0xff);
1308 static void clear_sdr_rep(IPMIBmcSim *ibs,
1309 uint8_t *cmd, unsigned int cmd_len,
1310 RspBuffer *rsp)
1312 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1313 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1314 return;
1317 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1318 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1319 return;
1321 if (cmd[7] == 0xaa) {
1322 ibs->sdr.next_free = 0;
1323 ibs->sdr.overflow = 0;
1324 set_timestamp(ibs, ibs->sdr.last_clear);
1325 rsp_buffer_push(rsp, 1); /* Erasure complete */
1326 sdr_inc_reservation(&ibs->sdr);
1327 } else if (cmd[7] == 0) {
1328 rsp_buffer_push(rsp, 1); /* Erasure complete */
1329 } else {
1330 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1331 return;
1335 static void get_sel_info(IPMIBmcSim *ibs,
1336 uint8_t *cmd, unsigned int cmd_len,
1337 RspBuffer *rsp)
1339 unsigned int i, val;
1341 rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */
1342 rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
1343 rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
1344 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1345 rsp_buffer_push(rsp, val & 0xff);
1346 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1347 for (i = 0; i < 4; i++) {
1348 rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
1350 for (i = 0; i < 4; i++) {
1351 rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
1353 /* Only support Reserve SEL */
1354 rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
1357 static void get_fru_area_info(IPMIBmcSim *ibs,
1358 uint8_t *cmd, unsigned int cmd_len,
1359 RspBuffer *rsp)
1361 uint8_t fruid;
1362 uint16_t fru_entry_size;
1364 fruid = cmd[2];
1366 if (fruid >= ibs->fru.nentries) {
1367 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1368 return;
1371 fru_entry_size = ibs->fru.areasize;
1373 rsp_buffer_push(rsp, fru_entry_size & 0xff);
1374 rsp_buffer_push(rsp, fru_entry_size >> 8 & 0xff);
1375 rsp_buffer_push(rsp, 0x0);
1378 static void read_fru_data(IPMIBmcSim *ibs,
1379 uint8_t *cmd, unsigned int cmd_len,
1380 RspBuffer *rsp)
1382 uint8_t fruid;
1383 uint16_t offset;
1384 int i;
1385 uint8_t *fru_entry;
1386 unsigned int count;
1388 fruid = cmd[2];
1389 offset = (cmd[3] | cmd[4] << 8);
1391 if (fruid >= ibs->fru.nentries) {
1392 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1393 return;
1396 if (offset >= ibs->fru.areasize - 1) {
1397 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1398 return;
1401 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1403 count = MIN(cmd[5], ibs->fru.areasize - offset);
1405 rsp_buffer_push(rsp, count & 0xff);
1406 for (i = 0; i < count; i++) {
1407 rsp_buffer_push(rsp, fru_entry[offset + i]);
1411 static void write_fru_data(IPMIBmcSim *ibs,
1412 uint8_t *cmd, unsigned int cmd_len,
1413 RspBuffer *rsp)
1415 uint8_t fruid;
1416 uint16_t offset;
1417 uint8_t *fru_entry;
1418 unsigned int count;
1420 fruid = cmd[2];
1421 offset = (cmd[3] | cmd[4] << 8);
1423 if (fruid >= ibs->fru.nentries) {
1424 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1425 return;
1428 if (offset >= ibs->fru.areasize - 1) {
1429 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1430 return;
1433 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1435 count = MIN(cmd_len - 5, ibs->fru.areasize - offset);
1437 memcpy(fru_entry + offset, cmd + 5, count);
1439 rsp_buffer_push(rsp, count & 0xff);
1442 static void reserve_sel(IPMIBmcSim *ibs,
1443 uint8_t *cmd, unsigned int cmd_len,
1444 RspBuffer *rsp)
1446 rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
1447 rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
1450 static void get_sel_entry(IPMIBmcSim *ibs,
1451 uint8_t *cmd, unsigned int cmd_len,
1452 RspBuffer *rsp)
1454 unsigned int val;
1456 if (cmd[6]) {
1457 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1458 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1459 return;
1462 if (ibs->sel.next_free == 0) {
1463 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1464 return;
1466 if (cmd[6] > 15) {
1467 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1468 return;
1470 if (cmd[7] == 0xff) {
1471 cmd[7] = 16;
1472 } else if ((cmd[7] + cmd[6]) > 16) {
1473 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1474 return;
1475 } else {
1476 cmd[7] += cmd[6];
1479 val = cmd[4] | (cmd[5] << 8);
1480 if (val == 0xffff) {
1481 val = ibs->sel.next_free - 1;
1482 } else if (val >= ibs->sel.next_free) {
1483 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1484 return;
1486 if ((val + 1) == ibs->sel.next_free) {
1487 rsp_buffer_push(rsp, 0xff);
1488 rsp_buffer_push(rsp, 0xff);
1489 } else {
1490 rsp_buffer_push(rsp, (val + 1) & 0xff);
1491 rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
1493 for (; cmd[6] < cmd[7]; cmd[6]++) {
1494 rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
1498 static void add_sel_entry(IPMIBmcSim *ibs,
1499 uint8_t *cmd, unsigned int cmd_len,
1500 RspBuffer *rsp)
1502 if (sel_add_event(ibs, cmd + 2)) {
1503 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1504 return;
1506 /* sel_add_event fills in the record number. */
1507 rsp_buffer_push(rsp, cmd[2]);
1508 rsp_buffer_push(rsp, cmd[3]);
1511 static void clear_sel(IPMIBmcSim *ibs,
1512 uint8_t *cmd, unsigned int cmd_len,
1513 RspBuffer *rsp)
1515 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1516 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1517 return;
1520 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1521 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1522 return;
1524 if (cmd[7] == 0xaa) {
1525 ibs->sel.next_free = 0;
1526 ibs->sel.overflow = 0;
1527 set_timestamp(ibs, ibs->sdr.last_clear);
1528 rsp_buffer_push(rsp, 1); /* Erasure complete */
1529 sel_inc_reservation(&ibs->sel);
1530 } else if (cmd[7] == 0) {
1531 rsp_buffer_push(rsp, 1); /* Erasure complete */
1532 } else {
1533 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1534 return;
1538 static void get_sel_time(IPMIBmcSim *ibs,
1539 uint8_t *cmd, unsigned int cmd_len,
1540 RspBuffer *rsp)
1542 uint32_t val;
1543 struct ipmi_time now;
1545 ipmi_gettime(&now);
1546 val = now.tv_sec + ibs->sel.time_offset;
1547 rsp_buffer_push(rsp, val & 0xff);
1548 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1549 rsp_buffer_push(rsp, (val >> 16) & 0xff);
1550 rsp_buffer_push(rsp, (val >> 24) & 0xff);
1553 static void set_sel_time(IPMIBmcSim *ibs,
1554 uint8_t *cmd, unsigned int cmd_len,
1555 RspBuffer *rsp)
1557 uint32_t val;
1558 struct ipmi_time now;
1560 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1561 ipmi_gettime(&now);
1562 ibs->sel.time_offset = now.tv_sec - ((long) val);
1565 static void platform_event_msg(IPMIBmcSim *ibs,
1566 uint8_t *cmd, unsigned int cmd_len,
1567 RspBuffer *rsp)
1569 uint8_t event[16];
1571 event[2] = 2; /* System event record */
1572 event[7] = cmd[2]; /* Generator ID */
1573 event[8] = 0;
1574 event[9] = cmd[3]; /* EvMRev */
1575 event[10] = cmd[4]; /* Sensor type */
1576 event[11] = cmd[5]; /* Sensor number */
1577 event[12] = cmd[6]; /* Event dir / Event type */
1578 event[13] = cmd[7]; /* Event data 1 */
1579 event[14] = cmd[8]; /* Event data 2 */
1580 event[15] = cmd[9]; /* Event data 3 */
1582 if (sel_add_event(ibs, event)) {
1583 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1587 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1588 uint8_t *cmd, unsigned int cmd_len,
1589 RspBuffer *rsp)
1591 IPMISensor *sens;
1593 if ((cmd[2] >= MAX_SENSORS) ||
1594 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1595 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1596 return;
1598 sens = ibs->sensors + cmd[2];
1599 switch ((cmd[3] >> 4) & 0x3) {
1600 case 0: /* Do not change */
1601 break;
1602 case 1: /* Enable bits */
1603 if (cmd_len > 4) {
1604 sens->assert_enable |= cmd[4];
1606 if (cmd_len > 5) {
1607 sens->assert_enable |= cmd[5] << 8;
1609 if (cmd_len > 6) {
1610 sens->deassert_enable |= cmd[6];
1612 if (cmd_len > 7) {
1613 sens->deassert_enable |= cmd[7] << 8;
1615 break;
1616 case 2: /* Disable bits */
1617 if (cmd_len > 4) {
1618 sens->assert_enable &= ~cmd[4];
1620 if (cmd_len > 5) {
1621 sens->assert_enable &= ~(cmd[5] << 8);
1623 if (cmd_len > 6) {
1624 sens->deassert_enable &= ~cmd[6];
1626 if (cmd_len > 7) {
1627 sens->deassert_enable &= ~(cmd[7] << 8);
1629 break;
1630 case 3:
1631 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1632 return;
1634 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1637 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1638 uint8_t *cmd, unsigned int cmd_len,
1639 RspBuffer *rsp)
1641 IPMISensor *sens;
1643 if ((cmd[2] >= MAX_SENSORS) ||
1644 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1645 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1646 return;
1648 sens = ibs->sensors + cmd[2];
1649 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1650 rsp_buffer_push(rsp, sens->assert_enable & 0xff);
1651 rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
1652 rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
1653 rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
1656 static void rearm_sensor_evts(IPMIBmcSim *ibs,
1657 uint8_t *cmd, unsigned int cmd_len,
1658 RspBuffer *rsp)
1660 IPMISensor *sens;
1662 if ((cmd[2] >= MAX_SENSORS) ||
1663 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1664 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1665 return;
1667 sens = ibs->sensors + cmd[2];
1669 if ((cmd[3] & 0x80) == 0) {
1670 /* Just clear everything */
1671 sens->states = 0;
1672 return;
1676 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1677 uint8_t *cmd, unsigned int cmd_len,
1678 RspBuffer *rsp)
1680 IPMISensor *sens;
1682 if ((cmd[2] >= MAX_SENSORS) ||
1683 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1684 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1685 return;
1687 sens = ibs->sensors + cmd[2];
1688 rsp_buffer_push(rsp, sens->reading);
1689 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1690 rsp_buffer_push(rsp, sens->assert_states & 0xff);
1691 rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
1692 rsp_buffer_push(rsp, sens->deassert_states & 0xff);
1693 rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
1696 static void get_sensor_reading(IPMIBmcSim *ibs,
1697 uint8_t *cmd, unsigned int cmd_len,
1698 RspBuffer *rsp)
1700 IPMISensor *sens;
1702 if ((cmd[2] >= MAX_SENSORS) ||
1703 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1704 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1705 return;
1707 sens = ibs->sensors + cmd[2];
1708 rsp_buffer_push(rsp, sens->reading);
1709 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1710 rsp_buffer_push(rsp, sens->states & 0xff);
1711 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1712 rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
1716 static void set_sensor_type(IPMIBmcSim *ibs,
1717 uint8_t *cmd, unsigned int cmd_len,
1718 RspBuffer *rsp)
1720 IPMISensor *sens;
1723 if ((cmd[2] >= MAX_SENSORS) ||
1724 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1725 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1726 return;
1728 sens = ibs->sensors + cmd[2];
1729 sens->sensor_type = cmd[3];
1730 sens->evt_reading_type_code = cmd[4] & 0x7f;
1733 static void get_sensor_type(IPMIBmcSim *ibs,
1734 uint8_t *cmd, unsigned int cmd_len,
1735 RspBuffer *rsp)
1737 IPMISensor *sens;
1740 if ((cmd[2] >= MAX_SENSORS) ||
1741 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1742 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1743 return;
1745 sens = ibs->sensors + cmd[2];
1746 rsp_buffer_push(rsp, sens->sensor_type);
1747 rsp_buffer_push(rsp, sens->evt_reading_type_code);
1751 static const IPMICmdHandler chassis_cmds[] = {
1752 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
1753 [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
1754 [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
1755 [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
1757 static const IPMINetfn chassis_netfn = {
1758 .cmd_nums = ARRAY_SIZE(chassis_cmds),
1759 .cmd_handlers = chassis_cmds
1762 static const IPMICmdHandler sensor_event_cmds[] = {
1763 [IPMI_CMD_PLATFORM_EVENT_MSG] = { platform_event_msg, 10 },
1764 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
1765 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
1766 [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
1767 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
1768 [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
1769 [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
1770 [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
1772 static const IPMINetfn sensor_event_netfn = {
1773 .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
1774 .cmd_handlers = sensor_event_cmds
1777 static const IPMICmdHandler app_cmds[] = {
1778 [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
1779 [IPMI_CMD_COLD_RESET] = { cold_reset },
1780 [IPMI_CMD_WARM_RESET] = { warm_reset },
1781 [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
1782 [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
1783 [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
1784 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
1785 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
1786 [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
1787 [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
1788 [IPMI_CMD_GET_MSG] = { get_msg },
1789 [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
1790 [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
1791 [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
1792 [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
1793 [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
1795 static const IPMINetfn app_netfn = {
1796 .cmd_nums = ARRAY_SIZE(app_cmds),
1797 .cmd_handlers = app_cmds
1800 static const IPMICmdHandler storage_cmds[] = {
1801 [IPMI_CMD_GET_FRU_AREA_INFO] = { get_fru_area_info, 3 },
1802 [IPMI_CMD_READ_FRU_DATA] = { read_fru_data, 5 },
1803 [IPMI_CMD_WRITE_FRU_DATA] = { write_fru_data, 5 },
1804 [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
1805 [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
1806 [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
1807 [IPMI_CMD_ADD_SDR] = { add_sdr },
1808 [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
1809 [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
1810 [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
1811 [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
1812 [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
1813 [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
1814 [IPMI_CMD_GET_SEL_TIME] = { get_sel_time },
1815 [IPMI_CMD_SET_SEL_TIME] = { set_sel_time, 6 },
1818 static const IPMINetfn storage_netfn = {
1819 .cmd_nums = ARRAY_SIZE(storage_cmds),
1820 .cmd_handlers = storage_cmds
1823 static void register_cmds(IPMIBmcSim *s)
1825 ipmi_sim_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
1826 ipmi_sim_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
1827 ipmi_sim_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
1828 ipmi_sim_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
1831 static uint8_t init_sdrs[] = {
1832 /* Watchdog device */
1833 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1834 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1835 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1836 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1837 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1840 static void ipmi_sdr_init(IPMIBmcSim *ibs)
1842 unsigned int i;
1843 int len;
1844 size_t sdrs_size;
1845 uint8_t *sdrs;
1847 sdrs_size = sizeof(init_sdrs);
1848 sdrs = init_sdrs;
1849 if (ibs->sdr_filename &&
1850 !g_file_get_contents(ibs->sdr_filename, (gchar **) &sdrs, &sdrs_size,
1851 NULL)) {
1852 error_report("failed to load sdr file '%s'", ibs->sdr_filename);
1853 sdrs_size = sizeof(init_sdrs);
1854 sdrs = init_sdrs;
1857 for (i = 0; i < sdrs_size; i += len) {
1858 struct ipmi_sdr_header *sdrh;
1860 if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
1861 error_report("Problem with recid 0x%4.4x", i);
1862 break;
1864 sdrh = (struct ipmi_sdr_header *) &sdrs[i];
1865 len = ipmi_sdr_length(sdrh);
1866 if (i + len > sdrs_size) {
1867 error_report("Problem with recid 0x%4.4x", i);
1868 break;
1870 sdr_add_entry(ibs, sdrh, len, NULL);
1873 if (sdrs != init_sdrs) {
1874 g_free(sdrs);
1878 static const VMStateDescription vmstate_ipmi_sim = {
1879 .name = TYPE_IPMI_BMC_SIMULATOR,
1880 .version_id = 1,
1881 .minimum_version_id = 1,
1882 .fields = (VMStateField[]) {
1883 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
1884 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
1885 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
1886 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
1887 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
1888 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
1889 VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
1890 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
1891 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
1892 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
1893 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
1894 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
1895 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
1896 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
1897 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
1898 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
1899 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
1900 IPMIBmcSim),
1901 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
1902 VMSTATE_END_OF_LIST()
1906 static void ipmi_fru_init(IPMIFru *fru)
1908 int fsize;
1909 int size = 0;
1911 if (!fru->filename) {
1912 goto out;
1915 fsize = get_image_size(fru->filename);
1916 if (fsize > 0) {
1917 size = QEMU_ALIGN_UP(fsize, fru->areasize);
1918 fru->data = g_malloc0(size);
1919 if (load_image_size(fru->filename, fru->data, fsize) != fsize) {
1920 error_report("Could not load file '%s'", fru->filename);
1921 g_free(fru->data);
1922 fru->data = NULL;
1926 out:
1927 if (!fru->data) {
1928 /* give one default FRU */
1929 size = fru->areasize;
1930 fru->data = g_malloc0(size);
1933 fru->nentries = size / fru->areasize;
1936 static void ipmi_sim_realize(DeviceState *dev, Error **errp)
1938 IPMIBmc *b = IPMI_BMC(dev);
1939 unsigned int i;
1940 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
1942 QTAILQ_INIT(&ibs->rcvbufs);
1944 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
1945 ibs->device_id = 0x20;
1946 ibs->ipmi_version = 0x02; /* IPMI 2.0 */
1947 ibs->restart_cause = 0;
1948 for (i = 0; i < 4; i++) {
1949 ibs->sel.last_addition[i] = 0xff;
1950 ibs->sel.last_clear[i] = 0xff;
1951 ibs->sdr.last_addition[i] = 0xff;
1952 ibs->sdr.last_clear[i] = 0xff;
1955 ipmi_sdr_init(ibs);
1957 ipmi_fru_init(&ibs->fru);
1959 ibs->acpi_power_state[0] = 0;
1960 ibs->acpi_power_state[1] = 0;
1962 ipmi_init_sensors_from_sdrs(ibs);
1963 register_cmds(ibs);
1965 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
1967 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
1970 static Property ipmi_sim_properties[] = {
1971 DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim, fru.areasize, 1024),
1972 DEFINE_PROP_STRING("frudatafile", IPMIBmcSim, fru.filename),
1973 DEFINE_PROP_STRING("sdrfile", IPMIBmcSim, sdr_filename),
1974 DEFINE_PROP_UINT8("device_id", IPMIBmcSim, device_id, 0x20),
1975 DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim, ipmi_version, 0x02),
1976 DEFINE_PROP_UINT8("device_rev", IPMIBmcSim, device_rev, 0),
1977 DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim, fwrev1, 0),
1978 DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim, fwrev2, 0),
1979 DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim, mfg_id, 0),
1980 DEFINE_PROP_UINT16("product_id", IPMIBmcSim, product_id, 0),
1981 DEFINE_PROP_UUID_NODEFAULT("guid", IPMIBmcSim, uuid),
1982 DEFINE_PROP_END_OF_LIST(),
1985 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
1987 DeviceClass *dc = DEVICE_CLASS(oc);
1988 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
1990 dc->hotpluggable = false;
1991 dc->realize = ipmi_sim_realize;
1992 dc->props = ipmi_sim_properties;
1993 bk->handle_command = ipmi_sim_handle_command;
1996 static const TypeInfo ipmi_sim_type = {
1997 .name = TYPE_IPMI_BMC_SIMULATOR,
1998 .parent = TYPE_IPMI_BMC,
1999 .instance_size = sizeof(IPMIBmcSim),
2000 .class_init = ipmi_sim_class_init,
2003 static void ipmi_sim_register_types(void)
2005 type_register_static(&ipmi_sim_type);
2008 type_init(ipmi_sim_register_types)