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