xref: /openbmc/qemu/hw/ipmi/ipmi_bmc_sim.c (revision 9884abee)
1 /*
2  * IPMI BMC emulation
3  *
4  * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 #include "qemu/osdep.h"
26 #include "qemu/timer.h"
27 #include "hw/ipmi/ipmi.h"
28 #include "qemu/error-report.h"
29 
30 #define IPMI_NETFN_CHASSIS            0x00
31 #define IPMI_NETFN_CHASSIS_MAXCMD         0x03
32 
33 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
34 #define IPMI_CMD_GET_CHASSIS_STATUS       0x01
35 #define IPMI_CMD_CHASSIS_CONTROL          0x02
36 
37 #define IPMI_NETFN_SENSOR_EVENT       0x04
38 #define IPMI_NETFN_SENSOR_EVENT_MAXCMD    0x2e
39 
40 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE    0x28
41 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE    0x29
42 #define IPMI_CMD_REARM_SENSOR_EVTS        0x2a
43 #define IPMI_CMD_GET_SENSOR_EVT_STATUS    0x2b
44 #define IPMI_CMD_GET_SENSOR_READING       0x2d
45 
46 /* #define IPMI_NETFN_APP             0x06 In ipmi.h */
47 #define IPMI_NETFN_APP_MAXCMD             0x36
48 
49 #define IPMI_CMD_GET_DEVICE_ID            0x01
50 #define IPMI_CMD_COLD_RESET               0x02
51 #define IPMI_CMD_WARM_RESET               0x03
52 #define IPMI_CMD_RESET_WATCHDOG_TIMER     0x22
53 #define IPMI_CMD_SET_WATCHDOG_TIMER       0x24
54 #define IPMI_CMD_GET_WATCHDOG_TIMER       0x25
55 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES   0x2e
56 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES   0x2f
57 #define IPMI_CMD_CLR_MSG_FLAGS            0x30
58 #define IPMI_CMD_GET_MSG_FLAGS            0x31
59 #define IPMI_CMD_GET_MSG                  0x33
60 #define IPMI_CMD_SEND_MSG                 0x34
61 #define IPMI_CMD_READ_EVT_MSG_BUF         0x35
62 
63 #define IPMI_NETFN_STORAGE            0x0a
64 #define IPMI_NETFN_STORAGE_MAXCMD         0x4a
65 
66 #define IPMI_CMD_GET_SDR_REP_INFO         0x20
67 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO   0x21
68 #define IPMI_CMD_RESERVE_SDR_REP          0x22
69 #define IPMI_CMD_GET_SDR                  0x23
70 #define IPMI_CMD_ADD_SDR                  0x24
71 #define IPMI_CMD_PARTIAL_ADD_SDR          0x25
72 #define IPMI_CMD_DELETE_SDR               0x26
73 #define IPMI_CMD_CLEAR_SDR_REP            0x27
74 #define IPMI_CMD_GET_SDR_REP_TIME         0x28
75 #define IPMI_CMD_SET_SDR_REP_TIME         0x29
76 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE   0x2A
77 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE    0x2B
78 #define IPMI_CMD_RUN_INIT_AGENT           0x2C
79 #define IPMI_CMD_GET_SEL_INFO             0x40
80 #define IPMI_CMD_GET_SEL_ALLOC_INFO       0x41
81 #define IPMI_CMD_RESERVE_SEL              0x42
82 #define IPMI_CMD_GET_SEL_ENTRY            0x43
83 #define IPMI_CMD_ADD_SEL_ENTRY            0x44
84 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY    0x45
85 #define IPMI_CMD_DELETE_SEL_ENTRY         0x46
86 #define IPMI_CMD_CLEAR_SEL                0x47
87 #define IPMI_CMD_GET_SEL_TIME             0x48
88 #define IPMI_CMD_SET_SEL_TIME             0x49
89 
90 
91 /* Same as a timespec struct. */
92 struct ipmi_time {
93     long tv_sec;
94     long tv_nsec;
95 };
96 
97 #define MAX_SEL_SIZE 128
98 
99 typedef struct IPMISel {
100     uint8_t sel[MAX_SEL_SIZE][16];
101     unsigned int next_free;
102     long time_offset;
103     uint16_t reservation;
104     uint8_t last_addition[4];
105     uint8_t last_clear[4];
106     uint8_t overflow;
107 } IPMISel;
108 
109 #define MAX_SDR_SIZE 16384
110 
111 typedef struct IPMISdr {
112     uint8_t sdr[MAX_SDR_SIZE];
113     unsigned int next_free;
114     uint16_t next_rec_id;
115     uint16_t reservation;
116     uint8_t last_addition[4];
117     uint8_t last_clear[4];
118     uint8_t overflow;
119 } IPMISdr;
120 
121 typedef struct IPMISensor {
122     uint8_t status;
123     uint8_t reading;
124     uint16_t states_suppt;
125     uint16_t assert_suppt;
126     uint16_t deassert_suppt;
127     uint16_t states;
128     uint16_t assert_states;
129     uint16_t deassert_states;
130     uint16_t assert_enable;
131     uint16_t deassert_enable;
132     uint8_t  sensor_type;
133     uint8_t  evt_reading_type_code;
134 } IPMISensor;
135 #define IPMI_SENSOR_GET_PRESENT(s)       ((s)->status & 0x01)
136 #define IPMI_SENSOR_SET_PRESENT(s, v)    ((s)->status = (s->status & ~0x01) | \
137                                              !!(v))
138 #define IPMI_SENSOR_GET_SCAN_ON(s)       ((s)->status & 0x40)
139 #define IPMI_SENSOR_SET_SCAN_ON(s, v)    ((s)->status = (s->status & ~0x40) | \
140                                              ((!!(v)) << 6))
141 #define IPMI_SENSOR_GET_EVENTS_ON(s)     ((s)->status & 0x80)
142 #define IPMI_SENSOR_SET_EVENTS_ON(s, v)  ((s)->status = (s->status & ~0x80) | \
143                                              ((!!(v)) << 7))
144 #define IPMI_SENSOR_GET_RET_STATUS(s)    ((s)->status & 0xc0)
145 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
146                                              (v & 0xc0))
147 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
148 
149 #define MAX_SENSORS 20
150 #define IPMI_WATCHDOG_SENSOR 0
151 
152 typedef struct IPMIBmcSim IPMIBmcSim;
153 
154 #define MAX_NETFNS 64
155 typedef void (*IPMICmdHandler)(IPMIBmcSim *s,
156                                uint8_t *cmd, unsigned int cmd_len,
157                                uint8_t *rsp, unsigned int *rsp_len,
158                                unsigned int max_rsp_len);
159 typedef struct IPMINetfn {
160     unsigned int cmd_nums;
161     const IPMICmdHandler *cmd_handlers;
162 } IPMINetfn;
163 
164 typedef struct IPMIRcvBufEntry {
165     QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
166     uint8_t len;
167     uint8_t buf[MAX_IPMI_MSG_SIZE];
168 } IPMIRcvBufEntry;
169 
170 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
171 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
172                                         TYPE_IPMI_BMC_SIMULATOR)
173 struct IPMIBmcSim {
174     IPMIBmc parent;
175 
176     QEMUTimer *timer;
177 
178     uint8_t bmc_global_enables;
179     uint8_t msg_flags;
180 
181     bool     watchdog_initialized;
182     uint8_t  watchdog_use;
183     uint8_t  watchdog_action;
184     uint8_t  watchdog_pretimeout; /* In seconds */
185     bool     watchdog_expired;
186     uint16_t watchdog_timeout; /* in 100's of milliseconds */
187 
188     bool     watchdog_running;
189     bool     watchdog_preaction_ran;
190     int64_t  watchdog_expiry;
191 
192     uint8_t device_id;
193     uint8_t ipmi_version;
194     uint8_t device_rev;
195     uint8_t fwrev1;
196     uint8_t fwrev2;
197     uint8_t mfg_id[3];
198     uint8_t product_id[2];
199 
200     IPMISel sel;
201     IPMISdr sdr;
202     IPMISensor sensors[MAX_SENSORS];
203 
204     /* Odd netfns are for responses, so we only need the even ones. */
205     const IPMINetfn *netfns[MAX_NETFNS / 2];
206 
207     QemuMutex lock;
208     /* We allow one event in the buffer */
209     uint8_t evtbuf[16];
210 
211     QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
212 };
213 
214 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK        (1 << 3)
215 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL                 (1 << 1)
216 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE                (1 << 0)
217 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
218     (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
219 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
220     (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
221 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
222     (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
223 
224 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT    0
225 #define IPMI_BMC_EVBUF_FULL_INT_BIT       1
226 #define IPMI_BMC_EVENT_MSG_BUF_BIT        2
227 #define IPMI_BMC_EVENT_LOG_BIT            3
228 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
229                                  (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
230 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
231                                         (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
232 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
233                                        (1 << IPMI_BMC_EVENT_LOG_BIT))
234 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
235                                            (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
236 
237 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
238 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
239 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
240 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
241 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
242 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
243 #define IPMI_BMC_WATCHDOG_PRE_NONE               0
244 #define IPMI_BMC_WATCHDOG_PRE_SMI                1
245 #define IPMI_BMC_WATCHDOG_PRE_NMI                2
246 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT            3
247 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
248 #define IPMI_BMC_WATCHDOG_ACTION_NONE            0
249 #define IPMI_BMC_WATCHDOG_ACTION_RESET           1
250 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN      2
251 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE     3
252 
253 
254 /* Add a byte to the response. */
255 #define IPMI_ADD_RSP_DATA(b) \
256     do {                                                   \
257         if (*rsp_len >= max_rsp_len) {                     \
258             rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;       \
259             goto out;                                      \
260         }                                                  \
261         rsp[(*rsp_len)++] = (b);                           \
262     } while (0)
263 
264 /* Verify that the received command is a certain length. */
265 #define IPMI_CHECK_CMD_LEN(l) \
266     if (cmd_len < l) {                                     \
267         rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;      \
268         goto out; \
269     }
270 
271 /* Check that the reservation in the command is valid. */
272 #define IPMI_CHECK_RESERVATION(off, r) \
273     do {                                                   \
274         if ((cmd[off] | (cmd[off + 1] << 8)) != r) {       \
275             rsp[2] = IPMI_CC_INVALID_RESERVATION;          \
276             goto out;                                      \
277         }                                                  \
278     } while (0)
279 
280 
281 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
282 
283 static void ipmi_gettime(struct ipmi_time *time)
284 {
285     int64_t stime;
286 
287     stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
288     time->tv_sec = stime / 1000000000LL;
289     time->tv_nsec = stime % 1000000000LL;
290 }
291 
292 static int64_t ipmi_getmonotime(void)
293 {
294     return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
295 }
296 
297 static void ipmi_timeout(void *opaque)
298 {
299     IPMIBmcSim *ibs = opaque;
300 
301     ipmi_sim_handle_timeout(ibs);
302 }
303 
304 static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
305 {
306     unsigned int val;
307     struct ipmi_time now;
308 
309     ipmi_gettime(&now);
310     val = now.tv_sec + ibs->sel.time_offset;
311     ts[0] = val & 0xff;
312     ts[1] = (val >> 8) & 0xff;
313     ts[2] = (val >> 16) & 0xff;
314     ts[3] = (val >> 24) & 0xff;
315 }
316 
317 static void sdr_inc_reservation(IPMISdr *sdr)
318 {
319     sdr->reservation++;
320     if (sdr->reservation == 0) {
321         sdr->reservation = 1;
322     }
323 }
324 
325 static int sdr_add_entry(IPMIBmcSim *ibs, const uint8_t *entry,
326                          unsigned int len, uint16_t *recid)
327 {
328     if ((len < 5) || (len > 255)) {
329         return 1;
330     }
331 
332     if (entry[4] != len - 5) {
333         return 1;
334     }
335 
336     if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
337         ibs->sdr.overflow = 1;
338         return 1;
339     }
340 
341     memcpy(ibs->sdr.sdr + ibs->sdr.next_free, entry, len);
342     ibs->sdr.sdr[ibs->sdr.next_free] = ibs->sdr.next_rec_id & 0xff;
343     ibs->sdr.sdr[ibs->sdr.next_free+1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
344     ibs->sdr.sdr[ibs->sdr.next_free+2] = 0x51; /* Conform to IPMI 1.5 spec */
345 
346     if (recid) {
347         *recid = ibs->sdr.next_rec_id;
348     }
349     ibs->sdr.next_rec_id++;
350     set_timestamp(ibs, ibs->sdr.last_addition);
351     ibs->sdr.next_free += len;
352     sdr_inc_reservation(&ibs->sdr);
353     return 0;
354 }
355 
356 static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
357                           unsigned int *retpos, uint16_t *nextrec)
358 {
359     unsigned int pos = *retpos;
360 
361     while (pos < sdr->next_free) {
362         uint16_t trec = sdr->sdr[pos] | (sdr->sdr[pos + 1] << 8);
363         unsigned int nextpos = pos + sdr->sdr[pos + 4];
364 
365         if (trec == recid) {
366             if (nextrec) {
367                 if (nextpos >= sdr->next_free) {
368                     *nextrec = 0xffff;
369                 } else {
370                     *nextrec = (sdr->sdr[nextpos] |
371                                 (sdr->sdr[nextpos + 1] << 8));
372                 }
373             }
374             *retpos = pos;
375             return 0;
376         }
377         pos = nextpos;
378     }
379     return 1;
380 }
381 
382 static void sel_inc_reservation(IPMISel *sel)
383 {
384     sel->reservation++;
385     if (sel->reservation == 0) {
386         sel->reservation = 1;
387     }
388 }
389 
390 /* Returns 1 if the SEL is full and can't hold the event. */
391 static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
392 {
393     event[0] = 0xff;
394     event[1] = 0xff;
395     set_timestamp(ibs, event + 3);
396     if (ibs->sel.next_free == MAX_SEL_SIZE) {
397         ibs->sel.overflow = 1;
398         return 1;
399     }
400     event[0] = ibs->sel.next_free & 0xff;
401     event[1] = (ibs->sel.next_free >> 8) & 0xff;
402     memcpy(ibs->sel.last_addition, event + 3, 4);
403     memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
404     ibs->sel.next_free++;
405     sel_inc_reservation(&ibs->sel);
406     return 0;
407 }
408 
409 static int attn_set(IPMIBmcSim *ibs)
410 {
411     return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
412         || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
413         || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
414 }
415 
416 static int attn_irq_enabled(IPMIBmcSim *ibs)
417 {
418     return (IPMI_BMC_MSG_INTS_ON(ibs) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs))
419         || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
420             IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
421 }
422 
423 static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
424                       uint8_t evd1, uint8_t evd2, uint8_t evd3)
425 {
426     IPMIInterface *s = ibs->parent.intf;
427     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
428     uint8_t evt[16];
429     IPMISensor *sens = ibs->sensors + sens_num;
430 
431     if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
432         return;
433     }
434     if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
435         return;
436     }
437 
438     evt[2] = 0x2; /* System event record */
439     evt[7] = ibs->parent.slave_addr;
440     evt[8] = 0;
441     evt[9] = 0x04; /* Format version */
442     evt[10] = sens->sensor_type;
443     evt[11] = sens_num;
444     evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
445     evt[13] = evd1;
446     evt[14] = evd2;
447     evt[15] = evd3;
448 
449     if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
450         sel_add_event(ibs, evt);
451     }
452 
453     if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
454         goto out;
455     }
456 
457     memcpy(ibs->evtbuf, evt, 16);
458     ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
459     k->set_atn(s, 1, attn_irq_enabled(ibs));
460  out:
461     return;
462 }
463 
464 static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
465                                     unsigned int bit, unsigned int val,
466                                     uint8_t evd1, uint8_t evd2, uint8_t evd3)
467 {
468     IPMISensor *sens;
469     uint16_t mask;
470 
471     if (sensor >= MAX_SENSORS) {
472         return;
473     }
474     if (bit >= 16) {
475         return;
476     }
477 
478     mask = (1 << bit);
479     sens = ibs->sensors + sensor;
480     if (val) {
481         sens->states |= mask & sens->states_suppt;
482         if (sens->assert_states & mask) {
483             return; /* Already asserted */
484         }
485         sens->assert_states |= mask & sens->assert_suppt;
486         if (sens->assert_enable & mask & sens->assert_states) {
487             /* Send an event on assert */
488             gen_event(ibs, sensor, 0, evd1, evd2, evd3);
489         }
490     } else {
491         sens->states &= ~(mask & sens->states_suppt);
492         if (sens->deassert_states & mask) {
493             return; /* Already deasserted */
494         }
495         sens->deassert_states |= mask & sens->deassert_suppt;
496         if (sens->deassert_enable & mask & sens->deassert_states) {
497             /* Send an event on deassert */
498             gen_event(ibs, sensor, 1, evd1, evd2, evd3);
499         }
500     }
501 }
502 
503 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
504 {
505     unsigned int i, pos;
506     IPMISensor *sens;
507 
508     for (i = 0; i < MAX_SENSORS; i++) {
509         memset(s->sensors + i, 0, sizeof(*sens));
510     }
511 
512     pos = 0;
513     for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
514         uint8_t *sdr = s->sdr.sdr + pos;
515         unsigned int len = sdr[4];
516 
517         if (len < 20) {
518             continue;
519         }
520         if ((sdr[3] < 1) || (sdr[3] > 2)) {
521             continue; /* Not a sensor SDR we set from */
522         }
523 
524         if (sdr[7] > MAX_SENSORS) {
525             continue;
526         }
527         sens = s->sensors + sdr[7];
528 
529         IPMI_SENSOR_SET_PRESENT(sens, 1);
530         IPMI_SENSOR_SET_SCAN_ON(sens, (sdr[10] >> 6) & 1);
531         IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr[10] >> 5) & 1);
532         sens->assert_suppt = sdr[14] | (sdr[15] << 8);
533         sens->deassert_suppt = sdr[16] | (sdr[17] << 8);
534         sens->states_suppt = sdr[18] | (sdr[19] << 8);
535         sens->sensor_type = sdr[12];
536         sens->evt_reading_type_code = sdr[13] & 0x7f;
537 
538         /* Enable all the events that are supported. */
539         sens->assert_enable = sens->assert_suppt;
540         sens->deassert_enable = sens->deassert_suppt;
541     }
542 }
543 
544 static int ipmi_register_netfn(IPMIBmcSim *s, unsigned int netfn,
545                                const IPMINetfn *netfnd)
546 {
547     if ((netfn & 1) || (netfn > MAX_NETFNS) || (s->netfns[netfn / 2])) {
548         return -1;
549     }
550     s->netfns[netfn / 2] = netfnd;
551     return 0;
552 }
553 
554 static void next_timeout(IPMIBmcSim *ibs)
555 {
556     int64_t next;
557     if (ibs->watchdog_running) {
558         next = ibs->watchdog_expiry;
559     } else {
560         /* Wait a minute */
561         next = ipmi_getmonotime() + 60 * 1000000000LL;
562     }
563     timer_mod_ns(ibs->timer, next);
564 }
565 
566 static void ipmi_sim_handle_command(IPMIBmc *b,
567                                     uint8_t *cmd, unsigned int cmd_len,
568                                     unsigned int max_cmd_len,
569                                     uint8_t msg_id)
570 {
571     IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
572     IPMIInterface *s = ibs->parent.intf;
573     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
574     unsigned int netfn;
575     uint8_t rsp[MAX_IPMI_MSG_SIZE];
576     unsigned int rsp_len_holder = 0;
577     unsigned int *rsp_len = &rsp_len_holder;
578     unsigned int max_rsp_len = sizeof(rsp);
579 
580     /* Set up the response, set the low bit of NETFN. */
581     /* Note that max_rsp_len must be at least 3 */
582     IPMI_ADD_RSP_DATA(cmd[0] | 0x04);
583     IPMI_ADD_RSP_DATA(cmd[1]);
584     IPMI_ADD_RSP_DATA(0); /* Assume success */
585 
586     /* If it's too short or it was truncated, return an error. */
587     if (cmd_len < 2) {
588         rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
589         goto out;
590     }
591     if (cmd_len > max_cmd_len) {
592         rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
593         goto out;
594     }
595 
596     if ((cmd[0] & 0x03) != 0) {
597         /* Only have stuff on LUN 0 */
598         rsp[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
599         goto out;
600     }
601 
602     netfn = cmd[0] >> 2;
603 
604     /* Odd netfns are not valid, make sure the command is registered */
605     if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
606                         (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
607                         (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
608         rsp[2] = IPMI_CC_INVALID_CMD;
609         goto out;
610     }
611 
612     ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
613                                                 max_rsp_len);
614 
615  out:
616     k->handle_rsp(s, msg_id, rsp, *rsp_len);
617 
618     next_timeout(ibs);
619 }
620 
621 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
622 {
623     IPMIInterface *s = ibs->parent.intf;
624     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
625 
626     if (!ibs->watchdog_running) {
627         goto out;
628     }
629 
630     if (!ibs->watchdog_preaction_ran) {
631         switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
632         case IPMI_BMC_WATCHDOG_PRE_NMI:
633             ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
634             k->do_hw_op(s, IPMI_SEND_NMI, 0);
635             sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
636                                     0xc8, (2 << 4) | 0xf, 0xff);
637             break;
638 
639         case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
640             ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
641             k->set_atn(s, 1, attn_irq_enabled(ibs));
642             sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
643                                     0xc8, (3 << 4) | 0xf, 0xff);
644             break;
645 
646         default:
647             goto do_full_expiry;
648         }
649 
650         ibs->watchdog_preaction_ran = 1;
651         /* Issued the pretimeout, do the rest of the timeout now. */
652         ibs->watchdog_expiry = ipmi_getmonotime();
653         ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
654         goto out;
655     }
656 
657  do_full_expiry:
658     ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
659     ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
660     switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
661     case IPMI_BMC_WATCHDOG_ACTION_NONE:
662         sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
663                                 0xc0, ibs->watchdog_use & 0xf, 0xff);
664         break;
665 
666     case IPMI_BMC_WATCHDOG_ACTION_RESET:
667         sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
668                                 0xc1, ibs->watchdog_use & 0xf, 0xff);
669         k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
670         break;
671 
672     case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
673         sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
674                                 0xc2, ibs->watchdog_use & 0xf, 0xff);
675         k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
676         break;
677 
678     case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
679         sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
680                                 0xc3, ibs->watchdog_use & 0xf, 0xff);
681         k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
682         break;
683     }
684 
685  out:
686     next_timeout(ibs);
687 }
688 
689 static void chassis_capabilities(IPMIBmcSim *ibs,
690                                  uint8_t *cmd, unsigned int cmd_len,
691                                  uint8_t *rsp, unsigned int *rsp_len,
692                                  unsigned int max_rsp_len)
693 {
694     IPMI_ADD_RSP_DATA(0);
695     IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
696     IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
697     IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
698     IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
699  out:
700     return;
701 }
702 
703 static void chassis_status(IPMIBmcSim *ibs,
704                            uint8_t *cmd, unsigned int cmd_len,
705                            uint8_t *rsp, unsigned int *rsp_len,
706                            unsigned int max_rsp_len)
707 {
708     IPMI_ADD_RSP_DATA(0x61); /* Unknown power restore, power is on */
709     IPMI_ADD_RSP_DATA(0);
710     IPMI_ADD_RSP_DATA(0);
711     IPMI_ADD_RSP_DATA(0);
712  out:
713     return;
714 }
715 
716 static void chassis_control(IPMIBmcSim *ibs,
717                             uint8_t *cmd, unsigned int cmd_len,
718                             uint8_t *rsp, unsigned int *rsp_len,
719                             unsigned int max_rsp_len)
720 {
721     IPMIInterface *s = ibs->parent.intf;
722     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
723 
724     IPMI_CHECK_CMD_LEN(3);
725     switch (cmd[2] & 0xf) {
726     case 0: /* power down */
727         rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
728         break;
729     case 1: /* power up */
730         rsp[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
731         break;
732     case 2: /* power cycle */
733         rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
734         break;
735     case 3: /* hard reset */
736         rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
737         break;
738     case 4: /* pulse diagnostic interrupt */
739         rsp[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
740         break;
741     case 5: /* soft shutdown via ACPI by overtemp emulation */
742         rsp[2] = k->do_hw_op(s,
743                              IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0);
744         break;
745     default:
746         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
747         goto out;
748     }
749  out:
750     return;
751 }
752 
753 static void get_device_id(IPMIBmcSim *ibs,
754                           uint8_t *cmd, unsigned int cmd_len,
755                           uint8_t *rsp, unsigned int *rsp_len,
756                           unsigned int max_rsp_len)
757 {
758     IPMI_ADD_RSP_DATA(ibs->device_id);
759     IPMI_ADD_RSP_DATA(ibs->device_rev & 0xf);
760     IPMI_ADD_RSP_DATA(ibs->fwrev1 & 0x7f);
761     IPMI_ADD_RSP_DATA(ibs->fwrev2);
762     IPMI_ADD_RSP_DATA(ibs->ipmi_version);
763     IPMI_ADD_RSP_DATA(0x07); /* sensor, SDR, and SEL. */
764     IPMI_ADD_RSP_DATA(ibs->mfg_id[0]);
765     IPMI_ADD_RSP_DATA(ibs->mfg_id[1]);
766     IPMI_ADD_RSP_DATA(ibs->mfg_id[2]);
767     IPMI_ADD_RSP_DATA(ibs->product_id[0]);
768     IPMI_ADD_RSP_DATA(ibs->product_id[1]);
769  out:
770     return;
771 }
772 
773 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
774 {
775     IPMIInterface *s = ibs->parent.intf;
776     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
777     bool irqs_on;
778 
779     ibs->bmc_global_enables = val;
780 
781     irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
782                      IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
783 
784     k->set_irq_enable(s, irqs_on);
785 }
786 
787 static void cold_reset(IPMIBmcSim *ibs,
788                        uint8_t *cmd, unsigned int cmd_len,
789                        uint8_t *rsp, unsigned int *rsp_len,
790                        unsigned int max_rsp_len)
791 {
792     IPMIInterface *s = ibs->parent.intf;
793     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
794 
795     /* Disable all interrupts */
796     set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
797 
798     if (k->reset) {
799         k->reset(s, true);
800     }
801 }
802 
803 static void warm_reset(IPMIBmcSim *ibs,
804                        uint8_t *cmd, unsigned int cmd_len,
805                        uint8_t *rsp, unsigned int *rsp_len,
806                        unsigned int max_rsp_len)
807 {
808     IPMIInterface *s = ibs->parent.intf;
809     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
810 
811     if (k->reset) {
812         k->reset(s, false);
813     }
814 }
815 
816 static void set_bmc_global_enables(IPMIBmcSim *ibs,
817                                    uint8_t *cmd, unsigned int cmd_len,
818                                    uint8_t *rsp, unsigned int *rsp_len,
819                                    unsigned int max_rsp_len)
820 {
821     IPMI_CHECK_CMD_LEN(3);
822     set_global_enables(ibs, cmd[2]);
823  out:
824     return;
825 }
826 
827 static void get_bmc_global_enables(IPMIBmcSim *ibs,
828                                    uint8_t *cmd, unsigned int cmd_len,
829                                    uint8_t *rsp, unsigned int *rsp_len,
830                                    unsigned int max_rsp_len)
831 {
832     IPMI_ADD_RSP_DATA(ibs->bmc_global_enables);
833  out:
834     return;
835 }
836 
837 static void clr_msg_flags(IPMIBmcSim *ibs,
838                           uint8_t *cmd, unsigned int cmd_len,
839                           uint8_t *rsp, unsigned int *rsp_len,
840                           unsigned int max_rsp_len)
841 {
842     IPMIInterface *s = ibs->parent.intf;
843     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
844 
845     IPMI_CHECK_CMD_LEN(3);
846     ibs->msg_flags &= ~cmd[2];
847     k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
848  out:
849     return;
850 }
851 
852 static void get_msg_flags(IPMIBmcSim *ibs,
853                           uint8_t *cmd, unsigned int cmd_len,
854                           uint8_t *rsp, unsigned int *rsp_len,
855                           unsigned int max_rsp_len)
856 {
857     IPMI_ADD_RSP_DATA(ibs->msg_flags);
858  out:
859     return;
860 }
861 
862 static void read_evt_msg_buf(IPMIBmcSim *ibs,
863                              uint8_t *cmd, unsigned int cmd_len,
864                              uint8_t *rsp, unsigned int *rsp_len,
865                             unsigned int max_rsp_len)
866 {
867     IPMIInterface *s = ibs->parent.intf;
868     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
869     unsigned int i;
870 
871     if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
872         rsp[2] = 0x80;
873         goto out;
874     }
875     for (i = 0; i < 16; i++) {
876         IPMI_ADD_RSP_DATA(ibs->evtbuf[i]);
877     }
878     ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
879     k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
880  out:
881     return;
882 }
883 
884 static void get_msg(IPMIBmcSim *ibs,
885                     uint8_t *cmd, unsigned int cmd_len,
886                     uint8_t *rsp, unsigned int *rsp_len,
887                     unsigned int max_rsp_len)
888 {
889     IPMIRcvBufEntry *msg;
890 
891     qemu_mutex_lock(&ibs->lock);
892     if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
893         rsp[2] = 0x80; /* Queue empty */
894         goto out;
895     }
896     rsp[3] = 0; /* Channel 0 */
897     *rsp_len += 1;
898     msg = QTAILQ_FIRST(&ibs->rcvbufs);
899     memcpy(rsp + 4, msg->buf, msg->len);
900     *rsp_len += msg->len;
901     QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
902     g_free(msg);
903 
904     if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
905         IPMIInterface *s = ibs->parent.intf;
906         IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
907 
908         ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
909         k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
910     }
911 
912  out:
913     qemu_mutex_unlock(&ibs->lock);
914     return;
915 }
916 
917 static unsigned char
918 ipmb_checksum(unsigned char *data, int size, unsigned char csum)
919 {
920     for (; size > 0; size--, data++) {
921             csum += *data;
922     }
923 
924     return -csum;
925 }
926 
927 static void send_msg(IPMIBmcSim *ibs,
928                      uint8_t *cmd, unsigned int cmd_len,
929                      uint8_t *rsp, unsigned int *rsp_len,
930                      unsigned int max_rsp_len)
931 {
932     IPMIInterface *s = ibs->parent.intf;
933     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
934     IPMIRcvBufEntry *msg;
935     uint8_t *buf;
936     uint8_t netfn, rqLun, rsLun, rqSeq;
937 
938     IPMI_CHECK_CMD_LEN(3);
939 
940     if (cmd[2] != 0) {
941         /* We only handle channel 0 with no options */
942         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
943         goto out;
944     }
945 
946     IPMI_CHECK_CMD_LEN(10);
947     if (cmd[3] != 0x40) {
948         /* We only emulate a MC at address 0x40. */
949         rsp[2] = 0x83; /* NAK on write */
950         goto out;
951     }
952 
953     cmd += 3; /* Skip the header. */
954     cmd_len -= 3;
955 
956     /*
957      * At this point we "send" the message successfully.  Any error will
958      * be returned in the response.
959      */
960     if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
961         cmd[3] != 0x20) { /* Improper response address */
962         goto out; /* No response */
963     }
964 
965     netfn = cmd[1] >> 2;
966     rqLun = cmd[4] & 0x3;
967     rsLun = cmd[1] & 0x3;
968     rqSeq = cmd[4] >> 2;
969 
970     if (rqLun != 2) {
971         /* We only support LUN 2 coming back to us. */
972         goto out;
973     }
974 
975     msg = g_malloc(sizeof(*msg));
976     msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
977     msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
978     msg->buf[2] = cmd[0]; /* rsSA */
979     msg->buf[3] = (rqSeq << 2) | rsLun;
980     msg->buf[4] = cmd[5]; /* Cmd */
981     msg->buf[5] = 0; /* Completion Code */
982     msg->len = 6;
983 
984     if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
985         /* Not a command we handle. */
986         msg->buf[5] = IPMI_CC_INVALID_CMD;
987         goto end_msg;
988     }
989 
990     buf = msg->buf + msg->len; /* After the CC */
991     buf[0] = 0;
992     buf[1] = 0;
993     buf[2] = 0;
994     buf[3] = 0;
995     buf[4] = 0x51;
996     buf[5] = 0;
997     buf[6] = 0;
998     buf[7] = 0;
999     buf[8] = 0;
1000     buf[9] = 0;
1001     buf[10] = 0;
1002     msg->len += 11;
1003 
1004  end_msg:
1005     msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1006     msg->len++;
1007     qemu_mutex_lock(&ibs->lock);
1008     QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1009     ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1010     k->set_atn(s, 1, attn_irq_enabled(ibs));
1011     qemu_mutex_unlock(&ibs->lock);
1012 
1013  out:
1014     return;
1015 }
1016 
1017 static void do_watchdog_reset(IPMIBmcSim *ibs)
1018 {
1019     if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1020         IPMI_BMC_WATCHDOG_ACTION_NONE) {
1021         ibs->watchdog_running = 0;
1022         return;
1023     }
1024     ibs->watchdog_preaction_ran = 0;
1025 
1026 
1027     /* Timeout is in tenths of a second, offset is in seconds */
1028     ibs->watchdog_expiry = ipmi_getmonotime();
1029     ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1030     if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1031         ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1032     }
1033     ibs->watchdog_running = 1;
1034 }
1035 
1036 static void reset_watchdog_timer(IPMIBmcSim *ibs,
1037                                  uint8_t *cmd, unsigned int cmd_len,
1038                                  uint8_t *rsp, unsigned int *rsp_len,
1039                                  unsigned int max_rsp_len)
1040 {
1041     if (!ibs->watchdog_initialized) {
1042         rsp[2] = 0x80;
1043         goto out;
1044     }
1045     do_watchdog_reset(ibs);
1046  out:
1047     return;
1048 }
1049 
1050 static void set_watchdog_timer(IPMIBmcSim *ibs,
1051                                uint8_t *cmd, unsigned int cmd_len,
1052                                uint8_t *rsp, unsigned int *rsp_len,
1053                                unsigned int max_rsp_len)
1054 {
1055     IPMIInterface *s = ibs->parent.intf;
1056     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1057     unsigned int val;
1058 
1059     IPMI_CHECK_CMD_LEN(8);
1060     val = cmd[2] & 0x7; /* Validate use */
1061     if (val == 0 || val > 5) {
1062         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1063         goto out;
1064     }
1065     val = cmd[3] & 0x7; /* Validate action */
1066     switch (val) {
1067     case IPMI_BMC_WATCHDOG_ACTION_NONE:
1068         break;
1069 
1070     case IPMI_BMC_WATCHDOG_ACTION_RESET:
1071         rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
1072         break;
1073 
1074     case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1075         rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
1076         break;
1077 
1078     case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1079         rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
1080         break;
1081 
1082     default:
1083         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1084     }
1085     if (rsp[2]) {
1086         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1087         goto out;
1088     }
1089 
1090     val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1091     switch (val) {
1092     case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1093     case IPMI_BMC_WATCHDOG_PRE_NONE:
1094         break;
1095 
1096     case IPMI_BMC_WATCHDOG_PRE_NMI:
1097         if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1098             /* NMI not supported. */
1099             rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1100             goto out;
1101         }
1102     default:
1103         /* We don't support PRE_SMI */
1104         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1105         goto out;
1106     }
1107 
1108     ibs->watchdog_initialized = 1;
1109     ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1110     ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1111     ibs->watchdog_pretimeout = cmd[4];
1112     ibs->watchdog_expired &= ~cmd[5];
1113     ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1114     if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1115         do_watchdog_reset(ibs);
1116     } else {
1117         ibs->watchdog_running = 0;
1118     }
1119  out:
1120     return;
1121 }
1122 
1123 static void get_watchdog_timer(IPMIBmcSim *ibs,
1124                                uint8_t *cmd, unsigned int cmd_len,
1125                                uint8_t *rsp, unsigned int *rsp_len,
1126                                unsigned int max_rsp_len)
1127 {
1128     IPMI_ADD_RSP_DATA(ibs->watchdog_use);
1129     IPMI_ADD_RSP_DATA(ibs->watchdog_action);
1130     IPMI_ADD_RSP_DATA(ibs->watchdog_pretimeout);
1131     IPMI_ADD_RSP_DATA(ibs->watchdog_expired);
1132     if (ibs->watchdog_running) {
1133         long timeout;
1134         timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1135                    / 100000000);
1136         IPMI_ADD_RSP_DATA(timeout & 0xff);
1137         IPMI_ADD_RSP_DATA((timeout >> 8) & 0xff);
1138     } else {
1139         IPMI_ADD_RSP_DATA(0);
1140         IPMI_ADD_RSP_DATA(0);
1141     }
1142  out:
1143     return;
1144 }
1145 
1146 static void get_sdr_rep_info(IPMIBmcSim *ibs,
1147                              uint8_t *cmd, unsigned int cmd_len,
1148                              uint8_t *rsp, unsigned int *rsp_len,
1149                              unsigned int max_rsp_len)
1150 {
1151     unsigned int i;
1152 
1153     IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 spec */
1154     IPMI_ADD_RSP_DATA(ibs->sdr.next_rec_id & 0xff);
1155     IPMI_ADD_RSP_DATA((ibs->sdr.next_rec_id >> 8) & 0xff);
1156     IPMI_ADD_RSP_DATA((MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1157     IPMI_ADD_RSP_DATA(((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1158     for (i = 0; i < 4; i++) {
1159         IPMI_ADD_RSP_DATA(ibs->sdr.last_addition[i]);
1160     }
1161     for (i = 0; i < 4; i++) {
1162         IPMI_ADD_RSP_DATA(ibs->sdr.last_clear[i]);
1163     }
1164     /* Only modal support, reserve supported */
1165     IPMI_ADD_RSP_DATA((ibs->sdr.overflow << 7) | 0x22);
1166  out:
1167     return;
1168 }
1169 
1170 static void reserve_sdr_rep(IPMIBmcSim *ibs,
1171                             uint8_t *cmd, unsigned int cmd_len,
1172                             uint8_t *rsp, unsigned int *rsp_len,
1173                             unsigned int max_rsp_len)
1174 {
1175     IPMI_ADD_RSP_DATA(ibs->sdr.reservation & 0xff);
1176     IPMI_ADD_RSP_DATA((ibs->sdr.reservation >> 8) & 0xff);
1177  out:
1178     return;
1179 }
1180 
1181 static void get_sdr(IPMIBmcSim *ibs,
1182                     uint8_t *cmd, unsigned int cmd_len,
1183                     uint8_t *rsp, unsigned int *rsp_len,
1184                     unsigned int max_rsp_len)
1185 {
1186     unsigned int pos;
1187     uint16_t nextrec;
1188 
1189     IPMI_CHECK_CMD_LEN(8);
1190     if (cmd[6]) {
1191         IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
1192     }
1193     pos = 0;
1194     if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1195                        &pos, &nextrec)) {
1196         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1197         goto out;
1198     }
1199     if (cmd[6] > (ibs->sdr.sdr[pos + 4])) {
1200         rsp[2] = IPMI_CC_PARM_OUT_OF_RANGE;
1201         goto out;
1202     }
1203 
1204     IPMI_ADD_RSP_DATA(nextrec & 0xff);
1205     IPMI_ADD_RSP_DATA((nextrec >> 8) & 0xff);
1206 
1207     if (cmd[7] == 0xff) {
1208         cmd[7] = ibs->sdr.sdr[pos + 4] - cmd[6];
1209     }
1210 
1211     if ((cmd[7] + *rsp_len) > max_rsp_len) {
1212         rsp[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
1213         goto out;
1214     }
1215     memcpy(rsp + *rsp_len, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1216     *rsp_len += cmd[7];
1217  out:
1218     return;
1219 }
1220 
1221 static void add_sdr(IPMIBmcSim *ibs,
1222                     uint8_t *cmd, unsigned int cmd_len,
1223                     uint8_t *rsp, unsigned int *rsp_len,
1224                     unsigned int max_rsp_len)
1225 {
1226     uint16_t recid;
1227 
1228     if (sdr_add_entry(ibs, cmd + 2, cmd_len - 2, &recid)) {
1229         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1230         goto out;
1231     }
1232     IPMI_ADD_RSP_DATA(recid & 0xff);
1233     IPMI_ADD_RSP_DATA((recid >> 8) & 0xff);
1234  out:
1235     return;
1236 }
1237 
1238 static void clear_sdr_rep(IPMIBmcSim *ibs,
1239                           uint8_t *cmd, unsigned int cmd_len,
1240                           uint8_t *rsp, unsigned int *rsp_len,
1241                           unsigned int max_rsp_len)
1242 {
1243     IPMI_CHECK_CMD_LEN(8);
1244     IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
1245     if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1246         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1247         goto out;
1248     }
1249     if (cmd[7] == 0xaa) {
1250         ibs->sdr.next_free = 0;
1251         ibs->sdr.overflow = 0;
1252         set_timestamp(ibs, ibs->sdr.last_clear);
1253         IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1254         sdr_inc_reservation(&ibs->sdr);
1255     } else if (cmd[7] == 0) {
1256         IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1257     } else {
1258         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1259         goto out;
1260     }
1261  out:
1262     return;
1263 }
1264 
1265 static void get_sel_info(IPMIBmcSim *ibs,
1266                          uint8_t *cmd, unsigned int cmd_len,
1267                          uint8_t *rsp, unsigned int *rsp_len,
1268                          unsigned int max_rsp_len)
1269 {
1270     unsigned int i, val;
1271 
1272     IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 */
1273     IPMI_ADD_RSP_DATA(ibs->sel.next_free & 0xff);
1274     IPMI_ADD_RSP_DATA((ibs->sel.next_free >> 8) & 0xff);
1275     val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1276     IPMI_ADD_RSP_DATA(val & 0xff);
1277     IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
1278     for (i = 0; i < 4; i++) {
1279         IPMI_ADD_RSP_DATA(ibs->sel.last_addition[i]);
1280     }
1281     for (i = 0; i < 4; i++) {
1282         IPMI_ADD_RSP_DATA(ibs->sel.last_clear[i]);
1283     }
1284     /* Only support Reserve SEL */
1285     IPMI_ADD_RSP_DATA((ibs->sel.overflow << 7) | 0x02);
1286  out:
1287     return;
1288 }
1289 
1290 static void reserve_sel(IPMIBmcSim *ibs,
1291                         uint8_t *cmd, unsigned int cmd_len,
1292                         uint8_t *rsp, unsigned int *rsp_len,
1293                         unsigned int max_rsp_len)
1294 {
1295     IPMI_ADD_RSP_DATA(ibs->sel.reservation & 0xff);
1296     IPMI_ADD_RSP_DATA((ibs->sel.reservation >> 8) & 0xff);
1297  out:
1298     return;
1299 }
1300 
1301 static void get_sel_entry(IPMIBmcSim *ibs,
1302                           uint8_t *cmd, unsigned int cmd_len,
1303                           uint8_t *rsp, unsigned int *rsp_len,
1304                           unsigned int max_rsp_len)
1305 {
1306     unsigned int val;
1307 
1308     IPMI_CHECK_CMD_LEN(8);
1309     if (cmd[6]) {
1310         IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
1311     }
1312     if (ibs->sel.next_free == 0) {
1313         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1314         goto out;
1315     }
1316     if (cmd[6] > 15) {
1317         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1318         goto out;
1319     }
1320     if (cmd[7] == 0xff) {
1321         cmd[7] = 16;
1322     } else if ((cmd[7] + cmd[6]) > 16) {
1323         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1324         goto out;
1325     } else {
1326         cmd[7] += cmd[6];
1327     }
1328 
1329     val = cmd[4] | (cmd[5] << 8);
1330     if (val == 0xffff) {
1331         val = ibs->sel.next_free - 1;
1332     } else if (val >= ibs->sel.next_free) {
1333         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1334         goto out;
1335     }
1336     if ((val + 1) == ibs->sel.next_free) {
1337         IPMI_ADD_RSP_DATA(0xff);
1338         IPMI_ADD_RSP_DATA(0xff);
1339     } else {
1340         IPMI_ADD_RSP_DATA((val + 1) & 0xff);
1341         IPMI_ADD_RSP_DATA(((val + 1) >> 8) & 0xff);
1342     }
1343     for (; cmd[6] < cmd[7]; cmd[6]++) {
1344         IPMI_ADD_RSP_DATA(ibs->sel.sel[val][cmd[6]]);
1345     }
1346  out:
1347     return;
1348 }
1349 
1350 static void add_sel_entry(IPMIBmcSim *ibs,
1351                           uint8_t *cmd, unsigned int cmd_len,
1352                           uint8_t *rsp, unsigned int *rsp_len,
1353                           unsigned int max_rsp_len)
1354 {
1355     IPMI_CHECK_CMD_LEN(18);
1356     if (sel_add_event(ibs, cmd + 2)) {
1357         rsp[2] = IPMI_CC_OUT_OF_SPACE;
1358         goto out;
1359     }
1360     /* sel_add_event fills in the record number. */
1361     IPMI_ADD_RSP_DATA(cmd[2]);
1362     IPMI_ADD_RSP_DATA(cmd[3]);
1363  out:
1364     return;
1365 }
1366 
1367 static void clear_sel(IPMIBmcSim *ibs,
1368                       uint8_t *cmd, unsigned int cmd_len,
1369                       uint8_t *rsp, unsigned int *rsp_len,
1370                       unsigned int max_rsp_len)
1371 {
1372     IPMI_CHECK_CMD_LEN(8);
1373     IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
1374     if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1375         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1376         goto out;
1377     }
1378     if (cmd[7] == 0xaa) {
1379         ibs->sel.next_free = 0;
1380         ibs->sel.overflow = 0;
1381         set_timestamp(ibs, ibs->sdr.last_clear);
1382         IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1383         sel_inc_reservation(&ibs->sel);
1384     } else if (cmd[7] == 0) {
1385         IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1386     } else {
1387         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1388         goto out;
1389     }
1390  out:
1391     return;
1392 }
1393 
1394 static void get_sel_time(IPMIBmcSim *ibs,
1395                          uint8_t *cmd, unsigned int cmd_len,
1396                          uint8_t *rsp, unsigned int *rsp_len,
1397                          unsigned int max_rsp_len)
1398 {
1399     uint32_t val;
1400     struct ipmi_time now;
1401 
1402     ipmi_gettime(&now);
1403     val = now.tv_sec + ibs->sel.time_offset;
1404     IPMI_ADD_RSP_DATA(val & 0xff);
1405     IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
1406     IPMI_ADD_RSP_DATA((val >> 16) & 0xff);
1407     IPMI_ADD_RSP_DATA((val >> 24) & 0xff);
1408  out:
1409     return;
1410 }
1411 
1412 static void set_sel_time(IPMIBmcSim *ibs,
1413                          uint8_t *cmd, unsigned int cmd_len,
1414                          uint8_t *rsp, unsigned int *rsp_len,
1415                          unsigned int max_rsp_len)
1416 {
1417     uint32_t val;
1418     struct ipmi_time now;
1419 
1420     IPMI_CHECK_CMD_LEN(6);
1421     val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1422     ipmi_gettime(&now);
1423     ibs->sel.time_offset = now.tv_sec - ((long) val);
1424  out:
1425     return;
1426 }
1427 
1428 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1429                                   uint8_t *cmd, unsigned int cmd_len,
1430                                   uint8_t *rsp, unsigned int *rsp_len,
1431                                   unsigned int max_rsp_len)
1432 {
1433     IPMISensor *sens;
1434 
1435     IPMI_CHECK_CMD_LEN(4);
1436     if ((cmd[2] > MAX_SENSORS) ||
1437             !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1438         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1439         goto out;
1440     }
1441     sens = ibs->sensors + cmd[2];
1442     switch ((cmd[3] >> 4) & 0x3) {
1443     case 0: /* Do not change */
1444         break;
1445     case 1: /* Enable bits */
1446         if (cmd_len > 4) {
1447             sens->assert_enable |= cmd[4];
1448         }
1449         if (cmd_len > 5) {
1450             sens->assert_enable |= cmd[5] << 8;
1451         }
1452         if (cmd_len > 6) {
1453             sens->deassert_enable |= cmd[6];
1454         }
1455         if (cmd_len > 7) {
1456             sens->deassert_enable |= cmd[7] << 8;
1457         }
1458         break;
1459     case 2: /* Disable bits */
1460         if (cmd_len > 4) {
1461             sens->assert_enable &= ~cmd[4];
1462         }
1463         if (cmd_len > 5) {
1464             sens->assert_enable &= ~(cmd[5] << 8);
1465         }
1466         if (cmd_len > 6) {
1467             sens->deassert_enable &= ~cmd[6];
1468         }
1469         if (cmd_len > 7) {
1470             sens->deassert_enable &= ~(cmd[7] << 8);
1471         }
1472         break;
1473     case 3:
1474         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
1475         goto out;
1476     }
1477     IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1478  out:
1479     return;
1480 }
1481 
1482 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1483                                   uint8_t *cmd, unsigned int cmd_len,
1484                                   uint8_t *rsp, unsigned int *rsp_len,
1485                                   unsigned int max_rsp_len)
1486 {
1487     IPMISensor *sens;
1488 
1489     IPMI_CHECK_CMD_LEN(3);
1490     if ((cmd[2] > MAX_SENSORS) ||
1491         !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1492         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1493         goto out;
1494     }
1495     sens = ibs->sensors + cmd[2];
1496     IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1497     IPMI_ADD_RSP_DATA(sens->assert_enable & 0xff);
1498     IPMI_ADD_RSP_DATA((sens->assert_enable >> 8) & 0xff);
1499     IPMI_ADD_RSP_DATA(sens->deassert_enable & 0xff);
1500     IPMI_ADD_RSP_DATA((sens->deassert_enable >> 8) & 0xff);
1501  out:
1502     return;
1503 }
1504 
1505 static void rearm_sensor_evts(IPMIBmcSim *ibs,
1506                               uint8_t *cmd, unsigned int cmd_len,
1507                               uint8_t *rsp, unsigned int *rsp_len,
1508                               unsigned int max_rsp_len)
1509 {
1510     IPMISensor *sens;
1511 
1512     IPMI_CHECK_CMD_LEN(4);
1513     if ((cmd[2] > MAX_SENSORS) ||
1514         !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1515         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1516         goto out;
1517     }
1518     sens = ibs->sensors + cmd[2];
1519 
1520     if ((cmd[3] & 0x80) == 0) {
1521         /* Just clear everything */
1522         sens->states = 0;
1523         goto out;
1524     }
1525  out:
1526     return;
1527 }
1528 
1529 static void get_sensor_evt_status(IPMIBmcSim *ibs,
1530                                   uint8_t *cmd, unsigned int cmd_len,
1531                                   uint8_t *rsp, unsigned int *rsp_len,
1532                                   unsigned int max_rsp_len)
1533 {
1534     IPMISensor *sens;
1535 
1536     IPMI_CHECK_CMD_LEN(3);
1537     if ((cmd[2] > MAX_SENSORS) ||
1538         !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1539         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1540         goto out;
1541     }
1542     sens = ibs->sensors + cmd[2];
1543     IPMI_ADD_RSP_DATA(sens->reading);
1544     IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1545     IPMI_ADD_RSP_DATA(sens->assert_states & 0xff);
1546     IPMI_ADD_RSP_DATA((sens->assert_states >> 8) & 0xff);
1547     IPMI_ADD_RSP_DATA(sens->deassert_states & 0xff);
1548     IPMI_ADD_RSP_DATA((sens->deassert_states >> 8) & 0xff);
1549  out:
1550     return;
1551 }
1552 
1553 static void get_sensor_reading(IPMIBmcSim *ibs,
1554                                uint8_t *cmd, unsigned int cmd_len,
1555                                uint8_t *rsp, unsigned int *rsp_len,
1556                                unsigned int max_rsp_len)
1557 {
1558     IPMISensor *sens;
1559 
1560     IPMI_CHECK_CMD_LEN(3);
1561     if ((cmd[2] > MAX_SENSORS) ||
1562             !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1563         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
1564         goto out;
1565     }
1566     sens = ibs->sensors + cmd[2];
1567     IPMI_ADD_RSP_DATA(sens->reading);
1568     IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
1569     IPMI_ADD_RSP_DATA(sens->states & 0xff);
1570     if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1571         IPMI_ADD_RSP_DATA((sens->states >> 8) & 0xff);
1572     }
1573  out:
1574     return;
1575 }
1576 
1577 static const IPMICmdHandler chassis_cmds[IPMI_NETFN_CHASSIS_MAXCMD] = {
1578     [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = chassis_capabilities,
1579     [IPMI_CMD_GET_CHASSIS_STATUS] = chassis_status,
1580     [IPMI_CMD_CHASSIS_CONTROL] = chassis_control
1581 };
1582 static const IPMINetfn chassis_netfn = {
1583     .cmd_nums = IPMI_NETFN_CHASSIS_MAXCMD,
1584     .cmd_handlers = chassis_cmds
1585 };
1586 
1587 static const IPMICmdHandler
1588 sensor_event_cmds[IPMI_NETFN_SENSOR_EVENT_MAXCMD] = {
1589     [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = set_sensor_evt_enable,
1590     [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = get_sensor_evt_enable,
1591     [IPMI_CMD_REARM_SENSOR_EVTS] = rearm_sensor_evts,
1592     [IPMI_CMD_GET_SENSOR_EVT_STATUS] = get_sensor_evt_status,
1593     [IPMI_CMD_GET_SENSOR_READING] = get_sensor_reading
1594 };
1595 static const IPMINetfn sensor_event_netfn = {
1596     .cmd_nums = IPMI_NETFN_SENSOR_EVENT_MAXCMD,
1597     .cmd_handlers = sensor_event_cmds
1598 };
1599 
1600 static const IPMICmdHandler app_cmds[IPMI_NETFN_APP_MAXCMD] = {
1601     [IPMI_CMD_GET_DEVICE_ID] = get_device_id,
1602     [IPMI_CMD_COLD_RESET] = cold_reset,
1603     [IPMI_CMD_WARM_RESET] = warm_reset,
1604     [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = set_bmc_global_enables,
1605     [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = get_bmc_global_enables,
1606     [IPMI_CMD_CLR_MSG_FLAGS] = clr_msg_flags,
1607     [IPMI_CMD_GET_MSG_FLAGS] = get_msg_flags,
1608     [IPMI_CMD_GET_MSG] = get_msg,
1609     [IPMI_CMD_SEND_MSG] = send_msg,
1610     [IPMI_CMD_READ_EVT_MSG_BUF] = read_evt_msg_buf,
1611     [IPMI_CMD_RESET_WATCHDOG_TIMER] = reset_watchdog_timer,
1612     [IPMI_CMD_SET_WATCHDOG_TIMER] = set_watchdog_timer,
1613     [IPMI_CMD_GET_WATCHDOG_TIMER] = get_watchdog_timer,
1614 };
1615 static const IPMINetfn app_netfn = {
1616     .cmd_nums = IPMI_NETFN_APP_MAXCMD,
1617     .cmd_handlers = app_cmds
1618 };
1619 
1620 static const IPMICmdHandler storage_cmds[IPMI_NETFN_STORAGE_MAXCMD] = {
1621     [IPMI_CMD_GET_SDR_REP_INFO] = get_sdr_rep_info,
1622     [IPMI_CMD_RESERVE_SDR_REP] = reserve_sdr_rep,
1623     [IPMI_CMD_GET_SDR] = get_sdr,
1624     [IPMI_CMD_ADD_SDR] = add_sdr,
1625     [IPMI_CMD_CLEAR_SDR_REP] = clear_sdr_rep,
1626     [IPMI_CMD_GET_SEL_INFO] = get_sel_info,
1627     [IPMI_CMD_RESERVE_SEL] = reserve_sel,
1628     [IPMI_CMD_GET_SEL_ENTRY] = get_sel_entry,
1629     [IPMI_CMD_ADD_SEL_ENTRY] = add_sel_entry,
1630     [IPMI_CMD_CLEAR_SEL] = clear_sel,
1631     [IPMI_CMD_GET_SEL_TIME] = get_sel_time,
1632     [IPMI_CMD_SET_SEL_TIME] = set_sel_time,
1633 };
1634 
1635 static const IPMINetfn storage_netfn = {
1636     .cmd_nums = IPMI_NETFN_STORAGE_MAXCMD,
1637     .cmd_handlers = storage_cmds
1638 };
1639 
1640 static void register_cmds(IPMIBmcSim *s)
1641 {
1642     ipmi_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
1643     ipmi_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
1644     ipmi_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
1645     ipmi_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
1646 }
1647 
1648 static const uint8_t init_sdrs[] = {
1649     /* Watchdog device */
1650     0x00, 0x00, 0x51, 0x02,   35, 0x20, 0x00, 0x00,
1651     0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1652     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1653     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1654     'W',  'a',  't',  'c',  'h',  'd',  'o',  'g',
1655     /* End */
1656     0xff, 0xff, 0x00, 0x00, 0x00
1657 };
1658 
1659 static const VMStateDescription vmstate_ipmi_sim = {
1660     .name = TYPE_IPMI_BMC_SIMULATOR,
1661     .version_id = 1,
1662     .minimum_version_id = 1,
1663     .fields      = (VMStateField[]) {
1664         VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
1665         VMSTATE_UINT8(msg_flags, IPMIBmcSim),
1666         VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
1667         VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
1668         VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
1669         VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
1670         VMSTATE_BOOL(watchdog_expired, IPMIBmcSim),
1671         VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
1672         VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
1673         VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
1674         VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
1675         VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
1676         VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
1677         VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
1678         VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
1679         VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
1680         VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
1681                        IPMIBmcSim),
1682         VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
1683         VMSTATE_END_OF_LIST()
1684     }
1685 };
1686 
1687 static void ipmi_sim_init(Object *obj)
1688 {
1689     IPMIBmc *b = IPMI_BMC(obj);
1690     unsigned int i;
1691     unsigned int recid;
1692     IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
1693 
1694     qemu_mutex_init(&ibs->lock);
1695     QTAILQ_INIT(&ibs->rcvbufs);
1696 
1697     ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
1698     ibs->device_id = 0x20;
1699     ibs->ipmi_version = 0x02; /* IPMI 2.0 */
1700     for (i = 0; i < 4; i++) {
1701         ibs->sel.last_addition[i] = 0xff;
1702         ibs->sel.last_clear[i] = 0xff;
1703         ibs->sdr.last_addition[i] = 0xff;
1704         ibs->sdr.last_clear[i] = 0xff;
1705     }
1706 
1707     for (i = 0;;) {
1708         int len;
1709         if ((i + 5) > sizeof(init_sdrs)) {
1710             error_report("Problem with recid 0x%4.4x: \n", i);
1711             return;
1712         }
1713         len = init_sdrs[i + 4];
1714         recid = init_sdrs[i] | (init_sdrs[i + 1] << 8);
1715         if (recid == 0xffff) {
1716             break;
1717         }
1718         if ((i + len + 5) > sizeof(init_sdrs)) {
1719             error_report("Problem with recid 0x%4.4x\n", i);
1720             return;
1721         }
1722         sdr_add_entry(ibs, init_sdrs + i, len, NULL);
1723         i += len + 5;
1724     }
1725 
1726     ipmi_init_sensors_from_sdrs(ibs);
1727     register_cmds(ibs);
1728 
1729     ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
1730 
1731     vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
1732 }
1733 
1734 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
1735 {
1736     IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
1737 
1738     bk->handle_command = ipmi_sim_handle_command;
1739 }
1740 
1741 static const TypeInfo ipmi_sim_type = {
1742     .name          = TYPE_IPMI_BMC_SIMULATOR,
1743     .parent        = TYPE_IPMI_BMC,
1744     .instance_size = sizeof(IPMIBmcSim),
1745     .instance_init = ipmi_sim_init,
1746     .class_init    = ipmi_sim_class_init,
1747 };
1748 
1749 static void ipmi_sim_register_types(void)
1750 {
1751     type_register_static(&ipmi_sim_type);
1752 }
1753 
1754 type_init(ipmi_sim_register_types)
1755