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"
32 #include "hw/qdev-properties.h"
33 #include "hw/qdev-properties-system.h"
34 #include "migration/vmstate.h"
36 #define IPMI_NETFN_CHASSIS 0x00
38 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
39 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
40 #define IPMI_CMD_CHASSIS_CONTROL 0x02
41 #define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09
43 #define IPMI_NETFN_SENSOR_EVENT 0x04
45 #define IPMI_CMD_PLATFORM_EVENT_MSG 0x02
46 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
47 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
48 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
49 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
50 #define IPMI_CMD_GET_SENSOR_READING 0x2d
51 #define IPMI_CMD_SET_SENSOR_TYPE 0x2e
52 #define IPMI_CMD_GET_SENSOR_TYPE 0x2f
53 #define IPMI_CMD_SET_SENSOR_READING 0x30
55 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
57 #define IPMI_CMD_GET_DEVICE_ID 0x01
58 #define IPMI_CMD_COLD_RESET 0x02
59 #define IPMI_CMD_WARM_RESET 0x03
60 #define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
61 #define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
62 #define IPMI_CMD_GET_DEVICE_GUID 0x08
63 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
64 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
65 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
66 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
67 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
68 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
69 #define IPMI_CMD_GET_MSG_FLAGS 0x31
70 #define IPMI_CMD_GET_MSG 0x33
71 #define IPMI_CMD_SEND_MSG 0x34
72 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
74 #define IPMI_NETFN_STORAGE 0x0a
76 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
77 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
78 #define IPMI_CMD_RESERVE_SDR_REP 0x22
79 #define IPMI_CMD_GET_SDR 0x23
80 #define IPMI_CMD_ADD_SDR 0x24
81 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
82 #define IPMI_CMD_DELETE_SDR 0x26
83 #define IPMI_CMD_CLEAR_SDR_REP 0x27
84 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
85 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
86 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
87 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
88 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
89 #define IPMI_CMD_GET_FRU_AREA_INFO 0x10
90 #define IPMI_CMD_READ_FRU_DATA 0x11
91 #define IPMI_CMD_WRITE_FRU_DATA 0x12
92 #define IPMI_CMD_GET_SEL_INFO 0x40
93 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
94 #define IPMI_CMD_RESERVE_SEL 0x42
95 #define IPMI_CMD_GET_SEL_ENTRY 0x43
96 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
97 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
98 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
99 #define IPMI_CMD_CLEAR_SEL 0x47
100 #define IPMI_CMD_GET_SEL_TIME 0x48
101 #define IPMI_CMD_SET_SEL_TIME 0x49
104 /* Same as a timespec struct. */
110 #define MAX_SEL_SIZE 128
112 typedef struct IPMISel
{
113 uint8_t sel
[MAX_SEL_SIZE
][16];
114 unsigned int next_free
;
116 uint16_t reservation
;
117 uint8_t last_addition
[4];
118 uint8_t last_clear
[4];
122 #define MAX_SDR_SIZE 16384
124 typedef struct IPMISdr
{
125 uint8_t sdr
[MAX_SDR_SIZE
];
126 unsigned int next_free
;
127 uint16_t next_rec_id
;
128 uint16_t reservation
;
129 uint8_t last_addition
[4];
130 uint8_t last_clear
[4];
134 typedef struct IPMIFru
{
136 unsigned int nentries
;
141 typedef struct IPMISensor
{
144 uint16_t states_suppt
;
145 uint16_t assert_suppt
;
146 uint16_t deassert_suppt
;
148 uint16_t assert_states
;
149 uint16_t deassert_states
;
150 uint16_t assert_enable
;
151 uint16_t deassert_enable
;
153 uint8_t evt_reading_type_code
;
155 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
156 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
158 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
159 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
161 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
162 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
164 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
165 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
167 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
169 #define MAX_SENSORS 20
170 #define IPMI_WATCHDOG_SENSOR 0
172 #define MAX_NETFNS 64
174 typedef struct IPMIRcvBufEntry
{
175 QTAILQ_ENTRY(IPMIRcvBufEntry
) entry
;
177 uint8_t buf
[MAX_IPMI_MSG_SIZE
];
185 uint8_t bmc_global_enables
;
188 bool watchdog_initialized
;
189 uint8_t watchdog_use
;
190 uint8_t watchdog_action
;
191 uint8_t watchdog_pretimeout
; /* In seconds */
192 uint8_t watchdog_expired
;
193 uint16_t watchdog_timeout
; /* in 100's of milliseconds */
195 bool watchdog_running
;
196 bool watchdog_preaction_ran
;
197 int64_t watchdog_expiry
;
200 uint8_t ipmi_version
;
207 uint8_t restart_cause
;
209 uint8_t acpi_power_state
[2];
215 IPMISensor sensors
[MAX_SENSORS
];
218 /* Odd netfns are for responses, so we only need the even ones. */
219 const IPMINetfn
*netfns
[MAX_NETFNS
/ 2];
221 /* We allow one event in the buffer */
224 QTAILQ_HEAD(, IPMIRcvBufEntry
) rcvbufs
;
227 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
228 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
229 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
230 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
231 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
232 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
233 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
234 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
235 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
237 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
238 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
239 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
240 #define IPMI_BMC_EVENT_LOG_BIT 3
241 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
242 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
243 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
244 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
245 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
246 (1 << IPMI_BMC_EVENT_LOG_BIT))
247 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
248 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
250 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
251 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
252 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
253 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
254 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
255 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
256 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
257 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
258 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
259 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
260 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
261 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
262 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
263 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
264 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
266 #define RSP_BUFFER_INITIALIZER { }
268 static inline void rsp_buffer_pushmore(RspBuffer
*rsp
, uint8_t *bytes
,
271 if (rsp
->len
+ n
>= sizeof(rsp
->buffer
)) {
272 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
276 memcpy(&rsp
->buffer
[rsp
->len
], bytes
, n
);
280 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
);
282 static void ipmi_gettime(struct ipmi_time
*time
)
286 stime
= qemu_clock_get_ns(QEMU_CLOCK_HOST
);
287 time
->tv_sec
= stime
/ 1000000000LL;
288 time
->tv_nsec
= stime
% 1000000000LL;
291 static int64_t ipmi_getmonotime(void)
293 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
296 static void ipmi_timeout(void *opaque
)
298 IPMIBmcSim
*ibs
= opaque
;
300 ipmi_sim_handle_timeout(ibs
);
303 static void set_timestamp(IPMIBmcSim
*ibs
, uint8_t *ts
)
306 struct ipmi_time now
;
309 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
311 ts
[1] = (val
>> 8) & 0xff;
312 ts
[2] = (val
>> 16) & 0xff;
313 ts
[3] = (val
>> 24) & 0xff;
316 static void sdr_inc_reservation(IPMISdr
*sdr
)
319 if (sdr
->reservation
== 0) {
320 sdr
->reservation
= 1;
324 static int sdr_add_entry(IPMIBmcSim
*ibs
,
325 const struct ipmi_sdr_header
*sdrh_entry
,
326 unsigned int len
, uint16_t *recid
)
328 struct ipmi_sdr_header
*sdrh
=
329 (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[ibs
->sdr
.next_free
];
331 if ((len
< IPMI_SDR_HEADER_SIZE
) || (len
> 255)) {
335 if (ipmi_sdr_length(sdrh_entry
) != len
) {
339 if (ibs
->sdr
.next_free
+ len
> MAX_SDR_SIZE
) {
340 ibs
->sdr
.overflow
= 1;
344 memcpy(sdrh
, sdrh_entry
, len
);
345 sdrh
->rec_id
[0] = ibs
->sdr
.next_rec_id
& 0xff;
346 sdrh
->rec_id
[1] = (ibs
->sdr
.next_rec_id
>> 8) & 0xff;
347 sdrh
->sdr_version
= 0x51; /* Conform to IPMI 1.5 spec */
350 *recid
= ibs
->sdr
.next_rec_id
;
352 ibs
->sdr
.next_rec_id
++;
353 set_timestamp(ibs
, ibs
->sdr
.last_addition
);
354 ibs
->sdr
.next_free
+= len
;
355 sdr_inc_reservation(&ibs
->sdr
);
359 static int sdr_find_entry(IPMISdr
*sdr
, uint16_t recid
,
360 unsigned int *retpos
, uint16_t *nextrec
)
362 unsigned int pos
= *retpos
;
364 while (pos
< sdr
->next_free
) {
365 struct ipmi_sdr_header
*sdrh
=
366 (struct ipmi_sdr_header
*) &sdr
->sdr
[pos
];
367 uint16_t trec
= ipmi_sdr_recid(sdrh
);
368 unsigned int nextpos
= pos
+ ipmi_sdr_length(sdrh
);
372 if (nextpos
>= sdr
->next_free
) {
375 *nextrec
= (sdr
->sdr
[nextpos
] |
376 (sdr
->sdr
[nextpos
+ 1] << 8));
387 int ipmi_bmc_sdr_find(IPMIBmc
*b
, uint16_t recid
,
388 const struct ipmi_sdr_compact
**sdr
, uint16_t *nextrec
)
391 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
395 if (sdr_find_entry(&ibs
->sdr
, recid
, &pos
, nextrec
)) {
399 *sdr
= (const struct ipmi_sdr_compact
*) &ibs
->sdr
.sdr
[pos
];
403 static void sel_inc_reservation(IPMISel
*sel
)
406 if (sel
->reservation
== 0) {
407 sel
->reservation
= 1;
411 /* Returns 1 if the SEL is full and can't hold the event. */
412 static int sel_add_event(IPMIBmcSim
*ibs
, uint8_t *event
)
418 set_timestamp(ibs
, ts
);
419 if (event
[2] < 0xe0) { /* Don't set timestamps for type 0xe0-0xff. */
420 memcpy(event
+ 3, ts
, 4);
422 if (ibs
->sel
.next_free
== MAX_SEL_SIZE
) {
423 ibs
->sel
.overflow
= 1;
426 event
[0] = ibs
->sel
.next_free
& 0xff;
427 event
[1] = (ibs
->sel
.next_free
>> 8) & 0xff;
428 memcpy(ibs
->sel
.last_addition
, ts
, 4);
429 memcpy(ibs
->sel
.sel
[ibs
->sel
.next_free
], event
, 16);
430 ibs
->sel
.next_free
++;
431 sel_inc_reservation(&ibs
->sel
);
435 static int attn_set(IPMIBmcSim
*ibs
)
437 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
)
438 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
)
439 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs
);
442 static int attn_irq_enabled(IPMIBmcSim
*ibs
)
444 return (IPMI_BMC_MSG_INTS_ON(ibs
) &&
445 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
) ||
446 IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs
)))
447 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs
) &&
448 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
));
451 void ipmi_bmc_gen_event(IPMIBmc
*b
, uint8_t *evt
, bool log
)
453 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
454 IPMIInterface
*s
= ibs
->parent
.intf
;
455 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
457 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
461 if (log
&& IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
462 sel_add_event(ibs
, evt
);
465 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
469 memcpy(ibs
->evtbuf
, evt
, 16);
470 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
471 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
475 static void gen_event(IPMIBmcSim
*ibs
, unsigned int sens_num
, uint8_t deassert
,
476 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
478 IPMIInterface
*s
= ibs
->parent
.intf
;
479 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
481 IPMISensor
*sens
= ibs
->sensors
+ sens_num
;
483 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
486 if (!IPMI_SENSOR_GET_EVENTS_ON(sens
)) {
490 evt
[2] = 0x2; /* System event record */
491 evt
[7] = ibs
->parent
.slave_addr
;
493 evt
[9] = 0x04; /* Format version */
494 evt
[10] = sens
->sensor_type
;
496 evt
[12] = sens
->evt_reading_type_code
| (!!deassert
<< 7);
501 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
502 sel_add_event(ibs
, evt
);
505 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
509 memcpy(ibs
->evtbuf
, evt
, 16);
510 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
511 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
514 static void sensor_set_discrete_bit(IPMIBmcSim
*ibs
, unsigned int sensor
,
515 unsigned int bit
, unsigned int val
,
516 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
521 if (sensor
>= MAX_SENSORS
) {
529 sens
= ibs
->sensors
+ sensor
;
531 sens
->states
|= mask
& sens
->states_suppt
;
532 if (sens
->assert_states
& mask
) {
533 return; /* Already asserted */
535 sens
->assert_states
|= mask
& sens
->assert_suppt
;
536 if (sens
->assert_enable
& mask
& sens
->assert_states
) {
537 /* Send an event on assert */
538 gen_event(ibs
, sensor
, 0, evd1
, evd2
, evd3
);
541 sens
->states
&= ~(mask
& sens
->states_suppt
);
542 if (sens
->deassert_states
& mask
) {
543 return; /* Already deasserted */
545 sens
->deassert_states
|= mask
& sens
->deassert_suppt
;
546 if (sens
->deassert_enable
& mask
& sens
->deassert_states
) {
547 /* Send an event on deassert */
548 gen_event(ibs
, sensor
, 1, evd1
, evd2
, evd3
);
553 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim
*s
)
558 for (i
= 0; i
< MAX_SENSORS
; i
++) {
559 memset(s
->sensors
+ i
, 0, sizeof(*sens
));
563 for (i
= 0; !sdr_find_entry(&s
->sdr
, i
, &pos
, NULL
); i
++) {
564 struct ipmi_sdr_compact
*sdr
=
565 (struct ipmi_sdr_compact
*) &s
->sdr
.sdr
[pos
];
566 unsigned int len
= sdr
->header
.rec_length
;
571 if (sdr
->header
.rec_type
!= IPMI_SDR_COMPACT_TYPE
) {
572 continue; /* Not a sensor SDR we set from */
575 if (sdr
->sensor_owner_number
>= MAX_SENSORS
) {
578 sens
= s
->sensors
+ sdr
->sensor_owner_number
;
580 IPMI_SENSOR_SET_PRESENT(sens
, 1);
581 IPMI_SENSOR_SET_SCAN_ON(sens
, (sdr
->sensor_init
>> 6) & 1);
582 IPMI_SENSOR_SET_EVENTS_ON(sens
, (sdr
->sensor_init
>> 5) & 1);
583 sens
->assert_suppt
= sdr
->assert_mask
[0] | (sdr
->assert_mask
[1] << 8);
584 sens
->deassert_suppt
=
585 sdr
->deassert_mask
[0] | (sdr
->deassert_mask
[1] << 8);
587 sdr
->discrete_mask
[0] | (sdr
->discrete_mask
[1] << 8);
588 sens
->sensor_type
= sdr
->sensor_type
;
589 sens
->evt_reading_type_code
= sdr
->reading_type
& 0x7f;
591 /* Enable all the events that are supported. */
592 sens
->assert_enable
= sens
->assert_suppt
;
593 sens
->deassert_enable
= sens
->deassert_suppt
;
597 int ipmi_sim_register_netfn(IPMIBmcSim
*s
, unsigned int netfn
,
598 const IPMINetfn
*netfnd
)
600 if ((netfn
& 1) || (netfn
>= MAX_NETFNS
) || (s
->netfns
[netfn
/ 2])) {
603 s
->netfns
[netfn
/ 2] = netfnd
;
607 static const IPMICmdHandler
*ipmi_get_handler(IPMIBmcSim
*ibs
,
611 const IPMICmdHandler
*hdl
;
613 if (netfn
& 1 || netfn
>= MAX_NETFNS
|| !ibs
->netfns
[netfn
/ 2]) {
617 if (cmd
>= ibs
->netfns
[netfn
/ 2]->cmd_nums
) {
621 hdl
= &ibs
->netfns
[netfn
/ 2]->cmd_handlers
[cmd
];
622 if (!hdl
->cmd_handler
) {
629 static void next_timeout(IPMIBmcSim
*ibs
)
632 if (ibs
->watchdog_running
) {
633 next
= ibs
->watchdog_expiry
;
636 next
= ipmi_getmonotime() + 60 * 1000000000LL;
638 timer_mod_ns(ibs
->timer
, next
);
641 static void ipmi_sim_handle_command(IPMIBmc
*b
,
642 uint8_t *cmd
, unsigned int cmd_len
,
643 unsigned int max_cmd_len
,
646 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
647 IPMIInterface
*s
= ibs
->parent
.intf
;
648 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
649 const IPMICmdHandler
*hdl
;
650 RspBuffer rsp
= RSP_BUFFER_INITIALIZER
;
652 /* Set up the response, set the low bit of NETFN. */
653 /* Note that max_rsp_len must be at least 3 */
654 if (sizeof(rsp
.buffer
) < 3) {
655 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
659 rsp_buffer_push(&rsp
, cmd
[0] | 0x04);
660 rsp_buffer_push(&rsp
, cmd
[1]);
661 rsp_buffer_push(&rsp
, 0); /* Assume success */
663 /* If it's too short or it was truncated, return an error. */
665 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
668 if (cmd_len
> max_cmd_len
) {
669 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
673 if ((cmd
[0] & 0x03) != 0) {
674 /* Only have stuff on LUN 0 */
675 rsp_buffer_set_error(&rsp
, IPMI_CC_COMMAND_INVALID_FOR_LUN
);
679 hdl
= ipmi_get_handler(ibs
, cmd
[0] >> 2, cmd
[1]);
681 rsp_buffer_set_error(&rsp
, IPMI_CC_INVALID_CMD
);
685 if (cmd_len
< hdl
->cmd_len_min
) {
686 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
690 hdl
->cmd_handler(ibs
, cmd
, cmd_len
, &rsp
);
693 k
->handle_rsp(s
, msg_id
, rsp
.buffer
, rsp
.len
);
698 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
)
700 IPMIInterface
*s
= ibs
->parent
.intf
;
701 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
703 if (!ibs
->watchdog_running
) {
707 if (!ibs
->watchdog_preaction_ran
) {
708 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
)) {
709 case IPMI_BMC_WATCHDOG_PRE_NMI
:
710 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
711 k
->do_hw_op(s
, IPMI_SEND_NMI
, 0);
712 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
713 0xc8, (2 << 4) | 0xf, 0xff);
716 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
717 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
718 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
719 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
720 0xc8, (3 << 4) | 0xf, 0xff);
727 ibs
->watchdog_preaction_ran
= 1;
728 /* Issued the pretimeout, do the rest of the timeout now. */
729 ibs
->watchdog_expiry
= ipmi_getmonotime();
730 ibs
->watchdog_expiry
+= ibs
->watchdog_pretimeout
* 1000000000LL;
735 ibs
->watchdog_running
= 0; /* Stop the watchdog on a timeout */
736 ibs
->watchdog_expired
|= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs
));
737 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
)) {
738 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
739 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 0, 1,
740 0xc0, ibs
->watchdog_use
& 0xf, 0xff);
743 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
744 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 1, 1,
745 0xc1, ibs
->watchdog_use
& 0xf, 0xff);
746 k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0);
749 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
750 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
751 0xc2, ibs
->watchdog_use
& 0xf, 0xff);
752 k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0);
755 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
756 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
757 0xc3, ibs
->watchdog_use
& 0xf, 0xff);
758 k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0);
766 static void chassis_capabilities(IPMIBmcSim
*ibs
,
767 uint8_t *cmd
, unsigned int cmd_len
,
770 rsp_buffer_push(rsp
, 0);
771 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
772 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
773 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
774 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
777 static void chassis_status(IPMIBmcSim
*ibs
,
778 uint8_t *cmd
, unsigned int cmd_len
,
781 rsp_buffer_push(rsp
, 0x61); /* Unknown power restore, power is on */
782 rsp_buffer_push(rsp
, 0);
783 rsp_buffer_push(rsp
, 0);
784 rsp_buffer_push(rsp
, 0);
787 static void chassis_control(IPMIBmcSim
*ibs
,
788 uint8_t *cmd
, unsigned int cmd_len
,
791 IPMIInterface
*s
= ibs
->parent
.intf
;
792 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
794 switch (cmd
[2] & 0xf) {
795 case 0: /* power down */
796 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0));
798 case 1: /* power up */
799 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERON_CHASSIS
, 0));
801 case 2: /* power cycle */
802 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0));
804 case 3: /* hard reset */
805 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0));
807 case 4: /* pulse diagnostic interrupt */
808 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_PULSE_DIAG_IRQ
, 0));
810 case 5: /* soft shutdown via ACPI by overtemp emulation */
811 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
,
812 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP
, 0));
815 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
820 static void chassis_get_sys_restart_cause(IPMIBmcSim
*ibs
,
821 uint8_t *cmd
, unsigned int cmd_len
,
825 rsp_buffer_push(rsp
, ibs
->restart_cause
& 0xf); /* Restart Cause */
826 rsp_buffer_push(rsp
, 0); /* Channel 0 */
829 static void get_device_id(IPMIBmcSim
*ibs
,
830 uint8_t *cmd
, unsigned int cmd_len
,
833 rsp_buffer_push(rsp
, ibs
->device_id
);
834 rsp_buffer_push(rsp
, ibs
->device_rev
& 0xf);
835 rsp_buffer_push(rsp
, ibs
->fwrev1
& 0x7f);
836 rsp_buffer_push(rsp
, ibs
->fwrev2
);
837 rsp_buffer_push(rsp
, ibs
->ipmi_version
);
838 rsp_buffer_push(rsp
, 0x07); /* sensor, SDR, and SEL. */
839 rsp_buffer_push(rsp
, ibs
->mfg_id
& 0xff);
840 rsp_buffer_push(rsp
, (ibs
->mfg_id
>> 8) & 0xff);
841 rsp_buffer_push(rsp
, (ibs
->mfg_id
>> 16) & 0xff);
842 rsp_buffer_push(rsp
, ibs
->product_id
& 0xff);
843 rsp_buffer_push(rsp
, (ibs
->product_id
>> 8) & 0xff);
846 static void set_global_enables(IPMIBmcSim
*ibs
, uint8_t val
)
848 IPMIInterface
*s
= ibs
->parent
.intf
;
849 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
852 ibs
->bmc_global_enables
= val
;
854 irqs_on
= val
& (IPMI_BMC_EVBUF_FULL_INT_BIT
|
855 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT
);
857 k
->set_irq_enable(s
, irqs_on
);
860 static void cold_reset(IPMIBmcSim
*ibs
,
861 uint8_t *cmd
, unsigned int cmd_len
,
864 IPMIInterface
*s
= ibs
->parent
.intf
;
865 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
867 /* Disable all interrupts */
868 set_global_enables(ibs
, 1 << IPMI_BMC_EVENT_LOG_BIT
);
875 static void warm_reset(IPMIBmcSim
*ibs
,
876 uint8_t *cmd
, unsigned int cmd_len
,
879 IPMIInterface
*s
= ibs
->parent
.intf
;
880 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
886 static void set_acpi_power_state(IPMIBmcSim
*ibs
,
887 uint8_t *cmd
, unsigned int cmd_len
,
890 ibs
->acpi_power_state
[0] = cmd
[2];
891 ibs
->acpi_power_state
[1] = cmd
[3];
894 static void get_acpi_power_state(IPMIBmcSim
*ibs
,
895 uint8_t *cmd
, unsigned int cmd_len
,
898 rsp_buffer_push(rsp
, ibs
->acpi_power_state
[0]);
899 rsp_buffer_push(rsp
, ibs
->acpi_power_state
[1]);
902 static void get_device_guid(IPMIBmcSim
*ibs
,
903 uint8_t *cmd
, unsigned int cmd_len
,
908 /* An uninitialized uuid is all zeros, use that to know if it is set. */
909 for (i
= 0; i
< 16; i
++) {
910 if (ibs
->uuid
.data
[i
]) {
914 /* No uuid is set, return an error. */
915 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_CMD
);
919 for (i
= 0; i
< 16; i
++) {
920 rsp_buffer_push(rsp
, ibs
->uuid
.data
[i
]);
924 static void set_bmc_global_enables(IPMIBmcSim
*ibs
,
925 uint8_t *cmd
, unsigned int cmd_len
,
928 set_global_enables(ibs
, cmd
[2]);
931 static void get_bmc_global_enables(IPMIBmcSim
*ibs
,
932 uint8_t *cmd
, unsigned int cmd_len
,
935 rsp_buffer_push(rsp
, ibs
->bmc_global_enables
);
938 static void clr_msg_flags(IPMIBmcSim
*ibs
,
939 uint8_t *cmd
, unsigned int cmd_len
,
942 IPMIInterface
*s
= ibs
->parent
.intf
;
943 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
945 ibs
->msg_flags
&= ~cmd
[2];
946 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
949 static void get_msg_flags(IPMIBmcSim
*ibs
,
950 uint8_t *cmd
, unsigned int cmd_len
,
953 rsp_buffer_push(rsp
, ibs
->msg_flags
);
956 static void read_evt_msg_buf(IPMIBmcSim
*ibs
,
957 uint8_t *cmd
, unsigned int cmd_len
,
960 IPMIInterface
*s
= ibs
->parent
.intf
;
961 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
964 if (!(ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
)) {
965 rsp_buffer_set_error(rsp
, 0x80);
968 for (i
= 0; i
< 16; i
++) {
969 rsp_buffer_push(rsp
, ibs
->evtbuf
[i
]);
971 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
972 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
975 static void get_msg(IPMIBmcSim
*ibs
,
976 uint8_t *cmd
, unsigned int cmd_len
,
979 IPMIRcvBufEntry
*msg
;
981 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
982 rsp_buffer_set_error(rsp
, 0x80); /* Queue empty */
985 rsp_buffer_push(rsp
, 0); /* Channel 0 */
986 msg
= QTAILQ_FIRST(&ibs
->rcvbufs
);
987 rsp_buffer_pushmore(rsp
, msg
->buf
, msg
->len
);
988 QTAILQ_REMOVE(&ibs
->rcvbufs
, msg
, entry
);
991 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
992 IPMIInterface
*s
= ibs
->parent
.intf
;
993 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
995 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
996 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
1003 static unsigned char
1004 ipmb_checksum(unsigned char *data
, int size
, unsigned char csum
)
1006 for (; size
> 0; size
--, data
++) {
1013 static void send_msg(IPMIBmcSim
*ibs
,
1014 uint8_t *cmd
, unsigned int cmd_len
,
1017 IPMIInterface
*s
= ibs
->parent
.intf
;
1018 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1019 IPMIRcvBufEntry
*msg
;
1021 uint8_t netfn
, rqLun
, rsLun
, rqSeq
;
1024 /* We only handle channel 0 with no options */
1025 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1030 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
1034 if (cmd
[3] != 0x40) {
1035 /* We only emulate a MC at address 0x40. */
1036 rsp_buffer_set_error(rsp
, 0x83); /* NAK on write */
1040 cmd
+= 3; /* Skip the header. */
1044 * At this point we "send" the message successfully. Any error will
1045 * be returned in the response.
1047 if (ipmb_checksum(cmd
, cmd_len
, 0) != 0 ||
1048 cmd
[3] != 0x20) { /* Improper response address */
1049 return; /* No response */
1052 netfn
= cmd
[1] >> 2;
1053 rqLun
= cmd
[4] & 0x3;
1054 rsLun
= cmd
[1] & 0x3;
1055 rqSeq
= cmd
[4] >> 2;
1058 /* We only support LUN 2 coming back to us. */
1062 msg
= g_malloc(sizeof(*msg
));
1063 msg
->buf
[0] = ((netfn
| 1) << 2) | rqLun
; /* NetFN, and make a response */
1064 msg
->buf
[1] = ipmb_checksum(msg
->buf
, 1, 0);
1065 msg
->buf
[2] = cmd
[0]; /* rsSA */
1066 msg
->buf
[3] = (rqSeq
<< 2) | rsLun
;
1067 msg
->buf
[4] = cmd
[5]; /* Cmd */
1068 msg
->buf
[5] = 0; /* Completion Code */
1071 if ((cmd
[1] >> 2) != IPMI_NETFN_APP
|| cmd
[5] != IPMI_CMD_GET_DEVICE_ID
) {
1072 /* Not a command we handle. */
1073 msg
->buf
[5] = IPMI_CC_INVALID_CMD
;
1077 buf
= msg
->buf
+ msg
->len
; /* After the CC */
1092 msg
->buf
[msg
->len
] = ipmb_checksum(msg
->buf
, msg
->len
, 0);
1094 QTAILQ_INSERT_TAIL(&ibs
->rcvbufs
, msg
, entry
);
1095 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
1096 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
1099 static void do_watchdog_reset(IPMIBmcSim
*ibs
)
1101 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
) ==
1102 IPMI_BMC_WATCHDOG_ACTION_NONE
) {
1103 ibs
->watchdog_running
= 0;
1106 ibs
->watchdog_preaction_ran
= 0;
1109 /* Timeout is in tenths of a second, offset is in seconds */
1110 ibs
->watchdog_expiry
= ipmi_getmonotime();
1111 ibs
->watchdog_expiry
+= ibs
->watchdog_timeout
* 100000000LL;
1112 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
) != IPMI_BMC_WATCHDOG_PRE_NONE
) {
1113 ibs
->watchdog_expiry
-= ibs
->watchdog_pretimeout
* 1000000000LL;
1115 ibs
->watchdog_running
= 1;
1118 static void reset_watchdog_timer(IPMIBmcSim
*ibs
,
1119 uint8_t *cmd
, unsigned int cmd_len
,
1122 if (!ibs
->watchdog_initialized
) {
1123 rsp_buffer_set_error(rsp
, 0x80);
1126 do_watchdog_reset(ibs
);
1129 static void set_watchdog_timer(IPMIBmcSim
*ibs
,
1130 uint8_t *cmd
, unsigned int cmd_len
,
1133 IPMIInterface
*s
= ibs
->parent
.intf
;
1134 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1137 val
= cmd
[2] & 0x7; /* Validate use */
1138 if (val
== 0 || val
> 5) {
1139 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1142 val
= cmd
[3] & 0x7; /* Validate action */
1144 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
1147 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
1148 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 1));
1151 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
1152 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 1));
1155 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
1156 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 1));
1160 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1162 if (rsp
->buffer
[2]) {
1163 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1167 val
= (cmd
[3] >> 4) & 0x7; /* Validate preaction */
1169 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
1170 case IPMI_BMC_WATCHDOG_PRE_NONE
:
1173 case IPMI_BMC_WATCHDOG_PRE_NMI
:
1174 if (k
->do_hw_op(s
, IPMI_SEND_NMI
, 1)) {
1175 /* NMI not supported. */
1176 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1182 /* We don't support PRE_SMI */
1183 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1187 ibs
->watchdog_initialized
= 1;
1188 ibs
->watchdog_use
= cmd
[2] & IPMI_BMC_WATCHDOG_USE_MASK
;
1189 ibs
->watchdog_action
= cmd
[3] & IPMI_BMC_WATCHDOG_ACTION_MASK
;
1190 ibs
->watchdog_pretimeout
= cmd
[4];
1191 ibs
->watchdog_expired
&= ~cmd
[5];
1192 ibs
->watchdog_timeout
= cmd
[6] | (((uint16_t) cmd
[7]) << 8);
1193 if (ibs
->watchdog_running
& IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs
)) {
1194 do_watchdog_reset(ibs
);
1196 ibs
->watchdog_running
= 0;
1200 static void get_watchdog_timer(IPMIBmcSim
*ibs
,
1201 uint8_t *cmd
, unsigned int cmd_len
,
1204 rsp_buffer_push(rsp
, ibs
->watchdog_use
);
1205 rsp_buffer_push(rsp
, ibs
->watchdog_action
);
1206 rsp_buffer_push(rsp
, ibs
->watchdog_pretimeout
);
1207 rsp_buffer_push(rsp
, ibs
->watchdog_expired
);
1208 rsp_buffer_push(rsp
, ibs
->watchdog_timeout
& 0xff);
1209 rsp_buffer_push(rsp
, (ibs
->watchdog_timeout
>> 8) & 0xff);
1210 if (ibs
->watchdog_running
) {
1212 timeout
= ((ibs
->watchdog_expiry
- ipmi_getmonotime() + 50000000)
1214 rsp_buffer_push(rsp
, timeout
& 0xff);
1215 rsp_buffer_push(rsp
, (timeout
>> 8) & 0xff);
1217 rsp_buffer_push(rsp
, 0);
1218 rsp_buffer_push(rsp
, 0);
1222 static void get_sdr_rep_info(IPMIBmcSim
*ibs
,
1223 uint8_t *cmd
, unsigned int cmd_len
,
1228 rsp_buffer_push(rsp
, 0x51); /* Conform to IPMI 1.5 spec */
1229 rsp_buffer_push(rsp
, ibs
->sdr
.next_rec_id
& 0xff);
1230 rsp_buffer_push(rsp
, (ibs
->sdr
.next_rec_id
>> 8) & 0xff);
1231 rsp_buffer_push(rsp
, (MAX_SDR_SIZE
- ibs
->sdr
.next_free
) & 0xff);
1232 rsp_buffer_push(rsp
, ((MAX_SDR_SIZE
- ibs
->sdr
.next_free
) >> 8) & 0xff);
1233 for (i
= 0; i
< 4; i
++) {
1234 rsp_buffer_push(rsp
, ibs
->sdr
.last_addition
[i
]);
1236 for (i
= 0; i
< 4; i
++) {
1237 rsp_buffer_push(rsp
, ibs
->sdr
.last_clear
[i
]);
1239 /* Only modal support, reserve supported */
1240 rsp_buffer_push(rsp
, (ibs
->sdr
.overflow
<< 7) | 0x22);
1243 static void reserve_sdr_rep(IPMIBmcSim
*ibs
,
1244 uint8_t *cmd
, unsigned int cmd_len
,
1247 rsp_buffer_push(rsp
, ibs
->sdr
.reservation
& 0xff);
1248 rsp_buffer_push(rsp
, (ibs
->sdr
.reservation
>> 8) & 0xff);
1251 static void get_sdr(IPMIBmcSim
*ibs
,
1252 uint8_t *cmd
, unsigned int cmd_len
,
1257 struct ipmi_sdr_header
*sdrh
;
1260 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sdr
.reservation
) {
1261 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1267 if (sdr_find_entry(&ibs
->sdr
, cmd
[4] | (cmd
[5] << 8),
1269 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1273 sdrh
= (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[pos
];
1275 if (cmd
[6] > ipmi_sdr_length(sdrh
)) {
1276 rsp_buffer_set_error(rsp
, IPMI_CC_PARM_OUT_OF_RANGE
);
1280 rsp_buffer_push(rsp
, nextrec
& 0xff);
1281 rsp_buffer_push(rsp
, (nextrec
>> 8) & 0xff);
1283 if (cmd
[7] == 0xff) {
1284 cmd
[7] = ipmi_sdr_length(sdrh
) - cmd
[6];
1287 if ((cmd
[7] + rsp
->len
) > sizeof(rsp
->buffer
)) {
1288 rsp_buffer_set_error(rsp
, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES
);
1292 rsp_buffer_pushmore(rsp
, ibs
->sdr
.sdr
+ pos
+ cmd
[6], cmd
[7]);
1295 static void add_sdr(IPMIBmcSim
*ibs
,
1296 uint8_t *cmd
, unsigned int cmd_len
,
1300 struct ipmi_sdr_header
*sdrh
= (struct ipmi_sdr_header
*) cmd
+ 2;
1302 if (sdr_add_entry(ibs
, sdrh
, cmd_len
- 2, &recid
)) {
1303 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1306 rsp_buffer_push(rsp
, recid
& 0xff);
1307 rsp_buffer_push(rsp
, (recid
>> 8) & 0xff);
1310 static void clear_sdr_rep(IPMIBmcSim
*ibs
,
1311 uint8_t *cmd
, unsigned int cmd_len
,
1314 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sdr
.reservation
) {
1315 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1319 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1320 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1323 if (cmd
[7] == 0xaa) {
1324 ibs
->sdr
.next_free
= 0;
1325 ibs
->sdr
.overflow
= 0;
1326 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1327 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1328 sdr_inc_reservation(&ibs
->sdr
);
1329 } else if (cmd
[7] == 0) {
1330 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1332 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1337 static void get_sel_info(IPMIBmcSim
*ibs
,
1338 uint8_t *cmd
, unsigned int cmd_len
,
1341 unsigned int i
, val
;
1343 rsp_buffer_push(rsp
, 0x51); /* Conform to IPMI 1.5 */
1344 rsp_buffer_push(rsp
, ibs
->sel
.next_free
& 0xff);
1345 rsp_buffer_push(rsp
, (ibs
->sel
.next_free
>> 8) & 0xff);
1346 val
= (MAX_SEL_SIZE
- ibs
->sel
.next_free
) * 16;
1347 rsp_buffer_push(rsp
, val
& 0xff);
1348 rsp_buffer_push(rsp
, (val
>> 8) & 0xff);
1349 for (i
= 0; i
< 4; i
++) {
1350 rsp_buffer_push(rsp
, ibs
->sel
.last_addition
[i
]);
1352 for (i
= 0; i
< 4; i
++) {
1353 rsp_buffer_push(rsp
, ibs
->sel
.last_clear
[i
]);
1355 /* Only support Reserve SEL */
1356 rsp_buffer_push(rsp
, (ibs
->sel
.overflow
<< 7) | 0x02);
1359 static void get_fru_area_info(IPMIBmcSim
*ibs
,
1360 uint8_t *cmd
, unsigned int cmd_len
,
1364 uint16_t fru_entry_size
;
1368 if (fruid
>= ibs
->fru
.nentries
) {
1369 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1373 fru_entry_size
= ibs
->fru
.areasize
;
1375 rsp_buffer_push(rsp
, fru_entry_size
& 0xff);
1376 rsp_buffer_push(rsp
, fru_entry_size
>> 8 & 0xff);
1377 rsp_buffer_push(rsp
, 0x0);
1380 static void read_fru_data(IPMIBmcSim
*ibs
,
1381 uint8_t *cmd
, unsigned int cmd_len
,
1391 offset
= (cmd
[3] | cmd
[4] << 8);
1393 if (fruid
>= ibs
->fru
.nentries
) {
1394 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1398 if (offset
>= ibs
->fru
.areasize
- 1) {
1399 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1403 fru_entry
= &ibs
->fru
.data
[fruid
* ibs
->fru
.areasize
];
1405 count
= MIN(cmd
[5], ibs
->fru
.areasize
- offset
);
1407 rsp_buffer_push(rsp
, count
& 0xff);
1408 for (i
= 0; i
< count
; i
++) {
1409 rsp_buffer_push(rsp
, fru_entry
[offset
+ i
]);
1413 static void write_fru_data(IPMIBmcSim
*ibs
,
1414 uint8_t *cmd
, unsigned int cmd_len
,
1423 offset
= (cmd
[3] | cmd
[4] << 8);
1425 if (fruid
>= ibs
->fru
.nentries
) {
1426 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1430 if (offset
>= ibs
->fru
.areasize
- 1) {
1431 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1435 fru_entry
= &ibs
->fru
.data
[fruid
* ibs
->fru
.areasize
];
1437 count
= MIN(cmd_len
- 5, ibs
->fru
.areasize
- offset
);
1439 memcpy(fru_entry
+ offset
, cmd
+ 5, count
);
1441 rsp_buffer_push(rsp
, count
& 0xff);
1444 static void reserve_sel(IPMIBmcSim
*ibs
,
1445 uint8_t *cmd
, unsigned int cmd_len
,
1448 rsp_buffer_push(rsp
, ibs
->sel
.reservation
& 0xff);
1449 rsp_buffer_push(rsp
, (ibs
->sel
.reservation
>> 8) & 0xff);
1452 static void get_sel_entry(IPMIBmcSim
*ibs
,
1453 uint8_t *cmd
, unsigned int cmd_len
,
1459 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sel
.reservation
) {
1460 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1464 if (ibs
->sel
.next_free
== 0) {
1465 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1469 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1472 if (cmd
[7] == 0xff) {
1474 } else if ((cmd
[7] + cmd
[6]) > 16) {
1475 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1481 val
= cmd
[4] | (cmd
[5] << 8);
1482 if (val
== 0xffff) {
1483 val
= ibs
->sel
.next_free
- 1;
1484 } else if (val
>= ibs
->sel
.next_free
) {
1485 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1488 if ((val
+ 1) == ibs
->sel
.next_free
) {
1489 rsp_buffer_push(rsp
, 0xff);
1490 rsp_buffer_push(rsp
, 0xff);
1492 rsp_buffer_push(rsp
, (val
+ 1) & 0xff);
1493 rsp_buffer_push(rsp
, ((val
+ 1) >> 8) & 0xff);
1495 for (; cmd
[6] < cmd
[7]; cmd
[6]++) {
1496 rsp_buffer_push(rsp
, ibs
->sel
.sel
[val
][cmd
[6]]);
1500 static void add_sel_entry(IPMIBmcSim
*ibs
,
1501 uint8_t *cmd
, unsigned int cmd_len
,
1504 if (sel_add_event(ibs
, cmd
+ 2)) {
1505 rsp_buffer_set_error(rsp
, IPMI_CC_OUT_OF_SPACE
);
1508 /* sel_add_event fills in the record number. */
1509 rsp_buffer_push(rsp
, cmd
[2]);
1510 rsp_buffer_push(rsp
, cmd
[3]);
1513 static void clear_sel(IPMIBmcSim
*ibs
,
1514 uint8_t *cmd
, unsigned int cmd_len
,
1517 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sel
.reservation
) {
1518 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1522 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1523 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1526 if (cmd
[7] == 0xaa) {
1527 ibs
->sel
.next_free
= 0;
1528 ibs
->sel
.overflow
= 0;
1529 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1530 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1531 sel_inc_reservation(&ibs
->sel
);
1532 } else if (cmd
[7] == 0) {
1533 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1535 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1540 static void get_sel_time(IPMIBmcSim
*ibs
,
1541 uint8_t *cmd
, unsigned int cmd_len
,
1545 struct ipmi_time now
;
1548 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
1549 rsp_buffer_push(rsp
, val
& 0xff);
1550 rsp_buffer_push(rsp
, (val
>> 8) & 0xff);
1551 rsp_buffer_push(rsp
, (val
>> 16) & 0xff);
1552 rsp_buffer_push(rsp
, (val
>> 24) & 0xff);
1555 static void set_sel_time(IPMIBmcSim
*ibs
,
1556 uint8_t *cmd
, unsigned int cmd_len
,
1560 struct ipmi_time now
;
1562 val
= cmd
[2] | (cmd
[3] << 8) | (cmd
[4] << 16) | (cmd
[5] << 24);
1564 ibs
->sel
.time_offset
= now
.tv_sec
- ((long) val
);
1567 static void platform_event_msg(IPMIBmcSim
*ibs
,
1568 uint8_t *cmd
, unsigned int cmd_len
,
1573 event
[2] = 2; /* System event record */
1574 event
[7] = cmd
[2]; /* Generator ID */
1576 event
[9] = cmd
[3]; /* EvMRev */
1577 event
[10] = cmd
[4]; /* Sensor type */
1578 event
[11] = cmd
[5]; /* Sensor number */
1579 event
[12] = cmd
[6]; /* Event dir / Event type */
1580 event
[13] = cmd
[7]; /* Event data 1 */
1581 event
[14] = cmd
[8]; /* Event data 2 */
1582 event
[15] = cmd
[9]; /* Event data 3 */
1584 if (sel_add_event(ibs
, event
)) {
1585 rsp_buffer_set_error(rsp
, IPMI_CC_OUT_OF_SPACE
);
1589 static void set_sensor_evt_enable(IPMIBmcSim
*ibs
,
1590 uint8_t *cmd
, unsigned int cmd_len
,
1595 if ((cmd
[2] >= MAX_SENSORS
) ||
1596 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1597 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1600 sens
= ibs
->sensors
+ cmd
[2];
1601 switch ((cmd
[3] >> 4) & 0x3) {
1602 case 0: /* Do not change */
1604 case 1: /* Enable bits */
1606 sens
->assert_enable
|= cmd
[4];
1609 sens
->assert_enable
|= cmd
[5] << 8;
1612 sens
->deassert_enable
|= cmd
[6];
1615 sens
->deassert_enable
|= cmd
[7] << 8;
1618 case 2: /* Disable bits */
1620 sens
->assert_enable
&= ~cmd
[4];
1623 sens
->assert_enable
&= ~(cmd
[5] << 8);
1626 sens
->deassert_enable
&= ~cmd
[6];
1629 sens
->deassert_enable
&= ~(cmd
[7] << 8);
1633 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1636 IPMI_SENSOR_SET_RET_STATUS(sens
, cmd
[3]);
1639 static void get_sensor_evt_enable(IPMIBmcSim
*ibs
,
1640 uint8_t *cmd
, unsigned int cmd_len
,
1645 if ((cmd
[2] >= MAX_SENSORS
) ||
1646 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1647 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1650 sens
= ibs
->sensors
+ cmd
[2];
1651 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1652 rsp_buffer_push(rsp
, sens
->assert_enable
& 0xff);
1653 rsp_buffer_push(rsp
, (sens
->assert_enable
>> 8) & 0xff);
1654 rsp_buffer_push(rsp
, sens
->deassert_enable
& 0xff);
1655 rsp_buffer_push(rsp
, (sens
->deassert_enable
>> 8) & 0xff);
1658 static void rearm_sensor_evts(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];
1671 if ((cmd
[3] & 0x80) == 0) {
1672 /* Just clear everything */
1678 static void get_sensor_evt_status(IPMIBmcSim
*ibs
,
1679 uint8_t *cmd
, unsigned int cmd_len
,
1684 if ((cmd
[2] >= MAX_SENSORS
) ||
1685 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1686 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1689 sens
= ibs
->sensors
+ cmd
[2];
1690 rsp_buffer_push(rsp
, sens
->reading
);
1691 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1692 rsp_buffer_push(rsp
, sens
->assert_states
& 0xff);
1693 rsp_buffer_push(rsp
, (sens
->assert_states
>> 8) & 0xff);
1694 rsp_buffer_push(rsp
, sens
->deassert_states
& 0xff);
1695 rsp_buffer_push(rsp
, (sens
->deassert_states
>> 8) & 0xff);
1698 static void get_sensor_reading(IPMIBmcSim
*ibs
,
1699 uint8_t *cmd
, unsigned int cmd_len
,
1704 if ((cmd
[2] >= MAX_SENSORS
) ||
1705 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1706 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1709 sens
= ibs
->sensors
+ cmd
[2];
1710 rsp_buffer_push(rsp
, sens
->reading
);
1711 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1712 rsp_buffer_push(rsp
, sens
->states
& 0xff);
1713 if (IPMI_SENSOR_IS_DISCRETE(sens
)) {
1714 rsp_buffer_push(rsp
, (sens
->states
>> 8) & 0xff);
1718 static void set_sensor_type(IPMIBmcSim
*ibs
,
1719 uint8_t *cmd
, unsigned int cmd_len
,
1725 if ((cmd
[2] >= MAX_SENSORS
) ||
1726 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1727 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1730 sens
= ibs
->sensors
+ cmd
[2];
1731 sens
->sensor_type
= cmd
[3];
1732 sens
->evt_reading_type_code
= cmd
[4] & 0x7f;
1735 static void get_sensor_type(IPMIBmcSim
*ibs
,
1736 uint8_t *cmd
, unsigned int cmd_len
,
1742 if ((cmd
[2] >= MAX_SENSORS
) ||
1743 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1744 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1747 sens
= ibs
->sensors
+ cmd
[2];
1748 rsp_buffer_push(rsp
, sens
->sensor_type
);
1749 rsp_buffer_push(rsp
, sens
->evt_reading_type_code
);
1755 * 2 operation (see below for bits meaning)
1757 * 4:5 assertion states (optional)
1758 * 6:7 deassertion states (optional)
1759 * 8:10 event data 1,2,3 (optional)
1761 static void set_sensor_reading(IPMIBmcSim
*ibs
,
1762 uint8_t *cmd
, unsigned int cmd_len
,
1769 uint8_t new_reading
= 0;
1770 uint16_t new_assert_states
= 0;
1771 uint16_t new_deassert_states
= 0;
1772 bool change_reading
= false;
1773 bool change_assert
= false;
1774 bool change_deassert
= false;
1776 SENSOR_GEN_EVENT_NONE
,
1777 SENSOR_GEN_EVENT_DATA
,
1778 SENSOR_GEN_EVENT_BMC
,
1779 } do_gen_event
= SENSOR_GEN_EVENT_NONE
;
1781 if ((cmd
[2] >= MAX_SENSORS
) ||
1782 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1783 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1787 sens
= ibs
->sensors
+ cmd
[2];
1789 /* [1:0] Sensor Reading operation */
1790 switch ((cmd
[3]) & 0x3) {
1791 case 0: /* Do not change */
1793 case 1: /* write given value to sensor reading byte */
1794 new_reading
= cmd
[4];
1795 if (sens
->reading
!= new_reading
) {
1796 change_reading
= true;
1801 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1805 /* [3:2] Deassertion bits operation */
1806 switch ((cmd
[3] >> 2) & 0x3) {
1807 case 0: /* Do not change */
1809 case 1: /* write given value */
1811 new_deassert_states
= cmd
[7];
1812 change_deassert
= true;
1815 new_deassert_states
|= (cmd
[8] << 8);
1819 case 2: /* mask on */
1821 new_deassert_states
= (sens
->deassert_states
| cmd
[7]);
1822 change_deassert
= true;
1825 new_deassert_states
|= (sens
->deassert_states
| (cmd
[8] << 8));
1829 case 3: /* mask off */
1831 new_deassert_states
= (sens
->deassert_states
& cmd
[7]);
1832 change_deassert
= true;
1835 new_deassert_states
|= (sens
->deassert_states
& (cmd
[8] << 8));
1840 if (change_deassert
&& (new_deassert_states
== sens
->deassert_states
)) {
1841 change_deassert
= false;
1844 /* [5:4] Assertion bits operation */
1845 switch ((cmd
[3] >> 4) & 0x3) {
1846 case 0: /* Do not change */
1848 case 1: /* write given value */
1850 new_assert_states
= cmd
[5];
1851 change_assert
= true;
1854 new_assert_states
|= (cmd
[6] << 8);
1858 case 2: /* mask on */
1860 new_assert_states
= (sens
->assert_states
| cmd
[5]);
1861 change_assert
= true;
1864 new_assert_states
|= (sens
->assert_states
| (cmd
[6] << 8));
1868 case 3: /* mask off */
1870 new_assert_states
= (sens
->assert_states
& cmd
[5]);
1871 change_assert
= true;
1874 new_assert_states
|= (sens
->assert_states
& (cmd
[6] << 8));
1879 if (change_assert
&& (new_assert_states
== sens
->assert_states
)) {
1880 change_assert
= false;
1893 /* [7:6] Event Data Bytes operation */
1894 switch ((cmd
[3] >> 6) & 0x3) {
1896 * Don’t use Event Data bytes from this command. BMC will
1897 * generate it's own Event Data bytes based on its sensor
1900 evd1
= evd2
= evd3
= 0x0;
1901 do_gen_event
= SENSOR_GEN_EVENT_BMC
;
1904 * Write given values to event data bytes including bits
1905 * [3:0] Event Data 1.
1907 do_gen_event
= SENSOR_GEN_EVENT_DATA
;
1910 * Write given values to event data bytes excluding bits
1911 * [3:0] Event Data 1.
1914 do_gen_event
= SENSOR_GEN_EVENT_DATA
;
1917 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1922 * Event Data Bytes operation and parameter are inconsistent. The
1923 * Specs are not clear on that topic but generating an error seems
1926 if (do_gen_event
== SENSOR_GEN_EVENT_DATA
&& cmd_len
< 10) {
1927 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1932 if (change_reading
) {
1933 sens
->reading
= new_reading
;
1936 if (change_assert
) {
1937 sens
->assert_states
= new_assert_states
;
1940 if (change_deassert
) {
1941 sens
->deassert_states
= new_deassert_states
;
1944 /* TODO: handle threshold sensor */
1945 if (!IPMI_SENSOR_IS_DISCRETE(sens
)) {
1949 switch (do_gen_event
) {
1950 case SENSOR_GEN_EVENT_DATA
: {
1951 unsigned int bit
= evd1
& 0xf;
1952 uint16_t mask
= (1 << bit
);
1954 if (sens
->assert_states
& mask
& sens
->assert_enable
) {
1955 gen_event(ibs
, cmd
[2], 0, evd1
, evd2
, evd3
);
1958 if (sens
->deassert_states
& mask
& sens
->deassert_enable
) {
1959 gen_event(ibs
, cmd
[2], 1, evd1
, evd2
, evd3
);
1963 case SENSOR_GEN_EVENT_BMC
:
1965 * TODO: generate event and event data bytes depending on the
1969 case SENSOR_GEN_EVENT_NONE
:
1974 static const IPMICmdHandler chassis_cmds
[] = {
1975 [IPMI_CMD_GET_CHASSIS_CAPABILITIES
] = { chassis_capabilities
},
1976 [IPMI_CMD_GET_CHASSIS_STATUS
] = { chassis_status
},
1977 [IPMI_CMD_CHASSIS_CONTROL
] = { chassis_control
, 3 },
1978 [IPMI_CMD_GET_SYS_RESTART_CAUSE
] = { chassis_get_sys_restart_cause
}
1980 static const IPMINetfn chassis_netfn
= {
1981 .cmd_nums
= ARRAY_SIZE(chassis_cmds
),
1982 .cmd_handlers
= chassis_cmds
1985 static const IPMICmdHandler sensor_event_cmds
[] = {
1986 [IPMI_CMD_PLATFORM_EVENT_MSG
] = { platform_event_msg
, 10 },
1987 [IPMI_CMD_SET_SENSOR_EVT_ENABLE
] = { set_sensor_evt_enable
, 4 },
1988 [IPMI_CMD_GET_SENSOR_EVT_ENABLE
] = { get_sensor_evt_enable
, 3 },
1989 [IPMI_CMD_REARM_SENSOR_EVTS
] = { rearm_sensor_evts
, 4 },
1990 [IPMI_CMD_GET_SENSOR_EVT_STATUS
] = { get_sensor_evt_status
, 3 },
1991 [IPMI_CMD_GET_SENSOR_READING
] = { get_sensor_reading
, 3 },
1992 [IPMI_CMD_SET_SENSOR_TYPE
] = { set_sensor_type
, 5 },
1993 [IPMI_CMD_GET_SENSOR_TYPE
] = { get_sensor_type
, 3 },
1994 [IPMI_CMD_SET_SENSOR_READING
] = { set_sensor_reading
, 5 },
1996 static const IPMINetfn sensor_event_netfn
= {
1997 .cmd_nums
= ARRAY_SIZE(sensor_event_cmds
),
1998 .cmd_handlers
= sensor_event_cmds
2001 static const IPMICmdHandler app_cmds
[] = {
2002 [IPMI_CMD_GET_DEVICE_ID
] = { get_device_id
},
2003 [IPMI_CMD_COLD_RESET
] = { cold_reset
},
2004 [IPMI_CMD_WARM_RESET
] = { warm_reset
},
2005 [IPMI_CMD_SET_ACPI_POWER_STATE
] = { set_acpi_power_state
, 4 },
2006 [IPMI_CMD_GET_ACPI_POWER_STATE
] = { get_acpi_power_state
},
2007 [IPMI_CMD_GET_DEVICE_GUID
] = { get_device_guid
},
2008 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES
] = { set_bmc_global_enables
, 3 },
2009 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES
] = { get_bmc_global_enables
},
2010 [IPMI_CMD_CLR_MSG_FLAGS
] = { clr_msg_flags
, 3 },
2011 [IPMI_CMD_GET_MSG_FLAGS
] = { get_msg_flags
},
2012 [IPMI_CMD_GET_MSG
] = { get_msg
},
2013 [IPMI_CMD_SEND_MSG
] = { send_msg
, 3 },
2014 [IPMI_CMD_READ_EVT_MSG_BUF
] = { read_evt_msg_buf
},
2015 [IPMI_CMD_RESET_WATCHDOG_TIMER
] = { reset_watchdog_timer
},
2016 [IPMI_CMD_SET_WATCHDOG_TIMER
] = { set_watchdog_timer
, 8 },
2017 [IPMI_CMD_GET_WATCHDOG_TIMER
] = { get_watchdog_timer
},
2019 static const IPMINetfn app_netfn
= {
2020 .cmd_nums
= ARRAY_SIZE(app_cmds
),
2021 .cmd_handlers
= app_cmds
2024 static const IPMICmdHandler storage_cmds
[] = {
2025 [IPMI_CMD_GET_FRU_AREA_INFO
] = { get_fru_area_info
, 3 },
2026 [IPMI_CMD_READ_FRU_DATA
] = { read_fru_data
, 5 },
2027 [IPMI_CMD_WRITE_FRU_DATA
] = { write_fru_data
, 5 },
2028 [IPMI_CMD_GET_SDR_REP_INFO
] = { get_sdr_rep_info
},
2029 [IPMI_CMD_RESERVE_SDR_REP
] = { reserve_sdr_rep
},
2030 [IPMI_CMD_GET_SDR
] = { get_sdr
, 8 },
2031 [IPMI_CMD_ADD_SDR
] = { add_sdr
},
2032 [IPMI_CMD_CLEAR_SDR_REP
] = { clear_sdr_rep
, 8 },
2033 [IPMI_CMD_GET_SEL_INFO
] = { get_sel_info
},
2034 [IPMI_CMD_RESERVE_SEL
] = { reserve_sel
},
2035 [IPMI_CMD_GET_SEL_ENTRY
] = { get_sel_entry
, 8 },
2036 [IPMI_CMD_ADD_SEL_ENTRY
] = { add_sel_entry
, 18 },
2037 [IPMI_CMD_CLEAR_SEL
] = { clear_sel
, 8 },
2038 [IPMI_CMD_GET_SEL_TIME
] = { get_sel_time
},
2039 [IPMI_CMD_SET_SEL_TIME
] = { set_sel_time
, 6 },
2042 static const IPMINetfn storage_netfn
= {
2043 .cmd_nums
= ARRAY_SIZE(storage_cmds
),
2044 .cmd_handlers
= storage_cmds
2047 static void register_cmds(IPMIBmcSim
*s
)
2049 ipmi_sim_register_netfn(s
, IPMI_NETFN_CHASSIS
, &chassis_netfn
);
2050 ipmi_sim_register_netfn(s
, IPMI_NETFN_SENSOR_EVENT
, &sensor_event_netfn
);
2051 ipmi_sim_register_netfn(s
, IPMI_NETFN_APP
, &app_netfn
);
2052 ipmi_sim_register_netfn(s
, IPMI_NETFN_STORAGE
, &storage_netfn
);
2055 static uint8_t init_sdrs
[] = {
2056 /* Watchdog device */
2057 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
2058 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
2059 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2060 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
2061 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
2064 static void ipmi_sdr_init(IPMIBmcSim
*ibs
)
2071 sdrs_size
= sizeof(init_sdrs
);
2073 if (ibs
->sdr_filename
&&
2074 !g_file_get_contents(ibs
->sdr_filename
, (gchar
**) &sdrs
, &sdrs_size
,
2076 error_report("failed to load sdr file '%s'", ibs
->sdr_filename
);
2077 sdrs_size
= sizeof(init_sdrs
);
2081 for (i
= 0; i
< sdrs_size
; i
+= len
) {
2082 struct ipmi_sdr_header
*sdrh
;
2084 if (i
+ IPMI_SDR_HEADER_SIZE
> sdrs_size
) {
2085 error_report("Problem with recid 0x%4.4x", i
);
2088 sdrh
= (struct ipmi_sdr_header
*) &sdrs
[i
];
2089 len
= ipmi_sdr_length(sdrh
);
2090 if (i
+ len
> sdrs_size
) {
2091 error_report("Problem with recid 0x%4.4x", i
);
2094 sdr_add_entry(ibs
, sdrh
, len
, NULL
);
2097 if (sdrs
!= init_sdrs
) {
2102 static const VMStateDescription vmstate_ipmi_sim
= {
2103 .name
= TYPE_IPMI_BMC_SIMULATOR
,
2105 .minimum_version_id
= 1,
2106 .fields
= (VMStateField
[]) {
2107 VMSTATE_UINT8(bmc_global_enables
, IPMIBmcSim
),
2108 VMSTATE_UINT8(msg_flags
, IPMIBmcSim
),
2109 VMSTATE_BOOL(watchdog_initialized
, IPMIBmcSim
),
2110 VMSTATE_UINT8(watchdog_use
, IPMIBmcSim
),
2111 VMSTATE_UINT8(watchdog_action
, IPMIBmcSim
),
2112 VMSTATE_UINT8(watchdog_pretimeout
, IPMIBmcSim
),
2113 VMSTATE_UINT8(watchdog_expired
, IPMIBmcSim
),
2114 VMSTATE_UINT16(watchdog_timeout
, IPMIBmcSim
),
2115 VMSTATE_BOOL(watchdog_running
, IPMIBmcSim
),
2116 VMSTATE_BOOL(watchdog_preaction_ran
, IPMIBmcSim
),
2117 VMSTATE_INT64(watchdog_expiry
, IPMIBmcSim
),
2118 VMSTATE_UINT8_ARRAY(evtbuf
, IPMIBmcSim
, 16),
2119 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].status
, IPMIBmcSim
),
2120 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].reading
, IPMIBmcSim
),
2121 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].states
, IPMIBmcSim
),
2122 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_states
, IPMIBmcSim
),
2123 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].deassert_states
,
2125 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_enable
, IPMIBmcSim
),
2126 VMSTATE_END_OF_LIST()
2130 static void ipmi_fru_init(IPMIFru
*fru
)
2135 if (!fru
->filename
) {
2139 fsize
= get_image_size(fru
->filename
);
2141 size
= QEMU_ALIGN_UP(fsize
, fru
->areasize
);
2142 fru
->data
= g_malloc0(size
);
2143 if (load_image_size(fru
->filename
, fru
->data
, fsize
) != fsize
) {
2144 error_report("Could not load file '%s'", fru
->filename
);
2152 /* give one default FRU */
2153 size
= fru
->areasize
;
2154 fru
->data
= g_malloc0(size
);
2157 fru
->nentries
= size
/ fru
->areasize
;
2160 static void ipmi_sim_realize(DeviceState
*dev
, Error
**errp
)
2162 IPMIBmc
*b
= IPMI_BMC(dev
);
2164 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
2166 QTAILQ_INIT(&ibs
->rcvbufs
);
2168 ibs
->bmc_global_enables
= (1 << IPMI_BMC_EVENT_LOG_BIT
);
2169 ibs
->device_id
= 0x20;
2170 ibs
->ipmi_version
= 0x02; /* IPMI 2.0 */
2171 ibs
->restart_cause
= 0;
2172 for (i
= 0; i
< 4; i
++) {
2173 ibs
->sel
.last_addition
[i
] = 0xff;
2174 ibs
->sel
.last_clear
[i
] = 0xff;
2175 ibs
->sdr
.last_addition
[i
] = 0xff;
2176 ibs
->sdr
.last_clear
[i
] = 0xff;
2181 ipmi_fru_init(&ibs
->fru
);
2183 ibs
->acpi_power_state
[0] = 0;
2184 ibs
->acpi_power_state
[1] = 0;
2186 ipmi_init_sensors_from_sdrs(ibs
);
2189 ibs
->timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, ipmi_timeout
, ibs
);
2191 vmstate_register(NULL
, 0, &vmstate_ipmi_sim
, ibs
);
2194 static Property ipmi_sim_properties
[] = {
2195 DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim
, fru
.areasize
, 1024),
2196 DEFINE_PROP_STRING("frudatafile", IPMIBmcSim
, fru
.filename
),
2197 DEFINE_PROP_STRING("sdrfile", IPMIBmcSim
, sdr_filename
),
2198 DEFINE_PROP_UINT8("device_id", IPMIBmcSim
, device_id
, 0x20),
2199 DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim
, ipmi_version
, 0x02),
2200 DEFINE_PROP_UINT8("device_rev", IPMIBmcSim
, device_rev
, 0),
2201 DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim
, fwrev1
, 0),
2202 DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim
, fwrev2
, 0),
2203 DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim
, mfg_id
, 0),
2204 DEFINE_PROP_UINT16("product_id", IPMIBmcSim
, product_id
, 0),
2205 DEFINE_PROP_UUID_NODEFAULT("guid", IPMIBmcSim
, uuid
),
2206 DEFINE_PROP_END_OF_LIST(),
2209 static void ipmi_sim_class_init(ObjectClass
*oc
, void *data
)
2211 DeviceClass
*dc
= DEVICE_CLASS(oc
);
2212 IPMIBmcClass
*bk
= IPMI_BMC_CLASS(oc
);
2214 dc
->hotpluggable
= false;
2215 dc
->realize
= ipmi_sim_realize
;
2216 device_class_set_props(dc
, ipmi_sim_properties
);
2217 bk
->handle_command
= ipmi_sim_handle_command
;
2220 static const TypeInfo ipmi_sim_type
= {
2221 .name
= TYPE_IPMI_BMC_SIMULATOR
,
2222 .parent
= TYPE_IPMI_BMC
,
2223 .instance_size
= sizeof(IPMIBmcSim
),
2224 .class_init
= ipmi_sim_class_init
,
2227 static void ipmi_sim_register_types(void)
2229 type_register_static(&ipmi_sim_type
);
2232 type_init(ipmi_sim_register_types
)