4 * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
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"
31 #define IPMI_NETFN_CHASSIS 0x00
33 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
34 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
35 #define IPMI_CMD_CHASSIS_CONTROL 0x02
36 #define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09
38 #define IPMI_NETFN_SENSOR_EVENT 0x04
40 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
41 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
42 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
43 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
44 #define IPMI_CMD_GET_SENSOR_READING 0x2d
45 #define IPMI_CMD_SET_SENSOR_TYPE 0x2e
46 #define IPMI_CMD_GET_SENSOR_TYPE 0x2f
48 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
50 #define IPMI_CMD_GET_DEVICE_ID 0x01
51 #define IPMI_CMD_COLD_RESET 0x02
52 #define IPMI_CMD_WARM_RESET 0x03
53 #define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
54 #define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
55 #define IPMI_CMD_GET_DEVICE_GUID 0x08
56 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
57 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
58 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
59 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
60 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
61 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
62 #define IPMI_CMD_GET_MSG_FLAGS 0x31
63 #define IPMI_CMD_GET_MSG 0x33
64 #define IPMI_CMD_SEND_MSG 0x34
65 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
67 #define IPMI_NETFN_STORAGE 0x0a
69 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
70 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
71 #define IPMI_CMD_RESERVE_SDR_REP 0x22
72 #define IPMI_CMD_GET_SDR 0x23
73 #define IPMI_CMD_ADD_SDR 0x24
74 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
75 #define IPMI_CMD_DELETE_SDR 0x26
76 #define IPMI_CMD_CLEAR_SDR_REP 0x27
77 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
78 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
79 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
80 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
81 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
82 #define IPMI_CMD_GET_SEL_INFO 0x40
83 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
84 #define IPMI_CMD_RESERVE_SEL 0x42
85 #define IPMI_CMD_GET_SEL_ENTRY 0x43
86 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
87 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
88 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
89 #define IPMI_CMD_CLEAR_SEL 0x47
90 #define IPMI_CMD_GET_SEL_TIME 0x48
91 #define IPMI_CMD_SET_SEL_TIME 0x49
94 /* Same as a timespec struct. */
100 #define MAX_SEL_SIZE 128
102 typedef struct IPMISel
{
103 uint8_t sel
[MAX_SEL_SIZE
][16];
104 unsigned int next_free
;
106 uint16_t reservation
;
107 uint8_t last_addition
[4];
108 uint8_t last_clear
[4];
112 #define MAX_SDR_SIZE 16384
114 typedef struct IPMISdr
{
115 uint8_t sdr
[MAX_SDR_SIZE
];
116 unsigned int next_free
;
117 uint16_t next_rec_id
;
118 uint16_t reservation
;
119 uint8_t last_addition
[4];
120 uint8_t last_clear
[4];
124 typedef struct IPMISensor
{
127 uint16_t states_suppt
;
128 uint16_t assert_suppt
;
129 uint16_t deassert_suppt
;
131 uint16_t assert_states
;
132 uint16_t deassert_states
;
133 uint16_t assert_enable
;
134 uint16_t deassert_enable
;
136 uint8_t evt_reading_type_code
;
138 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
139 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
141 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
142 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
144 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
145 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
147 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
148 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
150 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
152 #define MAX_SENSORS 20
153 #define IPMI_WATCHDOG_SENSOR 0
155 typedef struct IPMIBmcSim IPMIBmcSim
;
156 typedef struct RspBuffer RspBuffer
;
158 #define MAX_NETFNS 64
160 typedef struct IPMICmdHandler
{
161 void (*cmd_handler
)(IPMIBmcSim
*s
,
162 uint8_t *cmd
, unsigned int cmd_len
,
164 unsigned int cmd_len_min
;
167 typedef struct IPMINetfn
{
168 unsigned int cmd_nums
;
169 const IPMICmdHandler
*cmd_handlers
;
172 typedef struct IPMIRcvBufEntry
{
173 QTAILQ_ENTRY(IPMIRcvBufEntry
) entry
;
175 uint8_t buf
[MAX_IPMI_MSG_SIZE
];
178 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
179 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
180 TYPE_IPMI_BMC_SIMULATOR)
186 uint8_t bmc_global_enables
;
189 bool watchdog_initialized
;
190 uint8_t watchdog_use
;
191 uint8_t watchdog_action
;
192 uint8_t watchdog_pretimeout
; /* In seconds */
193 bool watchdog_expired
;
194 uint16_t watchdog_timeout
; /* in 100's of milliseconds */
196 bool watchdog_running
;
197 bool watchdog_preaction_ran
;
198 int64_t watchdog_expiry
;
201 uint8_t ipmi_version
;
206 uint8_t product_id
[2];
208 uint8_t restart_cause
;
210 uint8_t acpi_power_state
[2];
215 IPMISensor sensors
[MAX_SENSORS
];
217 /* Odd netfns are for responses, so we only need the even ones. */
218 const IPMINetfn
*netfns
[MAX_NETFNS
/ 2];
221 /* We allow one event in the buffer */
224 QTAILQ_HEAD(, IPMIRcvBufEntry
) rcvbufs
;
227 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
228 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
229 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
230 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
231 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
232 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
233 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
234 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
235 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
237 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
238 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
239 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
240 #define IPMI_BMC_EVENT_LOG_BIT 3
241 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
242 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
243 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
244 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
245 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
246 (1 << IPMI_BMC_EVENT_LOG_BIT))
247 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
248 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
250 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
251 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
252 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
253 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
254 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
255 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
256 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
257 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
258 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
259 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
260 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
261 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
262 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
263 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
264 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
267 uint8_t buffer
[MAX_IPMI_MSG_SIZE
];
271 #define RSP_BUFFER_INITIALIZER { }
273 static inline void rsp_buffer_set_error(RspBuffer
*rsp
, uint8_t byte
)
275 rsp
->buffer
[2] = byte
;
278 /* Add a byte to the response. */
279 static inline void rsp_buffer_push(RspBuffer
*rsp
, uint8_t byte
)
281 if (rsp
->len
>= sizeof(rsp
->buffer
)) {
282 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
285 rsp
->buffer
[rsp
->len
++] = byte
;
288 static inline void rsp_buffer_pushmore(RspBuffer
*rsp
, uint8_t *bytes
,
291 if (rsp
->len
+ n
>= sizeof(rsp
->buffer
)) {
292 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
296 memcpy(&rsp
->buffer
[rsp
->len
], bytes
, n
);
300 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
);
302 static void ipmi_gettime(struct ipmi_time
*time
)
306 stime
= qemu_clock_get_ns(QEMU_CLOCK_HOST
);
307 time
->tv_sec
= stime
/ 1000000000LL;
308 time
->tv_nsec
= stime
% 1000000000LL;
311 static int64_t ipmi_getmonotime(void)
313 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
316 static void ipmi_timeout(void *opaque
)
318 IPMIBmcSim
*ibs
= opaque
;
320 ipmi_sim_handle_timeout(ibs
);
323 static void set_timestamp(IPMIBmcSim
*ibs
, uint8_t *ts
)
326 struct ipmi_time now
;
329 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
331 ts
[1] = (val
>> 8) & 0xff;
332 ts
[2] = (val
>> 16) & 0xff;
333 ts
[3] = (val
>> 24) & 0xff;
336 static void sdr_inc_reservation(IPMISdr
*sdr
)
339 if (sdr
->reservation
== 0) {
340 sdr
->reservation
= 1;
344 static int sdr_add_entry(IPMIBmcSim
*ibs
,
345 const struct ipmi_sdr_header
*sdrh_entry
,
346 unsigned int len
, uint16_t *recid
)
348 struct ipmi_sdr_header
*sdrh
=
349 (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[ibs
->sdr
.next_free
];
351 if ((len
< IPMI_SDR_HEADER_SIZE
) || (len
> 255)) {
355 if (ipmi_sdr_length(sdrh_entry
) != len
) {
359 if (ibs
->sdr
.next_free
+ len
> MAX_SDR_SIZE
) {
360 ibs
->sdr
.overflow
= 1;
364 memcpy(sdrh
, sdrh_entry
, len
);
365 sdrh
->rec_id
[0] = ibs
->sdr
.next_rec_id
& 0xff;
366 sdrh
->rec_id
[1] = (ibs
->sdr
.next_rec_id
>> 8) & 0xff;
367 sdrh
->sdr_version
= 0x51; /* Conform to IPMI 1.5 spec */
370 *recid
= ibs
->sdr
.next_rec_id
;
372 ibs
->sdr
.next_rec_id
++;
373 set_timestamp(ibs
, ibs
->sdr
.last_addition
);
374 ibs
->sdr
.next_free
+= len
;
375 sdr_inc_reservation(&ibs
->sdr
);
379 static int sdr_find_entry(IPMISdr
*sdr
, uint16_t recid
,
380 unsigned int *retpos
, uint16_t *nextrec
)
382 unsigned int pos
= *retpos
;
384 while (pos
< sdr
->next_free
) {
385 struct ipmi_sdr_header
*sdrh
=
386 (struct ipmi_sdr_header
*) &sdr
->sdr
[pos
];
387 uint16_t trec
= ipmi_sdr_recid(sdrh
);
388 unsigned int nextpos
= pos
+ ipmi_sdr_length(sdrh
);
392 if (nextpos
>= sdr
->next_free
) {
395 *nextrec
= (sdr
->sdr
[nextpos
] |
396 (sdr
->sdr
[nextpos
+ 1] << 8));
407 static void sel_inc_reservation(IPMISel
*sel
)
410 if (sel
->reservation
== 0) {
411 sel
->reservation
= 1;
415 /* Returns 1 if the SEL is full and can't hold the event. */
416 static int sel_add_event(IPMIBmcSim
*ibs
, uint8_t *event
)
420 set_timestamp(ibs
, event
+ 3);
421 if (ibs
->sel
.next_free
== MAX_SEL_SIZE
) {
422 ibs
->sel
.overflow
= 1;
425 event
[0] = ibs
->sel
.next_free
& 0xff;
426 event
[1] = (ibs
->sel
.next_free
>> 8) & 0xff;
427 memcpy(ibs
->sel
.last_addition
, event
+ 3, 4);
428 memcpy(ibs
->sel
.sel
[ibs
->sel
.next_free
], event
, 16);
429 ibs
->sel
.next_free
++;
430 sel_inc_reservation(&ibs
->sel
);
434 static int attn_set(IPMIBmcSim
*ibs
)
436 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
)
437 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
)
438 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs
);
441 static int attn_irq_enabled(IPMIBmcSim
*ibs
)
443 return (IPMI_BMC_MSG_INTS_ON(ibs
) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
))
444 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs
) &&
445 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
));
448 static void gen_event(IPMIBmcSim
*ibs
, unsigned int sens_num
, uint8_t deassert
,
449 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
451 IPMIInterface
*s
= ibs
->parent
.intf
;
452 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
454 IPMISensor
*sens
= ibs
->sensors
+ sens_num
;
456 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
459 if (!IPMI_SENSOR_GET_EVENTS_ON(sens
)) {
463 evt
[2] = 0x2; /* System event record */
464 evt
[7] = ibs
->parent
.slave_addr
;
466 evt
[9] = 0x04; /* Format version */
467 evt
[10] = sens
->sensor_type
;
469 evt
[12] = sens
->evt_reading_type_code
| (!!deassert
<< 7);
474 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
475 sel_add_event(ibs
, evt
);
478 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
482 memcpy(ibs
->evtbuf
, evt
, 16);
483 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
484 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
487 static void sensor_set_discrete_bit(IPMIBmcSim
*ibs
, unsigned int sensor
,
488 unsigned int bit
, unsigned int val
,
489 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
494 if (sensor
>= MAX_SENSORS
) {
502 sens
= ibs
->sensors
+ sensor
;
504 sens
->states
|= mask
& sens
->states_suppt
;
505 if (sens
->assert_states
& mask
) {
506 return; /* Already asserted */
508 sens
->assert_states
|= mask
& sens
->assert_suppt
;
509 if (sens
->assert_enable
& mask
& sens
->assert_states
) {
510 /* Send an event on assert */
511 gen_event(ibs
, sensor
, 0, evd1
, evd2
, evd3
);
514 sens
->states
&= ~(mask
& sens
->states_suppt
);
515 if (sens
->deassert_states
& mask
) {
516 return; /* Already deasserted */
518 sens
->deassert_states
|= mask
& sens
->deassert_suppt
;
519 if (sens
->deassert_enable
& mask
& sens
->deassert_states
) {
520 /* Send an event on deassert */
521 gen_event(ibs
, sensor
, 1, evd1
, evd2
, evd3
);
526 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim
*s
)
531 for (i
= 0; i
< MAX_SENSORS
; i
++) {
532 memset(s
->sensors
+ i
, 0, sizeof(*sens
));
536 for (i
= 0; !sdr_find_entry(&s
->sdr
, i
, &pos
, NULL
); i
++) {
537 struct ipmi_sdr_compact
*sdr
=
538 (struct ipmi_sdr_compact
*) &s
->sdr
.sdr
[pos
];
539 unsigned int len
= sdr
->header
.rec_length
;
544 if (sdr
->header
.rec_type
!= IPMI_SDR_COMPACT_TYPE
) {
545 continue; /* Not a sensor SDR we set from */
548 if (sdr
->sensor_owner_number
>= MAX_SENSORS
) {
551 sens
= s
->sensors
+ sdr
->sensor_owner_number
;
553 IPMI_SENSOR_SET_PRESENT(sens
, 1);
554 IPMI_SENSOR_SET_SCAN_ON(sens
, (sdr
->sensor_init
>> 6) & 1);
555 IPMI_SENSOR_SET_EVENTS_ON(sens
, (sdr
->sensor_init
>> 5) & 1);
556 sens
->assert_suppt
= sdr
->assert_mask
[0] | (sdr
->assert_mask
[1] << 8);
557 sens
->deassert_suppt
=
558 sdr
->deassert_mask
[0] | (sdr
->deassert_mask
[1] << 8);
560 sdr
->discrete_mask
[0] | (sdr
->discrete_mask
[1] << 8);
561 sens
->sensor_type
= sdr
->sensor_type
;
562 sens
->evt_reading_type_code
= sdr
->reading_type
& 0x7f;
564 /* Enable all the events that are supported. */
565 sens
->assert_enable
= sens
->assert_suppt
;
566 sens
->deassert_enable
= sens
->deassert_suppt
;
570 static int ipmi_register_netfn(IPMIBmcSim
*s
, unsigned int netfn
,
571 const IPMINetfn
*netfnd
)
573 if ((netfn
& 1) || (netfn
>= MAX_NETFNS
) || (s
->netfns
[netfn
/ 2])) {
576 s
->netfns
[netfn
/ 2] = netfnd
;
580 static const IPMICmdHandler
*ipmi_get_handler(IPMIBmcSim
*ibs
,
584 const IPMICmdHandler
*hdl
;
586 if (netfn
& 1 || netfn
>= MAX_NETFNS
|| !ibs
->netfns
[netfn
/ 2]) {
590 if (cmd
>= ibs
->netfns
[netfn
/ 2]->cmd_nums
) {
594 hdl
= &ibs
->netfns
[netfn
/ 2]->cmd_handlers
[cmd
];
595 if (!hdl
->cmd_handler
) {
602 static void next_timeout(IPMIBmcSim
*ibs
)
605 if (ibs
->watchdog_running
) {
606 next
= ibs
->watchdog_expiry
;
609 next
= ipmi_getmonotime() + 60 * 1000000000LL;
611 timer_mod_ns(ibs
->timer
, next
);
614 static void ipmi_sim_handle_command(IPMIBmc
*b
,
615 uint8_t *cmd
, unsigned int cmd_len
,
616 unsigned int max_cmd_len
,
619 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
620 IPMIInterface
*s
= ibs
->parent
.intf
;
621 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
622 const IPMICmdHandler
*hdl
;
623 RspBuffer rsp
= RSP_BUFFER_INITIALIZER
;
625 /* Set up the response, set the low bit of NETFN. */
626 /* Note that max_rsp_len must be at least 3 */
627 if (sizeof(rsp
.buffer
) < 3) {
628 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
632 rsp_buffer_push(&rsp
, cmd
[0] | 0x04);
633 rsp_buffer_push(&rsp
, cmd
[1]);
634 rsp_buffer_push(&rsp
, 0); /* Assume success */
636 /* If it's too short or it was truncated, return an error. */
638 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
641 if (cmd_len
> max_cmd_len
) {
642 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
646 if ((cmd
[0] & 0x03) != 0) {
647 /* Only have stuff on LUN 0 */
648 rsp_buffer_set_error(&rsp
, IPMI_CC_COMMAND_INVALID_FOR_LUN
);
652 hdl
= ipmi_get_handler(ibs
, cmd
[0] >> 2, cmd
[1]);
654 rsp_buffer_set_error(&rsp
, IPMI_CC_INVALID_CMD
);
658 if (cmd_len
< hdl
->cmd_len_min
) {
659 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
663 hdl
->cmd_handler(ibs
, cmd
, cmd_len
, &rsp
);
666 k
->handle_rsp(s
, msg_id
, rsp
.buffer
, rsp
.len
);
671 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
)
673 IPMIInterface
*s
= ibs
->parent
.intf
;
674 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
676 if (!ibs
->watchdog_running
) {
680 if (!ibs
->watchdog_preaction_ran
) {
681 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
)) {
682 case IPMI_BMC_WATCHDOG_PRE_NMI
:
683 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
684 k
->do_hw_op(s
, IPMI_SEND_NMI
, 0);
685 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
686 0xc8, (2 << 4) | 0xf, 0xff);
689 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
690 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
691 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
692 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
693 0xc8, (3 << 4) | 0xf, 0xff);
700 ibs
->watchdog_preaction_ran
= 1;
701 /* Issued the pretimeout, do the rest of the timeout now. */
702 ibs
->watchdog_expiry
= ipmi_getmonotime();
703 ibs
->watchdog_expiry
+= ibs
->watchdog_pretimeout
* 1000000000LL;
708 ibs
->watchdog_running
= 0; /* Stop the watchdog on a timeout */
709 ibs
->watchdog_expired
|= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs
));
710 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
)) {
711 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
712 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 0, 1,
713 0xc0, ibs
->watchdog_use
& 0xf, 0xff);
716 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
717 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 1, 1,
718 0xc1, ibs
->watchdog_use
& 0xf, 0xff);
719 k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0);
722 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
723 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
724 0xc2, ibs
->watchdog_use
& 0xf, 0xff);
725 k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0);
728 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
729 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
730 0xc3, ibs
->watchdog_use
& 0xf, 0xff);
731 k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0);
739 static void chassis_capabilities(IPMIBmcSim
*ibs
,
740 uint8_t *cmd
, unsigned int cmd_len
,
743 rsp_buffer_push(rsp
, 0);
744 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
745 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
746 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
747 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
750 static void chassis_status(IPMIBmcSim
*ibs
,
751 uint8_t *cmd
, unsigned int cmd_len
,
754 rsp_buffer_push(rsp
, 0x61); /* Unknown power restore, power is on */
755 rsp_buffer_push(rsp
, 0);
756 rsp_buffer_push(rsp
, 0);
757 rsp_buffer_push(rsp
, 0);
760 static void chassis_control(IPMIBmcSim
*ibs
,
761 uint8_t *cmd
, unsigned int cmd_len
,
764 IPMIInterface
*s
= ibs
->parent
.intf
;
765 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
767 switch (cmd
[2] & 0xf) {
768 case 0: /* power down */
769 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0));
771 case 1: /* power up */
772 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERON_CHASSIS
, 0));
774 case 2: /* power cycle */
775 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0));
777 case 3: /* hard reset */
778 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0));
780 case 4: /* pulse diagnostic interrupt */
781 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_PULSE_DIAG_IRQ
, 0));
783 case 5: /* soft shutdown via ACPI by overtemp emulation */
784 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
,
785 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP
, 0));
788 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
793 static void chassis_get_sys_restart_cause(IPMIBmcSim
*ibs
,
794 uint8_t *cmd
, unsigned int cmd_len
,
798 rsp_buffer_push(rsp
, ibs
->restart_cause
& 0xf); /* Restart Cause */
799 rsp_buffer_push(rsp
, 0); /* Channel 0 */
802 static void get_device_id(IPMIBmcSim
*ibs
,
803 uint8_t *cmd
, unsigned int cmd_len
,
806 rsp_buffer_push(rsp
, ibs
->device_id
);
807 rsp_buffer_push(rsp
, ibs
->device_rev
& 0xf);
808 rsp_buffer_push(rsp
, ibs
->fwrev1
& 0x7f);
809 rsp_buffer_push(rsp
, ibs
->fwrev2
);
810 rsp_buffer_push(rsp
, ibs
->ipmi_version
);
811 rsp_buffer_push(rsp
, 0x07); /* sensor, SDR, and SEL. */
812 rsp_buffer_push(rsp
, ibs
->mfg_id
[0]);
813 rsp_buffer_push(rsp
, ibs
->mfg_id
[1]);
814 rsp_buffer_push(rsp
, ibs
->mfg_id
[2]);
815 rsp_buffer_push(rsp
, ibs
->product_id
[0]);
816 rsp_buffer_push(rsp
, ibs
->product_id
[1]);
819 static void set_global_enables(IPMIBmcSim
*ibs
, uint8_t val
)
821 IPMIInterface
*s
= ibs
->parent
.intf
;
822 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
825 ibs
->bmc_global_enables
= val
;
827 irqs_on
= val
& (IPMI_BMC_EVBUF_FULL_INT_BIT
|
828 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT
);
830 k
->set_irq_enable(s
, irqs_on
);
833 static void cold_reset(IPMIBmcSim
*ibs
,
834 uint8_t *cmd
, unsigned int cmd_len
,
837 IPMIInterface
*s
= ibs
->parent
.intf
;
838 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
840 /* Disable all interrupts */
841 set_global_enables(ibs
, 1 << IPMI_BMC_EVENT_LOG_BIT
);
848 static void warm_reset(IPMIBmcSim
*ibs
,
849 uint8_t *cmd
, unsigned int cmd_len
,
852 IPMIInterface
*s
= ibs
->parent
.intf
;
853 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
859 static void set_acpi_power_state(IPMIBmcSim
*ibs
,
860 uint8_t *cmd
, unsigned int cmd_len
,
863 ibs
->acpi_power_state
[0] = cmd
[2];
864 ibs
->acpi_power_state
[1] = cmd
[3];
867 static void get_acpi_power_state(IPMIBmcSim
*ibs
,
868 uint8_t *cmd
, unsigned int cmd_len
,
871 rsp_buffer_push(rsp
, ibs
->acpi_power_state
[0]);
872 rsp_buffer_push(rsp
, ibs
->acpi_power_state
[1]);
875 static void get_device_guid(IPMIBmcSim
*ibs
,
876 uint8_t *cmd
, unsigned int cmd_len
,
881 for (i
= 0; i
< 16; i
++) {
882 rsp_buffer_push(rsp
, ibs
->uuid
[i
]);
886 static void set_bmc_global_enables(IPMIBmcSim
*ibs
,
887 uint8_t *cmd
, unsigned int cmd_len
,
890 set_global_enables(ibs
, cmd
[2]);
893 static void get_bmc_global_enables(IPMIBmcSim
*ibs
,
894 uint8_t *cmd
, unsigned int cmd_len
,
897 rsp_buffer_push(rsp
, ibs
->bmc_global_enables
);
900 static void clr_msg_flags(IPMIBmcSim
*ibs
,
901 uint8_t *cmd
, unsigned int cmd_len
,
904 IPMIInterface
*s
= ibs
->parent
.intf
;
905 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
907 ibs
->msg_flags
&= ~cmd
[2];
908 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
911 static void get_msg_flags(IPMIBmcSim
*ibs
,
912 uint8_t *cmd
, unsigned int cmd_len
,
915 rsp_buffer_push(rsp
, ibs
->msg_flags
);
918 static void read_evt_msg_buf(IPMIBmcSim
*ibs
,
919 uint8_t *cmd
, unsigned int cmd_len
,
922 IPMIInterface
*s
= ibs
->parent
.intf
;
923 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
926 if (!(ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
)) {
927 rsp_buffer_set_error(rsp
, 0x80);
930 for (i
= 0; i
< 16; i
++) {
931 rsp_buffer_push(rsp
, ibs
->evtbuf
[i
]);
933 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
934 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
937 static void get_msg(IPMIBmcSim
*ibs
,
938 uint8_t *cmd
, unsigned int cmd_len
,
941 IPMIRcvBufEntry
*msg
;
943 qemu_mutex_lock(&ibs
->lock
);
944 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
945 rsp_buffer_set_error(rsp
, 0x80); /* Queue empty */
948 rsp_buffer_push(rsp
, 0); /* Channel 0 */
949 msg
= QTAILQ_FIRST(&ibs
->rcvbufs
);
950 rsp_buffer_pushmore(rsp
, msg
->buf
, msg
->len
);
951 QTAILQ_REMOVE(&ibs
->rcvbufs
, msg
, entry
);
954 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
955 IPMIInterface
*s
= ibs
->parent
.intf
;
956 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
958 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
959 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
963 qemu_mutex_unlock(&ibs
->lock
);
968 ipmb_checksum(unsigned char *data
, int size
, unsigned char csum
)
970 for (; size
> 0; size
--, data
++) {
977 static void send_msg(IPMIBmcSim
*ibs
,
978 uint8_t *cmd
, unsigned int cmd_len
,
981 IPMIInterface
*s
= ibs
->parent
.intf
;
982 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
983 IPMIRcvBufEntry
*msg
;
985 uint8_t netfn
, rqLun
, rsLun
, rqSeq
;
988 /* We only handle channel 0 with no options */
989 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
994 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
998 if (cmd
[3] != 0x40) {
999 /* We only emulate a MC at address 0x40. */
1000 rsp_buffer_set_error(rsp
, 0x83); /* NAK on write */
1004 cmd
+= 3; /* Skip the header. */
1008 * At this point we "send" the message successfully. Any error will
1009 * be returned in the response.
1011 if (ipmb_checksum(cmd
, cmd_len
, 0) != 0 ||
1012 cmd
[3] != 0x20) { /* Improper response address */
1013 return; /* No response */
1016 netfn
= cmd
[1] >> 2;
1017 rqLun
= cmd
[4] & 0x3;
1018 rsLun
= cmd
[1] & 0x3;
1019 rqSeq
= cmd
[4] >> 2;
1022 /* We only support LUN 2 coming back to us. */
1026 msg
= g_malloc(sizeof(*msg
));
1027 msg
->buf
[0] = ((netfn
| 1) << 2) | rqLun
; /* NetFN, and make a response */
1028 msg
->buf
[1] = ipmb_checksum(msg
->buf
, 1, 0);
1029 msg
->buf
[2] = cmd
[0]; /* rsSA */
1030 msg
->buf
[3] = (rqSeq
<< 2) | rsLun
;
1031 msg
->buf
[4] = cmd
[5]; /* Cmd */
1032 msg
->buf
[5] = 0; /* Completion Code */
1035 if ((cmd
[1] >> 2) != IPMI_NETFN_APP
|| cmd
[5] != IPMI_CMD_GET_DEVICE_ID
) {
1036 /* Not a command we handle. */
1037 msg
->buf
[5] = IPMI_CC_INVALID_CMD
;
1041 buf
= msg
->buf
+ msg
->len
; /* After the CC */
1056 msg
->buf
[msg
->len
] = ipmb_checksum(msg
->buf
, msg
->len
, 0);
1058 qemu_mutex_lock(&ibs
->lock
);
1059 QTAILQ_INSERT_TAIL(&ibs
->rcvbufs
, msg
, entry
);
1060 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
1061 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
1062 qemu_mutex_unlock(&ibs
->lock
);
1065 static void do_watchdog_reset(IPMIBmcSim
*ibs
)
1067 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
) ==
1068 IPMI_BMC_WATCHDOG_ACTION_NONE
) {
1069 ibs
->watchdog_running
= 0;
1072 ibs
->watchdog_preaction_ran
= 0;
1075 /* Timeout is in tenths of a second, offset is in seconds */
1076 ibs
->watchdog_expiry
= ipmi_getmonotime();
1077 ibs
->watchdog_expiry
+= ibs
->watchdog_timeout
* 100000000LL;
1078 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
) != IPMI_BMC_WATCHDOG_PRE_NONE
) {
1079 ibs
->watchdog_expiry
-= ibs
->watchdog_pretimeout
* 1000000000LL;
1081 ibs
->watchdog_running
= 1;
1084 static void reset_watchdog_timer(IPMIBmcSim
*ibs
,
1085 uint8_t *cmd
, unsigned int cmd_len
,
1088 if (!ibs
->watchdog_initialized
) {
1089 rsp_buffer_set_error(rsp
, 0x80);
1092 do_watchdog_reset(ibs
);
1095 static void set_watchdog_timer(IPMIBmcSim
*ibs
,
1096 uint8_t *cmd
, unsigned int cmd_len
,
1099 IPMIInterface
*s
= ibs
->parent
.intf
;
1100 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1103 val
= cmd
[2] & 0x7; /* Validate use */
1104 if (val
== 0 || val
> 5) {
1105 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1108 val
= cmd
[3] & 0x7; /* Validate action */
1110 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
1113 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
1114 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 1));
1117 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
1118 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 1));
1121 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
1122 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 1));
1126 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1128 if (rsp
->buffer
[2]) {
1129 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1133 val
= (cmd
[3] >> 4) & 0x7; /* Validate preaction */
1135 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
1136 case IPMI_BMC_WATCHDOG_PRE_NONE
:
1139 case IPMI_BMC_WATCHDOG_PRE_NMI
:
1140 if (!k
->do_hw_op(s
, IPMI_SEND_NMI
, 1)) {
1141 /* NMI not supported. */
1142 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1148 /* We don't support PRE_SMI */
1149 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1153 ibs
->watchdog_initialized
= 1;
1154 ibs
->watchdog_use
= cmd
[2] & IPMI_BMC_WATCHDOG_USE_MASK
;
1155 ibs
->watchdog_action
= cmd
[3] & IPMI_BMC_WATCHDOG_ACTION_MASK
;
1156 ibs
->watchdog_pretimeout
= cmd
[4];
1157 ibs
->watchdog_expired
&= ~cmd
[5];
1158 ibs
->watchdog_timeout
= cmd
[6] | (((uint16_t) cmd
[7]) << 8);
1159 if (ibs
->watchdog_running
& IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs
)) {
1160 do_watchdog_reset(ibs
);
1162 ibs
->watchdog_running
= 0;
1166 static void get_watchdog_timer(IPMIBmcSim
*ibs
,
1167 uint8_t *cmd
, unsigned int cmd_len
,
1170 rsp_buffer_push(rsp
, ibs
->watchdog_use
);
1171 rsp_buffer_push(rsp
, ibs
->watchdog_action
);
1172 rsp_buffer_push(rsp
, ibs
->watchdog_pretimeout
);
1173 rsp_buffer_push(rsp
, ibs
->watchdog_expired
);
1174 if (ibs
->watchdog_running
) {
1176 timeout
= ((ibs
->watchdog_expiry
- ipmi_getmonotime() + 50000000)
1178 rsp_buffer_push(rsp
, timeout
& 0xff);
1179 rsp_buffer_push(rsp
, (timeout
>> 8) & 0xff);
1181 rsp_buffer_push(rsp
, 0);
1182 rsp_buffer_push(rsp
, 0);
1186 static void get_sdr_rep_info(IPMIBmcSim
*ibs
,
1187 uint8_t *cmd
, unsigned int cmd_len
,
1192 rsp_buffer_push(rsp
, 0x51); /* Conform to IPMI 1.5 spec */
1193 rsp_buffer_push(rsp
, ibs
->sdr
.next_rec_id
& 0xff);
1194 rsp_buffer_push(rsp
, (ibs
->sdr
.next_rec_id
>> 8) & 0xff);
1195 rsp_buffer_push(rsp
, (MAX_SDR_SIZE
- ibs
->sdr
.next_free
) & 0xff);
1196 rsp_buffer_push(rsp
, ((MAX_SDR_SIZE
- ibs
->sdr
.next_free
) >> 8) & 0xff);
1197 for (i
= 0; i
< 4; i
++) {
1198 rsp_buffer_push(rsp
, ibs
->sdr
.last_addition
[i
]);
1200 for (i
= 0; i
< 4; i
++) {
1201 rsp_buffer_push(rsp
, ibs
->sdr
.last_clear
[i
]);
1203 /* Only modal support, reserve supported */
1204 rsp_buffer_push(rsp
, (ibs
->sdr
.overflow
<< 7) | 0x22);
1207 static void reserve_sdr_rep(IPMIBmcSim
*ibs
,
1208 uint8_t *cmd
, unsigned int cmd_len
,
1211 rsp_buffer_push(rsp
, ibs
->sdr
.reservation
& 0xff);
1212 rsp_buffer_push(rsp
, (ibs
->sdr
.reservation
>> 8) & 0xff);
1215 static void get_sdr(IPMIBmcSim
*ibs
,
1216 uint8_t *cmd
, unsigned int cmd_len
,
1221 struct ipmi_sdr_header
*sdrh
;
1224 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sdr
.reservation
) {
1225 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1231 if (sdr_find_entry(&ibs
->sdr
, cmd
[4] | (cmd
[5] << 8),
1233 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1237 sdrh
= (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[pos
];
1239 if (cmd
[6] > ipmi_sdr_length(sdrh
)) {
1240 rsp_buffer_set_error(rsp
, IPMI_CC_PARM_OUT_OF_RANGE
);
1244 rsp_buffer_push(rsp
, nextrec
& 0xff);
1245 rsp_buffer_push(rsp
, (nextrec
>> 8) & 0xff);
1247 if (cmd
[7] == 0xff) {
1248 cmd
[7] = ipmi_sdr_length(sdrh
) - cmd
[6];
1251 if ((cmd
[7] + rsp
->len
) > sizeof(rsp
->buffer
)) {
1252 rsp_buffer_set_error(rsp
, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES
);
1256 rsp_buffer_pushmore(rsp
, ibs
->sdr
.sdr
+ pos
+ cmd
[6], cmd
[7]);
1259 static void add_sdr(IPMIBmcSim
*ibs
,
1260 uint8_t *cmd
, unsigned int cmd_len
,
1264 struct ipmi_sdr_header
*sdrh
= (struct ipmi_sdr_header
*) cmd
+ 2;
1266 if (sdr_add_entry(ibs
, sdrh
, cmd_len
- 2, &recid
)) {
1267 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1270 rsp_buffer_push(rsp
, recid
& 0xff);
1271 rsp_buffer_push(rsp
, (recid
>> 8) & 0xff);
1274 static void clear_sdr_rep(IPMIBmcSim
*ibs
,
1275 uint8_t *cmd
, unsigned int cmd_len
,
1278 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sdr
.reservation
) {
1279 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1283 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1284 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1287 if (cmd
[7] == 0xaa) {
1288 ibs
->sdr
.next_free
= 0;
1289 ibs
->sdr
.overflow
= 0;
1290 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1291 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1292 sdr_inc_reservation(&ibs
->sdr
);
1293 } else if (cmd
[7] == 0) {
1294 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1296 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1301 static void get_sel_info(IPMIBmcSim
*ibs
,
1302 uint8_t *cmd
, unsigned int cmd_len
,
1305 unsigned int i
, val
;
1307 rsp_buffer_push(rsp
, 0x51); /* Conform to IPMI 1.5 */
1308 rsp_buffer_push(rsp
, ibs
->sel
.next_free
& 0xff);
1309 rsp_buffer_push(rsp
, (ibs
->sel
.next_free
>> 8) & 0xff);
1310 val
= (MAX_SEL_SIZE
- ibs
->sel
.next_free
) * 16;
1311 rsp_buffer_push(rsp
, val
& 0xff);
1312 rsp_buffer_push(rsp
, (val
>> 8) & 0xff);
1313 for (i
= 0; i
< 4; i
++) {
1314 rsp_buffer_push(rsp
, ibs
->sel
.last_addition
[i
]);
1316 for (i
= 0; i
< 4; i
++) {
1317 rsp_buffer_push(rsp
, ibs
->sel
.last_clear
[i
]);
1319 /* Only support Reserve SEL */
1320 rsp_buffer_push(rsp
, (ibs
->sel
.overflow
<< 7) | 0x02);
1323 static void reserve_sel(IPMIBmcSim
*ibs
,
1324 uint8_t *cmd
, unsigned int cmd_len
,
1327 rsp_buffer_push(rsp
, ibs
->sel
.reservation
& 0xff);
1328 rsp_buffer_push(rsp
, (ibs
->sel
.reservation
>> 8) & 0xff);
1331 static void get_sel_entry(IPMIBmcSim
*ibs
,
1332 uint8_t *cmd
, unsigned int cmd_len
,
1338 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sel
.reservation
) {
1339 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1343 if (ibs
->sel
.next_free
== 0) {
1344 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1348 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1351 if (cmd
[7] == 0xff) {
1353 } else if ((cmd
[7] + cmd
[6]) > 16) {
1354 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1360 val
= cmd
[4] | (cmd
[5] << 8);
1361 if (val
== 0xffff) {
1362 val
= ibs
->sel
.next_free
- 1;
1363 } else if (val
>= ibs
->sel
.next_free
) {
1364 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1367 if ((val
+ 1) == ibs
->sel
.next_free
) {
1368 rsp_buffer_push(rsp
, 0xff);
1369 rsp_buffer_push(rsp
, 0xff);
1371 rsp_buffer_push(rsp
, (val
+ 1) & 0xff);
1372 rsp_buffer_push(rsp
, ((val
+ 1) >> 8) & 0xff);
1374 for (; cmd
[6] < cmd
[7]; cmd
[6]++) {
1375 rsp_buffer_push(rsp
, ibs
->sel
.sel
[val
][cmd
[6]]);
1379 static void add_sel_entry(IPMIBmcSim
*ibs
,
1380 uint8_t *cmd
, unsigned int cmd_len
,
1383 if (sel_add_event(ibs
, cmd
+ 2)) {
1384 rsp_buffer_set_error(rsp
, IPMI_CC_OUT_OF_SPACE
);
1387 /* sel_add_event fills in the record number. */
1388 rsp_buffer_push(rsp
, cmd
[2]);
1389 rsp_buffer_push(rsp
, cmd
[3]);
1392 static void clear_sel(IPMIBmcSim
*ibs
,
1393 uint8_t *cmd
, unsigned int cmd_len
,
1396 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sel
.reservation
) {
1397 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1401 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1402 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1405 if (cmd
[7] == 0xaa) {
1406 ibs
->sel
.next_free
= 0;
1407 ibs
->sel
.overflow
= 0;
1408 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1409 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1410 sel_inc_reservation(&ibs
->sel
);
1411 } else if (cmd
[7] == 0) {
1412 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1414 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1419 static void get_sel_time(IPMIBmcSim
*ibs
,
1420 uint8_t *cmd
, unsigned int cmd_len
,
1424 struct ipmi_time now
;
1427 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
1428 rsp_buffer_push(rsp
, val
& 0xff);
1429 rsp_buffer_push(rsp
, (val
>> 8) & 0xff);
1430 rsp_buffer_push(rsp
, (val
>> 16) & 0xff);
1431 rsp_buffer_push(rsp
, (val
>> 24) & 0xff);
1434 static void set_sel_time(IPMIBmcSim
*ibs
,
1435 uint8_t *cmd
, unsigned int cmd_len
,
1439 struct ipmi_time now
;
1441 val
= cmd
[2] | (cmd
[3] << 8) | (cmd
[4] << 16) | (cmd
[5] << 24);
1443 ibs
->sel
.time_offset
= now
.tv_sec
- ((long) val
);
1446 static void set_sensor_evt_enable(IPMIBmcSim
*ibs
,
1447 uint8_t *cmd
, unsigned int cmd_len
,
1452 if ((cmd
[2] >= MAX_SENSORS
) ||
1453 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1454 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1457 sens
= ibs
->sensors
+ cmd
[2];
1458 switch ((cmd
[3] >> 4) & 0x3) {
1459 case 0: /* Do not change */
1461 case 1: /* Enable bits */
1463 sens
->assert_enable
|= cmd
[4];
1466 sens
->assert_enable
|= cmd
[5] << 8;
1469 sens
->deassert_enable
|= cmd
[6];
1472 sens
->deassert_enable
|= cmd
[7] << 8;
1475 case 2: /* Disable bits */
1477 sens
->assert_enable
&= ~cmd
[4];
1480 sens
->assert_enable
&= ~(cmd
[5] << 8);
1483 sens
->deassert_enable
&= ~cmd
[6];
1486 sens
->deassert_enable
&= ~(cmd
[7] << 8);
1490 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1493 IPMI_SENSOR_SET_RET_STATUS(sens
, cmd
[3]);
1496 static void get_sensor_evt_enable(IPMIBmcSim
*ibs
,
1497 uint8_t *cmd
, unsigned int cmd_len
,
1502 if ((cmd
[2] >= MAX_SENSORS
) ||
1503 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1504 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1507 sens
= ibs
->sensors
+ cmd
[2];
1508 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1509 rsp_buffer_push(rsp
, sens
->assert_enable
& 0xff);
1510 rsp_buffer_push(rsp
, (sens
->assert_enable
>> 8) & 0xff);
1511 rsp_buffer_push(rsp
, sens
->deassert_enable
& 0xff);
1512 rsp_buffer_push(rsp
, (sens
->deassert_enable
>> 8) & 0xff);
1515 static void rearm_sensor_evts(IPMIBmcSim
*ibs
,
1516 uint8_t *cmd
, unsigned int cmd_len
,
1521 if ((cmd
[2] >= MAX_SENSORS
) ||
1522 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1523 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1526 sens
= ibs
->sensors
+ cmd
[2];
1528 if ((cmd
[3] & 0x80) == 0) {
1529 /* Just clear everything */
1535 static void get_sensor_evt_status(IPMIBmcSim
*ibs
,
1536 uint8_t *cmd
, unsigned int cmd_len
,
1541 if ((cmd
[2] >= MAX_SENSORS
) ||
1542 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1543 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1546 sens
= ibs
->sensors
+ cmd
[2];
1547 rsp_buffer_push(rsp
, sens
->reading
);
1548 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1549 rsp_buffer_push(rsp
, sens
->assert_states
& 0xff);
1550 rsp_buffer_push(rsp
, (sens
->assert_states
>> 8) & 0xff);
1551 rsp_buffer_push(rsp
, sens
->deassert_states
& 0xff);
1552 rsp_buffer_push(rsp
, (sens
->deassert_states
>> 8) & 0xff);
1555 static void get_sensor_reading(IPMIBmcSim
*ibs
,
1556 uint8_t *cmd
, unsigned int cmd_len
,
1561 if ((cmd
[2] >= MAX_SENSORS
) ||
1562 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1563 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1566 sens
= ibs
->sensors
+ cmd
[2];
1567 rsp_buffer_push(rsp
, sens
->reading
);
1568 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1569 rsp_buffer_push(rsp
, sens
->states
& 0xff);
1570 if (IPMI_SENSOR_IS_DISCRETE(sens
)) {
1571 rsp_buffer_push(rsp
, (sens
->states
>> 8) & 0xff);
1575 static void set_sensor_type(IPMIBmcSim
*ibs
,
1576 uint8_t *cmd
, unsigned int cmd_len
,
1582 if ((cmd
[2] >= MAX_SENSORS
) ||
1583 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1584 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1587 sens
= ibs
->sensors
+ cmd
[2];
1588 sens
->sensor_type
= cmd
[3];
1589 sens
->evt_reading_type_code
= cmd
[4] & 0x7f;
1592 static void get_sensor_type(IPMIBmcSim
*ibs
,
1593 uint8_t *cmd
, unsigned int cmd_len
,
1599 if ((cmd
[2] >= MAX_SENSORS
) ||
1600 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1601 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1604 sens
= ibs
->sensors
+ cmd
[2];
1605 rsp_buffer_push(rsp
, sens
->sensor_type
);
1606 rsp_buffer_push(rsp
, sens
->evt_reading_type_code
);
1610 static const IPMICmdHandler chassis_cmds
[] = {
1611 [IPMI_CMD_GET_CHASSIS_CAPABILITIES
] = { chassis_capabilities
},
1612 [IPMI_CMD_GET_CHASSIS_STATUS
] = { chassis_status
},
1613 [IPMI_CMD_CHASSIS_CONTROL
] = { chassis_control
, 3 },
1614 [IPMI_CMD_GET_SYS_RESTART_CAUSE
] = { chassis_get_sys_restart_cause
}
1616 static const IPMINetfn chassis_netfn
= {
1617 .cmd_nums
= ARRAY_SIZE(chassis_cmds
),
1618 .cmd_handlers
= chassis_cmds
1621 static const IPMICmdHandler sensor_event_cmds
[] = {
1622 [IPMI_CMD_SET_SENSOR_EVT_ENABLE
] = { set_sensor_evt_enable
, 4 },
1623 [IPMI_CMD_GET_SENSOR_EVT_ENABLE
] = { get_sensor_evt_enable
, 3 },
1624 [IPMI_CMD_REARM_SENSOR_EVTS
] = { rearm_sensor_evts
, 4 },
1625 [IPMI_CMD_GET_SENSOR_EVT_STATUS
] = { get_sensor_evt_status
, 3 },
1626 [IPMI_CMD_GET_SENSOR_READING
] = { get_sensor_reading
, 3 },
1627 [IPMI_CMD_SET_SENSOR_TYPE
] = { set_sensor_type
, 5 },
1628 [IPMI_CMD_GET_SENSOR_TYPE
] = { get_sensor_type
, 3 },
1630 static const IPMINetfn sensor_event_netfn
= {
1631 .cmd_nums
= ARRAY_SIZE(sensor_event_cmds
),
1632 .cmd_handlers
= sensor_event_cmds
1635 static const IPMICmdHandler app_cmds
[] = {
1636 [IPMI_CMD_GET_DEVICE_ID
] = { get_device_id
},
1637 [IPMI_CMD_COLD_RESET
] = { cold_reset
},
1638 [IPMI_CMD_WARM_RESET
] = { warm_reset
},
1639 [IPMI_CMD_SET_ACPI_POWER_STATE
] = { set_acpi_power_state
, 4 },
1640 [IPMI_CMD_GET_ACPI_POWER_STATE
] = { get_acpi_power_state
},
1641 [IPMI_CMD_GET_DEVICE_GUID
] = { get_device_guid
},
1642 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES
] = { set_bmc_global_enables
, 3 },
1643 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES
] = { get_bmc_global_enables
},
1644 [IPMI_CMD_CLR_MSG_FLAGS
] = { clr_msg_flags
, 3 },
1645 [IPMI_CMD_GET_MSG_FLAGS
] = { get_msg_flags
},
1646 [IPMI_CMD_GET_MSG
] = { get_msg
},
1647 [IPMI_CMD_SEND_MSG
] = { send_msg
, 3 },
1648 [IPMI_CMD_READ_EVT_MSG_BUF
] = { read_evt_msg_buf
},
1649 [IPMI_CMD_RESET_WATCHDOG_TIMER
] = { reset_watchdog_timer
},
1650 [IPMI_CMD_SET_WATCHDOG_TIMER
] = { set_watchdog_timer
, 8 },
1651 [IPMI_CMD_GET_WATCHDOG_TIMER
] = { get_watchdog_timer
},
1653 static const IPMINetfn app_netfn
= {
1654 .cmd_nums
= ARRAY_SIZE(app_cmds
),
1655 .cmd_handlers
= app_cmds
1658 static const IPMICmdHandler storage_cmds
[] = {
1659 [IPMI_CMD_GET_SDR_REP_INFO
] = { get_sdr_rep_info
},
1660 [IPMI_CMD_RESERVE_SDR_REP
] = { reserve_sdr_rep
},
1661 [IPMI_CMD_GET_SDR
] = { get_sdr
, 8 },
1662 [IPMI_CMD_ADD_SDR
] = { add_sdr
},
1663 [IPMI_CMD_CLEAR_SDR_REP
] = { clear_sdr_rep
, 8 },
1664 [IPMI_CMD_GET_SEL_INFO
] = { get_sel_info
},
1665 [IPMI_CMD_RESERVE_SEL
] = { reserve_sel
},
1666 [IPMI_CMD_GET_SEL_ENTRY
] = { get_sel_entry
, 8 },
1667 [IPMI_CMD_ADD_SEL_ENTRY
] = { add_sel_entry
, 18 },
1668 [IPMI_CMD_CLEAR_SEL
] = { clear_sel
, 8 },
1669 [IPMI_CMD_GET_SEL_TIME
] = { get_sel_time
, 6 },
1670 [IPMI_CMD_SET_SEL_TIME
] = { set_sel_time
},
1673 static const IPMINetfn storage_netfn
= {
1674 .cmd_nums
= ARRAY_SIZE(storage_cmds
),
1675 .cmd_handlers
= storage_cmds
1678 static void register_cmds(IPMIBmcSim
*s
)
1680 ipmi_register_netfn(s
, IPMI_NETFN_CHASSIS
, &chassis_netfn
);
1681 ipmi_register_netfn(s
, IPMI_NETFN_SENSOR_EVENT
, &sensor_event_netfn
);
1682 ipmi_register_netfn(s
, IPMI_NETFN_APP
, &app_netfn
);
1683 ipmi_register_netfn(s
, IPMI_NETFN_STORAGE
, &storage_netfn
);
1686 static uint8_t init_sdrs
[] = {
1687 /* Watchdog device */
1688 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1689 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1692 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1695 static void ipmi_sdr_init(IPMIBmcSim
*ibs
)
1702 sdrs_size
= sizeof(init_sdrs
);
1705 for (i
= 0; i
< sdrs_size
; i
+= len
) {
1706 struct ipmi_sdr_header
*sdrh
;
1708 if (i
+ IPMI_SDR_HEADER_SIZE
> sdrs_size
) {
1709 error_report("Problem with recid 0x%4.4x", i
);
1712 sdrh
= (struct ipmi_sdr_header
*) &sdrs
[i
];
1713 len
= ipmi_sdr_length(sdrh
);
1714 if (i
+ len
> sdrs_size
) {
1715 error_report("Problem with recid 0x%4.4x", i
);
1718 sdr_add_entry(ibs
, sdrh
, len
, NULL
);
1722 static const VMStateDescription vmstate_ipmi_sim
= {
1723 .name
= TYPE_IPMI_BMC_SIMULATOR
,
1725 .minimum_version_id
= 1,
1726 .fields
= (VMStateField
[]) {
1727 VMSTATE_UINT8(bmc_global_enables
, IPMIBmcSim
),
1728 VMSTATE_UINT8(msg_flags
, IPMIBmcSim
),
1729 VMSTATE_BOOL(watchdog_initialized
, IPMIBmcSim
),
1730 VMSTATE_UINT8(watchdog_use
, IPMIBmcSim
),
1731 VMSTATE_UINT8(watchdog_action
, IPMIBmcSim
),
1732 VMSTATE_UINT8(watchdog_pretimeout
, IPMIBmcSim
),
1733 VMSTATE_BOOL(watchdog_expired
, IPMIBmcSim
),
1734 VMSTATE_UINT16(watchdog_timeout
, IPMIBmcSim
),
1735 VMSTATE_BOOL(watchdog_running
, IPMIBmcSim
),
1736 VMSTATE_BOOL(watchdog_preaction_ran
, IPMIBmcSim
),
1737 VMSTATE_INT64(watchdog_expiry
, IPMIBmcSim
),
1738 VMSTATE_UINT8_ARRAY(evtbuf
, IPMIBmcSim
, 16),
1739 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].status
, IPMIBmcSim
),
1740 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].reading
, IPMIBmcSim
),
1741 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].states
, IPMIBmcSim
),
1742 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_states
, IPMIBmcSim
),
1743 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].deassert_states
,
1745 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_enable
, IPMIBmcSim
),
1746 VMSTATE_END_OF_LIST()
1750 static void ipmi_sim_realize(DeviceState
*dev
, Error
**errp
)
1752 IPMIBmc
*b
= IPMI_BMC(dev
);
1754 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
1756 qemu_mutex_init(&ibs
->lock
);
1757 QTAILQ_INIT(&ibs
->rcvbufs
);
1759 ibs
->bmc_global_enables
= (1 << IPMI_BMC_EVENT_LOG_BIT
);
1760 ibs
->device_id
= 0x20;
1761 ibs
->ipmi_version
= 0x02; /* IPMI 2.0 */
1762 ibs
->restart_cause
= 0;
1763 for (i
= 0; i
< 4; i
++) {
1764 ibs
->sel
.last_addition
[i
] = 0xff;
1765 ibs
->sel
.last_clear
[i
] = 0xff;
1766 ibs
->sdr
.last_addition
[i
] = 0xff;
1767 ibs
->sdr
.last_clear
[i
] = 0xff;
1772 ibs
->acpi_power_state
[0] = 0;
1773 ibs
->acpi_power_state
[1] = 0;
1775 if (qemu_uuid_set
) {
1776 memcpy(&ibs
->uuid
, qemu_uuid
, 16);
1778 memset(&ibs
->uuid
, 0, 16);
1781 ipmi_init_sensors_from_sdrs(ibs
);
1784 ibs
->timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, ipmi_timeout
, ibs
);
1786 vmstate_register(NULL
, 0, &vmstate_ipmi_sim
, ibs
);
1789 static void ipmi_sim_class_init(ObjectClass
*oc
, void *data
)
1791 DeviceClass
*dc
= DEVICE_CLASS(oc
);
1792 IPMIBmcClass
*bk
= IPMI_BMC_CLASS(oc
);
1794 dc
->realize
= ipmi_sim_realize
;
1795 bk
->handle_command
= ipmi_sim_handle_command
;
1798 static const TypeInfo ipmi_sim_type
= {
1799 .name
= TYPE_IPMI_BMC_SIMULATOR
,
1800 .parent
= TYPE_IPMI_BMC
,
1801 .instance_size
= sizeof(IPMIBmcSim
),
1802 .class_init
= ipmi_sim_class_init
,
1805 static void ipmi_sim_register_types(void)
1807 type_register_static(&ipmi_sim_type
);
1810 type_init(ipmi_sim_register_types
)