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 "qemu/timer.h"
27 #include "hw/ipmi/ipmi.h"
28 #include "qemu/error-report.h"
30 #define IPMI_NETFN_CHASSIS 0x00
32 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
33 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
34 #define IPMI_CMD_CHASSIS_CONTROL 0x02
36 #define IPMI_NETFN_SENSOR_EVENT 0x04
38 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
39 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
40 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
41 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
42 #define IPMI_CMD_GET_SENSOR_READING 0x2d
44 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
46 #define IPMI_CMD_GET_DEVICE_ID 0x01
47 #define IPMI_CMD_COLD_RESET 0x02
48 #define IPMI_CMD_WARM_RESET 0x03
49 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
50 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
51 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
52 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
53 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
54 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
55 #define IPMI_CMD_GET_MSG_FLAGS 0x31
56 #define IPMI_CMD_GET_MSG 0x33
57 #define IPMI_CMD_SEND_MSG 0x34
58 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
60 #define IPMI_NETFN_STORAGE 0x0a
62 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
63 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
64 #define IPMI_CMD_RESERVE_SDR_REP 0x22
65 #define IPMI_CMD_GET_SDR 0x23
66 #define IPMI_CMD_ADD_SDR 0x24
67 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
68 #define IPMI_CMD_DELETE_SDR 0x26
69 #define IPMI_CMD_CLEAR_SDR_REP 0x27
70 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
71 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
72 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
73 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
74 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
75 #define IPMI_CMD_GET_SEL_INFO 0x40
76 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
77 #define IPMI_CMD_RESERVE_SEL 0x42
78 #define IPMI_CMD_GET_SEL_ENTRY 0x43
79 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
80 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
81 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
82 #define IPMI_CMD_CLEAR_SEL 0x47
83 #define IPMI_CMD_GET_SEL_TIME 0x48
84 #define IPMI_CMD_SET_SEL_TIME 0x49
87 /* Same as a timespec struct. */
93 #define MAX_SEL_SIZE 128
95 typedef struct IPMISel
{
96 uint8_t sel
[MAX_SEL_SIZE
][16];
97 unsigned int next_free
;
100 uint8_t last_addition
[4];
101 uint8_t last_clear
[4];
105 #define MAX_SDR_SIZE 16384
107 typedef struct IPMISdr
{
108 uint8_t sdr
[MAX_SDR_SIZE
];
109 unsigned int next_free
;
110 uint16_t next_rec_id
;
111 uint16_t reservation
;
112 uint8_t last_addition
[4];
113 uint8_t last_clear
[4];
117 typedef struct IPMISensor
{
120 uint16_t states_suppt
;
121 uint16_t assert_suppt
;
122 uint16_t deassert_suppt
;
124 uint16_t assert_states
;
125 uint16_t deassert_states
;
126 uint16_t assert_enable
;
127 uint16_t deassert_enable
;
129 uint8_t evt_reading_type_code
;
131 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
132 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
134 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
135 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
137 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
138 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
140 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
141 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
143 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
145 #define MAX_SENSORS 20
146 #define IPMI_WATCHDOG_SENSOR 0
148 typedef struct IPMIBmcSim IPMIBmcSim
;
150 #define MAX_NETFNS 64
151 typedef void (*IPMICmdHandler
)(IPMIBmcSim
*s
,
152 uint8_t *cmd
, unsigned int cmd_len
,
153 uint8_t *rsp
, unsigned int *rsp_len
,
154 unsigned int max_rsp_len
);
155 typedef struct IPMINetfn
{
156 unsigned int cmd_nums
;
157 const IPMICmdHandler
*cmd_handlers
;
160 typedef struct IPMIRcvBufEntry
{
161 QTAILQ_ENTRY(IPMIRcvBufEntry
) entry
;
163 uint8_t buf
[MAX_IPMI_MSG_SIZE
];
166 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
167 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
168 TYPE_IPMI_BMC_SIMULATOR)
174 uint8_t bmc_global_enables
;
177 bool watchdog_initialized
;
178 uint8_t watchdog_use
;
179 uint8_t watchdog_action
;
180 uint8_t watchdog_pretimeout
; /* In seconds */
181 bool watchdog_expired
;
182 uint16_t watchdog_timeout
; /* in 100's of milliseconds */
184 bool watchdog_running
;
185 bool watchdog_preaction_ran
;
186 int64_t watchdog_expiry
;
189 uint8_t ipmi_version
;
194 uint8_t product_id
[2];
198 IPMISensor sensors
[MAX_SENSORS
];
200 /* Odd netfns are for responses, so we only need the even ones. */
201 const IPMINetfn
*netfns
[MAX_NETFNS
/ 2];
204 /* We allow one event in the buffer */
207 QTAILQ_HEAD(, IPMIRcvBufEntry
) rcvbufs
;
210 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
211 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
212 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
213 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
214 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
215 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
216 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
217 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
218 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
220 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
221 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
222 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
223 #define IPMI_BMC_EVENT_LOG_BIT 3
224 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
225 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
226 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
227 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
228 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
229 (1 << IPMI_BMC_EVENT_LOG_BIT))
230 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
231 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
233 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
234 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
235 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
236 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
237 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
238 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
239 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
240 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
241 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
242 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
243 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
244 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
245 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
246 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
247 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
250 /* Add a byte to the response. */
251 #define IPMI_ADD_RSP_DATA(b) \
253 if (*rsp_len >= max_rsp_len) { \
254 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED; \
257 rsp[(*rsp_len)++] = (b); \
260 /* Verify that the received command is a certain length. */
261 #define IPMI_CHECK_CMD_LEN(l) \
263 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID; \
267 /* Check that the reservation in the command is valid. */
268 #define IPMI_CHECK_RESERVATION(off, r) \
270 if ((cmd[off] | (cmd[off + 1] << 8)) != r) { \
271 rsp[2] = IPMI_CC_INVALID_RESERVATION; \
277 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
);
279 static void ipmi_gettime(struct ipmi_time
*time
)
283 stime
= qemu_clock_get_ns(QEMU_CLOCK_HOST
);
284 time
->tv_sec
= stime
/ 1000000000LL;
285 time
->tv_nsec
= stime
% 1000000000LL;
288 static int64_t ipmi_getmonotime(void)
290 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
293 static void ipmi_timeout(void *opaque
)
295 IPMIBmcSim
*ibs
= opaque
;
297 ipmi_sim_handle_timeout(ibs
);
300 static void set_timestamp(IPMIBmcSim
*ibs
, uint8_t *ts
)
303 struct ipmi_time now
;
306 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
308 ts
[1] = (val
>> 8) & 0xff;
309 ts
[2] = (val
>> 16) & 0xff;
310 ts
[3] = (val
>> 24) & 0xff;
313 static void sdr_inc_reservation(IPMISdr
*sdr
)
316 if (sdr
->reservation
== 0) {
317 sdr
->reservation
= 1;
321 static int sdr_add_entry(IPMIBmcSim
*ibs
, const uint8_t *entry
,
322 unsigned int len
, uint16_t *recid
)
324 if ((len
< 5) || (len
> 255)) {
328 if (entry
[4] != len
- 5) {
332 if (ibs
->sdr
.next_free
+ len
> MAX_SDR_SIZE
) {
333 ibs
->sdr
.overflow
= 1;
337 memcpy(ibs
->sdr
.sdr
+ ibs
->sdr
.next_free
, entry
, len
);
338 ibs
->sdr
.sdr
[ibs
->sdr
.next_free
] = ibs
->sdr
.next_rec_id
& 0xff;
339 ibs
->sdr
.sdr
[ibs
->sdr
.next_free
+1] = (ibs
->sdr
.next_rec_id
>> 8) & 0xff;
340 ibs
->sdr
.sdr
[ibs
->sdr
.next_free
+2] = 0x51; /* Conform to IPMI 1.5 spec */
343 *recid
= ibs
->sdr
.next_rec_id
;
345 ibs
->sdr
.next_rec_id
++;
346 set_timestamp(ibs
, ibs
->sdr
.last_addition
);
347 ibs
->sdr
.next_free
+= len
;
348 sdr_inc_reservation(&ibs
->sdr
);
352 static int sdr_find_entry(IPMISdr
*sdr
, uint16_t recid
,
353 unsigned int *retpos
, uint16_t *nextrec
)
355 unsigned int pos
= *retpos
;
357 while (pos
< sdr
->next_free
) {
358 uint16_t trec
= sdr
->sdr
[pos
] | (sdr
->sdr
[pos
+ 1] << 8);
359 unsigned int nextpos
= pos
+ sdr
->sdr
[pos
+ 4];
363 if (nextpos
>= sdr
->next_free
) {
366 *nextrec
= (sdr
->sdr
[nextpos
] |
367 (sdr
->sdr
[nextpos
+ 1] << 8));
378 static void sel_inc_reservation(IPMISel
*sel
)
381 if (sel
->reservation
== 0) {
382 sel
->reservation
= 1;
386 /* Returns 1 if the SEL is full and can't hold the event. */
387 static int sel_add_event(IPMIBmcSim
*ibs
, uint8_t *event
)
391 set_timestamp(ibs
, event
+ 3);
392 if (ibs
->sel
.next_free
== MAX_SEL_SIZE
) {
393 ibs
->sel
.overflow
= 1;
396 event
[0] = ibs
->sel
.next_free
& 0xff;
397 event
[1] = (ibs
->sel
.next_free
>> 8) & 0xff;
398 memcpy(ibs
->sel
.last_addition
, event
+ 3, 4);
399 memcpy(ibs
->sel
.sel
[ibs
->sel
.next_free
], event
, 16);
400 ibs
->sel
.next_free
++;
401 sel_inc_reservation(&ibs
->sel
);
405 static int attn_set(IPMIBmcSim
*ibs
)
407 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
)
408 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
)
409 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs
);
412 static int attn_irq_enabled(IPMIBmcSim
*ibs
)
414 return (IPMI_BMC_MSG_INTS_ON(ibs
) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
))
415 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs
) &&
416 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
));
419 static void gen_event(IPMIBmcSim
*ibs
, unsigned int sens_num
, uint8_t deassert
,
420 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
422 IPMIInterface
*s
= ibs
->parent
.intf
;
423 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
425 IPMISensor
*sens
= ibs
->sensors
+ sens_num
;
427 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
430 if (!IPMI_SENSOR_GET_EVENTS_ON(sens
)) {
434 evt
[2] = 0x2; /* System event record */
435 evt
[7] = ibs
->parent
.slave_addr
;
437 evt
[9] = 0x04; /* Format version */
438 evt
[10] = sens
->sensor_type
;
440 evt
[12] = sens
->evt_reading_type_code
| (!!deassert
<< 7);
445 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
446 sel_add_event(ibs
, evt
);
449 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
453 memcpy(ibs
->evtbuf
, evt
, 16);
454 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
455 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
458 static void sensor_set_discrete_bit(IPMIBmcSim
*ibs
, unsigned int sensor
,
459 unsigned int bit
, unsigned int val
,
460 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
465 if (sensor
>= MAX_SENSORS
) {
473 sens
= ibs
->sensors
+ sensor
;
475 sens
->states
|= mask
& sens
->states_suppt
;
476 if (sens
->assert_states
& mask
) {
477 return; /* Already asserted */
479 sens
->assert_states
|= mask
& sens
->assert_suppt
;
480 if (sens
->assert_enable
& mask
& sens
->assert_states
) {
481 /* Send an event on assert */
482 gen_event(ibs
, sensor
, 0, evd1
, evd2
, evd3
);
485 sens
->states
&= ~(mask
& sens
->states_suppt
);
486 if (sens
->deassert_states
& mask
) {
487 return; /* Already deasserted */
489 sens
->deassert_states
|= mask
& sens
->deassert_suppt
;
490 if (sens
->deassert_enable
& mask
& sens
->deassert_states
) {
491 /* Send an event on deassert */
492 gen_event(ibs
, sensor
, 1, evd1
, evd2
, evd3
);
497 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim
*s
)
502 for (i
= 0; i
< MAX_SENSORS
; i
++) {
503 memset(s
->sensors
+ i
, 0, sizeof(*sens
));
507 for (i
= 0; !sdr_find_entry(&s
->sdr
, i
, &pos
, NULL
); i
++) {
508 uint8_t *sdr
= s
->sdr
.sdr
+ pos
;
509 unsigned int len
= sdr
[4];
514 if ((sdr
[3] < 1) || (sdr
[3] > 2)) {
515 continue; /* Not a sensor SDR we set from */
518 if (sdr
[7] > MAX_SENSORS
) {
521 sens
= s
->sensors
+ sdr
[7];
523 IPMI_SENSOR_SET_PRESENT(sens
, 1);
524 IPMI_SENSOR_SET_SCAN_ON(sens
, (sdr
[10] >> 6) & 1);
525 IPMI_SENSOR_SET_EVENTS_ON(sens
, (sdr
[10] >> 5) & 1);
526 sens
->assert_suppt
= sdr
[14] | (sdr
[15] << 8);
527 sens
->deassert_suppt
= sdr
[16] | (sdr
[17] << 8);
528 sens
->states_suppt
= sdr
[18] | (sdr
[19] << 8);
529 sens
->sensor_type
= sdr
[12];
530 sens
->evt_reading_type_code
= sdr
[13] & 0x7f;
532 /* Enable all the events that are supported. */
533 sens
->assert_enable
= sens
->assert_suppt
;
534 sens
->deassert_enable
= sens
->deassert_suppt
;
538 static int ipmi_register_netfn(IPMIBmcSim
*s
, unsigned int netfn
,
539 const IPMINetfn
*netfnd
)
541 if ((netfn
& 1) || (netfn
> MAX_NETFNS
) || (s
->netfns
[netfn
/ 2])) {
544 s
->netfns
[netfn
/ 2] = netfnd
;
548 static void next_timeout(IPMIBmcSim
*ibs
)
551 if (ibs
->watchdog_running
) {
552 next
= ibs
->watchdog_expiry
;
555 next
= ipmi_getmonotime() + 60 * 1000000000LL;
557 timer_mod_ns(ibs
->timer
, next
);
560 static void ipmi_sim_handle_command(IPMIBmc
*b
,
561 uint8_t *cmd
, unsigned int cmd_len
,
562 unsigned int max_cmd_len
,
565 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
566 IPMIInterface
*s
= ibs
->parent
.intf
;
567 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
569 uint8_t rsp
[MAX_IPMI_MSG_SIZE
];
570 unsigned int rsp_len_holder
= 0;
571 unsigned int *rsp_len
= &rsp_len_holder
;
572 unsigned int max_rsp_len
= sizeof(rsp
);
574 /* Set up the response, set the low bit of NETFN. */
575 /* Note that max_rsp_len must be at least 3 */
576 if (max_rsp_len
< 3) {
577 rsp
[2] = IPMI_CC_REQUEST_DATA_TRUNCATED
;
581 IPMI_ADD_RSP_DATA(cmd
[0] | 0x04);
582 IPMI_ADD_RSP_DATA(cmd
[1]);
583 IPMI_ADD_RSP_DATA(0); /* Assume success */
585 /* If it's too short or it was truncated, return an error. */
587 rsp
[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID
;
590 if (cmd_len
> max_cmd_len
) {
591 rsp
[2] = IPMI_CC_REQUEST_DATA_TRUNCATED
;
595 if ((cmd
[0] & 0x03) != 0) {
596 /* Only have stuff on LUN 0 */
597 rsp
[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN
;
603 /* Odd netfns are not valid, make sure the command is registered */
604 if ((netfn
& 1) || !ibs
->netfns
[netfn
/ 2] ||
605 (cmd
[1] >= ibs
->netfns
[netfn
/ 2]->cmd_nums
) ||
606 (!ibs
->netfns
[netfn
/ 2]->cmd_handlers
[cmd
[1]])) {
607 rsp
[2] = IPMI_CC_INVALID_CMD
;
611 ibs
->netfns
[netfn
/ 2]->cmd_handlers
[cmd
[1]](ibs
, cmd
, cmd_len
, rsp
, rsp_len
,
615 k
->handle_rsp(s
, msg_id
, rsp
, *rsp_len
);
620 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
)
622 IPMIInterface
*s
= ibs
->parent
.intf
;
623 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
625 if (!ibs
->watchdog_running
) {
629 if (!ibs
->watchdog_preaction_ran
) {
630 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
)) {
631 case IPMI_BMC_WATCHDOG_PRE_NMI
:
632 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
633 k
->do_hw_op(s
, IPMI_SEND_NMI
, 0);
634 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
635 0xc8, (2 << 4) | 0xf, 0xff);
638 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
639 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
640 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
641 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
642 0xc8, (3 << 4) | 0xf, 0xff);
649 ibs
->watchdog_preaction_ran
= 1;
650 /* Issued the pretimeout, do the rest of the timeout now. */
651 ibs
->watchdog_expiry
= ipmi_getmonotime();
652 ibs
->watchdog_expiry
+= ibs
->watchdog_pretimeout
* 1000000000LL;
657 ibs
->watchdog_running
= 0; /* Stop the watchdog on a timeout */
658 ibs
->watchdog_expired
|= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs
));
659 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
)) {
660 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
661 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 0, 1,
662 0xc0, ibs
->watchdog_use
& 0xf, 0xff);
665 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
666 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 1, 1,
667 0xc1, ibs
->watchdog_use
& 0xf, 0xff);
668 k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0);
671 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
672 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
673 0xc2, ibs
->watchdog_use
& 0xf, 0xff);
674 k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0);
677 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
678 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
679 0xc3, ibs
->watchdog_use
& 0xf, 0xff);
680 k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0);
688 static void chassis_capabilities(IPMIBmcSim
*ibs
,
689 uint8_t *cmd
, unsigned int cmd_len
,
690 uint8_t *rsp
, unsigned int *rsp_len
,
691 unsigned int max_rsp_len
)
693 IPMI_ADD_RSP_DATA(0);
694 IPMI_ADD_RSP_DATA(ibs
->parent
.slave_addr
);
695 IPMI_ADD_RSP_DATA(ibs
->parent
.slave_addr
);
696 IPMI_ADD_RSP_DATA(ibs
->parent
.slave_addr
);
697 IPMI_ADD_RSP_DATA(ibs
->parent
.slave_addr
);
700 static void chassis_status(IPMIBmcSim
*ibs
,
701 uint8_t *cmd
, unsigned int cmd_len
,
702 uint8_t *rsp
, unsigned int *rsp_len
,
703 unsigned int max_rsp_len
)
705 IPMI_ADD_RSP_DATA(0x61); /* Unknown power restore, power is on */
706 IPMI_ADD_RSP_DATA(0);
707 IPMI_ADD_RSP_DATA(0);
708 IPMI_ADD_RSP_DATA(0);
711 static void chassis_control(IPMIBmcSim
*ibs
,
712 uint8_t *cmd
, unsigned int cmd_len
,
713 uint8_t *rsp
, unsigned int *rsp_len
,
714 unsigned int max_rsp_len
)
716 IPMIInterface
*s
= ibs
->parent
.intf
;
717 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
719 IPMI_CHECK_CMD_LEN(3);
720 switch (cmd
[2] & 0xf) {
721 case 0: /* power down */
722 rsp
[2] = k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0);
724 case 1: /* power up */
725 rsp
[2] = k
->do_hw_op(s
, IPMI_POWERON_CHASSIS
, 0);
727 case 2: /* power cycle */
728 rsp
[2] = k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0);
730 case 3: /* hard reset */
731 rsp
[2] = k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0);
733 case 4: /* pulse diagnostic interrupt */
734 rsp
[2] = k
->do_hw_op(s
, IPMI_PULSE_DIAG_IRQ
, 0);
736 case 5: /* soft shutdown via ACPI by overtemp emulation */
737 rsp
[2] = k
->do_hw_op(s
,
738 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP
, 0);
741 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
746 static void get_device_id(IPMIBmcSim
*ibs
,
747 uint8_t *cmd
, unsigned int cmd_len
,
748 uint8_t *rsp
, unsigned int *rsp_len
,
749 unsigned int max_rsp_len
)
751 IPMI_ADD_RSP_DATA(ibs
->device_id
);
752 IPMI_ADD_RSP_DATA(ibs
->device_rev
& 0xf);
753 IPMI_ADD_RSP_DATA(ibs
->fwrev1
& 0x7f);
754 IPMI_ADD_RSP_DATA(ibs
->fwrev2
);
755 IPMI_ADD_RSP_DATA(ibs
->ipmi_version
);
756 IPMI_ADD_RSP_DATA(0x07); /* sensor, SDR, and SEL. */
757 IPMI_ADD_RSP_DATA(ibs
->mfg_id
[0]);
758 IPMI_ADD_RSP_DATA(ibs
->mfg_id
[1]);
759 IPMI_ADD_RSP_DATA(ibs
->mfg_id
[2]);
760 IPMI_ADD_RSP_DATA(ibs
->product_id
[0]);
761 IPMI_ADD_RSP_DATA(ibs
->product_id
[1]);
764 static void set_global_enables(IPMIBmcSim
*ibs
, uint8_t val
)
766 IPMIInterface
*s
= ibs
->parent
.intf
;
767 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
770 ibs
->bmc_global_enables
= val
;
772 irqs_on
= val
& (IPMI_BMC_EVBUF_FULL_INT_BIT
|
773 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT
);
775 k
->set_irq_enable(s
, irqs_on
);
778 static void cold_reset(IPMIBmcSim
*ibs
,
779 uint8_t *cmd
, unsigned int cmd_len
,
780 uint8_t *rsp
, unsigned int *rsp_len
,
781 unsigned int max_rsp_len
)
783 IPMIInterface
*s
= ibs
->parent
.intf
;
784 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
786 /* Disable all interrupts */
787 set_global_enables(ibs
, 1 << IPMI_BMC_EVENT_LOG_BIT
);
794 static void warm_reset(IPMIBmcSim
*ibs
,
795 uint8_t *cmd
, unsigned int cmd_len
,
796 uint8_t *rsp
, unsigned int *rsp_len
,
797 unsigned int max_rsp_len
)
799 IPMIInterface
*s
= ibs
->parent
.intf
;
800 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
807 static void set_bmc_global_enables(IPMIBmcSim
*ibs
,
808 uint8_t *cmd
, unsigned int cmd_len
,
809 uint8_t *rsp
, unsigned int *rsp_len
,
810 unsigned int max_rsp_len
)
812 IPMI_CHECK_CMD_LEN(3);
813 set_global_enables(ibs
, cmd
[2]);
816 static void get_bmc_global_enables(IPMIBmcSim
*ibs
,
817 uint8_t *cmd
, unsigned int cmd_len
,
818 uint8_t *rsp
, unsigned int *rsp_len
,
819 unsigned int max_rsp_len
)
821 IPMI_ADD_RSP_DATA(ibs
->bmc_global_enables
);
824 static void clr_msg_flags(IPMIBmcSim
*ibs
,
825 uint8_t *cmd
, unsigned int cmd_len
,
826 uint8_t *rsp
, unsigned int *rsp_len
,
827 unsigned int max_rsp_len
)
829 IPMIInterface
*s
= ibs
->parent
.intf
;
830 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
832 IPMI_CHECK_CMD_LEN(3);
833 ibs
->msg_flags
&= ~cmd
[2];
834 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
837 static void get_msg_flags(IPMIBmcSim
*ibs
,
838 uint8_t *cmd
, unsigned int cmd_len
,
839 uint8_t *rsp
, unsigned int *rsp_len
,
840 unsigned int max_rsp_len
)
842 IPMI_ADD_RSP_DATA(ibs
->msg_flags
);
845 static void read_evt_msg_buf(IPMIBmcSim
*ibs
,
846 uint8_t *cmd
, unsigned int cmd_len
,
847 uint8_t *rsp
, unsigned int *rsp_len
,
848 unsigned int max_rsp_len
)
850 IPMIInterface
*s
= ibs
->parent
.intf
;
851 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
854 if (!(ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
)) {
858 for (i
= 0; i
< 16; i
++) {
859 IPMI_ADD_RSP_DATA(ibs
->evtbuf
[i
]);
861 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
862 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
865 static void get_msg(IPMIBmcSim
*ibs
,
866 uint8_t *cmd
, unsigned int cmd_len
,
867 uint8_t *rsp
, unsigned int *rsp_len
,
868 unsigned int max_rsp_len
)
870 IPMIRcvBufEntry
*msg
;
872 qemu_mutex_lock(&ibs
->lock
);
873 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
874 rsp
[2] = 0x80; /* Queue empty */
877 rsp
[3] = 0; /* Channel 0 */
879 msg
= QTAILQ_FIRST(&ibs
->rcvbufs
);
880 memcpy(rsp
+ 4, msg
->buf
, msg
->len
);
881 *rsp_len
+= msg
->len
;
882 QTAILQ_REMOVE(&ibs
->rcvbufs
, msg
, entry
);
885 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
886 IPMIInterface
*s
= ibs
->parent
.intf
;
887 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
889 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
890 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
894 qemu_mutex_unlock(&ibs
->lock
);
899 ipmb_checksum(unsigned char *data
, int size
, unsigned char csum
)
901 for (; size
> 0; size
--, data
++) {
908 static void send_msg(IPMIBmcSim
*ibs
,
909 uint8_t *cmd
, unsigned int cmd_len
,
910 uint8_t *rsp
, unsigned int *rsp_len
,
911 unsigned int max_rsp_len
)
913 IPMIInterface
*s
= ibs
->parent
.intf
;
914 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
915 IPMIRcvBufEntry
*msg
;
917 uint8_t netfn
, rqLun
, rsLun
, rqSeq
;
919 IPMI_CHECK_CMD_LEN(3);
922 /* We only handle channel 0 with no options */
923 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
927 IPMI_CHECK_CMD_LEN(10);
928 if (cmd
[3] != 0x40) {
929 /* We only emulate a MC at address 0x40. */
930 rsp
[2] = 0x83; /* NAK on write */
934 cmd
+= 3; /* Skip the header. */
938 * At this point we "send" the message successfully. Any error will
939 * be returned in the response.
941 if (ipmb_checksum(cmd
, cmd_len
, 0) != 0 ||
942 cmd
[3] != 0x20) { /* Improper response address */
943 return; /* No response */
947 rqLun
= cmd
[4] & 0x3;
948 rsLun
= cmd
[1] & 0x3;
952 /* We only support LUN 2 coming back to us. */
956 msg
= g_malloc(sizeof(*msg
));
957 msg
->buf
[0] = ((netfn
| 1) << 2) | rqLun
; /* NetFN, and make a response */
958 msg
->buf
[1] = ipmb_checksum(msg
->buf
, 1, 0);
959 msg
->buf
[2] = cmd
[0]; /* rsSA */
960 msg
->buf
[3] = (rqSeq
<< 2) | rsLun
;
961 msg
->buf
[4] = cmd
[5]; /* Cmd */
962 msg
->buf
[5] = 0; /* Completion Code */
965 if ((cmd
[1] >> 2) != IPMI_NETFN_APP
|| cmd
[5] != IPMI_CMD_GET_DEVICE_ID
) {
966 /* Not a command we handle. */
967 msg
->buf
[5] = IPMI_CC_INVALID_CMD
;
971 buf
= msg
->buf
+ msg
->len
; /* After the CC */
986 msg
->buf
[msg
->len
] = ipmb_checksum(msg
->buf
, msg
->len
, 0);
988 qemu_mutex_lock(&ibs
->lock
);
989 QTAILQ_INSERT_TAIL(&ibs
->rcvbufs
, msg
, entry
);
990 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
991 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
992 qemu_mutex_unlock(&ibs
->lock
);
995 static void do_watchdog_reset(IPMIBmcSim
*ibs
)
997 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
) ==
998 IPMI_BMC_WATCHDOG_ACTION_NONE
) {
999 ibs
->watchdog_running
= 0;
1002 ibs
->watchdog_preaction_ran
= 0;
1005 /* Timeout is in tenths of a second, offset is in seconds */
1006 ibs
->watchdog_expiry
= ipmi_getmonotime();
1007 ibs
->watchdog_expiry
+= ibs
->watchdog_timeout
* 100000000LL;
1008 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
) != IPMI_BMC_WATCHDOG_PRE_NONE
) {
1009 ibs
->watchdog_expiry
-= ibs
->watchdog_pretimeout
* 1000000000LL;
1011 ibs
->watchdog_running
= 1;
1014 static void reset_watchdog_timer(IPMIBmcSim
*ibs
,
1015 uint8_t *cmd
, unsigned int cmd_len
,
1016 uint8_t *rsp
, unsigned int *rsp_len
,
1017 unsigned int max_rsp_len
)
1019 if (!ibs
->watchdog_initialized
) {
1023 do_watchdog_reset(ibs
);
1026 static void set_watchdog_timer(IPMIBmcSim
*ibs
,
1027 uint8_t *cmd
, unsigned int cmd_len
,
1028 uint8_t *rsp
, unsigned int *rsp_len
,
1029 unsigned int max_rsp_len
)
1031 IPMIInterface
*s
= ibs
->parent
.intf
;
1032 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1035 IPMI_CHECK_CMD_LEN(8);
1036 val
= cmd
[2] & 0x7; /* Validate use */
1037 if (val
== 0 || val
> 5) {
1038 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1041 val
= cmd
[3] & 0x7; /* Validate action */
1043 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
1046 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
1047 rsp
[2] = k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 1);
1050 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
1051 rsp
[2] = k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 1);
1054 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
1055 rsp
[2] = k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 1);
1059 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1062 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1066 val
= (cmd
[3] >> 4) & 0x7; /* Validate preaction */
1068 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
1069 case IPMI_BMC_WATCHDOG_PRE_NONE
:
1072 case IPMI_BMC_WATCHDOG_PRE_NMI
:
1073 if (!k
->do_hw_op(s
, IPMI_SEND_NMI
, 1)) {
1074 /* NMI not supported. */
1075 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1079 /* We don't support PRE_SMI */
1080 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1084 ibs
->watchdog_initialized
= 1;
1085 ibs
->watchdog_use
= cmd
[2] & IPMI_BMC_WATCHDOG_USE_MASK
;
1086 ibs
->watchdog_action
= cmd
[3] & IPMI_BMC_WATCHDOG_ACTION_MASK
;
1087 ibs
->watchdog_pretimeout
= cmd
[4];
1088 ibs
->watchdog_expired
&= ~cmd
[5];
1089 ibs
->watchdog_timeout
= cmd
[6] | (((uint16_t) cmd
[7]) << 8);
1090 if (ibs
->watchdog_running
& IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs
)) {
1091 do_watchdog_reset(ibs
);
1093 ibs
->watchdog_running
= 0;
1097 static void get_watchdog_timer(IPMIBmcSim
*ibs
,
1098 uint8_t *cmd
, unsigned int cmd_len
,
1099 uint8_t *rsp
, unsigned int *rsp_len
,
1100 unsigned int max_rsp_len
)
1102 IPMI_ADD_RSP_DATA(ibs
->watchdog_use
);
1103 IPMI_ADD_RSP_DATA(ibs
->watchdog_action
);
1104 IPMI_ADD_RSP_DATA(ibs
->watchdog_pretimeout
);
1105 IPMI_ADD_RSP_DATA(ibs
->watchdog_expired
);
1106 if (ibs
->watchdog_running
) {
1108 timeout
= ((ibs
->watchdog_expiry
- ipmi_getmonotime() + 50000000)
1110 IPMI_ADD_RSP_DATA(timeout
& 0xff);
1111 IPMI_ADD_RSP_DATA((timeout
>> 8) & 0xff);
1113 IPMI_ADD_RSP_DATA(0);
1114 IPMI_ADD_RSP_DATA(0);
1118 static void get_sdr_rep_info(IPMIBmcSim
*ibs
,
1119 uint8_t *cmd
, unsigned int cmd_len
,
1120 uint8_t *rsp
, unsigned int *rsp_len
,
1121 unsigned int max_rsp_len
)
1125 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 spec */
1126 IPMI_ADD_RSP_DATA(ibs
->sdr
.next_rec_id
& 0xff);
1127 IPMI_ADD_RSP_DATA((ibs
->sdr
.next_rec_id
>> 8) & 0xff);
1128 IPMI_ADD_RSP_DATA((MAX_SDR_SIZE
- ibs
->sdr
.next_free
) & 0xff);
1129 IPMI_ADD_RSP_DATA(((MAX_SDR_SIZE
- ibs
->sdr
.next_free
) >> 8) & 0xff);
1130 for (i
= 0; i
< 4; i
++) {
1131 IPMI_ADD_RSP_DATA(ibs
->sdr
.last_addition
[i
]);
1133 for (i
= 0; i
< 4; i
++) {
1134 IPMI_ADD_RSP_DATA(ibs
->sdr
.last_clear
[i
]);
1136 /* Only modal support, reserve supported */
1137 IPMI_ADD_RSP_DATA((ibs
->sdr
.overflow
<< 7) | 0x22);
1140 static void reserve_sdr_rep(IPMIBmcSim
*ibs
,
1141 uint8_t *cmd
, unsigned int cmd_len
,
1142 uint8_t *rsp
, unsigned int *rsp_len
,
1143 unsigned int max_rsp_len
)
1145 IPMI_ADD_RSP_DATA(ibs
->sdr
.reservation
& 0xff);
1146 IPMI_ADD_RSP_DATA((ibs
->sdr
.reservation
>> 8) & 0xff);
1149 static void get_sdr(IPMIBmcSim
*ibs
,
1150 uint8_t *cmd
, unsigned int cmd_len
,
1151 uint8_t *rsp
, unsigned int *rsp_len
,
1152 unsigned int max_rsp_len
)
1157 IPMI_CHECK_CMD_LEN(8);
1159 IPMI_CHECK_RESERVATION(2, ibs
->sdr
.reservation
);
1162 if (sdr_find_entry(&ibs
->sdr
, cmd
[4] | (cmd
[5] << 8),
1164 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1167 if (cmd
[6] > (ibs
->sdr
.sdr
[pos
+ 4])) {
1168 rsp
[2] = IPMI_CC_PARM_OUT_OF_RANGE
;
1172 IPMI_ADD_RSP_DATA(nextrec
& 0xff);
1173 IPMI_ADD_RSP_DATA((nextrec
>> 8) & 0xff);
1175 if (cmd
[7] == 0xff) {
1176 cmd
[7] = ibs
->sdr
.sdr
[pos
+ 4] - cmd
[6];
1179 if ((cmd
[7] + *rsp_len
) > max_rsp_len
) {
1180 rsp
[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES
;
1183 memcpy(rsp
+ *rsp_len
, ibs
->sdr
.sdr
+ pos
+ cmd
[6], cmd
[7]);
1187 static void add_sdr(IPMIBmcSim
*ibs
,
1188 uint8_t *cmd
, unsigned int cmd_len
,
1189 uint8_t *rsp
, unsigned int *rsp_len
,
1190 unsigned int max_rsp_len
)
1194 if (sdr_add_entry(ibs
, cmd
+ 2, cmd_len
- 2, &recid
)) {
1195 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1198 IPMI_ADD_RSP_DATA(recid
& 0xff);
1199 IPMI_ADD_RSP_DATA((recid
>> 8) & 0xff);
1202 static void clear_sdr_rep(IPMIBmcSim
*ibs
,
1203 uint8_t *cmd
, unsigned int cmd_len
,
1204 uint8_t *rsp
, unsigned int *rsp_len
,
1205 unsigned int max_rsp_len
)
1207 IPMI_CHECK_CMD_LEN(8);
1208 IPMI_CHECK_RESERVATION(2, ibs
->sdr
.reservation
);
1209 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1210 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1213 if (cmd
[7] == 0xaa) {
1214 ibs
->sdr
.next_free
= 0;
1215 ibs
->sdr
.overflow
= 0;
1216 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1217 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1218 sdr_inc_reservation(&ibs
->sdr
);
1219 } else if (cmd
[7] == 0) {
1220 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1222 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1227 static void get_sel_info(IPMIBmcSim
*ibs
,
1228 uint8_t *cmd
, unsigned int cmd_len
,
1229 uint8_t *rsp
, unsigned int *rsp_len
,
1230 unsigned int max_rsp_len
)
1232 unsigned int i
, val
;
1234 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 */
1235 IPMI_ADD_RSP_DATA(ibs
->sel
.next_free
& 0xff);
1236 IPMI_ADD_RSP_DATA((ibs
->sel
.next_free
>> 8) & 0xff);
1237 val
= (MAX_SEL_SIZE
- ibs
->sel
.next_free
) * 16;
1238 IPMI_ADD_RSP_DATA(val
& 0xff);
1239 IPMI_ADD_RSP_DATA((val
>> 8) & 0xff);
1240 for (i
= 0; i
< 4; i
++) {
1241 IPMI_ADD_RSP_DATA(ibs
->sel
.last_addition
[i
]);
1243 for (i
= 0; i
< 4; i
++) {
1244 IPMI_ADD_RSP_DATA(ibs
->sel
.last_clear
[i
]);
1246 /* Only support Reserve SEL */
1247 IPMI_ADD_RSP_DATA((ibs
->sel
.overflow
<< 7) | 0x02);
1250 static void reserve_sel(IPMIBmcSim
*ibs
,
1251 uint8_t *cmd
, unsigned int cmd_len
,
1252 uint8_t *rsp
, unsigned int *rsp_len
,
1253 unsigned int max_rsp_len
)
1255 IPMI_ADD_RSP_DATA(ibs
->sel
.reservation
& 0xff);
1256 IPMI_ADD_RSP_DATA((ibs
->sel
.reservation
>> 8) & 0xff);
1259 static void get_sel_entry(IPMIBmcSim
*ibs
,
1260 uint8_t *cmd
, unsigned int cmd_len
,
1261 uint8_t *rsp
, unsigned int *rsp_len
,
1262 unsigned int max_rsp_len
)
1266 IPMI_CHECK_CMD_LEN(8);
1268 IPMI_CHECK_RESERVATION(2, ibs
->sel
.reservation
);
1270 if (ibs
->sel
.next_free
== 0) {
1271 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1275 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1278 if (cmd
[7] == 0xff) {
1280 } else if ((cmd
[7] + cmd
[6]) > 16) {
1281 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1287 val
= cmd
[4] | (cmd
[5] << 8);
1288 if (val
== 0xffff) {
1289 val
= ibs
->sel
.next_free
- 1;
1290 } else if (val
>= ibs
->sel
.next_free
) {
1291 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1294 if ((val
+ 1) == ibs
->sel
.next_free
) {
1295 IPMI_ADD_RSP_DATA(0xff);
1296 IPMI_ADD_RSP_DATA(0xff);
1298 IPMI_ADD_RSP_DATA((val
+ 1) & 0xff);
1299 IPMI_ADD_RSP_DATA(((val
+ 1) >> 8) & 0xff);
1301 for (; cmd
[6] < cmd
[7]; cmd
[6]++) {
1302 IPMI_ADD_RSP_DATA(ibs
->sel
.sel
[val
][cmd
[6]]);
1306 static void add_sel_entry(IPMIBmcSim
*ibs
,
1307 uint8_t *cmd
, unsigned int cmd_len
,
1308 uint8_t *rsp
, unsigned int *rsp_len
,
1309 unsigned int max_rsp_len
)
1311 IPMI_CHECK_CMD_LEN(18);
1312 if (sel_add_event(ibs
, cmd
+ 2)) {
1313 rsp
[2] = IPMI_CC_OUT_OF_SPACE
;
1316 /* sel_add_event fills in the record number. */
1317 IPMI_ADD_RSP_DATA(cmd
[2]);
1318 IPMI_ADD_RSP_DATA(cmd
[3]);
1321 static void clear_sel(IPMIBmcSim
*ibs
,
1322 uint8_t *cmd
, unsigned int cmd_len
,
1323 uint8_t *rsp
, unsigned int *rsp_len
,
1324 unsigned int max_rsp_len
)
1326 IPMI_CHECK_CMD_LEN(8);
1327 IPMI_CHECK_RESERVATION(2, ibs
->sel
.reservation
);
1328 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1329 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1332 if (cmd
[7] == 0xaa) {
1333 ibs
->sel
.next_free
= 0;
1334 ibs
->sel
.overflow
= 0;
1335 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1336 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1337 sel_inc_reservation(&ibs
->sel
);
1338 } else if (cmd
[7] == 0) {
1339 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1341 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1346 static void get_sel_time(IPMIBmcSim
*ibs
,
1347 uint8_t *cmd
, unsigned int cmd_len
,
1348 uint8_t *rsp
, unsigned int *rsp_len
,
1349 unsigned int max_rsp_len
)
1352 struct ipmi_time now
;
1355 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
1356 IPMI_ADD_RSP_DATA(val
& 0xff);
1357 IPMI_ADD_RSP_DATA((val
>> 8) & 0xff);
1358 IPMI_ADD_RSP_DATA((val
>> 16) & 0xff);
1359 IPMI_ADD_RSP_DATA((val
>> 24) & 0xff);
1362 static void set_sel_time(IPMIBmcSim
*ibs
,
1363 uint8_t *cmd
, unsigned int cmd_len
,
1364 uint8_t *rsp
, unsigned int *rsp_len
,
1365 unsigned int max_rsp_len
)
1368 struct ipmi_time now
;
1370 IPMI_CHECK_CMD_LEN(6);
1371 val
= cmd
[2] | (cmd
[3] << 8) | (cmd
[4] << 16) | (cmd
[5] << 24);
1373 ibs
->sel
.time_offset
= now
.tv_sec
- ((long) val
);
1376 static void set_sensor_evt_enable(IPMIBmcSim
*ibs
,
1377 uint8_t *cmd
, unsigned int cmd_len
,
1378 uint8_t *rsp
, unsigned int *rsp_len
,
1379 unsigned int max_rsp_len
)
1383 IPMI_CHECK_CMD_LEN(4);
1384 if ((cmd
[2] > MAX_SENSORS
) ||
1385 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1386 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1389 sens
= ibs
->sensors
+ cmd
[2];
1390 switch ((cmd
[3] >> 4) & 0x3) {
1391 case 0: /* Do not change */
1393 case 1: /* Enable bits */
1395 sens
->assert_enable
|= cmd
[4];
1398 sens
->assert_enable
|= cmd
[5] << 8;
1401 sens
->deassert_enable
|= cmd
[6];
1404 sens
->deassert_enable
|= cmd
[7] << 8;
1407 case 2: /* Disable bits */
1409 sens
->assert_enable
&= ~cmd
[4];
1412 sens
->assert_enable
&= ~(cmd
[5] << 8);
1415 sens
->deassert_enable
&= ~cmd
[6];
1418 sens
->deassert_enable
&= ~(cmd
[7] << 8);
1422 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1425 IPMI_SENSOR_SET_RET_STATUS(sens
, cmd
[3]);
1428 static void get_sensor_evt_enable(IPMIBmcSim
*ibs
,
1429 uint8_t *cmd
, unsigned int cmd_len
,
1430 uint8_t *rsp
, unsigned int *rsp_len
,
1431 unsigned int max_rsp_len
)
1435 IPMI_CHECK_CMD_LEN(3);
1436 if ((cmd
[2] > MAX_SENSORS
) ||
1437 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1438 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1441 sens
= ibs
->sensors
+ cmd
[2];
1442 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens
));
1443 IPMI_ADD_RSP_DATA(sens
->assert_enable
& 0xff);
1444 IPMI_ADD_RSP_DATA((sens
->assert_enable
>> 8) & 0xff);
1445 IPMI_ADD_RSP_DATA(sens
->deassert_enable
& 0xff);
1446 IPMI_ADD_RSP_DATA((sens
->deassert_enable
>> 8) & 0xff);
1449 static void rearm_sensor_evts(IPMIBmcSim
*ibs
,
1450 uint8_t *cmd
, unsigned int cmd_len
,
1451 uint8_t *rsp
, unsigned int *rsp_len
,
1452 unsigned int max_rsp_len
)
1456 IPMI_CHECK_CMD_LEN(4);
1457 if ((cmd
[2] > MAX_SENSORS
) ||
1458 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1459 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1462 sens
= ibs
->sensors
+ cmd
[2];
1464 if ((cmd
[3] & 0x80) == 0) {
1465 /* Just clear everything */
1471 static void get_sensor_evt_status(IPMIBmcSim
*ibs
,
1472 uint8_t *cmd
, unsigned int cmd_len
,
1473 uint8_t *rsp
, unsigned int *rsp_len
,
1474 unsigned int max_rsp_len
)
1478 IPMI_CHECK_CMD_LEN(3);
1479 if ((cmd
[2] > MAX_SENSORS
) ||
1480 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1481 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1484 sens
= ibs
->sensors
+ cmd
[2];
1485 IPMI_ADD_RSP_DATA(sens
->reading
);
1486 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens
));
1487 IPMI_ADD_RSP_DATA(sens
->assert_states
& 0xff);
1488 IPMI_ADD_RSP_DATA((sens
->assert_states
>> 8) & 0xff);
1489 IPMI_ADD_RSP_DATA(sens
->deassert_states
& 0xff);
1490 IPMI_ADD_RSP_DATA((sens
->deassert_states
>> 8) & 0xff);
1493 static void get_sensor_reading(IPMIBmcSim
*ibs
,
1494 uint8_t *cmd
, unsigned int cmd_len
,
1495 uint8_t *rsp
, unsigned int *rsp_len
,
1496 unsigned int max_rsp_len
)
1500 IPMI_CHECK_CMD_LEN(3);
1501 if ((cmd
[2] > MAX_SENSORS
) ||
1502 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1503 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1506 sens
= ibs
->sensors
+ cmd
[2];
1507 IPMI_ADD_RSP_DATA(sens
->reading
);
1508 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens
));
1509 IPMI_ADD_RSP_DATA(sens
->states
& 0xff);
1510 if (IPMI_SENSOR_IS_DISCRETE(sens
)) {
1511 IPMI_ADD_RSP_DATA((sens
->states
>> 8) & 0xff);
1515 static const IPMICmdHandler chassis_cmds
[] = {
1516 [IPMI_CMD_GET_CHASSIS_CAPABILITIES
] = chassis_capabilities
,
1517 [IPMI_CMD_GET_CHASSIS_STATUS
] = chassis_status
,
1518 [IPMI_CMD_CHASSIS_CONTROL
] = chassis_control
1520 static const IPMINetfn chassis_netfn
= {
1521 .cmd_nums
= ARRAY_SIZE(chassis_cmds
),
1522 .cmd_handlers
= chassis_cmds
1525 static const IPMICmdHandler sensor_event_cmds
[] = {
1526 [IPMI_CMD_SET_SENSOR_EVT_ENABLE
] = set_sensor_evt_enable
,
1527 [IPMI_CMD_GET_SENSOR_EVT_ENABLE
] = get_sensor_evt_enable
,
1528 [IPMI_CMD_REARM_SENSOR_EVTS
] = rearm_sensor_evts
,
1529 [IPMI_CMD_GET_SENSOR_EVT_STATUS
] = get_sensor_evt_status
,
1530 [IPMI_CMD_GET_SENSOR_READING
] = get_sensor_reading
1532 static const IPMINetfn sensor_event_netfn
= {
1533 .cmd_nums
= ARRAY_SIZE(sensor_event_cmds
),
1534 .cmd_handlers
= sensor_event_cmds
1537 static const IPMICmdHandler app_cmds
[] = {
1538 [IPMI_CMD_GET_DEVICE_ID
] = get_device_id
,
1539 [IPMI_CMD_COLD_RESET
] = cold_reset
,
1540 [IPMI_CMD_WARM_RESET
] = warm_reset
,
1541 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES
] = set_bmc_global_enables
,
1542 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES
] = get_bmc_global_enables
,
1543 [IPMI_CMD_CLR_MSG_FLAGS
] = clr_msg_flags
,
1544 [IPMI_CMD_GET_MSG_FLAGS
] = get_msg_flags
,
1545 [IPMI_CMD_GET_MSG
] = get_msg
,
1546 [IPMI_CMD_SEND_MSG
] = send_msg
,
1547 [IPMI_CMD_READ_EVT_MSG_BUF
] = read_evt_msg_buf
,
1548 [IPMI_CMD_RESET_WATCHDOG_TIMER
] = reset_watchdog_timer
,
1549 [IPMI_CMD_SET_WATCHDOG_TIMER
] = set_watchdog_timer
,
1550 [IPMI_CMD_GET_WATCHDOG_TIMER
] = get_watchdog_timer
,
1552 static const IPMINetfn app_netfn
= {
1553 .cmd_nums
= ARRAY_SIZE(app_cmds
),
1554 .cmd_handlers
= app_cmds
1557 static const IPMICmdHandler storage_cmds
[] = {
1558 [IPMI_CMD_GET_SDR_REP_INFO
] = get_sdr_rep_info
,
1559 [IPMI_CMD_RESERVE_SDR_REP
] = reserve_sdr_rep
,
1560 [IPMI_CMD_GET_SDR
] = get_sdr
,
1561 [IPMI_CMD_ADD_SDR
] = add_sdr
,
1562 [IPMI_CMD_CLEAR_SDR_REP
] = clear_sdr_rep
,
1563 [IPMI_CMD_GET_SEL_INFO
] = get_sel_info
,
1564 [IPMI_CMD_RESERVE_SEL
] = reserve_sel
,
1565 [IPMI_CMD_GET_SEL_ENTRY
] = get_sel_entry
,
1566 [IPMI_CMD_ADD_SEL_ENTRY
] = add_sel_entry
,
1567 [IPMI_CMD_CLEAR_SEL
] = clear_sel
,
1568 [IPMI_CMD_GET_SEL_TIME
] = get_sel_time
,
1569 [IPMI_CMD_SET_SEL_TIME
] = set_sel_time
,
1572 static const IPMINetfn storage_netfn
= {
1573 .cmd_nums
= ARRAY_SIZE(storage_cmds
),
1574 .cmd_handlers
= storage_cmds
1577 static void register_cmds(IPMIBmcSim
*s
)
1579 ipmi_register_netfn(s
, IPMI_NETFN_CHASSIS
, &chassis_netfn
);
1580 ipmi_register_netfn(s
, IPMI_NETFN_SENSOR_EVENT
, &sensor_event_netfn
);
1581 ipmi_register_netfn(s
, IPMI_NETFN_APP
, &app_netfn
);
1582 ipmi_register_netfn(s
, IPMI_NETFN_STORAGE
, &storage_netfn
);
1585 static const uint8_t init_sdrs
[] = {
1586 /* Watchdog device */
1587 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1588 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1591 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1593 0xff, 0xff, 0x00, 0x00, 0x00
1596 static const VMStateDescription vmstate_ipmi_sim
= {
1597 .name
= TYPE_IPMI_BMC_SIMULATOR
,
1599 .minimum_version_id
= 1,
1600 .fields
= (VMStateField
[]) {
1601 VMSTATE_UINT8(bmc_global_enables
, IPMIBmcSim
),
1602 VMSTATE_UINT8(msg_flags
, IPMIBmcSim
),
1603 VMSTATE_BOOL(watchdog_initialized
, IPMIBmcSim
),
1604 VMSTATE_UINT8(watchdog_use
, IPMIBmcSim
),
1605 VMSTATE_UINT8(watchdog_action
, IPMIBmcSim
),
1606 VMSTATE_UINT8(watchdog_pretimeout
, IPMIBmcSim
),
1607 VMSTATE_BOOL(watchdog_expired
, IPMIBmcSim
),
1608 VMSTATE_UINT16(watchdog_timeout
, IPMIBmcSim
),
1609 VMSTATE_BOOL(watchdog_running
, IPMIBmcSim
),
1610 VMSTATE_BOOL(watchdog_preaction_ran
, IPMIBmcSim
),
1611 VMSTATE_INT64(watchdog_expiry
, IPMIBmcSim
),
1612 VMSTATE_UINT8_ARRAY(evtbuf
, IPMIBmcSim
, 16),
1613 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].status
, IPMIBmcSim
),
1614 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].reading
, IPMIBmcSim
),
1615 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].states
, IPMIBmcSim
),
1616 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_states
, IPMIBmcSim
),
1617 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].deassert_states
,
1619 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_enable
, IPMIBmcSim
),
1620 VMSTATE_END_OF_LIST()
1624 static void ipmi_sim_init(Object
*obj
)
1626 IPMIBmc
*b
= IPMI_BMC(obj
);
1629 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
1631 qemu_mutex_init(&ibs
->lock
);
1632 QTAILQ_INIT(&ibs
->rcvbufs
);
1634 ibs
->bmc_global_enables
= (1 << IPMI_BMC_EVENT_LOG_BIT
);
1635 ibs
->device_id
= 0x20;
1636 ibs
->ipmi_version
= 0x02; /* IPMI 2.0 */
1637 for (i
= 0; i
< 4; i
++) {
1638 ibs
->sel
.last_addition
[i
] = 0xff;
1639 ibs
->sel
.last_clear
[i
] = 0xff;
1640 ibs
->sdr
.last_addition
[i
] = 0xff;
1641 ibs
->sdr
.last_clear
[i
] = 0xff;
1646 if ((i
+ 5) > sizeof(init_sdrs
)) {
1647 error_report("Problem with recid 0x%4.4x", i
);
1650 len
= init_sdrs
[i
+ 4];
1651 recid
= init_sdrs
[i
] | (init_sdrs
[i
+ 1] << 8);
1652 if (recid
== 0xffff) {
1655 if ((i
+ len
+ 5) > sizeof(init_sdrs
)) {
1656 error_report("Problem with recid 0x%4.4x", i
);
1659 sdr_add_entry(ibs
, init_sdrs
+ i
, len
, NULL
);
1663 ipmi_init_sensors_from_sdrs(ibs
);
1666 ibs
->timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, ipmi_timeout
, ibs
);
1668 vmstate_register(NULL
, 0, &vmstate_ipmi_sim
, ibs
);
1671 static void ipmi_sim_class_init(ObjectClass
*oc
, void *data
)
1673 IPMIBmcClass
*bk
= IPMI_BMC_CLASS(oc
);
1675 bk
->handle_command
= ipmi_sim_handle_command
;
1678 static const TypeInfo ipmi_sim_type
= {
1679 .name
= TYPE_IPMI_BMC_SIMULATOR
,
1680 .parent
= TYPE_IPMI_BMC
,
1681 .instance_size
= sizeof(IPMIBmcSim
),
1682 .instance_init
= ipmi_sim_init
,
1683 .class_init
= ipmi_sim_class_init
,
1686 static void ipmi_sim_register_types(void)
1688 type_register_static(&ipmi_sim_type
);
1691 type_init(ipmi_sim_register_types
)