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 "migration/vmstate.h"
35 #define IPMI_NETFN_CHASSIS 0x00
37 #define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
38 #define IPMI_CMD_GET_CHASSIS_STATUS 0x01
39 #define IPMI_CMD_CHASSIS_CONTROL 0x02
40 #define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09
42 #define IPMI_NETFN_SENSOR_EVENT 0x04
44 #define IPMI_CMD_PLATFORM_EVENT_MSG 0x02
45 #define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
46 #define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
47 #define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
48 #define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b
49 #define IPMI_CMD_GET_SENSOR_READING 0x2d
50 #define IPMI_CMD_SET_SENSOR_TYPE 0x2e
51 #define IPMI_CMD_GET_SENSOR_TYPE 0x2f
52 #define IPMI_CMD_SET_SENSOR_READING 0x30
54 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
56 #define IPMI_CMD_GET_DEVICE_ID 0x01
57 #define IPMI_CMD_COLD_RESET 0x02
58 #define IPMI_CMD_WARM_RESET 0x03
59 #define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
60 #define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
61 #define IPMI_CMD_GET_DEVICE_GUID 0x08
62 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
63 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
64 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
65 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
66 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
67 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
68 #define IPMI_CMD_GET_MSG_FLAGS 0x31
69 #define IPMI_CMD_GET_MSG 0x33
70 #define IPMI_CMD_SEND_MSG 0x34
71 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
73 #define IPMI_NETFN_STORAGE 0x0a
75 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
76 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
77 #define IPMI_CMD_RESERVE_SDR_REP 0x22
78 #define IPMI_CMD_GET_SDR 0x23
79 #define IPMI_CMD_ADD_SDR 0x24
80 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
81 #define IPMI_CMD_DELETE_SDR 0x26
82 #define IPMI_CMD_CLEAR_SDR_REP 0x27
83 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
84 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
85 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
86 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
87 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
88 #define IPMI_CMD_GET_FRU_AREA_INFO 0x10
89 #define IPMI_CMD_READ_FRU_DATA 0x11
90 #define IPMI_CMD_WRITE_FRU_DATA 0x12
91 #define IPMI_CMD_GET_SEL_INFO 0x40
92 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
93 #define IPMI_CMD_RESERVE_SEL 0x42
94 #define IPMI_CMD_GET_SEL_ENTRY 0x43
95 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
96 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
97 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
98 #define IPMI_CMD_CLEAR_SEL 0x47
99 #define IPMI_CMD_GET_SEL_TIME 0x48
100 #define IPMI_CMD_SET_SEL_TIME 0x49
103 /* Same as a timespec struct. */
109 #define MAX_SEL_SIZE 128
111 typedef struct IPMISel
{
112 uint8_t sel
[MAX_SEL_SIZE
][16];
113 unsigned int next_free
;
115 uint16_t reservation
;
116 uint8_t last_addition
[4];
117 uint8_t last_clear
[4];
121 #define MAX_SDR_SIZE 16384
123 typedef struct IPMISdr
{
124 uint8_t sdr
[MAX_SDR_SIZE
];
125 unsigned int next_free
;
126 uint16_t next_rec_id
;
127 uint16_t reservation
;
128 uint8_t last_addition
[4];
129 uint8_t last_clear
[4];
133 typedef struct IPMIFru
{
135 unsigned int nentries
;
140 typedef struct IPMISensor
{
143 uint16_t states_suppt
;
144 uint16_t assert_suppt
;
145 uint16_t deassert_suppt
;
147 uint16_t assert_states
;
148 uint16_t deassert_states
;
149 uint16_t assert_enable
;
150 uint16_t deassert_enable
;
152 uint8_t evt_reading_type_code
;
154 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
155 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
157 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
158 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
160 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
161 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
163 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
164 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
166 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
168 #define MAX_SENSORS 20
169 #define IPMI_WATCHDOG_SENSOR 0
171 #define MAX_NETFNS 64
173 typedef struct IPMIRcvBufEntry
{
174 QTAILQ_ENTRY(IPMIRcvBufEntry
) entry
;
176 uint8_t buf
[MAX_IPMI_MSG_SIZE
];
184 uint8_t bmc_global_enables
;
187 bool watchdog_initialized
;
188 uint8_t watchdog_use
;
189 uint8_t watchdog_action
;
190 uint8_t watchdog_pretimeout
; /* In seconds */
191 bool watchdog_expired
;
192 uint16_t watchdog_timeout
; /* in 100's of milliseconds */
194 bool watchdog_running
;
195 bool watchdog_preaction_ran
;
196 int64_t watchdog_expiry
;
199 uint8_t ipmi_version
;
206 uint8_t restart_cause
;
208 uint8_t acpi_power_state
[2];
214 IPMISensor sensors
[MAX_SENSORS
];
217 /* Odd netfns are for responses, so we only need the even ones. */
218 const IPMINetfn
*netfns
[MAX_NETFNS
/ 2];
220 /* We allow one event in the buffer */
223 QTAILQ_HEAD(, IPMIRcvBufEntry
) rcvbufs
;
226 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
227 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
228 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
229 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
230 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
231 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
232 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
233 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
234 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
236 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
237 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
238 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
239 #define IPMI_BMC_EVENT_LOG_BIT 3
240 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
241 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
242 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
243 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
244 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
245 (1 << IPMI_BMC_EVENT_LOG_BIT))
246 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
247 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
249 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
250 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
251 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
252 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
253 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
254 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
255 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
256 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
257 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
258 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
259 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
260 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
261 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
262 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
263 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
265 #define RSP_BUFFER_INITIALIZER { }
267 static inline void rsp_buffer_pushmore(RspBuffer
*rsp
, uint8_t *bytes
,
270 if (rsp
->len
+ n
>= sizeof(rsp
->buffer
)) {
271 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
275 memcpy(&rsp
->buffer
[rsp
->len
], bytes
, n
);
279 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
);
281 static void ipmi_gettime(struct ipmi_time
*time
)
285 stime
= qemu_clock_get_ns(QEMU_CLOCK_HOST
);
286 time
->tv_sec
= stime
/ 1000000000LL;
287 time
->tv_nsec
= stime
% 1000000000LL;
290 static int64_t ipmi_getmonotime(void)
292 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
295 static void ipmi_timeout(void *opaque
)
297 IPMIBmcSim
*ibs
= opaque
;
299 ipmi_sim_handle_timeout(ibs
);
302 static void set_timestamp(IPMIBmcSim
*ibs
, uint8_t *ts
)
305 struct ipmi_time now
;
308 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
310 ts
[1] = (val
>> 8) & 0xff;
311 ts
[2] = (val
>> 16) & 0xff;
312 ts
[3] = (val
>> 24) & 0xff;
315 static void sdr_inc_reservation(IPMISdr
*sdr
)
318 if (sdr
->reservation
== 0) {
319 sdr
->reservation
= 1;
323 static int sdr_add_entry(IPMIBmcSim
*ibs
,
324 const struct ipmi_sdr_header
*sdrh_entry
,
325 unsigned int len
, uint16_t *recid
)
327 struct ipmi_sdr_header
*sdrh
=
328 (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[ibs
->sdr
.next_free
];
330 if ((len
< IPMI_SDR_HEADER_SIZE
) || (len
> 255)) {
334 if (ipmi_sdr_length(sdrh_entry
) != len
) {
338 if (ibs
->sdr
.next_free
+ len
> MAX_SDR_SIZE
) {
339 ibs
->sdr
.overflow
= 1;
343 memcpy(sdrh
, sdrh_entry
, len
);
344 sdrh
->rec_id
[0] = ibs
->sdr
.next_rec_id
& 0xff;
345 sdrh
->rec_id
[1] = (ibs
->sdr
.next_rec_id
>> 8) & 0xff;
346 sdrh
->sdr_version
= 0x51; /* Conform to IPMI 1.5 spec */
349 *recid
= ibs
->sdr
.next_rec_id
;
351 ibs
->sdr
.next_rec_id
++;
352 set_timestamp(ibs
, ibs
->sdr
.last_addition
);
353 ibs
->sdr
.next_free
+= len
;
354 sdr_inc_reservation(&ibs
->sdr
);
358 static int sdr_find_entry(IPMISdr
*sdr
, uint16_t recid
,
359 unsigned int *retpos
, uint16_t *nextrec
)
361 unsigned int pos
= *retpos
;
363 while (pos
< sdr
->next_free
) {
364 struct ipmi_sdr_header
*sdrh
=
365 (struct ipmi_sdr_header
*) &sdr
->sdr
[pos
];
366 uint16_t trec
= ipmi_sdr_recid(sdrh
);
367 unsigned int nextpos
= pos
+ ipmi_sdr_length(sdrh
);
371 if (nextpos
>= sdr
->next_free
) {
374 *nextrec
= (sdr
->sdr
[nextpos
] |
375 (sdr
->sdr
[nextpos
+ 1] << 8));
386 int ipmi_bmc_sdr_find(IPMIBmc
*b
, uint16_t recid
,
387 const struct ipmi_sdr_compact
**sdr
, uint16_t *nextrec
)
390 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
394 if (sdr_find_entry(&ibs
->sdr
, recid
, &pos
, nextrec
)) {
398 *sdr
= (const struct ipmi_sdr_compact
*) &ibs
->sdr
.sdr
[pos
];
402 static void sel_inc_reservation(IPMISel
*sel
)
405 if (sel
->reservation
== 0) {
406 sel
->reservation
= 1;
410 /* Returns 1 if the SEL is full and can't hold the event. */
411 static int sel_add_event(IPMIBmcSim
*ibs
, uint8_t *event
)
417 set_timestamp(ibs
, ts
);
418 if (event
[2] < 0xe0) { /* Don't set timestamps for type 0xe0-0xff. */
419 memcpy(event
+ 3, ts
, 4);
421 if (ibs
->sel
.next_free
== MAX_SEL_SIZE
) {
422 ibs
->sel
.overflow
= 1;
425 event
[0] = ibs
->sel
.next_free
& 0xff;
426 event
[1] = (ibs
->sel
.next_free
>> 8) & 0xff;
427 memcpy(ibs
->sel
.last_addition
, ts
, 4);
428 memcpy(ibs
->sel
.sel
[ibs
->sel
.next_free
], event
, 16);
429 ibs
->sel
.next_free
++;
430 sel_inc_reservation(&ibs
->sel
);
434 static int attn_set(IPMIBmcSim
*ibs
)
436 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
)
437 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
)
438 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs
);
441 static int attn_irq_enabled(IPMIBmcSim
*ibs
)
443 return (IPMI_BMC_MSG_INTS_ON(ibs
) &&
444 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
) ||
445 IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs
)))
446 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs
) &&
447 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
));
450 void ipmi_bmc_gen_event(IPMIBmc
*b
, uint8_t *evt
, bool log
)
452 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
453 IPMIInterface
*s
= ibs
->parent
.intf
;
454 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
456 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
460 if (log
&& IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
461 sel_add_event(ibs
, evt
);
464 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
468 memcpy(ibs
->evtbuf
, evt
, 16);
469 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
470 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
474 static void gen_event(IPMIBmcSim
*ibs
, unsigned int sens_num
, uint8_t deassert
,
475 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
477 IPMIInterface
*s
= ibs
->parent
.intf
;
478 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
480 IPMISensor
*sens
= ibs
->sensors
+ sens_num
;
482 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
485 if (!IPMI_SENSOR_GET_EVENTS_ON(sens
)) {
489 evt
[2] = 0x2; /* System event record */
490 evt
[7] = ibs
->parent
.slave_addr
;
492 evt
[9] = 0x04; /* Format version */
493 evt
[10] = sens
->sensor_type
;
495 evt
[12] = sens
->evt_reading_type_code
| (!!deassert
<< 7);
500 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
501 sel_add_event(ibs
, evt
);
504 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
508 memcpy(ibs
->evtbuf
, evt
, 16);
509 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
510 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
513 static void sensor_set_discrete_bit(IPMIBmcSim
*ibs
, unsigned int sensor
,
514 unsigned int bit
, unsigned int val
,
515 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
520 if (sensor
>= MAX_SENSORS
) {
528 sens
= ibs
->sensors
+ sensor
;
530 sens
->states
|= mask
& sens
->states_suppt
;
531 if (sens
->assert_states
& mask
) {
532 return; /* Already asserted */
534 sens
->assert_states
|= mask
& sens
->assert_suppt
;
535 if (sens
->assert_enable
& mask
& sens
->assert_states
) {
536 /* Send an event on assert */
537 gen_event(ibs
, sensor
, 0, evd1
, evd2
, evd3
);
540 sens
->states
&= ~(mask
& sens
->states_suppt
);
541 if (sens
->deassert_states
& mask
) {
542 return; /* Already deasserted */
544 sens
->deassert_states
|= mask
& sens
->deassert_suppt
;
545 if (sens
->deassert_enable
& mask
& sens
->deassert_states
) {
546 /* Send an event on deassert */
547 gen_event(ibs
, sensor
, 1, evd1
, evd2
, evd3
);
552 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim
*s
)
557 for (i
= 0; i
< MAX_SENSORS
; i
++) {
558 memset(s
->sensors
+ i
, 0, sizeof(*sens
));
562 for (i
= 0; !sdr_find_entry(&s
->sdr
, i
, &pos
, NULL
); i
++) {
563 struct ipmi_sdr_compact
*sdr
=
564 (struct ipmi_sdr_compact
*) &s
->sdr
.sdr
[pos
];
565 unsigned int len
= sdr
->header
.rec_length
;
570 if (sdr
->header
.rec_type
!= IPMI_SDR_COMPACT_TYPE
) {
571 continue; /* Not a sensor SDR we set from */
574 if (sdr
->sensor_owner_number
>= MAX_SENSORS
) {
577 sens
= s
->sensors
+ sdr
->sensor_owner_number
;
579 IPMI_SENSOR_SET_PRESENT(sens
, 1);
580 IPMI_SENSOR_SET_SCAN_ON(sens
, (sdr
->sensor_init
>> 6) & 1);
581 IPMI_SENSOR_SET_EVENTS_ON(sens
, (sdr
->sensor_init
>> 5) & 1);
582 sens
->assert_suppt
= sdr
->assert_mask
[0] | (sdr
->assert_mask
[1] << 8);
583 sens
->deassert_suppt
=
584 sdr
->deassert_mask
[0] | (sdr
->deassert_mask
[1] << 8);
586 sdr
->discrete_mask
[0] | (sdr
->discrete_mask
[1] << 8);
587 sens
->sensor_type
= sdr
->sensor_type
;
588 sens
->evt_reading_type_code
= sdr
->reading_type
& 0x7f;
590 /* Enable all the events that are supported. */
591 sens
->assert_enable
= sens
->assert_suppt
;
592 sens
->deassert_enable
= sens
->deassert_suppt
;
596 int ipmi_sim_register_netfn(IPMIBmcSim
*s
, unsigned int netfn
,
597 const IPMINetfn
*netfnd
)
599 if ((netfn
& 1) || (netfn
>= MAX_NETFNS
) || (s
->netfns
[netfn
/ 2])) {
602 s
->netfns
[netfn
/ 2] = netfnd
;
606 static const IPMICmdHandler
*ipmi_get_handler(IPMIBmcSim
*ibs
,
610 const IPMICmdHandler
*hdl
;
612 if (netfn
& 1 || netfn
>= MAX_NETFNS
|| !ibs
->netfns
[netfn
/ 2]) {
616 if (cmd
>= ibs
->netfns
[netfn
/ 2]->cmd_nums
) {
620 hdl
= &ibs
->netfns
[netfn
/ 2]->cmd_handlers
[cmd
];
621 if (!hdl
->cmd_handler
) {
628 static void next_timeout(IPMIBmcSim
*ibs
)
631 if (ibs
->watchdog_running
) {
632 next
= ibs
->watchdog_expiry
;
635 next
= ipmi_getmonotime() + 60 * 1000000000LL;
637 timer_mod_ns(ibs
->timer
, next
);
640 static void ipmi_sim_handle_command(IPMIBmc
*b
,
641 uint8_t *cmd
, unsigned int cmd_len
,
642 unsigned int max_cmd_len
,
645 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
646 IPMIInterface
*s
= ibs
->parent
.intf
;
647 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
648 const IPMICmdHandler
*hdl
;
649 RspBuffer rsp
= RSP_BUFFER_INITIALIZER
;
651 /* Set up the response, set the low bit of NETFN. */
652 /* Note that max_rsp_len must be at least 3 */
653 if (sizeof(rsp
.buffer
) < 3) {
654 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
658 rsp_buffer_push(&rsp
, cmd
[0] | 0x04);
659 rsp_buffer_push(&rsp
, cmd
[1]);
660 rsp_buffer_push(&rsp
, 0); /* Assume success */
662 /* If it's too short or it was truncated, return an error. */
664 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
667 if (cmd_len
> max_cmd_len
) {
668 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
672 if ((cmd
[0] & 0x03) != 0) {
673 /* Only have stuff on LUN 0 */
674 rsp_buffer_set_error(&rsp
, IPMI_CC_COMMAND_INVALID_FOR_LUN
);
678 hdl
= ipmi_get_handler(ibs
, cmd
[0] >> 2, cmd
[1]);
680 rsp_buffer_set_error(&rsp
, IPMI_CC_INVALID_CMD
);
684 if (cmd_len
< hdl
->cmd_len_min
) {
685 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
689 hdl
->cmd_handler(ibs
, cmd
, cmd_len
, &rsp
);
692 k
->handle_rsp(s
, msg_id
, rsp
.buffer
, rsp
.len
);
697 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
)
699 IPMIInterface
*s
= ibs
->parent
.intf
;
700 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
702 if (!ibs
->watchdog_running
) {
706 if (!ibs
->watchdog_preaction_ran
) {
707 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
)) {
708 case IPMI_BMC_WATCHDOG_PRE_NMI
:
709 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
710 k
->do_hw_op(s
, IPMI_SEND_NMI
, 0);
711 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
712 0xc8, (2 << 4) | 0xf, 0xff);
715 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
716 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
717 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
718 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
719 0xc8, (3 << 4) | 0xf, 0xff);
726 ibs
->watchdog_preaction_ran
= 1;
727 /* Issued the pretimeout, do the rest of the timeout now. */
728 ibs
->watchdog_expiry
= ipmi_getmonotime();
729 ibs
->watchdog_expiry
+= ibs
->watchdog_pretimeout
* 1000000000LL;
734 ibs
->watchdog_running
= 0; /* Stop the watchdog on a timeout */
735 ibs
->watchdog_expired
|= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs
));
736 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
)) {
737 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
738 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 0, 1,
739 0xc0, ibs
->watchdog_use
& 0xf, 0xff);
742 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
743 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 1, 1,
744 0xc1, ibs
->watchdog_use
& 0xf, 0xff);
745 k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0);
748 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
749 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
750 0xc2, ibs
->watchdog_use
& 0xf, 0xff);
751 k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0);
754 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
755 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
756 0xc3, ibs
->watchdog_use
& 0xf, 0xff);
757 k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0);
765 static void chassis_capabilities(IPMIBmcSim
*ibs
,
766 uint8_t *cmd
, unsigned int cmd_len
,
769 rsp_buffer_push(rsp
, 0);
770 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
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
);
776 static void chassis_status(IPMIBmcSim
*ibs
,
777 uint8_t *cmd
, unsigned int cmd_len
,
780 rsp_buffer_push(rsp
, 0x61); /* Unknown power restore, power is on */
781 rsp_buffer_push(rsp
, 0);
782 rsp_buffer_push(rsp
, 0);
783 rsp_buffer_push(rsp
, 0);
786 static void chassis_control(IPMIBmcSim
*ibs
,
787 uint8_t *cmd
, unsigned int cmd_len
,
790 IPMIInterface
*s
= ibs
->parent
.intf
;
791 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
793 switch (cmd
[2] & 0xf) {
794 case 0: /* power down */
795 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0));
797 case 1: /* power up */
798 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERON_CHASSIS
, 0));
800 case 2: /* power cycle */
801 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0));
803 case 3: /* hard reset */
804 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0));
806 case 4: /* pulse diagnostic interrupt */
807 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_PULSE_DIAG_IRQ
, 0));
809 case 5: /* soft shutdown via ACPI by overtemp emulation */
810 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
,
811 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP
, 0));
814 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
819 static void chassis_get_sys_restart_cause(IPMIBmcSim
*ibs
,
820 uint8_t *cmd
, unsigned int cmd_len
,
824 rsp_buffer_push(rsp
, ibs
->restart_cause
& 0xf); /* Restart Cause */
825 rsp_buffer_push(rsp
, 0); /* Channel 0 */
828 static void get_device_id(IPMIBmcSim
*ibs
,
829 uint8_t *cmd
, unsigned int cmd_len
,
832 rsp_buffer_push(rsp
, ibs
->device_id
);
833 rsp_buffer_push(rsp
, ibs
->device_rev
& 0xf);
834 rsp_buffer_push(rsp
, ibs
->fwrev1
& 0x7f);
835 rsp_buffer_push(rsp
, ibs
->fwrev2
);
836 rsp_buffer_push(rsp
, ibs
->ipmi_version
);
837 rsp_buffer_push(rsp
, 0x07); /* sensor, SDR, and SEL. */
838 rsp_buffer_push(rsp
, ibs
->mfg_id
& 0xff);
839 rsp_buffer_push(rsp
, (ibs
->mfg_id
>> 8) & 0xff);
840 rsp_buffer_push(rsp
, (ibs
->mfg_id
>> 16) & 0xff);
841 rsp_buffer_push(rsp
, ibs
->product_id
& 0xff);
842 rsp_buffer_push(rsp
, (ibs
->product_id
>> 8) & 0xff);
845 static void set_global_enables(IPMIBmcSim
*ibs
, uint8_t val
)
847 IPMIInterface
*s
= ibs
->parent
.intf
;
848 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
851 ibs
->bmc_global_enables
= val
;
853 irqs_on
= val
& (IPMI_BMC_EVBUF_FULL_INT_BIT
|
854 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT
);
856 k
->set_irq_enable(s
, irqs_on
);
859 static void cold_reset(IPMIBmcSim
*ibs
,
860 uint8_t *cmd
, unsigned int cmd_len
,
863 IPMIInterface
*s
= ibs
->parent
.intf
;
864 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
866 /* Disable all interrupts */
867 set_global_enables(ibs
, 1 << IPMI_BMC_EVENT_LOG_BIT
);
874 static void warm_reset(IPMIBmcSim
*ibs
,
875 uint8_t *cmd
, unsigned int cmd_len
,
878 IPMIInterface
*s
= ibs
->parent
.intf
;
879 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
885 static void set_acpi_power_state(IPMIBmcSim
*ibs
,
886 uint8_t *cmd
, unsigned int cmd_len
,
889 ibs
->acpi_power_state
[0] = cmd
[2];
890 ibs
->acpi_power_state
[1] = cmd
[3];
893 static void get_acpi_power_state(IPMIBmcSim
*ibs
,
894 uint8_t *cmd
, unsigned int cmd_len
,
897 rsp_buffer_push(rsp
, ibs
->acpi_power_state
[0]);
898 rsp_buffer_push(rsp
, ibs
->acpi_power_state
[1]);
901 static void get_device_guid(IPMIBmcSim
*ibs
,
902 uint8_t *cmd
, unsigned int cmd_len
,
907 /* An uninitialized uuid is all zeros, use that to know if it is set. */
908 for (i
= 0; i
< 16; i
++) {
909 if (ibs
->uuid
.data
[i
]) {
913 /* No uuid is set, return an error. */
914 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_CMD
);
918 for (i
= 0; i
< 16; i
++) {
919 rsp_buffer_push(rsp
, ibs
->uuid
.data
[i
]);
923 static void set_bmc_global_enables(IPMIBmcSim
*ibs
,
924 uint8_t *cmd
, unsigned int cmd_len
,
927 set_global_enables(ibs
, cmd
[2]);
930 static void get_bmc_global_enables(IPMIBmcSim
*ibs
,
931 uint8_t *cmd
, unsigned int cmd_len
,
934 rsp_buffer_push(rsp
, ibs
->bmc_global_enables
);
937 static void clr_msg_flags(IPMIBmcSim
*ibs
,
938 uint8_t *cmd
, unsigned int cmd_len
,
941 IPMIInterface
*s
= ibs
->parent
.intf
;
942 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
944 ibs
->msg_flags
&= ~cmd
[2];
945 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
948 static void get_msg_flags(IPMIBmcSim
*ibs
,
949 uint8_t *cmd
, unsigned int cmd_len
,
952 rsp_buffer_push(rsp
, ibs
->msg_flags
);
955 static void read_evt_msg_buf(IPMIBmcSim
*ibs
,
956 uint8_t *cmd
, unsigned int cmd_len
,
959 IPMIInterface
*s
= ibs
->parent
.intf
;
960 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
963 if (!(ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
)) {
964 rsp_buffer_set_error(rsp
, 0x80);
967 for (i
= 0; i
< 16; i
++) {
968 rsp_buffer_push(rsp
, ibs
->evtbuf
[i
]);
970 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
971 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
974 static void get_msg(IPMIBmcSim
*ibs
,
975 uint8_t *cmd
, unsigned int cmd_len
,
978 IPMIRcvBufEntry
*msg
;
980 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
981 rsp_buffer_set_error(rsp
, 0x80); /* Queue empty */
984 rsp_buffer_push(rsp
, 0); /* Channel 0 */
985 msg
= QTAILQ_FIRST(&ibs
->rcvbufs
);
986 rsp_buffer_pushmore(rsp
, msg
->buf
, msg
->len
);
987 QTAILQ_REMOVE(&ibs
->rcvbufs
, msg
, entry
);
990 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
991 IPMIInterface
*s
= ibs
->parent
.intf
;
992 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
994 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
995 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
1002 static unsigned char
1003 ipmb_checksum(unsigned char *data
, int size
, unsigned char csum
)
1005 for (; size
> 0; size
--, data
++) {
1012 static void send_msg(IPMIBmcSim
*ibs
,
1013 uint8_t *cmd
, unsigned int cmd_len
,
1016 IPMIInterface
*s
= ibs
->parent
.intf
;
1017 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1018 IPMIRcvBufEntry
*msg
;
1020 uint8_t netfn
, rqLun
, rsLun
, rqSeq
;
1023 /* We only handle channel 0 with no options */
1024 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1029 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
1033 if (cmd
[3] != 0x40) {
1034 /* We only emulate a MC at address 0x40. */
1035 rsp_buffer_set_error(rsp
, 0x83); /* NAK on write */
1039 cmd
+= 3; /* Skip the header. */
1043 * At this point we "send" the message successfully. Any error will
1044 * be returned in the response.
1046 if (ipmb_checksum(cmd
, cmd_len
, 0) != 0 ||
1047 cmd
[3] != 0x20) { /* Improper response address */
1048 return; /* No response */
1051 netfn
= cmd
[1] >> 2;
1052 rqLun
= cmd
[4] & 0x3;
1053 rsLun
= cmd
[1] & 0x3;
1054 rqSeq
= cmd
[4] >> 2;
1057 /* We only support LUN 2 coming back to us. */
1061 msg
= g_malloc(sizeof(*msg
));
1062 msg
->buf
[0] = ((netfn
| 1) << 2) | rqLun
; /* NetFN, and make a response */
1063 msg
->buf
[1] = ipmb_checksum(msg
->buf
, 1, 0);
1064 msg
->buf
[2] = cmd
[0]; /* rsSA */
1065 msg
->buf
[3] = (rqSeq
<< 2) | rsLun
;
1066 msg
->buf
[4] = cmd
[5]; /* Cmd */
1067 msg
->buf
[5] = 0; /* Completion Code */
1070 if ((cmd
[1] >> 2) != IPMI_NETFN_APP
|| cmd
[5] != IPMI_CMD_GET_DEVICE_ID
) {
1071 /* Not a command we handle. */
1072 msg
->buf
[5] = IPMI_CC_INVALID_CMD
;
1076 buf
= msg
->buf
+ msg
->len
; /* After the CC */
1091 msg
->buf
[msg
->len
] = ipmb_checksum(msg
->buf
, msg
->len
, 0);
1093 QTAILQ_INSERT_TAIL(&ibs
->rcvbufs
, msg
, entry
);
1094 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
1095 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
1098 static void do_watchdog_reset(IPMIBmcSim
*ibs
)
1100 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
) ==
1101 IPMI_BMC_WATCHDOG_ACTION_NONE
) {
1102 ibs
->watchdog_running
= 0;
1105 ibs
->watchdog_preaction_ran
= 0;
1108 /* Timeout is in tenths of a second, offset is in seconds */
1109 ibs
->watchdog_expiry
= ipmi_getmonotime();
1110 ibs
->watchdog_expiry
+= ibs
->watchdog_timeout
* 100000000LL;
1111 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
) != IPMI_BMC_WATCHDOG_PRE_NONE
) {
1112 ibs
->watchdog_expiry
-= ibs
->watchdog_pretimeout
* 1000000000LL;
1114 ibs
->watchdog_running
= 1;
1117 static void reset_watchdog_timer(IPMIBmcSim
*ibs
,
1118 uint8_t *cmd
, unsigned int cmd_len
,
1121 if (!ibs
->watchdog_initialized
) {
1122 rsp_buffer_set_error(rsp
, 0x80);
1125 do_watchdog_reset(ibs
);
1128 static void set_watchdog_timer(IPMIBmcSim
*ibs
,
1129 uint8_t *cmd
, unsigned int cmd_len
,
1132 IPMIInterface
*s
= ibs
->parent
.intf
;
1133 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1136 val
= cmd
[2] & 0x7; /* Validate use */
1137 if (val
== 0 || val
> 5) {
1138 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1141 val
= cmd
[3] & 0x7; /* Validate action */
1143 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
1146 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
1147 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 1));
1150 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
1151 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 1));
1154 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
1155 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 1));
1159 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1161 if (rsp
->buffer
[2]) {
1162 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1166 val
= (cmd
[3] >> 4) & 0x7; /* Validate preaction */
1168 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
1169 case IPMI_BMC_WATCHDOG_PRE_NONE
:
1172 case IPMI_BMC_WATCHDOG_PRE_NMI
:
1173 if (k
->do_hw_op(s
, IPMI_SEND_NMI
, 1)) {
1174 /* NMI not supported. */
1175 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1181 /* We don't support PRE_SMI */
1182 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1186 ibs
->watchdog_initialized
= 1;
1187 ibs
->watchdog_use
= cmd
[2] & IPMI_BMC_WATCHDOG_USE_MASK
;
1188 ibs
->watchdog_action
= cmd
[3] & IPMI_BMC_WATCHDOG_ACTION_MASK
;
1189 ibs
->watchdog_pretimeout
= cmd
[4];
1190 ibs
->watchdog_expired
&= ~cmd
[5];
1191 ibs
->watchdog_timeout
= cmd
[6] | (((uint16_t) cmd
[7]) << 8);
1192 if (ibs
->watchdog_running
& IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs
)) {
1193 do_watchdog_reset(ibs
);
1195 ibs
->watchdog_running
= 0;
1199 static void get_watchdog_timer(IPMIBmcSim
*ibs
,
1200 uint8_t *cmd
, unsigned int cmd_len
,
1203 rsp_buffer_push(rsp
, ibs
->watchdog_use
);
1204 rsp_buffer_push(rsp
, ibs
->watchdog_action
);
1205 rsp_buffer_push(rsp
, ibs
->watchdog_pretimeout
);
1206 rsp_buffer_push(rsp
, ibs
->watchdog_expired
);
1207 rsp_buffer_push(rsp
, ibs
->watchdog_timeout
& 0xff);
1208 rsp_buffer_push(rsp
, (ibs
->watchdog_timeout
>> 8) & 0xff);
1209 if (ibs
->watchdog_running
) {
1211 timeout
= ((ibs
->watchdog_expiry
- ipmi_getmonotime() + 50000000)
1213 rsp_buffer_push(rsp
, timeout
& 0xff);
1214 rsp_buffer_push(rsp
, (timeout
>> 8) & 0xff);
1216 rsp_buffer_push(rsp
, 0);
1217 rsp_buffer_push(rsp
, 0);
1221 static void get_sdr_rep_info(IPMIBmcSim
*ibs
,
1222 uint8_t *cmd
, unsigned int cmd_len
,
1227 rsp_buffer_push(rsp
, 0x51); /* Conform to IPMI 1.5 spec */
1228 rsp_buffer_push(rsp
, ibs
->sdr
.next_rec_id
& 0xff);
1229 rsp_buffer_push(rsp
, (ibs
->sdr
.next_rec_id
>> 8) & 0xff);
1230 rsp_buffer_push(rsp
, (MAX_SDR_SIZE
- ibs
->sdr
.next_free
) & 0xff);
1231 rsp_buffer_push(rsp
, ((MAX_SDR_SIZE
- ibs
->sdr
.next_free
) >> 8) & 0xff);
1232 for (i
= 0; i
< 4; i
++) {
1233 rsp_buffer_push(rsp
, ibs
->sdr
.last_addition
[i
]);
1235 for (i
= 0; i
< 4; i
++) {
1236 rsp_buffer_push(rsp
, ibs
->sdr
.last_clear
[i
]);
1238 /* Only modal support, reserve supported */
1239 rsp_buffer_push(rsp
, (ibs
->sdr
.overflow
<< 7) | 0x22);
1242 static void reserve_sdr_rep(IPMIBmcSim
*ibs
,
1243 uint8_t *cmd
, unsigned int cmd_len
,
1246 rsp_buffer_push(rsp
, ibs
->sdr
.reservation
& 0xff);
1247 rsp_buffer_push(rsp
, (ibs
->sdr
.reservation
>> 8) & 0xff);
1250 static void get_sdr(IPMIBmcSim
*ibs
,
1251 uint8_t *cmd
, unsigned int cmd_len
,
1256 struct ipmi_sdr_header
*sdrh
;
1259 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sdr
.reservation
) {
1260 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1266 if (sdr_find_entry(&ibs
->sdr
, cmd
[4] | (cmd
[5] << 8),
1268 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1272 sdrh
= (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[pos
];
1274 if (cmd
[6] > ipmi_sdr_length(sdrh
)) {
1275 rsp_buffer_set_error(rsp
, IPMI_CC_PARM_OUT_OF_RANGE
);
1279 rsp_buffer_push(rsp
, nextrec
& 0xff);
1280 rsp_buffer_push(rsp
, (nextrec
>> 8) & 0xff);
1282 if (cmd
[7] == 0xff) {
1283 cmd
[7] = ipmi_sdr_length(sdrh
) - cmd
[6];
1286 if ((cmd
[7] + rsp
->len
) > sizeof(rsp
->buffer
)) {
1287 rsp_buffer_set_error(rsp
, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES
);
1291 rsp_buffer_pushmore(rsp
, ibs
->sdr
.sdr
+ pos
+ cmd
[6], cmd
[7]);
1294 static void add_sdr(IPMIBmcSim
*ibs
,
1295 uint8_t *cmd
, unsigned int cmd_len
,
1299 struct ipmi_sdr_header
*sdrh
= (struct ipmi_sdr_header
*) cmd
+ 2;
1301 if (sdr_add_entry(ibs
, sdrh
, cmd_len
- 2, &recid
)) {
1302 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1305 rsp_buffer_push(rsp
, recid
& 0xff);
1306 rsp_buffer_push(rsp
, (recid
>> 8) & 0xff);
1309 static void clear_sdr_rep(IPMIBmcSim
*ibs
,
1310 uint8_t *cmd
, unsigned int cmd_len
,
1313 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sdr
.reservation
) {
1314 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1318 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1319 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1322 if (cmd
[7] == 0xaa) {
1323 ibs
->sdr
.next_free
= 0;
1324 ibs
->sdr
.overflow
= 0;
1325 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1326 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1327 sdr_inc_reservation(&ibs
->sdr
);
1328 } else if (cmd
[7] == 0) {
1329 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1331 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1336 static void get_sel_info(IPMIBmcSim
*ibs
,
1337 uint8_t *cmd
, unsigned int cmd_len
,
1340 unsigned int i
, val
;
1342 rsp_buffer_push(rsp
, 0x51); /* Conform to IPMI 1.5 */
1343 rsp_buffer_push(rsp
, ibs
->sel
.next_free
& 0xff);
1344 rsp_buffer_push(rsp
, (ibs
->sel
.next_free
>> 8) & 0xff);
1345 val
= (MAX_SEL_SIZE
- ibs
->sel
.next_free
) * 16;
1346 rsp_buffer_push(rsp
, val
& 0xff);
1347 rsp_buffer_push(rsp
, (val
>> 8) & 0xff);
1348 for (i
= 0; i
< 4; i
++) {
1349 rsp_buffer_push(rsp
, ibs
->sel
.last_addition
[i
]);
1351 for (i
= 0; i
< 4; i
++) {
1352 rsp_buffer_push(rsp
, ibs
->sel
.last_clear
[i
]);
1354 /* Only support Reserve SEL */
1355 rsp_buffer_push(rsp
, (ibs
->sel
.overflow
<< 7) | 0x02);
1358 static void get_fru_area_info(IPMIBmcSim
*ibs
,
1359 uint8_t *cmd
, unsigned int cmd_len
,
1363 uint16_t fru_entry_size
;
1367 if (fruid
>= ibs
->fru
.nentries
) {
1368 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1372 fru_entry_size
= ibs
->fru
.areasize
;
1374 rsp_buffer_push(rsp
, fru_entry_size
& 0xff);
1375 rsp_buffer_push(rsp
, fru_entry_size
>> 8 & 0xff);
1376 rsp_buffer_push(rsp
, 0x0);
1379 static void read_fru_data(IPMIBmcSim
*ibs
,
1380 uint8_t *cmd
, unsigned int cmd_len
,
1390 offset
= (cmd
[3] | cmd
[4] << 8);
1392 if (fruid
>= ibs
->fru
.nentries
) {
1393 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1397 if (offset
>= ibs
->fru
.areasize
- 1) {
1398 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1402 fru_entry
= &ibs
->fru
.data
[fruid
* ibs
->fru
.areasize
];
1404 count
= MIN(cmd
[5], ibs
->fru
.areasize
- offset
);
1406 rsp_buffer_push(rsp
, count
& 0xff);
1407 for (i
= 0; i
< count
; i
++) {
1408 rsp_buffer_push(rsp
, fru_entry
[offset
+ i
]);
1412 static void write_fru_data(IPMIBmcSim
*ibs
,
1413 uint8_t *cmd
, unsigned int cmd_len
,
1422 offset
= (cmd
[3] | cmd
[4] << 8);
1424 if (fruid
>= ibs
->fru
.nentries
) {
1425 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1429 if (offset
>= ibs
->fru
.areasize
- 1) {
1430 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1434 fru_entry
= &ibs
->fru
.data
[fruid
* ibs
->fru
.areasize
];
1436 count
= MIN(cmd_len
- 5, ibs
->fru
.areasize
- offset
);
1438 memcpy(fru_entry
+ offset
, cmd
+ 5, count
);
1440 rsp_buffer_push(rsp
, count
& 0xff);
1443 static void reserve_sel(IPMIBmcSim
*ibs
,
1444 uint8_t *cmd
, unsigned int cmd_len
,
1447 rsp_buffer_push(rsp
, ibs
->sel
.reservation
& 0xff);
1448 rsp_buffer_push(rsp
, (ibs
->sel
.reservation
>> 8) & 0xff);
1451 static void get_sel_entry(IPMIBmcSim
*ibs
,
1452 uint8_t *cmd
, unsigned int cmd_len
,
1458 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sel
.reservation
) {
1459 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1463 if (ibs
->sel
.next_free
== 0) {
1464 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1468 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1471 if (cmd
[7] == 0xff) {
1473 } else if ((cmd
[7] + cmd
[6]) > 16) {
1474 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1480 val
= cmd
[4] | (cmd
[5] << 8);
1481 if (val
== 0xffff) {
1482 val
= ibs
->sel
.next_free
- 1;
1483 } else if (val
>= ibs
->sel
.next_free
) {
1484 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1487 if ((val
+ 1) == ibs
->sel
.next_free
) {
1488 rsp_buffer_push(rsp
, 0xff);
1489 rsp_buffer_push(rsp
, 0xff);
1491 rsp_buffer_push(rsp
, (val
+ 1) & 0xff);
1492 rsp_buffer_push(rsp
, ((val
+ 1) >> 8) & 0xff);
1494 for (; cmd
[6] < cmd
[7]; cmd
[6]++) {
1495 rsp_buffer_push(rsp
, ibs
->sel
.sel
[val
][cmd
[6]]);
1499 static void add_sel_entry(IPMIBmcSim
*ibs
,
1500 uint8_t *cmd
, unsigned int cmd_len
,
1503 if (sel_add_event(ibs
, cmd
+ 2)) {
1504 rsp_buffer_set_error(rsp
, IPMI_CC_OUT_OF_SPACE
);
1507 /* sel_add_event fills in the record number. */
1508 rsp_buffer_push(rsp
, cmd
[2]);
1509 rsp_buffer_push(rsp
, cmd
[3]);
1512 static void clear_sel(IPMIBmcSim
*ibs
,
1513 uint8_t *cmd
, unsigned int cmd_len
,
1516 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sel
.reservation
) {
1517 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1521 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1522 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1525 if (cmd
[7] == 0xaa) {
1526 ibs
->sel
.next_free
= 0;
1527 ibs
->sel
.overflow
= 0;
1528 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1529 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1530 sel_inc_reservation(&ibs
->sel
);
1531 } else if (cmd
[7] == 0) {
1532 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1534 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1539 static void get_sel_time(IPMIBmcSim
*ibs
,
1540 uint8_t *cmd
, unsigned int cmd_len
,
1544 struct ipmi_time now
;
1547 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
1548 rsp_buffer_push(rsp
, val
& 0xff);
1549 rsp_buffer_push(rsp
, (val
>> 8) & 0xff);
1550 rsp_buffer_push(rsp
, (val
>> 16) & 0xff);
1551 rsp_buffer_push(rsp
, (val
>> 24) & 0xff);
1554 static void set_sel_time(IPMIBmcSim
*ibs
,
1555 uint8_t *cmd
, unsigned int cmd_len
,
1559 struct ipmi_time now
;
1561 val
= cmd
[2] | (cmd
[3] << 8) | (cmd
[4] << 16) | (cmd
[5] << 24);
1563 ibs
->sel
.time_offset
= now
.tv_sec
- ((long) val
);
1566 static void platform_event_msg(IPMIBmcSim
*ibs
,
1567 uint8_t *cmd
, unsigned int cmd_len
,
1572 event
[2] = 2; /* System event record */
1573 event
[7] = cmd
[2]; /* Generator ID */
1575 event
[9] = cmd
[3]; /* EvMRev */
1576 event
[10] = cmd
[4]; /* Sensor type */
1577 event
[11] = cmd
[5]; /* Sensor number */
1578 event
[12] = cmd
[6]; /* Event dir / Event type */
1579 event
[13] = cmd
[7]; /* Event data 1 */
1580 event
[14] = cmd
[8]; /* Event data 2 */
1581 event
[15] = cmd
[9]; /* Event data 3 */
1583 if (sel_add_event(ibs
, event
)) {
1584 rsp_buffer_set_error(rsp
, IPMI_CC_OUT_OF_SPACE
);
1588 static void set_sensor_evt_enable(IPMIBmcSim
*ibs
,
1589 uint8_t *cmd
, unsigned int cmd_len
,
1594 if ((cmd
[2] >= MAX_SENSORS
) ||
1595 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1596 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1599 sens
= ibs
->sensors
+ cmd
[2];
1600 switch ((cmd
[3] >> 4) & 0x3) {
1601 case 0: /* Do not change */
1603 case 1: /* Enable bits */
1605 sens
->assert_enable
|= cmd
[4];
1608 sens
->assert_enable
|= cmd
[5] << 8;
1611 sens
->deassert_enable
|= cmd
[6];
1614 sens
->deassert_enable
|= cmd
[7] << 8;
1617 case 2: /* Disable bits */
1619 sens
->assert_enable
&= ~cmd
[4];
1622 sens
->assert_enable
&= ~(cmd
[5] << 8);
1625 sens
->deassert_enable
&= ~cmd
[6];
1628 sens
->deassert_enable
&= ~(cmd
[7] << 8);
1632 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1635 IPMI_SENSOR_SET_RET_STATUS(sens
, cmd
[3]);
1638 static void get_sensor_evt_enable(IPMIBmcSim
*ibs
,
1639 uint8_t *cmd
, unsigned int cmd_len
,
1644 if ((cmd
[2] >= MAX_SENSORS
) ||
1645 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1646 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1649 sens
= ibs
->sensors
+ cmd
[2];
1650 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1651 rsp_buffer_push(rsp
, sens
->assert_enable
& 0xff);
1652 rsp_buffer_push(rsp
, (sens
->assert_enable
>> 8) & 0xff);
1653 rsp_buffer_push(rsp
, sens
->deassert_enable
& 0xff);
1654 rsp_buffer_push(rsp
, (sens
->deassert_enable
>> 8) & 0xff);
1657 static void rearm_sensor_evts(IPMIBmcSim
*ibs
,
1658 uint8_t *cmd
, unsigned int cmd_len
,
1663 if ((cmd
[2] >= MAX_SENSORS
) ||
1664 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1665 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1668 sens
= ibs
->sensors
+ cmd
[2];
1670 if ((cmd
[3] & 0x80) == 0) {
1671 /* Just clear everything */
1677 static void get_sensor_evt_status(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];
1689 rsp_buffer_push(rsp
, sens
->reading
);
1690 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1691 rsp_buffer_push(rsp
, sens
->assert_states
& 0xff);
1692 rsp_buffer_push(rsp
, (sens
->assert_states
>> 8) & 0xff);
1693 rsp_buffer_push(rsp
, sens
->deassert_states
& 0xff);
1694 rsp_buffer_push(rsp
, (sens
->deassert_states
>> 8) & 0xff);
1697 static void get_sensor_reading(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
->states
& 0xff);
1712 if (IPMI_SENSOR_IS_DISCRETE(sens
)) {
1713 rsp_buffer_push(rsp
, (sens
->states
>> 8) & 0xff);
1717 static void set_sensor_type(IPMIBmcSim
*ibs
,
1718 uint8_t *cmd
, unsigned int cmd_len
,
1724 if ((cmd
[2] >= MAX_SENSORS
) ||
1725 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1726 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1729 sens
= ibs
->sensors
+ cmd
[2];
1730 sens
->sensor_type
= cmd
[3];
1731 sens
->evt_reading_type_code
= cmd
[4] & 0x7f;
1734 static void get_sensor_type(IPMIBmcSim
*ibs
,
1735 uint8_t *cmd
, unsigned int cmd_len
,
1741 if ((cmd
[2] >= MAX_SENSORS
) ||
1742 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1743 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1746 sens
= ibs
->sensors
+ cmd
[2];
1747 rsp_buffer_push(rsp
, sens
->sensor_type
);
1748 rsp_buffer_push(rsp
, sens
->evt_reading_type_code
);
1754 * 2 operation (see below for bits meaning)
1756 * 4:5 assertion states (optional)
1757 * 6:7 deassertion states (optional)
1758 * 8:10 event data 1,2,3 (optional)
1760 static void set_sensor_reading(IPMIBmcSim
*ibs
,
1761 uint8_t *cmd
, unsigned int cmd_len
,
1768 uint8_t new_reading
= 0;
1769 uint16_t new_assert_states
= 0;
1770 uint16_t new_deassert_states
= 0;
1771 bool change_reading
= false;
1772 bool change_assert
= false;
1773 bool change_deassert
= false;
1775 SENSOR_GEN_EVENT_NONE
,
1776 SENSOR_GEN_EVENT_DATA
,
1777 SENSOR_GEN_EVENT_BMC
,
1778 } do_gen_event
= SENSOR_GEN_EVENT_NONE
;
1780 if ((cmd
[2] >= MAX_SENSORS
) ||
1781 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1782 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1786 sens
= ibs
->sensors
+ cmd
[2];
1788 /* [1:0] Sensor Reading operation */
1789 switch ((cmd
[3]) & 0x3) {
1790 case 0: /* Do not change */
1792 case 1: /* write given value to sensor reading byte */
1793 new_reading
= cmd
[4];
1794 if (sens
->reading
!= new_reading
) {
1795 change_reading
= true;
1800 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1804 /* [3:2] Deassertion bits operation */
1805 switch ((cmd
[3] >> 2) & 0x3) {
1806 case 0: /* Do not change */
1808 case 1: /* write given value */
1810 new_deassert_states
= cmd
[7];
1811 change_deassert
= true;
1814 new_deassert_states
|= (cmd
[8] << 8);
1818 case 2: /* mask on */
1820 new_deassert_states
= (sens
->deassert_states
| cmd
[7]);
1821 change_deassert
= true;
1824 new_deassert_states
|= (sens
->deassert_states
| (cmd
[8] << 8));
1828 case 3: /* mask off */
1830 new_deassert_states
= (sens
->deassert_states
& cmd
[7]);
1831 change_deassert
= true;
1834 new_deassert_states
|= (sens
->deassert_states
& (cmd
[8] << 8));
1839 if (change_deassert
&& (new_deassert_states
== sens
->deassert_states
)) {
1840 change_deassert
= false;
1843 /* [5:4] Assertion bits operation */
1844 switch ((cmd
[3] >> 4) & 0x3) {
1845 case 0: /* Do not change */
1847 case 1: /* write given value */
1849 new_assert_states
= cmd
[5];
1850 change_assert
= true;
1853 new_assert_states
|= (cmd
[6] << 8);
1857 case 2: /* mask on */
1859 new_assert_states
= (sens
->assert_states
| cmd
[5]);
1860 change_assert
= true;
1863 new_assert_states
|= (sens
->assert_states
| (cmd
[6] << 8));
1867 case 3: /* mask off */
1869 new_assert_states
= (sens
->assert_states
& cmd
[5]);
1870 change_assert
= true;
1873 new_assert_states
|= (sens
->assert_states
& (cmd
[6] << 8));
1878 if (change_assert
&& (new_assert_states
== sens
->assert_states
)) {
1879 change_assert
= false;
1892 /* [7:6] Event Data Bytes operation */
1893 switch ((cmd
[3] >> 6) & 0x3) {
1895 * Don’t use Event Data bytes from this command. BMC will
1896 * generate it's own Event Data bytes based on its sensor
1899 evd1
= evd2
= evd3
= 0x0;
1900 do_gen_event
= SENSOR_GEN_EVENT_BMC
;
1903 * Write given values to event data bytes including bits
1904 * [3:0] Event Data 1.
1906 do_gen_event
= SENSOR_GEN_EVENT_DATA
;
1909 * Write given values to event data bytes excluding bits
1910 * [3:0] Event Data 1.
1913 do_gen_event
= SENSOR_GEN_EVENT_DATA
;
1916 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1921 * Event Data Bytes operation and parameter are inconsistent. The
1922 * Specs are not clear on that topic but generating an error seems
1925 if (do_gen_event
== SENSOR_GEN_EVENT_DATA
&& cmd_len
< 10) {
1926 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1931 if (change_reading
) {
1932 sens
->reading
= new_reading
;
1935 if (change_assert
) {
1936 sens
->assert_states
= new_assert_states
;
1939 if (change_deassert
) {
1940 sens
->deassert_states
= new_deassert_states
;
1943 /* TODO: handle threshold sensor */
1944 if (!IPMI_SENSOR_IS_DISCRETE(sens
)) {
1948 switch (do_gen_event
) {
1949 case SENSOR_GEN_EVENT_DATA
: {
1950 unsigned int bit
= evd1
& 0xf;
1951 uint16_t mask
= (1 << bit
);
1953 if (sens
->assert_states
& mask
& sens
->assert_enable
) {
1954 gen_event(ibs
, cmd
[2], 0, evd1
, evd2
, evd3
);
1957 if (sens
->deassert_states
& mask
& sens
->deassert_enable
) {
1958 gen_event(ibs
, cmd
[2], 1, evd1
, evd2
, evd3
);
1962 case SENSOR_GEN_EVENT_BMC
:
1964 * TODO: generate event and event data bytes depending on the
1968 case SENSOR_GEN_EVENT_NONE
:
1973 static const IPMICmdHandler chassis_cmds
[] = {
1974 [IPMI_CMD_GET_CHASSIS_CAPABILITIES
] = { chassis_capabilities
},
1975 [IPMI_CMD_GET_CHASSIS_STATUS
] = { chassis_status
},
1976 [IPMI_CMD_CHASSIS_CONTROL
] = { chassis_control
, 3 },
1977 [IPMI_CMD_GET_SYS_RESTART_CAUSE
] = { chassis_get_sys_restart_cause
}
1979 static const IPMINetfn chassis_netfn
= {
1980 .cmd_nums
= ARRAY_SIZE(chassis_cmds
),
1981 .cmd_handlers
= chassis_cmds
1984 static const IPMICmdHandler sensor_event_cmds
[] = {
1985 [IPMI_CMD_PLATFORM_EVENT_MSG
] = { platform_event_msg
, 10 },
1986 [IPMI_CMD_SET_SENSOR_EVT_ENABLE
] = { set_sensor_evt_enable
, 4 },
1987 [IPMI_CMD_GET_SENSOR_EVT_ENABLE
] = { get_sensor_evt_enable
, 3 },
1988 [IPMI_CMD_REARM_SENSOR_EVTS
] = { rearm_sensor_evts
, 4 },
1989 [IPMI_CMD_GET_SENSOR_EVT_STATUS
] = { get_sensor_evt_status
, 3 },
1990 [IPMI_CMD_GET_SENSOR_READING
] = { get_sensor_reading
, 3 },
1991 [IPMI_CMD_SET_SENSOR_TYPE
] = { set_sensor_type
, 5 },
1992 [IPMI_CMD_GET_SENSOR_TYPE
] = { get_sensor_type
, 3 },
1993 [IPMI_CMD_SET_SENSOR_READING
] = { set_sensor_reading
, 5 },
1995 static const IPMINetfn sensor_event_netfn
= {
1996 .cmd_nums
= ARRAY_SIZE(sensor_event_cmds
),
1997 .cmd_handlers
= sensor_event_cmds
2000 static const IPMICmdHandler app_cmds
[] = {
2001 [IPMI_CMD_GET_DEVICE_ID
] = { get_device_id
},
2002 [IPMI_CMD_COLD_RESET
] = { cold_reset
},
2003 [IPMI_CMD_WARM_RESET
] = { warm_reset
},
2004 [IPMI_CMD_SET_ACPI_POWER_STATE
] = { set_acpi_power_state
, 4 },
2005 [IPMI_CMD_GET_ACPI_POWER_STATE
] = { get_acpi_power_state
},
2006 [IPMI_CMD_GET_DEVICE_GUID
] = { get_device_guid
},
2007 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES
] = { set_bmc_global_enables
, 3 },
2008 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES
] = { get_bmc_global_enables
},
2009 [IPMI_CMD_CLR_MSG_FLAGS
] = { clr_msg_flags
, 3 },
2010 [IPMI_CMD_GET_MSG_FLAGS
] = { get_msg_flags
},
2011 [IPMI_CMD_GET_MSG
] = { get_msg
},
2012 [IPMI_CMD_SEND_MSG
] = { send_msg
, 3 },
2013 [IPMI_CMD_READ_EVT_MSG_BUF
] = { read_evt_msg_buf
},
2014 [IPMI_CMD_RESET_WATCHDOG_TIMER
] = { reset_watchdog_timer
},
2015 [IPMI_CMD_SET_WATCHDOG_TIMER
] = { set_watchdog_timer
, 8 },
2016 [IPMI_CMD_GET_WATCHDOG_TIMER
] = { get_watchdog_timer
},
2018 static const IPMINetfn app_netfn
= {
2019 .cmd_nums
= ARRAY_SIZE(app_cmds
),
2020 .cmd_handlers
= app_cmds
2023 static const IPMICmdHandler storage_cmds
[] = {
2024 [IPMI_CMD_GET_FRU_AREA_INFO
] = { get_fru_area_info
, 3 },
2025 [IPMI_CMD_READ_FRU_DATA
] = { read_fru_data
, 5 },
2026 [IPMI_CMD_WRITE_FRU_DATA
] = { write_fru_data
, 5 },
2027 [IPMI_CMD_GET_SDR_REP_INFO
] = { get_sdr_rep_info
},
2028 [IPMI_CMD_RESERVE_SDR_REP
] = { reserve_sdr_rep
},
2029 [IPMI_CMD_GET_SDR
] = { get_sdr
, 8 },
2030 [IPMI_CMD_ADD_SDR
] = { add_sdr
},
2031 [IPMI_CMD_CLEAR_SDR_REP
] = { clear_sdr_rep
, 8 },
2032 [IPMI_CMD_GET_SEL_INFO
] = { get_sel_info
},
2033 [IPMI_CMD_RESERVE_SEL
] = { reserve_sel
},
2034 [IPMI_CMD_GET_SEL_ENTRY
] = { get_sel_entry
, 8 },
2035 [IPMI_CMD_ADD_SEL_ENTRY
] = { add_sel_entry
, 18 },
2036 [IPMI_CMD_CLEAR_SEL
] = { clear_sel
, 8 },
2037 [IPMI_CMD_GET_SEL_TIME
] = { get_sel_time
},
2038 [IPMI_CMD_SET_SEL_TIME
] = { set_sel_time
, 6 },
2041 static const IPMINetfn storage_netfn
= {
2042 .cmd_nums
= ARRAY_SIZE(storage_cmds
),
2043 .cmd_handlers
= storage_cmds
2046 static void register_cmds(IPMIBmcSim
*s
)
2048 ipmi_sim_register_netfn(s
, IPMI_NETFN_CHASSIS
, &chassis_netfn
);
2049 ipmi_sim_register_netfn(s
, IPMI_NETFN_SENSOR_EVENT
, &sensor_event_netfn
);
2050 ipmi_sim_register_netfn(s
, IPMI_NETFN_APP
, &app_netfn
);
2051 ipmi_sim_register_netfn(s
, IPMI_NETFN_STORAGE
, &storage_netfn
);
2054 static uint8_t init_sdrs
[] = {
2055 /* Watchdog device */
2056 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
2057 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
2058 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2059 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
2060 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
2063 static void ipmi_sdr_init(IPMIBmcSim
*ibs
)
2070 sdrs_size
= sizeof(init_sdrs
);
2072 if (ibs
->sdr_filename
&&
2073 !g_file_get_contents(ibs
->sdr_filename
, (gchar
**) &sdrs
, &sdrs_size
,
2075 error_report("failed to load sdr file '%s'", ibs
->sdr_filename
);
2076 sdrs_size
= sizeof(init_sdrs
);
2080 for (i
= 0; i
< sdrs_size
; i
+= len
) {
2081 struct ipmi_sdr_header
*sdrh
;
2083 if (i
+ IPMI_SDR_HEADER_SIZE
> sdrs_size
) {
2084 error_report("Problem with recid 0x%4.4x", i
);
2087 sdrh
= (struct ipmi_sdr_header
*) &sdrs
[i
];
2088 len
= ipmi_sdr_length(sdrh
);
2089 if (i
+ len
> sdrs_size
) {
2090 error_report("Problem with recid 0x%4.4x", i
);
2093 sdr_add_entry(ibs
, sdrh
, len
, NULL
);
2096 if (sdrs
!= init_sdrs
) {
2101 static const VMStateDescription vmstate_ipmi_sim
= {
2102 .name
= TYPE_IPMI_BMC_SIMULATOR
,
2104 .minimum_version_id
= 1,
2105 .fields
= (VMStateField
[]) {
2106 VMSTATE_UINT8(bmc_global_enables
, IPMIBmcSim
),
2107 VMSTATE_UINT8(msg_flags
, IPMIBmcSim
),
2108 VMSTATE_BOOL(watchdog_initialized
, IPMIBmcSim
),
2109 VMSTATE_UINT8(watchdog_use
, IPMIBmcSim
),
2110 VMSTATE_UINT8(watchdog_action
, IPMIBmcSim
),
2111 VMSTATE_UINT8(watchdog_pretimeout
, IPMIBmcSim
),
2112 VMSTATE_BOOL(watchdog_expired
, IPMIBmcSim
),
2113 VMSTATE_UINT16(watchdog_timeout
, IPMIBmcSim
),
2114 VMSTATE_BOOL(watchdog_running
, IPMIBmcSim
),
2115 VMSTATE_BOOL(watchdog_preaction_ran
, IPMIBmcSim
),
2116 VMSTATE_INT64(watchdog_expiry
, IPMIBmcSim
),
2117 VMSTATE_UINT8_ARRAY(evtbuf
, IPMIBmcSim
, 16),
2118 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].status
, IPMIBmcSim
),
2119 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].reading
, IPMIBmcSim
),
2120 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].states
, IPMIBmcSim
),
2121 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_states
, IPMIBmcSim
),
2122 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].deassert_states
,
2124 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_enable
, IPMIBmcSim
),
2125 VMSTATE_END_OF_LIST()
2129 static void ipmi_fru_init(IPMIFru
*fru
)
2134 if (!fru
->filename
) {
2138 fsize
= get_image_size(fru
->filename
);
2140 size
= QEMU_ALIGN_UP(fsize
, fru
->areasize
);
2141 fru
->data
= g_malloc0(size
);
2142 if (load_image_size(fru
->filename
, fru
->data
, fsize
) != fsize
) {
2143 error_report("Could not load file '%s'", fru
->filename
);
2151 /* give one default FRU */
2152 size
= fru
->areasize
;
2153 fru
->data
= g_malloc0(size
);
2156 fru
->nentries
= size
/ fru
->areasize
;
2159 static void ipmi_sim_realize(DeviceState
*dev
, Error
**errp
)
2161 IPMIBmc
*b
= IPMI_BMC(dev
);
2163 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
2165 QTAILQ_INIT(&ibs
->rcvbufs
);
2167 ibs
->bmc_global_enables
= (1 << IPMI_BMC_EVENT_LOG_BIT
);
2168 ibs
->device_id
= 0x20;
2169 ibs
->ipmi_version
= 0x02; /* IPMI 2.0 */
2170 ibs
->restart_cause
= 0;
2171 for (i
= 0; i
< 4; i
++) {
2172 ibs
->sel
.last_addition
[i
] = 0xff;
2173 ibs
->sel
.last_clear
[i
] = 0xff;
2174 ibs
->sdr
.last_addition
[i
] = 0xff;
2175 ibs
->sdr
.last_clear
[i
] = 0xff;
2180 ipmi_fru_init(&ibs
->fru
);
2182 ibs
->acpi_power_state
[0] = 0;
2183 ibs
->acpi_power_state
[1] = 0;
2185 ipmi_init_sensors_from_sdrs(ibs
);
2188 ibs
->timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, ipmi_timeout
, ibs
);
2190 vmstate_register(NULL
, 0, &vmstate_ipmi_sim
, ibs
);
2193 static Property ipmi_sim_properties
[] = {
2194 DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim
, fru
.areasize
, 1024),
2195 DEFINE_PROP_STRING("frudatafile", IPMIBmcSim
, fru
.filename
),
2196 DEFINE_PROP_STRING("sdrfile", IPMIBmcSim
, sdr_filename
),
2197 DEFINE_PROP_UINT8("device_id", IPMIBmcSim
, device_id
, 0x20),
2198 DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim
, ipmi_version
, 0x02),
2199 DEFINE_PROP_UINT8("device_rev", IPMIBmcSim
, device_rev
, 0),
2200 DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim
, fwrev1
, 0),
2201 DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim
, fwrev2
, 0),
2202 DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim
, mfg_id
, 0),
2203 DEFINE_PROP_UINT16("product_id", IPMIBmcSim
, product_id
, 0),
2204 DEFINE_PROP_UUID_NODEFAULT("guid", IPMIBmcSim
, uuid
),
2205 DEFINE_PROP_END_OF_LIST(),
2208 static void ipmi_sim_class_init(ObjectClass
*oc
, void *data
)
2210 DeviceClass
*dc
= DEVICE_CLASS(oc
);
2211 IPMIBmcClass
*bk
= IPMI_BMC_CLASS(oc
);
2213 dc
->hotpluggable
= false;
2214 dc
->realize
= ipmi_sim_realize
;
2215 device_class_set_props(dc
, ipmi_sim_properties
);
2216 bk
->handle_command
= ipmi_sim_handle_command
;
2219 static const TypeInfo ipmi_sim_type
= {
2220 .name
= TYPE_IPMI_BMC_SIMULATOR
,
2221 .parent
= TYPE_IPMI_BMC
,
2222 .instance_size
= sizeof(IPMIBmcSim
),
2223 .class_init
= ipmi_sim_class_init
,
2226 static void ipmi_sim_register_types(void)
2228 type_register_static(&ipmi_sim_type
);
2231 type_init(ipmi_sim_register_types
)