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
53 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */
55 #define IPMI_CMD_GET_DEVICE_ID 0x01
56 #define IPMI_CMD_COLD_RESET 0x02
57 #define IPMI_CMD_WARM_RESET 0x03
58 #define IPMI_CMD_SET_ACPI_POWER_STATE 0x06
59 #define IPMI_CMD_GET_ACPI_POWER_STATE 0x07
60 #define IPMI_CMD_GET_DEVICE_GUID 0x08
61 #define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22
62 #define IPMI_CMD_SET_WATCHDOG_TIMER 0x24
63 #define IPMI_CMD_GET_WATCHDOG_TIMER 0x25
64 #define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e
65 #define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f
66 #define IPMI_CMD_CLR_MSG_FLAGS 0x30
67 #define IPMI_CMD_GET_MSG_FLAGS 0x31
68 #define IPMI_CMD_GET_MSG 0x33
69 #define IPMI_CMD_SEND_MSG 0x34
70 #define IPMI_CMD_READ_EVT_MSG_BUF 0x35
72 #define IPMI_NETFN_STORAGE 0x0a
74 #define IPMI_CMD_GET_SDR_REP_INFO 0x20
75 #define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21
76 #define IPMI_CMD_RESERVE_SDR_REP 0x22
77 #define IPMI_CMD_GET_SDR 0x23
78 #define IPMI_CMD_ADD_SDR 0x24
79 #define IPMI_CMD_PARTIAL_ADD_SDR 0x25
80 #define IPMI_CMD_DELETE_SDR 0x26
81 #define IPMI_CMD_CLEAR_SDR_REP 0x27
82 #define IPMI_CMD_GET_SDR_REP_TIME 0x28
83 #define IPMI_CMD_SET_SDR_REP_TIME 0x29
84 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A
85 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B
86 #define IPMI_CMD_RUN_INIT_AGENT 0x2C
87 #define IPMI_CMD_GET_FRU_AREA_INFO 0x10
88 #define IPMI_CMD_READ_FRU_DATA 0x11
89 #define IPMI_CMD_WRITE_FRU_DATA 0x12
90 #define IPMI_CMD_GET_SEL_INFO 0x40
91 #define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
92 #define IPMI_CMD_RESERVE_SEL 0x42
93 #define IPMI_CMD_GET_SEL_ENTRY 0x43
94 #define IPMI_CMD_ADD_SEL_ENTRY 0x44
95 #define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
96 #define IPMI_CMD_DELETE_SEL_ENTRY 0x46
97 #define IPMI_CMD_CLEAR_SEL 0x47
98 #define IPMI_CMD_GET_SEL_TIME 0x48
99 #define IPMI_CMD_SET_SEL_TIME 0x49
102 /* Same as a timespec struct. */
108 #define MAX_SEL_SIZE 128
110 typedef struct IPMISel
{
111 uint8_t sel
[MAX_SEL_SIZE
][16];
112 unsigned int next_free
;
114 uint16_t reservation
;
115 uint8_t last_addition
[4];
116 uint8_t last_clear
[4];
120 #define MAX_SDR_SIZE 16384
122 typedef struct IPMISdr
{
123 uint8_t sdr
[MAX_SDR_SIZE
];
124 unsigned int next_free
;
125 uint16_t next_rec_id
;
126 uint16_t reservation
;
127 uint8_t last_addition
[4];
128 uint8_t last_clear
[4];
132 typedef struct IPMIFru
{
134 unsigned int nentries
;
139 typedef struct IPMISensor
{
142 uint16_t states_suppt
;
143 uint16_t assert_suppt
;
144 uint16_t deassert_suppt
;
146 uint16_t assert_states
;
147 uint16_t deassert_states
;
148 uint16_t assert_enable
;
149 uint16_t deassert_enable
;
151 uint8_t evt_reading_type_code
;
153 #define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01)
154 #define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \
156 #define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40)
157 #define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \
159 #define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80)
160 #define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \
162 #define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0)
163 #define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
165 #define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
167 #define MAX_SENSORS 20
168 #define IPMI_WATCHDOG_SENSOR 0
170 #define MAX_NETFNS 64
172 typedef struct IPMIRcvBufEntry
{
173 QTAILQ_ENTRY(IPMIRcvBufEntry
) entry
;
175 uint8_t buf
[MAX_IPMI_MSG_SIZE
];
183 uint8_t bmc_global_enables
;
186 bool watchdog_initialized
;
187 uint8_t watchdog_use
;
188 uint8_t watchdog_action
;
189 uint8_t watchdog_pretimeout
; /* In seconds */
190 bool watchdog_expired
;
191 uint16_t watchdog_timeout
; /* in 100's of milliseconds */
193 bool watchdog_running
;
194 bool watchdog_preaction_ran
;
195 int64_t watchdog_expiry
;
198 uint8_t ipmi_version
;
205 uint8_t restart_cause
;
207 uint8_t acpi_power_state
[2];
213 IPMISensor sensors
[MAX_SENSORS
];
216 /* Odd netfns are for responses, so we only need the even ones. */
217 const IPMINetfn
*netfns
[MAX_NETFNS
/ 2];
219 /* We allow one event in the buffer */
222 QTAILQ_HEAD(, IPMIRcvBufEntry
) rcvbufs
;
225 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3)
226 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1)
227 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0)
228 #define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
229 (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
230 #define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
231 (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
232 #define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
233 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
235 #define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
236 #define IPMI_BMC_EVBUF_FULL_INT_BIT 1
237 #define IPMI_BMC_EVENT_MSG_BUF_BIT 2
238 #define IPMI_BMC_EVENT_LOG_BIT 3
239 #define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
240 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
241 #define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
242 (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
243 #define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
244 (1 << IPMI_BMC_EVENT_LOG_BIT))
245 #define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
246 (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
248 #define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
249 #define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
250 #define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
251 #define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
252 #define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
253 #define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
254 #define IPMI_BMC_WATCHDOG_PRE_NONE 0
255 #define IPMI_BMC_WATCHDOG_PRE_SMI 1
256 #define IPMI_BMC_WATCHDOG_PRE_NMI 2
257 #define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3
258 #define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
259 #define IPMI_BMC_WATCHDOG_ACTION_NONE 0
260 #define IPMI_BMC_WATCHDOG_ACTION_RESET 1
261 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
262 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
264 #define RSP_BUFFER_INITIALIZER { }
266 static inline void rsp_buffer_pushmore(RspBuffer
*rsp
, uint8_t *bytes
,
269 if (rsp
->len
+ n
>= sizeof(rsp
->buffer
)) {
270 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
274 memcpy(&rsp
->buffer
[rsp
->len
], bytes
, n
);
278 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
);
280 static void ipmi_gettime(struct ipmi_time
*time
)
284 stime
= qemu_clock_get_ns(QEMU_CLOCK_HOST
);
285 time
->tv_sec
= stime
/ 1000000000LL;
286 time
->tv_nsec
= stime
% 1000000000LL;
289 static int64_t ipmi_getmonotime(void)
291 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
294 static void ipmi_timeout(void *opaque
)
296 IPMIBmcSim
*ibs
= opaque
;
298 ipmi_sim_handle_timeout(ibs
);
301 static void set_timestamp(IPMIBmcSim
*ibs
, uint8_t *ts
)
304 struct ipmi_time now
;
307 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
309 ts
[1] = (val
>> 8) & 0xff;
310 ts
[2] = (val
>> 16) & 0xff;
311 ts
[3] = (val
>> 24) & 0xff;
314 static void sdr_inc_reservation(IPMISdr
*sdr
)
317 if (sdr
->reservation
== 0) {
318 sdr
->reservation
= 1;
322 static int sdr_add_entry(IPMIBmcSim
*ibs
,
323 const struct ipmi_sdr_header
*sdrh_entry
,
324 unsigned int len
, uint16_t *recid
)
326 struct ipmi_sdr_header
*sdrh
=
327 (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[ibs
->sdr
.next_free
];
329 if ((len
< IPMI_SDR_HEADER_SIZE
) || (len
> 255)) {
333 if (ipmi_sdr_length(sdrh_entry
) != len
) {
337 if (ibs
->sdr
.next_free
+ len
> MAX_SDR_SIZE
) {
338 ibs
->sdr
.overflow
= 1;
342 memcpy(sdrh
, sdrh_entry
, len
);
343 sdrh
->rec_id
[0] = ibs
->sdr
.next_rec_id
& 0xff;
344 sdrh
->rec_id
[1] = (ibs
->sdr
.next_rec_id
>> 8) & 0xff;
345 sdrh
->sdr_version
= 0x51; /* Conform to IPMI 1.5 spec */
348 *recid
= ibs
->sdr
.next_rec_id
;
350 ibs
->sdr
.next_rec_id
++;
351 set_timestamp(ibs
, ibs
->sdr
.last_addition
);
352 ibs
->sdr
.next_free
+= len
;
353 sdr_inc_reservation(&ibs
->sdr
);
357 static int sdr_find_entry(IPMISdr
*sdr
, uint16_t recid
,
358 unsigned int *retpos
, uint16_t *nextrec
)
360 unsigned int pos
= *retpos
;
362 while (pos
< sdr
->next_free
) {
363 struct ipmi_sdr_header
*sdrh
=
364 (struct ipmi_sdr_header
*) &sdr
->sdr
[pos
];
365 uint16_t trec
= ipmi_sdr_recid(sdrh
);
366 unsigned int nextpos
= pos
+ ipmi_sdr_length(sdrh
);
370 if (nextpos
>= sdr
->next_free
) {
373 *nextrec
= (sdr
->sdr
[nextpos
] |
374 (sdr
->sdr
[nextpos
+ 1] << 8));
385 int ipmi_bmc_sdr_find(IPMIBmc
*b
, uint16_t recid
,
386 const struct ipmi_sdr_compact
**sdr
, uint16_t *nextrec
)
389 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
393 if (sdr_find_entry(&ibs
->sdr
, recid
, &pos
, nextrec
)) {
397 *sdr
= (const struct ipmi_sdr_compact
*) &ibs
->sdr
.sdr
[pos
];
401 static void sel_inc_reservation(IPMISel
*sel
)
404 if (sel
->reservation
== 0) {
405 sel
->reservation
= 1;
409 /* Returns 1 if the SEL is full and can't hold the event. */
410 static int sel_add_event(IPMIBmcSim
*ibs
, uint8_t *event
)
416 set_timestamp(ibs
, ts
);
417 if (event
[2] < 0xe0) { /* Don't set timestamps for type 0xe0-0xff. */
418 memcpy(event
+ 3, ts
, 4);
420 if (ibs
->sel
.next_free
== MAX_SEL_SIZE
) {
421 ibs
->sel
.overflow
= 1;
424 event
[0] = ibs
->sel
.next_free
& 0xff;
425 event
[1] = (ibs
->sel
.next_free
>> 8) & 0xff;
426 memcpy(ibs
->sel
.last_addition
, ts
, 4);
427 memcpy(ibs
->sel
.sel
[ibs
->sel
.next_free
], event
, 16);
428 ibs
->sel
.next_free
++;
429 sel_inc_reservation(&ibs
->sel
);
433 static int attn_set(IPMIBmcSim
*ibs
)
435 return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
)
436 || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
)
437 || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs
);
440 static int attn_irq_enabled(IPMIBmcSim
*ibs
)
442 return (IPMI_BMC_MSG_INTS_ON(ibs
) &&
443 (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs
) ||
444 IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs
)))
445 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs
) &&
446 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs
));
449 void ipmi_bmc_gen_event(IPMIBmc
*b
, uint8_t *evt
, bool log
)
451 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
452 IPMIInterface
*s
= ibs
->parent
.intf
;
453 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
455 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
459 if (log
&& IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
460 sel_add_event(ibs
, evt
);
463 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
467 memcpy(ibs
->evtbuf
, evt
, 16);
468 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
469 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
473 static void gen_event(IPMIBmcSim
*ibs
, unsigned int sens_num
, uint8_t deassert
,
474 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
476 IPMIInterface
*s
= ibs
->parent
.intf
;
477 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
479 IPMISensor
*sens
= ibs
->sensors
+ sens_num
;
481 if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs
)) {
484 if (!IPMI_SENSOR_GET_EVENTS_ON(sens
)) {
488 evt
[2] = 0x2; /* System event record */
489 evt
[7] = ibs
->parent
.slave_addr
;
491 evt
[9] = 0x04; /* Format version */
492 evt
[10] = sens
->sensor_type
;
494 evt
[12] = sens
->evt_reading_type_code
| (!!deassert
<< 7);
499 if (IPMI_BMC_EVENT_LOG_ENABLED(ibs
)) {
500 sel_add_event(ibs
, evt
);
503 if (ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
) {
507 memcpy(ibs
->evtbuf
, evt
, 16);
508 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
509 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
512 static void sensor_set_discrete_bit(IPMIBmcSim
*ibs
, unsigned int sensor
,
513 unsigned int bit
, unsigned int val
,
514 uint8_t evd1
, uint8_t evd2
, uint8_t evd3
)
519 if (sensor
>= MAX_SENSORS
) {
527 sens
= ibs
->sensors
+ sensor
;
529 sens
->states
|= mask
& sens
->states_suppt
;
530 if (sens
->assert_states
& mask
) {
531 return; /* Already asserted */
533 sens
->assert_states
|= mask
& sens
->assert_suppt
;
534 if (sens
->assert_enable
& mask
& sens
->assert_states
) {
535 /* Send an event on assert */
536 gen_event(ibs
, sensor
, 0, evd1
, evd2
, evd3
);
539 sens
->states
&= ~(mask
& sens
->states_suppt
);
540 if (sens
->deassert_states
& mask
) {
541 return; /* Already deasserted */
543 sens
->deassert_states
|= mask
& sens
->deassert_suppt
;
544 if (sens
->deassert_enable
& mask
& sens
->deassert_states
) {
545 /* Send an event on deassert */
546 gen_event(ibs
, sensor
, 1, evd1
, evd2
, evd3
);
551 static void ipmi_init_sensors_from_sdrs(IPMIBmcSim
*s
)
556 for (i
= 0; i
< MAX_SENSORS
; i
++) {
557 memset(s
->sensors
+ i
, 0, sizeof(*sens
));
561 for (i
= 0; !sdr_find_entry(&s
->sdr
, i
, &pos
, NULL
); i
++) {
562 struct ipmi_sdr_compact
*sdr
=
563 (struct ipmi_sdr_compact
*) &s
->sdr
.sdr
[pos
];
564 unsigned int len
= sdr
->header
.rec_length
;
569 if (sdr
->header
.rec_type
!= IPMI_SDR_COMPACT_TYPE
) {
570 continue; /* Not a sensor SDR we set from */
573 if (sdr
->sensor_owner_number
>= MAX_SENSORS
) {
576 sens
= s
->sensors
+ sdr
->sensor_owner_number
;
578 IPMI_SENSOR_SET_PRESENT(sens
, 1);
579 IPMI_SENSOR_SET_SCAN_ON(sens
, (sdr
->sensor_init
>> 6) & 1);
580 IPMI_SENSOR_SET_EVENTS_ON(sens
, (sdr
->sensor_init
>> 5) & 1);
581 sens
->assert_suppt
= sdr
->assert_mask
[0] | (sdr
->assert_mask
[1] << 8);
582 sens
->deassert_suppt
=
583 sdr
->deassert_mask
[0] | (sdr
->deassert_mask
[1] << 8);
585 sdr
->discrete_mask
[0] | (sdr
->discrete_mask
[1] << 8);
586 sens
->sensor_type
= sdr
->sensor_type
;
587 sens
->evt_reading_type_code
= sdr
->reading_type
& 0x7f;
589 /* Enable all the events that are supported. */
590 sens
->assert_enable
= sens
->assert_suppt
;
591 sens
->deassert_enable
= sens
->deassert_suppt
;
595 int ipmi_sim_register_netfn(IPMIBmcSim
*s
, unsigned int netfn
,
596 const IPMINetfn
*netfnd
)
598 if ((netfn
& 1) || (netfn
>= MAX_NETFNS
) || (s
->netfns
[netfn
/ 2])) {
601 s
->netfns
[netfn
/ 2] = netfnd
;
605 static const IPMICmdHandler
*ipmi_get_handler(IPMIBmcSim
*ibs
,
609 const IPMICmdHandler
*hdl
;
611 if (netfn
& 1 || netfn
>= MAX_NETFNS
|| !ibs
->netfns
[netfn
/ 2]) {
615 if (cmd
>= ibs
->netfns
[netfn
/ 2]->cmd_nums
) {
619 hdl
= &ibs
->netfns
[netfn
/ 2]->cmd_handlers
[cmd
];
620 if (!hdl
->cmd_handler
) {
627 static void next_timeout(IPMIBmcSim
*ibs
)
630 if (ibs
->watchdog_running
) {
631 next
= ibs
->watchdog_expiry
;
634 next
= ipmi_getmonotime() + 60 * 1000000000LL;
636 timer_mod_ns(ibs
->timer
, next
);
639 static void ipmi_sim_handle_command(IPMIBmc
*b
,
640 uint8_t *cmd
, unsigned int cmd_len
,
641 unsigned int max_cmd_len
,
644 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
645 IPMIInterface
*s
= ibs
->parent
.intf
;
646 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
647 const IPMICmdHandler
*hdl
;
648 RspBuffer rsp
= RSP_BUFFER_INITIALIZER
;
650 /* Set up the response, set the low bit of NETFN. */
651 /* Note that max_rsp_len must be at least 3 */
652 if (sizeof(rsp
.buffer
) < 3) {
653 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
657 rsp_buffer_push(&rsp
, cmd
[0] | 0x04);
658 rsp_buffer_push(&rsp
, cmd
[1]);
659 rsp_buffer_push(&rsp
, 0); /* Assume success */
661 /* If it's too short or it was truncated, return an error. */
663 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
666 if (cmd_len
> max_cmd_len
) {
667 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_TRUNCATED
);
671 if ((cmd
[0] & 0x03) != 0) {
672 /* Only have stuff on LUN 0 */
673 rsp_buffer_set_error(&rsp
, IPMI_CC_COMMAND_INVALID_FOR_LUN
);
677 hdl
= ipmi_get_handler(ibs
, cmd
[0] >> 2, cmd
[1]);
679 rsp_buffer_set_error(&rsp
, IPMI_CC_INVALID_CMD
);
683 if (cmd_len
< hdl
->cmd_len_min
) {
684 rsp_buffer_set_error(&rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
688 hdl
->cmd_handler(ibs
, cmd
, cmd_len
, &rsp
);
691 k
->handle_rsp(s
, msg_id
, rsp
.buffer
, rsp
.len
);
696 static void ipmi_sim_handle_timeout(IPMIBmcSim
*ibs
)
698 IPMIInterface
*s
= ibs
->parent
.intf
;
699 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
701 if (!ibs
->watchdog_running
) {
705 if (!ibs
->watchdog_preaction_ran
) {
706 switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
)) {
707 case IPMI_BMC_WATCHDOG_PRE_NMI
:
708 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
709 k
->do_hw_op(s
, IPMI_SEND_NMI
, 0);
710 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
711 0xc8, (2 << 4) | 0xf, 0xff);
714 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
715 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK
;
716 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
717 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 8, 1,
718 0xc8, (3 << 4) | 0xf, 0xff);
725 ibs
->watchdog_preaction_ran
= 1;
726 /* Issued the pretimeout, do the rest of the timeout now. */
727 ibs
->watchdog_expiry
= ipmi_getmonotime();
728 ibs
->watchdog_expiry
+= ibs
->watchdog_pretimeout
* 1000000000LL;
733 ibs
->watchdog_running
= 0; /* Stop the watchdog on a timeout */
734 ibs
->watchdog_expired
|= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs
));
735 switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
)) {
736 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
737 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 0, 1,
738 0xc0, ibs
->watchdog_use
& 0xf, 0xff);
741 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
742 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 1, 1,
743 0xc1, ibs
->watchdog_use
& 0xf, 0xff);
744 k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0);
747 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
748 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
749 0xc2, ibs
->watchdog_use
& 0xf, 0xff);
750 k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0);
753 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
754 sensor_set_discrete_bit(ibs
, IPMI_WATCHDOG_SENSOR
, 2, 1,
755 0xc3, ibs
->watchdog_use
& 0xf, 0xff);
756 k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0);
764 static void chassis_capabilities(IPMIBmcSim
*ibs
,
765 uint8_t *cmd
, unsigned int cmd_len
,
768 rsp_buffer_push(rsp
, 0);
769 rsp_buffer_push(rsp
, ibs
->parent
.slave_addr
);
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
);
775 static void chassis_status(IPMIBmcSim
*ibs
,
776 uint8_t *cmd
, unsigned int cmd_len
,
779 rsp_buffer_push(rsp
, 0x61); /* Unknown power restore, power is on */
780 rsp_buffer_push(rsp
, 0);
781 rsp_buffer_push(rsp
, 0);
782 rsp_buffer_push(rsp
, 0);
785 static void chassis_control(IPMIBmcSim
*ibs
,
786 uint8_t *cmd
, unsigned int cmd_len
,
789 IPMIInterface
*s
= ibs
->parent
.intf
;
790 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
792 switch (cmd
[2] & 0xf) {
793 case 0: /* power down */
794 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 0));
796 case 1: /* power up */
797 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERON_CHASSIS
, 0));
799 case 2: /* power cycle */
800 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 0));
802 case 3: /* hard reset */
803 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 0));
805 case 4: /* pulse diagnostic interrupt */
806 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_PULSE_DIAG_IRQ
, 0));
808 case 5: /* soft shutdown via ACPI by overtemp emulation */
809 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
,
810 IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP
, 0));
813 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
818 static void chassis_get_sys_restart_cause(IPMIBmcSim
*ibs
,
819 uint8_t *cmd
, unsigned int cmd_len
,
823 rsp_buffer_push(rsp
, ibs
->restart_cause
& 0xf); /* Restart Cause */
824 rsp_buffer_push(rsp
, 0); /* Channel 0 */
827 static void get_device_id(IPMIBmcSim
*ibs
,
828 uint8_t *cmd
, unsigned int cmd_len
,
831 rsp_buffer_push(rsp
, ibs
->device_id
);
832 rsp_buffer_push(rsp
, ibs
->device_rev
& 0xf);
833 rsp_buffer_push(rsp
, ibs
->fwrev1
& 0x7f);
834 rsp_buffer_push(rsp
, ibs
->fwrev2
);
835 rsp_buffer_push(rsp
, ibs
->ipmi_version
);
836 rsp_buffer_push(rsp
, 0x07); /* sensor, SDR, and SEL. */
837 rsp_buffer_push(rsp
, ibs
->mfg_id
& 0xff);
838 rsp_buffer_push(rsp
, (ibs
->mfg_id
>> 8) & 0xff);
839 rsp_buffer_push(rsp
, (ibs
->mfg_id
>> 16) & 0xff);
840 rsp_buffer_push(rsp
, ibs
->product_id
& 0xff);
841 rsp_buffer_push(rsp
, (ibs
->product_id
>> 8) & 0xff);
844 static void set_global_enables(IPMIBmcSim
*ibs
, uint8_t val
)
846 IPMIInterface
*s
= ibs
->parent
.intf
;
847 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
850 ibs
->bmc_global_enables
= val
;
852 irqs_on
= val
& (IPMI_BMC_EVBUF_FULL_INT_BIT
|
853 IPMI_BMC_RCV_MSG_QUEUE_INT_BIT
);
855 k
->set_irq_enable(s
, irqs_on
);
858 static void cold_reset(IPMIBmcSim
*ibs
,
859 uint8_t *cmd
, unsigned int cmd_len
,
862 IPMIInterface
*s
= ibs
->parent
.intf
;
863 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
865 /* Disable all interrupts */
866 set_global_enables(ibs
, 1 << IPMI_BMC_EVENT_LOG_BIT
);
873 static void warm_reset(IPMIBmcSim
*ibs
,
874 uint8_t *cmd
, unsigned int cmd_len
,
877 IPMIInterface
*s
= ibs
->parent
.intf
;
878 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
884 static void set_acpi_power_state(IPMIBmcSim
*ibs
,
885 uint8_t *cmd
, unsigned int cmd_len
,
888 ibs
->acpi_power_state
[0] = cmd
[2];
889 ibs
->acpi_power_state
[1] = cmd
[3];
892 static void get_acpi_power_state(IPMIBmcSim
*ibs
,
893 uint8_t *cmd
, unsigned int cmd_len
,
896 rsp_buffer_push(rsp
, ibs
->acpi_power_state
[0]);
897 rsp_buffer_push(rsp
, ibs
->acpi_power_state
[1]);
900 static void get_device_guid(IPMIBmcSim
*ibs
,
901 uint8_t *cmd
, unsigned int cmd_len
,
906 /* An uninitialized uuid is all zeros, use that to know if it is set. */
907 for (i
= 0; i
< 16; i
++) {
908 if (ibs
->uuid
.data
[i
]) {
912 /* No uuid is set, return an error. */
913 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_CMD
);
917 for (i
= 0; i
< 16; i
++) {
918 rsp_buffer_push(rsp
, ibs
->uuid
.data
[i
]);
922 static void set_bmc_global_enables(IPMIBmcSim
*ibs
,
923 uint8_t *cmd
, unsigned int cmd_len
,
926 set_global_enables(ibs
, cmd
[2]);
929 static void get_bmc_global_enables(IPMIBmcSim
*ibs
,
930 uint8_t *cmd
, unsigned int cmd_len
,
933 rsp_buffer_push(rsp
, ibs
->bmc_global_enables
);
936 static void clr_msg_flags(IPMIBmcSim
*ibs
,
937 uint8_t *cmd
, unsigned int cmd_len
,
940 IPMIInterface
*s
= ibs
->parent
.intf
;
941 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
943 ibs
->msg_flags
&= ~cmd
[2];
944 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
947 static void get_msg_flags(IPMIBmcSim
*ibs
,
948 uint8_t *cmd
, unsigned int cmd_len
,
951 rsp_buffer_push(rsp
, ibs
->msg_flags
);
954 static void read_evt_msg_buf(IPMIBmcSim
*ibs
,
955 uint8_t *cmd
, unsigned int cmd_len
,
958 IPMIInterface
*s
= ibs
->parent
.intf
;
959 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
962 if (!(ibs
->msg_flags
& IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
)) {
963 rsp_buffer_set_error(rsp
, 0x80);
966 for (i
= 0; i
< 16; i
++) {
967 rsp_buffer_push(rsp
, ibs
->evtbuf
[i
]);
969 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL
;
970 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
973 static void get_msg(IPMIBmcSim
*ibs
,
974 uint8_t *cmd
, unsigned int cmd_len
,
977 IPMIRcvBufEntry
*msg
;
979 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
980 rsp_buffer_set_error(rsp
, 0x80); /* Queue empty */
983 rsp_buffer_push(rsp
, 0); /* Channel 0 */
984 msg
= QTAILQ_FIRST(&ibs
->rcvbufs
);
985 rsp_buffer_pushmore(rsp
, msg
->buf
, msg
->len
);
986 QTAILQ_REMOVE(&ibs
->rcvbufs
, msg
, entry
);
989 if (QTAILQ_EMPTY(&ibs
->rcvbufs
)) {
990 IPMIInterface
*s
= ibs
->parent
.intf
;
991 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
993 ibs
->msg_flags
&= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
994 k
->set_atn(s
, attn_set(ibs
), attn_irq_enabled(ibs
));
1001 static unsigned char
1002 ipmb_checksum(unsigned char *data
, int size
, unsigned char csum
)
1004 for (; size
> 0; size
--, data
++) {
1011 static void send_msg(IPMIBmcSim
*ibs
,
1012 uint8_t *cmd
, unsigned int cmd_len
,
1015 IPMIInterface
*s
= ibs
->parent
.intf
;
1016 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1017 IPMIRcvBufEntry
*msg
;
1019 uint8_t netfn
, rqLun
, rsLun
, rqSeq
;
1022 /* We only handle channel 0 with no options */
1023 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1028 rsp_buffer_set_error(rsp
, IPMI_CC_REQUEST_DATA_LENGTH_INVALID
);
1032 if (cmd
[3] != 0x40) {
1033 /* We only emulate a MC at address 0x40. */
1034 rsp_buffer_set_error(rsp
, 0x83); /* NAK on write */
1038 cmd
+= 3; /* Skip the header. */
1042 * At this point we "send" the message successfully. Any error will
1043 * be returned in the response.
1045 if (ipmb_checksum(cmd
, cmd_len
, 0) != 0 ||
1046 cmd
[3] != 0x20) { /* Improper response address */
1047 return; /* No response */
1050 netfn
= cmd
[1] >> 2;
1051 rqLun
= cmd
[4] & 0x3;
1052 rsLun
= cmd
[1] & 0x3;
1053 rqSeq
= cmd
[4] >> 2;
1056 /* We only support LUN 2 coming back to us. */
1060 msg
= g_malloc(sizeof(*msg
));
1061 msg
->buf
[0] = ((netfn
| 1) << 2) | rqLun
; /* NetFN, and make a response */
1062 msg
->buf
[1] = ipmb_checksum(msg
->buf
, 1, 0);
1063 msg
->buf
[2] = cmd
[0]; /* rsSA */
1064 msg
->buf
[3] = (rqSeq
<< 2) | rsLun
;
1065 msg
->buf
[4] = cmd
[5]; /* Cmd */
1066 msg
->buf
[5] = 0; /* Completion Code */
1069 if ((cmd
[1] >> 2) != IPMI_NETFN_APP
|| cmd
[5] != IPMI_CMD_GET_DEVICE_ID
) {
1070 /* Not a command we handle. */
1071 msg
->buf
[5] = IPMI_CC_INVALID_CMD
;
1075 buf
= msg
->buf
+ msg
->len
; /* After the CC */
1090 msg
->buf
[msg
->len
] = ipmb_checksum(msg
->buf
, msg
->len
, 0);
1092 QTAILQ_INSERT_TAIL(&ibs
->rcvbufs
, msg
, entry
);
1093 ibs
->msg_flags
|= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE
;
1094 k
->set_atn(s
, 1, attn_irq_enabled(ibs
));
1097 static void do_watchdog_reset(IPMIBmcSim
*ibs
)
1099 if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs
) ==
1100 IPMI_BMC_WATCHDOG_ACTION_NONE
) {
1101 ibs
->watchdog_running
= 0;
1104 ibs
->watchdog_preaction_ran
= 0;
1107 /* Timeout is in tenths of a second, offset is in seconds */
1108 ibs
->watchdog_expiry
= ipmi_getmonotime();
1109 ibs
->watchdog_expiry
+= ibs
->watchdog_timeout
* 100000000LL;
1110 if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs
) != IPMI_BMC_WATCHDOG_PRE_NONE
) {
1111 ibs
->watchdog_expiry
-= ibs
->watchdog_pretimeout
* 1000000000LL;
1113 ibs
->watchdog_running
= 1;
1116 static void reset_watchdog_timer(IPMIBmcSim
*ibs
,
1117 uint8_t *cmd
, unsigned int cmd_len
,
1120 if (!ibs
->watchdog_initialized
) {
1121 rsp_buffer_set_error(rsp
, 0x80);
1124 do_watchdog_reset(ibs
);
1127 static void set_watchdog_timer(IPMIBmcSim
*ibs
,
1128 uint8_t *cmd
, unsigned int cmd_len
,
1131 IPMIInterface
*s
= ibs
->parent
.intf
;
1132 IPMIInterfaceClass
*k
= IPMI_INTERFACE_GET_CLASS(s
);
1135 val
= cmd
[2] & 0x7; /* Validate use */
1136 if (val
== 0 || val
> 5) {
1137 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1140 val
= cmd
[3] & 0x7; /* Validate action */
1142 case IPMI_BMC_WATCHDOG_ACTION_NONE
:
1145 case IPMI_BMC_WATCHDOG_ACTION_RESET
:
1146 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_RESET_CHASSIS
, 1));
1149 case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN
:
1150 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWEROFF_CHASSIS
, 1));
1153 case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE
:
1154 rsp_buffer_set_error(rsp
, k
->do_hw_op(s
, IPMI_POWERCYCLE_CHASSIS
, 1));
1158 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1160 if (rsp
->buffer
[2]) {
1161 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1165 val
= (cmd
[3] >> 4) & 0x7; /* Validate preaction */
1167 case IPMI_BMC_WATCHDOG_PRE_MSG_INT
:
1168 case IPMI_BMC_WATCHDOG_PRE_NONE
:
1171 case IPMI_BMC_WATCHDOG_PRE_NMI
:
1172 if (k
->do_hw_op(s
, IPMI_SEND_NMI
, 1)) {
1173 /* NMI not supported. */
1174 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1180 /* We don't support PRE_SMI */
1181 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1185 ibs
->watchdog_initialized
= 1;
1186 ibs
->watchdog_use
= cmd
[2] & IPMI_BMC_WATCHDOG_USE_MASK
;
1187 ibs
->watchdog_action
= cmd
[3] & IPMI_BMC_WATCHDOG_ACTION_MASK
;
1188 ibs
->watchdog_pretimeout
= cmd
[4];
1189 ibs
->watchdog_expired
&= ~cmd
[5];
1190 ibs
->watchdog_timeout
= cmd
[6] | (((uint16_t) cmd
[7]) << 8);
1191 if (ibs
->watchdog_running
& IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs
)) {
1192 do_watchdog_reset(ibs
);
1194 ibs
->watchdog_running
= 0;
1198 static void get_watchdog_timer(IPMIBmcSim
*ibs
,
1199 uint8_t *cmd
, unsigned int cmd_len
,
1202 rsp_buffer_push(rsp
, ibs
->watchdog_use
);
1203 rsp_buffer_push(rsp
, ibs
->watchdog_action
);
1204 rsp_buffer_push(rsp
, ibs
->watchdog_pretimeout
);
1205 rsp_buffer_push(rsp
, ibs
->watchdog_expired
);
1206 rsp_buffer_push(rsp
, ibs
->watchdog_timeout
& 0xff);
1207 rsp_buffer_push(rsp
, (ibs
->watchdog_timeout
>> 8) & 0xff);
1208 if (ibs
->watchdog_running
) {
1210 timeout
= ((ibs
->watchdog_expiry
- ipmi_getmonotime() + 50000000)
1212 rsp_buffer_push(rsp
, timeout
& 0xff);
1213 rsp_buffer_push(rsp
, (timeout
>> 8) & 0xff);
1215 rsp_buffer_push(rsp
, 0);
1216 rsp_buffer_push(rsp
, 0);
1220 static void get_sdr_rep_info(IPMIBmcSim
*ibs
,
1221 uint8_t *cmd
, unsigned int cmd_len
,
1226 rsp_buffer_push(rsp
, 0x51); /* Conform to IPMI 1.5 spec */
1227 rsp_buffer_push(rsp
, ibs
->sdr
.next_rec_id
& 0xff);
1228 rsp_buffer_push(rsp
, (ibs
->sdr
.next_rec_id
>> 8) & 0xff);
1229 rsp_buffer_push(rsp
, (MAX_SDR_SIZE
- ibs
->sdr
.next_free
) & 0xff);
1230 rsp_buffer_push(rsp
, ((MAX_SDR_SIZE
- ibs
->sdr
.next_free
) >> 8) & 0xff);
1231 for (i
= 0; i
< 4; i
++) {
1232 rsp_buffer_push(rsp
, ibs
->sdr
.last_addition
[i
]);
1234 for (i
= 0; i
< 4; i
++) {
1235 rsp_buffer_push(rsp
, ibs
->sdr
.last_clear
[i
]);
1237 /* Only modal support, reserve supported */
1238 rsp_buffer_push(rsp
, (ibs
->sdr
.overflow
<< 7) | 0x22);
1241 static void reserve_sdr_rep(IPMIBmcSim
*ibs
,
1242 uint8_t *cmd
, unsigned int cmd_len
,
1245 rsp_buffer_push(rsp
, ibs
->sdr
.reservation
& 0xff);
1246 rsp_buffer_push(rsp
, (ibs
->sdr
.reservation
>> 8) & 0xff);
1249 static void get_sdr(IPMIBmcSim
*ibs
,
1250 uint8_t *cmd
, unsigned int cmd_len
,
1255 struct ipmi_sdr_header
*sdrh
;
1258 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sdr
.reservation
) {
1259 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1265 if (sdr_find_entry(&ibs
->sdr
, cmd
[4] | (cmd
[5] << 8),
1267 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1271 sdrh
= (struct ipmi_sdr_header
*) &ibs
->sdr
.sdr
[pos
];
1273 if (cmd
[6] > ipmi_sdr_length(sdrh
)) {
1274 rsp_buffer_set_error(rsp
, IPMI_CC_PARM_OUT_OF_RANGE
);
1278 rsp_buffer_push(rsp
, nextrec
& 0xff);
1279 rsp_buffer_push(rsp
, (nextrec
>> 8) & 0xff);
1281 if (cmd
[7] == 0xff) {
1282 cmd
[7] = ipmi_sdr_length(sdrh
) - cmd
[6];
1285 if ((cmd
[7] + rsp
->len
) > sizeof(rsp
->buffer
)) {
1286 rsp_buffer_set_error(rsp
, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES
);
1290 rsp_buffer_pushmore(rsp
, ibs
->sdr
.sdr
+ pos
+ cmd
[6], cmd
[7]);
1293 static void add_sdr(IPMIBmcSim
*ibs
,
1294 uint8_t *cmd
, unsigned int cmd_len
,
1298 struct ipmi_sdr_header
*sdrh
= (struct ipmi_sdr_header
*) cmd
+ 2;
1300 if (sdr_add_entry(ibs
, sdrh
, cmd_len
- 2, &recid
)) {
1301 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1304 rsp_buffer_push(rsp
, recid
& 0xff);
1305 rsp_buffer_push(rsp
, (recid
>> 8) & 0xff);
1308 static void clear_sdr_rep(IPMIBmcSim
*ibs
,
1309 uint8_t *cmd
, unsigned int cmd_len
,
1312 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sdr
.reservation
) {
1313 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1317 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1318 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1321 if (cmd
[7] == 0xaa) {
1322 ibs
->sdr
.next_free
= 0;
1323 ibs
->sdr
.overflow
= 0;
1324 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1325 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1326 sdr_inc_reservation(&ibs
->sdr
);
1327 } else if (cmd
[7] == 0) {
1328 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1330 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1335 static void get_sel_info(IPMIBmcSim
*ibs
,
1336 uint8_t *cmd
, unsigned int cmd_len
,
1339 unsigned int i
, val
;
1341 rsp_buffer_push(rsp
, 0x51); /* Conform to IPMI 1.5 */
1342 rsp_buffer_push(rsp
, ibs
->sel
.next_free
& 0xff);
1343 rsp_buffer_push(rsp
, (ibs
->sel
.next_free
>> 8) & 0xff);
1344 val
= (MAX_SEL_SIZE
- ibs
->sel
.next_free
) * 16;
1345 rsp_buffer_push(rsp
, val
& 0xff);
1346 rsp_buffer_push(rsp
, (val
>> 8) & 0xff);
1347 for (i
= 0; i
< 4; i
++) {
1348 rsp_buffer_push(rsp
, ibs
->sel
.last_addition
[i
]);
1350 for (i
= 0; i
< 4; i
++) {
1351 rsp_buffer_push(rsp
, ibs
->sel
.last_clear
[i
]);
1353 /* Only support Reserve SEL */
1354 rsp_buffer_push(rsp
, (ibs
->sel
.overflow
<< 7) | 0x02);
1357 static void get_fru_area_info(IPMIBmcSim
*ibs
,
1358 uint8_t *cmd
, unsigned int cmd_len
,
1362 uint16_t fru_entry_size
;
1366 if (fruid
>= ibs
->fru
.nentries
) {
1367 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1371 fru_entry_size
= ibs
->fru
.areasize
;
1373 rsp_buffer_push(rsp
, fru_entry_size
& 0xff);
1374 rsp_buffer_push(rsp
, fru_entry_size
>> 8 & 0xff);
1375 rsp_buffer_push(rsp
, 0x0);
1378 static void read_fru_data(IPMIBmcSim
*ibs
,
1379 uint8_t *cmd
, unsigned int cmd_len
,
1389 offset
= (cmd
[3] | cmd
[4] << 8);
1391 if (fruid
>= ibs
->fru
.nentries
) {
1392 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1396 if (offset
>= ibs
->fru
.areasize
- 1) {
1397 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1401 fru_entry
= &ibs
->fru
.data
[fruid
* ibs
->fru
.areasize
];
1403 count
= MIN(cmd
[5], ibs
->fru
.areasize
- offset
);
1405 rsp_buffer_push(rsp
, count
& 0xff);
1406 for (i
= 0; i
< count
; i
++) {
1407 rsp_buffer_push(rsp
, fru_entry
[offset
+ i
]);
1411 static void write_fru_data(IPMIBmcSim
*ibs
,
1412 uint8_t *cmd
, unsigned int cmd_len
,
1421 offset
= (cmd
[3] | cmd
[4] << 8);
1423 if (fruid
>= ibs
->fru
.nentries
) {
1424 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1428 if (offset
>= ibs
->fru
.areasize
- 1) {
1429 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1433 fru_entry
= &ibs
->fru
.data
[fruid
* ibs
->fru
.areasize
];
1435 count
= MIN(cmd_len
- 5, ibs
->fru
.areasize
- offset
);
1437 memcpy(fru_entry
+ offset
, cmd
+ 5, count
);
1439 rsp_buffer_push(rsp
, count
& 0xff);
1442 static void reserve_sel(IPMIBmcSim
*ibs
,
1443 uint8_t *cmd
, unsigned int cmd_len
,
1446 rsp_buffer_push(rsp
, ibs
->sel
.reservation
& 0xff);
1447 rsp_buffer_push(rsp
, (ibs
->sel
.reservation
>> 8) & 0xff);
1450 static void get_sel_entry(IPMIBmcSim
*ibs
,
1451 uint8_t *cmd
, unsigned int cmd_len
,
1457 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sel
.reservation
) {
1458 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1462 if (ibs
->sel
.next_free
== 0) {
1463 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1467 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1470 if (cmd
[7] == 0xff) {
1472 } else if ((cmd
[7] + cmd
[6]) > 16) {
1473 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1479 val
= cmd
[4] | (cmd
[5] << 8);
1480 if (val
== 0xffff) {
1481 val
= ibs
->sel
.next_free
- 1;
1482 } else if (val
>= ibs
->sel
.next_free
) {
1483 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1486 if ((val
+ 1) == ibs
->sel
.next_free
) {
1487 rsp_buffer_push(rsp
, 0xff);
1488 rsp_buffer_push(rsp
, 0xff);
1490 rsp_buffer_push(rsp
, (val
+ 1) & 0xff);
1491 rsp_buffer_push(rsp
, ((val
+ 1) >> 8) & 0xff);
1493 for (; cmd
[6] < cmd
[7]; cmd
[6]++) {
1494 rsp_buffer_push(rsp
, ibs
->sel
.sel
[val
][cmd
[6]]);
1498 static void add_sel_entry(IPMIBmcSim
*ibs
,
1499 uint8_t *cmd
, unsigned int cmd_len
,
1502 if (sel_add_event(ibs
, cmd
+ 2)) {
1503 rsp_buffer_set_error(rsp
, IPMI_CC_OUT_OF_SPACE
);
1506 /* sel_add_event fills in the record number. */
1507 rsp_buffer_push(rsp
, cmd
[2]);
1508 rsp_buffer_push(rsp
, cmd
[3]);
1511 static void clear_sel(IPMIBmcSim
*ibs
,
1512 uint8_t *cmd
, unsigned int cmd_len
,
1515 if ((cmd
[2] | (cmd
[3] << 8)) != ibs
->sel
.reservation
) {
1516 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_RESERVATION
);
1520 if (cmd
[4] != 'C' || cmd
[5] != 'L' || cmd
[6] != 'R') {
1521 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1524 if (cmd
[7] == 0xaa) {
1525 ibs
->sel
.next_free
= 0;
1526 ibs
->sel
.overflow
= 0;
1527 set_timestamp(ibs
, ibs
->sdr
.last_clear
);
1528 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1529 sel_inc_reservation(&ibs
->sel
);
1530 } else if (cmd
[7] == 0) {
1531 rsp_buffer_push(rsp
, 1); /* Erasure complete */
1533 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1538 static void get_sel_time(IPMIBmcSim
*ibs
,
1539 uint8_t *cmd
, unsigned int cmd_len
,
1543 struct ipmi_time now
;
1546 val
= now
.tv_sec
+ ibs
->sel
.time_offset
;
1547 rsp_buffer_push(rsp
, val
& 0xff);
1548 rsp_buffer_push(rsp
, (val
>> 8) & 0xff);
1549 rsp_buffer_push(rsp
, (val
>> 16) & 0xff);
1550 rsp_buffer_push(rsp
, (val
>> 24) & 0xff);
1553 static void set_sel_time(IPMIBmcSim
*ibs
,
1554 uint8_t *cmd
, unsigned int cmd_len
,
1558 struct ipmi_time now
;
1560 val
= cmd
[2] | (cmd
[3] << 8) | (cmd
[4] << 16) | (cmd
[5] << 24);
1562 ibs
->sel
.time_offset
= now
.tv_sec
- ((long) val
);
1565 static void platform_event_msg(IPMIBmcSim
*ibs
,
1566 uint8_t *cmd
, unsigned int cmd_len
,
1571 event
[2] = 2; /* System event record */
1572 event
[7] = cmd
[2]; /* Generator ID */
1574 event
[9] = cmd
[3]; /* EvMRev */
1575 event
[10] = cmd
[4]; /* Sensor type */
1576 event
[11] = cmd
[5]; /* Sensor number */
1577 event
[12] = cmd
[6]; /* Event dir / Event type */
1578 event
[13] = cmd
[7]; /* Event data 1 */
1579 event
[14] = cmd
[8]; /* Event data 2 */
1580 event
[15] = cmd
[9]; /* Event data 3 */
1582 if (sel_add_event(ibs
, event
)) {
1583 rsp_buffer_set_error(rsp
, IPMI_CC_OUT_OF_SPACE
);
1587 static void set_sensor_evt_enable(IPMIBmcSim
*ibs
,
1588 uint8_t *cmd
, unsigned int cmd_len
,
1593 if ((cmd
[2] >= MAX_SENSORS
) ||
1594 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1595 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1598 sens
= ibs
->sensors
+ cmd
[2];
1599 switch ((cmd
[3] >> 4) & 0x3) {
1600 case 0: /* Do not change */
1602 case 1: /* Enable bits */
1604 sens
->assert_enable
|= cmd
[4];
1607 sens
->assert_enable
|= cmd
[5] << 8;
1610 sens
->deassert_enable
|= cmd
[6];
1613 sens
->deassert_enable
|= cmd
[7] << 8;
1616 case 2: /* Disable bits */
1618 sens
->assert_enable
&= ~cmd
[4];
1621 sens
->assert_enable
&= ~(cmd
[5] << 8);
1624 sens
->deassert_enable
&= ~cmd
[6];
1627 sens
->deassert_enable
&= ~(cmd
[7] << 8);
1631 rsp_buffer_set_error(rsp
, IPMI_CC_INVALID_DATA_FIELD
);
1634 IPMI_SENSOR_SET_RET_STATUS(sens
, cmd
[3]);
1637 static void get_sensor_evt_enable(IPMIBmcSim
*ibs
,
1638 uint8_t *cmd
, unsigned int cmd_len
,
1643 if ((cmd
[2] >= MAX_SENSORS
) ||
1644 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1645 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1648 sens
= ibs
->sensors
+ cmd
[2];
1649 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1650 rsp_buffer_push(rsp
, sens
->assert_enable
& 0xff);
1651 rsp_buffer_push(rsp
, (sens
->assert_enable
>> 8) & 0xff);
1652 rsp_buffer_push(rsp
, sens
->deassert_enable
& 0xff);
1653 rsp_buffer_push(rsp
, (sens
->deassert_enable
>> 8) & 0xff);
1656 static void rearm_sensor_evts(IPMIBmcSim
*ibs
,
1657 uint8_t *cmd
, unsigned int cmd_len
,
1662 if ((cmd
[2] >= MAX_SENSORS
) ||
1663 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1664 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1667 sens
= ibs
->sensors
+ cmd
[2];
1669 if ((cmd
[3] & 0x80) == 0) {
1670 /* Just clear everything */
1676 static void get_sensor_evt_status(IPMIBmcSim
*ibs
,
1677 uint8_t *cmd
, unsigned int cmd_len
,
1682 if ((cmd
[2] >= MAX_SENSORS
) ||
1683 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1684 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1687 sens
= ibs
->sensors
+ cmd
[2];
1688 rsp_buffer_push(rsp
, sens
->reading
);
1689 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1690 rsp_buffer_push(rsp
, sens
->assert_states
& 0xff);
1691 rsp_buffer_push(rsp
, (sens
->assert_states
>> 8) & 0xff);
1692 rsp_buffer_push(rsp
, sens
->deassert_states
& 0xff);
1693 rsp_buffer_push(rsp
, (sens
->deassert_states
>> 8) & 0xff);
1696 static void get_sensor_reading(IPMIBmcSim
*ibs
,
1697 uint8_t *cmd
, unsigned int cmd_len
,
1702 if ((cmd
[2] >= MAX_SENSORS
) ||
1703 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1704 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1707 sens
= ibs
->sensors
+ cmd
[2];
1708 rsp_buffer_push(rsp
, sens
->reading
);
1709 rsp_buffer_push(rsp
, IPMI_SENSOR_GET_RET_STATUS(sens
));
1710 rsp_buffer_push(rsp
, sens
->states
& 0xff);
1711 if (IPMI_SENSOR_IS_DISCRETE(sens
)) {
1712 rsp_buffer_push(rsp
, (sens
->states
>> 8) & 0xff);
1716 static void set_sensor_type(IPMIBmcSim
*ibs
,
1717 uint8_t *cmd
, unsigned int cmd_len
,
1723 if ((cmd
[2] >= MAX_SENSORS
) ||
1724 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1725 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1728 sens
= ibs
->sensors
+ cmd
[2];
1729 sens
->sensor_type
= cmd
[3];
1730 sens
->evt_reading_type_code
= cmd
[4] & 0x7f;
1733 static void get_sensor_type(IPMIBmcSim
*ibs
,
1734 uint8_t *cmd
, unsigned int cmd_len
,
1740 if ((cmd
[2] >= MAX_SENSORS
) ||
1741 !IPMI_SENSOR_GET_PRESENT(ibs
->sensors
+ cmd
[2])) {
1742 rsp_buffer_set_error(rsp
, IPMI_CC_REQ_ENTRY_NOT_PRESENT
);
1745 sens
= ibs
->sensors
+ cmd
[2];
1746 rsp_buffer_push(rsp
, sens
->sensor_type
);
1747 rsp_buffer_push(rsp
, sens
->evt_reading_type_code
);
1751 static const IPMICmdHandler chassis_cmds
[] = {
1752 [IPMI_CMD_GET_CHASSIS_CAPABILITIES
] = { chassis_capabilities
},
1753 [IPMI_CMD_GET_CHASSIS_STATUS
] = { chassis_status
},
1754 [IPMI_CMD_CHASSIS_CONTROL
] = { chassis_control
, 3 },
1755 [IPMI_CMD_GET_SYS_RESTART_CAUSE
] = { chassis_get_sys_restart_cause
}
1757 static const IPMINetfn chassis_netfn
= {
1758 .cmd_nums
= ARRAY_SIZE(chassis_cmds
),
1759 .cmd_handlers
= chassis_cmds
1762 static const IPMICmdHandler sensor_event_cmds
[] = {
1763 [IPMI_CMD_PLATFORM_EVENT_MSG
] = { platform_event_msg
, 10 },
1764 [IPMI_CMD_SET_SENSOR_EVT_ENABLE
] = { set_sensor_evt_enable
, 4 },
1765 [IPMI_CMD_GET_SENSOR_EVT_ENABLE
] = { get_sensor_evt_enable
, 3 },
1766 [IPMI_CMD_REARM_SENSOR_EVTS
] = { rearm_sensor_evts
, 4 },
1767 [IPMI_CMD_GET_SENSOR_EVT_STATUS
] = { get_sensor_evt_status
, 3 },
1768 [IPMI_CMD_GET_SENSOR_READING
] = { get_sensor_reading
, 3 },
1769 [IPMI_CMD_SET_SENSOR_TYPE
] = { set_sensor_type
, 5 },
1770 [IPMI_CMD_GET_SENSOR_TYPE
] = { get_sensor_type
, 3 },
1772 static const IPMINetfn sensor_event_netfn
= {
1773 .cmd_nums
= ARRAY_SIZE(sensor_event_cmds
),
1774 .cmd_handlers
= sensor_event_cmds
1777 static const IPMICmdHandler app_cmds
[] = {
1778 [IPMI_CMD_GET_DEVICE_ID
] = { get_device_id
},
1779 [IPMI_CMD_COLD_RESET
] = { cold_reset
},
1780 [IPMI_CMD_WARM_RESET
] = { warm_reset
},
1781 [IPMI_CMD_SET_ACPI_POWER_STATE
] = { set_acpi_power_state
, 4 },
1782 [IPMI_CMD_GET_ACPI_POWER_STATE
] = { get_acpi_power_state
},
1783 [IPMI_CMD_GET_DEVICE_GUID
] = { get_device_guid
},
1784 [IPMI_CMD_SET_BMC_GLOBAL_ENABLES
] = { set_bmc_global_enables
, 3 },
1785 [IPMI_CMD_GET_BMC_GLOBAL_ENABLES
] = { get_bmc_global_enables
},
1786 [IPMI_CMD_CLR_MSG_FLAGS
] = { clr_msg_flags
, 3 },
1787 [IPMI_CMD_GET_MSG_FLAGS
] = { get_msg_flags
},
1788 [IPMI_CMD_GET_MSG
] = { get_msg
},
1789 [IPMI_CMD_SEND_MSG
] = { send_msg
, 3 },
1790 [IPMI_CMD_READ_EVT_MSG_BUF
] = { read_evt_msg_buf
},
1791 [IPMI_CMD_RESET_WATCHDOG_TIMER
] = { reset_watchdog_timer
},
1792 [IPMI_CMD_SET_WATCHDOG_TIMER
] = { set_watchdog_timer
, 8 },
1793 [IPMI_CMD_GET_WATCHDOG_TIMER
] = { get_watchdog_timer
},
1795 static const IPMINetfn app_netfn
= {
1796 .cmd_nums
= ARRAY_SIZE(app_cmds
),
1797 .cmd_handlers
= app_cmds
1800 static const IPMICmdHandler storage_cmds
[] = {
1801 [IPMI_CMD_GET_FRU_AREA_INFO
] = { get_fru_area_info
, 3 },
1802 [IPMI_CMD_READ_FRU_DATA
] = { read_fru_data
, 5 },
1803 [IPMI_CMD_WRITE_FRU_DATA
] = { write_fru_data
, 5 },
1804 [IPMI_CMD_GET_SDR_REP_INFO
] = { get_sdr_rep_info
},
1805 [IPMI_CMD_RESERVE_SDR_REP
] = { reserve_sdr_rep
},
1806 [IPMI_CMD_GET_SDR
] = { get_sdr
, 8 },
1807 [IPMI_CMD_ADD_SDR
] = { add_sdr
},
1808 [IPMI_CMD_CLEAR_SDR_REP
] = { clear_sdr_rep
, 8 },
1809 [IPMI_CMD_GET_SEL_INFO
] = { get_sel_info
},
1810 [IPMI_CMD_RESERVE_SEL
] = { reserve_sel
},
1811 [IPMI_CMD_GET_SEL_ENTRY
] = { get_sel_entry
, 8 },
1812 [IPMI_CMD_ADD_SEL_ENTRY
] = { add_sel_entry
, 18 },
1813 [IPMI_CMD_CLEAR_SEL
] = { clear_sel
, 8 },
1814 [IPMI_CMD_GET_SEL_TIME
] = { get_sel_time
},
1815 [IPMI_CMD_SET_SEL_TIME
] = { set_sel_time
, 6 },
1818 static const IPMINetfn storage_netfn
= {
1819 .cmd_nums
= ARRAY_SIZE(storage_cmds
),
1820 .cmd_handlers
= storage_cmds
1823 static void register_cmds(IPMIBmcSim
*s
)
1825 ipmi_sim_register_netfn(s
, IPMI_NETFN_CHASSIS
, &chassis_netfn
);
1826 ipmi_sim_register_netfn(s
, IPMI_NETFN_SENSOR_EVENT
, &sensor_event_netfn
);
1827 ipmi_sim_register_netfn(s
, IPMI_NETFN_APP
, &app_netfn
);
1828 ipmi_sim_register_netfn(s
, IPMI_NETFN_STORAGE
, &storage_netfn
);
1831 static uint8_t init_sdrs
[] = {
1832 /* Watchdog device */
1833 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00,
1834 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
1835 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1836 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
1837 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
1840 static void ipmi_sdr_init(IPMIBmcSim
*ibs
)
1847 sdrs_size
= sizeof(init_sdrs
);
1849 if (ibs
->sdr_filename
&&
1850 !g_file_get_contents(ibs
->sdr_filename
, (gchar
**) &sdrs
, &sdrs_size
,
1852 error_report("failed to load sdr file '%s'", ibs
->sdr_filename
);
1853 sdrs_size
= sizeof(init_sdrs
);
1857 for (i
= 0; i
< sdrs_size
; i
+= len
) {
1858 struct ipmi_sdr_header
*sdrh
;
1860 if (i
+ IPMI_SDR_HEADER_SIZE
> sdrs_size
) {
1861 error_report("Problem with recid 0x%4.4x", i
);
1864 sdrh
= (struct ipmi_sdr_header
*) &sdrs
[i
];
1865 len
= ipmi_sdr_length(sdrh
);
1866 if (i
+ len
> sdrs_size
) {
1867 error_report("Problem with recid 0x%4.4x", i
);
1870 sdr_add_entry(ibs
, sdrh
, len
, NULL
);
1873 if (sdrs
!= init_sdrs
) {
1878 static const VMStateDescription vmstate_ipmi_sim
= {
1879 .name
= TYPE_IPMI_BMC_SIMULATOR
,
1881 .minimum_version_id
= 1,
1882 .fields
= (VMStateField
[]) {
1883 VMSTATE_UINT8(bmc_global_enables
, IPMIBmcSim
),
1884 VMSTATE_UINT8(msg_flags
, IPMIBmcSim
),
1885 VMSTATE_BOOL(watchdog_initialized
, IPMIBmcSim
),
1886 VMSTATE_UINT8(watchdog_use
, IPMIBmcSim
),
1887 VMSTATE_UINT8(watchdog_action
, IPMIBmcSim
),
1888 VMSTATE_UINT8(watchdog_pretimeout
, IPMIBmcSim
),
1889 VMSTATE_BOOL(watchdog_expired
, IPMIBmcSim
),
1890 VMSTATE_UINT16(watchdog_timeout
, IPMIBmcSim
),
1891 VMSTATE_BOOL(watchdog_running
, IPMIBmcSim
),
1892 VMSTATE_BOOL(watchdog_preaction_ran
, IPMIBmcSim
),
1893 VMSTATE_INT64(watchdog_expiry
, IPMIBmcSim
),
1894 VMSTATE_UINT8_ARRAY(evtbuf
, IPMIBmcSim
, 16),
1895 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].status
, IPMIBmcSim
),
1896 VMSTATE_UINT8(sensors
[IPMI_WATCHDOG_SENSOR
].reading
, IPMIBmcSim
),
1897 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].states
, IPMIBmcSim
),
1898 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_states
, IPMIBmcSim
),
1899 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].deassert_states
,
1901 VMSTATE_UINT16(sensors
[IPMI_WATCHDOG_SENSOR
].assert_enable
, IPMIBmcSim
),
1902 VMSTATE_END_OF_LIST()
1906 static void ipmi_fru_init(IPMIFru
*fru
)
1911 if (!fru
->filename
) {
1915 fsize
= get_image_size(fru
->filename
);
1917 size
= QEMU_ALIGN_UP(fsize
, fru
->areasize
);
1918 fru
->data
= g_malloc0(size
);
1919 if (load_image_size(fru
->filename
, fru
->data
, fsize
) != fsize
) {
1920 error_report("Could not load file '%s'", fru
->filename
);
1928 /* give one default FRU */
1929 size
= fru
->areasize
;
1930 fru
->data
= g_malloc0(size
);
1933 fru
->nentries
= size
/ fru
->areasize
;
1936 static void ipmi_sim_realize(DeviceState
*dev
, Error
**errp
)
1938 IPMIBmc
*b
= IPMI_BMC(dev
);
1940 IPMIBmcSim
*ibs
= IPMI_BMC_SIMULATOR(b
);
1942 QTAILQ_INIT(&ibs
->rcvbufs
);
1944 ibs
->bmc_global_enables
= (1 << IPMI_BMC_EVENT_LOG_BIT
);
1945 ibs
->device_id
= 0x20;
1946 ibs
->ipmi_version
= 0x02; /* IPMI 2.0 */
1947 ibs
->restart_cause
= 0;
1948 for (i
= 0; i
< 4; i
++) {
1949 ibs
->sel
.last_addition
[i
] = 0xff;
1950 ibs
->sel
.last_clear
[i
] = 0xff;
1951 ibs
->sdr
.last_addition
[i
] = 0xff;
1952 ibs
->sdr
.last_clear
[i
] = 0xff;
1957 ipmi_fru_init(&ibs
->fru
);
1959 ibs
->acpi_power_state
[0] = 0;
1960 ibs
->acpi_power_state
[1] = 0;
1962 ipmi_init_sensors_from_sdrs(ibs
);
1965 ibs
->timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, ipmi_timeout
, ibs
);
1967 vmstate_register(NULL
, 0, &vmstate_ipmi_sim
, ibs
);
1970 static Property ipmi_sim_properties
[] = {
1971 DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim
, fru
.areasize
, 1024),
1972 DEFINE_PROP_STRING("frudatafile", IPMIBmcSim
, fru
.filename
),
1973 DEFINE_PROP_STRING("sdrfile", IPMIBmcSim
, sdr_filename
),
1974 DEFINE_PROP_UINT8("device_id", IPMIBmcSim
, device_id
, 0x20),
1975 DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim
, ipmi_version
, 0x02),
1976 DEFINE_PROP_UINT8("device_rev", IPMIBmcSim
, device_rev
, 0),
1977 DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim
, fwrev1
, 0),
1978 DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim
, fwrev2
, 0),
1979 DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim
, mfg_id
, 0),
1980 DEFINE_PROP_UINT16("product_id", IPMIBmcSim
, product_id
, 0),
1981 DEFINE_PROP_UUID_NODEFAULT("guid", IPMIBmcSim
, uuid
),
1982 DEFINE_PROP_END_OF_LIST(),
1985 static void ipmi_sim_class_init(ObjectClass
*oc
, void *data
)
1987 DeviceClass
*dc
= DEVICE_CLASS(oc
);
1988 IPMIBmcClass
*bk
= IPMI_BMC_CLASS(oc
);
1990 dc
->hotpluggable
= false;
1991 dc
->realize
= ipmi_sim_realize
;
1992 device_class_set_props(dc
, ipmi_sim_properties
);
1993 bk
->handle_command
= ipmi_sim_handle_command
;
1996 static const TypeInfo ipmi_sim_type
= {
1997 .name
= TYPE_IPMI_BMC_SIMULATOR
,
1998 .parent
= TYPE_IPMI_BMC
,
1999 .instance_size
= sizeof(IPMIBmcSim
),
2000 .class_init
= ipmi_sim_class_init
,
2003 static void ipmi_sim_register_types(void)
2005 type_register_static(&ipmi_sim_type
);
2008 type_init(ipmi_sim_register_types
)