cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

ipmi_bmc_sim.c (68728B)


      1/*
      2 * IPMI BMC emulation
      3 *
      4 * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
      5 *
      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:
     12 *
     13 * The above copyright notice and this permission notice shall be included in
     14 * all copies or substantial portions of the Software.
     15 *
     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
     22 * THE SOFTWARE.
     23 */
     24
     25#include "qemu/osdep.h"
     26#include "sysemu/sysemu.h"
     27#include "qemu/timer.h"
     28#include "hw/ipmi/ipmi.h"
     29#include "qemu/error-report.h"
     30#include "qemu/module.h"
     31#include "hw/loader.h"
     32#include "hw/qdev-properties.h"
     33#include "hw/qdev-properties-system.h"
     34#include "migration/vmstate.h"
     35
     36#define IPMI_NETFN_CHASSIS            0x00
     37
     38#define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
     39#define IPMI_CMD_GET_CHASSIS_STATUS       0x01
     40#define IPMI_CMD_CHASSIS_CONTROL          0x02
     41#define IPMI_CMD_GET_SYS_RESTART_CAUSE    0x09
     42
     43#define IPMI_NETFN_SENSOR_EVENT       0x04
     44
     45#define IPMI_CMD_PLATFORM_EVENT_MSG       0x02
     46#define IPMI_CMD_SET_SENSOR_EVT_ENABLE    0x28
     47#define IPMI_CMD_GET_SENSOR_EVT_ENABLE    0x29
     48#define IPMI_CMD_REARM_SENSOR_EVTS        0x2a
     49#define IPMI_CMD_GET_SENSOR_EVT_STATUS    0x2b
     50#define IPMI_CMD_GET_SENSOR_READING       0x2d
     51#define IPMI_CMD_SET_SENSOR_TYPE          0x2e
     52#define IPMI_CMD_GET_SENSOR_TYPE          0x2f
     53#define IPMI_CMD_SET_SENSOR_READING       0x30
     54
     55/* #define IPMI_NETFN_APP             0x06 In ipmi.h */
     56
     57#define IPMI_CMD_GET_DEVICE_ID            0x01
     58#define IPMI_CMD_COLD_RESET               0x02
     59#define IPMI_CMD_WARM_RESET               0x03
     60#define IPMI_CMD_SET_ACPI_POWER_STATE     0x06
     61#define IPMI_CMD_GET_ACPI_POWER_STATE     0x07
     62#define IPMI_CMD_GET_DEVICE_GUID          0x08
     63#define IPMI_CMD_RESET_WATCHDOG_TIMER     0x22
     64#define IPMI_CMD_SET_WATCHDOG_TIMER       0x24
     65#define IPMI_CMD_GET_WATCHDOG_TIMER       0x25
     66#define IPMI_CMD_SET_BMC_GLOBAL_ENABLES   0x2e
     67#define IPMI_CMD_GET_BMC_GLOBAL_ENABLES   0x2f
     68#define IPMI_CMD_CLR_MSG_FLAGS            0x30
     69#define IPMI_CMD_GET_MSG_FLAGS            0x31
     70#define IPMI_CMD_GET_MSG                  0x33
     71#define IPMI_CMD_SEND_MSG                 0x34
     72#define IPMI_CMD_READ_EVT_MSG_BUF         0x35
     73
     74#define IPMI_NETFN_STORAGE            0x0a
     75
     76#define IPMI_CMD_GET_SDR_REP_INFO         0x20
     77#define IPMI_CMD_GET_SDR_REP_ALLOC_INFO   0x21
     78#define IPMI_CMD_RESERVE_SDR_REP          0x22
     79#define IPMI_CMD_GET_SDR                  0x23
     80#define IPMI_CMD_ADD_SDR                  0x24
     81#define IPMI_CMD_PARTIAL_ADD_SDR          0x25
     82#define IPMI_CMD_DELETE_SDR               0x26
     83#define IPMI_CMD_CLEAR_SDR_REP            0x27
     84#define IPMI_CMD_GET_SDR_REP_TIME         0x28
     85#define IPMI_CMD_SET_SDR_REP_TIME         0x29
     86#define IPMI_CMD_ENTER_SDR_REP_UPD_MODE   0x2A
     87#define IPMI_CMD_EXIT_SDR_REP_UPD_MODE    0x2B
     88#define IPMI_CMD_RUN_INIT_AGENT           0x2C
     89#define IPMI_CMD_GET_FRU_AREA_INFO        0x10
     90#define IPMI_CMD_READ_FRU_DATA            0x11
     91#define IPMI_CMD_WRITE_FRU_DATA           0x12
     92#define IPMI_CMD_GET_SEL_INFO             0x40
     93#define IPMI_CMD_GET_SEL_ALLOC_INFO       0x41
     94#define IPMI_CMD_RESERVE_SEL              0x42
     95#define IPMI_CMD_GET_SEL_ENTRY            0x43
     96#define IPMI_CMD_ADD_SEL_ENTRY            0x44
     97#define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY    0x45
     98#define IPMI_CMD_DELETE_SEL_ENTRY         0x46
     99#define IPMI_CMD_CLEAR_SEL                0x47
    100#define IPMI_CMD_GET_SEL_TIME             0x48
    101#define IPMI_CMD_SET_SEL_TIME             0x49
    102
    103
    104/* Same as a timespec struct. */
    105struct ipmi_time {
    106    long tv_sec;
    107    long tv_nsec;
    108};
    109
    110#define MAX_SEL_SIZE 128
    111
    112typedef struct IPMISel {
    113    uint8_t sel[MAX_SEL_SIZE][16];
    114    unsigned int next_free;
    115    long time_offset;
    116    uint16_t reservation;
    117    uint8_t last_addition[4];
    118    uint8_t last_clear[4];
    119    uint8_t overflow;
    120} IPMISel;
    121
    122#define MAX_SDR_SIZE 16384
    123
    124typedef struct IPMISdr {
    125    uint8_t sdr[MAX_SDR_SIZE];
    126    unsigned int next_free;
    127    uint16_t next_rec_id;
    128    uint16_t reservation;
    129    uint8_t last_addition[4];
    130    uint8_t last_clear[4];
    131    uint8_t overflow;
    132} IPMISdr;
    133
    134typedef struct IPMIFru {
    135    char *filename;
    136    unsigned int nentries;
    137    uint16_t areasize;
    138    uint8_t *data;
    139} IPMIFru;
    140
    141typedef struct IPMISensor {
    142    uint8_t status;
    143    uint8_t reading;
    144    uint16_t states_suppt;
    145    uint16_t assert_suppt;
    146    uint16_t deassert_suppt;
    147    uint16_t states;
    148    uint16_t assert_states;
    149    uint16_t deassert_states;
    150    uint16_t assert_enable;
    151    uint16_t deassert_enable;
    152    uint8_t  sensor_type;
    153    uint8_t  evt_reading_type_code;
    154} IPMISensor;
    155#define IPMI_SENSOR_GET_PRESENT(s)       ((s)->status & 0x01)
    156#define IPMI_SENSOR_SET_PRESENT(s, v)    ((s)->status = (s->status & ~0x01) | \
    157                                             !!(v))
    158#define IPMI_SENSOR_GET_SCAN_ON(s)       ((s)->status & 0x40)
    159#define IPMI_SENSOR_SET_SCAN_ON(s, v)    ((s)->status = (s->status & ~0x40) | \
    160                                             ((!!(v)) << 6))
    161#define IPMI_SENSOR_GET_EVENTS_ON(s)     ((s)->status & 0x80)
    162#define IPMI_SENSOR_SET_EVENTS_ON(s, v)  ((s)->status = (s->status & ~0x80) | \
    163                                             ((!!(v)) << 7))
    164#define IPMI_SENSOR_GET_RET_STATUS(s)    ((s)->status & 0xc0)
    165#define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
    166                                             (v & 0xc0))
    167#define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
    168
    169#define MAX_SENSORS 20
    170#define IPMI_WATCHDOG_SENSOR 0
    171
    172#define MAX_NETFNS 64
    173
    174typedef struct IPMIRcvBufEntry {
    175    QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
    176    uint8_t len;
    177    uint8_t buf[MAX_IPMI_MSG_SIZE];
    178} IPMIRcvBufEntry;
    179
    180struct IPMIBmcSim {
    181    IPMIBmc parent;
    182
    183    QEMUTimer *timer;
    184
    185    uint8_t bmc_global_enables;
    186    uint8_t msg_flags;
    187
    188    bool     watchdog_initialized;
    189    uint8_t  watchdog_use;
    190    uint8_t  watchdog_action;
    191    uint8_t  watchdog_pretimeout; /* In seconds */
    192    uint8_t  watchdog_expired;
    193    uint16_t watchdog_timeout; /* in 100's of milliseconds */
    194
    195    bool     watchdog_running;
    196    bool     watchdog_preaction_ran;
    197    int64_t  watchdog_expiry;
    198
    199    uint8_t device_id;
    200    uint8_t ipmi_version;
    201    uint8_t device_rev;
    202    uint8_t fwrev1;
    203    uint8_t fwrev2;
    204    uint32_t mfg_id;
    205    uint16_t product_id;
    206
    207    uint8_t restart_cause;
    208
    209    uint8_t acpi_power_state[2];
    210    QemuUUID uuid;
    211
    212    IPMISel sel;
    213    IPMISdr sdr;
    214    IPMIFru fru;
    215    IPMISensor sensors[MAX_SENSORS];
    216    char *sdr_filename;
    217
    218    /* Odd netfns are for responses, so we only need the even ones. */
    219    const IPMINetfn *netfns[MAX_NETFNS / 2];
    220
    221    /* We allow one event in the buffer */
    222    uint8_t evtbuf[16];
    223
    224    QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
    225};
    226
    227#define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK        (1 << 3)
    228#define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL                 (1 << 1)
    229#define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE                (1 << 0)
    230#define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
    231    (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
    232#define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
    233    (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
    234#define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
    235    (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
    236
    237#define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT    0
    238#define IPMI_BMC_EVBUF_FULL_INT_BIT       1
    239#define IPMI_BMC_EVENT_MSG_BUF_BIT        2
    240#define IPMI_BMC_EVENT_LOG_BIT            3
    241#define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
    242                                 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
    243#define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
    244                                        (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
    245#define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
    246                                       (1 << IPMI_BMC_EVENT_LOG_BIT))
    247#define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
    248                                           (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
    249
    250#define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
    251#define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
    252#define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
    253#define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
    254#define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
    255#define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
    256#define IPMI_BMC_WATCHDOG_PRE_NONE               0
    257#define IPMI_BMC_WATCHDOG_PRE_SMI                1
    258#define IPMI_BMC_WATCHDOG_PRE_NMI                2
    259#define IPMI_BMC_WATCHDOG_PRE_MSG_INT            3
    260#define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
    261#define IPMI_BMC_WATCHDOG_ACTION_NONE            0
    262#define IPMI_BMC_WATCHDOG_ACTION_RESET           1
    263#define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN      2
    264#define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE     3
    265
    266#define RSP_BUFFER_INITIALIZER { }
    267
    268static inline void rsp_buffer_pushmore(RspBuffer *rsp, uint8_t *bytes,
    269                                       unsigned int n)
    270{
    271    if (rsp->len + n >= sizeof(rsp->buffer)) {
    272        rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
    273        return;
    274    }
    275
    276    memcpy(&rsp->buffer[rsp->len], bytes, n);
    277    rsp->len += n;
    278}
    279
    280static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
    281
    282static void ipmi_gettime(struct ipmi_time *time)
    283{
    284    int64_t stime;
    285
    286    stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
    287    time->tv_sec = stime / 1000000000LL;
    288    time->tv_nsec = stime % 1000000000LL;
    289}
    290
    291static int64_t ipmi_getmonotime(void)
    292{
    293    return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
    294}
    295
    296static void ipmi_timeout(void *opaque)
    297{
    298    IPMIBmcSim *ibs = opaque;
    299
    300    ipmi_sim_handle_timeout(ibs);
    301}
    302
    303static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
    304{
    305    unsigned int val;
    306    struct ipmi_time now;
    307
    308    ipmi_gettime(&now);
    309    val = now.tv_sec + ibs->sel.time_offset;
    310    ts[0] = val & 0xff;
    311    ts[1] = (val >> 8) & 0xff;
    312    ts[2] = (val >> 16) & 0xff;
    313    ts[3] = (val >> 24) & 0xff;
    314}
    315
    316static void sdr_inc_reservation(IPMISdr *sdr)
    317{
    318    sdr->reservation++;
    319    if (sdr->reservation == 0) {
    320        sdr->reservation = 1;
    321    }
    322}
    323
    324static int sdr_add_entry(IPMIBmcSim *ibs,
    325                         const struct ipmi_sdr_header *sdrh_entry,
    326                         unsigned int len, uint16_t *recid)
    327{
    328    struct ipmi_sdr_header *sdrh =
    329        (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
    330
    331    if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
    332        return 1;
    333    }
    334
    335    if (ipmi_sdr_length(sdrh_entry) != len) {
    336        return 1;
    337    }
    338
    339    if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
    340        ibs->sdr.overflow = 1;
    341        return 1;
    342    }
    343
    344    memcpy(sdrh, sdrh_entry, len);
    345    sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff;
    346    sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
    347    sdrh->sdr_version = 0x51; /* Conform to IPMI 1.5 spec */
    348
    349    if (recid) {
    350        *recid = ibs->sdr.next_rec_id;
    351    }
    352    ibs->sdr.next_rec_id++;
    353    set_timestamp(ibs, ibs->sdr.last_addition);
    354    ibs->sdr.next_free += len;
    355    sdr_inc_reservation(&ibs->sdr);
    356    return 0;
    357}
    358
    359static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
    360                          unsigned int *retpos, uint16_t *nextrec)
    361{
    362    unsigned int pos = *retpos;
    363
    364    while (pos < sdr->next_free) {
    365        struct ipmi_sdr_header *sdrh =
    366            (struct ipmi_sdr_header *) &sdr->sdr[pos];
    367        uint16_t trec = ipmi_sdr_recid(sdrh);
    368        unsigned int nextpos = pos + ipmi_sdr_length(sdrh);
    369
    370        if (trec == recid) {
    371            if (nextrec) {
    372                if (nextpos >= sdr->next_free) {
    373                    *nextrec = 0xffff;
    374                } else {
    375                    *nextrec = (sdr->sdr[nextpos] |
    376                                (sdr->sdr[nextpos + 1] << 8));
    377                }
    378            }
    379            *retpos = pos;
    380            return 0;
    381        }
    382        pos = nextpos;
    383    }
    384    return 1;
    385}
    386
    387int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
    388                      const struct ipmi_sdr_compact **sdr, uint16_t *nextrec)
    389
    390{
    391    IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
    392    unsigned int pos;
    393
    394    pos = 0;
    395    if (sdr_find_entry(&ibs->sdr, recid, &pos, nextrec)) {
    396        return -1;
    397    }
    398
    399    *sdr = (const struct ipmi_sdr_compact *) &ibs->sdr.sdr[pos];
    400    return 0;
    401}
    402
    403static void sel_inc_reservation(IPMISel *sel)
    404{
    405    sel->reservation++;
    406    if (sel->reservation == 0) {
    407        sel->reservation = 1;
    408    }
    409}
    410
    411/* Returns 1 if the SEL is full and can't hold the event. */
    412static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
    413{
    414    uint8_t ts[4];
    415
    416    event[0] = 0xff;
    417    event[1] = 0xff;
    418    set_timestamp(ibs, ts);
    419    if (event[2] < 0xe0) { /* Don't set timestamps for type 0xe0-0xff. */
    420        memcpy(event + 3, ts, 4);
    421    }
    422    if (ibs->sel.next_free == MAX_SEL_SIZE) {
    423        ibs->sel.overflow = 1;
    424        return 1;
    425    }
    426    event[0] = ibs->sel.next_free & 0xff;
    427    event[1] = (ibs->sel.next_free >> 8) & 0xff;
    428    memcpy(ibs->sel.last_addition, ts, 4);
    429    memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
    430    ibs->sel.next_free++;
    431    sel_inc_reservation(&ibs->sel);
    432    return 0;
    433}
    434
    435static int attn_set(IPMIBmcSim *ibs)
    436{
    437    return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
    438        || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
    439        || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
    440}
    441
    442static int attn_irq_enabled(IPMIBmcSim *ibs)
    443{
    444    return (IPMI_BMC_MSG_INTS_ON(ibs) &&
    445            (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs) ||
    446             IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs)))
    447        || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
    448            IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
    449}
    450
    451void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log)
    452{
    453    IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
    454    IPMIInterface *s = ibs->parent.intf;
    455    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
    456
    457    if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
    458        return;
    459    }
    460
    461    if (log && IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
    462        sel_add_event(ibs, evt);
    463    }
    464
    465    if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
    466        goto out;
    467    }
    468
    469    memcpy(ibs->evtbuf, evt, 16);
    470    ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
    471    k->set_atn(s, 1, attn_irq_enabled(ibs));
    472 out:
    473    return;
    474}
    475static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
    476                      uint8_t evd1, uint8_t evd2, uint8_t evd3)
    477{
    478    IPMIInterface *s = ibs->parent.intf;
    479    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
    480    uint8_t evt[16];
    481    IPMISensor *sens = ibs->sensors + sens_num;
    482
    483    if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
    484        return;
    485    }
    486    if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
    487        return;
    488    }
    489
    490    evt[2] = 0x2; /* System event record */
    491    evt[7] = ibs->parent.slave_addr;
    492    evt[8] = 0;
    493    evt[9] = 0x04; /* Format version */
    494    evt[10] = sens->sensor_type;
    495    evt[11] = sens_num;
    496    evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
    497    evt[13] = evd1;
    498    evt[14] = evd2;
    499    evt[15] = evd3;
    500
    501    if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
    502        sel_add_event(ibs, evt);
    503    }
    504
    505    if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
    506        return;
    507    }
    508
    509    memcpy(ibs->evtbuf, evt, 16);
    510    ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
    511    k->set_atn(s, 1, attn_irq_enabled(ibs));
    512}
    513
    514static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
    515                                    unsigned int bit, unsigned int val,
    516                                    uint8_t evd1, uint8_t evd2, uint8_t evd3)
    517{
    518    IPMISensor *sens;
    519    uint16_t mask;
    520
    521    if (sensor >= MAX_SENSORS) {
    522        return;
    523    }
    524    if (bit >= 16) {
    525        return;
    526    }
    527
    528    mask = (1 << bit);
    529    sens = ibs->sensors + sensor;
    530    if (val) {
    531        sens->states |= mask & sens->states_suppt;
    532        if (sens->assert_states & mask) {
    533            return; /* Already asserted */
    534        }
    535        sens->assert_states |= mask & sens->assert_suppt;
    536        if (sens->assert_enable & mask & sens->assert_states) {
    537            /* Send an event on assert */
    538            gen_event(ibs, sensor, 0, evd1, evd2, evd3);
    539        }
    540    } else {
    541        sens->states &= ~(mask & sens->states_suppt);
    542        if (sens->deassert_states & mask) {
    543            return; /* Already deasserted */
    544        }
    545        sens->deassert_states |= mask & sens->deassert_suppt;
    546        if (sens->deassert_enable & mask & sens->deassert_states) {
    547            /* Send an event on deassert */
    548            gen_event(ibs, sensor, 1, evd1, evd2, evd3);
    549        }
    550    }
    551}
    552
    553static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
    554{
    555    unsigned int i, pos;
    556    IPMISensor *sens;
    557
    558    for (i = 0; i < MAX_SENSORS; i++) {
    559        memset(s->sensors + i, 0, sizeof(*sens));
    560    }
    561
    562    pos = 0;
    563    for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
    564        struct ipmi_sdr_compact *sdr =
    565            (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
    566        unsigned int len = sdr->header.rec_length;
    567
    568        if (len < 20) {
    569            continue;
    570        }
    571        if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
    572            continue; /* Not a sensor SDR we set from */
    573        }
    574
    575        if (sdr->sensor_owner_number >= MAX_SENSORS) {
    576            continue;
    577        }
    578        sens = s->sensors + sdr->sensor_owner_number;
    579
    580        IPMI_SENSOR_SET_PRESENT(sens, 1);
    581        IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
    582        IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
    583        sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
    584        sens->deassert_suppt =
    585            sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
    586        sens->states_suppt =
    587            sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
    588        sens->sensor_type = sdr->sensor_type;
    589        sens->evt_reading_type_code = sdr->reading_type & 0x7f;
    590
    591        /* Enable all the events that are supported. */
    592        sens->assert_enable = sens->assert_suppt;
    593        sens->deassert_enable = sens->deassert_suppt;
    594    }
    595}
    596
    597int ipmi_sim_register_netfn(IPMIBmcSim *s, unsigned int netfn,
    598                        const IPMINetfn *netfnd)
    599{
    600    if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
    601        return -1;
    602    }
    603    s->netfns[netfn / 2] = netfnd;
    604    return 0;
    605}
    606
    607static const IPMICmdHandler *ipmi_get_handler(IPMIBmcSim *ibs,
    608                                              unsigned int netfn,
    609                                              unsigned int cmd)
    610{
    611    const IPMICmdHandler *hdl;
    612
    613    if (netfn & 1 || netfn >= MAX_NETFNS || !ibs->netfns[netfn / 2]) {
    614        return NULL;
    615    }
    616
    617    if (cmd >= ibs->netfns[netfn / 2]->cmd_nums) {
    618        return NULL;
    619    }
    620
    621    hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd];
    622    if (!hdl->cmd_handler) {
    623        return NULL;
    624    }
    625
    626    return hdl;
    627}
    628
    629static void next_timeout(IPMIBmcSim *ibs)
    630{
    631    int64_t next;
    632    if (ibs->watchdog_running) {
    633        next = ibs->watchdog_expiry;
    634    } else {
    635        /* Wait a minute */
    636        next = ipmi_getmonotime() + 60 * 1000000000LL;
    637    }
    638    timer_mod_ns(ibs->timer, next);
    639}
    640
    641static void ipmi_sim_handle_command(IPMIBmc *b,
    642                                    uint8_t *cmd, unsigned int cmd_len,
    643                                    unsigned int max_cmd_len,
    644                                    uint8_t msg_id)
    645{
    646    IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
    647    IPMIInterface *s = ibs->parent.intf;
    648    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
    649    const IPMICmdHandler *hdl;
    650    RspBuffer rsp = RSP_BUFFER_INITIALIZER;
    651
    652    /* Set up the response, set the low bit of NETFN. */
    653    /* Note that max_rsp_len must be at least 3 */
    654    if (sizeof(rsp.buffer) < 3) {
    655        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
    656        goto out;
    657    }
    658
    659    rsp_buffer_push(&rsp, cmd[0] | 0x04);
    660    rsp_buffer_push(&rsp, cmd[1]);
    661    rsp_buffer_push(&rsp, 0); /* Assume success */
    662
    663    /* If it's too short or it was truncated, return an error. */
    664    if (cmd_len < 2) {
    665        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
    666        goto out;
    667    }
    668    if (cmd_len > max_cmd_len) {
    669        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
    670        goto out;
    671    }
    672
    673    if ((cmd[0] & 0x03) != 0) {
    674        /* Only have stuff on LUN 0 */
    675        rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN);
    676        goto out;
    677    }
    678
    679    hdl = ipmi_get_handler(ibs, cmd[0] >> 2, cmd[1]);
    680    if (!hdl) {
    681        rsp_buffer_set_error(&rsp, IPMI_CC_INVALID_CMD);
    682        goto out;
    683    }
    684
    685    if (cmd_len < hdl->cmd_len_min) {
    686        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
    687        goto out;
    688    }
    689
    690    hdl->cmd_handler(ibs, cmd, cmd_len, &rsp);
    691
    692 out:
    693    k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
    694
    695    next_timeout(ibs);
    696}
    697
    698static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
    699{
    700    IPMIInterface *s = ibs->parent.intf;
    701    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
    702
    703    if (!ibs->watchdog_running) {
    704        goto out;
    705    }
    706
    707    if (!ibs->watchdog_preaction_ran) {
    708        switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
    709        case IPMI_BMC_WATCHDOG_PRE_NMI:
    710            ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
    711            k->do_hw_op(s, IPMI_SEND_NMI, 0);
    712            sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
    713                                    0xc8, (2 << 4) | 0xf, 0xff);
    714            break;
    715
    716        case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
    717            ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
    718            k->set_atn(s, 1, attn_irq_enabled(ibs));
    719            sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
    720                                    0xc8, (3 << 4) | 0xf, 0xff);
    721            break;
    722
    723        default:
    724            goto do_full_expiry;
    725        }
    726
    727        ibs->watchdog_preaction_ran = 1;
    728        /* Issued the pretimeout, do the rest of the timeout now. */
    729        ibs->watchdog_expiry = ipmi_getmonotime();
    730        ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
    731        goto out;
    732    }
    733
    734 do_full_expiry:
    735    ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
    736    ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
    737    switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
    738    case IPMI_BMC_WATCHDOG_ACTION_NONE:
    739        sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
    740                                0xc0, ibs->watchdog_use & 0xf, 0xff);
    741        break;
    742
    743    case IPMI_BMC_WATCHDOG_ACTION_RESET:
    744        sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
    745                                0xc1, ibs->watchdog_use & 0xf, 0xff);
    746        k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
    747        break;
    748
    749    case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
    750        sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
    751                                0xc2, ibs->watchdog_use & 0xf, 0xff);
    752        k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
    753        break;
    754
    755    case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
    756        sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
    757                                0xc3, ibs->watchdog_use & 0xf, 0xff);
    758        k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
    759        break;
    760    }
    761
    762 out:
    763    next_timeout(ibs);
    764}
    765
    766static void chassis_capabilities(IPMIBmcSim *ibs,
    767                                 uint8_t *cmd, unsigned int cmd_len,
    768                                 RspBuffer *rsp)
    769{
    770    rsp_buffer_push(rsp, 0);
    771    rsp_buffer_push(rsp, ibs->parent.slave_addr);
    772    rsp_buffer_push(rsp, ibs->parent.slave_addr);
    773    rsp_buffer_push(rsp, ibs->parent.slave_addr);
    774    rsp_buffer_push(rsp, ibs->parent.slave_addr);
    775}
    776
    777static void chassis_status(IPMIBmcSim *ibs,
    778                           uint8_t *cmd, unsigned int cmd_len,
    779                           RspBuffer *rsp)
    780{
    781    rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */
    782    rsp_buffer_push(rsp, 0);
    783    rsp_buffer_push(rsp, 0);
    784    rsp_buffer_push(rsp, 0);
    785}
    786
    787static void chassis_control(IPMIBmcSim *ibs,
    788                            uint8_t *cmd, unsigned int cmd_len,
    789                            RspBuffer *rsp)
    790{
    791    IPMIInterface *s = ibs->parent.intf;
    792    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
    793
    794    switch (cmd[2] & 0xf) {
    795    case 0: /* power down */
    796        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0));
    797        break;
    798    case 1: /* power up */
    799        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0));
    800        break;
    801    case 2: /* power cycle */
    802        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0));
    803        break;
    804    case 3: /* hard reset */
    805        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0));
    806        break;
    807    case 4: /* pulse diagnostic interrupt */
    808        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0));
    809        break;
    810    case 5: /* soft shutdown via ACPI by overtemp emulation */
    811        rsp_buffer_set_error(rsp, k->do_hw_op(s,
    812                                          IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0));
    813        break;
    814    default:
    815        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
    816        return;
    817    }
    818}
    819
    820static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
    821                           uint8_t *cmd, unsigned int cmd_len,
    822                           RspBuffer *rsp)
    823
    824{
    825    rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */
    826    rsp_buffer_push(rsp, 0);  /* Channel 0 */
    827}
    828
    829static void get_device_id(IPMIBmcSim *ibs,
    830                          uint8_t *cmd, unsigned int cmd_len,
    831                          RspBuffer *rsp)
    832{
    833    rsp_buffer_push(rsp, ibs->device_id);
    834    rsp_buffer_push(rsp, ibs->device_rev & 0xf);
    835    rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
    836    rsp_buffer_push(rsp, ibs->fwrev2);
    837    rsp_buffer_push(rsp, ibs->ipmi_version);
    838    rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */
    839    rsp_buffer_push(rsp, ibs->mfg_id & 0xff);
    840    rsp_buffer_push(rsp, (ibs->mfg_id >> 8) & 0xff);
    841    rsp_buffer_push(rsp, (ibs->mfg_id >> 16) & 0xff);
    842    rsp_buffer_push(rsp, ibs->product_id & 0xff);
    843    rsp_buffer_push(rsp, (ibs->product_id >> 8) & 0xff);
    844}
    845
    846static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
    847{
    848    IPMIInterface *s = ibs->parent.intf;
    849    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
    850    bool irqs_on;
    851
    852    ibs->bmc_global_enables = val;
    853
    854    irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
    855                     IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
    856
    857    k->set_irq_enable(s, irqs_on);
    858}
    859
    860static void cold_reset(IPMIBmcSim *ibs,
    861                       uint8_t *cmd, unsigned int cmd_len,
    862                       RspBuffer *rsp)
    863{
    864    IPMIInterface *s = ibs->parent.intf;
    865    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
    866
    867    /* Disable all interrupts */
    868    set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
    869
    870    if (k->reset) {
    871        k->reset(s, true);
    872    }
    873}
    874
    875static void warm_reset(IPMIBmcSim *ibs,
    876                       uint8_t *cmd, unsigned int cmd_len,
    877                       RspBuffer *rsp)
    878{
    879    IPMIInterface *s = ibs->parent.intf;
    880    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
    881
    882    if (k->reset) {
    883        k->reset(s, false);
    884    }
    885}
    886static void set_acpi_power_state(IPMIBmcSim *ibs,
    887                                 uint8_t *cmd, unsigned int cmd_len,
    888                                 RspBuffer *rsp)
    889{
    890    ibs->acpi_power_state[0] = cmd[2];
    891    ibs->acpi_power_state[1] = cmd[3];
    892}
    893
    894static void get_acpi_power_state(IPMIBmcSim *ibs,
    895                                 uint8_t *cmd, unsigned int cmd_len,
    896                                 RspBuffer *rsp)
    897{
    898    rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
    899    rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
    900}
    901
    902static void get_device_guid(IPMIBmcSim *ibs,
    903                            uint8_t *cmd, unsigned int cmd_len,
    904                            RspBuffer *rsp)
    905{
    906    unsigned int i;
    907
    908    /* An uninitialized uuid is all zeros, use that to know if it is set. */
    909    for (i = 0; i < 16; i++) {
    910        if (ibs->uuid.data[i]) {
    911            goto uuid_set;
    912        }
    913    }
    914    /* No uuid is set, return an error. */
    915    rsp_buffer_set_error(rsp, IPMI_CC_INVALID_CMD);
    916    return;
    917
    918 uuid_set:
    919    for (i = 0; i < 16; i++) {
    920        rsp_buffer_push(rsp, ibs->uuid.data[i]);
    921    }
    922}
    923
    924static void set_bmc_global_enables(IPMIBmcSim *ibs,
    925                                   uint8_t *cmd, unsigned int cmd_len,
    926                                   RspBuffer *rsp)
    927{
    928    set_global_enables(ibs, cmd[2]);
    929}
    930
    931static void get_bmc_global_enables(IPMIBmcSim *ibs,
    932                                   uint8_t *cmd, unsigned int cmd_len,
    933                                   RspBuffer *rsp)
    934{
    935    rsp_buffer_push(rsp, ibs->bmc_global_enables);
    936}
    937
    938static void clr_msg_flags(IPMIBmcSim *ibs,
    939                          uint8_t *cmd, unsigned int cmd_len,
    940                          RspBuffer *rsp)
    941{
    942    IPMIInterface *s = ibs->parent.intf;
    943    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
    944
    945    ibs->msg_flags &= ~cmd[2];
    946    k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
    947}
    948
    949static void get_msg_flags(IPMIBmcSim *ibs,
    950                          uint8_t *cmd, unsigned int cmd_len,
    951                          RspBuffer *rsp)
    952{
    953    rsp_buffer_push(rsp, ibs->msg_flags);
    954}
    955
    956static void read_evt_msg_buf(IPMIBmcSim *ibs,
    957                             uint8_t *cmd, unsigned int cmd_len,
    958                             RspBuffer *rsp)
    959{
    960    IPMIInterface *s = ibs->parent.intf;
    961    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
    962    unsigned int i;
    963
    964    if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
    965        rsp_buffer_set_error(rsp, 0x80);
    966        return;
    967    }
    968    for (i = 0; i < 16; i++) {
    969        rsp_buffer_push(rsp, ibs->evtbuf[i]);
    970    }
    971    ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
    972    k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
    973}
    974
    975static void get_msg(IPMIBmcSim *ibs,
    976                    uint8_t *cmd, unsigned int cmd_len,
    977                    RspBuffer *rsp)
    978{
    979    IPMIRcvBufEntry *msg;
    980
    981    if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
    982        rsp_buffer_set_error(rsp, 0x80); /* Queue empty */
    983        goto out;
    984    }
    985    rsp_buffer_push(rsp, 0); /* Channel 0 */
    986    msg = QTAILQ_FIRST(&ibs->rcvbufs);
    987    rsp_buffer_pushmore(rsp, msg->buf, msg->len);
    988    QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
    989    g_free(msg);
    990
    991    if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
    992        IPMIInterface *s = ibs->parent.intf;
    993        IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
    994
    995        ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
    996        k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
    997    }
    998
    999out:
   1000    return;
   1001}
   1002
   1003static unsigned char
   1004ipmb_checksum(unsigned char *data, int size, unsigned char csum)
   1005{
   1006    for (; size > 0; size--, data++) {
   1007            csum += *data;
   1008    }
   1009
   1010    return -csum;
   1011}
   1012
   1013static void send_msg(IPMIBmcSim *ibs,
   1014                     uint8_t *cmd, unsigned int cmd_len,
   1015                     RspBuffer *rsp)
   1016{
   1017    IPMIInterface *s = ibs->parent.intf;
   1018    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
   1019    IPMIRcvBufEntry *msg;
   1020    uint8_t *buf;
   1021    uint8_t netfn, rqLun, rsLun, rqSeq;
   1022
   1023    if (cmd[2] != 0) {
   1024        /* We only handle channel 0 with no options */
   1025        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1026        return;
   1027    }
   1028
   1029    if (cmd_len < 10) {
   1030        rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
   1031        return;
   1032    }
   1033
   1034    if (cmd[3] != 0x40) {
   1035        /* We only emulate a MC at address 0x40. */
   1036        rsp_buffer_set_error(rsp, 0x83); /* NAK on write */
   1037        return;
   1038    }
   1039
   1040    cmd += 3; /* Skip the header. */
   1041    cmd_len -= 3;
   1042
   1043    /*
   1044     * At this point we "send" the message successfully.  Any error will
   1045     * be returned in the response.
   1046     */
   1047    if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
   1048        cmd[3] != 0x20) { /* Improper response address */
   1049        return; /* No response */
   1050    }
   1051
   1052    netfn = cmd[1] >> 2;
   1053    rqLun = cmd[4] & 0x3;
   1054    rsLun = cmd[1] & 0x3;
   1055    rqSeq = cmd[4] >> 2;
   1056
   1057    if (rqLun != 2) {
   1058        /* We only support LUN 2 coming back to us. */
   1059        return;
   1060    }
   1061
   1062    msg = g_malloc(sizeof(*msg));
   1063    msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
   1064    msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
   1065    msg->buf[2] = cmd[0]; /* rsSA */
   1066    msg->buf[3] = (rqSeq << 2) | rsLun;
   1067    msg->buf[4] = cmd[5]; /* Cmd */
   1068    msg->buf[5] = 0; /* Completion Code */
   1069    msg->len = 6;
   1070
   1071    if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
   1072        /* Not a command we handle. */
   1073        msg->buf[5] = IPMI_CC_INVALID_CMD;
   1074        goto end_msg;
   1075    }
   1076
   1077    buf = msg->buf + msg->len; /* After the CC */
   1078    buf[0] = 0;
   1079    buf[1] = 0;
   1080    buf[2] = 0;
   1081    buf[3] = 0;
   1082    buf[4] = 0x51;
   1083    buf[5] = 0;
   1084    buf[6] = 0;
   1085    buf[7] = 0;
   1086    buf[8] = 0;
   1087    buf[9] = 0;
   1088    buf[10] = 0;
   1089    msg->len += 11;
   1090
   1091 end_msg:
   1092    msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
   1093    msg->len++;
   1094    QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
   1095    ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
   1096    k->set_atn(s, 1, attn_irq_enabled(ibs));
   1097}
   1098
   1099static void do_watchdog_reset(IPMIBmcSim *ibs)
   1100{
   1101    if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
   1102        IPMI_BMC_WATCHDOG_ACTION_NONE) {
   1103        ibs->watchdog_running = 0;
   1104        return;
   1105    }
   1106    ibs->watchdog_preaction_ran = 0;
   1107
   1108
   1109    /* Timeout is in tenths of a second, offset is in seconds */
   1110    ibs->watchdog_expiry = ipmi_getmonotime();
   1111    ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
   1112    if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
   1113        ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
   1114    }
   1115    ibs->watchdog_running = 1;
   1116}
   1117
   1118static void reset_watchdog_timer(IPMIBmcSim *ibs,
   1119                                 uint8_t *cmd, unsigned int cmd_len,
   1120                                 RspBuffer *rsp)
   1121{
   1122    if (!ibs->watchdog_initialized) {
   1123        rsp_buffer_set_error(rsp, 0x80);
   1124        return;
   1125    }
   1126    do_watchdog_reset(ibs);
   1127}
   1128
   1129static void set_watchdog_timer(IPMIBmcSim *ibs,
   1130                               uint8_t *cmd, unsigned int cmd_len,
   1131                               RspBuffer *rsp)
   1132{
   1133    IPMIInterface *s = ibs->parent.intf;
   1134    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
   1135    unsigned int val;
   1136
   1137    val = cmd[2] & 0x7; /* Validate use */
   1138    if (val == 0 || val > 5) {
   1139        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1140        return;
   1141    }
   1142    val = cmd[3] & 0x7; /* Validate action */
   1143    switch (val) {
   1144    case IPMI_BMC_WATCHDOG_ACTION_NONE:
   1145        break;
   1146
   1147    case IPMI_BMC_WATCHDOG_ACTION_RESET:
   1148        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1));
   1149        break;
   1150
   1151    case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
   1152        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1));
   1153        break;
   1154
   1155    case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
   1156        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1));
   1157        break;
   1158
   1159    default:
   1160        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1161    }
   1162    if (rsp->buffer[2]) {
   1163        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1164        return;
   1165    }
   1166
   1167    val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
   1168    switch (val) {
   1169    case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
   1170    case IPMI_BMC_WATCHDOG_PRE_NONE:
   1171        break;
   1172
   1173    case IPMI_BMC_WATCHDOG_PRE_NMI:
   1174        if (k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
   1175            /* NMI not supported. */
   1176            rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1177            return;
   1178        }
   1179        break;
   1180
   1181    default:
   1182        /* We don't support PRE_SMI */
   1183        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1184        return;
   1185    }
   1186
   1187    ibs->watchdog_initialized = 1;
   1188    ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
   1189    ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
   1190    ibs->watchdog_pretimeout = cmd[4];
   1191    ibs->watchdog_expired &= ~cmd[5];
   1192    ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
   1193    if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
   1194        do_watchdog_reset(ibs);
   1195    } else {
   1196        ibs->watchdog_running = 0;
   1197    }
   1198}
   1199
   1200static void get_watchdog_timer(IPMIBmcSim *ibs,
   1201                               uint8_t *cmd, unsigned int cmd_len,
   1202                               RspBuffer *rsp)
   1203{
   1204    rsp_buffer_push(rsp, ibs->watchdog_use);
   1205    rsp_buffer_push(rsp, ibs->watchdog_action);
   1206    rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
   1207    rsp_buffer_push(rsp, ibs->watchdog_expired);
   1208    rsp_buffer_push(rsp, ibs->watchdog_timeout & 0xff);
   1209    rsp_buffer_push(rsp, (ibs->watchdog_timeout >> 8) & 0xff);
   1210    if (ibs->watchdog_running) {
   1211        long timeout;
   1212        timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
   1213                   / 100000000);
   1214        rsp_buffer_push(rsp, timeout & 0xff);
   1215        rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
   1216    } else {
   1217        rsp_buffer_push(rsp, 0);
   1218        rsp_buffer_push(rsp, 0);
   1219    }
   1220}
   1221
   1222static void get_sdr_rep_info(IPMIBmcSim *ibs,
   1223                             uint8_t *cmd, unsigned int cmd_len,
   1224                             RspBuffer *rsp)
   1225{
   1226    unsigned int i;
   1227
   1228    rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */
   1229    rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
   1230    rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
   1231    rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
   1232    rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
   1233    for (i = 0; i < 4; i++) {
   1234        rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
   1235    }
   1236    for (i = 0; i < 4; i++) {
   1237        rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
   1238    }
   1239    /* Only modal support, reserve supported */
   1240    rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
   1241}
   1242
   1243static void reserve_sdr_rep(IPMIBmcSim *ibs,
   1244                            uint8_t *cmd, unsigned int cmd_len,
   1245                            RspBuffer *rsp)
   1246{
   1247    rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
   1248    rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
   1249}
   1250
   1251static void get_sdr(IPMIBmcSim *ibs,
   1252                    uint8_t *cmd, unsigned int cmd_len,
   1253                    RspBuffer *rsp)
   1254{
   1255    unsigned int pos;
   1256    uint16_t nextrec;
   1257    struct ipmi_sdr_header *sdrh;
   1258
   1259    if (cmd[6]) {
   1260        if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
   1261            rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
   1262            return;
   1263        }
   1264    }
   1265
   1266    pos = 0;
   1267    if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
   1268                       &pos, &nextrec)) {
   1269        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
   1270        return;
   1271    }
   1272
   1273    sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
   1274
   1275    if (cmd[6] > ipmi_sdr_length(sdrh)) {
   1276        rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE);
   1277        return;
   1278    }
   1279
   1280    rsp_buffer_push(rsp, nextrec & 0xff);
   1281    rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
   1282
   1283    if (cmd[7] == 0xff) {
   1284        cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
   1285    }
   1286
   1287    if ((cmd[7] + rsp->len) > sizeof(rsp->buffer)) {
   1288        rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES);
   1289        return;
   1290    }
   1291
   1292    rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
   1293}
   1294
   1295static void add_sdr(IPMIBmcSim *ibs,
   1296                    uint8_t *cmd, unsigned int cmd_len,
   1297                    RspBuffer *rsp)
   1298{
   1299    uint16_t recid;
   1300    struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
   1301
   1302    if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
   1303        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1304        return;
   1305    }
   1306    rsp_buffer_push(rsp, recid & 0xff);
   1307    rsp_buffer_push(rsp, (recid >> 8) & 0xff);
   1308}
   1309
   1310static void clear_sdr_rep(IPMIBmcSim *ibs,
   1311                          uint8_t *cmd, unsigned int cmd_len,
   1312                          RspBuffer *rsp)
   1313{
   1314    if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
   1315        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
   1316        return;
   1317    }
   1318
   1319    if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
   1320        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1321        return;
   1322    }
   1323    if (cmd[7] == 0xaa) {
   1324        ibs->sdr.next_free = 0;
   1325        ibs->sdr.overflow = 0;
   1326        set_timestamp(ibs, ibs->sdr.last_clear);
   1327        rsp_buffer_push(rsp, 1); /* Erasure complete */
   1328        sdr_inc_reservation(&ibs->sdr);
   1329    } else if (cmd[7] == 0) {
   1330        rsp_buffer_push(rsp, 1); /* Erasure complete */
   1331    } else {
   1332        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1333        return;
   1334    }
   1335}
   1336
   1337static void get_sel_info(IPMIBmcSim *ibs,
   1338                         uint8_t *cmd, unsigned int cmd_len,
   1339                         RspBuffer *rsp)
   1340{
   1341    unsigned int i, val;
   1342
   1343    rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */
   1344    rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
   1345    rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
   1346    val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
   1347    rsp_buffer_push(rsp, val & 0xff);
   1348    rsp_buffer_push(rsp, (val >> 8) & 0xff);
   1349    for (i = 0; i < 4; i++) {
   1350        rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
   1351    }
   1352    for (i = 0; i < 4; i++) {
   1353        rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
   1354    }
   1355    /* Only support Reserve SEL */
   1356    rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
   1357}
   1358
   1359static void get_fru_area_info(IPMIBmcSim *ibs,
   1360                         uint8_t *cmd, unsigned int cmd_len,
   1361                         RspBuffer *rsp)
   1362{
   1363    uint8_t fruid;
   1364    uint16_t fru_entry_size;
   1365
   1366    fruid = cmd[2];
   1367
   1368    if (fruid >= ibs->fru.nentries) {
   1369        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1370        return;
   1371    }
   1372
   1373    fru_entry_size = ibs->fru.areasize;
   1374
   1375    rsp_buffer_push(rsp, fru_entry_size & 0xff);
   1376    rsp_buffer_push(rsp, fru_entry_size >> 8 & 0xff);
   1377    rsp_buffer_push(rsp, 0x0);
   1378}
   1379
   1380static void read_fru_data(IPMIBmcSim *ibs,
   1381                         uint8_t *cmd, unsigned int cmd_len,
   1382                         RspBuffer *rsp)
   1383{
   1384    uint8_t fruid;
   1385    uint16_t offset;
   1386    int i;
   1387    uint8_t *fru_entry;
   1388    unsigned int count;
   1389
   1390    fruid = cmd[2];
   1391    offset = (cmd[3] | cmd[4] << 8);
   1392
   1393    if (fruid >= ibs->fru.nentries) {
   1394        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1395        return;
   1396    }
   1397
   1398    if (offset >= ibs->fru.areasize - 1) {
   1399        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1400        return;
   1401    }
   1402
   1403    fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
   1404
   1405    count = MIN(cmd[5], ibs->fru.areasize - offset);
   1406
   1407    rsp_buffer_push(rsp, count & 0xff);
   1408    for (i = 0; i < count; i++) {
   1409        rsp_buffer_push(rsp, fru_entry[offset + i]);
   1410    }
   1411}
   1412
   1413static void write_fru_data(IPMIBmcSim *ibs,
   1414                         uint8_t *cmd, unsigned int cmd_len,
   1415                         RspBuffer *rsp)
   1416{
   1417    uint8_t fruid;
   1418    uint16_t offset;
   1419    uint8_t *fru_entry;
   1420    unsigned int count;
   1421
   1422    fruid = cmd[2];
   1423    offset = (cmd[3] | cmd[4] << 8);
   1424
   1425    if (fruid >= ibs->fru.nentries) {
   1426        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1427        return;
   1428    }
   1429
   1430    if (offset >= ibs->fru.areasize - 1) {
   1431        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1432        return;
   1433    }
   1434
   1435    fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
   1436
   1437    count = MIN(cmd_len - 5, ibs->fru.areasize - offset);
   1438
   1439    memcpy(fru_entry + offset, cmd + 5, count);
   1440
   1441    rsp_buffer_push(rsp, count & 0xff);
   1442}
   1443
   1444static void reserve_sel(IPMIBmcSim *ibs,
   1445                        uint8_t *cmd, unsigned int cmd_len,
   1446                        RspBuffer *rsp)
   1447{
   1448    rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
   1449    rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
   1450}
   1451
   1452static void get_sel_entry(IPMIBmcSim *ibs,
   1453                          uint8_t *cmd, unsigned int cmd_len,
   1454                          RspBuffer *rsp)
   1455{
   1456    unsigned int val;
   1457
   1458    if (cmd[6]) {
   1459        if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
   1460            rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
   1461            return;
   1462        }
   1463    }
   1464    if (ibs->sel.next_free == 0) {
   1465        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
   1466        return;
   1467    }
   1468    if (cmd[6] > 15) {
   1469        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1470        return;
   1471    }
   1472    if (cmd[7] == 0xff) {
   1473        cmd[7] = 16;
   1474    } else if ((cmd[7] + cmd[6]) > 16) {
   1475        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1476        return;
   1477    } else {
   1478        cmd[7] += cmd[6];
   1479    }
   1480
   1481    val = cmd[4] | (cmd[5] << 8);
   1482    if (val == 0xffff) {
   1483        val = ibs->sel.next_free - 1;
   1484    } else if (val >= ibs->sel.next_free) {
   1485        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
   1486        return;
   1487    }
   1488    if ((val + 1) == ibs->sel.next_free) {
   1489        rsp_buffer_push(rsp, 0xff);
   1490        rsp_buffer_push(rsp, 0xff);
   1491    } else {
   1492        rsp_buffer_push(rsp, (val + 1) & 0xff);
   1493        rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
   1494    }
   1495    for (; cmd[6] < cmd[7]; cmd[6]++) {
   1496        rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
   1497    }
   1498}
   1499
   1500static void add_sel_entry(IPMIBmcSim *ibs,
   1501                          uint8_t *cmd, unsigned int cmd_len,
   1502                          RspBuffer *rsp)
   1503{
   1504    if (sel_add_event(ibs, cmd + 2)) {
   1505        rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
   1506        return;
   1507    }
   1508    /* sel_add_event fills in the record number. */
   1509    rsp_buffer_push(rsp, cmd[2]);
   1510    rsp_buffer_push(rsp, cmd[3]);
   1511}
   1512
   1513static void clear_sel(IPMIBmcSim *ibs,
   1514                      uint8_t *cmd, unsigned int cmd_len,
   1515                      RspBuffer *rsp)
   1516{
   1517    if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
   1518        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
   1519        return;
   1520    }
   1521
   1522    if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
   1523        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1524        return;
   1525    }
   1526    if (cmd[7] == 0xaa) {
   1527        ibs->sel.next_free = 0;
   1528        ibs->sel.overflow = 0;
   1529        set_timestamp(ibs, ibs->sdr.last_clear);
   1530        rsp_buffer_push(rsp, 1); /* Erasure complete */
   1531        sel_inc_reservation(&ibs->sel);
   1532    } else if (cmd[7] == 0) {
   1533        rsp_buffer_push(rsp, 1); /* Erasure complete */
   1534    } else {
   1535        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1536        return;
   1537    }
   1538}
   1539
   1540static void get_sel_time(IPMIBmcSim *ibs,
   1541                         uint8_t *cmd, unsigned int cmd_len,
   1542                         RspBuffer *rsp)
   1543{
   1544    uint32_t val;
   1545    struct ipmi_time now;
   1546
   1547    ipmi_gettime(&now);
   1548    val = now.tv_sec + ibs->sel.time_offset;
   1549    rsp_buffer_push(rsp, val & 0xff);
   1550    rsp_buffer_push(rsp, (val >> 8) & 0xff);
   1551    rsp_buffer_push(rsp, (val >> 16) & 0xff);
   1552    rsp_buffer_push(rsp, (val >> 24) & 0xff);
   1553}
   1554
   1555static void set_sel_time(IPMIBmcSim *ibs,
   1556                         uint8_t *cmd, unsigned int cmd_len,
   1557                         RspBuffer *rsp)
   1558{
   1559    uint32_t val;
   1560    struct ipmi_time now;
   1561
   1562    val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
   1563    ipmi_gettime(&now);
   1564    ibs->sel.time_offset = now.tv_sec - ((long) val);
   1565}
   1566
   1567static void platform_event_msg(IPMIBmcSim *ibs,
   1568                               uint8_t *cmd, unsigned int cmd_len,
   1569                               RspBuffer *rsp)
   1570{
   1571    uint8_t event[16];
   1572
   1573    event[2] = 2; /* System event record */
   1574    event[7] = cmd[2]; /* Generator ID */
   1575    event[8] = 0;
   1576    event[9] = cmd[3]; /* EvMRev */
   1577    event[10] = cmd[4]; /* Sensor type */
   1578    event[11] = cmd[5]; /* Sensor number */
   1579    event[12] = cmd[6]; /* Event dir / Event type */
   1580    event[13] = cmd[7]; /* Event data 1 */
   1581    event[14] = cmd[8]; /* Event data 2 */
   1582    event[15] = cmd[9]; /* Event data 3 */
   1583
   1584    if (sel_add_event(ibs, event)) {
   1585        rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
   1586    }
   1587}
   1588
   1589static void set_sensor_evt_enable(IPMIBmcSim *ibs,
   1590                                  uint8_t *cmd, unsigned int cmd_len,
   1591                                  RspBuffer *rsp)
   1592{
   1593    IPMISensor *sens;
   1594
   1595    if ((cmd[2] >= MAX_SENSORS) ||
   1596            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
   1597        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
   1598        return;
   1599    }
   1600    sens = ibs->sensors + cmd[2];
   1601    switch ((cmd[3] >> 4) & 0x3) {
   1602    case 0: /* Do not change */
   1603        break;
   1604    case 1: /* Enable bits */
   1605        if (cmd_len > 4) {
   1606            sens->assert_enable |= cmd[4];
   1607        }
   1608        if (cmd_len > 5) {
   1609            sens->assert_enable |= cmd[5] << 8;
   1610        }
   1611        if (cmd_len > 6) {
   1612            sens->deassert_enable |= cmd[6];
   1613        }
   1614        if (cmd_len > 7) {
   1615            sens->deassert_enable |= cmd[7] << 8;
   1616        }
   1617        break;
   1618    case 2: /* Disable bits */
   1619        if (cmd_len > 4) {
   1620            sens->assert_enable &= ~cmd[4];
   1621        }
   1622        if (cmd_len > 5) {
   1623            sens->assert_enable &= ~(cmd[5] << 8);
   1624        }
   1625        if (cmd_len > 6) {
   1626            sens->deassert_enable &= ~cmd[6];
   1627        }
   1628        if (cmd_len > 7) {
   1629            sens->deassert_enable &= ~(cmd[7] << 8);
   1630        }
   1631        break;
   1632    case 3:
   1633        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1634        return;
   1635    }
   1636    IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
   1637}
   1638
   1639static void get_sensor_evt_enable(IPMIBmcSim *ibs,
   1640                                  uint8_t *cmd, unsigned int cmd_len,
   1641                                  RspBuffer *rsp)
   1642{
   1643    IPMISensor *sens;
   1644
   1645    if ((cmd[2] >= MAX_SENSORS) ||
   1646        !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
   1647        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
   1648        return;
   1649    }
   1650    sens = ibs->sensors + cmd[2];
   1651    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
   1652    rsp_buffer_push(rsp, sens->assert_enable & 0xff);
   1653    rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
   1654    rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
   1655    rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
   1656}
   1657
   1658static void rearm_sensor_evts(IPMIBmcSim *ibs,
   1659                              uint8_t *cmd, unsigned int cmd_len,
   1660                              RspBuffer *rsp)
   1661{
   1662    IPMISensor *sens;
   1663
   1664    if ((cmd[2] >= MAX_SENSORS) ||
   1665        !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
   1666        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
   1667        return;
   1668    }
   1669    sens = ibs->sensors + cmd[2];
   1670
   1671    if ((cmd[3] & 0x80) == 0) {
   1672        /* Just clear everything */
   1673        sens->states = 0;
   1674        return;
   1675    }
   1676}
   1677
   1678static void get_sensor_evt_status(IPMIBmcSim *ibs,
   1679                                  uint8_t *cmd, unsigned int cmd_len,
   1680                                  RspBuffer *rsp)
   1681{
   1682    IPMISensor *sens;
   1683
   1684    if ((cmd[2] >= MAX_SENSORS) ||
   1685        !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
   1686        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
   1687        return;
   1688    }
   1689    sens = ibs->sensors + cmd[2];
   1690    rsp_buffer_push(rsp, sens->reading);
   1691    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
   1692    rsp_buffer_push(rsp, sens->assert_states & 0xff);
   1693    rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
   1694    rsp_buffer_push(rsp, sens->deassert_states & 0xff);
   1695    rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
   1696}
   1697
   1698static void get_sensor_reading(IPMIBmcSim *ibs,
   1699                               uint8_t *cmd, unsigned int cmd_len,
   1700                               RspBuffer *rsp)
   1701{
   1702    IPMISensor *sens;
   1703
   1704    if ((cmd[2] >= MAX_SENSORS) ||
   1705            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
   1706        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
   1707        return;
   1708    }
   1709    sens = ibs->sensors + cmd[2];
   1710    rsp_buffer_push(rsp, sens->reading);
   1711    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
   1712    rsp_buffer_push(rsp, sens->states & 0xff);
   1713    if (IPMI_SENSOR_IS_DISCRETE(sens)) {
   1714        rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
   1715    }
   1716}
   1717
   1718static void set_sensor_type(IPMIBmcSim *ibs,
   1719                            uint8_t *cmd, unsigned int cmd_len,
   1720                            RspBuffer *rsp)
   1721{
   1722    IPMISensor *sens;
   1723
   1724
   1725    if ((cmd[2] >= MAX_SENSORS) ||
   1726            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
   1727        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
   1728        return;
   1729    }
   1730    sens = ibs->sensors + cmd[2];
   1731    sens->sensor_type = cmd[3];
   1732    sens->evt_reading_type_code = cmd[4] & 0x7f;
   1733}
   1734
   1735static void get_sensor_type(IPMIBmcSim *ibs,
   1736                            uint8_t *cmd, unsigned int cmd_len,
   1737                            RspBuffer *rsp)
   1738{
   1739    IPMISensor *sens;
   1740
   1741
   1742    if ((cmd[2] >= MAX_SENSORS) ||
   1743            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
   1744        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
   1745        return;
   1746    }
   1747    sens = ibs->sensors + cmd[2];
   1748    rsp_buffer_push(rsp, sens->sensor_type);
   1749    rsp_buffer_push(rsp, sens->evt_reading_type_code);
   1750}
   1751
   1752/*
   1753 * bytes   parameter
   1754 *    1    sensor number
   1755 *    2    operation (see below for bits meaning)
   1756 *    3    sensor reading
   1757 *  4:5    assertion states (optional)
   1758 *  6:7    deassertion states (optional)
   1759 *  8:10   event data 1,2,3 (optional)
   1760 */
   1761static void set_sensor_reading(IPMIBmcSim *ibs,
   1762                               uint8_t *cmd, unsigned int cmd_len,
   1763                               RspBuffer *rsp)
   1764{
   1765    IPMISensor *sens;
   1766    uint8_t evd1 = 0;
   1767    uint8_t evd2 = 0;
   1768    uint8_t evd3 = 0;
   1769    uint8_t new_reading = 0;
   1770    uint16_t new_assert_states = 0;
   1771    uint16_t new_deassert_states = 0;
   1772    bool change_reading = false;
   1773    bool change_assert = false;
   1774    bool change_deassert = false;
   1775    enum {
   1776        SENSOR_GEN_EVENT_NONE,
   1777        SENSOR_GEN_EVENT_DATA,
   1778        SENSOR_GEN_EVENT_BMC,
   1779    } do_gen_event = SENSOR_GEN_EVENT_NONE;
   1780
   1781    if ((cmd[2] >= MAX_SENSORS) ||
   1782            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
   1783        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
   1784        return;
   1785    }
   1786
   1787    sens = ibs->sensors + cmd[2];
   1788
   1789    /* [1:0] Sensor Reading operation */
   1790    switch ((cmd[3]) & 0x3) {
   1791    case 0: /* Do not change */
   1792        break;
   1793    case 1: /* write given value to sensor reading byte */
   1794        new_reading = cmd[4];
   1795        if (sens->reading != new_reading) {
   1796            change_reading = true;
   1797        }
   1798        break;
   1799    case 2:
   1800    case 3:
   1801        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1802        return;
   1803    }
   1804
   1805    /* [3:2] Deassertion bits operation */
   1806    switch ((cmd[3] >> 2) & 0x3) {
   1807    case 0: /* Do not change */
   1808        break;
   1809    case 1: /* write given value */
   1810        if (cmd_len > 7) {
   1811            new_deassert_states = cmd[7];
   1812            change_deassert = true;
   1813        }
   1814        if (cmd_len > 8) {
   1815            new_deassert_states |= (cmd[8] << 8);
   1816        }
   1817        break;
   1818
   1819    case 2: /* mask on */
   1820        if (cmd_len > 7) {
   1821            new_deassert_states = (sens->deassert_states | cmd[7]);
   1822            change_deassert = true;
   1823        }
   1824        if (cmd_len > 8) {
   1825            new_deassert_states |= (sens->deassert_states | (cmd[8] << 8));
   1826        }
   1827        break;
   1828
   1829    case 3: /* mask off */
   1830        if (cmd_len > 7) {
   1831            new_deassert_states = (sens->deassert_states & cmd[7]);
   1832            change_deassert = true;
   1833        }
   1834        if (cmd_len > 8) {
   1835            new_deassert_states |= (sens->deassert_states & (cmd[8] << 8));
   1836        }
   1837        break;
   1838    }
   1839
   1840    if (change_deassert && (new_deassert_states == sens->deassert_states)) {
   1841        change_deassert = false;
   1842    }
   1843
   1844    /* [5:4] Assertion bits operation */
   1845    switch ((cmd[3] >> 4) & 0x3) {
   1846    case 0: /* Do not change */
   1847        break;
   1848    case 1: /* write given value */
   1849        if (cmd_len > 5) {
   1850            new_assert_states = cmd[5];
   1851            change_assert = true;
   1852        }
   1853        if (cmd_len > 6) {
   1854            new_assert_states |= (cmd[6] << 8);
   1855        }
   1856        break;
   1857
   1858    case 2: /* mask on */
   1859        if (cmd_len > 5) {
   1860            new_assert_states = (sens->assert_states | cmd[5]);
   1861            change_assert = true;
   1862        }
   1863        if (cmd_len > 6) {
   1864            new_assert_states |= (sens->assert_states | (cmd[6] << 8));
   1865        }
   1866        break;
   1867
   1868    case 3: /* mask off */
   1869        if (cmd_len > 5) {
   1870            new_assert_states = (sens->assert_states & cmd[5]);
   1871            change_assert = true;
   1872        }
   1873        if (cmd_len > 6) {
   1874            new_assert_states |= (sens->assert_states & (cmd[6] << 8));
   1875        }
   1876        break;
   1877    }
   1878
   1879    if (change_assert && (new_assert_states == sens->assert_states)) {
   1880        change_assert = false;
   1881    }
   1882
   1883    if (cmd_len > 9) {
   1884        evd1 = cmd[9];
   1885    }
   1886    if (cmd_len > 10) {
   1887        evd2 = cmd[10];
   1888    }
   1889    if (cmd_len > 11) {
   1890        evd3 = cmd[11];
   1891    }
   1892
   1893    /* [7:6] Event Data Bytes operation */
   1894    switch ((cmd[3] >> 6) & 0x3) {
   1895    case 0: /*
   1896             * Don’t use Event Data bytes from this command. BMC will
   1897             * generate it's own Event Data bytes based on its sensor
   1898             * implementation.
   1899             */
   1900        evd1 = evd2 = evd3 = 0x0;
   1901        do_gen_event = SENSOR_GEN_EVENT_BMC;
   1902        break;
   1903    case 1: /*
   1904             * Write given values to event data bytes including bits
   1905             * [3:0] Event Data 1.
   1906             */
   1907        do_gen_event = SENSOR_GEN_EVENT_DATA;
   1908        break;
   1909    case 2: /*
   1910             * Write given values to event data bytes excluding bits
   1911             * [3:0] Event Data 1.
   1912             */
   1913        evd1 &= 0xf0;
   1914        do_gen_event = SENSOR_GEN_EVENT_DATA;
   1915        break;
   1916    case 3:
   1917        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1918        return;
   1919    }
   1920
   1921    /*
   1922     * Event Data Bytes operation and parameter are inconsistent. The
   1923     * Specs are not clear on that topic but generating an error seems
   1924     * correct.
   1925     */
   1926    if (do_gen_event == SENSOR_GEN_EVENT_DATA && cmd_len < 10) {
   1927        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
   1928        return;
   1929    }
   1930
   1931    /* commit values */
   1932    if (change_reading) {
   1933        sens->reading = new_reading;
   1934    }
   1935
   1936    if (change_assert) {
   1937        sens->assert_states = new_assert_states;
   1938    }
   1939
   1940    if (change_deassert) {
   1941        sens->deassert_states = new_deassert_states;
   1942    }
   1943
   1944    /* TODO: handle threshold sensor */
   1945    if (!IPMI_SENSOR_IS_DISCRETE(sens)) {
   1946        return;
   1947    }
   1948
   1949    switch (do_gen_event) {
   1950    case SENSOR_GEN_EVENT_DATA: {
   1951        unsigned int bit = evd1 & 0xf;
   1952        uint16_t mask = (1 << bit);
   1953
   1954        if (sens->assert_states & mask & sens->assert_enable) {
   1955            gen_event(ibs, cmd[2], 0, evd1, evd2, evd3);
   1956        }
   1957
   1958        if (sens->deassert_states & mask & sens->deassert_enable) {
   1959            gen_event(ibs, cmd[2], 1, evd1, evd2, evd3);
   1960        }
   1961        break;
   1962    }
   1963    case SENSOR_GEN_EVENT_BMC:
   1964        /*
   1965         * TODO: generate event and event data bytes depending on the
   1966         * sensor
   1967         */
   1968        break;
   1969    case SENSOR_GEN_EVENT_NONE:
   1970        break;
   1971    }
   1972}
   1973
   1974static const IPMICmdHandler chassis_cmds[] = {
   1975    [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
   1976    [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
   1977    [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
   1978    [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
   1979};
   1980static const IPMINetfn chassis_netfn = {
   1981    .cmd_nums = ARRAY_SIZE(chassis_cmds),
   1982    .cmd_handlers = chassis_cmds
   1983};
   1984
   1985static const IPMICmdHandler sensor_event_cmds[] = {
   1986    [IPMI_CMD_PLATFORM_EVENT_MSG] = { platform_event_msg, 10 },
   1987    [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
   1988    [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
   1989    [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
   1990    [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
   1991    [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
   1992    [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
   1993    [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
   1994    [IPMI_CMD_SET_SENSOR_READING] = { set_sensor_reading, 5 },
   1995};
   1996static const IPMINetfn sensor_event_netfn = {
   1997    .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
   1998    .cmd_handlers = sensor_event_cmds
   1999};
   2000
   2001static const IPMICmdHandler app_cmds[] = {
   2002    [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
   2003    [IPMI_CMD_COLD_RESET] = { cold_reset },
   2004    [IPMI_CMD_WARM_RESET] = { warm_reset },
   2005    [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
   2006    [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
   2007    [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
   2008    [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
   2009    [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
   2010    [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
   2011    [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
   2012    [IPMI_CMD_GET_MSG] = { get_msg },
   2013    [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
   2014    [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
   2015    [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
   2016    [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
   2017    [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
   2018};
   2019static const IPMINetfn app_netfn = {
   2020    .cmd_nums = ARRAY_SIZE(app_cmds),
   2021    .cmd_handlers = app_cmds
   2022};
   2023
   2024static const IPMICmdHandler storage_cmds[] = {
   2025    [IPMI_CMD_GET_FRU_AREA_INFO] = { get_fru_area_info, 3 },
   2026    [IPMI_CMD_READ_FRU_DATA] = { read_fru_data, 5 },
   2027    [IPMI_CMD_WRITE_FRU_DATA] = { write_fru_data, 5 },
   2028    [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
   2029    [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
   2030    [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
   2031    [IPMI_CMD_ADD_SDR] = { add_sdr },
   2032    [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
   2033    [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
   2034    [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
   2035    [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
   2036    [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
   2037    [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
   2038    [IPMI_CMD_GET_SEL_TIME] = { get_sel_time },
   2039    [IPMI_CMD_SET_SEL_TIME] = { set_sel_time, 6 },
   2040};
   2041
   2042static const IPMINetfn storage_netfn = {
   2043    .cmd_nums = ARRAY_SIZE(storage_cmds),
   2044    .cmd_handlers = storage_cmds
   2045};
   2046
   2047static void register_cmds(IPMIBmcSim *s)
   2048{
   2049    ipmi_sim_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
   2050    ipmi_sim_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
   2051    ipmi_sim_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
   2052    ipmi_sim_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
   2053}
   2054
   2055static uint8_t init_sdrs[] = {
   2056    /* Watchdog device */
   2057    0x00, 0x00, 0x51, 0x02,   35, 0x20, 0x00, 0x00,
   2058    0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
   2059    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   2060    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
   2061    'W',  'a',  't',  'c',  'h',  'd',  'o',  'g',
   2062};
   2063
   2064static void ipmi_sdr_init(IPMIBmcSim *ibs)
   2065{
   2066    unsigned int i;
   2067    int len;
   2068    size_t sdrs_size;
   2069    uint8_t *sdrs;
   2070
   2071    sdrs_size = sizeof(init_sdrs);
   2072    sdrs = init_sdrs;
   2073    if (ibs->sdr_filename &&
   2074        !g_file_get_contents(ibs->sdr_filename, (gchar **) &sdrs, &sdrs_size,
   2075                             NULL)) {
   2076        error_report("failed to load sdr file '%s'", ibs->sdr_filename);
   2077        sdrs_size = sizeof(init_sdrs);
   2078        sdrs = init_sdrs;
   2079    }
   2080
   2081    for (i = 0; i < sdrs_size; i += len) {
   2082        struct ipmi_sdr_header *sdrh;
   2083
   2084        if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
   2085            error_report("Problem with recid 0x%4.4x", i);
   2086            break;
   2087        }
   2088        sdrh = (struct ipmi_sdr_header *) &sdrs[i];
   2089        len = ipmi_sdr_length(sdrh);
   2090        if (i + len > sdrs_size) {
   2091            error_report("Problem with recid 0x%4.4x", i);
   2092            break;
   2093        }
   2094        sdr_add_entry(ibs, sdrh, len, NULL);
   2095    }
   2096
   2097    if (sdrs != init_sdrs) {
   2098        g_free(sdrs);
   2099    }
   2100}
   2101
   2102static const VMStateDescription vmstate_ipmi_sim = {
   2103    .name = TYPE_IPMI_BMC_SIMULATOR,
   2104    .version_id = 1,
   2105    .minimum_version_id = 1,
   2106    .fields      = (VMStateField[]) {
   2107        VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
   2108        VMSTATE_UINT8(msg_flags, IPMIBmcSim),
   2109        VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
   2110        VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
   2111        VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
   2112        VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
   2113        VMSTATE_UINT8(watchdog_expired, IPMIBmcSim),
   2114        VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
   2115        VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
   2116        VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
   2117        VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
   2118        VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
   2119        VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
   2120        VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
   2121        VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
   2122        VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
   2123        VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
   2124                       IPMIBmcSim),
   2125        VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
   2126        VMSTATE_END_OF_LIST()
   2127    }
   2128};
   2129
   2130static void ipmi_fru_init(IPMIFru *fru)
   2131{
   2132    int fsize;
   2133    int size = 0;
   2134
   2135    if (!fru->filename) {
   2136        goto out;
   2137    }
   2138
   2139    fsize = get_image_size(fru->filename);
   2140    if (fsize > 0) {
   2141        size = QEMU_ALIGN_UP(fsize, fru->areasize);
   2142        fru->data = g_malloc0(size);
   2143        if (load_image_size(fru->filename, fru->data, fsize) != fsize) {
   2144            error_report("Could not load file '%s'", fru->filename);
   2145            g_free(fru->data);
   2146            fru->data = NULL;
   2147        }
   2148    }
   2149
   2150out:
   2151    if (!fru->data) {
   2152        /* give one default FRU */
   2153        size = fru->areasize;
   2154        fru->data = g_malloc0(size);
   2155    }
   2156
   2157    fru->nentries = size / fru->areasize;
   2158}
   2159
   2160static void ipmi_sim_realize(DeviceState *dev, Error **errp)
   2161{
   2162    IPMIBmc *b = IPMI_BMC(dev);
   2163    unsigned int i;
   2164    IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
   2165
   2166    QTAILQ_INIT(&ibs->rcvbufs);
   2167
   2168    ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
   2169    ibs->device_id = 0x20;
   2170    ibs->ipmi_version = 0x02; /* IPMI 2.0 */
   2171    ibs->restart_cause = 0;
   2172    for (i = 0; i < 4; i++) {
   2173        ibs->sel.last_addition[i] = 0xff;
   2174        ibs->sel.last_clear[i] = 0xff;
   2175        ibs->sdr.last_addition[i] = 0xff;
   2176        ibs->sdr.last_clear[i] = 0xff;
   2177    }
   2178
   2179    ipmi_sdr_init(ibs);
   2180
   2181    ipmi_fru_init(&ibs->fru);
   2182
   2183    ibs->acpi_power_state[0] = 0;
   2184    ibs->acpi_power_state[1] = 0;
   2185
   2186    ipmi_init_sensors_from_sdrs(ibs);
   2187    register_cmds(ibs);
   2188
   2189    ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
   2190
   2191    vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
   2192}
   2193
   2194static Property ipmi_sim_properties[] = {
   2195    DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim, fru.areasize, 1024),
   2196    DEFINE_PROP_STRING("frudatafile", IPMIBmcSim, fru.filename),
   2197    DEFINE_PROP_STRING("sdrfile", IPMIBmcSim, sdr_filename),
   2198    DEFINE_PROP_UINT8("device_id", IPMIBmcSim, device_id, 0x20),
   2199    DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim, ipmi_version, 0x02),
   2200    DEFINE_PROP_UINT8("device_rev", IPMIBmcSim, device_rev, 0),
   2201    DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim, fwrev1, 0),
   2202    DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim, fwrev2, 0),
   2203    DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim, mfg_id, 0),
   2204    DEFINE_PROP_UINT16("product_id", IPMIBmcSim, product_id, 0),
   2205    DEFINE_PROP_UUID_NODEFAULT("guid", IPMIBmcSim, uuid),
   2206    DEFINE_PROP_END_OF_LIST(),
   2207};
   2208
   2209static void ipmi_sim_class_init(ObjectClass *oc, void *data)
   2210{
   2211    DeviceClass *dc = DEVICE_CLASS(oc);
   2212    IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
   2213
   2214    dc->hotpluggable = false;
   2215    dc->realize = ipmi_sim_realize;
   2216    device_class_set_props(dc, ipmi_sim_properties);
   2217    bk->handle_command = ipmi_sim_handle_command;
   2218}
   2219
   2220static const TypeInfo ipmi_sim_type = {
   2221    .name          = TYPE_IPMI_BMC_SIMULATOR,
   2222    .parent        = TYPE_IPMI_BMC,
   2223    .instance_size = sizeof(IPMIBmcSim),
   2224    .class_init    = ipmi_sim_class_init,
   2225};
   2226
   2227static void ipmi_sim_register_types(void)
   2228{
   2229    type_register_static(&ipmi_sim_type);
   2230}
   2231
   2232type_init(ipmi_sim_register_types)