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 "qemu/module.h"
31 #include "hw/loader.h"
33 #define IPMI_NETFN_CHASSIS 0x00
35 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
36 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
37 #define IPMI_CMD_CHASSIS_CONTROL 0x02
38 #define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09
40 #define IPMI_NETFN_SENSOR_EVENT 0x04
42 #define IPMI_CMD_PLATFORM_EVENT_MSG 0x02
43 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
44 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
45 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
46 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
47 #define IPMI_CMD_GET_SENSOR_READING 0x2d
48 #define IPMI_CMD_SET_SENSOR_TYPE 0x2e
49 #define IPMI_CMD_GET_SENSOR_TYPE 0x2f
51 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
53 #define IPMI_CMD_GET_DEVICE_ID 0x01
54 #define IPMI_CMD_COLD_RESET 0x02
55 #define IPMI_CMD_WARM_RESET 0x03
56 #define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
57 #define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
58 #define IPMI_CMD_GET_DEVICE_GUID 0x08
59 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
60 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
61 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
62 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
63 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
64 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
65 #define IPMI_CMD_GET_MSG_FLAGS 0x31
66 #define IPMI_CMD_GET_MSG 0x33
67 #define IPMI_CMD_SEND_MSG 0x34
68 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
70 #define IPMI_NETFN_STORAGE 0x0a
72 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
73 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
74 #define IPMI_CMD_RESERVE_SDR_REP 0x22
75 #define IPMI_CMD_GET_SDR 0x23
76 #define IPMI_CMD_ADD_SDR 0x24
77 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
78 #define IPMI_CMD_DELETE_SDR 0x26
79 #define IPMI_CMD_CLEAR_SDR_REP 0x27
80 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
81 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
82 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
83 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
84 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
85 #define IPMI_CMD_GET_FRU_AREA_INFO 0x10
86 #define IPMI_CMD_READ_FRU_DATA 0x11
87 #define IPMI_CMD_WRITE_FRU_DATA 0x12
88 #define IPMI_CMD_GET_SEL_INFO 0x40
89 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
90 #define IPMI_CMD_RESERVE_SEL 0x42
91 #define IPMI_CMD_GET_SEL_ENTRY 0x43
92 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
93 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
94 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
95 #define IPMI_CMD_CLEAR_SEL 0x47
96 #define IPMI_CMD_GET_SEL_TIME 0x48
97 #define IPMI_CMD_SET_SEL_TIME 0x49
100 /* Same as a timespec struct. */
106 #define MAX_SEL_SIZE 128
108 typedef struct IPMISel
{
109 uint8_t sel
[MAX_SEL_SIZE
][16];
110 unsigned int next_free
;
112 uint16_t reservation
;
113 uint8_t last_addition
[4];
114 uint8_t last_clear
[4];
118 #define MAX_SDR_SIZE 16384
120 typedef struct IPMISdr
{
121 uint8_t sdr
[MAX_SDR_SIZE
];
122 unsigned int next_free
;
123 uint16_t next_rec_id
;
124 uint16_t reservation
;
125 uint8_t last_addition
[4];
126 uint8_t last_clear
[4];
130 typedef struct IPMIFru
{
132 unsigned int nentries
;
137 typedef struct IPMISensor
{
140 uint16_t states_suppt
;
141 uint16_t assert_suppt
;
142 uint16_t deassert_suppt
;
144 uint16_t assert_states
;
145 uint16_t deassert_states
;
146 uint16_t assert_enable
;
147 uint16_t deassert_enable
;
149 uint8_t evt_reading_type_code
;
151 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
152 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
154 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
155 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
157 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
158 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
160 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
161 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
163 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
165 #define MAX_SENSORS 20
166 #define IPMI_WATCHDOG_SENSOR 0
168 typedef struct IPMIBmcSim IPMIBmcSim
;
169 typedef struct RspBuffer RspBuffer
;
171 #define MAX_NETFNS 64
173 typedef struct IPMICmdHandler
{
174 void (*cmd_handler
)(IPMIBmcSim
*s
,
175 uint8_t *cmd
, unsigned int cmd_len
,
177 unsigned int cmd_len_min
;
180 typedef struct IPMINetfn
{
181 unsigned int cmd_nums
;
182 const IPMICmdHandler
*cmd_handlers
;
185 typedef struct IPMIRcvBufEntry
{
186 QTAILQ_ENTRY(IPMIRcvBufEntry
) entry
;
188 uint8_t buf
[MAX_IPMI_MSG_SIZE
];
191 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
192 #define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
193 TYPE_IPMI_BMC_SIMULATOR)
199 uint8_t bmc_global_enables
;
202 bool watchdog_initialized
;
203 uint8_t watchdog_use
;
204 uint8_t watchdog_action
;
205 uint8_t watchdog_pretimeout
; /* In seconds */
206 bool watchdog_expired
;
207 uint16_t watchdog_timeout
; /* in 100's of milliseconds */
209 bool watchdog_running
;
210 bool watchdog_preaction_ran
;
211 int64_t watchdog_expiry
;
214 uint8_t ipmi_version
;
221 uint8_t restart_cause
;
223 uint8_t acpi_power_state
[2];
229 IPMISensor sensors
[MAX_SENSORS
];
232 /* Odd netfns are for responses, so we only need the even ones. */
233 const IPMINetfn
*netfns
[MAX_NETFNS
/ 2];
235 /* We allow one event in the buffer */
238 QTAILQ_HEAD(, IPMIRcvBufEntry
) rcvbufs
;
241 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
242 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
243 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
244 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
245 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
246 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
247 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
248 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
249 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
251 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
252 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
253 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
254 #define IPMI_BMC_EVENT_LOG_BIT 3
255 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
256 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
257 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
258 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
259 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
260 (1 << IPMI_BMC_EVENT_LOG_BIT))
261 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
262 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
264 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
265 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
266 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
267 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
268 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
269 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
270 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
271 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
272 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
273 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
274 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
275 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
276 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
277 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
278 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
281 uint8_t buffer
[MAX_IPMI_MSG_SIZE
];
285 #define RSP_BUFFER_INITIALIZER { }
287 static inline void rsp_buffer_set_error(RspBuffer
*rsp
, uint8_t byte
)
289 rsp
->buffer
[2] = byte
;
292 /* Add a byte to the response. */
293 static inline void rsp_buffer_push(RspBuffer
*rsp
, uint8_t byte
)
295 if (rsp
->len
>= sizeof(rsp
->buffer
)) {
296 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
299 rsp
->buffer
[rsp
->len
++] = byte
;
302 static inline void rsp_buffer_pushmore(RspBuffer
*rsp
, uint8_t *bytes
,
305 if (rsp
->len
+ n
>= sizeof(rsp
->buffer
)) {
306 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
310 memcpy(&rsp
->buffer
[rsp
->len
], bytes
, n
);
314 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
);
316 static void ipmi_gettime(struct ipmi_time
*time
)
320 stime
= qemu_clock_get_ns(QEMU_CLOCK_HOST
);
321 time
->tv_sec
= stime
/ 1000000000LL;
322 time
->tv_nsec
= stime
% 1000000000LL;
325 static int64_t ipmi_getmonotime(void)
327 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
330 static void ipmi_timeout(void *opaque
)
332 IPMIBmcSim
*ibs
= opaque
;
334 ipmi_sim_handle_timeout(ibs
);
337 static void set_timestamp(IPMIBmcSim
*ibs
, uint8_t *ts
)
340 struct ipmi_time now
;
343 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
345 ts
[1] = (val
>> 8) & 0xff;
346 ts
[2] = (val
>> 16) & 0xff;
347 ts
[3] = (val
>> 24) & 0xff;
350 static void sdr_inc_reservation(IPMISdr
*sdr
)
353 if (sdr
->reservation
== 0) {
354 sdr
->reservation
= 1;
358 static int sdr_add_entry(IPMIBmcSim
*ibs
,
359 const struct ipmi_sdr_header
*sdrh_entry
,
360 unsigned int len
, uint16_t *recid
)
362 struct ipmi_sdr_header
*sdrh
=
363 (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[ibs
->sdr
.next_free
];
365 if ((len
< IPMI_SDR_HEADER_SIZE
) || (len
> 255)) {
369 if (ipmi_sdr_length(sdrh_entry
) != len
) {
373 if (ibs
->sdr
.next_free
+ len
> MAX_SDR_SIZE
) {
374 ibs
->sdr
.overflow
= 1;
378 memcpy(sdrh
, sdrh_entry
, len
);
379 sdrh
->rec_id
[0] = ibs
->sdr
.next_rec_id
& 0xff;
380 sdrh
->rec_id
[1] = (ibs
->sdr
.next_rec_id
>> 8) & 0xff;
381 sdrh
->sdr_version
= 0x51; /* Conform to IPMI 1.5 spec */
384 *recid
= ibs
->sdr
.next_rec_id
;
386 ibs
->sdr
.next_rec_id
++;
387 set_timestamp(ibs
, ibs
->sdr
.last_addition
);
388 ibs
->sdr
.next_free
+= len
;
389 sdr_inc_reservation(&ibs
->sdr
);
393 static int sdr_find_entry(IPMISdr
*sdr
, uint16_t recid
,
394 unsigned int *retpos
, uint16_t *nextrec
)
396 unsigned int pos
= *retpos
;
398 while (pos
< sdr
->next_free
) {
399 struct ipmi_sdr_header
*sdrh
=
400 (struct ipmi_sdr_header
*) &sdr
->sdr
[pos
];
401 uint16_t trec
= ipmi_sdr_recid(sdrh
);
402 unsigned int nextpos
= pos
+ ipmi_sdr_length(sdrh
);
406 if (nextpos
>= sdr
->next_free
) {
409 *nextrec
= (sdr
->sdr
[nextpos
] |
410 (sdr
->sdr
[nextpos
+ 1] << 8));
421 int ipmi_bmc_sdr_find(IPMIBmc
*b
, uint16_t recid
,
422 const struct ipmi_sdr_compact
**sdr
, uint16_t *nextrec
)
425 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
429 if (sdr_find_entry(&ibs
->sdr
, recid
, &pos
, nextrec
)) {
433 *sdr
= (const struct ipmi_sdr_compact
*) &ibs
->sdr
.sdr
[pos
];
437 static void sel_inc_reservation(IPMISel
*sel
)
440 if (sel
->reservation
== 0) {
441 sel
->reservation
= 1;
445 /* Returns 1 if the SEL is full and can't hold the event. */
446 static int sel_add_event(IPMIBmcSim
*ibs
, uint8_t *event
)
452 set_timestamp(ibs
, ts
);
453 if (event
[2] < 0xe0) { /* Don't set timestamps for type 0xe0-0xff. */
454 memcpy(event
+ 3, ts
, 4);
456 if (ibs
->sel
.next_free
== MAX_SEL_SIZE
) {
457 ibs
->sel
.overflow
= 1;
460 event
[0] = ibs
->sel
.next_free
& 0xff;
461 event
[1] = (ibs
->sel
.next_free
>> 8) & 0xff;
462 memcpy(ibs
->sel
.last_addition
, ts
, 4);
463 memcpy(ibs
->sel
.sel
[ibs
->sel
.next_free
], event
, 16);
464 ibs
->sel
.next_free
++;
465 sel_inc_reservation(&ibs
->sel
);
469 static int attn_set(IPMIBmcSim
*ibs
)
471 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
)
472 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
)
473 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs
);
476 static int attn_irq_enabled(IPMIBmcSim
*ibs
)
478 return (IPMI_BMC_MSG_INTS_ON(ibs
) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
))
479 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs
) &&
480 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
));
483 void ipmi_bmc_gen_event(IPMIBmc
*b
, uint8_t *evt
, bool log
)
485 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
486 IPMIInterface
*s
= ibs
->parent
.intf
;
487 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
489 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
493 if (log
&& IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
494 sel_add_event(ibs
, evt
);
497 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
501 memcpy(ibs
->evtbuf
, evt
, 16);
502 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
503 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
507 static void gen_event(IPMIBmcSim
*ibs
, unsigned int sens_num
, uint8_t deassert
,
508 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
510 IPMIInterface
*s
= ibs
->parent
.intf
;
511 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
513 IPMISensor
*sens
= ibs
->sensors
+ sens_num
;
515 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
518 if (!IPMI_SENSOR_GET_EVENTS_ON(sens
)) {
522 evt
[2] = 0x2; /* System event record */
523 evt
[7] = ibs
->parent
.slave_addr
;
525 evt
[9] = 0x04; /* Format version */
526 evt
[10] = sens
->sensor_type
;
528 evt
[12] = sens
->evt_reading_type_code
| (!!deassert
<< 7);
533 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
534 sel_add_event(ibs
, evt
);
537 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
541 memcpy(ibs
->evtbuf
, evt
, 16);
542 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
543 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
546 static void sensor_set_discrete_bit(IPMIBmcSim
*ibs
, unsigned int sensor
,
547 unsigned int bit
, unsigned int val
,
548 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
553 if (sensor
>= MAX_SENSORS
) {
561 sens
= ibs
->sensors
+ sensor
;
563 sens
->states
|= mask
& sens
->states_suppt
;
564 if (sens
->assert_states
& mask
) {
565 return; /* Already asserted */
567 sens
->assert_states
|= mask
& sens
->assert_suppt
;
568 if (sens
->assert_enable
& mask
& sens
->assert_states
) {
569 /* Send an event on assert */
570 gen_event(ibs
, sensor
, 0, evd1
, evd2
, evd3
);
573 sens
->states
&= ~(mask
& sens
->states_suppt
);
574 if (sens
->deassert_states
& mask
) {
575 return; /* Already deasserted */
577 sens
->deassert_states
|= mask
& sens
->deassert_suppt
;
578 if (sens
->deassert_enable
& mask
& sens
->deassert_states
) {
579 /* Send an event on deassert */
580 gen_event(ibs
, sensor
, 1, evd1
, evd2
, evd3
);
585 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim
*s
)
590 for (i
= 0; i
< MAX_SENSORS
; i
++) {
591 memset(s
->sensors
+ i
, 0, sizeof(*sens
));
595 for (i
= 0; !sdr_find_entry(&s
->sdr
, i
, &pos
, NULL
); i
++) {
596 struct ipmi_sdr_compact
*sdr
=
597 (struct ipmi_sdr_compact
*) &s
->sdr
.sdr
[pos
];
598 unsigned int len
= sdr
->header
.rec_length
;
603 if (sdr
->header
.rec_type
!= IPMI_SDR_COMPACT_TYPE
) {
604 continue; /* Not a sensor SDR we set from */
607 if (sdr
->sensor_owner_number
>= MAX_SENSORS
) {
610 sens
= s
->sensors
+ sdr
->sensor_owner_number
;
612 IPMI_SENSOR_SET_PRESENT(sens
, 1);
613 IPMI_SENSOR_SET_SCAN_ON(sens
, (sdr
->sensor_init
>> 6) & 1);
614 IPMI_SENSOR_SET_EVENTS_ON(sens
, (sdr
->sensor_init
>> 5) & 1);
615 sens
->assert_suppt
= sdr
->assert_mask
[0] | (sdr
->assert_mask
[1] << 8);
616 sens
->deassert_suppt
=
617 sdr
->deassert_mask
[0] | (sdr
->deassert_mask
[1] << 8);
619 sdr
->discrete_mask
[0] | (sdr
->discrete_mask
[1] << 8);
620 sens
->sensor_type
= sdr
->sensor_type
;
621 sens
->evt_reading_type_code
= sdr
->reading_type
& 0x7f;
623 /* Enable all the events that are supported. */
624 sens
->assert_enable
= sens
->assert_suppt
;
625 sens
->deassert_enable
= sens
->deassert_suppt
;
629 static int ipmi_register_netfn(IPMIBmcSim
*s
, unsigned int netfn
,
630 const IPMINetfn
*netfnd
)
632 if ((netfn
& 1) || (netfn
>= MAX_NETFNS
) || (s
->netfns
[netfn
/ 2])) {
635 s
->netfns
[netfn
/ 2] = netfnd
;
639 static const IPMICmdHandler
*ipmi_get_handler(IPMIBmcSim
*ibs
,
643 const IPMICmdHandler
*hdl
;
645 if (netfn
& 1 || netfn
>= MAX_NETFNS
|| !ibs
->netfns
[netfn
/ 2]) {
649 if (cmd
>= ibs
->netfns
[netfn
/ 2]->cmd_nums
) {
653 hdl
= &ibs
->netfns
[netfn
/ 2]->cmd_handlers
[cmd
];
654 if (!hdl
->cmd_handler
) {
661 static void next_timeout(IPMIBmcSim
*ibs
)
664 if (ibs
->watchdog_running
) {
665 next
= ibs
->watchdog_expiry
;
668 next
= ipmi_getmonotime() + 60 * 1000000000LL;
670 timer_mod_ns(ibs
->timer
, next
);
673 static void ipmi_sim_handle_command(IPMIBmc
*b
,
674 uint8_t *cmd
, unsigned int cmd_len
,
675 unsigned int max_cmd_len
,
678 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
679 IPMIInterface
*s
= ibs
->parent
.intf
;
680 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
681 const IPMICmdHandler
*hdl
;
682 RspBuffer rsp
= RSP_BUFFER_INITIALIZER
;
684 /* Set up the response, set the low bit of NETFN. */
685 /* Note that max_rsp_len must be at least 3 */
686 if (sizeof(rsp
.buffer
) < 3) {
687 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
691 rsp_buffer_push(&rsp
, cmd
[0] | 0x04);
692 rsp_buffer_push(&rsp
, cmd
[1]);
693 rsp_buffer_push(&rsp
, 0); /* Assume success */
695 /* If it's too short or it was truncated, return an error. */
697 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
700 if (cmd_len
> max_cmd_len
) {
701 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
705 if ((cmd
[0] & 0x03) != 0) {
706 /* Only have stuff on LUN 0 */
707 rsp_buffer_set_error(&rsp
, IPMI_CC_COMMAND_INVALID_FOR_LUN
);
711 hdl
= ipmi_get_handler(ibs
, cmd
[0] >> 2, cmd
[1]);
713 rsp_buffer_set_error(&rsp
, IPMI_CC_INVALID_CMD
);
717 if (cmd_len
< hdl
->cmd_len_min
) {
718 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
722 hdl
->cmd_handler(ibs
, cmd
, cmd_len
, &rsp
);
725 k
->handle_rsp(s
, msg_id
, rsp
.buffer
, rsp
.len
);
730 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
)
732 IPMIInterface
*s
= ibs
->parent
.intf
;
733 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
735 if (!ibs
->watchdog_running
) {
739 if (!ibs
->watchdog_preaction_ran
) {
740 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
)) {
741 case IPMI_BMC_WATCHDOG_PRE_NMI
:
742 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
743 k
->do_hw_op(s
, IPMI_SEND_NMI
, 0);
744 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
745 0xc8, (2 << 4) | 0xf, 0xff);
748 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
749 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
750 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
751 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
752 0xc8, (3 << 4) | 0xf, 0xff);
759 ibs
->watchdog_preaction_ran
= 1;
760 /* Issued the pretimeout, do the rest of the timeout now. */
761 ibs
->watchdog_expiry
= ipmi_getmonotime();
762 ibs
->watchdog_expiry
+= ibs
->watchdog_pretimeout
* 1000000000LL;
767 ibs
->watchdog_running
= 0; /* Stop the watchdog on a timeout */
768 ibs
->watchdog_expired
|= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs
));
769 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
)) {
770 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
771 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 0, 1,
772 0xc0, ibs
->watchdog_use
& 0xf, 0xff);
775 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
776 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 1, 1,
777 0xc1, ibs
->watchdog_use
& 0xf, 0xff);
778 k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0);
781 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
782 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
783 0xc2, ibs
->watchdog_use
& 0xf, 0xff);
784 k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0);
787 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
788 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
789 0xc3, ibs
->watchdog_use
& 0xf, 0xff);
790 k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0);
798 static void chassis_capabilities(IPMIBmcSim
*ibs
,
799 uint8_t *cmd
, unsigned int cmd_len
,
802 rsp_buffer_push(rsp
, 0);
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
);
806 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
809 static void chassis_status(IPMIBmcSim
*ibs
,
810 uint8_t *cmd
, unsigned int cmd_len
,
813 rsp_buffer_push(rsp
, 0x61); /* Unknown power restore, power is on */
814 rsp_buffer_push(rsp
, 0);
815 rsp_buffer_push(rsp
, 0);
816 rsp_buffer_push(rsp
, 0);
819 static void chassis_control(IPMIBmcSim
*ibs
,
820 uint8_t *cmd
, unsigned int cmd_len
,
823 IPMIInterface
*s
= ibs
->parent
.intf
;
824 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
826 switch (cmd
[2] & 0xf) {
827 case 0: /* power down */
828 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0));
830 case 1: /* power up */
831 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERON_CHASSIS
, 0));
833 case 2: /* power cycle */
834 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0));
836 case 3: /* hard reset */
837 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0));
839 case 4: /* pulse diagnostic interrupt */
840 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_PULSE_DIAG_IRQ
, 0));
842 case 5: /* soft shutdown via ACPI by overtemp emulation */
843 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
,
844 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP
, 0));
847 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
852 static void chassis_get_sys_restart_cause(IPMIBmcSim
*ibs
,
853 uint8_t *cmd
, unsigned int cmd_len
,
857 rsp_buffer_push(rsp
, ibs
->restart_cause
& 0xf); /* Restart Cause */
858 rsp_buffer_push(rsp
, 0); /* Channel 0 */
861 static void get_device_id(IPMIBmcSim
*ibs
,
862 uint8_t *cmd
, unsigned int cmd_len
,
865 rsp_buffer_push(rsp
, ibs
->device_id
);
866 rsp_buffer_push(rsp
, ibs
->device_rev
& 0xf);
867 rsp_buffer_push(rsp
, ibs
->fwrev1
& 0x7f);
868 rsp_buffer_push(rsp
, ibs
->fwrev2
);
869 rsp_buffer_push(rsp
, ibs
->ipmi_version
);
870 rsp_buffer_push(rsp
, 0x07); /* sensor, SDR, and SEL. */
871 rsp_buffer_push(rsp
, ibs
->mfg_id
& 0xff);
872 rsp_buffer_push(rsp
, (ibs
->mfg_id
>> 8) & 0xff);
873 rsp_buffer_push(rsp
, (ibs
->mfg_id
>> 16) & 0xff);
874 rsp_buffer_push(rsp
, ibs
->product_id
& 0xff);
875 rsp_buffer_push(rsp
, (ibs
->product_id
>> 8) & 0xff);
878 static void set_global_enables(IPMIBmcSim
*ibs
, uint8_t val
)
880 IPMIInterface
*s
= ibs
->parent
.intf
;
881 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
884 ibs
->bmc_global_enables
= val
;
886 irqs_on
= val
& (IPMI_BMC_EVBUF_FULL_INT_BIT
|
887 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT
);
889 k
->set_irq_enable(s
, irqs_on
);
892 static void cold_reset(IPMIBmcSim
*ibs
,
893 uint8_t *cmd
, unsigned int cmd_len
,
896 IPMIInterface
*s
= ibs
->parent
.intf
;
897 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
899 /* Disable all interrupts */
900 set_global_enables(ibs
, 1 << IPMI_BMC_EVENT_LOG_BIT
);
907 static void warm_reset(IPMIBmcSim
*ibs
,
908 uint8_t *cmd
, unsigned int cmd_len
,
911 IPMIInterface
*s
= ibs
->parent
.intf
;
912 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
918 static void set_acpi_power_state(IPMIBmcSim
*ibs
,
919 uint8_t *cmd
, unsigned int cmd_len
,
922 ibs
->acpi_power_state
[0] = cmd
[2];
923 ibs
->acpi_power_state
[1] = cmd
[3];
926 static void get_acpi_power_state(IPMIBmcSim
*ibs
,
927 uint8_t *cmd
, unsigned int cmd_len
,
930 rsp_buffer_push(rsp
, ibs
->acpi_power_state
[0]);
931 rsp_buffer_push(rsp
, ibs
->acpi_power_state
[1]);
934 static void get_device_guid(IPMIBmcSim
*ibs
,
935 uint8_t *cmd
, unsigned int cmd_len
,
940 for (i
= 0; i
< 16; i
++) {
941 rsp_buffer_push(rsp
, ibs
->uuid
[i
]);
945 static void set_bmc_global_enables(IPMIBmcSim
*ibs
,
946 uint8_t *cmd
, unsigned int cmd_len
,
949 set_global_enables(ibs
, cmd
[2]);
952 static void get_bmc_global_enables(IPMIBmcSim
*ibs
,
953 uint8_t *cmd
, unsigned int cmd_len
,
956 rsp_buffer_push(rsp
, ibs
->bmc_global_enables
);
959 static void clr_msg_flags(IPMIBmcSim
*ibs
,
960 uint8_t *cmd
, unsigned int cmd_len
,
963 IPMIInterface
*s
= ibs
->parent
.intf
;
964 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
966 ibs
->msg_flags
&= ~cmd
[2];
967 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
970 static void get_msg_flags(IPMIBmcSim
*ibs
,
971 uint8_t *cmd
, unsigned int cmd_len
,
974 rsp_buffer_push(rsp
, ibs
->msg_flags
);
977 static void read_evt_msg_buf(IPMIBmcSim
*ibs
,
978 uint8_t *cmd
, unsigned int cmd_len
,
981 IPMIInterface
*s
= ibs
->parent
.intf
;
982 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
985 if (!(ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
)) {
986 rsp_buffer_set_error(rsp
, 0x80);
989 for (i
= 0; i
< 16; i
++) {
990 rsp_buffer_push(rsp
, ibs
->evtbuf
[i
]);
992 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
993 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
996 static void get_msg(IPMIBmcSim
*ibs
,
997 uint8_t *cmd
, unsigned int cmd_len
,
1000 IPMIRcvBufEntry
*msg
;
1002 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
1003 rsp_buffer_set_error(rsp
, 0x80); /* Queue empty */
1006 rsp_buffer_push(rsp
, 0); /* Channel 0 */
1007 msg
= QTAILQ_FIRST(&ibs
->rcvbufs
);
1008 rsp_buffer_pushmore(rsp
, msg
->buf
, msg
->len
);
1009 QTAILQ_REMOVE(&ibs
->rcvbufs
, msg
, entry
);
1012 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
1013 IPMIInterface
*s
= ibs
->parent
.intf
;
1014 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1016 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
1017 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
1024 static unsigned char
1025 ipmb_checksum(unsigned char *data
, int size
, unsigned char csum
)
1027 for (; size
> 0; size
--, data
++) {
1034 static void send_msg(IPMIBmcSim
*ibs
,
1035 uint8_t *cmd
, unsigned int cmd_len
,
1038 IPMIInterface
*s
= ibs
->parent
.intf
;
1039 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1040 IPMIRcvBufEntry
*msg
;
1042 uint8_t netfn
, rqLun
, rsLun
, rqSeq
;
1045 /* We only handle channel 0 with no options */
1046 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1051 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
1055 if (cmd
[3] != 0x40) {
1056 /* We only emulate a MC at address 0x40. */
1057 rsp_buffer_set_error(rsp
, 0x83); /* NAK on write */
1061 cmd
+= 3; /* Skip the header. */
1065 * At this point we "send" the message successfully. Any error will
1066 * be returned in the response.
1068 if (ipmb_checksum(cmd
, cmd_len
, 0) != 0 ||
1069 cmd
[3] != 0x20) { /* Improper response address */
1070 return; /* No response */
1073 netfn
= cmd
[1] >> 2;
1074 rqLun
= cmd
[4] & 0x3;
1075 rsLun
= cmd
[1] & 0x3;
1076 rqSeq
= cmd
[4] >> 2;
1079 /* We only support LUN 2 coming back to us. */
1083 msg
= g_malloc(sizeof(*msg
));
1084 msg
->buf
[0] = ((netfn
| 1) << 2) | rqLun
; /* NetFN, and make a response */
1085 msg
->buf
[1] = ipmb_checksum(msg
->buf
, 1, 0);
1086 msg
->buf
[2] = cmd
[0]; /* rsSA */
1087 msg
->buf
[3] = (rqSeq
<< 2) | rsLun
;
1088 msg
->buf
[4] = cmd
[5]; /* Cmd */
1089 msg
->buf
[5] = 0; /* Completion Code */
1092 if ((cmd
[1] >> 2) != IPMI_NETFN_APP
|| cmd
[5] != IPMI_CMD_GET_DEVICE_ID
) {
1093 /* Not a command we handle. */
1094 msg
->buf
[5] = IPMI_CC_INVALID_CMD
;
1098 buf
= msg
->buf
+ msg
->len
; /* After the CC */
1113 msg
->buf
[msg
->len
] = ipmb_checksum(msg
->buf
, msg
->len
, 0);
1115 QTAILQ_INSERT_TAIL(&ibs
->rcvbufs
, msg
, entry
);
1116 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
1117 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
1120 static void do_watchdog_reset(IPMIBmcSim
*ibs
)
1122 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
) ==
1123 IPMI_BMC_WATCHDOG_ACTION_NONE
) {
1124 ibs
->watchdog_running
= 0;
1127 ibs
->watchdog_preaction_ran
= 0;
1130 /* Timeout is in tenths of a second, offset is in seconds */
1131 ibs
->watchdog_expiry
= ipmi_getmonotime();
1132 ibs
->watchdog_expiry
+= ibs
->watchdog_timeout
* 100000000LL;
1133 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
) != IPMI_BMC_WATCHDOG_PRE_NONE
) {
1134 ibs
->watchdog_expiry
-= ibs
->watchdog_pretimeout
* 1000000000LL;
1136 ibs
->watchdog_running
= 1;
1139 static void reset_watchdog_timer(IPMIBmcSim
*ibs
,
1140 uint8_t *cmd
, unsigned int cmd_len
,
1143 if (!ibs
->watchdog_initialized
) {
1144 rsp_buffer_set_error(rsp
, 0x80);
1147 do_watchdog_reset(ibs
);
1150 static void set_watchdog_timer(IPMIBmcSim
*ibs
,
1151 uint8_t *cmd
, unsigned int cmd_len
,
1154 IPMIInterface
*s
= ibs
->parent
.intf
;
1155 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1158 val
= cmd
[2] & 0x7; /* Validate use */
1159 if (val
== 0 || val
> 5) {
1160 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1163 val
= cmd
[3] & 0x7; /* Validate action */
1165 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
1168 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
1169 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 1));
1172 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
1173 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 1));
1176 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
1177 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 1));
1181 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1183 if (rsp
->buffer
[2]) {
1184 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1188 val
= (cmd
[3] >> 4) & 0x7; /* Validate preaction */
1190 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
1191 case IPMI_BMC_WATCHDOG_PRE_NONE
:
1194 case IPMI_BMC_WATCHDOG_PRE_NMI
:
1195 if (!k
->do_hw_op(s
, IPMI_SEND_NMI
, 1)) {
1196 /* NMI not supported. */
1197 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1203 /* We don't support PRE_SMI */
1204 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1208 ibs
->watchdog_initialized
= 1;
1209 ibs
->watchdog_use
= cmd
[2] & IPMI_BMC_WATCHDOG_USE_MASK
;
1210 ibs
->watchdog_action
= cmd
[3] & IPMI_BMC_WATCHDOG_ACTION_MASK
;
1211 ibs
->watchdog_pretimeout
= cmd
[4];
1212 ibs
->watchdog_expired
&= ~cmd
[5];
1213 ibs
->watchdog_timeout
= cmd
[6] | (((uint16_t) cmd
[7]) << 8);
1214 if (ibs
->watchdog_running
& IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs
)) {
1215 do_watchdog_reset(ibs
);
1217 ibs
->watchdog_running
= 0;
1221 static void get_watchdog_timer(IPMIBmcSim
*ibs
,
1222 uint8_t *cmd
, unsigned int cmd_len
,
1225 rsp_buffer_push(rsp
, ibs
->watchdog_use
);
1226 rsp_buffer_push(rsp
, ibs
->watchdog_action
);
1227 rsp_buffer_push(rsp
, ibs
->watchdog_pretimeout
);
1228 rsp_buffer_push(rsp
, ibs
->watchdog_expired
);
1229 if (ibs
->watchdog_running
) {
1231 timeout
= ((ibs
->watchdog_expiry
- ipmi_getmonotime() + 50000000)
1233 rsp_buffer_push(rsp
, timeout
& 0xff);
1234 rsp_buffer_push(rsp
, (timeout
>> 8) & 0xff);
1236 rsp_buffer_push(rsp
, 0);
1237 rsp_buffer_push(rsp
, 0);
1241 static void get_sdr_rep_info(IPMIBmcSim
*ibs
,
1242 uint8_t *cmd
, unsigned int cmd_len
,
1247 rsp_buffer_push(rsp
, 0x51); /* Conform to IPMI 1.5 spec */
1248 rsp_buffer_push(rsp
, ibs
->sdr
.next_rec_id
& 0xff);
1249 rsp_buffer_push(rsp
, (ibs
->sdr
.next_rec_id
>> 8) & 0xff);
1250 rsp_buffer_push(rsp
, (MAX_SDR_SIZE
- ibs
->sdr
.next_free
) & 0xff);
1251 rsp_buffer_push(rsp
, ((MAX_SDR_SIZE
- ibs
->sdr
.next_free
) >> 8) & 0xff);
1252 for (i
= 0; i
< 4; i
++) {
1253 rsp_buffer_push(rsp
, ibs
->sdr
.last_addition
[i
]);
1255 for (i
= 0; i
< 4; i
++) {
1256 rsp_buffer_push(rsp
, ibs
->sdr
.last_clear
[i
]);
1258 /* Only modal support, reserve supported */
1259 rsp_buffer_push(rsp
, (ibs
->sdr
.overflow
<< 7) | 0x22);
1262 static void reserve_sdr_rep(IPMIBmcSim
*ibs
,
1263 uint8_t *cmd
, unsigned int cmd_len
,
1266 rsp_buffer_push(rsp
, ibs
->sdr
.reservation
& 0xff);
1267 rsp_buffer_push(rsp
, (ibs
->sdr
.reservation
>> 8) & 0xff);
1270 static void get_sdr(IPMIBmcSim
*ibs
,
1271 uint8_t *cmd
, unsigned int cmd_len
,
1276 struct ipmi_sdr_header
*sdrh
;
1279 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sdr
.reservation
) {
1280 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1286 if (sdr_find_entry(&ibs
->sdr
, cmd
[4] | (cmd
[5] << 8),
1288 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1292 sdrh
= (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[pos
];
1294 if (cmd
[6] > ipmi_sdr_length(sdrh
)) {
1295 rsp_buffer_set_error(rsp
, IPMI_CC_PARM_OUT_OF_RANGE
);
1299 rsp_buffer_push(rsp
, nextrec
& 0xff);
1300 rsp_buffer_push(rsp
, (nextrec
>> 8) & 0xff);
1302 if (cmd
[7] == 0xff) {
1303 cmd
[7] = ipmi_sdr_length(sdrh
) - cmd
[6];
1306 if ((cmd
[7] + rsp
->len
) > sizeof(rsp
->buffer
)) {
1307 rsp_buffer_set_error(rsp
, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES
);
1311 rsp_buffer_pushmore(rsp
, ibs
->sdr
.sdr
+ pos
+ cmd
[6], cmd
[7]);
1314 static void add_sdr(IPMIBmcSim
*ibs
,
1315 uint8_t *cmd
, unsigned int cmd_len
,
1319 struct ipmi_sdr_header
*sdrh
= (struct ipmi_sdr_header
*) cmd
+ 2;
1321 if (sdr_add_entry(ibs
, sdrh
, cmd_len
- 2, &recid
)) {
1322 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1325 rsp_buffer_push(rsp
, recid
& 0xff);
1326 rsp_buffer_push(rsp
, (recid
>> 8) & 0xff);
1329 static void clear_sdr_rep(IPMIBmcSim
*ibs
,
1330 uint8_t *cmd
, unsigned int cmd_len
,
1333 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sdr
.reservation
) {
1334 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1338 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1339 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1342 if (cmd
[7] == 0xaa) {
1343 ibs
->sdr
.next_free
= 0;
1344 ibs
->sdr
.overflow
= 0;
1345 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1346 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1347 sdr_inc_reservation(&ibs
->sdr
);
1348 } else if (cmd
[7] == 0) {
1349 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1351 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1356 static void get_sel_info(IPMIBmcSim
*ibs
,
1357 uint8_t *cmd
, unsigned int cmd_len
,
1360 unsigned int i
, val
;
1362 rsp_buffer_push(rsp
, 0x51); /* Conform to IPMI 1.5 */
1363 rsp_buffer_push(rsp
, ibs
->sel
.next_free
& 0xff);
1364 rsp_buffer_push(rsp
, (ibs
->sel
.next_free
>> 8) & 0xff);
1365 val
= (MAX_SEL_SIZE
- ibs
->sel
.next_free
) * 16;
1366 rsp_buffer_push(rsp
, val
& 0xff);
1367 rsp_buffer_push(rsp
, (val
>> 8) & 0xff);
1368 for (i
= 0; i
< 4; i
++) {
1369 rsp_buffer_push(rsp
, ibs
->sel
.last_addition
[i
]);
1371 for (i
= 0; i
< 4; i
++) {
1372 rsp_buffer_push(rsp
, ibs
->sel
.last_clear
[i
]);
1374 /* Only support Reserve SEL */
1375 rsp_buffer_push(rsp
, (ibs
->sel
.overflow
<< 7) | 0x02);
1378 static void get_fru_area_info(IPMIBmcSim
*ibs
,
1379 uint8_t *cmd
, unsigned int cmd_len
,
1383 uint16_t fru_entry_size
;
1387 if (fruid
>= ibs
->fru
.nentries
) {
1388 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1392 fru_entry_size
= ibs
->fru
.areasize
;
1394 rsp_buffer_push(rsp
, fru_entry_size
& 0xff);
1395 rsp_buffer_push(rsp
, fru_entry_size
>> 8 & 0xff);
1396 rsp_buffer_push(rsp
, 0x0);
1399 static void read_fru_data(IPMIBmcSim
*ibs
,
1400 uint8_t *cmd
, unsigned int cmd_len
,
1410 offset
= (cmd
[3] | cmd
[4] << 8);
1412 if (fruid
>= ibs
->fru
.nentries
) {
1413 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1417 if (offset
>= ibs
->fru
.areasize
- 1) {
1418 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1422 fru_entry
= &ibs
->fru
.data
[fruid
* ibs
->fru
.areasize
];
1424 count
= MIN(cmd
[5], ibs
->fru
.areasize
- offset
);
1426 rsp_buffer_push(rsp
, count
& 0xff);
1427 for (i
= 0; i
< count
; i
++) {
1428 rsp_buffer_push(rsp
, fru_entry
[offset
+ i
]);
1432 static void write_fru_data(IPMIBmcSim
*ibs
,
1433 uint8_t *cmd
, unsigned int cmd_len
,
1442 offset
= (cmd
[3] | cmd
[4] << 8);
1444 if (fruid
>= ibs
->fru
.nentries
) {
1445 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1449 if (offset
>= ibs
->fru
.areasize
- 1) {
1450 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1454 fru_entry
= &ibs
->fru
.data
[fruid
* ibs
->fru
.areasize
];
1456 count
= MIN(cmd_len
- 5, ibs
->fru
.areasize
- offset
);
1458 memcpy(fru_entry
+ offset
, cmd
+ 5, count
);
1460 rsp_buffer_push(rsp
, count
& 0xff);
1463 static void reserve_sel(IPMIBmcSim
*ibs
,
1464 uint8_t *cmd
, unsigned int cmd_len
,
1467 rsp_buffer_push(rsp
, ibs
->sel
.reservation
& 0xff);
1468 rsp_buffer_push(rsp
, (ibs
->sel
.reservation
>> 8) & 0xff);
1471 static void get_sel_entry(IPMIBmcSim
*ibs
,
1472 uint8_t *cmd
, unsigned int cmd_len
,
1478 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sel
.reservation
) {
1479 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1483 if (ibs
->sel
.next_free
== 0) {
1484 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1488 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1491 if (cmd
[7] == 0xff) {
1493 } else if ((cmd
[7] + cmd
[6]) > 16) {
1494 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1500 val
= cmd
[4] | (cmd
[5] << 8);
1501 if (val
== 0xffff) {
1502 val
= ibs
->sel
.next_free
- 1;
1503 } else if (val
>= ibs
->sel
.next_free
) {
1504 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1507 if ((val
+ 1) == ibs
->sel
.next_free
) {
1508 rsp_buffer_push(rsp
, 0xff);
1509 rsp_buffer_push(rsp
, 0xff);
1511 rsp_buffer_push(rsp
, (val
+ 1) & 0xff);
1512 rsp_buffer_push(rsp
, ((val
+ 1) >> 8) & 0xff);
1514 for (; cmd
[6] < cmd
[7]; cmd
[6]++) {
1515 rsp_buffer_push(rsp
, ibs
->sel
.sel
[val
][cmd
[6]]);
1519 static void add_sel_entry(IPMIBmcSim
*ibs
,
1520 uint8_t *cmd
, unsigned int cmd_len
,
1523 if (sel_add_event(ibs
, cmd
+ 2)) {
1524 rsp_buffer_set_error(rsp
, IPMI_CC_OUT_OF_SPACE
);
1527 /* sel_add_event fills in the record number. */
1528 rsp_buffer_push(rsp
, cmd
[2]);
1529 rsp_buffer_push(rsp
, cmd
[3]);
1532 static void clear_sel(IPMIBmcSim
*ibs
,
1533 uint8_t *cmd
, unsigned int cmd_len
,
1536 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sel
.reservation
) {
1537 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1541 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1542 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1545 if (cmd
[7] == 0xaa) {
1546 ibs
->sel
.next_free
= 0;
1547 ibs
->sel
.overflow
= 0;
1548 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1549 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1550 sel_inc_reservation(&ibs
->sel
);
1551 } else if (cmd
[7] == 0) {
1552 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1554 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1559 static void get_sel_time(IPMIBmcSim
*ibs
,
1560 uint8_t *cmd
, unsigned int cmd_len
,
1564 struct ipmi_time now
;
1567 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
1568 rsp_buffer_push(rsp
, val
& 0xff);
1569 rsp_buffer_push(rsp
, (val
>> 8) & 0xff);
1570 rsp_buffer_push(rsp
, (val
>> 16) & 0xff);
1571 rsp_buffer_push(rsp
, (val
>> 24) & 0xff);
1574 static void set_sel_time(IPMIBmcSim
*ibs
,
1575 uint8_t *cmd
, unsigned int cmd_len
,
1579 struct ipmi_time now
;
1581 val
= cmd
[2] | (cmd
[3] << 8) | (cmd
[4] << 16) | (cmd
[5] << 24);
1583 ibs
->sel
.time_offset
= now
.tv_sec
- ((long) val
);
1586 static void platform_event_msg(IPMIBmcSim
*ibs
,
1587 uint8_t *cmd
, unsigned int cmd_len
,
1592 event
[2] = 2; /* System event record */
1593 event
[7] = cmd
[2]; /* Generator ID */
1595 event
[9] = cmd
[3]; /* EvMRev */
1596 event
[10] = cmd
[4]; /* Sensor type */
1597 event
[11] = cmd
[5]; /* Sensor number */
1598 event
[12] = cmd
[6]; /* Event dir / Event type */
1599 event
[13] = cmd
[7]; /* Event data 1 */
1600 event
[14] = cmd
[8]; /* Event data 2 */
1601 event
[15] = cmd
[9]; /* Event data 3 */
1603 if (sel_add_event(ibs
, event
)) {
1604 rsp_buffer_set_error(rsp
, IPMI_CC_OUT_OF_SPACE
);
1608 static void set_sensor_evt_enable(IPMIBmcSim
*ibs
,
1609 uint8_t *cmd
, unsigned int cmd_len
,
1614 if ((cmd
[2] >= MAX_SENSORS
) ||
1615 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1616 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1619 sens
= ibs
->sensors
+ cmd
[2];
1620 switch ((cmd
[3] >> 4) & 0x3) {
1621 case 0: /* Do not change */
1623 case 1: /* Enable bits */
1625 sens
->assert_enable
|= cmd
[4];
1628 sens
->assert_enable
|= cmd
[5] << 8;
1631 sens
->deassert_enable
|= cmd
[6];
1634 sens
->deassert_enable
|= cmd
[7] << 8;
1637 case 2: /* Disable bits */
1639 sens
->assert_enable
&= ~cmd
[4];
1642 sens
->assert_enable
&= ~(cmd
[5] << 8);
1645 sens
->deassert_enable
&= ~cmd
[6];
1648 sens
->deassert_enable
&= ~(cmd
[7] << 8);
1652 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1655 IPMI_SENSOR_SET_RET_STATUS(sens
, cmd
[3]);
1658 static void get_sensor_evt_enable(IPMIBmcSim
*ibs
,
1659 uint8_t *cmd
, unsigned int cmd_len
,
1664 if ((cmd
[2] >= MAX_SENSORS
) ||
1665 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1666 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1669 sens
= ibs
->sensors
+ cmd
[2];
1670 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1671 rsp_buffer_push(rsp
, sens
->assert_enable
& 0xff);
1672 rsp_buffer_push(rsp
, (sens
->assert_enable
>> 8) & 0xff);
1673 rsp_buffer_push(rsp
, sens
->deassert_enable
& 0xff);
1674 rsp_buffer_push(rsp
, (sens
->deassert_enable
>> 8) & 0xff);
1677 static void rearm_sensor_evts(IPMIBmcSim
*ibs
,
1678 uint8_t *cmd
, unsigned int cmd_len
,
1683 if ((cmd
[2] >= MAX_SENSORS
) ||
1684 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1685 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1688 sens
= ibs
->sensors
+ cmd
[2];
1690 if ((cmd
[3] & 0x80) == 0) {
1691 /* Just clear everything */
1697 static void get_sensor_evt_status(IPMIBmcSim
*ibs
,
1698 uint8_t *cmd
, unsigned int cmd_len
,
1703 if ((cmd
[2] >= MAX_SENSORS
) ||
1704 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1705 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1708 sens
= ibs
->sensors
+ cmd
[2];
1709 rsp_buffer_push(rsp
, sens
->reading
);
1710 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1711 rsp_buffer_push(rsp
, sens
->assert_states
& 0xff);
1712 rsp_buffer_push(rsp
, (sens
->assert_states
>> 8) & 0xff);
1713 rsp_buffer_push(rsp
, sens
->deassert_states
& 0xff);
1714 rsp_buffer_push(rsp
, (sens
->deassert_states
>> 8) & 0xff);
1717 static void get_sensor_reading(IPMIBmcSim
*ibs
,
1718 uint8_t *cmd
, unsigned int cmd_len
,
1723 if ((cmd
[2] >= MAX_SENSORS
) ||
1724 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1725 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1728 sens
= ibs
->sensors
+ cmd
[2];
1729 rsp_buffer_push(rsp
, sens
->reading
);
1730 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1731 rsp_buffer_push(rsp
, sens
->states
& 0xff);
1732 if (IPMI_SENSOR_IS_DISCRETE(sens
)) {
1733 rsp_buffer_push(rsp
, (sens
->states
>> 8) & 0xff);
1737 static void set_sensor_type(IPMIBmcSim
*ibs
,
1738 uint8_t *cmd
, unsigned int cmd_len
,
1744 if ((cmd
[2] >= MAX_SENSORS
) ||
1745 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1746 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1749 sens
= ibs
->sensors
+ cmd
[2];
1750 sens
->sensor_type
= cmd
[3];
1751 sens
->evt_reading_type_code
= cmd
[4] & 0x7f;
1754 static void get_sensor_type(IPMIBmcSim
*ibs
,
1755 uint8_t *cmd
, unsigned int cmd_len
,
1761 if ((cmd
[2] >= MAX_SENSORS
) ||
1762 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1763 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1766 sens
= ibs
->sensors
+ cmd
[2];
1767 rsp_buffer_push(rsp
, sens
->sensor_type
);
1768 rsp_buffer_push(rsp
, sens
->evt_reading_type_code
);
1772 static const IPMICmdHandler chassis_cmds
[] = {
1773 [IPMI_CMD_GET_CHASSIS_CAPABILITIES
] = { chassis_capabilities
},
1774 [IPMI_CMD_GET_CHASSIS_STATUS
] = { chassis_status
},
1775 [IPMI_CMD_CHASSIS_CONTROL
] = { chassis_control
, 3 },
1776 [IPMI_CMD_GET_SYS_RESTART_CAUSE
] = { chassis_get_sys_restart_cause
}
1778 static const IPMINetfn chassis_netfn
= {
1779 .cmd_nums
= ARRAY_SIZE(chassis_cmds
),
1780 .cmd_handlers
= chassis_cmds
1783 static const IPMICmdHandler sensor_event_cmds
[] = {
1784 [IPMI_CMD_PLATFORM_EVENT_MSG
] = { platform_event_msg
, 10 },
1785 [IPMI_CMD_SET_SENSOR_EVT_ENABLE
] = { set_sensor_evt_enable
, 4 },
1786 [IPMI_CMD_GET_SENSOR_EVT_ENABLE
] = { get_sensor_evt_enable
, 3 },
1787 [IPMI_CMD_REARM_SENSOR_EVTS
] = { rearm_sensor_evts
, 4 },
1788 [IPMI_CMD_GET_SENSOR_EVT_STATUS
] = { get_sensor_evt_status
, 3 },
1789 [IPMI_CMD_GET_SENSOR_READING
] = { get_sensor_reading
, 3 },
1790 [IPMI_CMD_SET_SENSOR_TYPE
] = { set_sensor_type
, 5 },
1791 [IPMI_CMD_GET_SENSOR_TYPE
] = { get_sensor_type
, 3 },
1793 static const IPMINetfn sensor_event_netfn
= {
1794 .cmd_nums
= ARRAY_SIZE(sensor_event_cmds
),
1795 .cmd_handlers
= sensor_event_cmds
1798 static const IPMICmdHandler app_cmds
[] = {
1799 [IPMI_CMD_GET_DEVICE_ID
] = { get_device_id
},
1800 [IPMI_CMD_COLD_RESET
] = { cold_reset
},
1801 [IPMI_CMD_WARM_RESET
] = { warm_reset
},
1802 [IPMI_CMD_SET_ACPI_POWER_STATE
] = { set_acpi_power_state
, 4 },
1803 [IPMI_CMD_GET_ACPI_POWER_STATE
] = { get_acpi_power_state
},
1804 [IPMI_CMD_GET_DEVICE_GUID
] = { get_device_guid
},
1805 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES
] = { set_bmc_global_enables
, 3 },
1806 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES
] = { get_bmc_global_enables
},
1807 [IPMI_CMD_CLR_MSG_FLAGS
] = { clr_msg_flags
, 3 },
1808 [IPMI_CMD_GET_MSG_FLAGS
] = { get_msg_flags
},
1809 [IPMI_CMD_GET_MSG
] = { get_msg
},
1810 [IPMI_CMD_SEND_MSG
] = { send_msg
, 3 },
1811 [IPMI_CMD_READ_EVT_MSG_BUF
] = { read_evt_msg_buf
},
1812 [IPMI_CMD_RESET_WATCHDOG_TIMER
] = { reset_watchdog_timer
},
1813 [IPMI_CMD_SET_WATCHDOG_TIMER
] = { set_watchdog_timer
, 8 },
1814 [IPMI_CMD_GET_WATCHDOG_TIMER
] = { get_watchdog_timer
},
1816 static const IPMINetfn app_netfn
= {
1817 .cmd_nums
= ARRAY_SIZE(app_cmds
),
1818 .cmd_handlers
= app_cmds
1821 static const IPMICmdHandler storage_cmds
[] = {
1822 [IPMI_CMD_GET_FRU_AREA_INFO
] = { get_fru_area_info
, 3 },
1823 [IPMI_CMD_READ_FRU_DATA
] = { read_fru_data
, 5 },
1824 [IPMI_CMD_WRITE_FRU_DATA
] = { write_fru_data
, 5 },
1825 [IPMI_CMD_GET_SDR_REP_INFO
] = { get_sdr_rep_info
},
1826 [IPMI_CMD_RESERVE_SDR_REP
] = { reserve_sdr_rep
},
1827 [IPMI_CMD_GET_SDR
] = { get_sdr
, 8 },
1828 [IPMI_CMD_ADD_SDR
] = { add_sdr
},
1829 [IPMI_CMD_CLEAR_SDR_REP
] = { clear_sdr_rep
, 8 },
1830 [IPMI_CMD_GET_SEL_INFO
] = { get_sel_info
},
1831 [IPMI_CMD_RESERVE_SEL
] = { reserve_sel
},
1832 [IPMI_CMD_GET_SEL_ENTRY
] = { get_sel_entry
, 8 },
1833 [IPMI_CMD_ADD_SEL_ENTRY
] = { add_sel_entry
, 18 },
1834 [IPMI_CMD_CLEAR_SEL
] = { clear_sel
, 8 },
1835 [IPMI_CMD_GET_SEL_TIME
] = { get_sel_time
},
1836 [IPMI_CMD_SET_SEL_TIME
] = { set_sel_time
, 6 },
1839 static const IPMINetfn storage_netfn
= {
1840 .cmd_nums
= ARRAY_SIZE(storage_cmds
),
1841 .cmd_handlers
= storage_cmds
1844 static void register_cmds(IPMIBmcSim
*s
)
1846 ipmi_register_netfn(s
, IPMI_NETFN_CHASSIS
, &chassis_netfn
);
1847 ipmi_register_netfn(s
, IPMI_NETFN_SENSOR_EVENT
, &sensor_event_netfn
);
1848 ipmi_register_netfn(s
, IPMI_NETFN_APP
, &app_netfn
);
1849 ipmi_register_netfn(s
, IPMI_NETFN_STORAGE
, &storage_netfn
);
1852 static uint8_t init_sdrs
[] = {
1853 /* Watchdog device */
1854 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1855 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1856 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1858 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1861 static void ipmi_sdr_init(IPMIBmcSim
*ibs
)
1868 sdrs_size
= sizeof(init_sdrs
);
1870 if (ibs
->sdr_filename
&&
1871 !g_file_get_contents(ibs
->sdr_filename
, (gchar
**) &sdrs
, &sdrs_size
,
1873 error_report("failed to load sdr file '%s'", ibs
->sdr_filename
);
1874 sdrs_size
= sizeof(init_sdrs
);
1878 for (i
= 0; i
< sdrs_size
; i
+= len
) {
1879 struct ipmi_sdr_header
*sdrh
;
1881 if (i
+ IPMI_SDR_HEADER_SIZE
> sdrs_size
) {
1882 error_report("Problem with recid 0x%4.4x", i
);
1885 sdrh
= (struct ipmi_sdr_header
*) &sdrs
[i
];
1886 len
= ipmi_sdr_length(sdrh
);
1887 if (i
+ len
> sdrs_size
) {
1888 error_report("Problem with recid 0x%4.4x", i
);
1891 sdr_add_entry(ibs
, sdrh
, len
, NULL
);
1894 if (sdrs
!= init_sdrs
) {
1899 static const VMStateDescription vmstate_ipmi_sim
= {
1900 .name
= TYPE_IPMI_BMC_SIMULATOR
,
1902 .minimum_version_id
= 1,
1903 .fields
= (VMStateField
[]) {
1904 VMSTATE_UINT8(bmc_global_enables
, IPMIBmcSim
),
1905 VMSTATE_UINT8(msg_flags
, IPMIBmcSim
),
1906 VMSTATE_BOOL(watchdog_initialized
, IPMIBmcSim
),
1907 VMSTATE_UINT8(watchdog_use
, IPMIBmcSim
),
1908 VMSTATE_UINT8(watchdog_action
, IPMIBmcSim
),
1909 VMSTATE_UINT8(watchdog_pretimeout
, IPMIBmcSim
),
1910 VMSTATE_BOOL(watchdog_expired
, IPMIBmcSim
),
1911 VMSTATE_UINT16(watchdog_timeout
, IPMIBmcSim
),
1912 VMSTATE_BOOL(watchdog_running
, IPMIBmcSim
),
1913 VMSTATE_BOOL(watchdog_preaction_ran
, IPMIBmcSim
),
1914 VMSTATE_INT64(watchdog_expiry
, IPMIBmcSim
),
1915 VMSTATE_UINT8_ARRAY(evtbuf
, IPMIBmcSim
, 16),
1916 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].status
, IPMIBmcSim
),
1917 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].reading
, IPMIBmcSim
),
1918 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].states
, IPMIBmcSim
),
1919 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_states
, IPMIBmcSim
),
1920 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].deassert_states
,
1922 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_enable
, IPMIBmcSim
),
1923 VMSTATE_END_OF_LIST()
1927 static void ipmi_fru_init(IPMIFru
*fru
)
1932 if (!fru
->filename
) {
1936 fsize
= get_image_size(fru
->filename
);
1938 size
= QEMU_ALIGN_UP(fsize
, fru
->areasize
);
1939 fru
->data
= g_malloc0(size
);
1940 if (load_image_size(fru
->filename
, fru
->data
, fsize
) != fsize
) {
1941 error_report("Could not load file '%s'", fru
->filename
);
1949 /* give one default FRU */
1950 size
= fru
->areasize
;
1951 fru
->data
= g_malloc0(size
);
1954 fru
->nentries
= size
/ fru
->areasize
;
1957 static void ipmi_sim_realize(DeviceState
*dev
, Error
**errp
)
1959 IPMIBmc
*b
= IPMI_BMC(dev
);
1961 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
1963 QTAILQ_INIT(&ibs
->rcvbufs
);
1965 ibs
->bmc_global_enables
= (1 << IPMI_BMC_EVENT_LOG_BIT
);
1966 ibs
->device_id
= 0x20;
1967 ibs
->ipmi_version
= 0x02; /* IPMI 2.0 */
1968 ibs
->restart_cause
= 0;
1969 for (i
= 0; i
< 4; i
++) {
1970 ibs
->sel
.last_addition
[i
] = 0xff;
1971 ibs
->sel
.last_clear
[i
] = 0xff;
1972 ibs
->sdr
.last_addition
[i
] = 0xff;
1973 ibs
->sdr
.last_clear
[i
] = 0xff;
1978 ipmi_fru_init(&ibs
->fru
);
1980 ibs
->acpi_power_state
[0] = 0;
1981 ibs
->acpi_power_state
[1] = 0;
1983 if (qemu_uuid_set
) {
1984 memcpy(&ibs
->uuid
, &qemu_uuid
, 16);
1986 memset(&ibs
->uuid
, 0, 16);
1989 ipmi_init_sensors_from_sdrs(ibs
);
1992 ibs
->timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, ipmi_timeout
, ibs
);
1994 vmstate_register(NULL
, 0, &vmstate_ipmi_sim
, ibs
);
1997 static Property ipmi_sim_properties
[] = {
1998 DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim
, fru
.areasize
, 1024),
1999 DEFINE_PROP_STRING("frudatafile", IPMIBmcSim
, fru
.filename
),
2000 DEFINE_PROP_STRING("sdrfile", IPMIBmcSim
, sdr_filename
),
2001 DEFINE_PROP_UINT8("device_id", IPMIBmcSim
, device_id
, 0x20),
2002 DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim
, ipmi_version
, 0x02),
2003 DEFINE_PROP_UINT8("device_rev", IPMIBmcSim
, device_rev
, 0),
2004 DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim
, fwrev1
, 0),
2005 DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim
, fwrev2
, 0),
2006 DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim
, mfg_id
, 0),
2007 DEFINE_PROP_UINT16("product_id", IPMIBmcSim
, product_id
, 0),
2008 DEFINE_PROP_END_OF_LIST(),
2011 static void ipmi_sim_class_init(ObjectClass
*oc
, void *data
)
2013 DeviceClass
*dc
= DEVICE_CLASS(oc
);
2014 IPMIBmcClass
*bk
= IPMI_BMC_CLASS(oc
);
2016 dc
->hotpluggable
= false;
2017 dc
->realize
= ipmi_sim_realize
;
2018 dc
->props
= ipmi_sim_properties
;
2019 bk
->handle_command
= ipmi_sim_handle_command
;
2022 static const TypeInfo ipmi_sim_type
= {
2023 .name
= TYPE_IPMI_BMC_SIMULATOR
,
2024 .parent
= TYPE_IPMI_BMC
,
2025 .instance_size
= sizeof(IPMIBmcSim
),
2026 .class_init
= ipmi_sim_class_init
,
2029 static void ipmi_sim_register_types(void)
2031 type_register_static(&ipmi_sim_type
);
2034 type_init(ipmi_sim_register_types
)