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