qemu/hw/ipmi/ipmi_bmc_sim.c
<<
>>
Prefs
   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)
2233