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