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"
30 #include "hw/loader.h"
32 #define IPMI_NETFN_CHASSIS 0x00
34 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
35 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
36 #define IPMI_CMD_CHASSIS_CONTROL 0x02
37 #define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09
39 #define IPMI_NETFN_SENSOR_EVENT 0x04
41 #define IPMI_CMD_PLATFORM_EVENT_MSG 0x02
42 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
43 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
44 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
45 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
46 #define IPMI_CMD_GET_SENSOR_READING 0x2d
47 #define IPMI_CMD_SET_SENSOR_TYPE 0x2e
48 #define IPMI_CMD_GET_SENSOR_TYPE 0x2f
50 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
52 #define IPMI_CMD_GET_DEVICE_ID 0x01
53 #define IPMI_CMD_COLD_RESET 0x02
54 #define IPMI_CMD_WARM_RESET 0x03
55 #define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
56 #define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
57 #define IPMI_CMD_GET_DEVICE_GUID 0x08
58 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
59 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
60 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
61 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
62 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
63 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
64 #define IPMI_CMD_GET_MSG_FLAGS 0x31
65 #define IPMI_CMD_GET_MSG 0x33
66 #define IPMI_CMD_SEND_MSG 0x34
67 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
69 #define IPMI_NETFN_STORAGE 0x0a
71 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
72 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
73 #define IPMI_CMD_RESERVE_SDR_REP 0x22
74 #define IPMI_CMD_GET_SDR 0x23
75 #define IPMI_CMD_ADD_SDR 0x24
76 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
77 #define IPMI_CMD_DELETE_SDR 0x26
78 #define IPMI_CMD_CLEAR_SDR_REP 0x27
79 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
80 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
81 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
82 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
83 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
84 #define IPMI_CMD_GET_FRU_AREA_INFO 0x10
85 #define IPMI_CMD_READ_FRU_DATA 0x11
86 #define IPMI_CMD_WRITE_FRU_DATA 0x12
87 #define IPMI_CMD_GET_SEL_INFO 0x40
88 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
89 #define IPMI_CMD_RESERVE_SEL 0x42
90 #define IPMI_CMD_GET_SEL_ENTRY 0x43
91 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
92 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
93 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
94 #define IPMI_CMD_CLEAR_SEL 0x47
95 #define IPMI_CMD_GET_SEL_TIME 0x48
96 #define IPMI_CMD_SET_SEL_TIME 0x49
99 /* Same as a timespec struct. */
105 #define MAX_SEL_SIZE 128
107 typedef struct IPMISel
{
108 uint8_t sel
[MAX_SEL_SIZE
][16];
109 unsigned int next_free
;
111 uint16_t reservation
;
112 uint8_t last_addition
[4];
113 uint8_t last_clear
[4];
117 #define MAX_SDR_SIZE 16384
119 typedef struct IPMISdr
{
120 uint8_t sdr
[MAX_SDR_SIZE
];
121 unsigned int next_free
;
122 uint16_t next_rec_id
;
123 uint16_t reservation
;
124 uint8_t last_addition
[4];
125 uint8_t last_clear
[4];
129 typedef struct IPMIFru
{
131 unsigned int nentries
;
136 typedef struct IPMISensor
{
139 uint16_t states_suppt
;
140 uint16_t assert_suppt
;
141 uint16_t deassert_suppt
;
143 uint16_t assert_states
;
144 uint16_t deassert_states
;
145 uint16_t assert_enable
;
146 uint16_t deassert_enable
;
148 uint8_t evt_reading_type_code
;
150 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
151 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
153 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
154 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
156 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
157 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
159 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
160 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
162 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
164 #define MAX_SENSORS 20
165 #define IPMI_WATCHDOG_SENSOR 0
167 typedef struct IPMIBmcSim IPMIBmcSim
;
168 typedef struct RspBuffer RspBuffer
;
170 #define MAX_NETFNS 64
172 typedef struct IPMICmdHandler
{
173 void (*cmd_handler
)(IPMIBmcSim
*s
,
174 uint8_t *cmd
, unsigned int cmd_len
,
176 unsigned int cmd_len_min
;
179 typedef struct IPMINetfn
{
180 unsigned int cmd_nums
;
181 const IPMICmdHandler
*cmd_handlers
;
184 typedef struct IPMIRcvBufEntry
{
185 QTAILQ_ENTRY(IPMIRcvBufEntry
) entry
;
187 uint8_t buf
[MAX_IPMI_MSG_SIZE
];
190 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
191 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
192 TYPE_IPMI_BMC_SIMULATOR)
198 uint8_t bmc_global_enables
;
201 bool watchdog_initialized
;
202 uint8_t watchdog_use
;
203 uint8_t watchdog_action
;
204 uint8_t watchdog_pretimeout
; /* In seconds */
205 bool watchdog_expired
;
206 uint16_t watchdog_timeout
; /* in 100's of milliseconds */
208 bool watchdog_running
;
209 bool watchdog_preaction_ran
;
210 int64_t watchdog_expiry
;
213 uint8_t ipmi_version
;
220 uint8_t restart_cause
;
222 uint8_t acpi_power_state
[2];
228 IPMISensor sensors
[MAX_SENSORS
];
231 /* Odd netfns are for responses, so we only need the even ones. */
232 const IPMINetfn
*netfns
[MAX_NETFNS
/ 2];
234 /* We allow one event in the buffer */
237 QTAILQ_HEAD(, IPMIRcvBufEntry
) rcvbufs
;
240 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
241 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
242 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
243 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
244 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
245 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
246 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
247 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
248 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
250 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
251 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
252 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
253 #define IPMI_BMC_EVENT_LOG_BIT 3
254 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
255 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
256 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
257 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
258 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
259 (1 << IPMI_BMC_EVENT_LOG_BIT))
260 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
261 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
263 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
264 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
265 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
266 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
267 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
268 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
269 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
270 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
271 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
272 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
273 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
274 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
275 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
276 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
277 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
280 uint8_t buffer
[MAX_IPMI_MSG_SIZE
];
284 #define RSP_BUFFER_INITIALIZER { }
286 static inline void rsp_buffer_set_error(RspBuffer
*rsp
, uint8_t byte
)
288 rsp
->buffer
[2] = byte
;
291 /* Add a byte to the response. */
292 static inline void rsp_buffer_push(RspBuffer
*rsp
, uint8_t byte
)
294 if (rsp
->len
>= sizeof(rsp
->buffer
)) {
295 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
298 rsp
->buffer
[rsp
->len
++] = byte
;
301 static inline void rsp_buffer_pushmore(RspBuffer
*rsp
, uint8_t *bytes
,
304 if (rsp
->len
+ n
>= sizeof(rsp
->buffer
)) {
305 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
309 memcpy(&rsp
->buffer
[rsp
->len
], bytes
, n
);
313 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
);
315 static void ipmi_gettime(struct ipmi_time
*time
)
319 stime
= qemu_clock_get_ns(QEMU_CLOCK_HOST
);
320 time
->tv_sec
= stime
/ 1000000000LL;
321 time
->tv_nsec
= stime
% 1000000000LL;
324 static int64_t ipmi_getmonotime(void)
326 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
329 static void ipmi_timeout(void *opaque
)
331 IPMIBmcSim
*ibs
= opaque
;
333 ipmi_sim_handle_timeout(ibs
);
336 static void set_timestamp(IPMIBmcSim
*ibs
, uint8_t *ts
)
339 struct ipmi_time now
;
342 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
344 ts
[1] = (val
>> 8) & 0xff;
345 ts
[2] = (val
>> 16) & 0xff;
346 ts
[3] = (val
>> 24) & 0xff;
349 static void sdr_inc_reservation(IPMISdr
*sdr
)
352 if (sdr
->reservation
== 0) {
353 sdr
->reservation
= 1;
357 static int sdr_add_entry(IPMIBmcSim
*ibs
,
358 const struct ipmi_sdr_header
*sdrh_entry
,
359 unsigned int len
, uint16_t *recid
)
361 struct ipmi_sdr_header
*sdrh
=
362 (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[ibs
->sdr
.next_free
];
364 if ((len
< IPMI_SDR_HEADER_SIZE
) || (len
> 255)) {
368 if (ipmi_sdr_length(sdrh_entry
) != len
) {
372 if (ibs
->sdr
.next_free
+ len
> MAX_SDR_SIZE
) {
373 ibs
->sdr
.overflow
= 1;
377 memcpy(sdrh
, sdrh_entry
, len
);
378 sdrh
->rec_id
[0] = ibs
->sdr
.next_rec_id
& 0xff;
379 sdrh
->rec_id
[1] = (ibs
->sdr
.next_rec_id
>> 8) & 0xff;
380 sdrh
->sdr_version
= 0x51; /* Conform to IPMI 1.5 spec */
383 *recid
= ibs
->sdr
.next_rec_id
;
385 ibs
->sdr
.next_rec_id
++;
386 set_timestamp(ibs
, ibs
->sdr
.last_addition
);
387 ibs
->sdr
.next_free
+= len
;
388 sdr_inc_reservation(&ibs
->sdr
);
392 static int sdr_find_entry(IPMISdr
*sdr
, uint16_t recid
,
393 unsigned int *retpos
, uint16_t *nextrec
)
395 unsigned int pos
= *retpos
;
397 while (pos
< sdr
->next_free
) {
398 struct ipmi_sdr_header
*sdrh
=
399 (struct ipmi_sdr_header
*) &sdr
->sdr
[pos
];
400 uint16_t trec
= ipmi_sdr_recid(sdrh
);
401 unsigned int nextpos
= pos
+ ipmi_sdr_length(sdrh
);
405 if (nextpos
>= sdr
->next_free
) {
408 *nextrec
= (sdr
->sdr
[nextpos
] |
409 (sdr
->sdr
[nextpos
+ 1] << 8));
420 int ipmi_bmc_sdr_find(IPMIBmc
*b
, uint16_t recid
,
421 const struct ipmi_sdr_compact
**sdr
, uint16_t *nextrec
)
424 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
428 if (sdr_find_entry(&ibs
->sdr
, recid
, &pos
, nextrec
)) {
432 *sdr
= (const struct ipmi_sdr_compact
*) &ibs
->sdr
.sdr
[pos
];
436 static void sel_inc_reservation(IPMISel
*sel
)
439 if (sel
->reservation
== 0) {
440 sel
->reservation
= 1;
444 /* Returns 1 if the SEL is full and can't hold the event. */
445 static int sel_add_event(IPMIBmcSim
*ibs
, uint8_t *event
)
451 set_timestamp(ibs
, ts
);
452 if (event
[2] < 0xe0) { /* Don't set timestamps for type 0xe0-0xff. */
453 memcpy(event
+ 3, ts
, 4);
455 if (ibs
->sel
.next_free
== MAX_SEL_SIZE
) {
456 ibs
->sel
.overflow
= 1;
459 event
[0] = ibs
->sel
.next_free
& 0xff;
460 event
[1] = (ibs
->sel
.next_free
>> 8) & 0xff;
461 memcpy(ibs
->sel
.last_addition
, ts
, 4);
462 memcpy(ibs
->sel
.sel
[ibs
->sel
.next_free
], event
, 16);
463 ibs
->sel
.next_free
++;
464 sel_inc_reservation(&ibs
->sel
);
468 static int attn_set(IPMIBmcSim
*ibs
)
470 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
)
471 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
)
472 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs
);
475 static int attn_irq_enabled(IPMIBmcSim
*ibs
)
477 return (IPMI_BMC_MSG_INTS_ON(ibs
) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
))
478 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs
) &&
479 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
));
482 void ipmi_bmc_gen_event(IPMIBmc
*b
, uint8_t *evt
, bool log
)
484 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
485 IPMIInterface
*s
= ibs
->parent
.intf
;
486 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
488 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
492 if (log
&& IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
493 sel_add_event(ibs
, evt
);
496 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
500 memcpy(ibs
->evtbuf
, evt
, 16);
501 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
502 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
506 static void gen_event(IPMIBmcSim
*ibs
, unsigned int sens_num
, uint8_t deassert
,
507 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
509 IPMIInterface
*s
= ibs
->parent
.intf
;
510 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
512 IPMISensor
*sens
= ibs
->sensors
+ sens_num
;
514 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
517 if (!IPMI_SENSOR_GET_EVENTS_ON(sens
)) {
521 evt
[2] = 0x2; /* System event record */
522 evt
[7] = ibs
->parent
.slave_addr
;
524 evt
[9] = 0x04; /* Format version */
525 evt
[10] = sens
->sensor_type
;
527 evt
[12] = sens
->evt_reading_type_code
| (!!deassert
<< 7);
532 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
533 sel_add_event(ibs
, evt
);
536 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
540 memcpy(ibs
->evtbuf
, evt
, 16);
541 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
542 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
545 static void sensor_set_discrete_bit(IPMIBmcSim
*ibs
, unsigned int sensor
,
546 unsigned int bit
, unsigned int val
,
547 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
552 if (sensor
>= MAX_SENSORS
) {
560 sens
= ibs
->sensors
+ sensor
;
562 sens
->states
|= mask
& sens
->states_suppt
;
563 if (sens
->assert_states
& mask
) {
564 return; /* Already asserted */
566 sens
->assert_states
|= mask
& sens
->assert_suppt
;
567 if (sens
->assert_enable
& mask
& sens
->assert_states
) {
568 /* Send an event on assert */
569 gen_event(ibs
, sensor
, 0, evd1
, evd2
, evd3
);
572 sens
->states
&= ~(mask
& sens
->states_suppt
);
573 if (sens
->deassert_states
& mask
) {
574 return; /* Already deasserted */
576 sens
->deassert_states
|= mask
& sens
->deassert_suppt
;
577 if (sens
->deassert_enable
& mask
& sens
->deassert_states
) {
578 /* Send an event on deassert */
579 gen_event(ibs
, sensor
, 1, evd1
, evd2
, evd3
);
584 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim
*s
)
589 for (i
= 0; i
< MAX_SENSORS
; i
++) {
590 memset(s
->sensors
+ i
, 0, sizeof(*sens
));
594 for (i
= 0; !sdr_find_entry(&s
->sdr
, i
, &pos
, NULL
); i
++) {
595 struct ipmi_sdr_compact
*sdr
=
596 (struct ipmi_sdr_compact
*) &s
->sdr
.sdr
[pos
];
597 unsigned int len
= sdr
->header
.rec_length
;
602 if (sdr
->header
.rec_type
!= IPMI_SDR_COMPACT_TYPE
) {
603 continue; /* Not a sensor SDR we set from */
606 if (sdr
->sensor_owner_number
>= MAX_SENSORS
) {
609 sens
= s
->sensors
+ sdr
->sensor_owner_number
;
611 IPMI_SENSOR_SET_PRESENT(sens
, 1);
612 IPMI_SENSOR_SET_SCAN_ON(sens
, (sdr
->sensor_init
>> 6) & 1);
613 IPMI_SENSOR_SET_EVENTS_ON(sens
, (sdr
->sensor_init
>> 5) & 1);
614 sens
->assert_suppt
= sdr
->assert_mask
[0] | (sdr
->assert_mask
[1] << 8);
615 sens
->deassert_suppt
=
616 sdr
->deassert_mask
[0] | (sdr
->deassert_mask
[1] << 8);
618 sdr
->discrete_mask
[0] | (sdr
->discrete_mask
[1] << 8);
619 sens
->sensor_type
= sdr
->sensor_type
;
620 sens
->evt_reading_type_code
= sdr
->reading_type
& 0x7f;
622 /* Enable all the events that are supported. */
623 sens
->assert_enable
= sens
->assert_suppt
;
624 sens
->deassert_enable
= sens
->deassert_suppt
;
628 static int ipmi_register_netfn(IPMIBmcSim
*s
, unsigned int netfn
,
629 const IPMINetfn
*netfnd
)
631 if ((netfn
& 1) || (netfn
>= MAX_NETFNS
) || (s
->netfns
[netfn
/ 2])) {
634 s
->netfns
[netfn
/ 2] = netfnd
;
638 static const IPMICmdHandler
*ipmi_get_handler(IPMIBmcSim
*ibs
,
642 const IPMICmdHandler
*hdl
;
644 if (netfn
& 1 || netfn
>= MAX_NETFNS
|| !ibs
->netfns
[netfn
/ 2]) {
648 if (cmd
>= ibs
->netfns
[netfn
/ 2]->cmd_nums
) {
652 hdl
= &ibs
->netfns
[netfn
/ 2]->cmd_handlers
[cmd
];
653 if (!hdl
->cmd_handler
) {
660 static void next_timeout(IPMIBmcSim
*ibs
)
663 if (ibs
->watchdog_running
) {
664 next
= ibs
->watchdog_expiry
;
667 next
= ipmi_getmonotime() + 60 * 1000000000LL;
669 timer_mod_ns(ibs
->timer
, next
);
672 static void ipmi_sim_handle_command(IPMIBmc
*b
,
673 uint8_t *cmd
, unsigned int cmd_len
,
674 unsigned int max_cmd_len
,
677 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
678 IPMIInterface
*s
= ibs
->parent
.intf
;
679 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
680 const IPMICmdHandler
*hdl
;
681 RspBuffer rsp
= RSP_BUFFER_INITIALIZER
;
683 /* Set up the response, set the low bit of NETFN. */
684 /* Note that max_rsp_len must be at least 3 */
685 if (sizeof(rsp
.buffer
) < 3) {
686 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
690 rsp_buffer_push(&rsp
, cmd
[0] | 0x04);
691 rsp_buffer_push(&rsp
, cmd
[1]);
692 rsp_buffer_push(&rsp
, 0); /* Assume success */
694 /* If it's too short or it was truncated, return an error. */
696 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
699 if (cmd_len
> max_cmd_len
) {
700 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
704 if ((cmd
[0] & 0x03) != 0) {
705 /* Only have stuff on LUN 0 */
706 rsp_buffer_set_error(&rsp
, IPMI_CC_COMMAND_INVALID_FOR_LUN
);
710 hdl
= ipmi_get_handler(ibs
, cmd
[0] >> 2, cmd
[1]);
712 rsp_buffer_set_error(&rsp
, IPMI_CC_INVALID_CMD
);
716 if (cmd_len
< hdl
->cmd_len_min
) {
717 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
721 hdl
->cmd_handler(ibs
, cmd
, cmd_len
, &rsp
);
724 k
->handle_rsp(s
, msg_id
, rsp
.buffer
, rsp
.len
);
729 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
)
731 IPMIInterface
*s
= ibs
->parent
.intf
;
732 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
734 if (!ibs
->watchdog_running
) {
738 if (!ibs
->watchdog_preaction_ran
) {
739 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
)) {
740 case IPMI_BMC_WATCHDOG_PRE_NMI
:
741 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
742 k
->do_hw_op(s
, IPMI_SEND_NMI
, 0);
743 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
744 0xc8, (2 << 4) | 0xf, 0xff);
747 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
748 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
749 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
750 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
751 0xc8, (3 << 4) | 0xf, 0xff);
758 ibs
->watchdog_preaction_ran
= 1;
759 /* Issued the pretimeout, do the rest of the timeout now. */
760 ibs
->watchdog_expiry
= ipmi_getmonotime();
761 ibs
->watchdog_expiry
+= ibs
->watchdog_pretimeout
* 1000000000LL;
766 ibs
->watchdog_running
= 0; /* Stop the watchdog on a timeout */
767 ibs
->watchdog_expired
|= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs
));
768 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
)) {
769 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
770 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 0, 1,
771 0xc0, ibs
->watchdog_use
& 0xf, 0xff);
774 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
775 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 1, 1,
776 0xc1, ibs
->watchdog_use
& 0xf, 0xff);
777 k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0);
780 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
781 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
782 0xc2, ibs
->watchdog_use
& 0xf, 0xff);
783 k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0);
786 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
787 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
788 0xc3, ibs
->watchdog_use
& 0xf, 0xff);
789 k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0);
797 static void chassis_capabilities(IPMIBmcSim
*ibs
,
798 uint8_t *cmd
, unsigned int cmd_len
,
801 rsp_buffer_push(rsp
, 0);
802 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
803 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
804 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
805 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
808 static void chassis_status(IPMIBmcSim
*ibs
,
809 uint8_t *cmd
, unsigned int cmd_len
,
812 rsp_buffer_push(rsp
, 0x61); /* Unknown power restore, power is on */
813 rsp_buffer_push(rsp
, 0);
814 rsp_buffer_push(rsp
, 0);
815 rsp_buffer_push(rsp
, 0);
818 static void chassis_control(IPMIBmcSim
*ibs
,
819 uint8_t *cmd
, unsigned int cmd_len
,
822 IPMIInterface
*s
= ibs
->parent
.intf
;
823 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
825 switch (cmd
[2] & 0xf) {
826 case 0: /* power down */
827 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0));
829 case 1: /* power up */
830 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERON_CHASSIS
, 0));
832 case 2: /* power cycle */
833 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0));
835 case 3: /* hard reset */
836 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0));
838 case 4: /* pulse diagnostic interrupt */
839 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_PULSE_DIAG_IRQ
, 0));
841 case 5: /* soft shutdown via ACPI by overtemp emulation */
842 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
,
843 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP
, 0));
846 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
851 static void chassis_get_sys_restart_cause(IPMIBmcSim
*ibs
,
852 uint8_t *cmd
, unsigned int cmd_len
,
856 rsp_buffer_push(rsp
, ibs
->restart_cause
& 0xf); /* Restart Cause */
857 rsp_buffer_push(rsp
, 0); /* Channel 0 */
860 static void get_device_id(IPMIBmcSim
*ibs
,
861 uint8_t *cmd
, unsigned int cmd_len
,
864 rsp_buffer_push(rsp
, ibs
->device_id
);
865 rsp_buffer_push(rsp
, ibs
->device_rev
& 0xf);
866 rsp_buffer_push(rsp
, ibs
->fwrev1
& 0x7f);
867 rsp_buffer_push(rsp
, ibs
->fwrev2
);
868 rsp_buffer_push(rsp
, ibs
->ipmi_version
);
869 rsp_buffer_push(rsp
, 0x07); /* sensor, SDR, and SEL. */
870 rsp_buffer_push(rsp
, ibs
->mfg_id
& 0xff);
871 rsp_buffer_push(rsp
, (ibs
->mfg_id
>> 8) & 0xff);
872 rsp_buffer_push(rsp
, (ibs
->mfg_id
>> 16) & 0xff);
873 rsp_buffer_push(rsp
, ibs
->product_id
& 0xff);
874 rsp_buffer_push(rsp
, (ibs
->product_id
>> 8) & 0xff);
877 static void set_global_enables(IPMIBmcSim
*ibs
, uint8_t val
)
879 IPMIInterface
*s
= ibs
->parent
.intf
;
880 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
883 ibs
->bmc_global_enables
= val
;
885 irqs_on
= val
& (IPMI_BMC_EVBUF_FULL_INT_BIT
|
886 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT
);
888 k
->set_irq_enable(s
, irqs_on
);
891 static void cold_reset(IPMIBmcSim
*ibs
,
892 uint8_t *cmd
, unsigned int cmd_len
,
895 IPMIInterface
*s
= ibs
->parent
.intf
;
896 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
898 /* Disable all interrupts */
899 set_global_enables(ibs
, 1 << IPMI_BMC_EVENT_LOG_BIT
);
906 static void warm_reset(IPMIBmcSim
*ibs
,
907 uint8_t *cmd
, unsigned int cmd_len
,
910 IPMIInterface
*s
= ibs
->parent
.intf
;
911 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
917 static void set_acpi_power_state(IPMIBmcSim
*ibs
,
918 uint8_t *cmd
, unsigned int cmd_len
,
921 ibs
->acpi_power_state
[0] = cmd
[2];
922 ibs
->acpi_power_state
[1] = cmd
[3];
925 static void get_acpi_power_state(IPMIBmcSim
*ibs
,
926 uint8_t *cmd
, unsigned int cmd_len
,
929 rsp_buffer_push(rsp
, ibs
->acpi_power_state
[0]);
930 rsp_buffer_push(rsp
, ibs
->acpi_power_state
[1]);
933 static void get_device_guid(IPMIBmcSim
*ibs
,
934 uint8_t *cmd
, unsigned int cmd_len
,
939 for (i
= 0; i
< 16; i
++) {
940 rsp_buffer_push(rsp
, ibs
->uuid
[i
]);
944 static void set_bmc_global_enables(IPMIBmcSim
*ibs
,
945 uint8_t *cmd
, unsigned int cmd_len
,
948 set_global_enables(ibs
, cmd
[2]);
951 static void get_bmc_global_enables(IPMIBmcSim
*ibs
,
952 uint8_t *cmd
, unsigned int cmd_len
,
955 rsp_buffer_push(rsp
, ibs
->bmc_global_enables
);
958 static void clr_msg_flags(IPMIBmcSim
*ibs
,
959 uint8_t *cmd
, unsigned int cmd_len
,
962 IPMIInterface
*s
= ibs
->parent
.intf
;
963 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
965 ibs
->msg_flags
&= ~cmd
[2];
966 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
969 static void get_msg_flags(IPMIBmcSim
*ibs
,
970 uint8_t *cmd
, unsigned int cmd_len
,
973 rsp_buffer_push(rsp
, ibs
->msg_flags
);
976 static void read_evt_msg_buf(IPMIBmcSim
*ibs
,
977 uint8_t *cmd
, unsigned int cmd_len
,
980 IPMIInterface
*s
= ibs
->parent
.intf
;
981 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
984 if (!(ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
)) {
985 rsp_buffer_set_error(rsp
, 0x80);
988 for (i
= 0; i
< 16; i
++) {
989 rsp_buffer_push(rsp
, ibs
->evtbuf
[i
]);
991 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
992 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
995 static void get_msg(IPMIBmcSim
*ibs
,
996 uint8_t *cmd
, unsigned int cmd_len
,
999 IPMIRcvBufEntry
*msg
;
1001 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
1002 rsp_buffer_set_error(rsp
, 0x80); /* Queue empty */
1005 rsp_buffer_push(rsp
, 0); /* Channel 0 */
1006 msg
= QTAILQ_FIRST(&ibs
->rcvbufs
);
1007 rsp_buffer_pushmore(rsp
, msg
->buf
, msg
->len
);
1008 QTAILQ_REMOVE(&ibs
->rcvbufs
, msg
, entry
);
1011 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
1012 IPMIInterface
*s
= ibs
->parent
.intf
;
1013 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1015 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
1016 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
1023 static unsigned char
1024 ipmb_checksum(unsigned char *data
, int size
, unsigned char csum
)
1026 for (; size
> 0; size
--, data
++) {
1033 static void send_msg(IPMIBmcSim
*ibs
,
1034 uint8_t *cmd
, unsigned int cmd_len
,
1037 IPMIInterface
*s
= ibs
->parent
.intf
;
1038 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1039 IPMIRcvBufEntry
*msg
;
1041 uint8_t netfn
, rqLun
, rsLun
, rqSeq
;
1044 /* We only handle channel 0 with no options */
1045 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1050 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
1054 if (cmd
[3] != 0x40) {
1055 /* We only emulate a MC at address 0x40. */
1056 rsp_buffer_set_error(rsp
, 0x83); /* NAK on write */
1060 cmd
+= 3; /* Skip the header. */
1064 * At this point we "send" the message successfully. Any error will
1065 * be returned in the response.
1067 if (ipmb_checksum(cmd
, cmd_len
, 0) != 0 ||
1068 cmd
[3] != 0x20) { /* Improper response address */
1069 return; /* No response */
1072 netfn
= cmd
[1] >> 2;
1073 rqLun
= cmd
[4] & 0x3;
1074 rsLun
= cmd
[1] & 0x3;
1075 rqSeq
= cmd
[4] >> 2;
1078 /* We only support LUN 2 coming back to us. */
1082 msg
= g_malloc(sizeof(*msg
));
1083 msg
->buf
[0] = ((netfn
| 1) << 2) | rqLun
; /* NetFN, and make a response */
1084 msg
->buf
[1] = ipmb_checksum(msg
->buf
, 1, 0);
1085 msg
->buf
[2] = cmd
[0]; /* rsSA */
1086 msg
->buf
[3] = (rqSeq
<< 2) | rsLun
;
1087 msg
->buf
[4] = cmd
[5]; /* Cmd */
1088 msg
->buf
[5] = 0; /* Completion Code */
1091 if ((cmd
[1] >> 2) != IPMI_NETFN_APP
|| cmd
[5] != IPMI_CMD_GET_DEVICE_ID
) {
1092 /* Not a command we handle. */
1093 msg
->buf
[5] = IPMI_CC_INVALID_CMD
;
1097 buf
= msg
->buf
+ msg
->len
; /* After the CC */
1112 msg
->buf
[msg
->len
] = ipmb_checksum(msg
->buf
, msg
->len
, 0);
1114 QTAILQ_INSERT_TAIL(&ibs
->rcvbufs
, msg
, entry
);
1115 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
1116 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
1119 static void do_watchdog_reset(IPMIBmcSim
*ibs
)
1121 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
) ==
1122 IPMI_BMC_WATCHDOG_ACTION_NONE
) {
1123 ibs
->watchdog_running
= 0;
1126 ibs
->watchdog_preaction_ran
= 0;
1129 /* Timeout is in tenths of a second, offset is in seconds */
1130 ibs
->watchdog_expiry
= ipmi_getmonotime();
1131 ibs
->watchdog_expiry
+= ibs
->watchdog_timeout
* 100000000LL;
1132 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
) != IPMI_BMC_WATCHDOG_PRE_NONE
) {
1133 ibs
->watchdog_expiry
-= ibs
->watchdog_pretimeout
* 1000000000LL;
1135 ibs
->watchdog_running
= 1;
1138 static void reset_watchdog_timer(IPMIBmcSim
*ibs
,
1139 uint8_t *cmd
, unsigned int cmd_len
,
1142 if (!ibs
->watchdog_initialized
) {
1143 rsp_buffer_set_error(rsp
, 0x80);
1146 do_watchdog_reset(ibs
);
1149 static void set_watchdog_timer(IPMIBmcSim
*ibs
,
1150 uint8_t *cmd
, unsigned int cmd_len
,
1153 IPMIInterface
*s
= ibs
->parent
.intf
;
1154 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1157 val
= cmd
[2] & 0x7; /* Validate use */
1158 if (val
== 0 || val
> 5) {
1159 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1162 val
= cmd
[3] & 0x7; /* Validate action */
1164 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
1167 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
1168 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 1));
1171 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
1172 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 1));
1175 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
1176 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 1));
1180 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1182 if (rsp
->buffer
[2]) {
1183 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1187 val
= (cmd
[3] >> 4) & 0x7; /* Validate preaction */
1189 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
1190 case IPMI_BMC_WATCHDOG_PRE_NONE
:
1193 case IPMI_BMC_WATCHDOG_PRE_NMI
:
1194 if (!k
->do_hw_op(s
, IPMI_SEND_NMI
, 1)) {
1195 /* NMI not supported. */
1196 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1202 /* We don't support PRE_SMI */
1203 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1207 ibs
->watchdog_initialized
= 1;
1208 ibs
->watchdog_use
= cmd
[2] & IPMI_BMC_WATCHDOG_USE_MASK
;
1209 ibs
->watchdog_action
= cmd
[3] & IPMI_BMC_WATCHDOG_ACTION_MASK
;
1210 ibs
->watchdog_pretimeout
= cmd
[4];
1211 ibs
->watchdog_expired
&= ~cmd
[5];
1212 ibs
->watchdog_timeout
= cmd
[6] | (((uint16_t) cmd
[7]) << 8);
1213 if (ibs
->watchdog_running
& IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs
)) {
1214 do_watchdog_reset(ibs
);
1216 ibs
->watchdog_running
= 0;
1220 static void get_watchdog_timer(IPMIBmcSim
*ibs
,
1221 uint8_t *cmd
, unsigned int cmd_len
,
1224 rsp_buffer_push(rsp
, ibs
->watchdog_use
);
1225 rsp_buffer_push(rsp
, ibs
->watchdog_action
);
1226 rsp_buffer_push(rsp
, ibs
->watchdog_pretimeout
);
1227 rsp_buffer_push(rsp
, ibs
->watchdog_expired
);
1228 if (ibs
->watchdog_running
) {
1230 timeout
= ((ibs
->watchdog_expiry
- ipmi_getmonotime() + 50000000)
1232 rsp_buffer_push(rsp
, timeout
& 0xff);
1233 rsp_buffer_push(rsp
, (timeout
>> 8) & 0xff);
1235 rsp_buffer_push(rsp
, 0);
1236 rsp_buffer_push(rsp
, 0);
1240 static void get_sdr_rep_info(IPMIBmcSim
*ibs
,
1241 uint8_t *cmd
, unsigned int cmd_len
,
1246 rsp_buffer_push(rsp
, 0x51); /* Conform to IPMI 1.5 spec */
1247 rsp_buffer_push(rsp
, ibs
->sdr
.next_rec_id
& 0xff);
1248 rsp_buffer_push(rsp
, (ibs
->sdr
.next_rec_id
>> 8) & 0xff);
1249 rsp_buffer_push(rsp
, (MAX_SDR_SIZE
- ibs
->sdr
.next_free
) & 0xff);
1250 rsp_buffer_push(rsp
, ((MAX_SDR_SIZE
- ibs
->sdr
.next_free
) >> 8) & 0xff);
1251 for (i
= 0; i
< 4; i
++) {
1252 rsp_buffer_push(rsp
, ibs
->sdr
.last_addition
[i
]);
1254 for (i
= 0; i
< 4; i
++) {
1255 rsp_buffer_push(rsp
, ibs
->sdr
.last_clear
[i
]);
1257 /* Only modal support, reserve supported */
1258 rsp_buffer_push(rsp
, (ibs
->sdr
.overflow
<< 7) | 0x22);
1261 static void reserve_sdr_rep(IPMIBmcSim
*ibs
,
1262 uint8_t *cmd
, unsigned int cmd_len
,
1265 rsp_buffer_push(rsp
, ibs
->sdr
.reservation
& 0xff);
1266 rsp_buffer_push(rsp
, (ibs
->sdr
.reservation
>> 8) & 0xff);
1269 static void get_sdr(IPMIBmcSim
*ibs
,
1270 uint8_t *cmd
, unsigned int cmd_len
,
1275 struct ipmi_sdr_header
*sdrh
;
1278 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sdr
.reservation
) {
1279 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1285 if (sdr_find_entry(&ibs
->sdr
, cmd
[4] | (cmd
[5] << 8),
1287 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1291 sdrh
= (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[pos
];
1293 if (cmd
[6] > ipmi_sdr_length(sdrh
)) {
1294 rsp_buffer_set_error(rsp
, IPMI_CC_PARM_OUT_OF_RANGE
);
1298 rsp_buffer_push(rsp
, nextrec
& 0xff);
1299 rsp_buffer_push(rsp
, (nextrec
>> 8) & 0xff);
1301 if (cmd
[7] == 0xff) {
1302 cmd
[7] = ipmi_sdr_length(sdrh
) - cmd
[6];
1305 if ((cmd
[7] + rsp
->len
) > sizeof(rsp
->buffer
)) {
1306 rsp_buffer_set_error(rsp
, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES
);
1310 rsp_buffer_pushmore(rsp
, ibs
->sdr
.sdr
+ pos
+ cmd
[6], cmd
[7]);
1313 static void add_sdr(IPMIBmcSim
*ibs
,
1314 uint8_t *cmd
, unsigned int cmd_len
,
1318 struct ipmi_sdr_header
*sdrh
= (struct ipmi_sdr_header
*) cmd
+ 2;
1320 if (sdr_add_entry(ibs
, sdrh
, cmd_len
- 2, &recid
)) {
1321 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1324 rsp_buffer_push(rsp
, recid
& 0xff);
1325 rsp_buffer_push(rsp
, (recid
>> 8) & 0xff);
1328 static void clear_sdr_rep(IPMIBmcSim
*ibs
,
1329 uint8_t *cmd
, unsigned int cmd_len
,
1332 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sdr
.reservation
) {
1333 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1337 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1338 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1341 if (cmd
[7] == 0xaa) {
1342 ibs
->sdr
.next_free
= 0;
1343 ibs
->sdr
.overflow
= 0;
1344 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1345 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1346 sdr_inc_reservation(&ibs
->sdr
);
1347 } else if (cmd
[7] == 0) {
1348 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1350 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1355 static void get_sel_info(IPMIBmcSim
*ibs
,
1356 uint8_t *cmd
, unsigned int cmd_len
,
1359 unsigned int i
, val
;
1361 rsp_buffer_push(rsp
, 0x51); /* Conform to IPMI 1.5 */
1362 rsp_buffer_push(rsp
, ibs
->sel
.next_free
& 0xff);
1363 rsp_buffer_push(rsp
, (ibs
->sel
.next_free
>> 8) & 0xff);
1364 val
= (MAX_SEL_SIZE
- ibs
->sel
.next_free
) * 16;
1365 rsp_buffer_push(rsp
, val
& 0xff);
1366 rsp_buffer_push(rsp
, (val
>> 8) & 0xff);
1367 for (i
= 0; i
< 4; i
++) {
1368 rsp_buffer_push(rsp
, ibs
->sel
.last_addition
[i
]);
1370 for (i
= 0; i
< 4; i
++) {
1371 rsp_buffer_push(rsp
, ibs
->sel
.last_clear
[i
]);
1373 /* Only support Reserve SEL */
1374 rsp_buffer_push(rsp
, (ibs
->sel
.overflow
<< 7) | 0x02);
1377 static void get_fru_area_info(IPMIBmcSim
*ibs
,
1378 uint8_t *cmd
, unsigned int cmd_len
,
1382 uint16_t fru_entry_size
;
1386 if (fruid
>= ibs
->fru
.nentries
) {
1387 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1391 fru_entry_size
= ibs
->fru
.areasize
;
1393 rsp_buffer_push(rsp
, fru_entry_size
& 0xff);
1394 rsp_buffer_push(rsp
, fru_entry_size
>> 8 & 0xff);
1395 rsp_buffer_push(rsp
, 0x0);
1398 static void read_fru_data(IPMIBmcSim
*ibs
,
1399 uint8_t *cmd
, unsigned int cmd_len
,
1409 offset
= (cmd
[3] | cmd
[4] << 8);
1411 if (fruid
>= ibs
->fru
.nentries
) {
1412 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1416 if (offset
>= ibs
->fru
.areasize
- 1) {
1417 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1421 fru_entry
= &ibs
->fru
.data
[fruid
* ibs
->fru
.areasize
];
1423 count
= MIN(cmd
[5], ibs
->fru
.areasize
- offset
);
1425 rsp_buffer_push(rsp
, count
& 0xff);
1426 for (i
= 0; i
< count
; i
++) {
1427 rsp_buffer_push(rsp
, fru_entry
[offset
+ i
]);
1431 static void write_fru_data(IPMIBmcSim
*ibs
,
1432 uint8_t *cmd
, unsigned int cmd_len
,
1441 offset
= (cmd
[3] | cmd
[4] << 8);
1443 if (fruid
>= ibs
->fru
.nentries
) {
1444 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1448 if (offset
>= ibs
->fru
.areasize
- 1) {
1449 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1453 fru_entry
= &ibs
->fru
.data
[fruid
* ibs
->fru
.areasize
];
1455 count
= MIN(cmd_len
- 5, ibs
->fru
.areasize
- offset
);
1457 memcpy(fru_entry
+ offset
, cmd
+ 5, count
);
1459 rsp_buffer_push(rsp
, count
& 0xff);
1462 static void reserve_sel(IPMIBmcSim
*ibs
,
1463 uint8_t *cmd
, unsigned int cmd_len
,
1466 rsp_buffer_push(rsp
, ibs
->sel
.reservation
& 0xff);
1467 rsp_buffer_push(rsp
, (ibs
->sel
.reservation
>> 8) & 0xff);
1470 static void get_sel_entry(IPMIBmcSim
*ibs
,
1471 uint8_t *cmd
, unsigned int cmd_len
,
1477 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sel
.reservation
) {
1478 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1482 if (ibs
->sel
.next_free
== 0) {
1483 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1487 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1490 if (cmd
[7] == 0xff) {
1492 } else if ((cmd
[7] + cmd
[6]) > 16) {
1493 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1499 val
= cmd
[4] | (cmd
[5] << 8);
1500 if (val
== 0xffff) {
1501 val
= ibs
->sel
.next_free
- 1;
1502 } else if (val
>= ibs
->sel
.next_free
) {
1503 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1506 if ((val
+ 1) == ibs
->sel
.next_free
) {
1507 rsp_buffer_push(rsp
, 0xff);
1508 rsp_buffer_push(rsp
, 0xff);
1510 rsp_buffer_push(rsp
, (val
+ 1) & 0xff);
1511 rsp_buffer_push(rsp
, ((val
+ 1) >> 8) & 0xff);
1513 for (; cmd
[6] < cmd
[7]; cmd
[6]++) {
1514 rsp_buffer_push(rsp
, ibs
->sel
.sel
[val
][cmd
[6]]);
1518 static void add_sel_entry(IPMIBmcSim
*ibs
,
1519 uint8_t *cmd
, unsigned int cmd_len
,
1522 if (sel_add_event(ibs
, cmd
+ 2)) {
1523 rsp_buffer_set_error(rsp
, IPMI_CC_OUT_OF_SPACE
);
1526 /* sel_add_event fills in the record number. */
1527 rsp_buffer_push(rsp
, cmd
[2]);
1528 rsp_buffer_push(rsp
, cmd
[3]);
1531 static void clear_sel(IPMIBmcSim
*ibs
,
1532 uint8_t *cmd
, unsigned int cmd_len
,
1535 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sel
.reservation
) {
1536 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1540 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1541 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1544 if (cmd
[7] == 0xaa) {
1545 ibs
->sel
.next_free
= 0;
1546 ibs
->sel
.overflow
= 0;
1547 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1548 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1549 sel_inc_reservation(&ibs
->sel
);
1550 } else if (cmd
[7] == 0) {
1551 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1553 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1558 static void get_sel_time(IPMIBmcSim
*ibs
,
1559 uint8_t *cmd
, unsigned int cmd_len
,
1563 struct ipmi_time now
;
1566 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
1567 rsp_buffer_push(rsp
, val
& 0xff);
1568 rsp_buffer_push(rsp
, (val
>> 8) & 0xff);
1569 rsp_buffer_push(rsp
, (val
>> 16) & 0xff);
1570 rsp_buffer_push(rsp
, (val
>> 24) & 0xff);
1573 static void set_sel_time(IPMIBmcSim
*ibs
,
1574 uint8_t *cmd
, unsigned int cmd_len
,
1578 struct ipmi_time now
;
1580 val
= cmd
[2] | (cmd
[3] << 8) | (cmd
[4] << 16) | (cmd
[5] << 24);
1582 ibs
->sel
.time_offset
= now
.tv_sec
- ((long) val
);
1585 static void platform_event_msg(IPMIBmcSim
*ibs
,
1586 uint8_t *cmd
, unsigned int cmd_len
,
1591 event
[2] = 2; /* System event record */
1592 event
[7] = cmd
[2]; /* Generator ID */
1594 event
[9] = cmd
[3]; /* EvMRev */
1595 event
[10] = cmd
[4]; /* Sensor type */
1596 event
[11] = cmd
[5]; /* Sensor number */
1597 event
[12] = cmd
[6]; /* Event dir / Event type */
1598 event
[13] = cmd
[7]; /* Event data 1 */
1599 event
[14] = cmd
[8]; /* Event data 2 */
1600 event
[15] = cmd
[9]; /* Event data 3 */
1602 if (sel_add_event(ibs
, event
)) {
1603 rsp_buffer_set_error(rsp
, IPMI_CC_OUT_OF_SPACE
);
1607 static void set_sensor_evt_enable(IPMIBmcSim
*ibs
,
1608 uint8_t *cmd
, unsigned int cmd_len
,
1613 if ((cmd
[2] >= MAX_SENSORS
) ||
1614 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1615 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1618 sens
= ibs
->sensors
+ cmd
[2];
1619 switch ((cmd
[3] >> 4) & 0x3) {
1620 case 0: /* Do not change */
1622 case 1: /* Enable bits */
1624 sens
->assert_enable
|= cmd
[4];
1627 sens
->assert_enable
|= cmd
[5] << 8;
1630 sens
->deassert_enable
|= cmd
[6];
1633 sens
->deassert_enable
|= cmd
[7] << 8;
1636 case 2: /* Disable bits */
1638 sens
->assert_enable
&= ~cmd
[4];
1641 sens
->assert_enable
&= ~(cmd
[5] << 8);
1644 sens
->deassert_enable
&= ~cmd
[6];
1647 sens
->deassert_enable
&= ~(cmd
[7] << 8);
1651 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1654 IPMI_SENSOR_SET_RET_STATUS(sens
, cmd
[3]);
1657 static void get_sensor_evt_enable(IPMIBmcSim
*ibs
,
1658 uint8_t *cmd
, unsigned int cmd_len
,
1663 if ((cmd
[2] >= MAX_SENSORS
) ||
1664 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1665 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1668 sens
= ibs
->sensors
+ cmd
[2];
1669 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1670 rsp_buffer_push(rsp
, sens
->assert_enable
& 0xff);
1671 rsp_buffer_push(rsp
, (sens
->assert_enable
>> 8) & 0xff);
1672 rsp_buffer_push(rsp
, sens
->deassert_enable
& 0xff);
1673 rsp_buffer_push(rsp
, (sens
->deassert_enable
>> 8) & 0xff);
1676 static void rearm_sensor_evts(IPMIBmcSim
*ibs
,
1677 uint8_t *cmd
, unsigned int cmd_len
,
1682 if ((cmd
[2] >= MAX_SENSORS
) ||
1683 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1684 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1687 sens
= ibs
->sensors
+ cmd
[2];
1689 if ((cmd
[3] & 0x80) == 0) {
1690 /* Just clear everything */
1696 static void get_sensor_evt_status(IPMIBmcSim
*ibs
,
1697 uint8_t *cmd
, unsigned int cmd_len
,
1702 if ((cmd
[2] >= MAX_SENSORS
) ||
1703 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1704 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1707 sens
= ibs
->sensors
+ cmd
[2];
1708 rsp_buffer_push(rsp
, sens
->reading
);
1709 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1710 rsp_buffer_push(rsp
, sens
->assert_states
& 0xff);
1711 rsp_buffer_push(rsp
, (sens
->assert_states
>> 8) & 0xff);
1712 rsp_buffer_push(rsp
, sens
->deassert_states
& 0xff);
1713 rsp_buffer_push(rsp
, (sens
->deassert_states
>> 8) & 0xff);
1716 static void get_sensor_reading(IPMIBmcSim
*ibs
,
1717 uint8_t *cmd
, unsigned int cmd_len
,
1722 if ((cmd
[2] >= MAX_SENSORS
) ||
1723 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1724 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1727 sens
= ibs
->sensors
+ cmd
[2];
1728 rsp_buffer_push(rsp
, sens
->reading
);
1729 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1730 rsp_buffer_push(rsp
, sens
->states
& 0xff);
1731 if (IPMI_SENSOR_IS_DISCRETE(sens
)) {
1732 rsp_buffer_push(rsp
, (sens
->states
>> 8) & 0xff);
1736 static void set_sensor_type(IPMIBmcSim
*ibs
,
1737 uint8_t *cmd
, unsigned int cmd_len
,
1743 if ((cmd
[2] >= MAX_SENSORS
) ||
1744 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1745 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1748 sens
= ibs
->sensors
+ cmd
[2];
1749 sens
->sensor_type
= cmd
[3];
1750 sens
->evt_reading_type_code
= cmd
[4] & 0x7f;
1753 static void get_sensor_type(IPMIBmcSim
*ibs
,
1754 uint8_t *cmd
, unsigned int cmd_len
,
1760 if ((cmd
[2] >= MAX_SENSORS
) ||
1761 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1762 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1765 sens
= ibs
->sensors
+ cmd
[2];
1766 rsp_buffer_push(rsp
, sens
->sensor_type
);
1767 rsp_buffer_push(rsp
, sens
->evt_reading_type_code
);
1771 static const IPMICmdHandler chassis_cmds
[] = {
1772 [IPMI_CMD_GET_CHASSIS_CAPABILITIES
] = { chassis_capabilities
},
1773 [IPMI_CMD_GET_CHASSIS_STATUS
] = { chassis_status
},
1774 [IPMI_CMD_CHASSIS_CONTROL
] = { chassis_control
, 3 },
1775 [IPMI_CMD_GET_SYS_RESTART_CAUSE
] = { chassis_get_sys_restart_cause
}
1777 static const IPMINetfn chassis_netfn
= {
1778 .cmd_nums
= ARRAY_SIZE(chassis_cmds
),
1779 .cmd_handlers
= chassis_cmds
1782 static const IPMICmdHandler sensor_event_cmds
[] = {
1783 [IPMI_CMD_PLATFORM_EVENT_MSG
] = { platform_event_msg
, 10 },
1784 [IPMI_CMD_SET_SENSOR_EVT_ENABLE
] = { set_sensor_evt_enable
, 4 },
1785 [IPMI_CMD_GET_SENSOR_EVT_ENABLE
] = { get_sensor_evt_enable
, 3 },
1786 [IPMI_CMD_REARM_SENSOR_EVTS
] = { rearm_sensor_evts
, 4 },
1787 [IPMI_CMD_GET_SENSOR_EVT_STATUS
] = { get_sensor_evt_status
, 3 },
1788 [IPMI_CMD_GET_SENSOR_READING
] = { get_sensor_reading
, 3 },
1789 [IPMI_CMD_SET_SENSOR_TYPE
] = { set_sensor_type
, 5 },
1790 [IPMI_CMD_GET_SENSOR_TYPE
] = { get_sensor_type
, 3 },
1792 static const IPMINetfn sensor_event_netfn
= {
1793 .cmd_nums
= ARRAY_SIZE(sensor_event_cmds
),
1794 .cmd_handlers
= sensor_event_cmds
1797 static const IPMICmdHandler app_cmds
[] = {
1798 [IPMI_CMD_GET_DEVICE_ID
] = { get_device_id
},
1799 [IPMI_CMD_COLD_RESET
] = { cold_reset
},
1800 [IPMI_CMD_WARM_RESET
] = { warm_reset
},
1801 [IPMI_CMD_SET_ACPI_POWER_STATE
] = { set_acpi_power_state
, 4 },
1802 [IPMI_CMD_GET_ACPI_POWER_STATE
] = { get_acpi_power_state
},
1803 [IPMI_CMD_GET_DEVICE_GUID
] = { get_device_guid
},
1804 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES
] = { set_bmc_global_enables
, 3 },
1805 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES
] = { get_bmc_global_enables
},
1806 [IPMI_CMD_CLR_MSG_FLAGS
] = { clr_msg_flags
, 3 },
1807 [IPMI_CMD_GET_MSG_FLAGS
] = { get_msg_flags
},
1808 [IPMI_CMD_GET_MSG
] = { get_msg
},
1809 [IPMI_CMD_SEND_MSG
] = { send_msg
, 3 },
1810 [IPMI_CMD_READ_EVT_MSG_BUF
] = { read_evt_msg_buf
},
1811 [IPMI_CMD_RESET_WATCHDOG_TIMER
] = { reset_watchdog_timer
},
1812 [IPMI_CMD_SET_WATCHDOG_TIMER
] = { set_watchdog_timer
, 8 },
1813 [IPMI_CMD_GET_WATCHDOG_TIMER
] = { get_watchdog_timer
},
1815 static const IPMINetfn app_netfn
= {
1816 .cmd_nums
= ARRAY_SIZE(app_cmds
),
1817 .cmd_handlers
= app_cmds
1820 static const IPMICmdHandler storage_cmds
[] = {
1821 [IPMI_CMD_GET_FRU_AREA_INFO
] = { get_fru_area_info
, 3 },
1822 [IPMI_CMD_READ_FRU_DATA
] = { read_fru_data
, 5 },
1823 [IPMI_CMD_WRITE_FRU_DATA
] = { write_fru_data
, 5 },
1824 [IPMI_CMD_GET_SDR_REP_INFO
] = { get_sdr_rep_info
},
1825 [IPMI_CMD_RESERVE_SDR_REP
] = { reserve_sdr_rep
},
1826 [IPMI_CMD_GET_SDR
] = { get_sdr
, 8 },
1827 [IPMI_CMD_ADD_SDR
] = { add_sdr
},
1828 [IPMI_CMD_CLEAR_SDR_REP
] = { clear_sdr_rep
, 8 },
1829 [IPMI_CMD_GET_SEL_INFO
] = { get_sel_info
},
1830 [IPMI_CMD_RESERVE_SEL
] = { reserve_sel
},
1831 [IPMI_CMD_GET_SEL_ENTRY
] = { get_sel_entry
, 8 },
1832 [IPMI_CMD_ADD_SEL_ENTRY
] = { add_sel_entry
, 18 },
1833 [IPMI_CMD_CLEAR_SEL
] = { clear_sel
, 8 },
1834 [IPMI_CMD_GET_SEL_TIME
] = { get_sel_time
},
1835 [IPMI_CMD_SET_SEL_TIME
] = { set_sel_time
, 6 },
1838 static const IPMINetfn storage_netfn
= {
1839 .cmd_nums
= ARRAY_SIZE(storage_cmds
),
1840 .cmd_handlers
= storage_cmds
1843 static void register_cmds(IPMIBmcSim
*s
)
1845 ipmi_register_netfn(s
, IPMI_NETFN_CHASSIS
, &chassis_netfn
);
1846 ipmi_register_netfn(s
, IPMI_NETFN_SENSOR_EVENT
, &sensor_event_netfn
);
1847 ipmi_register_netfn(s
, IPMI_NETFN_APP
, &app_netfn
);
1848 ipmi_register_netfn(s
, IPMI_NETFN_STORAGE
, &storage_netfn
);
1851 static uint8_t init_sdrs
[] = {
1852 /* Watchdog device */
1853 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1854 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1855 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1856 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1857 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1860 static void ipmi_sdr_init(IPMIBmcSim
*ibs
)
1867 sdrs_size
= sizeof(init_sdrs
);
1869 if (ibs
->sdr_filename
&&
1870 !g_file_get_contents(ibs
->sdr_filename
, (gchar
**) &sdrs
, &sdrs_size
,
1872 error_report("failed to load sdr file '%s'", ibs
->sdr_filename
);
1873 sdrs_size
= sizeof(init_sdrs
);
1877 for (i
= 0; i
< sdrs_size
; i
+= len
) {
1878 struct ipmi_sdr_header
*sdrh
;
1880 if (i
+ IPMI_SDR_HEADER_SIZE
> sdrs_size
) {
1881 error_report("Problem with recid 0x%4.4x", i
);
1884 sdrh
= (struct ipmi_sdr_header
*) &sdrs
[i
];
1885 len
= ipmi_sdr_length(sdrh
);
1886 if (i
+ len
> sdrs_size
) {
1887 error_report("Problem with recid 0x%4.4x", i
);
1890 sdr_add_entry(ibs
, sdrh
, len
, NULL
);
1893 if (sdrs
!= init_sdrs
) {
1898 static const VMStateDescription vmstate_ipmi_sim
= {
1899 .name
= TYPE_IPMI_BMC_SIMULATOR
,
1901 .minimum_version_id
= 1,
1902 .fields
= (VMStateField
[]) {
1903 VMSTATE_UINT8(bmc_global_enables
, IPMIBmcSim
),
1904 VMSTATE_UINT8(msg_flags
, IPMIBmcSim
),
1905 VMSTATE_BOOL(watchdog_initialized
, IPMIBmcSim
),
1906 VMSTATE_UINT8(watchdog_use
, IPMIBmcSim
),
1907 VMSTATE_UINT8(watchdog_action
, IPMIBmcSim
),
1908 VMSTATE_UINT8(watchdog_pretimeout
, IPMIBmcSim
),
1909 VMSTATE_BOOL(watchdog_expired
, IPMIBmcSim
),
1910 VMSTATE_UINT16(watchdog_timeout
, IPMIBmcSim
),
1911 VMSTATE_BOOL(watchdog_running
, IPMIBmcSim
),
1912 VMSTATE_BOOL(watchdog_preaction_ran
, IPMIBmcSim
),
1913 VMSTATE_INT64(watchdog_expiry
, IPMIBmcSim
),
1914 VMSTATE_UINT8_ARRAY(evtbuf
, IPMIBmcSim
, 16),
1915 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].status
, IPMIBmcSim
),
1916 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].reading
, IPMIBmcSim
),
1917 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].states
, IPMIBmcSim
),
1918 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_states
, IPMIBmcSim
),
1919 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].deassert_states
,
1921 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_enable
, IPMIBmcSim
),
1922 VMSTATE_END_OF_LIST()
1926 static void ipmi_fru_init(IPMIFru
*fru
)
1931 if (!fru
->filename
) {
1935 fsize
= get_image_size(fru
->filename
);
1937 size
= QEMU_ALIGN_UP(fsize
, fru
->areasize
);
1938 fru
->data
= g_malloc0(size
);
1939 if (load_image_size(fru
->filename
, fru
->data
, fsize
) != fsize
) {
1940 error_report("Could not load file '%s'", fru
->filename
);
1948 /* give one default FRU */
1949 size
= fru
->areasize
;
1950 fru
->data
= g_malloc0(size
);
1953 fru
->nentries
= size
/ fru
->areasize
;
1956 static void ipmi_sim_realize(DeviceState
*dev
, Error
**errp
)
1958 IPMIBmc
*b
= IPMI_BMC(dev
);
1960 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
1962 QTAILQ_INIT(&ibs
->rcvbufs
);
1964 ibs
->bmc_global_enables
= (1 << IPMI_BMC_EVENT_LOG_BIT
);
1965 ibs
->device_id
= 0x20;
1966 ibs
->ipmi_version
= 0x02; /* IPMI 2.0 */
1967 ibs
->restart_cause
= 0;
1968 for (i
= 0; i
< 4; i
++) {
1969 ibs
->sel
.last_addition
[i
] = 0xff;
1970 ibs
->sel
.last_clear
[i
] = 0xff;
1971 ibs
->sdr
.last_addition
[i
] = 0xff;
1972 ibs
->sdr
.last_clear
[i
] = 0xff;
1977 ipmi_fru_init(&ibs
->fru
);
1979 ibs
->acpi_power_state
[0] = 0;
1980 ibs
->acpi_power_state
[1] = 0;
1982 if (qemu_uuid_set
) {
1983 memcpy(&ibs
->uuid
, &qemu_uuid
, 16);
1985 memset(&ibs
->uuid
, 0, 16);
1988 ipmi_init_sensors_from_sdrs(ibs
);
1991 ibs
->timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, ipmi_timeout
, ibs
);
1993 vmstate_register(NULL
, 0, &vmstate_ipmi_sim
, ibs
);
1996 static Property ipmi_sim_properties
[] = {
1997 DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim
, fru
.areasize
, 1024),
1998 DEFINE_PROP_STRING("frudatafile", IPMIBmcSim
, fru
.filename
),
1999 DEFINE_PROP_STRING("sdrfile", IPMIBmcSim
, sdr_filename
),
2000 DEFINE_PROP_UINT8("device_id", IPMIBmcSim
, device_id
, 0x20),
2001 DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim
, ipmi_version
, 0x02),
2002 DEFINE_PROP_UINT8("device_rev", IPMIBmcSim
, device_rev
, 0),
2003 DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim
, fwrev1
, 0),
2004 DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim
, fwrev2
, 0),
2005 DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim
, mfg_id
, 0),
2006 DEFINE_PROP_UINT16("product_id", IPMIBmcSim
, product_id
, 0),
2007 DEFINE_PROP_END_OF_LIST(),
2010 static void ipmi_sim_class_init(ObjectClass
*oc
, void *data
)
2012 DeviceClass
*dc
= DEVICE_CLASS(oc
);
2013 IPMIBmcClass
*bk
= IPMI_BMC_CLASS(oc
);
2015 dc
->hotpluggable
= false;
2016 dc
->realize
= ipmi_sim_realize
;
2017 dc
->props
= ipmi_sim_properties
;
2018 bk
->handle_command
= ipmi_sim_handle_command
;
2021 static const TypeInfo ipmi_sim_type
= {
2022 .name
= TYPE_IPMI_BMC_SIMULATOR
,
2023 .parent
= TYPE_IPMI_BMC
,
2024 .instance_size
= sizeof(IPMIBmcSim
),
2025 .class_init
= ipmi_sim_class_init
,
2028 static void ipmi_sim_register_types(void)
2030 type_register_static(&ipmi_sim_type
);
2033 type_init(ipmi_sim_register_types
)