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