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