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