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