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