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