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