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
31 #define IPMI_NETFN_CHASSIS_MAXCMD 0x03
33 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
34 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
35 #define IPMI_CMD_CHASSIS_CONTROL 0x02
37 #define IPMI_NETFN_SENSOR_EVENT 0x04
38 #define IPMI_NETFN_SENSOR_EVENT_MAXCMD 0x2e
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
46 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
47 #define IPMI_NETFN_APP_MAXCMD 0x36
49 #define IPMI_CMD_GET_DEVICE_ID 0x01
50 #define IPMI_CMD_COLD_RESET 0x02
51 #define IPMI_CMD_WARM_RESET 0x03
52 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
53 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
54 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
55 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
56 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
57 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
58 #define IPMI_CMD_GET_MSG_FLAGS 0x31
59 #define IPMI_CMD_GET_MSG 0x33
60 #define IPMI_CMD_SEND_MSG 0x34
61 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
63 #define IPMI_NETFN_STORAGE 0x0a
64 #define IPMI_NETFN_STORAGE_MAXCMD 0x4a
66 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
67 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
68 #define IPMI_CMD_RESERVE_SDR_REP 0x22
69 #define IPMI_CMD_GET_SDR 0x23
70 #define IPMI_CMD_ADD_SDR 0x24
71 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
72 #define IPMI_CMD_DELETE_SDR 0x26
73 #define IPMI_CMD_CLEAR_SDR_REP 0x27
74 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
75 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
76 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
77 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
78 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
79 #define IPMI_CMD_GET_SEL_INFO 0x40
80 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
81 #define IPMI_CMD_RESERVE_SEL 0x42
82 #define IPMI_CMD_GET_SEL_ENTRY 0x43
83 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
84 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
85 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
86 #define IPMI_CMD_CLEAR_SEL 0x47
87 #define IPMI_CMD_GET_SEL_TIME 0x48
88 #define IPMI_CMD_SET_SEL_TIME 0x49
91 /* Same as a timespec struct. */
97 #define MAX_SEL_SIZE 128
99 typedef struct IPMISel
{
100 uint8_t sel
[MAX_SEL_SIZE
][16];
101 unsigned int next_free
;
103 uint16_t reservation
;
104 uint8_t last_addition
[4];
105 uint8_t last_clear
[4];
109 #define MAX_SDR_SIZE 16384
111 typedef struct IPMISdr
{
112 uint8_t sdr
[MAX_SDR_SIZE
];
113 unsigned int next_free
;
114 uint16_t next_rec_id
;
115 uint16_t reservation
;
116 uint8_t last_addition
[4];
117 uint8_t last_clear
[4];
121 typedef struct IPMISensor
{
124 uint16_t states_suppt
;
125 uint16_t assert_suppt
;
126 uint16_t deassert_suppt
;
128 uint16_t assert_states
;
129 uint16_t deassert_states
;
130 uint16_t assert_enable
;
131 uint16_t deassert_enable
;
133 uint8_t evt_reading_type_code
;
135 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
136 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
138 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
139 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
141 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
142 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
144 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
145 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
147 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
149 #define MAX_SENSORS 20
150 #define IPMI_WATCHDOG_SENSOR 0
152 typedef struct IPMIBmcSim IPMIBmcSim
;
154 #define MAX_NETFNS 64
155 typedef void (*IPMICmdHandler
)(IPMIBmcSim
*s
,
156 uint8_t *cmd
, unsigned int cmd_len
,
157 uint8_t *rsp
, unsigned int *rsp_len
,
158 unsigned int max_rsp_len
);
159 typedef struct IPMINetfn
{
160 unsigned int cmd_nums
;
161 const IPMICmdHandler
*cmd_handlers
;
164 typedef struct IPMIRcvBufEntry
{
165 QTAILQ_ENTRY(IPMIRcvBufEntry
) entry
;
167 uint8_t buf
[MAX_IPMI_MSG_SIZE
];
170 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
171 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
172 TYPE_IPMI_BMC_SIMULATOR)
178 uint8_t bmc_global_enables
;
181 bool watchdog_initialized
;
182 uint8_t watchdog_use
;
183 uint8_t watchdog_action
;
184 uint8_t watchdog_pretimeout
; /* In seconds */
185 bool watchdog_expired
;
186 uint16_t watchdog_timeout
; /* in 100's of milliseconds */
188 bool watchdog_running
;
189 bool watchdog_preaction_ran
;
190 int64_t watchdog_expiry
;
193 uint8_t ipmi_version
;
198 uint8_t product_id
[2];
202 IPMISensor sensors
[MAX_SENSORS
];
204 /* Odd netfns are for responses, so we only need the even ones. */
205 const IPMINetfn
*netfns
[MAX_NETFNS
/ 2];
208 /* We allow one event in the buffer */
211 QTAILQ_HEAD(, IPMIRcvBufEntry
) rcvbufs
;
214 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
215 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
216 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
217 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
218 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
219 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
220 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
221 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
222 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
224 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
225 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
226 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
227 #define IPMI_BMC_EVENT_LOG_BIT 3
228 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
229 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
230 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
231 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
232 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
233 (1 << IPMI_BMC_EVENT_LOG_BIT))
234 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
235 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
237 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
238 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
239 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
240 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
241 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
242 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
243 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
244 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
245 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
246 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
247 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
248 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
249 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
250 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
251 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
254 /* Add a byte to the response. */
255 #define IPMI_ADD_RSP_DATA(b) \
257 if (*rsp_len >= max_rsp_len) { \
258 rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED; \
261 rsp[(*rsp_len)++] = (b); \
264 /* Verify that the received command is a certain length. */
265 #define IPMI_CHECK_CMD_LEN(l) \
267 rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID; \
271 /* Check that the reservation in the command is valid. */
272 #define IPMI_CHECK_RESERVATION(off, r) \
274 if ((cmd[off] | (cmd[off + 1] << 8)) != r) { \
275 rsp[2] = IPMI_CC_INVALID_RESERVATION; \
281 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
);
283 static void ipmi_gettime(struct ipmi_time
*time
)
287 stime
= qemu_clock_get_ns(QEMU_CLOCK_HOST
);
288 time
->tv_sec
= stime
/ 1000000000LL;
289 time
->tv_nsec
= stime
% 1000000000LL;
292 static int64_t ipmi_getmonotime(void)
294 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
297 static void ipmi_timeout(void *opaque
)
299 IPMIBmcSim
*ibs
= opaque
;
301 ipmi_sim_handle_timeout(ibs
);
304 static void set_timestamp(IPMIBmcSim
*ibs
, uint8_t *ts
)
307 struct ipmi_time now
;
310 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
312 ts
[1] = (val
>> 8) & 0xff;
313 ts
[2] = (val
>> 16) & 0xff;
314 ts
[3] = (val
>> 24) & 0xff;
317 static void sdr_inc_reservation(IPMISdr
*sdr
)
320 if (sdr
->reservation
== 0) {
321 sdr
->reservation
= 1;
325 static int sdr_add_entry(IPMIBmcSim
*ibs
, const uint8_t *entry
,
326 unsigned int len
, uint16_t *recid
)
328 if ((len
< 5) || (len
> 255)) {
332 if (entry
[4] != len
- 5) {
336 if (ibs
->sdr
.next_free
+ len
> MAX_SDR_SIZE
) {
337 ibs
->sdr
.overflow
= 1;
341 memcpy(ibs
->sdr
.sdr
+ ibs
->sdr
.next_free
, entry
, len
);
342 ibs
->sdr
.sdr
[ibs
->sdr
.next_free
] = ibs
->sdr
.next_rec_id
& 0xff;
343 ibs
->sdr
.sdr
[ibs
->sdr
.next_free
+1] = (ibs
->sdr
.next_rec_id
>> 8) & 0xff;
344 ibs
->sdr
.sdr
[ibs
->sdr
.next_free
+2] = 0x51; /* Conform to IPMI 1.5 spec */
347 *recid
= ibs
->sdr
.next_rec_id
;
349 ibs
->sdr
.next_rec_id
++;
350 set_timestamp(ibs
, ibs
->sdr
.last_addition
);
351 ibs
->sdr
.next_free
+= len
;
352 sdr_inc_reservation(&ibs
->sdr
);
356 static int sdr_find_entry(IPMISdr
*sdr
, uint16_t recid
,
357 unsigned int *retpos
, uint16_t *nextrec
)
359 unsigned int pos
= *retpos
;
361 while (pos
< sdr
->next_free
) {
362 uint16_t trec
= sdr
->sdr
[pos
] | (sdr
->sdr
[pos
+ 1] << 8);
363 unsigned int nextpos
= pos
+ sdr
->sdr
[pos
+ 4];
367 if (nextpos
>= sdr
->next_free
) {
370 *nextrec
= (sdr
->sdr
[nextpos
] |
371 (sdr
->sdr
[nextpos
+ 1] << 8));
382 static void sel_inc_reservation(IPMISel
*sel
)
385 if (sel
->reservation
== 0) {
386 sel
->reservation
= 1;
390 /* Returns 1 if the SEL is full and can't hold the event. */
391 static int sel_add_event(IPMIBmcSim
*ibs
, uint8_t *event
)
395 set_timestamp(ibs
, event
+ 3);
396 if (ibs
->sel
.next_free
== MAX_SEL_SIZE
) {
397 ibs
->sel
.overflow
= 1;
400 event
[0] = ibs
->sel
.next_free
& 0xff;
401 event
[1] = (ibs
->sel
.next_free
>> 8) & 0xff;
402 memcpy(ibs
->sel
.last_addition
, event
+ 3, 4);
403 memcpy(ibs
->sel
.sel
[ibs
->sel
.next_free
], event
, 16);
404 ibs
->sel
.next_free
++;
405 sel_inc_reservation(&ibs
->sel
);
409 static int attn_set(IPMIBmcSim
*ibs
)
411 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
)
412 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
)
413 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs
);
416 static int attn_irq_enabled(IPMIBmcSim
*ibs
)
418 return (IPMI_BMC_MSG_INTS_ON(ibs
) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
))
419 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs
) &&
420 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
));
423 static void gen_event(IPMIBmcSim
*ibs
, unsigned int sens_num
, uint8_t deassert
,
424 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
426 IPMIInterface
*s
= ibs
->parent
.intf
;
427 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
429 IPMISensor
*sens
= ibs
->sensors
+ sens_num
;
431 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
434 if (!IPMI_SENSOR_GET_EVENTS_ON(sens
)) {
438 evt
[2] = 0x2; /* System event record */
439 evt
[7] = ibs
->parent
.slave_addr
;
441 evt
[9] = 0x04; /* Format version */
442 evt
[10] = sens
->sensor_type
;
444 evt
[12] = sens
->evt_reading_type_code
| (!!deassert
<< 7);
449 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
450 sel_add_event(ibs
, evt
);
453 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
457 memcpy(ibs
->evtbuf
, evt
, 16);
458 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
459 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
464 static void sensor_set_discrete_bit(IPMIBmcSim
*ibs
, unsigned int sensor
,
465 unsigned int bit
, unsigned int val
,
466 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
471 if (sensor
>= MAX_SENSORS
) {
479 sens
= ibs
->sensors
+ sensor
;
481 sens
->states
|= mask
& sens
->states_suppt
;
482 if (sens
->assert_states
& mask
) {
483 return; /* Already asserted */
485 sens
->assert_states
|= mask
& sens
->assert_suppt
;
486 if (sens
->assert_enable
& mask
& sens
->assert_states
) {
487 /* Send an event on assert */
488 gen_event(ibs
, sensor
, 0, evd1
, evd2
, evd3
);
491 sens
->states
&= ~(mask
& sens
->states_suppt
);
492 if (sens
->deassert_states
& mask
) {
493 return; /* Already deasserted */
495 sens
->deassert_states
|= mask
& sens
->deassert_suppt
;
496 if (sens
->deassert_enable
& mask
& sens
->deassert_states
) {
497 /* Send an event on deassert */
498 gen_event(ibs
, sensor
, 1, evd1
, evd2
, evd3
);
503 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim
*s
)
508 for (i
= 0; i
< MAX_SENSORS
; i
++) {
509 memset(s
->sensors
+ i
, 0, sizeof(*sens
));
513 for (i
= 0; !sdr_find_entry(&s
->sdr
, i
, &pos
, NULL
); i
++) {
514 uint8_t *sdr
= s
->sdr
.sdr
+ pos
;
515 unsigned int len
= sdr
[4];
520 if ((sdr
[3] < 1) || (sdr
[3] > 2)) {
521 continue; /* Not a sensor SDR we set from */
524 if (sdr
[7] > MAX_SENSORS
) {
527 sens
= s
->sensors
+ sdr
[7];
529 IPMI_SENSOR_SET_PRESENT(sens
, 1);
530 IPMI_SENSOR_SET_SCAN_ON(sens
, (sdr
[10] >> 6) & 1);
531 IPMI_SENSOR_SET_EVENTS_ON(sens
, (sdr
[10] >> 5) & 1);
532 sens
->assert_suppt
= sdr
[14] | (sdr
[15] << 8);
533 sens
->deassert_suppt
= sdr
[16] | (sdr
[17] << 8);
534 sens
->states_suppt
= sdr
[18] | (sdr
[19] << 8);
535 sens
->sensor_type
= sdr
[12];
536 sens
->evt_reading_type_code
= sdr
[13] & 0x7f;
538 /* Enable all the events that are supported. */
539 sens
->assert_enable
= sens
->assert_suppt
;
540 sens
->deassert_enable
= sens
->deassert_suppt
;
544 static int ipmi_register_netfn(IPMIBmcSim
*s
, unsigned int netfn
,
545 const IPMINetfn
*netfnd
)
547 if ((netfn
& 1) || (netfn
> MAX_NETFNS
) || (s
->netfns
[netfn
/ 2])) {
550 s
->netfns
[netfn
/ 2] = netfnd
;
554 static void next_timeout(IPMIBmcSim
*ibs
)
557 if (ibs
->watchdog_running
) {
558 next
= ibs
->watchdog_expiry
;
561 next
= ipmi_getmonotime() + 60 * 1000000000LL;
563 timer_mod_ns(ibs
->timer
, next
);
566 static void ipmi_sim_handle_command(IPMIBmc
*b
,
567 uint8_t *cmd
, unsigned int cmd_len
,
568 unsigned int max_cmd_len
,
571 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
572 IPMIInterface
*s
= ibs
->parent
.intf
;
573 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
575 uint8_t rsp
[MAX_IPMI_MSG_SIZE
];
576 unsigned int rsp_len_holder
= 0;
577 unsigned int *rsp_len
= &rsp_len_holder
;
578 unsigned int max_rsp_len
= sizeof(rsp
);
580 /* Set up the response, set the low bit of NETFN. */
581 /* Note that max_rsp_len must be at least 3 */
582 IPMI_ADD_RSP_DATA(cmd
[0] | 0x04);
583 IPMI_ADD_RSP_DATA(cmd
[1]);
584 IPMI_ADD_RSP_DATA(0); /* Assume success */
586 /* If it's too short or it was truncated, return an error. */
588 rsp
[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID
;
591 if (cmd_len
> max_cmd_len
) {
592 rsp
[2] = IPMI_CC_REQUEST_DATA_TRUNCATED
;
596 if ((cmd
[0] & 0x03) != 0) {
597 /* Only have stuff on LUN 0 */
598 rsp
[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN
;
604 /* Odd netfns are not valid, make sure the command is registered */
605 if ((netfn
& 1) || !ibs
->netfns
[netfn
/ 2] ||
606 (cmd
[1] >= ibs
->netfns
[netfn
/ 2]->cmd_nums
) ||
607 (!ibs
->netfns
[netfn
/ 2]->cmd_handlers
[cmd
[1]])) {
608 rsp
[2] = IPMI_CC_INVALID_CMD
;
612 ibs
->netfns
[netfn
/ 2]->cmd_handlers
[cmd
[1]](ibs
, cmd
, cmd_len
, rsp
, rsp_len
,
616 k
->handle_rsp(s
, msg_id
, rsp
, *rsp_len
);
621 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
)
623 IPMIInterface
*s
= ibs
->parent
.intf
;
624 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
626 if (!ibs
->watchdog_running
) {
630 if (!ibs
->watchdog_preaction_ran
) {
631 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
)) {
632 case IPMI_BMC_WATCHDOG_PRE_NMI
:
633 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
634 k
->do_hw_op(s
, IPMI_SEND_NMI
, 0);
635 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
636 0xc8, (2 << 4) | 0xf, 0xff);
639 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
640 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
641 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
642 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
643 0xc8, (3 << 4) | 0xf, 0xff);
650 ibs
->watchdog_preaction_ran
= 1;
651 /* Issued the pretimeout, do the rest of the timeout now. */
652 ibs
->watchdog_expiry
= ipmi_getmonotime();
653 ibs
->watchdog_expiry
+= ibs
->watchdog_pretimeout
* 1000000000LL;
658 ibs
->watchdog_running
= 0; /* Stop the watchdog on a timeout */
659 ibs
->watchdog_expired
|= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs
));
660 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
)) {
661 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
662 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 0, 1,
663 0xc0, ibs
->watchdog_use
& 0xf, 0xff);
666 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
667 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 1, 1,
668 0xc1, ibs
->watchdog_use
& 0xf, 0xff);
669 k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0);
672 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
673 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
674 0xc2, ibs
->watchdog_use
& 0xf, 0xff);
675 k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0);
678 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
679 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
680 0xc3, ibs
->watchdog_use
& 0xf, 0xff);
681 k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0);
689 static void chassis_capabilities(IPMIBmcSim
*ibs
,
690 uint8_t *cmd
, unsigned int cmd_len
,
691 uint8_t *rsp
, unsigned int *rsp_len
,
692 unsigned int max_rsp_len
)
694 IPMI_ADD_RSP_DATA(0);
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
);
698 IPMI_ADD_RSP_DATA(ibs
->parent
.slave_addr
);
703 static void chassis_status(IPMIBmcSim
*ibs
,
704 uint8_t *cmd
, unsigned int cmd_len
,
705 uint8_t *rsp
, unsigned int *rsp_len
,
706 unsigned int max_rsp_len
)
708 IPMI_ADD_RSP_DATA(0x61); /* Unknown power restore, power is on */
709 IPMI_ADD_RSP_DATA(0);
710 IPMI_ADD_RSP_DATA(0);
711 IPMI_ADD_RSP_DATA(0);
716 static void chassis_control(IPMIBmcSim
*ibs
,
717 uint8_t *cmd
, unsigned int cmd_len
,
718 uint8_t *rsp
, unsigned int *rsp_len
,
719 unsigned int max_rsp_len
)
721 IPMIInterface
*s
= ibs
->parent
.intf
;
722 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
724 IPMI_CHECK_CMD_LEN(3);
725 switch (cmd
[2] & 0xf) {
726 case 0: /* power down */
727 rsp
[2] = k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0);
729 case 1: /* power up */
730 rsp
[2] = k
->do_hw_op(s
, IPMI_POWERON_CHASSIS
, 0);
732 case 2: /* power cycle */
733 rsp
[2] = k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0);
735 case 3: /* hard reset */
736 rsp
[2] = k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0);
738 case 4: /* pulse diagnostic interrupt */
739 rsp
[2] = k
->do_hw_op(s
, IPMI_PULSE_DIAG_IRQ
, 0);
741 case 5: /* soft shutdown via ACPI by overtemp emulation */
742 rsp
[2] = k
->do_hw_op(s
,
743 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP
, 0);
746 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
753 static void get_device_id(IPMIBmcSim
*ibs
,
754 uint8_t *cmd
, unsigned int cmd_len
,
755 uint8_t *rsp
, unsigned int *rsp_len
,
756 unsigned int max_rsp_len
)
758 IPMI_ADD_RSP_DATA(ibs
->device_id
);
759 IPMI_ADD_RSP_DATA(ibs
->device_rev
& 0xf);
760 IPMI_ADD_RSP_DATA(ibs
->fwrev1
& 0x7f);
761 IPMI_ADD_RSP_DATA(ibs
->fwrev2
);
762 IPMI_ADD_RSP_DATA(ibs
->ipmi_version
);
763 IPMI_ADD_RSP_DATA(0x07); /* sensor, SDR, and SEL. */
764 IPMI_ADD_RSP_DATA(ibs
->mfg_id
[0]);
765 IPMI_ADD_RSP_DATA(ibs
->mfg_id
[1]);
766 IPMI_ADD_RSP_DATA(ibs
->mfg_id
[2]);
767 IPMI_ADD_RSP_DATA(ibs
->product_id
[0]);
768 IPMI_ADD_RSP_DATA(ibs
->product_id
[1]);
773 static void set_global_enables(IPMIBmcSim
*ibs
, uint8_t val
)
775 IPMIInterface
*s
= ibs
->parent
.intf
;
776 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
779 ibs
->bmc_global_enables
= val
;
781 irqs_on
= val
& (IPMI_BMC_EVBUF_FULL_INT_BIT
|
782 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT
);
784 k
->set_irq_enable(s
, irqs_on
);
787 static void cold_reset(IPMIBmcSim
*ibs
,
788 uint8_t *cmd
, unsigned int cmd_len
,
789 uint8_t *rsp
, unsigned int *rsp_len
,
790 unsigned int max_rsp_len
)
792 IPMIInterface
*s
= ibs
->parent
.intf
;
793 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
795 /* Disable all interrupts */
796 set_global_enables(ibs
, 1 << IPMI_BMC_EVENT_LOG_BIT
);
803 static void warm_reset(IPMIBmcSim
*ibs
,
804 uint8_t *cmd
, unsigned int cmd_len
,
805 uint8_t *rsp
, unsigned int *rsp_len
,
806 unsigned int max_rsp_len
)
808 IPMIInterface
*s
= ibs
->parent
.intf
;
809 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
816 static void set_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_CHECK_CMD_LEN(3);
822 set_global_enables(ibs
, cmd
[2]);
827 static void get_bmc_global_enables(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 IPMI_ADD_RSP_DATA(ibs
->bmc_global_enables
);
837 static void clr_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 IPMIInterface
*s
= ibs
->parent
.intf
;
843 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
845 IPMI_CHECK_CMD_LEN(3);
846 ibs
->msg_flags
&= ~cmd
[2];
847 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
852 static void get_msg_flags(IPMIBmcSim
*ibs
,
853 uint8_t *cmd
, unsigned int cmd_len
,
854 uint8_t *rsp
, unsigned int *rsp_len
,
855 unsigned int max_rsp_len
)
857 IPMI_ADD_RSP_DATA(ibs
->msg_flags
);
862 static void read_evt_msg_buf(IPMIBmcSim
*ibs
,
863 uint8_t *cmd
, unsigned int cmd_len
,
864 uint8_t *rsp
, unsigned int *rsp_len
,
865 unsigned int max_rsp_len
)
867 IPMIInterface
*s
= ibs
->parent
.intf
;
868 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
871 if (!(ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
)) {
875 for (i
= 0; i
< 16; i
++) {
876 IPMI_ADD_RSP_DATA(ibs
->evtbuf
[i
]);
878 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
879 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
884 static void get_msg(IPMIBmcSim
*ibs
,
885 uint8_t *cmd
, unsigned int cmd_len
,
886 uint8_t *rsp
, unsigned int *rsp_len
,
887 unsigned int max_rsp_len
)
889 IPMIRcvBufEntry
*msg
;
891 qemu_mutex_lock(&ibs
->lock
);
892 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
893 rsp
[2] = 0x80; /* Queue empty */
896 rsp
[3] = 0; /* Channel 0 */
898 msg
= QTAILQ_FIRST(&ibs
->rcvbufs
);
899 memcpy(rsp
+ 4, msg
->buf
, msg
->len
);
900 *rsp_len
+= msg
->len
;
901 QTAILQ_REMOVE(&ibs
->rcvbufs
, msg
, entry
);
904 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
905 IPMIInterface
*s
= ibs
->parent
.intf
;
906 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
908 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
909 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
913 qemu_mutex_unlock(&ibs
->lock
);
918 ipmb_checksum(unsigned char *data
, int size
, unsigned char csum
)
920 for (; size
> 0; size
--, data
++) {
927 static void send_msg(IPMIBmcSim
*ibs
,
928 uint8_t *cmd
, unsigned int cmd_len
,
929 uint8_t *rsp
, unsigned int *rsp_len
,
930 unsigned int max_rsp_len
)
932 IPMIInterface
*s
= ibs
->parent
.intf
;
933 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
934 IPMIRcvBufEntry
*msg
;
936 uint8_t netfn
, rqLun
, rsLun
, rqSeq
;
938 IPMI_CHECK_CMD_LEN(3);
941 /* We only handle channel 0 with no options */
942 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
946 IPMI_CHECK_CMD_LEN(10);
947 if (cmd
[3] != 0x40) {
948 /* We only emulate a MC at address 0x40. */
949 rsp
[2] = 0x83; /* NAK on write */
953 cmd
+= 3; /* Skip the header. */
957 * At this point we "send" the message successfully. Any error will
958 * be returned in the response.
960 if (ipmb_checksum(cmd
, cmd_len
, 0) != 0 ||
961 cmd
[3] != 0x20) { /* Improper response address */
962 goto out
; /* No response */
966 rqLun
= cmd
[4] & 0x3;
967 rsLun
= cmd
[1] & 0x3;
971 /* We only support LUN 2 coming back to us. */
975 msg
= g_malloc(sizeof(*msg
));
976 msg
->buf
[0] = ((netfn
| 1) << 2) | rqLun
; /* NetFN, and make a response */
977 msg
->buf
[1] = ipmb_checksum(msg
->buf
, 1, 0);
978 msg
->buf
[2] = cmd
[0]; /* rsSA */
979 msg
->buf
[3] = (rqSeq
<< 2) | rsLun
;
980 msg
->buf
[4] = cmd
[5]; /* Cmd */
981 msg
->buf
[5] = 0; /* Completion Code */
984 if ((cmd
[1] >> 2) != IPMI_NETFN_APP
|| cmd
[5] != IPMI_CMD_GET_DEVICE_ID
) {
985 /* Not a command we handle. */
986 msg
->buf
[5] = IPMI_CC_INVALID_CMD
;
990 buf
= msg
->buf
+ msg
->len
; /* After the CC */
1005 msg
->buf
[msg
->len
] = ipmb_checksum(msg
->buf
, msg
->len
, 0);
1007 qemu_mutex_lock(&ibs
->lock
);
1008 QTAILQ_INSERT_TAIL(&ibs
->rcvbufs
, msg
, entry
);
1009 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
1010 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
1011 qemu_mutex_unlock(&ibs
->lock
);
1017 static void do_watchdog_reset(IPMIBmcSim
*ibs
)
1019 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
) ==
1020 IPMI_BMC_WATCHDOG_ACTION_NONE
) {
1021 ibs
->watchdog_running
= 0;
1024 ibs
->watchdog_preaction_ran
= 0;
1027 /* Timeout is in tenths of a second, offset is in seconds */
1028 ibs
->watchdog_expiry
= ipmi_getmonotime();
1029 ibs
->watchdog_expiry
+= ibs
->watchdog_timeout
* 100000000LL;
1030 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
) != IPMI_BMC_WATCHDOG_PRE_NONE
) {
1031 ibs
->watchdog_expiry
-= ibs
->watchdog_pretimeout
* 1000000000LL;
1033 ibs
->watchdog_running
= 1;
1036 static void reset_watchdog_timer(IPMIBmcSim
*ibs
,
1037 uint8_t *cmd
, unsigned int cmd_len
,
1038 uint8_t *rsp
, unsigned int *rsp_len
,
1039 unsigned int max_rsp_len
)
1041 if (!ibs
->watchdog_initialized
) {
1045 do_watchdog_reset(ibs
);
1050 static void set_watchdog_timer(IPMIBmcSim
*ibs
,
1051 uint8_t *cmd
, unsigned int cmd_len
,
1052 uint8_t *rsp
, unsigned int *rsp_len
,
1053 unsigned int max_rsp_len
)
1055 IPMIInterface
*s
= ibs
->parent
.intf
;
1056 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1059 IPMI_CHECK_CMD_LEN(8);
1060 val
= cmd
[2] & 0x7; /* Validate use */
1061 if (val
== 0 || val
> 5) {
1062 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1065 val
= cmd
[3] & 0x7; /* Validate action */
1067 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
1070 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
1071 rsp
[2] = k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 1);
1074 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
1075 rsp
[2] = k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 1);
1078 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
1079 rsp
[2] = k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 1);
1083 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1086 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1090 val
= (cmd
[3] >> 4) & 0x7; /* Validate preaction */
1092 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
1093 case IPMI_BMC_WATCHDOG_PRE_NONE
:
1096 case IPMI_BMC_WATCHDOG_PRE_NMI
:
1097 if (!k
->do_hw_op(s
, IPMI_SEND_NMI
, 1)) {
1098 /* NMI not supported. */
1099 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1103 /* We don't support PRE_SMI */
1104 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1108 ibs
->watchdog_initialized
= 1;
1109 ibs
->watchdog_use
= cmd
[2] & IPMI_BMC_WATCHDOG_USE_MASK
;
1110 ibs
->watchdog_action
= cmd
[3] & IPMI_BMC_WATCHDOG_ACTION_MASK
;
1111 ibs
->watchdog_pretimeout
= cmd
[4];
1112 ibs
->watchdog_expired
&= ~cmd
[5];
1113 ibs
->watchdog_timeout
= cmd
[6] | (((uint16_t) cmd
[7]) << 8);
1114 if (ibs
->watchdog_running
& IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs
)) {
1115 do_watchdog_reset(ibs
);
1117 ibs
->watchdog_running
= 0;
1123 static void get_watchdog_timer(IPMIBmcSim
*ibs
,
1124 uint8_t *cmd
, unsigned int cmd_len
,
1125 uint8_t *rsp
, unsigned int *rsp_len
,
1126 unsigned int max_rsp_len
)
1128 IPMI_ADD_RSP_DATA(ibs
->watchdog_use
);
1129 IPMI_ADD_RSP_DATA(ibs
->watchdog_action
);
1130 IPMI_ADD_RSP_DATA(ibs
->watchdog_pretimeout
);
1131 IPMI_ADD_RSP_DATA(ibs
->watchdog_expired
);
1132 if (ibs
->watchdog_running
) {
1134 timeout
= ((ibs
->watchdog_expiry
- ipmi_getmonotime() + 50000000)
1136 IPMI_ADD_RSP_DATA(timeout
& 0xff);
1137 IPMI_ADD_RSP_DATA((timeout
>> 8) & 0xff);
1139 IPMI_ADD_RSP_DATA(0);
1140 IPMI_ADD_RSP_DATA(0);
1146 static void get_sdr_rep_info(IPMIBmcSim
*ibs
,
1147 uint8_t *cmd
, unsigned int cmd_len
,
1148 uint8_t *rsp
, unsigned int *rsp_len
,
1149 unsigned int max_rsp_len
)
1153 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 spec */
1154 IPMI_ADD_RSP_DATA(ibs
->sdr
.next_rec_id
& 0xff);
1155 IPMI_ADD_RSP_DATA((ibs
->sdr
.next_rec_id
>> 8) & 0xff);
1156 IPMI_ADD_RSP_DATA((MAX_SDR_SIZE
- ibs
->sdr
.next_free
) & 0xff);
1157 IPMI_ADD_RSP_DATA(((MAX_SDR_SIZE
- ibs
->sdr
.next_free
) >> 8) & 0xff);
1158 for (i
= 0; i
< 4; i
++) {
1159 IPMI_ADD_RSP_DATA(ibs
->sdr
.last_addition
[i
]);
1161 for (i
= 0; i
< 4; i
++) {
1162 IPMI_ADD_RSP_DATA(ibs
->sdr
.last_clear
[i
]);
1164 /* Only modal support, reserve supported */
1165 IPMI_ADD_RSP_DATA((ibs
->sdr
.overflow
<< 7) | 0x22);
1170 static void reserve_sdr_rep(IPMIBmcSim
*ibs
,
1171 uint8_t *cmd
, unsigned int cmd_len
,
1172 uint8_t *rsp
, unsigned int *rsp_len
,
1173 unsigned int max_rsp_len
)
1175 IPMI_ADD_RSP_DATA(ibs
->sdr
.reservation
& 0xff);
1176 IPMI_ADD_RSP_DATA((ibs
->sdr
.reservation
>> 8) & 0xff);
1181 static void get_sdr(IPMIBmcSim
*ibs
,
1182 uint8_t *cmd
, unsigned int cmd_len
,
1183 uint8_t *rsp
, unsigned int *rsp_len
,
1184 unsigned int max_rsp_len
)
1189 IPMI_CHECK_CMD_LEN(8);
1191 IPMI_CHECK_RESERVATION(2, ibs
->sdr
.reservation
);
1194 if (sdr_find_entry(&ibs
->sdr
, cmd
[4] | (cmd
[5] << 8),
1196 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1199 if (cmd
[6] > (ibs
->sdr
.sdr
[pos
+ 4])) {
1200 rsp
[2] = IPMI_CC_PARM_OUT_OF_RANGE
;
1204 IPMI_ADD_RSP_DATA(nextrec
& 0xff);
1205 IPMI_ADD_RSP_DATA((nextrec
>> 8) & 0xff);
1207 if (cmd
[7] == 0xff) {
1208 cmd
[7] = ibs
->sdr
.sdr
[pos
+ 4] - cmd
[6];
1211 if ((cmd
[7] + *rsp_len
) > max_rsp_len
) {
1212 rsp
[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES
;
1215 memcpy(rsp
+ *rsp_len
, ibs
->sdr
.sdr
+ pos
+ cmd
[6], cmd
[7]);
1221 static void add_sdr(IPMIBmcSim
*ibs
,
1222 uint8_t *cmd
, unsigned int cmd_len
,
1223 uint8_t *rsp
, unsigned int *rsp_len
,
1224 unsigned int max_rsp_len
)
1228 if (sdr_add_entry(ibs
, cmd
+ 2, cmd_len
- 2, &recid
)) {
1229 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1232 IPMI_ADD_RSP_DATA(recid
& 0xff);
1233 IPMI_ADD_RSP_DATA((recid
>> 8) & 0xff);
1238 static void clear_sdr_rep(IPMIBmcSim
*ibs
,
1239 uint8_t *cmd
, unsigned int cmd_len
,
1240 uint8_t *rsp
, unsigned int *rsp_len
,
1241 unsigned int max_rsp_len
)
1243 IPMI_CHECK_CMD_LEN(8);
1244 IPMI_CHECK_RESERVATION(2, ibs
->sdr
.reservation
);
1245 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1246 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1249 if (cmd
[7] == 0xaa) {
1250 ibs
->sdr
.next_free
= 0;
1251 ibs
->sdr
.overflow
= 0;
1252 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1253 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1254 sdr_inc_reservation(&ibs
->sdr
);
1255 } else if (cmd
[7] == 0) {
1256 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1258 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1265 static void get_sel_info(IPMIBmcSim
*ibs
,
1266 uint8_t *cmd
, unsigned int cmd_len
,
1267 uint8_t *rsp
, unsigned int *rsp_len
,
1268 unsigned int max_rsp_len
)
1270 unsigned int i
, val
;
1272 IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 */
1273 IPMI_ADD_RSP_DATA(ibs
->sel
.next_free
& 0xff);
1274 IPMI_ADD_RSP_DATA((ibs
->sel
.next_free
>> 8) & 0xff);
1275 val
= (MAX_SEL_SIZE
- ibs
->sel
.next_free
) * 16;
1276 IPMI_ADD_RSP_DATA(val
& 0xff);
1277 IPMI_ADD_RSP_DATA((val
>> 8) & 0xff);
1278 for (i
= 0; i
< 4; i
++) {
1279 IPMI_ADD_RSP_DATA(ibs
->sel
.last_addition
[i
]);
1281 for (i
= 0; i
< 4; i
++) {
1282 IPMI_ADD_RSP_DATA(ibs
->sel
.last_clear
[i
]);
1284 /* Only support Reserve SEL */
1285 IPMI_ADD_RSP_DATA((ibs
->sel
.overflow
<< 7) | 0x02);
1290 static void reserve_sel(IPMIBmcSim
*ibs
,
1291 uint8_t *cmd
, unsigned int cmd_len
,
1292 uint8_t *rsp
, unsigned int *rsp_len
,
1293 unsigned int max_rsp_len
)
1295 IPMI_ADD_RSP_DATA(ibs
->sel
.reservation
& 0xff);
1296 IPMI_ADD_RSP_DATA((ibs
->sel
.reservation
>> 8) & 0xff);
1301 static void get_sel_entry(IPMIBmcSim
*ibs
,
1302 uint8_t *cmd
, unsigned int cmd_len
,
1303 uint8_t *rsp
, unsigned int *rsp_len
,
1304 unsigned int max_rsp_len
)
1308 IPMI_CHECK_CMD_LEN(8);
1310 IPMI_CHECK_RESERVATION(2, ibs
->sel
.reservation
);
1312 if (ibs
->sel
.next_free
== 0) {
1313 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1317 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1320 if (cmd
[7] == 0xff) {
1322 } else if ((cmd
[7] + cmd
[6]) > 16) {
1323 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1329 val
= cmd
[4] | (cmd
[5] << 8);
1330 if (val
== 0xffff) {
1331 val
= ibs
->sel
.next_free
- 1;
1332 } else if (val
>= ibs
->sel
.next_free
) {
1333 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1336 if ((val
+ 1) == ibs
->sel
.next_free
) {
1337 IPMI_ADD_RSP_DATA(0xff);
1338 IPMI_ADD_RSP_DATA(0xff);
1340 IPMI_ADD_RSP_DATA((val
+ 1) & 0xff);
1341 IPMI_ADD_RSP_DATA(((val
+ 1) >> 8) & 0xff);
1343 for (; cmd
[6] < cmd
[7]; cmd
[6]++) {
1344 IPMI_ADD_RSP_DATA(ibs
->sel
.sel
[val
][cmd
[6]]);
1350 static void add_sel_entry(IPMIBmcSim
*ibs
,
1351 uint8_t *cmd
, unsigned int cmd_len
,
1352 uint8_t *rsp
, unsigned int *rsp_len
,
1353 unsigned int max_rsp_len
)
1355 IPMI_CHECK_CMD_LEN(18);
1356 if (sel_add_event(ibs
, cmd
+ 2)) {
1357 rsp
[2] = IPMI_CC_OUT_OF_SPACE
;
1360 /* sel_add_event fills in the record number. */
1361 IPMI_ADD_RSP_DATA(cmd
[2]);
1362 IPMI_ADD_RSP_DATA(cmd
[3]);
1367 static void clear_sel(IPMIBmcSim
*ibs
,
1368 uint8_t *cmd
, unsigned int cmd_len
,
1369 uint8_t *rsp
, unsigned int *rsp_len
,
1370 unsigned int max_rsp_len
)
1372 IPMI_CHECK_CMD_LEN(8);
1373 IPMI_CHECK_RESERVATION(2, ibs
->sel
.reservation
);
1374 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1375 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1378 if (cmd
[7] == 0xaa) {
1379 ibs
->sel
.next_free
= 0;
1380 ibs
->sel
.overflow
= 0;
1381 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1382 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1383 sel_inc_reservation(&ibs
->sel
);
1384 } else if (cmd
[7] == 0) {
1385 IPMI_ADD_RSP_DATA(1); /* Erasure complete */
1387 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1394 static void get_sel_time(IPMIBmcSim
*ibs
,
1395 uint8_t *cmd
, unsigned int cmd_len
,
1396 uint8_t *rsp
, unsigned int *rsp_len
,
1397 unsigned int max_rsp_len
)
1400 struct ipmi_time now
;
1403 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
1404 IPMI_ADD_RSP_DATA(val
& 0xff);
1405 IPMI_ADD_RSP_DATA((val
>> 8) & 0xff);
1406 IPMI_ADD_RSP_DATA((val
>> 16) & 0xff);
1407 IPMI_ADD_RSP_DATA((val
>> 24) & 0xff);
1412 static void set_sel_time(IPMIBmcSim
*ibs
,
1413 uint8_t *cmd
, unsigned int cmd_len
,
1414 uint8_t *rsp
, unsigned int *rsp_len
,
1415 unsigned int max_rsp_len
)
1418 struct ipmi_time now
;
1420 IPMI_CHECK_CMD_LEN(6);
1421 val
= cmd
[2] | (cmd
[3] << 8) | (cmd
[4] << 16) | (cmd
[5] << 24);
1423 ibs
->sel
.time_offset
= now
.tv_sec
- ((long) val
);
1428 static void set_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(4);
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 switch ((cmd
[3] >> 4) & 0x3) {
1443 case 0: /* Do not change */
1445 case 1: /* Enable bits */
1447 sens
->assert_enable
|= cmd
[4];
1450 sens
->assert_enable
|= cmd
[5] << 8;
1453 sens
->deassert_enable
|= cmd
[6];
1456 sens
->deassert_enable
|= cmd
[7] << 8;
1459 case 2: /* Disable bits */
1461 sens
->assert_enable
&= ~cmd
[4];
1464 sens
->assert_enable
&= ~(cmd
[5] << 8);
1467 sens
->deassert_enable
&= ~cmd
[6];
1470 sens
->deassert_enable
&= ~(cmd
[7] << 8);
1474 rsp
[2] = IPMI_CC_INVALID_DATA_FIELD
;
1477 IPMI_SENSOR_SET_RET_STATUS(sens
, cmd
[3]);
1482 static void get_sensor_evt_enable(IPMIBmcSim
*ibs
,
1483 uint8_t *cmd
, unsigned int cmd_len
,
1484 uint8_t *rsp
, unsigned int *rsp_len
,
1485 unsigned int max_rsp_len
)
1489 IPMI_CHECK_CMD_LEN(3);
1490 if ((cmd
[2] > MAX_SENSORS
) ||
1491 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1492 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1495 sens
= ibs
->sensors
+ cmd
[2];
1496 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens
));
1497 IPMI_ADD_RSP_DATA(sens
->assert_enable
& 0xff);
1498 IPMI_ADD_RSP_DATA((sens
->assert_enable
>> 8) & 0xff);
1499 IPMI_ADD_RSP_DATA(sens
->deassert_enable
& 0xff);
1500 IPMI_ADD_RSP_DATA((sens
->deassert_enable
>> 8) & 0xff);
1505 static void rearm_sensor_evts(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 IPMI_CHECK_CMD_LEN(4);
1513 if ((cmd
[2] > MAX_SENSORS
) ||
1514 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1515 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1518 sens
= ibs
->sensors
+ cmd
[2];
1520 if ((cmd
[3] & 0x80) == 0) {
1521 /* Just clear everything */
1529 static void get_sensor_evt_status(IPMIBmcSim
*ibs
,
1530 uint8_t *cmd
, unsigned int cmd_len
,
1531 uint8_t *rsp
, unsigned int *rsp_len
,
1532 unsigned int max_rsp_len
)
1536 IPMI_CHECK_CMD_LEN(3);
1537 if ((cmd
[2] > MAX_SENSORS
) ||
1538 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1539 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1542 sens
= ibs
->sensors
+ cmd
[2];
1543 IPMI_ADD_RSP_DATA(sens
->reading
);
1544 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens
));
1545 IPMI_ADD_RSP_DATA(sens
->assert_states
& 0xff);
1546 IPMI_ADD_RSP_DATA((sens
->assert_states
>> 8) & 0xff);
1547 IPMI_ADD_RSP_DATA(sens
->deassert_states
& 0xff);
1548 IPMI_ADD_RSP_DATA((sens
->deassert_states
>> 8) & 0xff);
1553 static void get_sensor_reading(IPMIBmcSim
*ibs
,
1554 uint8_t *cmd
, unsigned int cmd_len
,
1555 uint8_t *rsp
, unsigned int *rsp_len
,
1556 unsigned int max_rsp_len
)
1560 IPMI_CHECK_CMD_LEN(3);
1561 if ((cmd
[2] > MAX_SENSORS
) ||
1562 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1563 rsp
[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT
;
1566 sens
= ibs
->sensors
+ cmd
[2];
1567 IPMI_ADD_RSP_DATA(sens
->reading
);
1568 IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens
));
1569 IPMI_ADD_RSP_DATA(sens
->states
& 0xff);
1570 if (IPMI_SENSOR_IS_DISCRETE(sens
)) {
1571 IPMI_ADD_RSP_DATA((sens
->states
>> 8) & 0xff);
1577 static const IPMICmdHandler chassis_cmds
[IPMI_NETFN_CHASSIS_MAXCMD
] = {
1578 [IPMI_CMD_GET_CHASSIS_CAPABILITIES
] = chassis_capabilities
,
1579 [IPMI_CMD_GET_CHASSIS_STATUS
] = chassis_status
,
1580 [IPMI_CMD_CHASSIS_CONTROL
] = chassis_control
1582 static const IPMINetfn chassis_netfn
= {
1583 .cmd_nums
= IPMI_NETFN_CHASSIS_MAXCMD
,
1584 .cmd_handlers
= chassis_cmds
1587 static const IPMICmdHandler
1588 sensor_event_cmds
[IPMI_NETFN_SENSOR_EVENT_MAXCMD
] = {
1589 [IPMI_CMD_SET_SENSOR_EVT_ENABLE
] = set_sensor_evt_enable
,
1590 [IPMI_CMD_GET_SENSOR_EVT_ENABLE
] = get_sensor_evt_enable
,
1591 [IPMI_CMD_REARM_SENSOR_EVTS
] = rearm_sensor_evts
,
1592 [IPMI_CMD_GET_SENSOR_EVT_STATUS
] = get_sensor_evt_status
,
1593 [IPMI_CMD_GET_SENSOR_READING
] = get_sensor_reading
1595 static const IPMINetfn sensor_event_netfn
= {
1596 .cmd_nums
= IPMI_NETFN_SENSOR_EVENT_MAXCMD
,
1597 .cmd_handlers
= sensor_event_cmds
1600 static const IPMICmdHandler app_cmds
[IPMI_NETFN_APP_MAXCMD
] = {
1601 [IPMI_CMD_GET_DEVICE_ID
] = get_device_id
,
1602 [IPMI_CMD_COLD_RESET
] = cold_reset
,
1603 [IPMI_CMD_WARM_RESET
] = warm_reset
,
1604 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES
] = set_bmc_global_enables
,
1605 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES
] = get_bmc_global_enables
,
1606 [IPMI_CMD_CLR_MSG_FLAGS
] = clr_msg_flags
,
1607 [IPMI_CMD_GET_MSG_FLAGS
] = get_msg_flags
,
1608 [IPMI_CMD_GET_MSG
] = get_msg
,
1609 [IPMI_CMD_SEND_MSG
] = send_msg
,
1610 [IPMI_CMD_READ_EVT_MSG_BUF
] = read_evt_msg_buf
,
1611 [IPMI_CMD_RESET_WATCHDOG_TIMER
] = reset_watchdog_timer
,
1612 [IPMI_CMD_SET_WATCHDOG_TIMER
] = set_watchdog_timer
,
1613 [IPMI_CMD_GET_WATCHDOG_TIMER
] = get_watchdog_timer
,
1615 static const IPMINetfn app_netfn
= {
1616 .cmd_nums
= IPMI_NETFN_APP_MAXCMD
,
1617 .cmd_handlers
= app_cmds
1620 static const IPMICmdHandler storage_cmds
[IPMI_NETFN_STORAGE_MAXCMD
] = {
1621 [IPMI_CMD_GET_SDR_REP_INFO
] = get_sdr_rep_info
,
1622 [IPMI_CMD_RESERVE_SDR_REP
] = reserve_sdr_rep
,
1623 [IPMI_CMD_GET_SDR
] = get_sdr
,
1624 [IPMI_CMD_ADD_SDR
] = add_sdr
,
1625 [IPMI_CMD_CLEAR_SDR_REP
] = clear_sdr_rep
,
1626 [IPMI_CMD_GET_SEL_INFO
] = get_sel_info
,
1627 [IPMI_CMD_RESERVE_SEL
] = reserve_sel
,
1628 [IPMI_CMD_GET_SEL_ENTRY
] = get_sel_entry
,
1629 [IPMI_CMD_ADD_SEL_ENTRY
] = add_sel_entry
,
1630 [IPMI_CMD_CLEAR_SEL
] = clear_sel
,
1631 [IPMI_CMD_GET_SEL_TIME
] = get_sel_time
,
1632 [IPMI_CMD_SET_SEL_TIME
] = set_sel_time
,
1635 static const IPMINetfn storage_netfn
= {
1636 .cmd_nums
= IPMI_NETFN_STORAGE_MAXCMD
,
1637 .cmd_handlers
= storage_cmds
1640 static void register_cmds(IPMIBmcSim
*s
)
1642 ipmi_register_netfn(s
, IPMI_NETFN_CHASSIS
, &chassis_netfn
);
1643 ipmi_register_netfn(s
, IPMI_NETFN_SENSOR_EVENT
, &sensor_event_netfn
);
1644 ipmi_register_netfn(s
, IPMI_NETFN_APP
, &app_netfn
);
1645 ipmi_register_netfn(s
, IPMI_NETFN_STORAGE
, &storage_netfn
);
1648 static const uint8_t init_sdrs
[] = {
1649 /* Watchdog device */
1650 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1651 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1654 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1656 0xff, 0xff, 0x00, 0x00, 0x00
1659 static const VMStateDescription vmstate_ipmi_sim
= {
1660 .name
= TYPE_IPMI_BMC_SIMULATOR
,
1662 .minimum_version_id
= 1,
1663 .fields
= (VMStateField
[]) {
1664 VMSTATE_UINT8(bmc_global_enables
, IPMIBmcSim
),
1665 VMSTATE_UINT8(msg_flags
, IPMIBmcSim
),
1666 VMSTATE_BOOL(watchdog_initialized
, IPMIBmcSim
),
1667 VMSTATE_UINT8(watchdog_use
, IPMIBmcSim
),
1668 VMSTATE_UINT8(watchdog_action
, IPMIBmcSim
),
1669 VMSTATE_UINT8(watchdog_pretimeout
, IPMIBmcSim
),
1670 VMSTATE_BOOL(watchdog_expired
, IPMIBmcSim
),
1671 VMSTATE_UINT16(watchdog_timeout
, IPMIBmcSim
),
1672 VMSTATE_BOOL(watchdog_running
, IPMIBmcSim
),
1673 VMSTATE_BOOL(watchdog_preaction_ran
, IPMIBmcSim
),
1674 VMSTATE_INT64(watchdog_expiry
, IPMIBmcSim
),
1675 VMSTATE_UINT8_ARRAY(evtbuf
, IPMIBmcSim
, 16),
1676 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].status
, IPMIBmcSim
),
1677 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].reading
, IPMIBmcSim
),
1678 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].states
, IPMIBmcSim
),
1679 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_states
, IPMIBmcSim
),
1680 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].deassert_states
,
1682 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_enable
, IPMIBmcSim
),
1683 VMSTATE_END_OF_LIST()
1687 static void ipmi_sim_init(Object
*obj
)
1689 IPMIBmc
*b
= IPMI_BMC(obj
);
1692 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
1694 qemu_mutex_init(&ibs
->lock
);
1695 QTAILQ_INIT(&ibs
->rcvbufs
);
1697 ibs
->bmc_global_enables
= (1 << IPMI_BMC_EVENT_LOG_BIT
);
1698 ibs
->device_id
= 0x20;
1699 ibs
->ipmi_version
= 0x02; /* IPMI 2.0 */
1700 for (i
= 0; i
< 4; i
++) {
1701 ibs
->sel
.last_addition
[i
] = 0xff;
1702 ibs
->sel
.last_clear
[i
] = 0xff;
1703 ibs
->sdr
.last_addition
[i
] = 0xff;
1704 ibs
->sdr
.last_clear
[i
] = 0xff;
1709 if ((i
+ 5) > sizeof(init_sdrs
)) {
1710 error_report("Problem with recid 0x%4.4x: \n", i
);
1713 len
= init_sdrs
[i
+ 4];
1714 recid
= init_sdrs
[i
] | (init_sdrs
[i
+ 1] << 8);
1715 if (recid
== 0xffff) {
1718 if ((i
+ len
+ 5) > sizeof(init_sdrs
)) {
1719 error_report("Problem with recid 0x%4.4x\n", i
);
1722 sdr_add_entry(ibs
, init_sdrs
+ i
, len
, NULL
);
1726 ipmi_init_sensors_from_sdrs(ibs
);
1729 ibs
->timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, ipmi_timeout
, ibs
);
1731 vmstate_register(NULL
, 0, &vmstate_ipmi_sim
, ibs
);
1734 static void ipmi_sim_class_init(ObjectClass
*oc
, void *data
)
1736 IPMIBmcClass
*bk
= IPMI_BMC_CLASS(oc
);
1738 bk
->handle_command
= ipmi_sim_handle_command
;
1741 static const TypeInfo ipmi_sim_type
= {
1742 .name
= TYPE_IPMI_BMC_SIMULATOR
,
1743 .parent
= TYPE_IPMI_BMC
,
1744 .instance_size
= sizeof(IPMIBmcSim
),
1745 .instance_init
= ipmi_sim_init
,
1746 .class_init
= ipmi_sim_class_init
,
1749 static void ipmi_sim_register_types(void)
1751 type_register_static(&ipmi_sim_type
);
1754 type_init(ipmi_sim_register_types
)