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];
220 /* We allow one event in the buffer */
223 QTAILQ_HEAD(, IPMIRcvBufEntry
) rcvbufs
;
226 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
227 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
228 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
229 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
230 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
231 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
232 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
233 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
234 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
236 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
237 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
238 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
239 #define IPMI_BMC_EVENT_LOG_BIT 3
240 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
241 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
242 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
243 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
244 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
245 (1 << IPMI_BMC_EVENT_LOG_BIT))
246 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
247 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
249 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
250 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
251 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
252 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
253 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
254 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
255 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
256 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
257 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
258 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
259 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
260 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
261 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
262 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
263 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
266 uint8_t buffer
[MAX_IPMI_MSG_SIZE
];
270 #define RSP_BUFFER_INITIALIZER { }
272 static inline void rsp_buffer_set_error(RspBuffer
*rsp
, uint8_t byte
)
274 rsp
->buffer
[2] = byte
;
277 /* Add a byte to the response. */
278 static inline void rsp_buffer_push(RspBuffer
*rsp
, uint8_t byte
)
280 if (rsp
->len
>= sizeof(rsp
->buffer
)) {
281 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
284 rsp
->buffer
[rsp
->len
++] = byte
;
287 static inline void rsp_buffer_pushmore(RspBuffer
*rsp
, uint8_t *bytes
,
290 if (rsp
->len
+ n
>= sizeof(rsp
->buffer
)) {
291 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
295 memcpy(&rsp
->buffer
[rsp
->len
], bytes
, n
);
299 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
);
301 static void ipmi_gettime(struct ipmi_time
*time
)
305 stime
= qemu_clock_get_ns(QEMU_CLOCK_HOST
);
306 time
->tv_sec
= stime
/ 1000000000LL;
307 time
->tv_nsec
= stime
% 1000000000LL;
310 static int64_t ipmi_getmonotime(void)
312 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
315 static void ipmi_timeout(void *opaque
)
317 IPMIBmcSim
*ibs
= opaque
;
319 ipmi_sim_handle_timeout(ibs
);
322 static void set_timestamp(IPMIBmcSim
*ibs
, uint8_t *ts
)
325 struct ipmi_time now
;
328 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
330 ts
[1] = (val
>> 8) & 0xff;
331 ts
[2] = (val
>> 16) & 0xff;
332 ts
[3] = (val
>> 24) & 0xff;
335 static void sdr_inc_reservation(IPMISdr
*sdr
)
338 if (sdr
->reservation
== 0) {
339 sdr
->reservation
= 1;
343 static int sdr_add_entry(IPMIBmcSim
*ibs
,
344 const struct ipmi_sdr_header
*sdrh_entry
,
345 unsigned int len
, uint16_t *recid
)
347 struct ipmi_sdr_header
*sdrh
=
348 (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[ibs
->sdr
.next_free
];
350 if ((len
< IPMI_SDR_HEADER_SIZE
) || (len
> 255)) {
354 if (ipmi_sdr_length(sdrh_entry
) != len
) {
358 if (ibs
->sdr
.next_free
+ len
> MAX_SDR_SIZE
) {
359 ibs
->sdr
.overflow
= 1;
363 memcpy(sdrh
, sdrh_entry
, len
);
364 sdrh
->rec_id
[0] = ibs
->sdr
.next_rec_id
& 0xff;
365 sdrh
->rec_id
[1] = (ibs
->sdr
.next_rec_id
>> 8) & 0xff;
366 sdrh
->sdr_version
= 0x51; /* Conform to IPMI 1.5 spec */
369 *recid
= ibs
->sdr
.next_rec_id
;
371 ibs
->sdr
.next_rec_id
++;
372 set_timestamp(ibs
, ibs
->sdr
.last_addition
);
373 ibs
->sdr
.next_free
+= len
;
374 sdr_inc_reservation(&ibs
->sdr
);
378 static int sdr_find_entry(IPMISdr
*sdr
, uint16_t recid
,
379 unsigned int *retpos
, uint16_t *nextrec
)
381 unsigned int pos
= *retpos
;
383 while (pos
< sdr
->next_free
) {
384 struct ipmi_sdr_header
*sdrh
=
385 (struct ipmi_sdr_header
*) &sdr
->sdr
[pos
];
386 uint16_t trec
= ipmi_sdr_recid(sdrh
);
387 unsigned int nextpos
= pos
+ ipmi_sdr_length(sdrh
);
391 if (nextpos
>= sdr
->next_free
) {
394 *nextrec
= (sdr
->sdr
[nextpos
] |
395 (sdr
->sdr
[nextpos
+ 1] << 8));
406 static void sel_inc_reservation(IPMISel
*sel
)
409 if (sel
->reservation
== 0) {
410 sel
->reservation
= 1;
414 /* Returns 1 if the SEL is full and can't hold the event. */
415 static int sel_add_event(IPMIBmcSim
*ibs
, uint8_t *event
)
419 set_timestamp(ibs
, event
+ 3);
420 if (ibs
->sel
.next_free
== MAX_SEL_SIZE
) {
421 ibs
->sel
.overflow
= 1;
424 event
[0] = ibs
->sel
.next_free
& 0xff;
425 event
[1] = (ibs
->sel
.next_free
>> 8) & 0xff;
426 memcpy(ibs
->sel
.last_addition
, event
+ 3, 4);
427 memcpy(ibs
->sel
.sel
[ibs
->sel
.next_free
], event
, 16);
428 ibs
->sel
.next_free
++;
429 sel_inc_reservation(&ibs
->sel
);
433 static int attn_set(IPMIBmcSim
*ibs
)
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
);
440 static int attn_irq_enabled(IPMIBmcSim
*ibs
)
442 return (IPMI_BMC_MSG_INTS_ON(ibs
) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
))
443 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs
) &&
444 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
));
447 static void gen_event(IPMIBmcSim
*ibs
, unsigned int sens_num
, uint8_t deassert
,
448 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
450 IPMIInterface
*s
= ibs
->parent
.intf
;
451 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
453 IPMISensor
*sens
= ibs
->sensors
+ sens_num
;
455 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
458 if (!IPMI_SENSOR_GET_EVENTS_ON(sens
)) {
462 evt
[2] = 0x2; /* System event record */
463 evt
[7] = ibs
->parent
.slave_addr
;
465 evt
[9] = 0x04; /* Format version */
466 evt
[10] = sens
->sensor_type
;
468 evt
[12] = sens
->evt_reading_type_code
| (!!deassert
<< 7);
473 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
474 sel_add_event(ibs
, evt
);
477 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
481 memcpy(ibs
->evtbuf
, evt
, 16);
482 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
483 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
486 static void sensor_set_discrete_bit(IPMIBmcSim
*ibs
, unsigned int sensor
,
487 unsigned int bit
, unsigned int val
,
488 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
493 if (sensor
>= MAX_SENSORS
) {
501 sens
= ibs
->sensors
+ sensor
;
503 sens
->states
|= mask
& sens
->states_suppt
;
504 if (sens
->assert_states
& mask
) {
505 return; /* Already asserted */
507 sens
->assert_states
|= mask
& sens
->assert_suppt
;
508 if (sens
->assert_enable
& mask
& sens
->assert_states
) {
509 /* Send an event on assert */
510 gen_event(ibs
, sensor
, 0, evd1
, evd2
, evd3
);
513 sens
->states
&= ~(mask
& sens
->states_suppt
);
514 if (sens
->deassert_states
& mask
) {
515 return; /* Already deasserted */
517 sens
->deassert_states
|= mask
& sens
->deassert_suppt
;
518 if (sens
->deassert_enable
& mask
& sens
->deassert_states
) {
519 /* Send an event on deassert */
520 gen_event(ibs
, sensor
, 1, evd1
, evd2
, evd3
);
525 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim
*s
)
530 for (i
= 0; i
< MAX_SENSORS
; i
++) {
531 memset(s
->sensors
+ i
, 0, sizeof(*sens
));
535 for (i
= 0; !sdr_find_entry(&s
->sdr
, i
, &pos
, NULL
); i
++) {
536 struct ipmi_sdr_compact
*sdr
=
537 (struct ipmi_sdr_compact
*) &s
->sdr
.sdr
[pos
];
538 unsigned int len
= sdr
->header
.rec_length
;
543 if (sdr
->header
.rec_type
!= IPMI_SDR_COMPACT_TYPE
) {
544 continue; /* Not a sensor SDR we set from */
547 if (sdr
->sensor_owner_number
>= MAX_SENSORS
) {
550 sens
= s
->sensors
+ sdr
->sensor_owner_number
;
552 IPMI_SENSOR_SET_PRESENT(sens
, 1);
553 IPMI_SENSOR_SET_SCAN_ON(sens
, (sdr
->sensor_init
>> 6) & 1);
554 IPMI_SENSOR_SET_EVENTS_ON(sens
, (sdr
->sensor_init
>> 5) & 1);
555 sens
->assert_suppt
= sdr
->assert_mask
[0] | (sdr
->assert_mask
[1] << 8);
556 sens
->deassert_suppt
=
557 sdr
->deassert_mask
[0] | (sdr
->deassert_mask
[1] << 8);
559 sdr
->discrete_mask
[0] | (sdr
->discrete_mask
[1] << 8);
560 sens
->sensor_type
= sdr
->sensor_type
;
561 sens
->evt_reading_type_code
= sdr
->reading_type
& 0x7f;
563 /* Enable all the events that are supported. */
564 sens
->assert_enable
= sens
->assert_suppt
;
565 sens
->deassert_enable
= sens
->deassert_suppt
;
569 static int ipmi_register_netfn(IPMIBmcSim
*s
, unsigned int netfn
,
570 const IPMINetfn
*netfnd
)
572 if ((netfn
& 1) || (netfn
>= MAX_NETFNS
) || (s
->netfns
[netfn
/ 2])) {
575 s
->netfns
[netfn
/ 2] = netfnd
;
579 static const IPMICmdHandler
*ipmi_get_handler(IPMIBmcSim
*ibs
,
583 const IPMICmdHandler
*hdl
;
585 if (netfn
& 1 || netfn
>= MAX_NETFNS
|| !ibs
->netfns
[netfn
/ 2]) {
589 if (cmd
>= ibs
->netfns
[netfn
/ 2]->cmd_nums
) {
593 hdl
= &ibs
->netfns
[netfn
/ 2]->cmd_handlers
[cmd
];
594 if (!hdl
->cmd_handler
) {
601 static void next_timeout(IPMIBmcSim
*ibs
)
604 if (ibs
->watchdog_running
) {
605 next
= ibs
->watchdog_expiry
;
608 next
= ipmi_getmonotime() + 60 * 1000000000LL;
610 timer_mod_ns(ibs
->timer
, next
);
613 static void ipmi_sim_handle_command(IPMIBmc
*b
,
614 uint8_t *cmd
, unsigned int cmd_len
,
615 unsigned int max_cmd_len
,
618 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
619 IPMIInterface
*s
= ibs
->parent
.intf
;
620 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
621 const IPMICmdHandler
*hdl
;
622 RspBuffer rsp
= RSP_BUFFER_INITIALIZER
;
624 /* Set up the response, set the low bit of NETFN. */
625 /* Note that max_rsp_len must be at least 3 */
626 if (sizeof(rsp
.buffer
) < 3) {
627 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
631 rsp_buffer_push(&rsp
, cmd
[0] | 0x04);
632 rsp_buffer_push(&rsp
, cmd
[1]);
633 rsp_buffer_push(&rsp
, 0); /* Assume success */
635 /* If it's too short or it was truncated, return an error. */
637 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
640 if (cmd_len
> max_cmd_len
) {
641 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
645 if ((cmd
[0] & 0x03) != 0) {
646 /* Only have stuff on LUN 0 */
647 rsp_buffer_set_error(&rsp
, IPMI_CC_COMMAND_INVALID_FOR_LUN
);
651 hdl
= ipmi_get_handler(ibs
, cmd
[0] >> 2, cmd
[1]);
653 rsp_buffer_set_error(&rsp
, IPMI_CC_INVALID_CMD
);
657 if (cmd_len
< hdl
->cmd_len_min
) {
658 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
662 hdl
->cmd_handler(ibs
, cmd
, cmd_len
, &rsp
);
665 k
->handle_rsp(s
, msg_id
, rsp
.buffer
, rsp
.len
);
670 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
)
672 IPMIInterface
*s
= ibs
->parent
.intf
;
673 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
675 if (!ibs
->watchdog_running
) {
679 if (!ibs
->watchdog_preaction_ran
) {
680 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
)) {
681 case IPMI_BMC_WATCHDOG_PRE_NMI
:
682 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
683 k
->do_hw_op(s
, IPMI_SEND_NMI
, 0);
684 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
685 0xc8, (2 << 4) | 0xf, 0xff);
688 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
689 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
690 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
691 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
692 0xc8, (3 << 4) | 0xf, 0xff);
699 ibs
->watchdog_preaction_ran
= 1;
700 /* Issued the pretimeout, do the rest of the timeout now. */
701 ibs
->watchdog_expiry
= ipmi_getmonotime();
702 ibs
->watchdog_expiry
+= ibs
->watchdog_pretimeout
* 1000000000LL;
707 ibs
->watchdog_running
= 0; /* Stop the watchdog on a timeout */
708 ibs
->watchdog_expired
|= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs
));
709 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
)) {
710 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
711 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 0, 1,
712 0xc0, ibs
->watchdog_use
& 0xf, 0xff);
715 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
716 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 1, 1,
717 0xc1, ibs
->watchdog_use
& 0xf, 0xff);
718 k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0);
721 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
722 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
723 0xc2, ibs
->watchdog_use
& 0xf, 0xff);
724 k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0);
727 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
728 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
729 0xc3, ibs
->watchdog_use
& 0xf, 0xff);
730 k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0);
738 static void chassis_capabilities(IPMIBmcSim
*ibs
,
739 uint8_t *cmd
, unsigned int cmd_len
,
742 rsp_buffer_push(rsp
, 0);
743 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
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
);
749 static void chassis_status(IPMIBmcSim
*ibs
,
750 uint8_t *cmd
, unsigned int cmd_len
,
753 rsp_buffer_push(rsp
, 0x61); /* Unknown power restore, power is on */
754 rsp_buffer_push(rsp
, 0);
755 rsp_buffer_push(rsp
, 0);
756 rsp_buffer_push(rsp
, 0);
759 static void chassis_control(IPMIBmcSim
*ibs
,
760 uint8_t *cmd
, unsigned int cmd_len
,
763 IPMIInterface
*s
= ibs
->parent
.intf
;
764 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
766 switch (cmd
[2] & 0xf) {
767 case 0: /* power down */
768 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0));
770 case 1: /* power up */
771 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERON_CHASSIS
, 0));
773 case 2: /* power cycle */
774 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0));
776 case 3: /* hard reset */
777 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0));
779 case 4: /* pulse diagnostic interrupt */
780 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_PULSE_DIAG_IRQ
, 0));
782 case 5: /* soft shutdown via ACPI by overtemp emulation */
783 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
,
784 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP
, 0));
787 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
792 static void chassis_get_sys_restart_cause(IPMIBmcSim
*ibs
,
793 uint8_t *cmd
, unsigned int cmd_len
,
797 rsp_buffer_push(rsp
, ibs
->restart_cause
& 0xf); /* Restart Cause */
798 rsp_buffer_push(rsp
, 0); /* Channel 0 */
801 static void get_device_id(IPMIBmcSim
*ibs
,
802 uint8_t *cmd
, unsigned int cmd_len
,
805 rsp_buffer_push(rsp
, ibs
->device_id
);
806 rsp_buffer_push(rsp
, ibs
->device_rev
& 0xf);
807 rsp_buffer_push(rsp
, ibs
->fwrev1
& 0x7f);
808 rsp_buffer_push(rsp
, ibs
->fwrev2
);
809 rsp_buffer_push(rsp
, ibs
->ipmi_version
);
810 rsp_buffer_push(rsp
, 0x07); /* sensor, SDR, and SEL. */
811 rsp_buffer_push(rsp
, ibs
->mfg_id
[0]);
812 rsp_buffer_push(rsp
, ibs
->mfg_id
[1]);
813 rsp_buffer_push(rsp
, ibs
->mfg_id
[2]);
814 rsp_buffer_push(rsp
, ibs
->product_id
[0]);
815 rsp_buffer_push(rsp
, ibs
->product_id
[1]);
818 static void set_global_enables(IPMIBmcSim
*ibs
, uint8_t val
)
820 IPMIInterface
*s
= ibs
->parent
.intf
;
821 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
824 ibs
->bmc_global_enables
= val
;
826 irqs_on
= val
& (IPMI_BMC_EVBUF_FULL_INT_BIT
|
827 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT
);
829 k
->set_irq_enable(s
, irqs_on
);
832 static void cold_reset(IPMIBmcSim
*ibs
,
833 uint8_t *cmd
, unsigned int cmd_len
,
836 IPMIInterface
*s
= ibs
->parent
.intf
;
837 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
839 /* Disable all interrupts */
840 set_global_enables(ibs
, 1 << IPMI_BMC_EVENT_LOG_BIT
);
847 static void warm_reset(IPMIBmcSim
*ibs
,
848 uint8_t *cmd
, unsigned int cmd_len
,
851 IPMIInterface
*s
= ibs
->parent
.intf
;
852 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
858 static void set_acpi_power_state(IPMIBmcSim
*ibs
,
859 uint8_t *cmd
, unsigned int cmd_len
,
862 ibs
->acpi_power_state
[0] = cmd
[2];
863 ibs
->acpi_power_state
[1] = cmd
[3];
866 static void get_acpi_power_state(IPMIBmcSim
*ibs
,
867 uint8_t *cmd
, unsigned int cmd_len
,
870 rsp_buffer_push(rsp
, ibs
->acpi_power_state
[0]);
871 rsp_buffer_push(rsp
, ibs
->acpi_power_state
[1]);
874 static void get_device_guid(IPMIBmcSim
*ibs
,
875 uint8_t *cmd
, unsigned int cmd_len
,
880 for (i
= 0; i
< 16; i
++) {
881 rsp_buffer_push(rsp
, ibs
->uuid
[i
]);
885 static void set_bmc_global_enables(IPMIBmcSim
*ibs
,
886 uint8_t *cmd
, unsigned int cmd_len
,
889 set_global_enables(ibs
, cmd
[2]);
892 static void get_bmc_global_enables(IPMIBmcSim
*ibs
,
893 uint8_t *cmd
, unsigned int cmd_len
,
896 rsp_buffer_push(rsp
, ibs
->bmc_global_enables
);
899 static void clr_msg_flags(IPMIBmcSim
*ibs
,
900 uint8_t *cmd
, unsigned int cmd_len
,
903 IPMIInterface
*s
= ibs
->parent
.intf
;
904 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
906 ibs
->msg_flags
&= ~cmd
[2];
907 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
910 static void get_msg_flags(IPMIBmcSim
*ibs
,
911 uint8_t *cmd
, unsigned int cmd_len
,
914 rsp_buffer_push(rsp
, ibs
->msg_flags
);
917 static void read_evt_msg_buf(IPMIBmcSim
*ibs
,
918 uint8_t *cmd
, unsigned int cmd_len
,
921 IPMIInterface
*s
= ibs
->parent
.intf
;
922 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
925 if (!(ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
)) {
926 rsp_buffer_set_error(rsp
, 0x80);
929 for (i
= 0; i
< 16; i
++) {
930 rsp_buffer_push(rsp
, ibs
->evtbuf
[i
]);
932 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
933 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
936 static void get_msg(IPMIBmcSim
*ibs
,
937 uint8_t *cmd
, unsigned int cmd_len
,
940 IPMIRcvBufEntry
*msg
;
942 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
943 rsp_buffer_set_error(rsp
, 0x80); /* Queue empty */
946 rsp_buffer_push(rsp
, 0); /* Channel 0 */
947 msg
= QTAILQ_FIRST(&ibs
->rcvbufs
);
948 rsp_buffer_pushmore(rsp
, msg
->buf
, msg
->len
);
949 QTAILQ_REMOVE(&ibs
->rcvbufs
, msg
, entry
);
952 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
953 IPMIInterface
*s
= ibs
->parent
.intf
;
954 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
956 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
957 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
965 ipmb_checksum(unsigned char *data
, int size
, unsigned char csum
)
967 for (; size
> 0; size
--, data
++) {
974 static void send_msg(IPMIBmcSim
*ibs
,
975 uint8_t *cmd
, unsigned int cmd_len
,
978 IPMIInterface
*s
= ibs
->parent
.intf
;
979 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
980 IPMIRcvBufEntry
*msg
;
982 uint8_t netfn
, rqLun
, rsLun
, rqSeq
;
985 /* We only handle channel 0 with no options */
986 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
991 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
995 if (cmd
[3] != 0x40) {
996 /* We only emulate a MC at address 0x40. */
997 rsp_buffer_set_error(rsp
, 0x83); /* NAK on write */
1001 cmd
+= 3; /* Skip the header. */
1005 * At this point we "send" the message successfully. Any error will
1006 * be returned in the response.
1008 if (ipmb_checksum(cmd
, cmd_len
, 0) != 0 ||
1009 cmd
[3] != 0x20) { /* Improper response address */
1010 return; /* No response */
1013 netfn
= cmd
[1] >> 2;
1014 rqLun
= cmd
[4] & 0x3;
1015 rsLun
= cmd
[1] & 0x3;
1016 rqSeq
= cmd
[4] >> 2;
1019 /* We only support LUN 2 coming back to us. */
1023 msg
= g_malloc(sizeof(*msg
));
1024 msg
->buf
[0] = ((netfn
| 1) << 2) | rqLun
; /* NetFN, and make a response */
1025 msg
->buf
[1] = ipmb_checksum(msg
->buf
, 1, 0);
1026 msg
->buf
[2] = cmd
[0]; /* rsSA */
1027 msg
->buf
[3] = (rqSeq
<< 2) | rsLun
;
1028 msg
->buf
[4] = cmd
[5]; /* Cmd */
1029 msg
->buf
[5] = 0; /* Completion Code */
1032 if ((cmd
[1] >> 2) != IPMI_NETFN_APP
|| cmd
[5] != IPMI_CMD_GET_DEVICE_ID
) {
1033 /* Not a command we handle. */
1034 msg
->buf
[5] = IPMI_CC_INVALID_CMD
;
1038 buf
= msg
->buf
+ msg
->len
; /* After the CC */
1053 msg
->buf
[msg
->len
] = ipmb_checksum(msg
->buf
, msg
->len
, 0);
1055 QTAILQ_INSERT_TAIL(&ibs
->rcvbufs
, msg
, entry
);
1056 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
1057 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
1060 static void do_watchdog_reset(IPMIBmcSim
*ibs
)
1062 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
) ==
1063 IPMI_BMC_WATCHDOG_ACTION_NONE
) {
1064 ibs
->watchdog_running
= 0;
1067 ibs
->watchdog_preaction_ran
= 0;
1070 /* Timeout is in tenths of a second, offset is in seconds */
1071 ibs
->watchdog_expiry
= ipmi_getmonotime();
1072 ibs
->watchdog_expiry
+= ibs
->watchdog_timeout
* 100000000LL;
1073 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
) != IPMI_BMC_WATCHDOG_PRE_NONE
) {
1074 ibs
->watchdog_expiry
-= ibs
->watchdog_pretimeout
* 1000000000LL;
1076 ibs
->watchdog_running
= 1;
1079 static void reset_watchdog_timer(IPMIBmcSim
*ibs
,
1080 uint8_t *cmd
, unsigned int cmd_len
,
1083 if (!ibs
->watchdog_initialized
) {
1084 rsp_buffer_set_error(rsp
, 0x80);
1087 do_watchdog_reset(ibs
);
1090 static void set_watchdog_timer(IPMIBmcSim
*ibs
,
1091 uint8_t *cmd
, unsigned int cmd_len
,
1094 IPMIInterface
*s
= ibs
->parent
.intf
;
1095 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1098 val
= cmd
[2] & 0x7; /* Validate use */
1099 if (val
== 0 || val
> 5) {
1100 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1103 val
= cmd
[3] & 0x7; /* Validate action */
1105 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
1108 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
1109 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 1));
1112 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
1113 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 1));
1116 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
1117 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 1));
1121 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1123 if (rsp
->buffer
[2]) {
1124 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1128 val
= (cmd
[3] >> 4) & 0x7; /* Validate preaction */
1130 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
1131 case IPMI_BMC_WATCHDOG_PRE_NONE
:
1134 case IPMI_BMC_WATCHDOG_PRE_NMI
:
1135 if (!k
->do_hw_op(s
, IPMI_SEND_NMI
, 1)) {
1136 /* NMI not supported. */
1137 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1143 /* We don't support PRE_SMI */
1144 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1148 ibs
->watchdog_initialized
= 1;
1149 ibs
->watchdog_use
= cmd
[2] & IPMI_BMC_WATCHDOG_USE_MASK
;
1150 ibs
->watchdog_action
= cmd
[3] & IPMI_BMC_WATCHDOG_ACTION_MASK
;
1151 ibs
->watchdog_pretimeout
= cmd
[4];
1152 ibs
->watchdog_expired
&= ~cmd
[5];
1153 ibs
->watchdog_timeout
= cmd
[6] | (((uint16_t) cmd
[7]) << 8);
1154 if (ibs
->watchdog_running
& IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs
)) {
1155 do_watchdog_reset(ibs
);
1157 ibs
->watchdog_running
= 0;
1161 static void get_watchdog_timer(IPMIBmcSim
*ibs
,
1162 uint8_t *cmd
, unsigned int cmd_len
,
1165 rsp_buffer_push(rsp
, ibs
->watchdog_use
);
1166 rsp_buffer_push(rsp
, ibs
->watchdog_action
);
1167 rsp_buffer_push(rsp
, ibs
->watchdog_pretimeout
);
1168 rsp_buffer_push(rsp
, ibs
->watchdog_expired
);
1169 if (ibs
->watchdog_running
) {
1171 timeout
= ((ibs
->watchdog_expiry
- ipmi_getmonotime() + 50000000)
1173 rsp_buffer_push(rsp
, timeout
& 0xff);
1174 rsp_buffer_push(rsp
, (timeout
>> 8) & 0xff);
1176 rsp_buffer_push(rsp
, 0);
1177 rsp_buffer_push(rsp
, 0);
1181 static void get_sdr_rep_info(IPMIBmcSim
*ibs
,
1182 uint8_t *cmd
, unsigned int cmd_len
,
1187 rsp_buffer_push(rsp
, 0x51); /* Conform to IPMI 1.5 spec */
1188 rsp_buffer_push(rsp
, ibs
->sdr
.next_rec_id
& 0xff);
1189 rsp_buffer_push(rsp
, (ibs
->sdr
.next_rec_id
>> 8) & 0xff);
1190 rsp_buffer_push(rsp
, (MAX_SDR_SIZE
- ibs
->sdr
.next_free
) & 0xff);
1191 rsp_buffer_push(rsp
, ((MAX_SDR_SIZE
- ibs
->sdr
.next_free
) >> 8) & 0xff);
1192 for (i
= 0; i
< 4; i
++) {
1193 rsp_buffer_push(rsp
, ibs
->sdr
.last_addition
[i
]);
1195 for (i
= 0; i
< 4; i
++) {
1196 rsp_buffer_push(rsp
, ibs
->sdr
.last_clear
[i
]);
1198 /* Only modal support, reserve supported */
1199 rsp_buffer_push(rsp
, (ibs
->sdr
.overflow
<< 7) | 0x22);
1202 static void reserve_sdr_rep(IPMIBmcSim
*ibs
,
1203 uint8_t *cmd
, unsigned int cmd_len
,
1206 rsp_buffer_push(rsp
, ibs
->sdr
.reservation
& 0xff);
1207 rsp_buffer_push(rsp
, (ibs
->sdr
.reservation
>> 8) & 0xff);
1210 static void get_sdr(IPMIBmcSim
*ibs
,
1211 uint8_t *cmd
, unsigned int cmd_len
,
1216 struct ipmi_sdr_header
*sdrh
;
1219 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sdr
.reservation
) {
1220 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1226 if (sdr_find_entry(&ibs
->sdr
, cmd
[4] | (cmd
[5] << 8),
1228 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1232 sdrh
= (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[pos
];
1234 if (cmd
[6] > ipmi_sdr_length(sdrh
)) {
1235 rsp_buffer_set_error(rsp
, IPMI_CC_PARM_OUT_OF_RANGE
);
1239 rsp_buffer_push(rsp
, nextrec
& 0xff);
1240 rsp_buffer_push(rsp
, (nextrec
>> 8) & 0xff);
1242 if (cmd
[7] == 0xff) {
1243 cmd
[7] = ipmi_sdr_length(sdrh
) - cmd
[6];
1246 if ((cmd
[7] + rsp
->len
) > sizeof(rsp
->buffer
)) {
1247 rsp_buffer_set_error(rsp
, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES
);
1251 rsp_buffer_pushmore(rsp
, ibs
->sdr
.sdr
+ pos
+ cmd
[6], cmd
[7]);
1254 static void add_sdr(IPMIBmcSim
*ibs
,
1255 uint8_t *cmd
, unsigned int cmd_len
,
1259 struct ipmi_sdr_header
*sdrh
= (struct ipmi_sdr_header
*) cmd
+ 2;
1261 if (sdr_add_entry(ibs
, sdrh
, cmd_len
- 2, &recid
)) {
1262 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1265 rsp_buffer_push(rsp
, recid
& 0xff);
1266 rsp_buffer_push(rsp
, (recid
>> 8) & 0xff);
1269 static void clear_sdr_rep(IPMIBmcSim
*ibs
,
1270 uint8_t *cmd
, unsigned int cmd_len
,
1273 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sdr
.reservation
) {
1274 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1278 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1279 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1282 if (cmd
[7] == 0xaa) {
1283 ibs
->sdr
.next_free
= 0;
1284 ibs
->sdr
.overflow
= 0;
1285 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1286 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1287 sdr_inc_reservation(&ibs
->sdr
);
1288 } else if (cmd
[7] == 0) {
1289 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1291 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1296 static void get_sel_info(IPMIBmcSim
*ibs
,
1297 uint8_t *cmd
, unsigned int cmd_len
,
1300 unsigned int i
, val
;
1302 rsp_buffer_push(rsp
, 0x51); /* Conform to IPMI 1.5 */
1303 rsp_buffer_push(rsp
, ibs
->sel
.next_free
& 0xff);
1304 rsp_buffer_push(rsp
, (ibs
->sel
.next_free
>> 8) & 0xff);
1305 val
= (MAX_SEL_SIZE
- ibs
->sel
.next_free
) * 16;
1306 rsp_buffer_push(rsp
, val
& 0xff);
1307 rsp_buffer_push(rsp
, (val
>> 8) & 0xff);
1308 for (i
= 0; i
< 4; i
++) {
1309 rsp_buffer_push(rsp
, ibs
->sel
.last_addition
[i
]);
1311 for (i
= 0; i
< 4; i
++) {
1312 rsp_buffer_push(rsp
, ibs
->sel
.last_clear
[i
]);
1314 /* Only support Reserve SEL */
1315 rsp_buffer_push(rsp
, (ibs
->sel
.overflow
<< 7) | 0x02);
1318 static void reserve_sel(IPMIBmcSim
*ibs
,
1319 uint8_t *cmd
, unsigned int cmd_len
,
1322 rsp_buffer_push(rsp
, ibs
->sel
.reservation
& 0xff);
1323 rsp_buffer_push(rsp
, (ibs
->sel
.reservation
>> 8) & 0xff);
1326 static void get_sel_entry(IPMIBmcSim
*ibs
,
1327 uint8_t *cmd
, unsigned int cmd_len
,
1333 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sel
.reservation
) {
1334 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1338 if (ibs
->sel
.next_free
== 0) {
1339 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1343 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1346 if (cmd
[7] == 0xff) {
1348 } else if ((cmd
[7] + cmd
[6]) > 16) {
1349 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1355 val
= cmd
[4] | (cmd
[5] << 8);
1356 if (val
== 0xffff) {
1357 val
= ibs
->sel
.next_free
- 1;
1358 } else if (val
>= ibs
->sel
.next_free
) {
1359 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1362 if ((val
+ 1) == ibs
->sel
.next_free
) {
1363 rsp_buffer_push(rsp
, 0xff);
1364 rsp_buffer_push(rsp
, 0xff);
1366 rsp_buffer_push(rsp
, (val
+ 1) & 0xff);
1367 rsp_buffer_push(rsp
, ((val
+ 1) >> 8) & 0xff);
1369 for (; cmd
[6] < cmd
[7]; cmd
[6]++) {
1370 rsp_buffer_push(rsp
, ibs
->sel
.sel
[val
][cmd
[6]]);
1374 static void add_sel_entry(IPMIBmcSim
*ibs
,
1375 uint8_t *cmd
, unsigned int cmd_len
,
1378 if (sel_add_event(ibs
, cmd
+ 2)) {
1379 rsp_buffer_set_error(rsp
, IPMI_CC_OUT_OF_SPACE
);
1382 /* sel_add_event fills in the record number. */
1383 rsp_buffer_push(rsp
, cmd
[2]);
1384 rsp_buffer_push(rsp
, cmd
[3]);
1387 static void clear_sel(IPMIBmcSim
*ibs
,
1388 uint8_t *cmd
, unsigned int cmd_len
,
1391 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sel
.reservation
) {
1392 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1396 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1397 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1400 if (cmd
[7] == 0xaa) {
1401 ibs
->sel
.next_free
= 0;
1402 ibs
->sel
.overflow
= 0;
1403 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1404 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1405 sel_inc_reservation(&ibs
->sel
);
1406 } else if (cmd
[7] == 0) {
1407 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1409 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1414 static void get_sel_time(IPMIBmcSim
*ibs
,
1415 uint8_t *cmd
, unsigned int cmd_len
,
1419 struct ipmi_time now
;
1422 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
1423 rsp_buffer_push(rsp
, val
& 0xff);
1424 rsp_buffer_push(rsp
, (val
>> 8) & 0xff);
1425 rsp_buffer_push(rsp
, (val
>> 16) & 0xff);
1426 rsp_buffer_push(rsp
, (val
>> 24) & 0xff);
1429 static void set_sel_time(IPMIBmcSim
*ibs
,
1430 uint8_t *cmd
, unsigned int cmd_len
,
1434 struct ipmi_time now
;
1436 val
= cmd
[2] | (cmd
[3] << 8) | (cmd
[4] << 16) | (cmd
[5] << 24);
1438 ibs
->sel
.time_offset
= now
.tv_sec
- ((long) val
);
1441 static void set_sensor_evt_enable(IPMIBmcSim
*ibs
,
1442 uint8_t *cmd
, unsigned int cmd_len
,
1447 if ((cmd
[2] >= MAX_SENSORS
) ||
1448 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1449 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1452 sens
= ibs
->sensors
+ cmd
[2];
1453 switch ((cmd
[3] >> 4) & 0x3) {
1454 case 0: /* Do not change */
1456 case 1: /* Enable bits */
1458 sens
->assert_enable
|= cmd
[4];
1461 sens
->assert_enable
|= cmd
[5] << 8;
1464 sens
->deassert_enable
|= cmd
[6];
1467 sens
->deassert_enable
|= cmd
[7] << 8;
1470 case 2: /* Disable bits */
1472 sens
->assert_enable
&= ~cmd
[4];
1475 sens
->assert_enable
&= ~(cmd
[5] << 8);
1478 sens
->deassert_enable
&= ~cmd
[6];
1481 sens
->deassert_enable
&= ~(cmd
[7] << 8);
1485 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1488 IPMI_SENSOR_SET_RET_STATUS(sens
, cmd
[3]);
1491 static void get_sensor_evt_enable(IPMIBmcSim
*ibs
,
1492 uint8_t *cmd
, unsigned int cmd_len
,
1497 if ((cmd
[2] >= MAX_SENSORS
) ||
1498 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1499 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1502 sens
= ibs
->sensors
+ cmd
[2];
1503 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1504 rsp_buffer_push(rsp
, sens
->assert_enable
& 0xff);
1505 rsp_buffer_push(rsp
, (sens
->assert_enable
>> 8) & 0xff);
1506 rsp_buffer_push(rsp
, sens
->deassert_enable
& 0xff);
1507 rsp_buffer_push(rsp
, (sens
->deassert_enable
>> 8) & 0xff);
1510 static void rearm_sensor_evts(IPMIBmcSim
*ibs
,
1511 uint8_t *cmd
, unsigned int cmd_len
,
1516 if ((cmd
[2] >= MAX_SENSORS
) ||
1517 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1518 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1521 sens
= ibs
->sensors
+ cmd
[2];
1523 if ((cmd
[3] & 0x80) == 0) {
1524 /* Just clear everything */
1530 static void get_sensor_evt_status(IPMIBmcSim
*ibs
,
1531 uint8_t *cmd
, unsigned int cmd_len
,
1536 if ((cmd
[2] >= MAX_SENSORS
) ||
1537 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1538 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1541 sens
= ibs
->sensors
+ cmd
[2];
1542 rsp_buffer_push(rsp
, sens
->reading
);
1543 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1544 rsp_buffer_push(rsp
, sens
->assert_states
& 0xff);
1545 rsp_buffer_push(rsp
, (sens
->assert_states
>> 8) & 0xff);
1546 rsp_buffer_push(rsp
, sens
->deassert_states
& 0xff);
1547 rsp_buffer_push(rsp
, (sens
->deassert_states
>> 8) & 0xff);
1550 static void get_sensor_reading(IPMIBmcSim
*ibs
,
1551 uint8_t *cmd
, unsigned int cmd_len
,
1556 if ((cmd
[2] >= MAX_SENSORS
) ||
1557 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1558 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1561 sens
= ibs
->sensors
+ cmd
[2];
1562 rsp_buffer_push(rsp
, sens
->reading
);
1563 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1564 rsp_buffer_push(rsp
, sens
->states
& 0xff);
1565 if (IPMI_SENSOR_IS_DISCRETE(sens
)) {
1566 rsp_buffer_push(rsp
, (sens
->states
>> 8) & 0xff);
1570 static void set_sensor_type(IPMIBmcSim
*ibs
,
1571 uint8_t *cmd
, unsigned int cmd_len
,
1577 if ((cmd
[2] >= MAX_SENSORS
) ||
1578 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1579 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1582 sens
= ibs
->sensors
+ cmd
[2];
1583 sens
->sensor_type
= cmd
[3];
1584 sens
->evt_reading_type_code
= cmd
[4] & 0x7f;
1587 static void get_sensor_type(IPMIBmcSim
*ibs
,
1588 uint8_t *cmd
, unsigned int cmd_len
,
1594 if ((cmd
[2] >= MAX_SENSORS
) ||
1595 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1596 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1599 sens
= ibs
->sensors
+ cmd
[2];
1600 rsp_buffer_push(rsp
, sens
->sensor_type
);
1601 rsp_buffer_push(rsp
, sens
->evt_reading_type_code
);
1605 static const IPMICmdHandler chassis_cmds
[] = {
1606 [IPMI_CMD_GET_CHASSIS_CAPABILITIES
] = { chassis_capabilities
},
1607 [IPMI_CMD_GET_CHASSIS_STATUS
] = { chassis_status
},
1608 [IPMI_CMD_CHASSIS_CONTROL
] = { chassis_control
, 3 },
1609 [IPMI_CMD_GET_SYS_RESTART_CAUSE
] = { chassis_get_sys_restart_cause
}
1611 static const IPMINetfn chassis_netfn
= {
1612 .cmd_nums
= ARRAY_SIZE(chassis_cmds
),
1613 .cmd_handlers
= chassis_cmds
1616 static const IPMICmdHandler sensor_event_cmds
[] = {
1617 [IPMI_CMD_SET_SENSOR_EVT_ENABLE
] = { set_sensor_evt_enable
, 4 },
1618 [IPMI_CMD_GET_SENSOR_EVT_ENABLE
] = { get_sensor_evt_enable
, 3 },
1619 [IPMI_CMD_REARM_SENSOR_EVTS
] = { rearm_sensor_evts
, 4 },
1620 [IPMI_CMD_GET_SENSOR_EVT_STATUS
] = { get_sensor_evt_status
, 3 },
1621 [IPMI_CMD_GET_SENSOR_READING
] = { get_sensor_reading
, 3 },
1622 [IPMI_CMD_SET_SENSOR_TYPE
] = { set_sensor_type
, 5 },
1623 [IPMI_CMD_GET_SENSOR_TYPE
] = { get_sensor_type
, 3 },
1625 static const IPMINetfn sensor_event_netfn
= {
1626 .cmd_nums
= ARRAY_SIZE(sensor_event_cmds
),
1627 .cmd_handlers
= sensor_event_cmds
1630 static const IPMICmdHandler app_cmds
[] = {
1631 [IPMI_CMD_GET_DEVICE_ID
] = { get_device_id
},
1632 [IPMI_CMD_COLD_RESET
] = { cold_reset
},
1633 [IPMI_CMD_WARM_RESET
] = { warm_reset
},
1634 [IPMI_CMD_SET_ACPI_POWER_STATE
] = { set_acpi_power_state
, 4 },
1635 [IPMI_CMD_GET_ACPI_POWER_STATE
] = { get_acpi_power_state
},
1636 [IPMI_CMD_GET_DEVICE_GUID
] = { get_device_guid
},
1637 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES
] = { set_bmc_global_enables
, 3 },
1638 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES
] = { get_bmc_global_enables
},
1639 [IPMI_CMD_CLR_MSG_FLAGS
] = { clr_msg_flags
, 3 },
1640 [IPMI_CMD_GET_MSG_FLAGS
] = { get_msg_flags
},
1641 [IPMI_CMD_GET_MSG
] = { get_msg
},
1642 [IPMI_CMD_SEND_MSG
] = { send_msg
, 3 },
1643 [IPMI_CMD_READ_EVT_MSG_BUF
] = { read_evt_msg_buf
},
1644 [IPMI_CMD_RESET_WATCHDOG_TIMER
] = { reset_watchdog_timer
},
1645 [IPMI_CMD_SET_WATCHDOG_TIMER
] = { set_watchdog_timer
, 8 },
1646 [IPMI_CMD_GET_WATCHDOG_TIMER
] = { get_watchdog_timer
},
1648 static const IPMINetfn app_netfn
= {
1649 .cmd_nums
= ARRAY_SIZE(app_cmds
),
1650 .cmd_handlers
= app_cmds
1653 static const IPMICmdHandler storage_cmds
[] = {
1654 [IPMI_CMD_GET_SDR_REP_INFO
] = { get_sdr_rep_info
},
1655 [IPMI_CMD_RESERVE_SDR_REP
] = { reserve_sdr_rep
},
1656 [IPMI_CMD_GET_SDR
] = { get_sdr
, 8 },
1657 [IPMI_CMD_ADD_SDR
] = { add_sdr
},
1658 [IPMI_CMD_CLEAR_SDR_REP
] = { clear_sdr_rep
, 8 },
1659 [IPMI_CMD_GET_SEL_INFO
] = { get_sel_info
},
1660 [IPMI_CMD_RESERVE_SEL
] = { reserve_sel
},
1661 [IPMI_CMD_GET_SEL_ENTRY
] = { get_sel_entry
, 8 },
1662 [IPMI_CMD_ADD_SEL_ENTRY
] = { add_sel_entry
, 18 },
1663 [IPMI_CMD_CLEAR_SEL
] = { clear_sel
, 8 },
1664 [IPMI_CMD_GET_SEL_TIME
] = { get_sel_time
, 6 },
1665 [IPMI_CMD_SET_SEL_TIME
] = { set_sel_time
},
1668 static const IPMINetfn storage_netfn
= {
1669 .cmd_nums
= ARRAY_SIZE(storage_cmds
),
1670 .cmd_handlers
= storage_cmds
1673 static void register_cmds(IPMIBmcSim
*s
)
1675 ipmi_register_netfn(s
, IPMI_NETFN_CHASSIS
, &chassis_netfn
);
1676 ipmi_register_netfn(s
, IPMI_NETFN_SENSOR_EVENT
, &sensor_event_netfn
);
1677 ipmi_register_netfn(s
, IPMI_NETFN_APP
, &app_netfn
);
1678 ipmi_register_netfn(s
, IPMI_NETFN_STORAGE
, &storage_netfn
);
1681 static uint8_t init_sdrs
[] = {
1682 /* Watchdog device */
1683 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1684 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1685 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1687 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1690 static void ipmi_sdr_init(IPMIBmcSim
*ibs
)
1697 sdrs_size
= sizeof(init_sdrs
);
1700 for (i
= 0; i
< sdrs_size
; i
+= len
) {
1701 struct ipmi_sdr_header
*sdrh
;
1703 if (i
+ IPMI_SDR_HEADER_SIZE
> sdrs_size
) {
1704 error_report("Problem with recid 0x%4.4x", i
);
1707 sdrh
= (struct ipmi_sdr_header
*) &sdrs
[i
];
1708 len
= ipmi_sdr_length(sdrh
);
1709 if (i
+ len
> sdrs_size
) {
1710 error_report("Problem with recid 0x%4.4x", i
);
1713 sdr_add_entry(ibs
, sdrh
, len
, NULL
);
1717 static const VMStateDescription vmstate_ipmi_sim
= {
1718 .name
= TYPE_IPMI_BMC_SIMULATOR
,
1720 .minimum_version_id
= 1,
1721 .fields
= (VMStateField
[]) {
1722 VMSTATE_UINT8(bmc_global_enables
, IPMIBmcSim
),
1723 VMSTATE_UINT8(msg_flags
, IPMIBmcSim
),
1724 VMSTATE_BOOL(watchdog_initialized
, IPMIBmcSim
),
1725 VMSTATE_UINT8(watchdog_use
, IPMIBmcSim
),
1726 VMSTATE_UINT8(watchdog_action
, IPMIBmcSim
),
1727 VMSTATE_UINT8(watchdog_pretimeout
, IPMIBmcSim
),
1728 VMSTATE_BOOL(watchdog_expired
, IPMIBmcSim
),
1729 VMSTATE_UINT16(watchdog_timeout
, IPMIBmcSim
),
1730 VMSTATE_BOOL(watchdog_running
, IPMIBmcSim
),
1731 VMSTATE_BOOL(watchdog_preaction_ran
, IPMIBmcSim
),
1732 VMSTATE_INT64(watchdog_expiry
, IPMIBmcSim
),
1733 VMSTATE_UINT8_ARRAY(evtbuf
, IPMIBmcSim
, 16),
1734 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].status
, IPMIBmcSim
),
1735 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].reading
, IPMIBmcSim
),
1736 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].states
, IPMIBmcSim
),
1737 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_states
, IPMIBmcSim
),
1738 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].deassert_states
,
1740 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_enable
, IPMIBmcSim
),
1741 VMSTATE_END_OF_LIST()
1745 static void ipmi_sim_realize(DeviceState
*dev
, Error
**errp
)
1747 IPMIBmc
*b
= IPMI_BMC(dev
);
1749 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
1751 QTAILQ_INIT(&ibs
->rcvbufs
);
1753 ibs
->bmc_global_enables
= (1 << IPMI_BMC_EVENT_LOG_BIT
);
1754 ibs
->device_id
= 0x20;
1755 ibs
->ipmi_version
= 0x02; /* IPMI 2.0 */
1756 ibs
->restart_cause
= 0;
1757 for (i
= 0; i
< 4; i
++) {
1758 ibs
->sel
.last_addition
[i
] = 0xff;
1759 ibs
->sel
.last_clear
[i
] = 0xff;
1760 ibs
->sdr
.last_addition
[i
] = 0xff;
1761 ibs
->sdr
.last_clear
[i
] = 0xff;
1766 ibs
->acpi_power_state
[0] = 0;
1767 ibs
->acpi_power_state
[1] = 0;
1769 if (qemu_uuid_set
) {
1770 memcpy(&ibs
->uuid
, &qemu_uuid
, 16);
1772 memset(&ibs
->uuid
, 0, 16);
1775 ipmi_init_sensors_from_sdrs(ibs
);
1778 ibs
->timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, ipmi_timeout
, ibs
);
1780 vmstate_register(NULL
, 0, &vmstate_ipmi_sim
, ibs
);
1783 static void ipmi_sim_class_init(ObjectClass
*oc
, void *data
)
1785 DeviceClass
*dc
= DEVICE_CLASS(oc
);
1786 IPMIBmcClass
*bk
= IPMI_BMC_CLASS(oc
);
1788 dc
->hotpluggable
= false;
1789 dc
->realize
= ipmi_sim_realize
;
1790 bk
->handle_command
= ipmi_sim_handle_command
;
1793 static const TypeInfo ipmi_sim_type
= {
1794 .name
= TYPE_IPMI_BMC_SIMULATOR
,
1795 .parent
= TYPE_IPMI_BMC
,
1796 .instance_size
= sizeof(IPMIBmcSim
),
1797 .class_init
= ipmi_sim_class_init
,
1800 static void ipmi_sim_register_types(void)
1802 type_register_static(&ipmi_sim_type
);
1805 type_init(ipmi_sim_register_types
)