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
;
157 #define MAX_NETFNS 64
159 typedef struct IPMICmdHandler
{
160 void (*cmd_handler
)(IPMIBmcSim
*s
,
161 uint8_t *cmd
, unsigned int cmd_len
,
162 uint8_t *rsp
, unsigned int *rsp_len
,
163 unsigned int max_rsp_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 /* Add a byte to the response. */
268 #define IPMI_ADD_RSP_DATA(b) \
270 if (*rsp_len >= max_rsp_len) { \
271 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED; \
274 rsp[(*rsp_len)++] = (b); \
277 /* Check that the reservation in the command is valid. */
278 #define IPMI_CHECK_RESERVATION(off, r) \
280 if ((cmd[off] | (cmd[off + 1] << 8)) != r) { \
281 rsp[2] = IPMI_CC_INVALID_RESERVATION; \
287 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
);
289 static void ipmi_gettime(struct ipmi_time
*time
)
293 stime
= qemu_clock_get_ns(QEMU_CLOCK_HOST
);
294 time
->tv_sec
= stime
/ 1000000000LL;
295 time
->tv_nsec
= stime
% 1000000000LL;
298 static int64_t ipmi_getmonotime(void)
300 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
303 static void ipmi_timeout(void *opaque
)
305 IPMIBmcSim
*ibs
= opaque
;
307 ipmi_sim_handle_timeout(ibs
);
310 static void set_timestamp(IPMIBmcSim
*ibs
, uint8_t *ts
)
313 struct ipmi_time now
;
316 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
318 ts
[1] = (val
>> 8) & 0xff;
319 ts
[2] = (val
>> 16) & 0xff;
320 ts
[3] = (val
>> 24) & 0xff;
323 static void sdr_inc_reservation(IPMISdr
*sdr
)
326 if (sdr
->reservation
== 0) {
327 sdr
->reservation
= 1;
331 static int sdr_add_entry(IPMIBmcSim
*ibs
,
332 const struct ipmi_sdr_header
*sdrh_entry
,
333 unsigned int len
, uint16_t *recid
)
335 struct ipmi_sdr_header
*sdrh
=
336 (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[ibs
->sdr
.next_free
];
338 if ((len
< IPMI_SDR_HEADER_SIZE
) || (len
> 255)) {
342 if (ipmi_sdr_length(sdrh_entry
) != len
) {
346 if (ibs
->sdr
.next_free
+ len
> MAX_SDR_SIZE
) {
347 ibs
->sdr
.overflow
= 1;
351 memcpy(sdrh
, sdrh_entry
, len
);
352 sdrh
->rec_id
[0] = ibs
->sdr
.next_rec_id
& 0xff;
353 sdrh
->rec_id
[1] = (ibs
->sdr
.next_rec_id
>> 8) & 0xff;
354 sdrh
->sdr_version
= 0x51; /* Conform to IPMI 1.5 spec */
357 *recid
= ibs
->sdr
.next_rec_id
;
359 ibs
->sdr
.next_rec_id
++;
360 set_timestamp(ibs
, ibs
->sdr
.last_addition
);
361 ibs
->sdr
.next_free
+= len
;
362 sdr_inc_reservation(&ibs
->sdr
);
366 static int sdr_find_entry(IPMISdr
*sdr
, uint16_t recid
,
367 unsigned int *retpos
, uint16_t *nextrec
)
369 unsigned int pos
= *retpos
;
371 while (pos
< sdr
->next_free
) {
372 struct ipmi_sdr_header
*sdrh
=
373 (struct ipmi_sdr_header
*) &sdr
->sdr
[pos
];
374 uint16_t trec
= ipmi_sdr_recid(sdrh
);
375 unsigned int nextpos
= pos
+ ipmi_sdr_length(sdrh
);
379 if (nextpos
>= sdr
->next_free
) {
382 *nextrec
= (sdr
->sdr
[nextpos
] |
383 (sdr
->sdr
[nextpos
+ 1] << 8));
394 static void sel_inc_reservation(IPMISel
*sel
)
397 if (sel
->reservation
== 0) {
398 sel
->reservation
= 1;
402 /* Returns 1 if the SEL is full and can't hold the event. */
403 static int sel_add_event(IPMIBmcSim
*ibs
, uint8_t *event
)
407 set_timestamp(ibs
, event
+ 3);
408 if (ibs
->sel
.next_free
== MAX_SEL_SIZE
) {
409 ibs
->sel
.overflow
= 1;
412 event
[0] = ibs
->sel
.next_free
& 0xff;
413 event
[1] = (ibs
->sel
.next_free
>> 8) & 0xff;
414 memcpy(ibs
->sel
.last_addition
, event
+ 3, 4);
415 memcpy(ibs
->sel
.sel
[ibs
->sel
.next_free
], event
, 16);
416 ibs
->sel
.next_free
++;
417 sel_inc_reservation(&ibs
->sel
);
421 static int attn_set(IPMIBmcSim
*ibs
)
423 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
)
424 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
)
425 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs
);
428 static int attn_irq_enabled(IPMIBmcSim
*ibs
)
430 return (IPMI_BMC_MSG_INTS_ON(ibs
) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
))
431 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs
) &&
432 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
));
435 static void gen_event(IPMIBmcSim
*ibs
, unsigned int sens_num
, uint8_t deassert
,
436 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
438 IPMIInterface
*s
= ibs
->parent
.intf
;
439 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
441 IPMISensor
*sens
= ibs
->sensors
+ sens_num
;
443 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
446 if (!IPMI_SENSOR_GET_EVENTS_ON(sens
)) {
450 evt
[2] = 0x2; /* System event record */
451 evt
[7] = ibs
->parent
.slave_addr
;
453 evt
[9] = 0x04; /* Format version */
454 evt
[10] = sens
->sensor_type
;
456 evt
[12] = sens
->evt_reading_type_code
| (!!deassert
<< 7);
461 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
462 sel_add_event(ibs
, evt
);
465 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
469 memcpy(ibs
->evtbuf
, evt
, 16);
470 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
471 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
474 static void sensor_set_discrete_bit(IPMIBmcSim
*ibs
, unsigned int sensor
,
475 unsigned int bit
, unsigned int val
,
476 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
481 if (sensor
>= MAX_SENSORS
) {
489 sens
= ibs
->sensors
+ sensor
;
491 sens
->states
|= mask
& sens
->states_suppt
;
492 if (sens
->assert_states
& mask
) {
493 return; /* Already asserted */
495 sens
->assert_states
|= mask
& sens
->assert_suppt
;
496 if (sens
->assert_enable
& mask
& sens
->assert_states
) {
497 /* Send an event on assert */
498 gen_event(ibs
, sensor
, 0, evd1
, evd2
, evd3
);
501 sens
->states
&= ~(mask
& sens
->states_suppt
);
502 if (sens
->deassert_states
& mask
) {
503 return; /* Already deasserted */
505 sens
->deassert_states
|= mask
& sens
->deassert_suppt
;
506 if (sens
->deassert_enable
& mask
& sens
->deassert_states
) {
507 /* Send an event on deassert */
508 gen_event(ibs
, sensor
, 1, evd1
, evd2
, evd3
);
513 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim
*s
)
518 for (i
= 0; i
< MAX_SENSORS
; i
++) {
519 memset(s
->sensors
+ i
, 0, sizeof(*sens
));
523 for (i
= 0; !sdr_find_entry(&s
->sdr
, i
, &pos
, NULL
); i
++) {
524 struct ipmi_sdr_compact
*sdr
=
525 (struct ipmi_sdr_compact
*) &s
->sdr
.sdr
[pos
];
526 unsigned int len
= sdr
->header
.rec_length
;
531 if (sdr
->header
.rec_type
!= IPMI_SDR_COMPACT_TYPE
) {
532 continue; /* Not a sensor SDR we set from */
535 if (sdr
->sensor_owner_number
>= MAX_SENSORS
) {
538 sens
= s
->sensors
+ sdr
->sensor_owner_number
;
540 IPMI_SENSOR_SET_PRESENT(sens
, 1);
541 IPMI_SENSOR_SET_SCAN_ON(sens
, (sdr
->sensor_init
>> 6) & 1);
542 IPMI_SENSOR_SET_EVENTS_ON(sens
, (sdr
->sensor_init
>> 5) & 1);
543 sens
->assert_suppt
= sdr
->assert_mask
[0] | (sdr
->assert_mask
[1] << 8);
544 sens
->deassert_suppt
=
545 sdr
->deassert_mask
[0] | (sdr
->deassert_mask
[1] << 8);
547 sdr
->discrete_mask
[0] | (sdr
->discrete_mask
[1] << 8);
548 sens
->sensor_type
= sdr
->sensor_type
;
549 sens
->evt_reading_type_code
= sdr
->reading_type
& 0x7f;
551 /* Enable all the events that are supported. */
552 sens
->assert_enable
= sens
->assert_suppt
;
553 sens
->deassert_enable
= sens
->deassert_suppt
;
557 static int ipmi_register_netfn(IPMIBmcSim
*s
, unsigned int netfn
,
558 const IPMINetfn
*netfnd
)
560 if ((netfn
& 1) || (netfn
>= MAX_NETFNS
) || (s
->netfns
[netfn
/ 2])) {
563 s
->netfns
[netfn
/ 2] = netfnd
;
567 static const IPMICmdHandler
*ipmi_get_handler(IPMIBmcSim
*ibs
,
571 const IPMICmdHandler
*hdl
;
573 if (netfn
& 1 || netfn
>= MAX_NETFNS
|| !ibs
->netfns
[netfn
/ 2]) {
577 if (cmd
>= ibs
->netfns
[netfn
/ 2]->cmd_nums
) {
581 hdl
= &ibs
->netfns
[netfn
/ 2]->cmd_handlers
[cmd
];
582 if (!hdl
->cmd_handler
) {
589 static void next_timeout(IPMIBmcSim
*ibs
)
592 if (ibs
->watchdog_running
) {
593 next
= ibs
->watchdog_expiry
;
596 next
= ipmi_getmonotime() + 60 * 1000000000LL;
598 timer_mod_ns(ibs
->timer
, next
);
601 static void ipmi_sim_handle_command(IPMIBmc
*b
,
602 uint8_t *cmd
, unsigned int cmd_len
,
603 unsigned int max_cmd_len
,
606 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
607 IPMIInterface
*s
= ibs
->parent
.intf
;
608 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
609 uint8_t rsp
[MAX_IPMI_MSG_SIZE
];
610 unsigned int rsp_len_holder
= 0;
611 unsigned int *rsp_len
= &rsp_len_holder
;
612 unsigned int max_rsp_len
= sizeof(rsp
);
613 const IPMICmdHandler
*hdl
;
615 /* Set up the response, set the low bit of NETFN. */
616 /* Note that max_rsp_len must be at least 3 */
617 if (max_rsp_len
< 3) {
618 rsp
[2] = IPMI_CC_REQUEST_DATA_TRUNCATED
;
622 IPMI_ADD_RSP_DATA(cmd
[0] | 0x04);
623 IPMI_ADD_RSP_DATA(cmd
[1]);
624 IPMI_ADD_RSP_DATA(0); /* Assume success */
626 /* If it's too short or it was truncated, return an error. */
628 rsp
[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID
;
631 if (cmd_len
> max_cmd_len
) {
632 rsp
[2] = IPMI_CC_REQUEST_DATA_TRUNCATED
;
636 if ((cmd
[0] & 0x03) != 0) {
637 /* Only have stuff on LUN 0 */
638 rsp
[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN
;
642 hdl
= ipmi_get_handler(ibs
, cmd
[0] >> 2, cmd
[1]);
644 rsp
[2] = IPMI_CC_INVALID_CMD
;
648 if (cmd_len
< hdl
->cmd_len_min
) {
649 rsp
[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID
;
653 hdl
->cmd_handler(ibs
, cmd
, cmd_len
, rsp
, rsp_len
, max_rsp_len
);
656 k
->handle_rsp(s
, msg_id
, rsp
, *rsp_len
);
661 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
)
663 IPMIInterface
*s
= ibs
->parent
.intf
;
664 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
666 if (!ibs
->watchdog_running
) {
670 if (!ibs
->watchdog_preaction_ran
) {
671 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
)) {
672 case IPMI_BMC_WATCHDOG_PRE_NMI
:
673 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
674 k
->do_hw_op(s
, IPMI_SEND_NMI
, 0);
675 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
676 0xc8, (2 << 4) | 0xf, 0xff);
679 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
680 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
681 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
682 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
683 0xc8, (3 << 4) | 0xf, 0xff);
690 ibs
->watchdog_preaction_ran
= 1;
691 /* Issued the pretimeout, do the rest of the timeout now. */
692 ibs
->watchdog_expiry
= ipmi_getmonotime();
693 ibs
->watchdog_expiry
+= ibs
->watchdog_pretimeout
* 1000000000LL;
698 ibs
->watchdog_running
= 0; /* Stop the watchdog on a timeout */
699 ibs
->watchdog_expired
|= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs
));
700 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
)) {
701 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
702 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 0, 1,
703 0xc0, ibs
->watchdog_use
& 0xf, 0xff);
706 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
707 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 1, 1,
708 0xc1, ibs
->watchdog_use
& 0xf, 0xff);
709 k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0);
712 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
713 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
714 0xc2, ibs
->watchdog_use
& 0xf, 0xff);
715 k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0);
718 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
719 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
720 0xc3, ibs
->watchdog_use
& 0xf, 0xff);
721 k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0);
729 static void chassis_capabilities(IPMIBmcSim
*ibs
,
730 uint8_t *cmd
, unsigned int cmd_len
,
731 uint8_t *rsp
, unsigned int *rsp_len
,
732 unsigned int max_rsp_len
)
734 IPMI_ADD_RSP_DATA(0);
735 IPMI_ADD_RSP_DATA(ibs
->parent
.slave_addr
);
736 IPMI_ADD_RSP_DATA(ibs
->parent
.slave_addr
);
737 IPMI_ADD_RSP_DATA(ibs
->parent
.slave_addr
);
738 IPMI_ADD_RSP_DATA(ibs
->parent
.slave_addr
);
741 static void chassis_status(IPMIBmcSim
*ibs
,
742 uint8_t *cmd
, unsigned int cmd_len
,
743 uint8_t *rsp
, unsigned int *rsp_len
,
744 unsigned int max_rsp_len
)
746 IPMI_ADD_RSP_DATA(0x61); /* Unknown power restore, power is on */
747 IPMI_ADD_RSP_DATA(0);
748 IPMI_ADD_RSP_DATA(0);
749 IPMI_ADD_RSP_DATA(0);
752 static void chassis_control(IPMIBmcSim
*ibs
,
753 uint8_t *cmd
, unsigned int cmd_len
,
754 uint8_t *rsp
, unsigned int *rsp_len
,
755 unsigned int max_rsp_len
)
757 IPMIInterface
*s
= ibs
->parent
.intf
;
758 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
760 switch (cmd
[2] & 0xf) {
761 case 0: /* power down */
762 rsp
[2] = k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0);
764 case 1: /* power up */
765 rsp
[2] = k
->do_hw_op(s
, IPMI_POWERON_CHASSIS
, 0);
767 case 2: /* power cycle */
768 rsp
[2] = k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0);
770 case 3: /* hard reset */
771 rsp
[2] = k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0);
773 case 4: /* pulse diagnostic interrupt */
774 rsp
[2] = k
->do_hw_op(s
, IPMI_PULSE_DIAG_IRQ
, 0);
776 case 5: /* soft shutdown via ACPI by overtemp emulation */
777 rsp
[2] = k
->do_hw_op(s
,
778 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP
, 0);
781 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
786 static void chassis_get_sys_restart_cause(IPMIBmcSim
*ibs
,
787 uint8_t *cmd
, unsigned int cmd_len
,
788 uint8_t *rsp
, unsigned int *rsp_len
,
789 unsigned int max_rsp_len
)
791 IPMI_ADD_RSP_DATA(ibs
->restart_cause
& 0xf); /* Restart Cause */
792 IPMI_ADD_RSP_DATA(0); /* Channel 0 */
795 static void get_device_id(IPMIBmcSim
*ibs
,
796 uint8_t *cmd
, unsigned int cmd_len
,
797 uint8_t *rsp
, unsigned int *rsp_len
,
798 unsigned int max_rsp_len
)
800 IPMI_ADD_RSP_DATA(ibs
->device_id
);
801 IPMI_ADD_RSP_DATA(ibs
->device_rev
& 0xf);
802 IPMI_ADD_RSP_DATA(ibs
->fwrev1
& 0x7f);
803 IPMI_ADD_RSP_DATA(ibs
->fwrev2
);
804 IPMI_ADD_RSP_DATA(ibs
->ipmi_version
);
805 IPMI_ADD_RSP_DATA(0x07); /* sensor, SDR, and SEL. */
806 IPMI_ADD_RSP_DATA(ibs
->mfg_id
[0]);
807 IPMI_ADD_RSP_DATA(ibs
->mfg_id
[1]);
808 IPMI_ADD_RSP_DATA(ibs
->mfg_id
[2]);
809 IPMI_ADD_RSP_DATA(ibs
->product_id
[0]);
810 IPMI_ADD_RSP_DATA(ibs
->product_id
[1]);
813 static void set_global_enables(IPMIBmcSim
*ibs
, uint8_t val
)
815 IPMIInterface
*s
= ibs
->parent
.intf
;
816 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
819 ibs
->bmc_global_enables
= val
;
821 irqs_on
= val
& (IPMI_BMC_EVBUF_FULL_INT_BIT
|
822 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT
);
824 k
->set_irq_enable(s
, irqs_on
);
827 static void cold_reset(IPMIBmcSim
*ibs
,
828 uint8_t *cmd
, unsigned int cmd_len
,
829 uint8_t *rsp
, unsigned int *rsp_len
,
830 unsigned int max_rsp_len
)
832 IPMIInterface
*s
= ibs
->parent
.intf
;
833 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
835 /* Disable all interrupts */
836 set_global_enables(ibs
, 1 << IPMI_BMC_EVENT_LOG_BIT
);
843 static void warm_reset(IPMIBmcSim
*ibs
,
844 uint8_t *cmd
, unsigned int cmd_len
,
845 uint8_t *rsp
, unsigned int *rsp_len
,
846 unsigned int max_rsp_len
)
848 IPMIInterface
*s
= ibs
->parent
.intf
;
849 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
855 static void set_acpi_power_state(IPMIBmcSim
*ibs
,
856 uint8_t *cmd
, unsigned int cmd_len
,
857 uint8_t *rsp
, unsigned int *rsp_len
,
858 unsigned int max_rsp_len
)
860 ibs
->acpi_power_state
[0] = cmd
[2];
861 ibs
->acpi_power_state
[1] = cmd
[3];
864 static void get_acpi_power_state(IPMIBmcSim
*ibs
,
865 uint8_t *cmd
, unsigned int cmd_len
,
866 uint8_t *rsp
, unsigned int *rsp_len
,
867 unsigned int max_rsp_len
)
869 IPMI_ADD_RSP_DATA(ibs
->acpi_power_state
[0]);
870 IPMI_ADD_RSP_DATA(ibs
->acpi_power_state
[1]);
873 static void get_device_guid(IPMIBmcSim
*ibs
,
874 uint8_t *cmd
, unsigned int cmd_len
,
875 uint8_t *rsp
, unsigned int *rsp_len
,
876 unsigned int max_rsp_len
)
880 for (i
= 0; i
< 16; i
++) {
881 IPMI_ADD_RSP_DATA(ibs
->uuid
[i
]);
885 static void set_bmc_global_enables(IPMIBmcSim
*ibs
,
886 uint8_t *cmd
, unsigned int cmd_len
,
887 uint8_t *rsp
, unsigned int *rsp_len
,
888 unsigned int max_rsp_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
,
895 uint8_t *rsp
, unsigned int *rsp_len
,
896 unsigned int max_rsp_len
)
898 IPMI_ADD_RSP_DATA(ibs
->bmc_global_enables
);
901 static void clr_msg_flags(IPMIBmcSim
*ibs
,
902 uint8_t *cmd
, unsigned int cmd_len
,
903 uint8_t *rsp
, unsigned int *rsp_len
,
904 unsigned int max_rsp_len
)
906 IPMIInterface
*s
= ibs
->parent
.intf
;
907 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
909 ibs
->msg_flags
&= ~cmd
[2];
910 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
913 static void get_msg_flags(IPMIBmcSim
*ibs
,
914 uint8_t *cmd
, unsigned int cmd_len
,
915 uint8_t *rsp
, unsigned int *rsp_len
,
916 unsigned int max_rsp_len
)
918 IPMI_ADD_RSP_DATA(ibs
->msg_flags
);
921 static void read_evt_msg_buf(IPMIBmcSim
*ibs
,
922 uint8_t *cmd
, unsigned int cmd_len
,
923 uint8_t *rsp
, unsigned int *rsp_len
,
924 unsigned int max_rsp_len
)
926 IPMIInterface
*s
= ibs
->parent
.intf
;
927 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
930 if (!(ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
)) {
934 for (i
= 0; i
< 16; i
++) {
935 IPMI_ADD_RSP_DATA(ibs
->evtbuf
[i
]);
937 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
938 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
941 static void get_msg(IPMIBmcSim
*ibs
,
942 uint8_t *cmd
, unsigned int cmd_len
,
943 uint8_t *rsp
, unsigned int *rsp_len
,
944 unsigned int max_rsp_len
)
946 IPMIRcvBufEntry
*msg
;
948 qemu_mutex_lock(&ibs
->lock
);
949 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
950 rsp
[2] = 0x80; /* Queue empty */
953 rsp
[3] = 0; /* Channel 0 */
955 msg
= QTAILQ_FIRST(&ibs
->rcvbufs
);
956 memcpy(rsp
+ 4, msg
->buf
, msg
->len
);
957 *rsp_len
+= msg
->len
;
958 QTAILQ_REMOVE(&ibs
->rcvbufs
, msg
, entry
);
961 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
962 IPMIInterface
*s
= ibs
->parent
.intf
;
963 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
965 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
966 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
970 qemu_mutex_unlock(&ibs
->lock
);
975 ipmb_checksum(unsigned char *data
, int size
, unsigned char csum
)
977 for (; size
> 0; size
--, data
++) {
984 static void send_msg(IPMIBmcSim
*ibs
,
985 uint8_t *cmd
, unsigned int cmd_len
,
986 uint8_t *rsp
, unsigned int *rsp_len
,
987 unsigned int max_rsp_len
)
989 IPMIInterface
*s
= ibs
->parent
.intf
;
990 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
991 IPMIRcvBufEntry
*msg
;
993 uint8_t netfn
, rqLun
, rsLun
, rqSeq
;
996 /* We only handle channel 0 with no options */
997 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1002 rsp
[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID
;
1006 if (cmd
[3] != 0x40) {
1007 /* We only emulate a MC at address 0x40. */
1008 rsp
[2] = 0x83; /* NAK on write */
1012 cmd
+= 3; /* Skip the header. */
1016 * At this point we "send" the message successfully. Any error will
1017 * be returned in the response.
1019 if (ipmb_checksum(cmd
, cmd_len
, 0) != 0 ||
1020 cmd
[3] != 0x20) { /* Improper response address */
1021 return; /* No response */
1024 netfn
= cmd
[1] >> 2;
1025 rqLun
= cmd
[4] & 0x3;
1026 rsLun
= cmd
[1] & 0x3;
1027 rqSeq
= cmd
[4] >> 2;
1030 /* We only support LUN 2 coming back to us. */
1034 msg
= g_malloc(sizeof(*msg
));
1035 msg
->buf
[0] = ((netfn
| 1) << 2) | rqLun
; /* NetFN, and make a response */
1036 msg
->buf
[1] = ipmb_checksum(msg
->buf
, 1, 0);
1037 msg
->buf
[2] = cmd
[0]; /* rsSA */
1038 msg
->buf
[3] = (rqSeq
<< 2) | rsLun
;
1039 msg
->buf
[4] = cmd
[5]; /* Cmd */
1040 msg
->buf
[5] = 0; /* Completion Code */
1043 if ((cmd
[1] >> 2) != IPMI_NETFN_APP
|| cmd
[5] != IPMI_CMD_GET_DEVICE_ID
) {
1044 /* Not a command we handle. */
1045 msg
->buf
[5] = IPMI_CC_INVALID_CMD
;
1049 buf
= msg
->buf
+ msg
->len
; /* After the CC */
1064 msg
->buf
[msg
->len
] = ipmb_checksum(msg
->buf
, msg
->len
, 0);
1066 qemu_mutex_lock(&ibs
->lock
);
1067 QTAILQ_INSERT_TAIL(&ibs
->rcvbufs
, msg
, entry
);
1068 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
1069 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
1070 qemu_mutex_unlock(&ibs
->lock
);
1073 static void do_watchdog_reset(IPMIBmcSim
*ibs
)
1075 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
) ==
1076 IPMI_BMC_WATCHDOG_ACTION_NONE
) {
1077 ibs
->watchdog_running
= 0;
1080 ibs
->watchdog_preaction_ran
= 0;
1083 /* Timeout is in tenths of a second, offset is in seconds */
1084 ibs
->watchdog_expiry
= ipmi_getmonotime();
1085 ibs
->watchdog_expiry
+= ibs
->watchdog_timeout
* 100000000LL;
1086 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
) != IPMI_BMC_WATCHDOG_PRE_NONE
) {
1087 ibs
->watchdog_expiry
-= ibs
->watchdog_pretimeout
* 1000000000LL;
1089 ibs
->watchdog_running
= 1;
1092 static void reset_watchdog_timer(IPMIBmcSim
*ibs
,
1093 uint8_t *cmd
, unsigned int cmd_len
,
1094 uint8_t *rsp
, unsigned int *rsp_len
,
1095 unsigned int max_rsp_len
)
1097 if (!ibs
->watchdog_initialized
) {
1101 do_watchdog_reset(ibs
);
1104 static void set_watchdog_timer(IPMIBmcSim
*ibs
,
1105 uint8_t *cmd
, unsigned int cmd_len
,
1106 uint8_t *rsp
, unsigned int *rsp_len
,
1107 unsigned int max_rsp_len
)
1109 IPMIInterface
*s
= ibs
->parent
.intf
;
1110 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1113 val
= cmd
[2] & 0x7; /* Validate use */
1114 if (val
== 0 || val
> 5) {
1115 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1118 val
= cmd
[3] & 0x7; /* Validate action */
1120 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
1123 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
1124 rsp
[2] = k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 1);
1127 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
1128 rsp
[2] = k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 1);
1131 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
1132 rsp
[2] = k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 1);
1136 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1139 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1143 val
= (cmd
[3] >> 4) & 0x7; /* Validate preaction */
1145 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
1146 case IPMI_BMC_WATCHDOG_PRE_NONE
:
1149 case IPMI_BMC_WATCHDOG_PRE_NMI
:
1150 if (!k
->do_hw_op(s
, IPMI_SEND_NMI
, 1)) {
1151 /* NMI not supported. */
1152 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1158 /* We don't support PRE_SMI */
1159 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1163 ibs
->watchdog_initialized
= 1;
1164 ibs
->watchdog_use
= cmd
[2] & IPMI_BMC_WATCHDOG_USE_MASK
;
1165 ibs
->watchdog_action
= cmd
[3] & IPMI_BMC_WATCHDOG_ACTION_MASK
;
1166 ibs
->watchdog_pretimeout
= cmd
[4];
1167 ibs
->watchdog_expired
&= ~cmd
[5];
1168 ibs
->watchdog_timeout
= cmd
[6] | (((uint16_t) cmd
[7]) << 8);
1169 if (ibs
->watchdog_running
& IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs
)) {
1170 do_watchdog_reset(ibs
);
1172 ibs
->watchdog_running
= 0;
1176 static void get_watchdog_timer(IPMIBmcSim
*ibs
,
1177 uint8_t *cmd
, unsigned int cmd_len
,
1178 uint8_t *rsp
, unsigned int *rsp_len
,
1179 unsigned int max_rsp_len
)
1181 IPMI_ADD_RSP_DATA(ibs
->watchdog_use
);
1182 IPMI_ADD_RSP_DATA(ibs
->watchdog_action
);
1183 IPMI_ADD_RSP_DATA(ibs
->watchdog_pretimeout
);
1184 IPMI_ADD_RSP_DATA(ibs
->watchdog_expired
);
1185 if (ibs
->watchdog_running
) {
1187 timeout
= ((ibs
->watchdog_expiry
- ipmi_getmonotime() + 50000000)
1189 IPMI_ADD_RSP_DATA(timeout
& 0xff);
1190 IPMI_ADD_RSP_DATA((timeout
>> 8) & 0xff);
1192 IPMI_ADD_RSP_DATA(0);
1193 IPMI_ADD_RSP_DATA(0);
1197 static void get_sdr_rep_info(IPMIBmcSim
*ibs
,
1198 uint8_t *cmd
, unsigned int cmd_len
,
1199 uint8_t *rsp
, unsigned int *rsp_len
,
1200 unsigned int max_rsp_len
)
1204 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 spec */
1205 IPMI_ADD_RSP_DATA(ibs
->sdr
.next_rec_id
& 0xff);
1206 IPMI_ADD_RSP_DATA((ibs
->sdr
.next_rec_id
>> 8) & 0xff);
1207 IPMI_ADD_RSP_DATA((MAX_SDR_SIZE
- ibs
->sdr
.next_free
) & 0xff);
1208 IPMI_ADD_RSP_DATA(((MAX_SDR_SIZE
- ibs
->sdr
.next_free
) >> 8) & 0xff);
1209 for (i
= 0; i
< 4; i
++) {
1210 IPMI_ADD_RSP_DATA(ibs
->sdr
.last_addition
[i
]);
1212 for (i
= 0; i
< 4; i
++) {
1213 IPMI_ADD_RSP_DATA(ibs
->sdr
.last_clear
[i
]);
1215 /* Only modal support, reserve supported */
1216 IPMI_ADD_RSP_DATA((ibs
->sdr
.overflow
<< 7) | 0x22);
1219 static void reserve_sdr_rep(IPMIBmcSim
*ibs
,
1220 uint8_t *cmd
, unsigned int cmd_len
,
1221 uint8_t *rsp
, unsigned int *rsp_len
,
1222 unsigned int max_rsp_len
)
1224 IPMI_ADD_RSP_DATA(ibs
->sdr
.reservation
& 0xff);
1225 IPMI_ADD_RSP_DATA((ibs
->sdr
.reservation
>> 8) & 0xff);
1228 static void get_sdr(IPMIBmcSim
*ibs
,
1229 uint8_t *cmd
, unsigned int cmd_len
,
1230 uint8_t *rsp
, unsigned int *rsp_len
,
1231 unsigned int max_rsp_len
)
1235 struct ipmi_sdr_header
*sdrh
;
1238 IPMI_CHECK_RESERVATION(2, ibs
->sdr
.reservation
);
1241 if (sdr_find_entry(&ibs
->sdr
, cmd
[4] | (cmd
[5] << 8),
1243 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1247 sdrh
= (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[pos
];
1249 if (cmd
[6] > ipmi_sdr_length(sdrh
)) {
1250 rsp
[2] = IPMI_CC_PARM_OUT_OF_RANGE
;
1254 IPMI_ADD_RSP_DATA(nextrec
& 0xff);
1255 IPMI_ADD_RSP_DATA((nextrec
>> 8) & 0xff);
1257 if (cmd
[7] == 0xff) {
1258 cmd
[7] = ipmi_sdr_length(sdrh
) - cmd
[6];
1261 if ((cmd
[7] + *rsp_len
) > max_rsp_len
) {
1262 rsp
[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES
;
1265 memcpy(rsp
+ *rsp_len
, ibs
->sdr
.sdr
+ pos
+ cmd
[6], cmd
[7]);
1269 static void add_sdr(IPMIBmcSim
*ibs
,
1270 uint8_t *cmd
, unsigned int cmd_len
,
1271 uint8_t *rsp
, unsigned int *rsp_len
,
1272 unsigned int max_rsp_len
)
1275 struct ipmi_sdr_header
*sdrh
= (struct ipmi_sdr_header
*) cmd
+ 2;
1277 if (sdr_add_entry(ibs
, sdrh
, cmd_len
- 2, &recid
)) {
1278 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1281 IPMI_ADD_RSP_DATA(recid
& 0xff);
1282 IPMI_ADD_RSP_DATA((recid
>> 8) & 0xff);
1285 static void clear_sdr_rep(IPMIBmcSim
*ibs
,
1286 uint8_t *cmd
, unsigned int cmd_len
,
1287 uint8_t *rsp
, unsigned int *rsp_len
,
1288 unsigned int max_rsp_len
)
1290 IPMI_CHECK_RESERVATION(2, ibs
->sdr
.reservation
);
1291 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1292 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1295 if (cmd
[7] == 0xaa) {
1296 ibs
->sdr
.next_free
= 0;
1297 ibs
->sdr
.overflow
= 0;
1298 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1299 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1300 sdr_inc_reservation(&ibs
->sdr
);
1301 } else if (cmd
[7] == 0) {
1302 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1304 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1309 static void get_sel_info(IPMIBmcSim
*ibs
,
1310 uint8_t *cmd
, unsigned int cmd_len
,
1311 uint8_t *rsp
, unsigned int *rsp_len
,
1312 unsigned int max_rsp_len
)
1314 unsigned int i
, val
;
1316 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 */
1317 IPMI_ADD_RSP_DATA(ibs
->sel
.next_free
& 0xff);
1318 IPMI_ADD_RSP_DATA((ibs
->sel
.next_free
>> 8) & 0xff);
1319 val
= (MAX_SEL_SIZE
- ibs
->sel
.next_free
) * 16;
1320 IPMI_ADD_RSP_DATA(val
& 0xff);
1321 IPMI_ADD_RSP_DATA((val
>> 8) & 0xff);
1322 for (i
= 0; i
< 4; i
++) {
1323 IPMI_ADD_RSP_DATA(ibs
->sel
.last_addition
[i
]);
1325 for (i
= 0; i
< 4; i
++) {
1326 IPMI_ADD_RSP_DATA(ibs
->sel
.last_clear
[i
]);
1328 /* Only support Reserve SEL */
1329 IPMI_ADD_RSP_DATA((ibs
->sel
.overflow
<< 7) | 0x02);
1332 static void reserve_sel(IPMIBmcSim
*ibs
,
1333 uint8_t *cmd
, unsigned int cmd_len
,
1334 uint8_t *rsp
, unsigned int *rsp_len
,
1335 unsigned int max_rsp_len
)
1337 IPMI_ADD_RSP_DATA(ibs
->sel
.reservation
& 0xff);
1338 IPMI_ADD_RSP_DATA((ibs
->sel
.reservation
>> 8) & 0xff);
1341 static void get_sel_entry(IPMIBmcSim
*ibs
,
1342 uint8_t *cmd
, unsigned int cmd_len
,
1343 uint8_t *rsp
, unsigned int *rsp_len
,
1344 unsigned int max_rsp_len
)
1349 IPMI_CHECK_RESERVATION(2, ibs
->sel
.reservation
);
1351 if (ibs
->sel
.next_free
== 0) {
1352 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1356 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1359 if (cmd
[7] == 0xff) {
1361 } else if ((cmd
[7] + cmd
[6]) > 16) {
1362 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1368 val
= cmd
[4] | (cmd
[5] << 8);
1369 if (val
== 0xffff) {
1370 val
= ibs
->sel
.next_free
- 1;
1371 } else if (val
>= ibs
->sel
.next_free
) {
1372 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1375 if ((val
+ 1) == ibs
->sel
.next_free
) {
1376 IPMI_ADD_RSP_DATA(0xff);
1377 IPMI_ADD_RSP_DATA(0xff);
1379 IPMI_ADD_RSP_DATA((val
+ 1) & 0xff);
1380 IPMI_ADD_RSP_DATA(((val
+ 1) >> 8) & 0xff);
1382 for (; cmd
[6] < cmd
[7]; cmd
[6]++) {
1383 IPMI_ADD_RSP_DATA(ibs
->sel
.sel
[val
][cmd
[6]]);
1387 static void add_sel_entry(IPMIBmcSim
*ibs
,
1388 uint8_t *cmd
, unsigned int cmd_len
,
1389 uint8_t *rsp
, unsigned int *rsp_len
,
1390 unsigned int max_rsp_len
)
1392 if (sel_add_event(ibs
, cmd
+ 2)) {
1393 rsp
[2] = IPMI_CC_OUT_OF_SPACE
;
1396 /* sel_add_event fills in the record number. */
1397 IPMI_ADD_RSP_DATA(cmd
[2]);
1398 IPMI_ADD_RSP_DATA(cmd
[3]);
1401 static void clear_sel(IPMIBmcSim
*ibs
,
1402 uint8_t *cmd
, unsigned int cmd_len
,
1403 uint8_t *rsp
, unsigned int *rsp_len
,
1404 unsigned int max_rsp_len
)
1406 IPMI_CHECK_RESERVATION(2, ibs
->sel
.reservation
);
1407 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1408 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1411 if (cmd
[7] == 0xaa) {
1412 ibs
->sel
.next_free
= 0;
1413 ibs
->sel
.overflow
= 0;
1414 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1415 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1416 sel_inc_reservation(&ibs
->sel
);
1417 } else if (cmd
[7] == 0) {
1418 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1420 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1425 static void get_sel_time(IPMIBmcSim
*ibs
,
1426 uint8_t *cmd
, unsigned int cmd_len
,
1427 uint8_t *rsp
, unsigned int *rsp_len
,
1428 unsigned int max_rsp_len
)
1431 struct ipmi_time now
;
1434 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
1435 IPMI_ADD_RSP_DATA(val
& 0xff);
1436 IPMI_ADD_RSP_DATA((val
>> 8) & 0xff);
1437 IPMI_ADD_RSP_DATA((val
>> 16) & 0xff);
1438 IPMI_ADD_RSP_DATA((val
>> 24) & 0xff);
1441 static void set_sel_time(IPMIBmcSim
*ibs
,
1442 uint8_t *cmd
, unsigned int cmd_len
,
1443 uint8_t *rsp
, unsigned int *rsp_len
,
1444 unsigned int max_rsp_len
)
1447 struct ipmi_time now
;
1449 val
= cmd
[2] | (cmd
[3] << 8) | (cmd
[4] << 16) | (cmd
[5] << 24);
1451 ibs
->sel
.time_offset
= now
.tv_sec
- ((long) val
);
1454 static void set_sensor_evt_enable(IPMIBmcSim
*ibs
,
1455 uint8_t *cmd
, unsigned int cmd_len
,
1456 uint8_t *rsp
, unsigned int *rsp_len
,
1457 unsigned int max_rsp_len
)
1461 if ((cmd
[2] >= MAX_SENSORS
) ||
1462 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1463 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1466 sens
= ibs
->sensors
+ cmd
[2];
1467 switch ((cmd
[3] >> 4) & 0x3) {
1468 case 0: /* Do not change */
1470 case 1: /* Enable 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;
1484 case 2: /* Disable bits */
1486 sens
->assert_enable
&= ~cmd
[4];
1489 sens
->assert_enable
&= ~(cmd
[5] << 8);
1492 sens
->deassert_enable
&= ~cmd
[6];
1495 sens
->deassert_enable
&= ~(cmd
[7] << 8);
1499 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1502 IPMI_SENSOR_SET_RET_STATUS(sens
, cmd
[3]);
1505 static void get_sensor_evt_enable(IPMIBmcSim
*ibs
,
1506 uint8_t *cmd
, unsigned int cmd_len
,
1507 uint8_t *rsp
, unsigned int *rsp_len
,
1508 unsigned int max_rsp_len
)
1512 if ((cmd
[2] >= MAX_SENSORS
) ||
1513 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1514 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1517 sens
= ibs
->sensors
+ cmd
[2];
1518 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens
));
1519 IPMI_ADD_RSP_DATA(sens
->assert_enable
& 0xff);
1520 IPMI_ADD_RSP_DATA((sens
->assert_enable
>> 8) & 0xff);
1521 IPMI_ADD_RSP_DATA(sens
->deassert_enable
& 0xff);
1522 IPMI_ADD_RSP_DATA((sens
->deassert_enable
>> 8) & 0xff);
1525 static void rearm_sensor_evts(IPMIBmcSim
*ibs
,
1526 uint8_t *cmd
, unsigned int cmd_len
,
1527 uint8_t *rsp
, unsigned int *rsp_len
,
1528 unsigned int max_rsp_len
)
1532 if ((cmd
[2] >= MAX_SENSORS
) ||
1533 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1534 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1537 sens
= ibs
->sensors
+ cmd
[2];
1539 if ((cmd
[3] & 0x80) == 0) {
1540 /* Just clear everything */
1546 static void get_sensor_evt_status(IPMIBmcSim
*ibs
,
1547 uint8_t *cmd
, unsigned int cmd_len
,
1548 uint8_t *rsp
, unsigned int *rsp_len
,
1549 unsigned int max_rsp_len
)
1553 if ((cmd
[2] >= MAX_SENSORS
) ||
1554 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1555 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1558 sens
= ibs
->sensors
+ cmd
[2];
1559 IPMI_ADD_RSP_DATA(sens
->reading
);
1560 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens
));
1561 IPMI_ADD_RSP_DATA(sens
->assert_states
& 0xff);
1562 IPMI_ADD_RSP_DATA((sens
->assert_states
>> 8) & 0xff);
1563 IPMI_ADD_RSP_DATA(sens
->deassert_states
& 0xff);
1564 IPMI_ADD_RSP_DATA((sens
->deassert_states
>> 8) & 0xff);
1567 static void get_sensor_reading(IPMIBmcSim
*ibs
,
1568 uint8_t *cmd
, unsigned int cmd_len
,
1569 uint8_t *rsp
, unsigned int *rsp_len
,
1570 unsigned int max_rsp_len
)
1574 if ((cmd
[2] >= MAX_SENSORS
) ||
1575 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1576 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1579 sens
= ibs
->sensors
+ cmd
[2];
1580 IPMI_ADD_RSP_DATA(sens
->reading
);
1581 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens
));
1582 IPMI_ADD_RSP_DATA(sens
->states
& 0xff);
1583 if (IPMI_SENSOR_IS_DISCRETE(sens
)) {
1584 IPMI_ADD_RSP_DATA((sens
->states
>> 8) & 0xff);
1588 static void set_sensor_type(IPMIBmcSim
*ibs
,
1589 uint8_t *cmd
, unsigned int cmd_len
,
1590 uint8_t *rsp
, unsigned int *rsp_len
,
1591 unsigned int max_rsp_len
)
1596 if ((cmd
[2] >= MAX_SENSORS
) ||
1597 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1598 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1601 sens
= ibs
->sensors
+ cmd
[2];
1602 sens
->sensor_type
= cmd
[3];
1603 sens
->evt_reading_type_code
= cmd
[4] & 0x7f;
1606 static void get_sensor_type(IPMIBmcSim
*ibs
,
1607 uint8_t *cmd
, unsigned int cmd_len
,
1608 uint8_t *rsp
, unsigned int *rsp_len
,
1609 unsigned int max_rsp_len
)
1614 if ((cmd
[2] >= MAX_SENSORS
) ||
1615 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1616 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1619 sens
= ibs
->sensors
+ cmd
[2];
1620 IPMI_ADD_RSP_DATA(sens
->sensor_type
);
1621 IPMI_ADD_RSP_DATA(sens
->evt_reading_type_code
);
1625 static const IPMICmdHandler chassis_cmds
[] = {
1626 [IPMI_CMD_GET_CHASSIS_CAPABILITIES
] = { chassis_capabilities
},
1627 [IPMI_CMD_GET_CHASSIS_STATUS
] = { chassis_status
},
1628 [IPMI_CMD_CHASSIS_CONTROL
] = { chassis_control
, 3 },
1629 [IPMI_CMD_GET_SYS_RESTART_CAUSE
] = { chassis_get_sys_restart_cause
}
1631 static const IPMINetfn chassis_netfn
= {
1632 .cmd_nums
= ARRAY_SIZE(chassis_cmds
),
1633 .cmd_handlers
= chassis_cmds
1636 static const IPMICmdHandler sensor_event_cmds
[] = {
1637 [IPMI_CMD_SET_SENSOR_EVT_ENABLE
] = { set_sensor_evt_enable
, 4 },
1638 [IPMI_CMD_GET_SENSOR_EVT_ENABLE
] = { get_sensor_evt_enable
, 3 },
1639 [IPMI_CMD_REARM_SENSOR_EVTS
] = { rearm_sensor_evts
, 4 },
1640 [IPMI_CMD_GET_SENSOR_EVT_STATUS
] = { get_sensor_evt_status
, 3 },
1641 [IPMI_CMD_GET_SENSOR_READING
] = { get_sensor_reading
, 3 },
1642 [IPMI_CMD_SET_SENSOR_TYPE
] = { set_sensor_type
, 5 },
1643 [IPMI_CMD_GET_SENSOR_TYPE
] = { get_sensor_type
, 3 },
1645 static const IPMINetfn sensor_event_netfn
= {
1646 .cmd_nums
= ARRAY_SIZE(sensor_event_cmds
),
1647 .cmd_handlers
= sensor_event_cmds
1650 static const IPMICmdHandler app_cmds
[] = {
1651 [IPMI_CMD_GET_DEVICE_ID
] = { get_device_id
},
1652 [IPMI_CMD_COLD_RESET
] = { cold_reset
},
1653 [IPMI_CMD_WARM_RESET
] = { warm_reset
},
1654 [IPMI_CMD_SET_ACPI_POWER_STATE
] = { set_acpi_power_state
, 4 },
1655 [IPMI_CMD_GET_ACPI_POWER_STATE
] = { get_acpi_power_state
},
1656 [IPMI_CMD_GET_DEVICE_GUID
] = { get_device_guid
},
1657 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES
] = { set_bmc_global_enables
, 3 },
1658 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES
] = { get_bmc_global_enables
},
1659 [IPMI_CMD_CLR_MSG_FLAGS
] = { clr_msg_flags
, 3 },
1660 [IPMI_CMD_GET_MSG_FLAGS
] = { get_msg_flags
},
1661 [IPMI_CMD_GET_MSG
] = { get_msg
},
1662 [IPMI_CMD_SEND_MSG
] = { send_msg
, 3 },
1663 [IPMI_CMD_READ_EVT_MSG_BUF
] = { read_evt_msg_buf
},
1664 [IPMI_CMD_RESET_WATCHDOG_TIMER
] = { reset_watchdog_timer
},
1665 [IPMI_CMD_SET_WATCHDOG_TIMER
] = { set_watchdog_timer
, 8 },
1666 [IPMI_CMD_GET_WATCHDOG_TIMER
] = { get_watchdog_timer
},
1668 static const IPMINetfn app_netfn
= {
1669 .cmd_nums
= ARRAY_SIZE(app_cmds
),
1670 .cmd_handlers
= app_cmds
1673 static const IPMICmdHandler storage_cmds
[] = {
1674 [IPMI_CMD_GET_SDR_REP_INFO
] = { get_sdr_rep_info
},
1675 [IPMI_CMD_RESERVE_SDR_REP
] = { reserve_sdr_rep
},
1676 [IPMI_CMD_GET_SDR
] = { get_sdr
, 8 },
1677 [IPMI_CMD_ADD_SDR
] = { add_sdr
},
1678 [IPMI_CMD_CLEAR_SDR_REP
] = { clear_sdr_rep
, 8 },
1679 [IPMI_CMD_GET_SEL_INFO
] = { get_sel_info
},
1680 [IPMI_CMD_RESERVE_SEL
] = { reserve_sel
},
1681 [IPMI_CMD_GET_SEL_ENTRY
] = { get_sel_entry
, 8 },
1682 [IPMI_CMD_ADD_SEL_ENTRY
] = { add_sel_entry
, 18 },
1683 [IPMI_CMD_CLEAR_SEL
] = { clear_sel
, 8 },
1684 [IPMI_CMD_GET_SEL_TIME
] = { get_sel_time
, 6 },
1685 [IPMI_CMD_SET_SEL_TIME
] = { set_sel_time
},
1688 static const IPMINetfn storage_netfn
= {
1689 .cmd_nums
= ARRAY_SIZE(storage_cmds
),
1690 .cmd_handlers
= storage_cmds
1693 static void register_cmds(IPMIBmcSim
*s
)
1695 ipmi_register_netfn(s
, IPMI_NETFN_CHASSIS
, &chassis_netfn
);
1696 ipmi_register_netfn(s
, IPMI_NETFN_SENSOR_EVENT
, &sensor_event_netfn
);
1697 ipmi_register_netfn(s
, IPMI_NETFN_APP
, &app_netfn
);
1698 ipmi_register_netfn(s
, IPMI_NETFN_STORAGE
, &storage_netfn
);
1701 static const uint8_t init_sdrs
[] = {
1702 /* Watchdog device */
1703 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1704 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1707 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1709 0xff, 0xff, 0x00, 0x00, 0x00
1712 static const VMStateDescription vmstate_ipmi_sim
= {
1713 .name
= TYPE_IPMI_BMC_SIMULATOR
,
1715 .minimum_version_id
= 1,
1716 .fields
= (VMStateField
[]) {
1717 VMSTATE_UINT8(bmc_global_enables
, IPMIBmcSim
),
1718 VMSTATE_UINT8(msg_flags
, IPMIBmcSim
),
1719 VMSTATE_BOOL(watchdog_initialized
, IPMIBmcSim
),
1720 VMSTATE_UINT8(watchdog_use
, IPMIBmcSim
),
1721 VMSTATE_UINT8(watchdog_action
, IPMIBmcSim
),
1722 VMSTATE_UINT8(watchdog_pretimeout
, IPMIBmcSim
),
1723 VMSTATE_BOOL(watchdog_expired
, IPMIBmcSim
),
1724 VMSTATE_UINT16(watchdog_timeout
, IPMIBmcSim
),
1725 VMSTATE_BOOL(watchdog_running
, IPMIBmcSim
),
1726 VMSTATE_BOOL(watchdog_preaction_ran
, IPMIBmcSim
),
1727 VMSTATE_INT64(watchdog_expiry
, IPMIBmcSim
),
1728 VMSTATE_UINT8_ARRAY(evtbuf
, IPMIBmcSim
, 16),
1729 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].status
, IPMIBmcSim
),
1730 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].reading
, IPMIBmcSim
),
1731 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].states
, IPMIBmcSim
),
1732 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_states
, IPMIBmcSim
),
1733 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].deassert_states
,
1735 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_enable
, IPMIBmcSim
),
1736 VMSTATE_END_OF_LIST()
1740 static void ipmi_sim_init(Object
*obj
)
1742 IPMIBmc
*b
= IPMI_BMC(obj
);
1745 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
1747 qemu_mutex_init(&ibs
->lock
);
1748 QTAILQ_INIT(&ibs
->rcvbufs
);
1750 ibs
->bmc_global_enables
= (1 << IPMI_BMC_EVENT_LOG_BIT
);
1751 ibs
->device_id
= 0x20;
1752 ibs
->ipmi_version
= 0x02; /* IPMI 2.0 */
1753 ibs
->restart_cause
= 0;
1754 for (i
= 0; i
< 4; i
++) {
1755 ibs
->sel
.last_addition
[i
] = 0xff;
1756 ibs
->sel
.last_clear
[i
] = 0xff;
1757 ibs
->sdr
.last_addition
[i
] = 0xff;
1758 ibs
->sdr
.last_clear
[i
] = 0xff;
1762 struct ipmi_sdr_header
*sdrh
;
1764 if ((i
+ IPMI_SDR_HEADER_SIZE
) > sizeof(init_sdrs
)) {
1765 error_report("Problem with recid 0x%4.4x", i
);
1768 sdrh
= (struct ipmi_sdr_header
*) &init_sdrs
[i
];
1769 len
= ipmi_sdr_length(sdrh
);
1770 recid
= ipmi_sdr_recid(sdrh
);
1771 if (recid
== 0xffff) {
1774 if ((i
+ len
) > sizeof(init_sdrs
)) {
1775 error_report("Problem with recid 0x%4.4x", i
);
1778 sdr_add_entry(ibs
, sdrh
, len
, NULL
);
1782 ibs
->acpi_power_state
[0] = 0;
1783 ibs
->acpi_power_state
[1] = 0;
1785 if (qemu_uuid_set
) {
1786 memcpy(&ibs
->uuid
, qemu_uuid
, 16);
1788 memset(&ibs
->uuid
, 0, 16);
1791 ipmi_init_sensors_from_sdrs(ibs
);
1794 ibs
->timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, ipmi_timeout
, ibs
);
1796 vmstate_register(NULL
, 0, &vmstate_ipmi_sim
, ibs
);
1799 static void ipmi_sim_class_init(ObjectClass
*oc
, void *data
)
1801 IPMIBmcClass
*bk
= IPMI_BMC_CLASS(oc
);
1803 bk
->handle_command
= ipmi_sim_handle_command
;
1806 static const TypeInfo ipmi_sim_type
= {
1807 .name
= TYPE_IPMI_BMC_SIMULATOR
,
1808 .parent
= TYPE_IPMI_BMC
,
1809 .instance_size
= sizeof(IPMIBmcSim
),
1810 .instance_init
= ipmi_sim_init
,
1811 .class_init
= ipmi_sim_class_init
,
1814 static void ipmi_sim_register_types(void)
1816 type_register_static(&ipmi_sim_type
);
1819 type_init(ipmi_sim_register_types
)