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