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