1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "qemu/osdep.h"
26#include "sysemu/sysemu.h"
27#include "qemu/timer.h"
28#include "hw/ipmi/ipmi.h"
29#include "qemu/error-report.h"
30#include "qemu/module.h"
31#include "hw/loader.h"
32#include "hw/qdev-properties.h"
33#include "hw/qdev-properties-system.h"
34#include "migration/vmstate.h"
35
36#define IPMI_NETFN_CHASSIS 0x00
37
38#define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
39#define IPMI_CMD_GET_CHASSIS_STATUS 0x01
40#define IPMI_CMD_CHASSIS_CONTROL 0x02
41#define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09
42
43#define IPMI_NETFN_SENSOR_EVENT 0x04
44
45#define IPMI_CMD_PLATFORM_EVENT_MSG 0x02
46#define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
47#define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
48#define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
49#define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
50#define IPMI_CMD_GET_SENSOR_READING 0x2d
51#define IPMI_CMD_SET_SENSOR_TYPE 0x2e
52#define IPMI_CMD_GET_SENSOR_TYPE 0x2f
53#define IPMI_CMD_SET_SENSOR_READING 0x30
54
55
56
57#define IPMI_CMD_GET_DEVICE_ID 0x01
58#define IPMI_CMD_COLD_RESET 0x02
59#define IPMI_CMD_WARM_RESET 0x03
60#define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
61#define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
62#define IPMI_CMD_GET_DEVICE_GUID 0x08
63#define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
64#define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
65#define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
66#define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
67#define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
68#define IPMI_CMD_CLR_MSG_FLAGS 0x30
69#define IPMI_CMD_GET_MSG_FLAGS 0x31
70#define IPMI_CMD_GET_MSG 0x33
71#define IPMI_CMD_SEND_MSG 0x34
72#define IPMI_CMD_READ_EVT_MSG_BUF 0x35
73
74#define IPMI_NETFN_STORAGE 0x0a
75
76#define IPMI_CMD_GET_SDR_REP_INFO 0x20
77#define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
78#define IPMI_CMD_RESERVE_SDR_REP 0x22
79#define IPMI_CMD_GET_SDR 0x23
80#define IPMI_CMD_ADD_SDR 0x24
81#define IPMI_CMD_PARTIAL_ADD_SDR 0x25
82#define IPMI_CMD_DELETE_SDR 0x26
83#define IPMI_CMD_CLEAR_SDR_REP 0x27
84#define IPMI_CMD_GET_SDR_REP_TIME 0x28
85#define IPMI_CMD_SET_SDR_REP_TIME 0x29
86#define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
87#define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
88#define IPMI_CMD_RUN_INIT_AGENT 0x2C
89#define IPMI_CMD_GET_FRU_AREA_INFO 0x10
90#define IPMI_CMD_READ_FRU_DATA 0x11
91#define IPMI_CMD_WRITE_FRU_DATA 0x12
92#define IPMI_CMD_GET_SEL_INFO 0x40
93#define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
94#define IPMI_CMD_RESERVE_SEL 0x42
95#define IPMI_CMD_GET_SEL_ENTRY 0x43
96#define IPMI_CMD_ADD_SEL_ENTRY 0x44
97#define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
98#define IPMI_CMD_DELETE_SEL_ENTRY 0x46
99#define IPMI_CMD_CLEAR_SEL 0x47
100#define IPMI_CMD_GET_SEL_TIME 0x48
101#define IPMI_CMD_SET_SEL_TIME 0x49
102
103
104
105struct ipmi_time {
106 long tv_sec;
107 long tv_nsec;
108};
109
110#define MAX_SEL_SIZE 128
111
112typedef struct IPMISel {
113 uint8_t sel[MAX_SEL_SIZE][16];
114 unsigned int next_free;
115 long time_offset;
116 uint16_t reservation;
117 uint8_t last_addition[4];
118 uint8_t last_clear[4];
119 uint8_t overflow;
120} IPMISel;
121
122#define MAX_SDR_SIZE 16384
123
124typedef struct IPMISdr {
125 uint8_t sdr[MAX_SDR_SIZE];
126 unsigned int next_free;
127 uint16_t next_rec_id;
128 uint16_t reservation;
129 uint8_t last_addition[4];
130 uint8_t last_clear[4];
131 uint8_t overflow;
132} IPMISdr;
133
134typedef struct IPMIFru {
135 char *filename;
136 unsigned int nentries;
137 uint16_t areasize;
138 uint8_t *data;
139} IPMIFru;
140
141typedef struct IPMISensor {
142 uint8_t status;
143 uint8_t reading;
144 uint16_t states_suppt;
145 uint16_t assert_suppt;
146 uint16_t deassert_suppt;
147 uint16_t states;
148 uint16_t assert_states;
149 uint16_t deassert_states;
150 uint16_t assert_enable;
151 uint16_t deassert_enable;
152 uint8_t sensor_type;
153 uint8_t evt_reading_type_code;
154} IPMISensor;
155#define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
156#define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
157 !!(v))
158#define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
159#define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
160 ((!!(v)) << 6))
161#define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
162#define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
163 ((!!(v)) << 7))
164#define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
165#define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
166 (v & 0xc0))
167#define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
168
169#define MAX_SENSORS 20
170#define IPMI_WATCHDOG_SENSOR 0
171
172#define MAX_NETFNS 64
173
174typedef struct IPMIRcvBufEntry {
175 QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
176 uint8_t len;
177 uint8_t buf[MAX_IPMI_MSG_SIZE];
178} IPMIRcvBufEntry;
179
180struct IPMIBmcSim {
181 IPMIBmc parent;
182
183 QEMUTimer *timer;
184
185 uint8_t bmc_global_enables;
186 uint8_t msg_flags;
187
188 bool watchdog_initialized;
189 uint8_t watchdog_use;
190 uint8_t watchdog_action;
191 uint8_t watchdog_pretimeout;
192 bool watchdog_expired;
193 uint16_t watchdog_timeout;
194
195 bool watchdog_running;
196 bool watchdog_preaction_ran;
197 int64_t watchdog_expiry;
198
199 uint8_t device_id;
200 uint8_t ipmi_version;
201 uint8_t device_rev;
202 uint8_t fwrev1;
203 uint8_t fwrev2;
204 uint32_t mfg_id;
205 uint16_t product_id;
206
207 uint8_t restart_cause;
208
209 uint8_t acpi_power_state[2];
210 QemuUUID uuid;
211
212 IPMISel sel;
213 IPMISdr sdr;
214 IPMIFru fru;
215 IPMISensor sensors[MAX_SENSORS];
216 char *sdr_filename;
217
218
219 const IPMINetfn *netfns[MAX_NETFNS / 2];
220
221
222 uint8_t evtbuf[16];
223
224 QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
225};
226
227#define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
228#define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
229#define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
230#define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
231 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
232#define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
233 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
234#define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
235 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
236
237#define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
238#define IPMI_BMC_EVBUF_FULL_INT_BIT 1
239#define IPMI_BMC_EVENT_MSG_BUF_BIT 2
240#define IPMI_BMC_EVENT_LOG_BIT 3
241#define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
242 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
243#define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
244 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
245#define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
246 (1 << IPMI_BMC_EVENT_LOG_BIT))
247#define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
248 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
249
250#define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
251#define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
252#define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
253#define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
254#define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
255#define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
256#define IPMI_BMC_WATCHDOG_PRE_NONE 0
257#define IPMI_BMC_WATCHDOG_PRE_SMI 1
258#define IPMI_BMC_WATCHDOG_PRE_NMI 2
259#define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
260#define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
261#define IPMI_BMC_WATCHDOG_ACTION_NONE 0
262#define IPMI_BMC_WATCHDOG_ACTION_RESET 1
263#define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
264#define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
265
266#define RSP_BUFFER_INITIALIZER { }
267
268static inline void rsp_buffer_pushmore(RspBuffer *rsp, uint8_t *bytes,
269 unsigned int n)
270{
271 if (rsp->len + n >= sizeof(rsp->buffer)) {
272 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
273 return;
274 }
275
276 memcpy(&rsp->buffer[rsp->len], bytes, n);
277 rsp->len += n;
278}
279
280static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
281
282static void ipmi_gettime(struct ipmi_time *time)
283{
284 int64_t stime;
285
286 stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
287 time->tv_sec = stime / 1000000000LL;
288 time->tv_nsec = stime % 1000000000LL;
289}
290
291static int64_t ipmi_getmonotime(void)
292{
293 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
294}
295
296static void ipmi_timeout(void *opaque)
297{
298 IPMIBmcSim *ibs = opaque;
299
300 ipmi_sim_handle_timeout(ibs);
301}
302
303static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
304{
305 unsigned int val;
306 struct ipmi_time now;
307
308 ipmi_gettime(&now);
309 val = now.tv_sec + ibs->sel.time_offset;
310 ts[0] = val & 0xff;
311 ts[1] = (val >> 8) & 0xff;
312 ts[2] = (val >> 16) & 0xff;
313 ts[3] = (val >> 24) & 0xff;
314}
315
316static void sdr_inc_reservation(IPMISdr *sdr)
317{
318 sdr->reservation++;
319 if (sdr->reservation == 0) {
320 sdr->reservation = 1;
321 }
322}
323
324static int sdr_add_entry(IPMIBmcSim *ibs,
325 const struct ipmi_sdr_header *sdrh_entry,
326 unsigned int len, uint16_t *recid)
327{
328 struct ipmi_sdr_header *sdrh =
329 (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
330
331 if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
332 return 1;
333 }
334
335 if (ipmi_sdr_length(sdrh_entry) != len) {
336 return 1;
337 }
338
339 if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
340 ibs->sdr.overflow = 1;
341 return 1;
342 }
343
344 memcpy(sdrh, sdrh_entry, len);
345 sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff;
346 sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
347 sdrh->sdr_version = 0x51;
348
349 if (recid) {
350 *recid = ibs->sdr.next_rec_id;
351 }
352 ibs->sdr.next_rec_id++;
353 set_timestamp(ibs, ibs->sdr.last_addition);
354 ibs->sdr.next_free += len;
355 sdr_inc_reservation(&ibs->sdr);
356 return 0;
357}
358
359static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
360 unsigned int *retpos, uint16_t *nextrec)
361{
362 unsigned int pos = *retpos;
363
364 while (pos < sdr->next_free) {
365 struct ipmi_sdr_header *sdrh =
366 (struct ipmi_sdr_header *) &sdr->sdr[pos];
367 uint16_t trec = ipmi_sdr_recid(sdrh);
368 unsigned int nextpos = pos + ipmi_sdr_length(sdrh);
369
370 if (trec == recid) {
371 if (nextrec) {
372 if (nextpos >= sdr->next_free) {
373 *nextrec = 0xffff;
374 } else {
375 *nextrec = (sdr->sdr[nextpos] |
376 (sdr->sdr[nextpos + 1] << 8));
377 }
378 }
379 *retpos = pos;
380 return 0;
381 }
382 pos = nextpos;
383 }
384 return 1;
385}
386
387int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
388 const struct ipmi_sdr_compact **sdr, uint16_t *nextrec)
389
390{
391 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
392 unsigned int pos;
393
394 pos = 0;
395 if (sdr_find_entry(&ibs->sdr, recid, &pos, nextrec)) {
396 return -1;
397 }
398
399 *sdr = (const struct ipmi_sdr_compact *) &ibs->sdr.sdr[pos];
400 return 0;
401}
402
403static void sel_inc_reservation(IPMISel *sel)
404{
405 sel->reservation++;
406 if (sel->reservation == 0) {
407 sel->reservation = 1;
408 }
409}
410
411
412static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
413{
414 uint8_t ts[4];
415
416 event[0] = 0xff;
417 event[1] = 0xff;
418 set_timestamp(ibs, ts);
419 if (event[2] < 0xe0) {
420 memcpy(event + 3, ts, 4);
421 }
422 if (ibs->sel.next_free == MAX_SEL_SIZE) {
423 ibs->sel.overflow = 1;
424 return 1;
425 }
426 event[0] = ibs->sel.next_free & 0xff;
427 event[1] = (ibs->sel.next_free >> 8) & 0xff;
428 memcpy(ibs->sel.last_addition, ts, 4);
429 memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
430 ibs->sel.next_free++;
431 sel_inc_reservation(&ibs->sel);
432 return 0;
433}
434
435static int attn_set(IPMIBmcSim *ibs)
436{
437 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
438 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
439 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
440}
441
442static int attn_irq_enabled(IPMIBmcSim *ibs)
443{
444 return (IPMI_BMC_MSG_INTS_ON(ibs) &&
445 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs) ||
446 IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs)))
447 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
448 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
449}
450
451void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log)
452{
453 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
454 IPMIInterface *s = ibs->parent.intf;
455 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
456
457 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
458 return;
459 }
460
461 if (log && IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
462 sel_add_event(ibs, evt);
463 }
464
465 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
466 goto out;
467 }
468
469 memcpy(ibs->evtbuf, evt, 16);
470 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
471 k->set_atn(s, 1, attn_irq_enabled(ibs));
472 out:
473 return;
474}
475static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
476 uint8_t evd1, uint8_t evd2, uint8_t evd3)
477{
478 IPMIInterface *s = ibs->parent.intf;
479 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
480 uint8_t evt[16];
481 IPMISensor *sens = ibs->sensors + sens_num;
482
483 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
484 return;
485 }
486 if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
487 return;
488 }
489
490 evt[2] = 0x2;
491 evt[7] = ibs->parent.slave_addr;
492 evt[8] = 0;
493 evt[9] = 0x04;
494 evt[10] = sens->sensor_type;
495 evt[11] = sens_num;
496 evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
497 evt[13] = evd1;
498 evt[14] = evd2;
499 evt[15] = evd3;
500
501 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
502 sel_add_event(ibs, evt);
503 }
504
505 if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
506 return;
507 }
508
509 memcpy(ibs->evtbuf, evt, 16);
510 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
511 k->set_atn(s, 1, attn_irq_enabled(ibs));
512}
513
514static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
515 unsigned int bit, unsigned int val,
516 uint8_t evd1, uint8_t evd2, uint8_t evd3)
517{
518 IPMISensor *sens;
519 uint16_t mask;
520
521 if (sensor >= MAX_SENSORS) {
522 return;
523 }
524 if (bit >= 16) {
525 return;
526 }
527
528 mask = (1 << bit);
529 sens = ibs->sensors + sensor;
530 if (val) {
531 sens->states |= mask & sens->states_suppt;
532 if (sens->assert_states & mask) {
533 return;
534 }
535 sens->assert_states |= mask & sens->assert_suppt;
536 if (sens->assert_enable & mask & sens->assert_states) {
537
538 gen_event(ibs, sensor, 0, evd1, evd2, evd3);
539 }
540 } else {
541 sens->states &= ~(mask & sens->states_suppt);
542 if (sens->deassert_states & mask) {
543 return;
544 }
545 sens->deassert_states |= mask & sens->deassert_suppt;
546 if (sens->deassert_enable & mask & sens->deassert_states) {
547
548 gen_event(ibs, sensor, 1, evd1, evd2, evd3);
549 }
550 }
551}
552
553static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
554{
555 unsigned int i, pos;
556 IPMISensor *sens;
557
558 for (i = 0; i < MAX_SENSORS; i++) {
559 memset(s->sensors + i, 0, sizeof(*sens));
560 }
561
562 pos = 0;
563 for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
564 struct ipmi_sdr_compact *sdr =
565 (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
566 unsigned int len = sdr->header.rec_length;
567
568 if (len < 20) {
569 continue;
570 }
571 if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
572 continue;
573 }
574
575 if (sdr->sensor_owner_number >= MAX_SENSORS) {
576 continue;
577 }
578 sens = s->sensors + sdr->sensor_owner_number;
579
580 IPMI_SENSOR_SET_PRESENT(sens, 1);
581 IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
582 IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
583 sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
584 sens->deassert_suppt =
585 sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
586 sens->states_suppt =
587 sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
588 sens->sensor_type = sdr->sensor_type;
589 sens->evt_reading_type_code = sdr->reading_type & 0x7f;
590
591
592 sens->assert_enable = sens->assert_suppt;
593 sens->deassert_enable = sens->deassert_suppt;
594 }
595}
596
597int ipmi_sim_register_netfn(IPMIBmcSim *s, unsigned int netfn,
598 const IPMINetfn *netfnd)
599{
600 if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
601 return -1;
602 }
603 s->netfns[netfn / 2] = netfnd;
604 return 0;
605}
606
607static const IPMICmdHandler *ipmi_get_handler(IPMIBmcSim *ibs,
608 unsigned int netfn,
609 unsigned int cmd)
610{
611 const IPMICmdHandler *hdl;
612
613 if (netfn & 1 || netfn >= MAX_NETFNS || !ibs->netfns[netfn / 2]) {
614 return NULL;
615 }
616
617 if (cmd >= ibs->netfns[netfn / 2]->cmd_nums) {
618 return NULL;
619 }
620
621 hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd];
622 if (!hdl->cmd_handler) {
623 return NULL;
624 }
625
626 return hdl;
627}
628
629static void next_timeout(IPMIBmcSim *ibs)
630{
631 int64_t next;
632 if (ibs->watchdog_running) {
633 next = ibs->watchdog_expiry;
634 } else {
635
636 next = ipmi_getmonotime() + 60 * 1000000000LL;
637 }
638 timer_mod_ns(ibs->timer, next);
639}
640
641static void ipmi_sim_handle_command(IPMIBmc *b,
642 uint8_t *cmd, unsigned int cmd_len,
643 unsigned int max_cmd_len,
644 uint8_t msg_id)
645{
646 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
647 IPMIInterface *s = ibs->parent.intf;
648 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
649 const IPMICmdHandler *hdl;
650 RspBuffer rsp = RSP_BUFFER_INITIALIZER;
651
652
653
654 if (sizeof(rsp.buffer) < 3) {
655 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
656 goto out;
657 }
658
659 rsp_buffer_push(&rsp, cmd[0] | 0x04);
660 rsp_buffer_push(&rsp, cmd[1]);
661 rsp_buffer_push(&rsp, 0);
662
663
664 if (cmd_len < 2) {
665 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
666 goto out;
667 }
668 if (cmd_len > max_cmd_len) {
669 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
670 goto out;
671 }
672
673 if ((cmd[0] & 0x03) != 0) {
674
675 rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN);
676 goto out;
677 }
678
679 hdl = ipmi_get_handler(ibs, cmd[0] >> 2, cmd[1]);
680 if (!hdl) {
681 rsp_buffer_set_error(&rsp, IPMI_CC_INVALID_CMD);
682 goto out;
683 }
684
685 if (cmd_len < hdl->cmd_len_min) {
686 rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
687 goto out;
688 }
689
690 hdl->cmd_handler(ibs, cmd, cmd_len, &rsp);
691
692 out:
693 k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
694
695 next_timeout(ibs);
696}
697
698static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
699{
700 IPMIInterface *s = ibs->parent.intf;
701 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
702
703 if (!ibs->watchdog_running) {
704 goto out;
705 }
706
707 if (!ibs->watchdog_preaction_ran) {
708 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
709 case IPMI_BMC_WATCHDOG_PRE_NMI:
710 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
711 k->do_hw_op(s, IPMI_SEND_NMI, 0);
712 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
713 0xc8, (2 << 4) | 0xf, 0xff);
714 break;
715
716 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
717 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
718 k->set_atn(s, 1, attn_irq_enabled(ibs));
719 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
720 0xc8, (3 << 4) | 0xf, 0xff);
721 break;
722
723 default:
724 goto do_full_expiry;
725 }
726
727 ibs->watchdog_preaction_ran = 1;
728
729 ibs->watchdog_expiry = ipmi_getmonotime();
730 ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
731 goto out;
732 }
733
734 do_full_expiry:
735 ibs->watchdog_running = 0;
736 ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
737 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
738 case IPMI_BMC_WATCHDOG_ACTION_NONE:
739 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
740 0xc0, ibs->watchdog_use & 0xf, 0xff);
741 break;
742
743 case IPMI_BMC_WATCHDOG_ACTION_RESET:
744 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
745 0xc1, ibs->watchdog_use & 0xf, 0xff);
746 k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
747 break;
748
749 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
750 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
751 0xc2, ibs->watchdog_use & 0xf, 0xff);
752 k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
753 break;
754
755 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
756 sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
757 0xc3, ibs->watchdog_use & 0xf, 0xff);
758 k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
759 break;
760 }
761
762 out:
763 next_timeout(ibs);
764}
765
766static void chassis_capabilities(IPMIBmcSim *ibs,
767 uint8_t *cmd, unsigned int cmd_len,
768 RspBuffer *rsp)
769{
770 rsp_buffer_push(rsp, 0);
771 rsp_buffer_push(rsp, ibs->parent.slave_addr);
772 rsp_buffer_push(rsp, ibs->parent.slave_addr);
773 rsp_buffer_push(rsp, ibs->parent.slave_addr);
774 rsp_buffer_push(rsp, ibs->parent.slave_addr);
775}
776
777static void chassis_status(IPMIBmcSim *ibs,
778 uint8_t *cmd, unsigned int cmd_len,
779 RspBuffer *rsp)
780{
781 rsp_buffer_push(rsp, 0x61);
782 rsp_buffer_push(rsp, 0);
783 rsp_buffer_push(rsp, 0);
784 rsp_buffer_push(rsp, 0);
785}
786
787static void chassis_control(IPMIBmcSim *ibs,
788 uint8_t *cmd, unsigned int cmd_len,
789 RspBuffer *rsp)
790{
791 IPMIInterface *s = ibs->parent.intf;
792 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
793
794 switch (cmd[2] & 0xf) {
795 case 0:
796 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0));
797 break;
798 case 1:
799 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0));
800 break;
801 case 2:
802 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0));
803 break;
804 case 3:
805 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0));
806 break;
807 case 4:
808 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0));
809 break;
810 case 5:
811 rsp_buffer_set_error(rsp, k->do_hw_op(s,
812 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0));
813 break;
814 default:
815 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
816 return;
817 }
818}
819
820static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
821 uint8_t *cmd, unsigned int cmd_len,
822 RspBuffer *rsp)
823
824{
825 rsp_buffer_push(rsp, ibs->restart_cause & 0xf);
826 rsp_buffer_push(rsp, 0);
827}
828
829static void get_device_id(IPMIBmcSim *ibs,
830 uint8_t *cmd, unsigned int cmd_len,
831 RspBuffer *rsp)
832{
833 rsp_buffer_push(rsp, ibs->device_id);
834 rsp_buffer_push(rsp, ibs->device_rev & 0xf);
835 rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
836 rsp_buffer_push(rsp, ibs->fwrev2);
837 rsp_buffer_push(rsp, ibs->ipmi_version);
838 rsp_buffer_push(rsp, 0x07);
839 rsp_buffer_push(rsp, ibs->mfg_id & 0xff);
840 rsp_buffer_push(rsp, (ibs->mfg_id >> 8) & 0xff);
841 rsp_buffer_push(rsp, (ibs->mfg_id >> 16) & 0xff);
842 rsp_buffer_push(rsp, ibs->product_id & 0xff);
843 rsp_buffer_push(rsp, (ibs->product_id >> 8) & 0xff);
844}
845
846static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
847{
848 IPMIInterface *s = ibs->parent.intf;
849 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
850 bool irqs_on;
851
852 ibs->bmc_global_enables = val;
853
854 irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
855 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
856
857 k->set_irq_enable(s, irqs_on);
858}
859
860static void cold_reset(IPMIBmcSim *ibs,
861 uint8_t *cmd, unsigned int cmd_len,
862 RspBuffer *rsp)
863{
864 IPMIInterface *s = ibs->parent.intf;
865 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
866
867
868 set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
869
870 if (k->reset) {
871 k->reset(s, true);
872 }
873}
874
875static void warm_reset(IPMIBmcSim *ibs,
876 uint8_t *cmd, unsigned int cmd_len,
877 RspBuffer *rsp)
878{
879 IPMIInterface *s = ibs->parent.intf;
880 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
881
882 if (k->reset) {
883 k->reset(s, false);
884 }
885}
886static void set_acpi_power_state(IPMIBmcSim *ibs,
887 uint8_t *cmd, unsigned int cmd_len,
888 RspBuffer *rsp)
889{
890 ibs->acpi_power_state[0] = cmd[2];
891 ibs->acpi_power_state[1] = cmd[3];
892}
893
894static void get_acpi_power_state(IPMIBmcSim *ibs,
895 uint8_t *cmd, unsigned int cmd_len,
896 RspBuffer *rsp)
897{
898 rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
899 rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
900}
901
902static void get_device_guid(IPMIBmcSim *ibs,
903 uint8_t *cmd, unsigned int cmd_len,
904 RspBuffer *rsp)
905{
906 unsigned int i;
907
908
909 for (i = 0; i < 16; i++) {
910 if (ibs->uuid.data[i]) {
911 goto uuid_set;
912 }
913 }
914
915 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_CMD);
916 return;
917
918 uuid_set:
919 for (i = 0; i < 16; i++) {
920 rsp_buffer_push(rsp, ibs->uuid.data[i]);
921 }
922}
923
924static void set_bmc_global_enables(IPMIBmcSim *ibs,
925 uint8_t *cmd, unsigned int cmd_len,
926 RspBuffer *rsp)
927{
928 set_global_enables(ibs, cmd[2]);
929}
930
931static void get_bmc_global_enables(IPMIBmcSim *ibs,
932 uint8_t *cmd, unsigned int cmd_len,
933 RspBuffer *rsp)
934{
935 rsp_buffer_push(rsp, ibs->bmc_global_enables);
936}
937
938static void clr_msg_flags(IPMIBmcSim *ibs,
939 uint8_t *cmd, unsigned int cmd_len,
940 RspBuffer *rsp)
941{
942 IPMIInterface *s = ibs->parent.intf;
943 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
944
945 ibs->msg_flags &= ~cmd[2];
946 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
947}
948
949static void get_msg_flags(IPMIBmcSim *ibs,
950 uint8_t *cmd, unsigned int cmd_len,
951 RspBuffer *rsp)
952{
953 rsp_buffer_push(rsp, ibs->msg_flags);
954}
955
956static void read_evt_msg_buf(IPMIBmcSim *ibs,
957 uint8_t *cmd, unsigned int cmd_len,
958 RspBuffer *rsp)
959{
960 IPMIInterface *s = ibs->parent.intf;
961 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
962 unsigned int i;
963
964 if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
965 rsp_buffer_set_error(rsp, 0x80);
966 return;
967 }
968 for (i = 0; i < 16; i++) {
969 rsp_buffer_push(rsp, ibs->evtbuf[i]);
970 }
971 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
972 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
973}
974
975static void get_msg(IPMIBmcSim *ibs,
976 uint8_t *cmd, unsigned int cmd_len,
977 RspBuffer *rsp)
978{
979 IPMIRcvBufEntry *msg;
980
981 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
982 rsp_buffer_set_error(rsp, 0x80);
983 goto out;
984 }
985 rsp_buffer_push(rsp, 0);
986 msg = QTAILQ_FIRST(&ibs->rcvbufs);
987 rsp_buffer_pushmore(rsp, msg->buf, msg->len);
988 QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
989 g_free(msg);
990
991 if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
992 IPMIInterface *s = ibs->parent.intf;
993 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
994
995 ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
996 k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
997 }
998
999out:
1000 return;
1001}
1002
1003static unsigned char
1004ipmb_checksum(unsigned char *data, int size, unsigned char csum)
1005{
1006 for (; size > 0; size--, data++) {
1007 csum += *data;
1008 }
1009
1010 return -csum;
1011}
1012
1013static void send_msg(IPMIBmcSim *ibs,
1014 uint8_t *cmd, unsigned int cmd_len,
1015 RspBuffer *rsp)
1016{
1017 IPMIInterface *s = ibs->parent.intf;
1018 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1019 IPMIRcvBufEntry *msg;
1020 uint8_t *buf;
1021 uint8_t netfn, rqLun, rsLun, rqSeq;
1022
1023 if (cmd[2] != 0) {
1024
1025 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1026 return;
1027 }
1028
1029 if (cmd_len < 10) {
1030 rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
1031 return;
1032 }
1033
1034 if (cmd[3] != 0x40) {
1035
1036 rsp_buffer_set_error(rsp, 0x83);
1037 return;
1038 }
1039
1040 cmd += 3;
1041 cmd_len -= 3;
1042
1043
1044
1045
1046
1047 if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
1048 cmd[3] != 0x20) {
1049 return;
1050 }
1051
1052 netfn = cmd[1] >> 2;
1053 rqLun = cmd[4] & 0x3;
1054 rsLun = cmd[1] & 0x3;
1055 rqSeq = cmd[4] >> 2;
1056
1057 if (rqLun != 2) {
1058
1059 return;
1060 }
1061
1062 msg = g_malloc(sizeof(*msg));
1063 msg->buf[0] = ((netfn | 1) << 2) | rqLun;
1064 msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
1065 msg->buf[2] = cmd[0];
1066 msg->buf[3] = (rqSeq << 2) | rsLun;
1067 msg->buf[4] = cmd[5];
1068 msg->buf[5] = 0;
1069 msg->len = 6;
1070
1071 if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
1072
1073 msg->buf[5] = IPMI_CC_INVALID_CMD;
1074 goto end_msg;
1075 }
1076
1077 buf = msg->buf + msg->len;
1078 buf[0] = 0;
1079 buf[1] = 0;
1080 buf[2] = 0;
1081 buf[3] = 0;
1082 buf[4] = 0x51;
1083 buf[5] = 0;
1084 buf[6] = 0;
1085 buf[7] = 0;
1086 buf[8] = 0;
1087 buf[9] = 0;
1088 buf[10] = 0;
1089 msg->len += 11;
1090
1091 end_msg:
1092 msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1093 msg->len++;
1094 QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1095 ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1096 k->set_atn(s, 1, attn_irq_enabled(ibs));
1097}
1098
1099static void do_watchdog_reset(IPMIBmcSim *ibs)
1100{
1101 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1102 IPMI_BMC_WATCHDOG_ACTION_NONE) {
1103 ibs->watchdog_running = 0;
1104 return;
1105 }
1106 ibs->watchdog_preaction_ran = 0;
1107
1108
1109
1110 ibs->watchdog_expiry = ipmi_getmonotime();
1111 ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1112 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1113 ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1114 }
1115 ibs->watchdog_running = 1;
1116}
1117
1118static void reset_watchdog_timer(IPMIBmcSim *ibs,
1119 uint8_t *cmd, unsigned int cmd_len,
1120 RspBuffer *rsp)
1121{
1122 if (!ibs->watchdog_initialized) {
1123 rsp_buffer_set_error(rsp, 0x80);
1124 return;
1125 }
1126 do_watchdog_reset(ibs);
1127}
1128
1129static void set_watchdog_timer(IPMIBmcSim *ibs,
1130 uint8_t *cmd, unsigned int cmd_len,
1131 RspBuffer *rsp)
1132{
1133 IPMIInterface *s = ibs->parent.intf;
1134 IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1135 unsigned int val;
1136
1137 val = cmd[2] & 0x7;
1138 if (val == 0 || val > 5) {
1139 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1140 return;
1141 }
1142 val = cmd[3] & 0x7;
1143 switch (val) {
1144 case IPMI_BMC_WATCHDOG_ACTION_NONE:
1145 break;
1146
1147 case IPMI_BMC_WATCHDOG_ACTION_RESET:
1148 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1));
1149 break;
1150
1151 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1152 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1));
1153 break;
1154
1155 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1156 rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1));
1157 break;
1158
1159 default:
1160 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1161 }
1162 if (rsp->buffer[2]) {
1163 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1164 return;
1165 }
1166
1167 val = (cmd[3] >> 4) & 0x7;
1168 switch (val) {
1169 case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1170 case IPMI_BMC_WATCHDOG_PRE_NONE:
1171 break;
1172
1173 case IPMI_BMC_WATCHDOG_PRE_NMI:
1174 if (k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1175
1176 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1177 return;
1178 }
1179 break;
1180
1181 default:
1182
1183 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1184 return;
1185 }
1186
1187 ibs->watchdog_initialized = 1;
1188 ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1189 ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1190 ibs->watchdog_pretimeout = cmd[4];
1191 ibs->watchdog_expired &= ~cmd[5];
1192 ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1193 if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1194 do_watchdog_reset(ibs);
1195 } else {
1196 ibs->watchdog_running = 0;
1197 }
1198}
1199
1200static void get_watchdog_timer(IPMIBmcSim *ibs,
1201 uint8_t *cmd, unsigned int cmd_len,
1202 RspBuffer *rsp)
1203{
1204 rsp_buffer_push(rsp, ibs->watchdog_use);
1205 rsp_buffer_push(rsp, ibs->watchdog_action);
1206 rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
1207 rsp_buffer_push(rsp, ibs->watchdog_expired);
1208 rsp_buffer_push(rsp, ibs->watchdog_timeout & 0xff);
1209 rsp_buffer_push(rsp, (ibs->watchdog_timeout >> 8) & 0xff);
1210 if (ibs->watchdog_running) {
1211 long timeout;
1212 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1213 / 100000000);
1214 rsp_buffer_push(rsp, timeout & 0xff);
1215 rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
1216 } else {
1217 rsp_buffer_push(rsp, 0);
1218 rsp_buffer_push(rsp, 0);
1219 }
1220}
1221
1222static void get_sdr_rep_info(IPMIBmcSim *ibs,
1223 uint8_t *cmd, unsigned int cmd_len,
1224 RspBuffer *rsp)
1225{
1226 unsigned int i;
1227
1228 rsp_buffer_push(rsp, 0x51);
1229 rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
1230 rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
1231 rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1232 rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1233 for (i = 0; i < 4; i++) {
1234 rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
1235 }
1236 for (i = 0; i < 4; i++) {
1237 rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
1238 }
1239
1240 rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
1241}
1242
1243static void reserve_sdr_rep(IPMIBmcSim *ibs,
1244 uint8_t *cmd, unsigned int cmd_len,
1245 RspBuffer *rsp)
1246{
1247 rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
1248 rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
1249}
1250
1251static void get_sdr(IPMIBmcSim *ibs,
1252 uint8_t *cmd, unsigned int cmd_len,
1253 RspBuffer *rsp)
1254{
1255 unsigned int pos;
1256 uint16_t nextrec;
1257 struct ipmi_sdr_header *sdrh;
1258
1259 if (cmd[6]) {
1260 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1261 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1262 return;
1263 }
1264 }
1265
1266 pos = 0;
1267 if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1268 &pos, &nextrec)) {
1269 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1270 return;
1271 }
1272
1273 sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1274
1275 if (cmd[6] > ipmi_sdr_length(sdrh)) {
1276 rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE);
1277 return;
1278 }
1279
1280 rsp_buffer_push(rsp, nextrec & 0xff);
1281 rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
1282
1283 if (cmd[7] == 0xff) {
1284 cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1285 }
1286
1287 if ((cmd[7] + rsp->len) > sizeof(rsp->buffer)) {
1288 rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES);
1289 return;
1290 }
1291
1292 rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1293}
1294
1295static void add_sdr(IPMIBmcSim *ibs,
1296 uint8_t *cmd, unsigned int cmd_len,
1297 RspBuffer *rsp)
1298{
1299 uint16_t recid;
1300 struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1301
1302 if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1303 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1304 return;
1305 }
1306 rsp_buffer_push(rsp, recid & 0xff);
1307 rsp_buffer_push(rsp, (recid >> 8) & 0xff);
1308}
1309
1310static void clear_sdr_rep(IPMIBmcSim *ibs,
1311 uint8_t *cmd, unsigned int cmd_len,
1312 RspBuffer *rsp)
1313{
1314 if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1315 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1316 return;
1317 }
1318
1319 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1320 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1321 return;
1322 }
1323 if (cmd[7] == 0xaa) {
1324 ibs->sdr.next_free = 0;
1325 ibs->sdr.overflow = 0;
1326 set_timestamp(ibs, ibs->sdr.last_clear);
1327 rsp_buffer_push(rsp, 1);
1328 sdr_inc_reservation(&ibs->sdr);
1329 } else if (cmd[7] == 0) {
1330 rsp_buffer_push(rsp, 1);
1331 } else {
1332 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1333 return;
1334 }
1335}
1336
1337static void get_sel_info(IPMIBmcSim *ibs,
1338 uint8_t *cmd, unsigned int cmd_len,
1339 RspBuffer *rsp)
1340{
1341 unsigned int i, val;
1342
1343 rsp_buffer_push(rsp, 0x51);
1344 rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
1345 rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
1346 val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1347 rsp_buffer_push(rsp, val & 0xff);
1348 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1349 for (i = 0; i < 4; i++) {
1350 rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
1351 }
1352 for (i = 0; i < 4; i++) {
1353 rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
1354 }
1355
1356 rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
1357}
1358
1359static void get_fru_area_info(IPMIBmcSim *ibs,
1360 uint8_t *cmd, unsigned int cmd_len,
1361 RspBuffer *rsp)
1362{
1363 uint8_t fruid;
1364 uint16_t fru_entry_size;
1365
1366 fruid = cmd[2];
1367
1368 if (fruid >= ibs->fru.nentries) {
1369 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1370 return;
1371 }
1372
1373 fru_entry_size = ibs->fru.areasize;
1374
1375 rsp_buffer_push(rsp, fru_entry_size & 0xff);
1376 rsp_buffer_push(rsp, fru_entry_size >> 8 & 0xff);
1377 rsp_buffer_push(rsp, 0x0);
1378}
1379
1380static void read_fru_data(IPMIBmcSim *ibs,
1381 uint8_t *cmd, unsigned int cmd_len,
1382 RspBuffer *rsp)
1383{
1384 uint8_t fruid;
1385 uint16_t offset;
1386 int i;
1387 uint8_t *fru_entry;
1388 unsigned int count;
1389
1390 fruid = cmd[2];
1391 offset = (cmd[3] | cmd[4] << 8);
1392
1393 if (fruid >= ibs->fru.nentries) {
1394 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1395 return;
1396 }
1397
1398 if (offset >= ibs->fru.areasize - 1) {
1399 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1400 return;
1401 }
1402
1403 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1404
1405 count = MIN(cmd[5], ibs->fru.areasize - offset);
1406
1407 rsp_buffer_push(rsp, count & 0xff);
1408 for (i = 0; i < count; i++) {
1409 rsp_buffer_push(rsp, fru_entry[offset + i]);
1410 }
1411}
1412
1413static void write_fru_data(IPMIBmcSim *ibs,
1414 uint8_t *cmd, unsigned int cmd_len,
1415 RspBuffer *rsp)
1416{
1417 uint8_t fruid;
1418 uint16_t offset;
1419 uint8_t *fru_entry;
1420 unsigned int count;
1421
1422 fruid = cmd[2];
1423 offset = (cmd[3] | cmd[4] << 8);
1424
1425 if (fruid >= ibs->fru.nentries) {
1426 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1427 return;
1428 }
1429
1430 if (offset >= ibs->fru.areasize - 1) {
1431 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1432 return;
1433 }
1434
1435 fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1436
1437 count = MIN(cmd_len - 5, ibs->fru.areasize - offset);
1438
1439 memcpy(fru_entry + offset, cmd + 5, count);
1440
1441 rsp_buffer_push(rsp, count & 0xff);
1442}
1443
1444static void reserve_sel(IPMIBmcSim *ibs,
1445 uint8_t *cmd, unsigned int cmd_len,
1446 RspBuffer *rsp)
1447{
1448 rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
1449 rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
1450}
1451
1452static void get_sel_entry(IPMIBmcSim *ibs,
1453 uint8_t *cmd, unsigned int cmd_len,
1454 RspBuffer *rsp)
1455{
1456 unsigned int val;
1457
1458 if (cmd[6]) {
1459 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1460 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1461 return;
1462 }
1463 }
1464 if (ibs->sel.next_free == 0) {
1465 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1466 return;
1467 }
1468 if (cmd[6] > 15) {
1469 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1470 return;
1471 }
1472 if (cmd[7] == 0xff) {
1473 cmd[7] = 16;
1474 } else if ((cmd[7] + cmd[6]) > 16) {
1475 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1476 return;
1477 } else {
1478 cmd[7] += cmd[6];
1479 }
1480
1481 val = cmd[4] | (cmd[5] << 8);
1482 if (val == 0xffff) {
1483 val = ibs->sel.next_free - 1;
1484 } else if (val >= ibs->sel.next_free) {
1485 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1486 return;
1487 }
1488 if ((val + 1) == ibs->sel.next_free) {
1489 rsp_buffer_push(rsp, 0xff);
1490 rsp_buffer_push(rsp, 0xff);
1491 } else {
1492 rsp_buffer_push(rsp, (val + 1) & 0xff);
1493 rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
1494 }
1495 for (; cmd[6] < cmd[7]; cmd[6]++) {
1496 rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
1497 }
1498}
1499
1500static void add_sel_entry(IPMIBmcSim *ibs,
1501 uint8_t *cmd, unsigned int cmd_len,
1502 RspBuffer *rsp)
1503{
1504 if (sel_add_event(ibs, cmd + 2)) {
1505 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1506 return;
1507 }
1508
1509 rsp_buffer_push(rsp, cmd[2]);
1510 rsp_buffer_push(rsp, cmd[3]);
1511}
1512
1513static void clear_sel(IPMIBmcSim *ibs,
1514 uint8_t *cmd, unsigned int cmd_len,
1515 RspBuffer *rsp)
1516{
1517 if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1518 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1519 return;
1520 }
1521
1522 if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1523 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1524 return;
1525 }
1526 if (cmd[7] == 0xaa) {
1527 ibs->sel.next_free = 0;
1528 ibs->sel.overflow = 0;
1529 set_timestamp(ibs, ibs->sdr.last_clear);
1530 rsp_buffer_push(rsp, 1);
1531 sel_inc_reservation(&ibs->sel);
1532 } else if (cmd[7] == 0) {
1533 rsp_buffer_push(rsp, 1);
1534 } else {
1535 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1536 return;
1537 }
1538}
1539
1540static void get_sel_time(IPMIBmcSim *ibs,
1541 uint8_t *cmd, unsigned int cmd_len,
1542 RspBuffer *rsp)
1543{
1544 uint32_t val;
1545 struct ipmi_time now;
1546
1547 ipmi_gettime(&now);
1548 val = now.tv_sec + ibs->sel.time_offset;
1549 rsp_buffer_push(rsp, val & 0xff);
1550 rsp_buffer_push(rsp, (val >> 8) & 0xff);
1551 rsp_buffer_push(rsp, (val >> 16) & 0xff);
1552 rsp_buffer_push(rsp, (val >> 24) & 0xff);
1553}
1554
1555static void set_sel_time(IPMIBmcSim *ibs,
1556 uint8_t *cmd, unsigned int cmd_len,
1557 RspBuffer *rsp)
1558{
1559 uint32_t val;
1560 struct ipmi_time now;
1561
1562 val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1563 ipmi_gettime(&now);
1564 ibs->sel.time_offset = now.tv_sec - ((long) val);
1565}
1566
1567static void platform_event_msg(IPMIBmcSim *ibs,
1568 uint8_t *cmd, unsigned int cmd_len,
1569 RspBuffer *rsp)
1570{
1571 uint8_t event[16];
1572
1573 event[2] = 2;
1574 event[7] = cmd[2];
1575 event[8] = 0;
1576 event[9] = cmd[3];
1577 event[10] = cmd[4];
1578 event[11] = cmd[5];
1579 event[12] = cmd[6];
1580 event[13] = cmd[7];
1581 event[14] = cmd[8];
1582 event[15] = cmd[9];
1583
1584 if (sel_add_event(ibs, event)) {
1585 rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1586 }
1587}
1588
1589static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1590 uint8_t *cmd, unsigned int cmd_len,
1591 RspBuffer *rsp)
1592{
1593 IPMISensor *sens;
1594
1595 if ((cmd[2] >= MAX_SENSORS) ||
1596 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1597 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1598 return;
1599 }
1600 sens = ibs->sensors + cmd[2];
1601 switch ((cmd[3] >> 4) & 0x3) {
1602 case 0:
1603 break;
1604 case 1:
1605 if (cmd_len > 4) {
1606 sens->assert_enable |= cmd[4];
1607 }
1608 if (cmd_len > 5) {
1609 sens->assert_enable |= cmd[5] << 8;
1610 }
1611 if (cmd_len > 6) {
1612 sens->deassert_enable |= cmd[6];
1613 }
1614 if (cmd_len > 7) {
1615 sens->deassert_enable |= cmd[7] << 8;
1616 }
1617 break;
1618 case 2:
1619 if (cmd_len > 4) {
1620 sens->assert_enable &= ~cmd[4];
1621 }
1622 if (cmd_len > 5) {
1623 sens->assert_enable &= ~(cmd[5] << 8);
1624 }
1625 if (cmd_len > 6) {
1626 sens->deassert_enable &= ~cmd[6];
1627 }
1628 if (cmd_len > 7) {
1629 sens->deassert_enable &= ~(cmd[7] << 8);
1630 }
1631 break;
1632 case 3:
1633 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1634 return;
1635 }
1636 IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1637}
1638
1639static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1640 uint8_t *cmd, unsigned int cmd_len,
1641 RspBuffer *rsp)
1642{
1643 IPMISensor *sens;
1644
1645 if ((cmd[2] >= MAX_SENSORS) ||
1646 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1647 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1648 return;
1649 }
1650 sens = ibs->sensors + cmd[2];
1651 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1652 rsp_buffer_push(rsp, sens->assert_enable & 0xff);
1653 rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
1654 rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
1655 rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
1656}
1657
1658static void rearm_sensor_evts(IPMIBmcSim *ibs,
1659 uint8_t *cmd, unsigned int cmd_len,
1660 RspBuffer *rsp)
1661{
1662 IPMISensor *sens;
1663
1664 if ((cmd[2] >= MAX_SENSORS) ||
1665 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1666 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1667 return;
1668 }
1669 sens = ibs->sensors + cmd[2];
1670
1671 if ((cmd[3] & 0x80) == 0) {
1672
1673 sens->states = 0;
1674 return;
1675 }
1676}
1677
1678static void get_sensor_evt_status(IPMIBmcSim *ibs,
1679 uint8_t *cmd, unsigned int cmd_len,
1680 RspBuffer *rsp)
1681{
1682 IPMISensor *sens;
1683
1684 if ((cmd[2] >= MAX_SENSORS) ||
1685 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1686 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1687 return;
1688 }
1689 sens = ibs->sensors + cmd[2];
1690 rsp_buffer_push(rsp, sens->reading);
1691 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1692 rsp_buffer_push(rsp, sens->assert_states & 0xff);
1693 rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
1694 rsp_buffer_push(rsp, sens->deassert_states & 0xff);
1695 rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
1696}
1697
1698static void get_sensor_reading(IPMIBmcSim *ibs,
1699 uint8_t *cmd, unsigned int cmd_len,
1700 RspBuffer *rsp)
1701{
1702 IPMISensor *sens;
1703
1704 if ((cmd[2] >= MAX_SENSORS) ||
1705 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1706 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1707 return;
1708 }
1709 sens = ibs->sensors + cmd[2];
1710 rsp_buffer_push(rsp, sens->reading);
1711 rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1712 rsp_buffer_push(rsp, sens->states & 0xff);
1713 if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1714 rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
1715 }
1716}
1717
1718static void set_sensor_type(IPMIBmcSim *ibs,
1719 uint8_t *cmd, unsigned int cmd_len,
1720 RspBuffer *rsp)
1721{
1722 IPMISensor *sens;
1723
1724
1725 if ((cmd[2] >= MAX_SENSORS) ||
1726 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1727 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1728 return;
1729 }
1730 sens = ibs->sensors + cmd[2];
1731 sens->sensor_type = cmd[3];
1732 sens->evt_reading_type_code = cmd[4] & 0x7f;
1733}
1734
1735static void get_sensor_type(IPMIBmcSim *ibs,
1736 uint8_t *cmd, unsigned int cmd_len,
1737 RspBuffer *rsp)
1738{
1739 IPMISensor *sens;
1740
1741
1742 if ((cmd[2] >= MAX_SENSORS) ||
1743 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1744 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1745 return;
1746 }
1747 sens = ibs->sensors + cmd[2];
1748 rsp_buffer_push(rsp, sens->sensor_type);
1749 rsp_buffer_push(rsp, sens->evt_reading_type_code);
1750}
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761static void set_sensor_reading(IPMIBmcSim *ibs,
1762 uint8_t *cmd, unsigned int cmd_len,
1763 RspBuffer *rsp)
1764{
1765 IPMISensor *sens;
1766 uint8_t evd1 = 0;
1767 uint8_t evd2 = 0;
1768 uint8_t evd3 = 0;
1769 uint8_t new_reading = 0;
1770 uint16_t new_assert_states = 0;
1771 uint16_t new_deassert_states = 0;
1772 bool change_reading = false;
1773 bool change_assert = false;
1774 bool change_deassert = false;
1775 enum {
1776 SENSOR_GEN_EVENT_NONE,
1777 SENSOR_GEN_EVENT_DATA,
1778 SENSOR_GEN_EVENT_BMC,
1779 } do_gen_event = SENSOR_GEN_EVENT_NONE;
1780
1781 if ((cmd[2] >= MAX_SENSORS) ||
1782 !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1783 rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1784 return;
1785 }
1786
1787 sens = ibs->sensors + cmd[2];
1788
1789
1790 switch ((cmd[3]) & 0x3) {
1791 case 0:
1792 break;
1793 case 1:
1794 new_reading = cmd[4];
1795 if (sens->reading != new_reading) {
1796 change_reading = true;
1797 }
1798 break;
1799 case 2:
1800 case 3:
1801 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1802 return;
1803 }
1804
1805
1806 switch ((cmd[3] >> 2) & 0x3) {
1807 case 0:
1808 break;
1809 case 1:
1810 if (cmd_len > 7) {
1811 new_deassert_states = cmd[7];
1812 change_deassert = true;
1813 }
1814 if (cmd_len > 8) {
1815 new_deassert_states |= (cmd[8] << 8);
1816 }
1817 break;
1818
1819 case 2:
1820 if (cmd_len > 7) {
1821 new_deassert_states = (sens->deassert_states | cmd[7]);
1822 change_deassert = true;
1823 }
1824 if (cmd_len > 8) {
1825 new_deassert_states |= (sens->deassert_states | (cmd[8] << 8));
1826 }
1827 break;
1828
1829 case 3:
1830 if (cmd_len > 7) {
1831 new_deassert_states = (sens->deassert_states & cmd[7]);
1832 change_deassert = true;
1833 }
1834 if (cmd_len > 8) {
1835 new_deassert_states |= (sens->deassert_states & (cmd[8] << 8));
1836 }
1837 break;
1838 }
1839
1840 if (change_deassert && (new_deassert_states == sens->deassert_states)) {
1841 change_deassert = false;
1842 }
1843
1844
1845 switch ((cmd[3] >> 4) & 0x3) {
1846 case 0:
1847 break;
1848 case 1:
1849 if (cmd_len > 5) {
1850 new_assert_states = cmd[5];
1851 change_assert = true;
1852 }
1853 if (cmd_len > 6) {
1854 new_assert_states |= (cmd[6] << 8);
1855 }
1856 break;
1857
1858 case 2:
1859 if (cmd_len > 5) {
1860 new_assert_states = (sens->assert_states | cmd[5]);
1861 change_assert = true;
1862 }
1863 if (cmd_len > 6) {
1864 new_assert_states |= (sens->assert_states | (cmd[6] << 8));
1865 }
1866 break;
1867
1868 case 3:
1869 if (cmd_len > 5) {
1870 new_assert_states = (sens->assert_states & cmd[5]);
1871 change_assert = true;
1872 }
1873 if (cmd_len > 6) {
1874 new_assert_states |= (sens->assert_states & (cmd[6] << 8));
1875 }
1876 break;
1877 }
1878
1879 if (change_assert && (new_assert_states == sens->assert_states)) {
1880 change_assert = false;
1881 }
1882
1883 if (cmd_len > 9) {
1884 evd1 = cmd[9];
1885 }
1886 if (cmd_len > 10) {
1887 evd2 = cmd[10];
1888 }
1889 if (cmd_len > 11) {
1890 evd3 = cmd[11];
1891 }
1892
1893
1894 switch ((cmd[3] >> 6) & 0x3) {
1895 case 0:
1896
1897
1898
1899
1900 evd1 = evd2 = evd3 = 0x0;
1901 do_gen_event = SENSOR_GEN_EVENT_BMC;
1902 break;
1903 case 1:
1904
1905
1906
1907 do_gen_event = SENSOR_GEN_EVENT_DATA;
1908 break;
1909 case 2:
1910
1911
1912
1913 evd1 &= 0xf0;
1914 do_gen_event = SENSOR_GEN_EVENT_DATA;
1915 break;
1916 case 3:
1917 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1918 return;
1919 }
1920
1921
1922
1923
1924
1925
1926 if (do_gen_event == SENSOR_GEN_EVENT_DATA && cmd_len < 10) {
1927 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1928 return;
1929 }
1930
1931
1932 if (change_reading) {
1933 sens->reading = new_reading;
1934 }
1935
1936 if (change_assert) {
1937 sens->assert_states = new_assert_states;
1938 }
1939
1940 if (change_deassert) {
1941 sens->deassert_states = new_deassert_states;
1942 }
1943
1944
1945 if (!IPMI_SENSOR_IS_DISCRETE(sens)) {
1946 return;
1947 }
1948
1949 switch (do_gen_event) {
1950 case SENSOR_GEN_EVENT_DATA: {
1951 unsigned int bit = evd1 & 0xf;
1952 uint16_t mask = (1 << bit);
1953
1954 if (sens->assert_states & mask & sens->assert_enable) {
1955 gen_event(ibs, cmd[2], 0, evd1, evd2, evd3);
1956 }
1957
1958 if (sens->deassert_states & mask & sens->deassert_enable) {
1959 gen_event(ibs, cmd[2], 1, evd1, evd2, evd3);
1960 }
1961 break;
1962 }
1963 case SENSOR_GEN_EVENT_BMC:
1964
1965
1966
1967
1968 break;
1969 case SENSOR_GEN_EVENT_NONE:
1970 break;
1971 }
1972}
1973
1974static const IPMICmdHandler chassis_cmds[] = {
1975 [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
1976 [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
1977 [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
1978 [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
1979};
1980static const IPMINetfn chassis_netfn = {
1981 .cmd_nums = ARRAY_SIZE(chassis_cmds),
1982 .cmd_handlers = chassis_cmds
1983};
1984
1985static const IPMICmdHandler sensor_event_cmds[] = {
1986 [IPMI_CMD_PLATFORM_EVENT_MSG] = { platform_event_msg, 10 },
1987 [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
1988 [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
1989 [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
1990 [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
1991 [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
1992 [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
1993 [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
1994 [IPMI_CMD_SET_SENSOR_READING] = { set_sensor_reading, 5 },
1995};
1996static const IPMINetfn sensor_event_netfn = {
1997 .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
1998 .cmd_handlers = sensor_event_cmds
1999};
2000
2001static const IPMICmdHandler app_cmds[] = {
2002 [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
2003 [IPMI_CMD_COLD_RESET] = { cold_reset },
2004 [IPMI_CMD_WARM_RESET] = { warm_reset },
2005 [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
2006 [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
2007 [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
2008 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
2009 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
2010 [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
2011 [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
2012 [IPMI_CMD_GET_MSG] = { get_msg },
2013 [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
2014 [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
2015 [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
2016 [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
2017 [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
2018};
2019static const IPMINetfn app_netfn = {
2020 .cmd_nums = ARRAY_SIZE(app_cmds),
2021 .cmd_handlers = app_cmds
2022};
2023
2024static const IPMICmdHandler storage_cmds[] = {
2025 [IPMI_CMD_GET_FRU_AREA_INFO] = { get_fru_area_info, 3 },
2026 [IPMI_CMD_READ_FRU_DATA] = { read_fru_data, 5 },
2027 [IPMI_CMD_WRITE_FRU_DATA] = { write_fru_data, 5 },
2028 [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
2029 [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
2030 [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
2031 [IPMI_CMD_ADD_SDR] = { add_sdr },
2032 [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
2033 [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
2034 [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
2035 [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
2036 [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
2037 [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
2038 [IPMI_CMD_GET_SEL_TIME] = { get_sel_time },
2039 [IPMI_CMD_SET_SEL_TIME] = { set_sel_time, 6 },
2040};
2041
2042static const IPMINetfn storage_netfn = {
2043 .cmd_nums = ARRAY_SIZE(storage_cmds),
2044 .cmd_handlers = storage_cmds
2045};
2046
2047static void register_cmds(IPMIBmcSim *s)
2048{
2049 ipmi_sim_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
2050 ipmi_sim_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
2051 ipmi_sim_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
2052 ipmi_sim_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
2053}
2054
2055static uint8_t init_sdrs[] = {
2056
2057 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
2058 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
2059 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2060 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
2061 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
2062};
2063
2064static void ipmi_sdr_init(IPMIBmcSim *ibs)
2065{
2066 unsigned int i;
2067 int len;
2068 size_t sdrs_size;
2069 uint8_t *sdrs;
2070
2071 sdrs_size = sizeof(init_sdrs);
2072 sdrs = init_sdrs;
2073 if (ibs->sdr_filename &&
2074 !g_file_get_contents(ibs->sdr_filename, (gchar **) &sdrs, &sdrs_size,
2075 NULL)) {
2076 error_report("failed to load sdr file '%s'", ibs->sdr_filename);
2077 sdrs_size = sizeof(init_sdrs);
2078 sdrs = init_sdrs;
2079 }
2080
2081 for (i = 0; i < sdrs_size; i += len) {
2082 struct ipmi_sdr_header *sdrh;
2083
2084 if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
2085 error_report("Problem with recid 0x%4.4x", i);
2086 break;
2087 }
2088 sdrh = (struct ipmi_sdr_header *) &sdrs[i];
2089 len = ipmi_sdr_length(sdrh);
2090 if (i + len > sdrs_size) {
2091 error_report("Problem with recid 0x%4.4x", i);
2092 break;
2093 }
2094 sdr_add_entry(ibs, sdrh, len, NULL);
2095 }
2096
2097 if (sdrs != init_sdrs) {
2098 g_free(sdrs);
2099 }
2100}
2101
2102static const VMStateDescription vmstate_ipmi_sim = {
2103 .name = TYPE_IPMI_BMC_SIMULATOR,
2104 .version_id = 1,
2105 .minimum_version_id = 1,
2106 .fields = (VMStateField[]) {
2107 VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
2108 VMSTATE_UINT8(msg_flags, IPMIBmcSim),
2109 VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
2110 VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
2111 VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
2112 VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
2113 VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
2114 VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
2115 VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
2116 VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
2117 VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
2118 VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
2119 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
2120 VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
2121 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
2122 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
2123 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
2124 IPMIBmcSim),
2125 VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
2126 VMSTATE_END_OF_LIST()
2127 }
2128};
2129
2130static void ipmi_fru_init(IPMIFru *fru)
2131{
2132 int fsize;
2133 int size = 0;
2134
2135 if (!fru->filename) {
2136 goto out;
2137 }
2138
2139 fsize = get_image_size(fru->filename);
2140 if (fsize > 0) {
2141 size = QEMU_ALIGN_UP(fsize, fru->areasize);
2142 fru->data = g_malloc0(size);
2143 if (load_image_size(fru->filename, fru->data, fsize) != fsize) {
2144 error_report("Could not load file '%s'", fru->filename);
2145 g_free(fru->data);
2146 fru->data = NULL;
2147 }
2148 }
2149
2150out:
2151 if (!fru->data) {
2152
2153 size = fru->areasize;
2154 fru->data = g_malloc0(size);
2155 }
2156
2157 fru->nentries = size / fru->areasize;
2158}
2159
2160static void ipmi_sim_realize(DeviceState *dev, Error **errp)
2161{
2162 IPMIBmc *b = IPMI_BMC(dev);
2163 unsigned int i;
2164 IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
2165
2166 QTAILQ_INIT(&ibs->rcvbufs);
2167
2168 ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
2169 ibs->device_id = 0x20;
2170 ibs->ipmi_version = 0x02;
2171 ibs->restart_cause = 0;
2172 for (i = 0; i < 4; i++) {
2173 ibs->sel.last_addition[i] = 0xff;
2174 ibs->sel.last_clear[i] = 0xff;
2175 ibs->sdr.last_addition[i] = 0xff;
2176 ibs->sdr.last_clear[i] = 0xff;
2177 }
2178
2179 ipmi_sdr_init(ibs);
2180
2181 ipmi_fru_init(&ibs->fru);
2182
2183 ibs->acpi_power_state[0] = 0;
2184 ibs->acpi_power_state[1] = 0;
2185
2186 ipmi_init_sensors_from_sdrs(ibs);
2187 register_cmds(ibs);
2188
2189 ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
2190
2191 vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
2192}
2193
2194static Property ipmi_sim_properties[] = {
2195 DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim, fru.areasize, 1024),
2196 DEFINE_PROP_STRING("frudatafile", IPMIBmcSim, fru.filename),
2197 DEFINE_PROP_STRING("sdrfile", IPMIBmcSim, sdr_filename),
2198 DEFINE_PROP_UINT8("device_id", IPMIBmcSim, device_id, 0x20),
2199 DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim, ipmi_version, 0x02),
2200 DEFINE_PROP_UINT8("device_rev", IPMIBmcSim, device_rev, 0),
2201 DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim, fwrev1, 0),
2202 DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim, fwrev2, 0),
2203 DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim, mfg_id, 0),
2204 DEFINE_PROP_UINT16("product_id", IPMIBmcSim, product_id, 0),
2205 DEFINE_PROP_UUID_NODEFAULT("guid", IPMIBmcSim, uuid),
2206 DEFINE_PROP_END_OF_LIST(),
2207};
2208
2209static void ipmi_sim_class_init(ObjectClass *oc, void *data)
2210{
2211 DeviceClass *dc = DEVICE_CLASS(oc);
2212 IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
2213
2214 dc->hotpluggable = false;
2215 dc->realize = ipmi_sim_realize;
2216 device_class_set_props(dc, ipmi_sim_properties);
2217 bk->handle_command = ipmi_sim_handle_command;
2218}
2219
2220static const TypeInfo ipmi_sim_type = {
2221 .name = TYPE_IPMI_BMC_SIMULATOR,
2222 .parent = TYPE_IPMI_BMC,
2223 .instance_size = sizeof(IPMIBmcSim),
2224 .class_init = ipmi_sim_class_init,
2225};
2226
2227static void ipmi_sim_register_types(void)
2228{
2229 type_register_static(&ipmi_sim_type);
2230}
2231
2232type_init(ipmi_sim_register_types)
2233