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