diff options
author | RajithaY <rajithax.yerrumsetty@intel.com> | 2017-04-25 03:31:15 -0700 |
---|---|---|
committer | Rajitha Yerrumchetty <rajithax.yerrumsetty@intel.com> | 2017-05-22 06:48:08 +0000 |
commit | bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch) | |
tree | ca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/hw/ipmi/ipmi_bmc_sim.c | |
parent | a14b48d18a9ed03ec191cf16b162206998a895ce (diff) |
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to
kvmfornfv repo and make use of the updated latest qemu for the
execution of all testcase
Change-Id: I1280af507a857675c7f81d30c95255635667bdd7
Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/hw/ipmi/ipmi_bmc_sim.c')
-rw-r--r-- | qemu/hw/ipmi/ipmi_bmc_sim.c | 1810 |
1 files changed, 0 insertions, 1810 deletions
diff --git a/qemu/hw/ipmi/ipmi_bmc_sim.c b/qemu/hw/ipmi/ipmi_bmc_sim.c deleted file mode 100644 index dc9c14cd2..000000000 --- a/qemu/hw/ipmi/ipmi_bmc_sim.c +++ /dev/null @@ -1,1810 +0,0 @@ -/* - * IPMI BMC emulation - * - * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "qemu/osdep.h" -#include "sysemu/sysemu.h" -#include "qemu/timer.h" -#include "hw/ipmi/ipmi.h" -#include "qemu/error-report.h" - -#define IPMI_NETFN_CHASSIS 0x00 - -#define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00 -#define IPMI_CMD_GET_CHASSIS_STATUS 0x01 -#define IPMI_CMD_CHASSIS_CONTROL 0x02 -#define IPMI_CMD_GET_SYS_RESTART_CAUSE 0x09 - -#define IPMI_NETFN_SENSOR_EVENT 0x04 - -#define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28 -#define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29 -#define IPMI_CMD_REARM_SENSOR_EVTS 0x2a -#define IPMI_CMD_GET_SENSOR_EVT_STATUS 0x2b -#define IPMI_CMD_GET_SENSOR_READING 0x2d -#define IPMI_CMD_SET_SENSOR_TYPE 0x2e -#define IPMI_CMD_GET_SENSOR_TYPE 0x2f - -/* #define IPMI_NETFN_APP 0x06 In ipmi.h */ - -#define IPMI_CMD_GET_DEVICE_ID 0x01 -#define IPMI_CMD_COLD_RESET 0x02 -#define IPMI_CMD_WARM_RESET 0x03 -#define IPMI_CMD_SET_ACPI_POWER_STATE 0x06 -#define IPMI_CMD_GET_ACPI_POWER_STATE 0x07 -#define IPMI_CMD_GET_DEVICE_GUID 0x08 -#define IPMI_CMD_RESET_WATCHDOG_TIMER 0x22 -#define IPMI_CMD_SET_WATCHDOG_TIMER 0x24 -#define IPMI_CMD_GET_WATCHDOG_TIMER 0x25 -#define IPMI_CMD_SET_BMC_GLOBAL_ENABLES 0x2e -#define IPMI_CMD_GET_BMC_GLOBAL_ENABLES 0x2f -#define IPMI_CMD_CLR_MSG_FLAGS 0x30 -#define IPMI_CMD_GET_MSG_FLAGS 0x31 -#define IPMI_CMD_GET_MSG 0x33 -#define IPMI_CMD_SEND_MSG 0x34 -#define IPMI_CMD_READ_EVT_MSG_BUF 0x35 - -#define IPMI_NETFN_STORAGE 0x0a - -#define IPMI_CMD_GET_SDR_REP_INFO 0x20 -#define IPMI_CMD_GET_SDR_REP_ALLOC_INFO 0x21 -#define IPMI_CMD_RESERVE_SDR_REP 0x22 -#define IPMI_CMD_GET_SDR 0x23 -#define IPMI_CMD_ADD_SDR 0x24 -#define IPMI_CMD_PARTIAL_ADD_SDR 0x25 -#define IPMI_CMD_DELETE_SDR 0x26 -#define IPMI_CMD_CLEAR_SDR_REP 0x27 -#define IPMI_CMD_GET_SDR_REP_TIME 0x28 -#define IPMI_CMD_SET_SDR_REP_TIME 0x29 -#define IPMI_CMD_ENTER_SDR_REP_UPD_MODE 0x2A -#define IPMI_CMD_EXIT_SDR_REP_UPD_MODE 0x2B -#define IPMI_CMD_RUN_INIT_AGENT 0x2C -#define IPMI_CMD_GET_SEL_INFO 0x40 -#define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41 -#define IPMI_CMD_RESERVE_SEL 0x42 -#define IPMI_CMD_GET_SEL_ENTRY 0x43 -#define IPMI_CMD_ADD_SEL_ENTRY 0x44 -#define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45 -#define IPMI_CMD_DELETE_SEL_ENTRY 0x46 -#define IPMI_CMD_CLEAR_SEL 0x47 -#define IPMI_CMD_GET_SEL_TIME 0x48 -#define IPMI_CMD_SET_SEL_TIME 0x49 - - -/* Same as a timespec struct. */ -struct ipmi_time { - long tv_sec; - long tv_nsec; -}; - -#define MAX_SEL_SIZE 128 - -typedef struct IPMISel { - uint8_t sel[MAX_SEL_SIZE][16]; - unsigned int next_free; - long time_offset; - uint16_t reservation; - uint8_t last_addition[4]; - uint8_t last_clear[4]; - uint8_t overflow; -} IPMISel; - -#define MAX_SDR_SIZE 16384 - -typedef struct IPMISdr { - uint8_t sdr[MAX_SDR_SIZE]; - unsigned int next_free; - uint16_t next_rec_id; - uint16_t reservation; - uint8_t last_addition[4]; - uint8_t last_clear[4]; - uint8_t overflow; -} IPMISdr; - -typedef struct IPMISensor { - uint8_t status; - uint8_t reading; - uint16_t states_suppt; - uint16_t assert_suppt; - uint16_t deassert_suppt; - uint16_t states; - uint16_t assert_states; - uint16_t deassert_states; - uint16_t assert_enable; - uint16_t deassert_enable; - uint8_t sensor_type; - uint8_t evt_reading_type_code; -} IPMISensor; -#define IPMI_SENSOR_GET_PRESENT(s) ((s)->status & 0x01) -#define IPMI_SENSOR_SET_PRESENT(s, v) ((s)->status = (s->status & ~0x01) | \ - !!(v)) -#define IPMI_SENSOR_GET_SCAN_ON(s) ((s)->status & 0x40) -#define IPMI_SENSOR_SET_SCAN_ON(s, v) ((s)->status = (s->status & ~0x40) | \ - ((!!(v)) << 6)) -#define IPMI_SENSOR_GET_EVENTS_ON(s) ((s)->status & 0x80) -#define IPMI_SENSOR_SET_EVENTS_ON(s, v) ((s)->status = (s->status & ~0x80) | \ - ((!!(v)) << 7)) -#define IPMI_SENSOR_GET_RET_STATUS(s) ((s)->status & 0xc0) -#define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \ - (v & 0xc0)) -#define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1) - -#define MAX_SENSORS 20 -#define IPMI_WATCHDOG_SENSOR 0 - -typedef struct IPMIBmcSim IPMIBmcSim; -typedef struct RspBuffer RspBuffer; - -#define MAX_NETFNS 64 - -typedef struct IPMICmdHandler { - void (*cmd_handler)(IPMIBmcSim *s, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp); - unsigned int cmd_len_min; -} IPMICmdHandler; - -typedef struct IPMINetfn { - unsigned int cmd_nums; - const IPMICmdHandler *cmd_handlers; -} IPMINetfn; - -typedef struct IPMIRcvBufEntry { - QTAILQ_ENTRY(IPMIRcvBufEntry) entry; - uint8_t len; - uint8_t buf[MAX_IPMI_MSG_SIZE]; -} IPMIRcvBufEntry; - -#define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim" -#define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \ - TYPE_IPMI_BMC_SIMULATOR) -struct IPMIBmcSim { - IPMIBmc parent; - - QEMUTimer *timer; - - uint8_t bmc_global_enables; - uint8_t msg_flags; - - bool watchdog_initialized; - uint8_t watchdog_use; - uint8_t watchdog_action; - uint8_t watchdog_pretimeout; /* In seconds */ - bool watchdog_expired; - uint16_t watchdog_timeout; /* in 100's of milliseconds */ - - bool watchdog_running; - bool watchdog_preaction_ran; - int64_t watchdog_expiry; - - uint8_t device_id; - uint8_t ipmi_version; - uint8_t device_rev; - uint8_t fwrev1; - uint8_t fwrev2; - uint8_t mfg_id[3]; - uint8_t product_id[2]; - - uint8_t restart_cause; - - uint8_t acpi_power_state[2]; - uint8_t uuid[16]; - - IPMISel sel; - IPMISdr sdr; - IPMISensor sensors[MAX_SENSORS]; - - /* Odd netfns are for responses, so we only need the even ones. */ - const IPMINetfn *netfns[MAX_NETFNS / 2]; - - QemuMutex lock; - /* We allow one event in the buffer */ - uint8_t evtbuf[16]; - - QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs; -}; - -#define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3) -#define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL (1 << 1) -#define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0) -#define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \ - (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags) -#define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \ - (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags) -#define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \ - (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags) - -#define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0 -#define IPMI_BMC_EVBUF_FULL_INT_BIT 1 -#define IPMI_BMC_EVENT_MSG_BUF_BIT 2 -#define IPMI_BMC_EVENT_LOG_BIT 3 -#define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \ - (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT)) -#define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \ - (1 << IPMI_BMC_EVBUF_FULL_INT_BIT)) -#define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \ - (1 << IPMI_BMC_EVENT_LOG_BIT)) -#define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \ - (1 << IPMI_BMC_EVENT_MSG_BUF_BIT)) - -#define IPMI_BMC_WATCHDOG_USE_MASK 0xc7 -#define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77 -#define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7) -#define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1) -#define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1) -#define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7) -#define IPMI_BMC_WATCHDOG_PRE_NONE 0 -#define IPMI_BMC_WATCHDOG_PRE_SMI 1 -#define IPMI_BMC_WATCHDOG_PRE_NMI 2 -#define IPMI_BMC_WATCHDOG_PRE_MSG_INT 3 -#define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7) -#define IPMI_BMC_WATCHDOG_ACTION_NONE 0 -#define IPMI_BMC_WATCHDOG_ACTION_RESET 1 -#define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2 -#define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3 - -struct RspBuffer { - uint8_t buffer[MAX_IPMI_MSG_SIZE]; - unsigned int len; -}; - -#define RSP_BUFFER_INITIALIZER { } - -static inline void rsp_buffer_set_error(RspBuffer *rsp, uint8_t byte) -{ - rsp->buffer[2] = byte; -} - -/* Add a byte to the response. */ -static inline void rsp_buffer_push(RspBuffer *rsp, uint8_t byte) -{ - if (rsp->len >= sizeof(rsp->buffer)) { - rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED); - return; - } - rsp->buffer[rsp->len++] = byte; -} - -static inline void rsp_buffer_pushmore(RspBuffer *rsp, uint8_t *bytes, - unsigned int n) -{ - if (rsp->len + n >= sizeof(rsp->buffer)) { - rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED); - return; - } - - memcpy(&rsp->buffer[rsp->len], bytes, n); - rsp->len += n; -} - -static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs); - -static void ipmi_gettime(struct ipmi_time *time) -{ - int64_t stime; - - stime = qemu_clock_get_ns(QEMU_CLOCK_HOST); - time->tv_sec = stime / 1000000000LL; - time->tv_nsec = stime % 1000000000LL; -} - -static int64_t ipmi_getmonotime(void) -{ - return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); -} - -static void ipmi_timeout(void *opaque) -{ - IPMIBmcSim *ibs = opaque; - - ipmi_sim_handle_timeout(ibs); -} - -static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts) -{ - unsigned int val; - struct ipmi_time now; - - ipmi_gettime(&now); - val = now.tv_sec + ibs->sel.time_offset; - ts[0] = val & 0xff; - ts[1] = (val >> 8) & 0xff; - ts[2] = (val >> 16) & 0xff; - ts[3] = (val >> 24) & 0xff; -} - -static void sdr_inc_reservation(IPMISdr *sdr) -{ - sdr->reservation++; - if (sdr->reservation == 0) { - sdr->reservation = 1; - } -} - -static int sdr_add_entry(IPMIBmcSim *ibs, - const struct ipmi_sdr_header *sdrh_entry, - unsigned int len, uint16_t *recid) -{ - struct ipmi_sdr_header *sdrh = - (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free]; - - if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) { - return 1; - } - - if (ipmi_sdr_length(sdrh_entry) != len) { - return 1; - } - - if (ibs->sdr.next_free + len > MAX_SDR_SIZE) { - ibs->sdr.overflow = 1; - return 1; - } - - memcpy(sdrh, sdrh_entry, len); - sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff; - sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff; - sdrh->sdr_version = 0x51; /* Conform to IPMI 1.5 spec */ - - if (recid) { - *recid = ibs->sdr.next_rec_id; - } - ibs->sdr.next_rec_id++; - set_timestamp(ibs, ibs->sdr.last_addition); - ibs->sdr.next_free += len; - sdr_inc_reservation(&ibs->sdr); - return 0; -} - -static int sdr_find_entry(IPMISdr *sdr, uint16_t recid, - unsigned int *retpos, uint16_t *nextrec) -{ - unsigned int pos = *retpos; - - while (pos < sdr->next_free) { - struct ipmi_sdr_header *sdrh = - (struct ipmi_sdr_header *) &sdr->sdr[pos]; - uint16_t trec = ipmi_sdr_recid(sdrh); - unsigned int nextpos = pos + ipmi_sdr_length(sdrh); - - if (trec == recid) { - if (nextrec) { - if (nextpos >= sdr->next_free) { - *nextrec = 0xffff; - } else { - *nextrec = (sdr->sdr[nextpos] | - (sdr->sdr[nextpos + 1] << 8)); - } - } - *retpos = pos; - return 0; - } - pos = nextpos; - } - return 1; -} - -static void sel_inc_reservation(IPMISel *sel) -{ - sel->reservation++; - if (sel->reservation == 0) { - sel->reservation = 1; - } -} - -/* Returns 1 if the SEL is full and can't hold the event. */ -static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event) -{ - event[0] = 0xff; - event[1] = 0xff; - set_timestamp(ibs, event + 3); - if (ibs->sel.next_free == MAX_SEL_SIZE) { - ibs->sel.overflow = 1; - return 1; - } - event[0] = ibs->sel.next_free & 0xff; - event[1] = (ibs->sel.next_free >> 8) & 0xff; - memcpy(ibs->sel.last_addition, event + 3, 4); - memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16); - ibs->sel.next_free++; - sel_inc_reservation(&ibs->sel); - return 0; -} - -static int attn_set(IPMIBmcSim *ibs) -{ - return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs) - || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs) - || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs); -} - -static int attn_irq_enabled(IPMIBmcSim *ibs) -{ - return (IPMI_BMC_MSG_INTS_ON(ibs) && IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)) - || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) && - IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)); -} - -static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert, - uint8_t evd1, uint8_t evd2, uint8_t evd3) -{ - IPMIInterface *s = ibs->parent.intf; - IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); - uint8_t evt[16]; - IPMISensor *sens = ibs->sensors + sens_num; - - if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) { - return; - } - if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) { - return; - } - - evt[2] = 0x2; /* System event record */ - evt[7] = ibs->parent.slave_addr; - evt[8] = 0; - evt[9] = 0x04; /* Format version */ - evt[10] = sens->sensor_type; - evt[11] = sens_num; - evt[12] = sens->evt_reading_type_code | (!!deassert << 7); - evt[13] = evd1; - evt[14] = evd2; - evt[15] = evd3; - - if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) { - sel_add_event(ibs, evt); - } - - if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) { - return; - } - - memcpy(ibs->evtbuf, evt, 16); - ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL; - k->set_atn(s, 1, attn_irq_enabled(ibs)); -} - -static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor, - unsigned int bit, unsigned int val, - uint8_t evd1, uint8_t evd2, uint8_t evd3) -{ - IPMISensor *sens; - uint16_t mask; - - if (sensor >= MAX_SENSORS) { - return; - } - if (bit >= 16) { - return; - } - - mask = (1 << bit); - sens = ibs->sensors + sensor; - if (val) { - sens->states |= mask & sens->states_suppt; - if (sens->assert_states & mask) { - return; /* Already asserted */ - } - sens->assert_states |= mask & sens->assert_suppt; - if (sens->assert_enable & mask & sens->assert_states) { - /* Send an event on assert */ - gen_event(ibs, sensor, 0, evd1, evd2, evd3); - } - } else { - sens->states &= ~(mask & sens->states_suppt); - if (sens->deassert_states & mask) { - return; /* Already deasserted */ - } - sens->deassert_states |= mask & sens->deassert_suppt; - if (sens->deassert_enable & mask & sens->deassert_states) { - /* Send an event on deassert */ - gen_event(ibs, sensor, 1, evd1, evd2, evd3); - } - } -} - -static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s) -{ - unsigned int i, pos; - IPMISensor *sens; - - for (i = 0; i < MAX_SENSORS; i++) { - memset(s->sensors + i, 0, sizeof(*sens)); - } - - pos = 0; - for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) { - struct ipmi_sdr_compact *sdr = - (struct ipmi_sdr_compact *) &s->sdr.sdr[pos]; - unsigned int len = sdr->header.rec_length; - - if (len < 20) { - continue; - } - if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) { - continue; /* Not a sensor SDR we set from */ - } - - if (sdr->sensor_owner_number >= MAX_SENSORS) { - continue; - } - sens = s->sensors + sdr->sensor_owner_number; - - IPMI_SENSOR_SET_PRESENT(sens, 1); - IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1); - IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1); - sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8); - sens->deassert_suppt = - sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8); - sens->states_suppt = - sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8); - sens->sensor_type = sdr->sensor_type; - sens->evt_reading_type_code = sdr->reading_type & 0x7f; - - /* Enable all the events that are supported. */ - sens->assert_enable = sens->assert_suppt; - sens->deassert_enable = sens->deassert_suppt; - } -} - -static int ipmi_register_netfn(IPMIBmcSim *s, unsigned int netfn, - const IPMINetfn *netfnd) -{ - if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) { - return -1; - } - s->netfns[netfn / 2] = netfnd; - return 0; -} - -static const IPMICmdHandler *ipmi_get_handler(IPMIBmcSim *ibs, - unsigned int netfn, - unsigned int cmd) -{ - const IPMICmdHandler *hdl; - - if (netfn & 1 || netfn >= MAX_NETFNS || !ibs->netfns[netfn / 2]) { - return NULL; - } - - if (cmd >= ibs->netfns[netfn / 2]->cmd_nums) { - return NULL; - } - - hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd]; - if (!hdl->cmd_handler) { - return NULL; - } - - return hdl; -} - -static void next_timeout(IPMIBmcSim *ibs) -{ - int64_t next; - if (ibs->watchdog_running) { - next = ibs->watchdog_expiry; - } else { - /* Wait a minute */ - next = ipmi_getmonotime() + 60 * 1000000000LL; - } - timer_mod_ns(ibs->timer, next); -} - -static void ipmi_sim_handle_command(IPMIBmc *b, - uint8_t *cmd, unsigned int cmd_len, - unsigned int max_cmd_len, - uint8_t msg_id) -{ - IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b); - IPMIInterface *s = ibs->parent.intf; - IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); - const IPMICmdHandler *hdl; - RspBuffer rsp = RSP_BUFFER_INITIALIZER; - - /* Set up the response, set the low bit of NETFN. */ - /* Note that max_rsp_len must be at least 3 */ - if (sizeof(rsp.buffer) < 3) { - rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED); - goto out; - } - - rsp_buffer_push(&rsp, cmd[0] | 0x04); - rsp_buffer_push(&rsp, cmd[1]); - rsp_buffer_push(&rsp, 0); /* Assume success */ - - /* If it's too short or it was truncated, return an error. */ - if (cmd_len < 2) { - rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID); - goto out; - } - if (cmd_len > max_cmd_len) { - rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED); - goto out; - } - - if ((cmd[0] & 0x03) != 0) { - /* Only have stuff on LUN 0 */ - rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN); - goto out; - } - - hdl = ipmi_get_handler(ibs, cmd[0] >> 2, cmd[1]); - if (!hdl) { - rsp_buffer_set_error(&rsp, IPMI_CC_INVALID_CMD); - goto out; - } - - if (cmd_len < hdl->cmd_len_min) { - rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID); - goto out; - } - - hdl->cmd_handler(ibs, cmd, cmd_len, &rsp); - - out: - k->handle_rsp(s, msg_id, rsp.buffer, rsp.len); - - next_timeout(ibs); -} - -static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs) -{ - IPMIInterface *s = ibs->parent.intf; - IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); - - if (!ibs->watchdog_running) { - goto out; - } - - if (!ibs->watchdog_preaction_ran) { - switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) { - case IPMI_BMC_WATCHDOG_PRE_NMI: - ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK; - k->do_hw_op(s, IPMI_SEND_NMI, 0); - sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1, - 0xc8, (2 << 4) | 0xf, 0xff); - break; - - case IPMI_BMC_WATCHDOG_PRE_MSG_INT: - ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK; - k->set_atn(s, 1, attn_irq_enabled(ibs)); - sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1, - 0xc8, (3 << 4) | 0xf, 0xff); - break; - - default: - goto do_full_expiry; - } - - ibs->watchdog_preaction_ran = 1; - /* Issued the pretimeout, do the rest of the timeout now. */ - ibs->watchdog_expiry = ipmi_getmonotime(); - ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL; - goto out; - } - - do_full_expiry: - ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */ - ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs)); - switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) { - case IPMI_BMC_WATCHDOG_ACTION_NONE: - sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1, - 0xc0, ibs->watchdog_use & 0xf, 0xff); - break; - - case IPMI_BMC_WATCHDOG_ACTION_RESET: - sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1, - 0xc1, ibs->watchdog_use & 0xf, 0xff); - k->do_hw_op(s, IPMI_RESET_CHASSIS, 0); - break; - - case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN: - sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1, - 0xc2, ibs->watchdog_use & 0xf, 0xff); - k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0); - break; - - case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE: - sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1, - 0xc3, ibs->watchdog_use & 0xf, 0xff); - k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0); - break; - } - - out: - next_timeout(ibs); -} - -static void chassis_capabilities(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - rsp_buffer_push(rsp, 0); - rsp_buffer_push(rsp, ibs->parent.slave_addr); - rsp_buffer_push(rsp, ibs->parent.slave_addr); - rsp_buffer_push(rsp, ibs->parent.slave_addr); - rsp_buffer_push(rsp, ibs->parent.slave_addr); -} - -static void chassis_status(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */ - rsp_buffer_push(rsp, 0); - rsp_buffer_push(rsp, 0); - rsp_buffer_push(rsp, 0); -} - -static void chassis_control(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMIInterface *s = ibs->parent.intf; - IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); - - switch (cmd[2] & 0xf) { - case 0: /* power down */ - rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0)); - break; - case 1: /* power up */ - rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0)); - break; - case 2: /* power cycle */ - rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0)); - break; - case 3: /* hard reset */ - rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0)); - break; - case 4: /* pulse diagnostic interrupt */ - rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0)); - break; - case 5: /* soft shutdown via ACPI by overtemp emulation */ - rsp_buffer_set_error(rsp, k->do_hw_op(s, - IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0)); - break; - default: - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - return; - } -} - -static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) - -{ - rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */ - rsp_buffer_push(rsp, 0); /* Channel 0 */ -} - -static void get_device_id(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - rsp_buffer_push(rsp, ibs->device_id); - rsp_buffer_push(rsp, ibs->device_rev & 0xf); - rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f); - rsp_buffer_push(rsp, ibs->fwrev2); - rsp_buffer_push(rsp, ibs->ipmi_version); - rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */ - rsp_buffer_push(rsp, ibs->mfg_id[0]); - rsp_buffer_push(rsp, ibs->mfg_id[1]); - rsp_buffer_push(rsp, ibs->mfg_id[2]); - rsp_buffer_push(rsp, ibs->product_id[0]); - rsp_buffer_push(rsp, ibs->product_id[1]); -} - -static void set_global_enables(IPMIBmcSim *ibs, uint8_t val) -{ - IPMIInterface *s = ibs->parent.intf; - IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); - bool irqs_on; - - ibs->bmc_global_enables = val; - - irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT | - IPMI_BMC_RCV_MSG_QUEUE_INT_BIT); - - k->set_irq_enable(s, irqs_on); -} - -static void cold_reset(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMIInterface *s = ibs->parent.intf; - IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); - - /* Disable all interrupts */ - set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT); - - if (k->reset) { - k->reset(s, true); - } -} - -static void warm_reset(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMIInterface *s = ibs->parent.intf; - IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); - - if (k->reset) { - k->reset(s, false); - } -} -static void set_acpi_power_state(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - ibs->acpi_power_state[0] = cmd[2]; - ibs->acpi_power_state[1] = cmd[3]; -} - -static void get_acpi_power_state(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - rsp_buffer_push(rsp, ibs->acpi_power_state[0]); - rsp_buffer_push(rsp, ibs->acpi_power_state[1]); -} - -static void get_device_guid(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - unsigned int i; - - for (i = 0; i < 16; i++) { - rsp_buffer_push(rsp, ibs->uuid[i]); - } -} - -static void set_bmc_global_enables(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - set_global_enables(ibs, cmd[2]); -} - -static void get_bmc_global_enables(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - rsp_buffer_push(rsp, ibs->bmc_global_enables); -} - -static void clr_msg_flags(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMIInterface *s = ibs->parent.intf; - IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); - - ibs->msg_flags &= ~cmd[2]; - k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs)); -} - -static void get_msg_flags(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - rsp_buffer_push(rsp, ibs->msg_flags); -} - -static void read_evt_msg_buf(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMIInterface *s = ibs->parent.intf; - IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); - unsigned int i; - - if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) { - rsp_buffer_set_error(rsp, 0x80); - return; - } - for (i = 0; i < 16; i++) { - rsp_buffer_push(rsp, ibs->evtbuf[i]); - } - ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL; - k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs)); -} - -static void get_msg(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMIRcvBufEntry *msg; - - qemu_mutex_lock(&ibs->lock); - if (QTAILQ_EMPTY(&ibs->rcvbufs)) { - rsp_buffer_set_error(rsp, 0x80); /* Queue empty */ - goto out; - } - rsp_buffer_push(rsp, 0); /* Channel 0 */ - msg = QTAILQ_FIRST(&ibs->rcvbufs); - rsp_buffer_pushmore(rsp, msg->buf, msg->len); - QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry); - g_free(msg); - - if (QTAILQ_EMPTY(&ibs->rcvbufs)) { - IPMIInterface *s = ibs->parent.intf; - IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); - - ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE; - k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs)); - } - -out: - qemu_mutex_unlock(&ibs->lock); - return; -} - -static unsigned char -ipmb_checksum(unsigned char *data, int size, unsigned char csum) -{ - for (; size > 0; size--, data++) { - csum += *data; - } - - return -csum; -} - -static void send_msg(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMIInterface *s = ibs->parent.intf; - IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); - IPMIRcvBufEntry *msg; - uint8_t *buf; - uint8_t netfn, rqLun, rsLun, rqSeq; - - if (cmd[2] != 0) { - /* We only handle channel 0 with no options */ - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - return; - } - - if (cmd_len < 10) { - rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID); - return; - } - - if (cmd[3] != 0x40) { - /* We only emulate a MC at address 0x40. */ - rsp_buffer_set_error(rsp, 0x83); /* NAK on write */ - return; - } - - cmd += 3; /* Skip the header. */ - cmd_len -= 3; - - /* - * At this point we "send" the message successfully. Any error will - * be returned in the response. - */ - if (ipmb_checksum(cmd, cmd_len, 0) != 0 || - cmd[3] != 0x20) { /* Improper response address */ - return; /* No response */ - } - - netfn = cmd[1] >> 2; - rqLun = cmd[4] & 0x3; - rsLun = cmd[1] & 0x3; - rqSeq = cmd[4] >> 2; - - if (rqLun != 2) { - /* We only support LUN 2 coming back to us. */ - return; - } - - msg = g_malloc(sizeof(*msg)); - msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */ - msg->buf[1] = ipmb_checksum(msg->buf, 1, 0); - msg->buf[2] = cmd[0]; /* rsSA */ - msg->buf[3] = (rqSeq << 2) | rsLun; - msg->buf[4] = cmd[5]; /* Cmd */ - msg->buf[5] = 0; /* Completion Code */ - msg->len = 6; - - if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) { - /* Not a command we handle. */ - msg->buf[5] = IPMI_CC_INVALID_CMD; - goto end_msg; - } - - buf = msg->buf + msg->len; /* After the CC */ - buf[0] = 0; - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - buf[4] = 0x51; - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - buf[8] = 0; - buf[9] = 0; - buf[10] = 0; - msg->len += 11; - - end_msg: - msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0); - msg->len++; - qemu_mutex_lock(&ibs->lock); - QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry); - ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE; - k->set_atn(s, 1, attn_irq_enabled(ibs)); - qemu_mutex_unlock(&ibs->lock); -} - -static void do_watchdog_reset(IPMIBmcSim *ibs) -{ - if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) == - IPMI_BMC_WATCHDOG_ACTION_NONE) { - ibs->watchdog_running = 0; - return; - } - ibs->watchdog_preaction_ran = 0; - - - /* Timeout is in tenths of a second, offset is in seconds */ - ibs->watchdog_expiry = ipmi_getmonotime(); - ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL; - if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) { - ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL; - } - ibs->watchdog_running = 1; -} - -static void reset_watchdog_timer(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - if (!ibs->watchdog_initialized) { - rsp_buffer_set_error(rsp, 0x80); - return; - } - do_watchdog_reset(ibs); -} - -static void set_watchdog_timer(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMIInterface *s = ibs->parent.intf; - IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); - unsigned int val; - - val = cmd[2] & 0x7; /* Validate use */ - if (val == 0 || val > 5) { - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - return; - } - val = cmd[3] & 0x7; /* Validate action */ - switch (val) { - case IPMI_BMC_WATCHDOG_ACTION_NONE: - break; - - case IPMI_BMC_WATCHDOG_ACTION_RESET: - rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1)); - break; - - case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN: - rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1)); - break; - - case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE: - rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1)); - break; - - default: - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - } - if (rsp->buffer[2]) { - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - return; - } - - val = (cmd[3] >> 4) & 0x7; /* Validate preaction */ - switch (val) { - case IPMI_BMC_WATCHDOG_PRE_MSG_INT: - case IPMI_BMC_WATCHDOG_PRE_NONE: - break; - - case IPMI_BMC_WATCHDOG_PRE_NMI: - if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) { - /* NMI not supported. */ - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - return; - } - break; - - default: - /* We don't support PRE_SMI */ - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - return; - } - - ibs->watchdog_initialized = 1; - ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK; - ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK; - ibs->watchdog_pretimeout = cmd[4]; - ibs->watchdog_expired &= ~cmd[5]; - ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8); - if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) { - do_watchdog_reset(ibs); - } else { - ibs->watchdog_running = 0; - } -} - -static void get_watchdog_timer(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - rsp_buffer_push(rsp, ibs->watchdog_use); - rsp_buffer_push(rsp, ibs->watchdog_action); - rsp_buffer_push(rsp, ibs->watchdog_pretimeout); - rsp_buffer_push(rsp, ibs->watchdog_expired); - if (ibs->watchdog_running) { - long timeout; - timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000) - / 100000000); - rsp_buffer_push(rsp, timeout & 0xff); - rsp_buffer_push(rsp, (timeout >> 8) & 0xff); - } else { - rsp_buffer_push(rsp, 0); - rsp_buffer_push(rsp, 0); - } -} - -static void get_sdr_rep_info(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - unsigned int i; - - rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */ - rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff); - rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff); - rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff); - rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff); - for (i = 0; i < 4; i++) { - rsp_buffer_push(rsp, ibs->sdr.last_addition[i]); - } - for (i = 0; i < 4; i++) { - rsp_buffer_push(rsp, ibs->sdr.last_clear[i]); - } - /* Only modal support, reserve supported */ - rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22); -} - -static void reserve_sdr_rep(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff); - rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff); -} - -static void get_sdr(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - unsigned int pos; - uint16_t nextrec; - struct ipmi_sdr_header *sdrh; - - if (cmd[6]) { - if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) { - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION); - return; - } - } - - pos = 0; - if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8), - &pos, &nextrec)) { - rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT); - return; - } - - sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos]; - - if (cmd[6] > ipmi_sdr_length(sdrh)) { - rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE); - return; - } - - rsp_buffer_push(rsp, nextrec & 0xff); - rsp_buffer_push(rsp, (nextrec >> 8) & 0xff); - - if (cmd[7] == 0xff) { - cmd[7] = ipmi_sdr_length(sdrh) - cmd[6]; - } - - if ((cmd[7] + rsp->len) > sizeof(rsp->buffer)) { - rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES); - return; - } - - rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]); -} - -static void add_sdr(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - uint16_t recid; - struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2; - - if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) { - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - return; - } - rsp_buffer_push(rsp, recid & 0xff); - rsp_buffer_push(rsp, (recid >> 8) & 0xff); -} - -static void clear_sdr_rep(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) { - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION); - return; - } - - if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') { - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - return; - } - if (cmd[7] == 0xaa) { - ibs->sdr.next_free = 0; - ibs->sdr.overflow = 0; - set_timestamp(ibs, ibs->sdr.last_clear); - rsp_buffer_push(rsp, 1); /* Erasure complete */ - sdr_inc_reservation(&ibs->sdr); - } else if (cmd[7] == 0) { - rsp_buffer_push(rsp, 1); /* Erasure complete */ - } else { - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - return; - } -} - -static void get_sel_info(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - unsigned int i, val; - - rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */ - rsp_buffer_push(rsp, ibs->sel.next_free & 0xff); - rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff); - val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16; - rsp_buffer_push(rsp, val & 0xff); - rsp_buffer_push(rsp, (val >> 8) & 0xff); - for (i = 0; i < 4; i++) { - rsp_buffer_push(rsp, ibs->sel.last_addition[i]); - } - for (i = 0; i < 4; i++) { - rsp_buffer_push(rsp, ibs->sel.last_clear[i]); - } - /* Only support Reserve SEL */ - rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02); -} - -static void reserve_sel(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - rsp_buffer_push(rsp, ibs->sel.reservation & 0xff); - rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff); -} - -static void get_sel_entry(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - unsigned int val; - - if (cmd[6]) { - if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) { - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION); - return; - } - } - if (ibs->sel.next_free == 0) { - rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT); - return; - } - if (cmd[6] > 15) { - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - return; - } - if (cmd[7] == 0xff) { - cmd[7] = 16; - } else if ((cmd[7] + cmd[6]) > 16) { - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - return; - } else { - cmd[7] += cmd[6]; - } - - val = cmd[4] | (cmd[5] << 8); - if (val == 0xffff) { - val = ibs->sel.next_free - 1; - } else if (val >= ibs->sel.next_free) { - rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT); - return; - } - if ((val + 1) == ibs->sel.next_free) { - rsp_buffer_push(rsp, 0xff); - rsp_buffer_push(rsp, 0xff); - } else { - rsp_buffer_push(rsp, (val + 1) & 0xff); - rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff); - } - for (; cmd[6] < cmd[7]; cmd[6]++) { - rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]); - } -} - -static void add_sel_entry(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - if (sel_add_event(ibs, cmd + 2)) { - rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE); - return; - } - /* sel_add_event fills in the record number. */ - rsp_buffer_push(rsp, cmd[2]); - rsp_buffer_push(rsp, cmd[3]); -} - -static void clear_sel(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) { - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION); - return; - } - - if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') { - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - return; - } - if (cmd[7] == 0xaa) { - ibs->sel.next_free = 0; - ibs->sel.overflow = 0; - set_timestamp(ibs, ibs->sdr.last_clear); - rsp_buffer_push(rsp, 1); /* Erasure complete */ - sel_inc_reservation(&ibs->sel); - } else if (cmd[7] == 0) { - rsp_buffer_push(rsp, 1); /* Erasure complete */ - } else { - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - return; - } -} - -static void get_sel_time(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - uint32_t val; - struct ipmi_time now; - - ipmi_gettime(&now); - val = now.tv_sec + ibs->sel.time_offset; - rsp_buffer_push(rsp, val & 0xff); - rsp_buffer_push(rsp, (val >> 8) & 0xff); - rsp_buffer_push(rsp, (val >> 16) & 0xff); - rsp_buffer_push(rsp, (val >> 24) & 0xff); -} - -static void set_sel_time(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - uint32_t val; - struct ipmi_time now; - - val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24); - ipmi_gettime(&now); - ibs->sel.time_offset = now.tv_sec - ((long) val); -} - -static void set_sensor_evt_enable(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMISensor *sens; - - if ((cmd[2] >= MAX_SENSORS) || - !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) { - rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT); - return; - } - sens = ibs->sensors + cmd[2]; - switch ((cmd[3] >> 4) & 0x3) { - case 0: /* Do not change */ - break; - case 1: /* Enable bits */ - if (cmd_len > 4) { - sens->assert_enable |= cmd[4]; - } - if (cmd_len > 5) { - sens->assert_enable |= cmd[5] << 8; - } - if (cmd_len > 6) { - sens->deassert_enable |= cmd[6]; - } - if (cmd_len > 7) { - sens->deassert_enable |= cmd[7] << 8; - } - break; - case 2: /* Disable bits */ - if (cmd_len > 4) { - sens->assert_enable &= ~cmd[4]; - } - if (cmd_len > 5) { - sens->assert_enable &= ~(cmd[5] << 8); - } - if (cmd_len > 6) { - sens->deassert_enable &= ~cmd[6]; - } - if (cmd_len > 7) { - sens->deassert_enable &= ~(cmd[7] << 8); - } - break; - case 3: - rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); - return; - } - IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]); -} - -static void get_sensor_evt_enable(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMISensor *sens; - - if ((cmd[2] >= MAX_SENSORS) || - !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) { - rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT); - return; - } - sens = ibs->sensors + cmd[2]; - rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens)); - rsp_buffer_push(rsp, sens->assert_enable & 0xff); - rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff); - rsp_buffer_push(rsp, sens->deassert_enable & 0xff); - rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff); -} - -static void rearm_sensor_evts(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMISensor *sens; - - if ((cmd[2] >= MAX_SENSORS) || - !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) { - rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT); - return; - } - sens = ibs->sensors + cmd[2]; - - if ((cmd[3] & 0x80) == 0) { - /* Just clear everything */ - sens->states = 0; - return; - } -} - -static void get_sensor_evt_status(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMISensor *sens; - - if ((cmd[2] >= MAX_SENSORS) || - !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) { - rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT); - return; - } - sens = ibs->sensors + cmd[2]; - rsp_buffer_push(rsp, sens->reading); - rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens)); - rsp_buffer_push(rsp, sens->assert_states & 0xff); - rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff); - rsp_buffer_push(rsp, sens->deassert_states & 0xff); - rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff); -} - -static void get_sensor_reading(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMISensor *sens; - - if ((cmd[2] >= MAX_SENSORS) || - !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) { - rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT); - return; - } - sens = ibs->sensors + cmd[2]; - rsp_buffer_push(rsp, sens->reading); - rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens)); - rsp_buffer_push(rsp, sens->states & 0xff); - if (IPMI_SENSOR_IS_DISCRETE(sens)) { - rsp_buffer_push(rsp, (sens->states >> 8) & 0xff); - } -} - -static void set_sensor_type(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMISensor *sens; - - - if ((cmd[2] >= MAX_SENSORS) || - !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) { - rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT); - return; - } - sens = ibs->sensors + cmd[2]; - sens->sensor_type = cmd[3]; - sens->evt_reading_type_code = cmd[4] & 0x7f; -} - -static void get_sensor_type(IPMIBmcSim *ibs, - uint8_t *cmd, unsigned int cmd_len, - RspBuffer *rsp) -{ - IPMISensor *sens; - - - if ((cmd[2] >= MAX_SENSORS) || - !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) { - rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT); - return; - } - sens = ibs->sensors + cmd[2]; - rsp_buffer_push(rsp, sens->sensor_type); - rsp_buffer_push(rsp, sens->evt_reading_type_code); -} - - -static const IPMICmdHandler chassis_cmds[] = { - [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities }, - [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status }, - [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 }, - [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause } -}; -static const IPMINetfn chassis_netfn = { - .cmd_nums = ARRAY_SIZE(chassis_cmds), - .cmd_handlers = chassis_cmds -}; - -static const IPMICmdHandler sensor_event_cmds[] = { - [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 }, - [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 }, - [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 }, - [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 }, - [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 }, - [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 }, - [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 }, -}; -static const IPMINetfn sensor_event_netfn = { - .cmd_nums = ARRAY_SIZE(sensor_event_cmds), - .cmd_handlers = sensor_event_cmds -}; - -static const IPMICmdHandler app_cmds[] = { - [IPMI_CMD_GET_DEVICE_ID] = { get_device_id }, - [IPMI_CMD_COLD_RESET] = { cold_reset }, - [IPMI_CMD_WARM_RESET] = { warm_reset }, - [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 }, - [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state }, - [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid }, - [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 }, - [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables }, - [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 }, - [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags }, - [IPMI_CMD_GET_MSG] = { get_msg }, - [IPMI_CMD_SEND_MSG] = { send_msg, 3 }, - [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf }, - [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer }, - [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 }, - [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer }, -}; -static const IPMINetfn app_netfn = { - .cmd_nums = ARRAY_SIZE(app_cmds), - .cmd_handlers = app_cmds -}; - -static const IPMICmdHandler storage_cmds[] = { - [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info }, - [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep }, - [IPMI_CMD_GET_SDR] = { get_sdr, 8 }, - [IPMI_CMD_ADD_SDR] = { add_sdr }, - [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 }, - [IPMI_CMD_GET_SEL_INFO] = { get_sel_info }, - [IPMI_CMD_RESERVE_SEL] = { reserve_sel }, - [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 }, - [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 }, - [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 }, - [IPMI_CMD_GET_SEL_TIME] = { get_sel_time, 6 }, - [IPMI_CMD_SET_SEL_TIME] = { set_sel_time }, -}; - -static const IPMINetfn storage_netfn = { - .cmd_nums = ARRAY_SIZE(storage_cmds), - .cmd_handlers = storage_cmds -}; - -static void register_cmds(IPMIBmcSim *s) -{ - ipmi_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn); - ipmi_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn); - ipmi_register_netfn(s, IPMI_NETFN_APP, &app_netfn); - ipmi_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn); -} - -static uint8_t init_sdrs[] = { - /* Watchdog device */ - 0x00, 0x00, 0x51, 0x02, 35, 0x20, 0x00, 0x00, - 0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, - 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', -}; - -static void ipmi_sdr_init(IPMIBmcSim *ibs) -{ - unsigned int i; - int len; - size_t sdrs_size; - uint8_t *sdrs; - - sdrs_size = sizeof(init_sdrs); - sdrs = init_sdrs; - - for (i = 0; i < sdrs_size; i += len) { - struct ipmi_sdr_header *sdrh; - - if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) { - error_report("Problem with recid 0x%4.4x", i); - return; - } - sdrh = (struct ipmi_sdr_header *) &sdrs[i]; - len = ipmi_sdr_length(sdrh); - if (i + len > sdrs_size) { - error_report("Problem with recid 0x%4.4x", i); - return; - } - sdr_add_entry(ibs, sdrh, len, NULL); - } -} - -static const VMStateDescription vmstate_ipmi_sim = { - .name = TYPE_IPMI_BMC_SIMULATOR, - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim), - VMSTATE_UINT8(msg_flags, IPMIBmcSim), - VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim), - VMSTATE_UINT8(watchdog_use, IPMIBmcSim), - VMSTATE_UINT8(watchdog_action, IPMIBmcSim), - VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim), - VMSTATE_BOOL(watchdog_expired, IPMIBmcSim), - VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim), - VMSTATE_BOOL(watchdog_running, IPMIBmcSim), - VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim), - VMSTATE_INT64(watchdog_expiry, IPMIBmcSim), - VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16), - VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim), - VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim), - VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim), - VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim), - VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states, - IPMIBmcSim), - VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim), - VMSTATE_END_OF_LIST() - } -}; - -static void ipmi_sim_realize(DeviceState *dev, Error **errp) -{ - IPMIBmc *b = IPMI_BMC(dev); - unsigned int i; - IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b); - - qemu_mutex_init(&ibs->lock); - QTAILQ_INIT(&ibs->rcvbufs); - - ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT); - ibs->device_id = 0x20; - ibs->ipmi_version = 0x02; /* IPMI 2.0 */ - ibs->restart_cause = 0; - for (i = 0; i < 4; i++) { - ibs->sel.last_addition[i] = 0xff; - ibs->sel.last_clear[i] = 0xff; - ibs->sdr.last_addition[i] = 0xff; - ibs->sdr.last_clear[i] = 0xff; - } - - ipmi_sdr_init(ibs); - - ibs->acpi_power_state[0] = 0; - ibs->acpi_power_state[1] = 0; - - if (qemu_uuid_set) { - memcpy(&ibs->uuid, qemu_uuid, 16); - } else { - memset(&ibs->uuid, 0, 16); - } - - ipmi_init_sensors_from_sdrs(ibs); - register_cmds(ibs); - - ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs); - - vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs); -} - -static void ipmi_sim_class_init(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - IPMIBmcClass *bk = IPMI_BMC_CLASS(oc); - - dc->realize = ipmi_sim_realize; - bk->handle_command = ipmi_sim_handle_command; -} - -static const TypeInfo ipmi_sim_type = { - .name = TYPE_IPMI_BMC_SIMULATOR, - .parent = TYPE_IPMI_BMC, - .instance_size = sizeof(IPMIBmcSim), - .class_init = ipmi_sim_class_init, -}; - -static void ipmi_sim_register_types(void) -{ - type_register_static(&ipmi_sim_type); -} - -type_init(ipmi_sim_register_types) |