qemu

Форк
0
/
ipmi_bmc_sim.c 
2232 строки · 67.1 Кб
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 "hw/qdev-properties-system.h"
34
#include "migration/vmstate.h"
35

36
#define IPMI_NETFN_CHASSIS            0x00
37

38
#define IPMI_CMD_GET_CHASSIS_CAPABILITIES 0x00
39
#define IPMI_CMD_GET_CHASSIS_STATUS       0x01
40
#define IPMI_CMD_CHASSIS_CONTROL          0x02
41
#define IPMI_CMD_GET_SYS_RESTART_CAUSE    0x09
42

43
#define IPMI_NETFN_SENSOR_EVENT       0x04
44

45
#define IPMI_CMD_PLATFORM_EVENT_MSG       0x02
46
#define IPMI_CMD_SET_SENSOR_EVT_ENABLE    0x28
47
#define IPMI_CMD_GET_SENSOR_EVT_ENABLE    0x29
48
#define IPMI_CMD_REARM_SENSOR_EVTS        0x2a
49
#define IPMI_CMD_GET_SENSOR_EVT_STATUS    0x2b
50
#define IPMI_CMD_GET_SENSOR_READING       0x2d
51
#define IPMI_CMD_SET_SENSOR_TYPE          0x2e
52
#define IPMI_CMD_GET_SENSOR_TYPE          0x2f
53
#define IPMI_CMD_SET_SENSOR_READING       0x30
54

55
/* #define IPMI_NETFN_APP             0x06 In ipmi.h */
56

57
#define IPMI_CMD_GET_DEVICE_ID            0x01
58
#define IPMI_CMD_COLD_RESET               0x02
59
#define IPMI_CMD_WARM_RESET               0x03
60
#define IPMI_CMD_SET_ACPI_POWER_STATE     0x06
61
#define IPMI_CMD_GET_ACPI_POWER_STATE     0x07
62
#define IPMI_CMD_GET_DEVICE_GUID          0x08
63
#define IPMI_CMD_RESET_WATCHDOG_TIMER     0x22
64
#define IPMI_CMD_SET_WATCHDOG_TIMER       0x24
65
#define IPMI_CMD_GET_WATCHDOG_TIMER       0x25
66
#define IPMI_CMD_SET_BMC_GLOBAL_ENABLES   0x2e
67
#define IPMI_CMD_GET_BMC_GLOBAL_ENABLES   0x2f
68
#define IPMI_CMD_CLR_MSG_FLAGS            0x30
69
#define IPMI_CMD_GET_MSG_FLAGS            0x31
70
#define IPMI_CMD_GET_MSG                  0x33
71
#define IPMI_CMD_SEND_MSG                 0x34
72
#define IPMI_CMD_READ_EVT_MSG_BUF         0x35
73

74
#define IPMI_NETFN_STORAGE            0x0a
75

76
#define IPMI_CMD_GET_SDR_REP_INFO         0x20
77
#define IPMI_CMD_GET_SDR_REP_ALLOC_INFO   0x21
78
#define IPMI_CMD_RESERVE_SDR_REP          0x22
79
#define IPMI_CMD_GET_SDR                  0x23
80
#define IPMI_CMD_ADD_SDR                  0x24
81
#define IPMI_CMD_PARTIAL_ADD_SDR          0x25
82
#define IPMI_CMD_DELETE_SDR               0x26
83
#define IPMI_CMD_CLEAR_SDR_REP            0x27
84
#define IPMI_CMD_GET_SDR_REP_TIME         0x28
85
#define IPMI_CMD_SET_SDR_REP_TIME         0x29
86
#define IPMI_CMD_ENTER_SDR_REP_UPD_MODE   0x2A
87
#define IPMI_CMD_EXIT_SDR_REP_UPD_MODE    0x2B
88
#define IPMI_CMD_RUN_INIT_AGENT           0x2C
89
#define IPMI_CMD_GET_FRU_AREA_INFO        0x10
90
#define IPMI_CMD_READ_FRU_DATA            0x11
91
#define IPMI_CMD_WRITE_FRU_DATA           0x12
92
#define IPMI_CMD_GET_SEL_INFO             0x40
93
#define IPMI_CMD_GET_SEL_ALLOC_INFO       0x41
94
#define IPMI_CMD_RESERVE_SEL              0x42
95
#define IPMI_CMD_GET_SEL_ENTRY            0x43
96
#define IPMI_CMD_ADD_SEL_ENTRY            0x44
97
#define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY    0x45
98
#define IPMI_CMD_DELETE_SEL_ENTRY         0x46
99
#define IPMI_CMD_CLEAR_SEL                0x47
100
#define IPMI_CMD_GET_SEL_TIME             0x48
101
#define IPMI_CMD_SET_SEL_TIME             0x49
102

103

104
/* Same as a timespec struct. */
105
struct ipmi_time {
106
    long tv_sec;
107
    long tv_nsec;
108
};
109

110
#define MAX_SEL_SIZE 128
111

112
typedef struct IPMISel {
113
    uint8_t sel[MAX_SEL_SIZE][16];
114
    unsigned int next_free;
115
    long time_offset;
116
    uint16_t reservation;
117
    uint8_t last_addition[4];
118
    uint8_t last_clear[4];
119
    uint8_t overflow;
120
} IPMISel;
121

122
#define MAX_SDR_SIZE 16384
123

124
typedef struct IPMISdr {
125
    uint8_t sdr[MAX_SDR_SIZE];
126
    unsigned int next_free;
127
    uint16_t next_rec_id;
128
    uint16_t reservation;
129
    uint8_t last_addition[4];
130
    uint8_t last_clear[4];
131
    uint8_t overflow;
132
} IPMISdr;
133

134
typedef struct IPMIFru {
135
    char *filename;
136
    unsigned int nentries;
137
    uint16_t areasize;
138
    uint8_t *data;
139
} IPMIFru;
140

141
typedef struct IPMISensor {
142
    uint8_t status;
143
    uint8_t reading;
144
    uint16_t states_suppt;
145
    uint16_t assert_suppt;
146
    uint16_t deassert_suppt;
147
    uint16_t states;
148
    uint16_t assert_states;
149
    uint16_t deassert_states;
150
    uint16_t assert_enable;
151
    uint16_t deassert_enable;
152
    uint8_t  sensor_type;
153
    uint8_t  evt_reading_type_code;
154
} IPMISensor;
155
#define IPMI_SENSOR_GET_PRESENT(s)       ((s)->status & 0x01)
156
#define IPMI_SENSOR_SET_PRESENT(s, v)    ((s)->status = (s->status & ~0x01) | \
157
                                             !!(v))
158
#define IPMI_SENSOR_GET_SCAN_ON(s)       ((s)->status & 0x40)
159
#define IPMI_SENSOR_SET_SCAN_ON(s, v)    ((s)->status = (s->status & ~0x40) | \
160
                                             ((!!(v)) << 6))
161
#define IPMI_SENSOR_GET_EVENTS_ON(s)     ((s)->status & 0x80)
162
#define IPMI_SENSOR_SET_EVENTS_ON(s, v)  ((s)->status = (s->status & ~0x80) | \
163
                                             ((!!(v)) << 7))
164
#define IPMI_SENSOR_GET_RET_STATUS(s)    ((s)->status & 0xc0)
165
#define IPMI_SENSOR_SET_RET_STATUS(s, v) ((s)->status = (s->status & ~0xc0) | \
166
                                             (v & 0xc0))
167
#define IPMI_SENSOR_IS_DISCRETE(s) ((s)->evt_reading_type_code != 1)
168

169
#define MAX_SENSORS 20
170
#define IPMI_WATCHDOG_SENSOR 0
171

172
#define MAX_NETFNS 64
173

174
typedef struct IPMIRcvBufEntry {
175
    QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
176
    uint8_t len;
177
    uint8_t buf[MAX_IPMI_MSG_SIZE];
178
} IPMIRcvBufEntry;
179

180
struct IPMIBmcSim {
181
    IPMIBmc parent;
182

183
    QEMUTimer *timer;
184

185
    uint8_t bmc_global_enables;
186
    uint8_t msg_flags;
187

188
    bool     watchdog_initialized;
189
    uint8_t  watchdog_use;
190
    uint8_t  watchdog_action;
191
    uint8_t  watchdog_pretimeout; /* In seconds */
192
    uint8_t  watchdog_expired;
193
    uint16_t watchdog_timeout; /* in 100's of milliseconds */
194

195
    bool     watchdog_running;
196
    bool     watchdog_preaction_ran;
197
    int64_t  watchdog_expiry;
198

199
    uint8_t device_id;
200
    uint8_t ipmi_version;
201
    uint8_t device_rev;
202
    uint8_t fwrev1;
203
    uint8_t fwrev2;
204
    uint32_t mfg_id;
205
    uint16_t product_id;
206

207
    uint8_t restart_cause;
208

209
    uint8_t acpi_power_state[2];
210
    QemuUUID uuid;
211

212
    IPMISel sel;
213
    IPMISdr sdr;
214
    IPMIFru fru;
215
    IPMISensor sensors[MAX_SENSORS];
216
    char *sdr_filename;
217

218
    /* Odd netfns are for responses, so we only need the even ones. */
219
    const IPMINetfn *netfns[MAX_NETFNS / 2];
220

221
    /* We allow one event in the buffer */
222
    uint8_t evtbuf[16];
223

224
    QTAILQ_HEAD(, IPMIRcvBufEntry) rcvbufs;
225
};
226

227
#define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK        (1 << 3)
228
#define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL                 (1 << 1)
229
#define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE                (1 << 0)
230
#define IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(s) \
231
    (IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (s)->msg_flags)
232
#define IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(s) \
233
    (IPMI_BMC_MSG_FLAG_EVT_BUF_FULL & (s)->msg_flags)
234
#define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
235
    (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
236

237
#define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT    0
238
#define IPMI_BMC_EVBUF_FULL_INT_BIT       1
239
#define IPMI_BMC_EVENT_MSG_BUF_BIT        2
240
#define IPMI_BMC_EVENT_LOG_BIT            3
241
#define IPMI_BMC_MSG_INTS_ON(s) ((s)->bmc_global_enables & \
242
                                 (1 << IPMI_BMC_RCV_MSG_QUEUE_INT_BIT))
243
#define IPMI_BMC_EVBUF_FULL_INT_ENABLED(s) ((s)->bmc_global_enables & \
244
                                        (1 << IPMI_BMC_EVBUF_FULL_INT_BIT))
245
#define IPMI_BMC_EVENT_LOG_ENABLED(s) ((s)->bmc_global_enables & \
246
                                       (1 << IPMI_BMC_EVENT_LOG_BIT))
247
#define IPMI_BMC_EVENT_MSG_BUF_ENABLED(s) ((s)->bmc_global_enables & \
248
                                           (1 << IPMI_BMC_EVENT_MSG_BUF_BIT))
249

250
#define IPMI_BMC_WATCHDOG_USE_MASK 0xc7
251
#define IPMI_BMC_WATCHDOG_ACTION_MASK 0x77
252
#define IPMI_BMC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7)
253
#define IPMI_BMC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1)
254
#define IPMI_BMC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1)
255
#define IPMI_BMC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7)
256
#define IPMI_BMC_WATCHDOG_PRE_NONE               0
257
#define IPMI_BMC_WATCHDOG_PRE_SMI                1
258
#define IPMI_BMC_WATCHDOG_PRE_NMI                2
259
#define IPMI_BMC_WATCHDOG_PRE_MSG_INT            3
260
#define IPMI_BMC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7)
261
#define IPMI_BMC_WATCHDOG_ACTION_NONE            0
262
#define IPMI_BMC_WATCHDOG_ACTION_RESET           1
263
#define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN      2
264
#define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE     3
265

266
#define RSP_BUFFER_INITIALIZER { }
267

268
static inline void rsp_buffer_pushmore(RspBuffer *rsp, uint8_t *bytes,
269
                                       unsigned int n)
270
{
271
    if (rsp->len + n >= sizeof(rsp->buffer)) {
272
        rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
273
        return;
274
    }
275

276
    memcpy(&rsp->buffer[rsp->len], bytes, n);
277
    rsp->len += n;
278
}
279

280
static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
281

282
static void ipmi_gettime(struct ipmi_time *time)
283
{
284
    int64_t stime;
285

286
    stime = qemu_clock_get_ns(QEMU_CLOCK_HOST);
287
    time->tv_sec = stime / 1000000000LL;
288
    time->tv_nsec = stime % 1000000000LL;
289
}
290

291
static int64_t ipmi_getmonotime(void)
292
{
293
    return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
294
}
295

296
static void ipmi_timeout(void *opaque)
297
{
298
    IPMIBmcSim *ibs = opaque;
299

300
    ipmi_sim_handle_timeout(ibs);
301
}
302

303
static void set_timestamp(IPMIBmcSim *ibs, uint8_t *ts)
304
{
305
    unsigned int val;
306
    struct ipmi_time now;
307

308
    ipmi_gettime(&now);
309
    val = now.tv_sec + ibs->sel.time_offset;
310
    ts[0] = val & 0xff;
311
    ts[1] = (val >> 8) & 0xff;
312
    ts[2] = (val >> 16) & 0xff;
313
    ts[3] = (val >> 24) & 0xff;
314
}
315

316
static void sdr_inc_reservation(IPMISdr *sdr)
317
{
318
    sdr->reservation++;
319
    if (sdr->reservation == 0) {
320
        sdr->reservation = 1;
321
    }
322
}
323

324
static int sdr_add_entry(IPMIBmcSim *ibs,
325
                         const struct ipmi_sdr_header *sdrh_entry,
326
                         unsigned int len, uint16_t *recid)
327
{
328
    struct ipmi_sdr_header *sdrh =
329
        (struct ipmi_sdr_header *) &ibs->sdr.sdr[ibs->sdr.next_free];
330

331
    if ((len < IPMI_SDR_HEADER_SIZE) || (len > 255)) {
332
        return 1;
333
    }
334

335
    if (ipmi_sdr_length(sdrh_entry) != len) {
336
        return 1;
337
    }
338

339
    if (ibs->sdr.next_free + len > MAX_SDR_SIZE) {
340
        ibs->sdr.overflow = 1;
341
        return 1;
342
    }
343

344
    memcpy(sdrh, sdrh_entry, len);
345
    sdrh->rec_id[0] = ibs->sdr.next_rec_id & 0xff;
346
    sdrh->rec_id[1] = (ibs->sdr.next_rec_id >> 8) & 0xff;
347
    sdrh->sdr_version = 0x51; /* Conform to IPMI 1.5 spec */
348

349
    if (recid) {
350
        *recid = ibs->sdr.next_rec_id;
351
    }
352
    ibs->sdr.next_rec_id++;
353
    set_timestamp(ibs, ibs->sdr.last_addition);
354
    ibs->sdr.next_free += len;
355
    sdr_inc_reservation(&ibs->sdr);
356
    return 0;
357
}
358

359
static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
360
                          unsigned int *retpos, uint16_t *nextrec)
361
{
362
    unsigned int pos = *retpos;
363

364
    while (pos < sdr->next_free) {
365
        struct ipmi_sdr_header *sdrh =
366
            (struct ipmi_sdr_header *) &sdr->sdr[pos];
367
        uint16_t trec = ipmi_sdr_recid(sdrh);
368
        unsigned int nextpos = pos + ipmi_sdr_length(sdrh);
369

370
        if (trec == recid) {
371
            if (nextrec) {
372
                if (nextpos >= sdr->next_free) {
373
                    *nextrec = 0xffff;
374
                } else {
375
                    *nextrec = (sdr->sdr[nextpos] |
376
                                (sdr->sdr[nextpos + 1] << 8));
377
                }
378
            }
379
            *retpos = pos;
380
            return 0;
381
        }
382
        pos = nextpos;
383
    }
384
    return 1;
385
}
386

387
int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
388
                      const struct ipmi_sdr_compact **sdr, uint16_t *nextrec)
389

390
{
391
    IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
392
    unsigned int pos;
393

394
    pos = 0;
395
    if (sdr_find_entry(&ibs->sdr, recid, &pos, nextrec)) {
396
        return -1;
397
    }
398

399
    *sdr = (const struct ipmi_sdr_compact *) &ibs->sdr.sdr[pos];
400
    return 0;
401
}
402

403
static void sel_inc_reservation(IPMISel *sel)
404
{
405
    sel->reservation++;
406
    if (sel->reservation == 0) {
407
        sel->reservation = 1;
408
    }
409
}
410

411
/* Returns 1 if the SEL is full and can't hold the event. */
412
static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
413
{
414
    uint8_t ts[4];
415

416
    event[0] = 0xff;
417
    event[1] = 0xff;
418
    set_timestamp(ibs, ts);
419
    if (event[2] < 0xe0) { /* Don't set timestamps for type 0xe0-0xff. */
420
        memcpy(event + 3, ts, 4);
421
    }
422
    if (ibs->sel.next_free == MAX_SEL_SIZE) {
423
        ibs->sel.overflow = 1;
424
        return 1;
425
    }
426
    event[0] = ibs->sel.next_free & 0xff;
427
    event[1] = (ibs->sel.next_free >> 8) & 0xff;
428
    memcpy(ibs->sel.last_addition, ts, 4);
429
    memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
430
    ibs->sel.next_free++;
431
    sel_inc_reservation(&ibs->sel);
432
    return 0;
433
}
434

435
static int attn_set(IPMIBmcSim *ibs)
436
{
437
    return IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs)
438
        || IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs)
439
        || IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs);
440
}
441

442
static int attn_irq_enabled(IPMIBmcSim *ibs)
443
{
444
    return (IPMI_BMC_MSG_INTS_ON(ibs) &&
445
            (IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs) ||
446
             IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs)))
447
        || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
448
            IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
449
}
450

451
void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log)
452
{
453
    IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
454
    IPMIInterface *s = ibs->parent.intf;
455
    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
456

457
    if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
458
        return;
459
    }
460

461
    if (log && IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
462
        sel_add_event(ibs, evt);
463
    }
464

465
    if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
466
        goto out;
467
    }
468

469
    memcpy(ibs->evtbuf, evt, 16);
470
    ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
471
    k->set_atn(s, 1, attn_irq_enabled(ibs));
472
 out:
473
    return;
474
}
475
static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
476
                      uint8_t evd1, uint8_t evd2, uint8_t evd3)
477
{
478
    IPMIInterface *s = ibs->parent.intf;
479
    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
480
    uint8_t evt[16];
481
    IPMISensor *sens = ibs->sensors + sens_num;
482

483
    if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
484
        return;
485
    }
486
    if (!IPMI_SENSOR_GET_EVENTS_ON(sens)) {
487
        return;
488
    }
489

490
    evt[2] = 0x2; /* System event record */
491
    evt[7] = ibs->parent.slave_addr;
492
    evt[8] = 0;
493
    evt[9] = 0x04; /* Format version */
494
    evt[10] = sens->sensor_type;
495
    evt[11] = sens_num;
496
    evt[12] = sens->evt_reading_type_code | (!!deassert << 7);
497
    evt[13] = evd1;
498
    evt[14] = evd2;
499
    evt[15] = evd3;
500

501
    if (IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
502
        sel_add_event(ibs, evt);
503
    }
504

505
    if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
506
        return;
507
    }
508

509
    memcpy(ibs->evtbuf, evt, 16);
510
    ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
511
    k->set_atn(s, 1, attn_irq_enabled(ibs));
512
}
513

514
static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
515
                                    unsigned int bit, unsigned int val,
516
                                    uint8_t evd1, uint8_t evd2, uint8_t evd3)
517
{
518
    IPMISensor *sens;
519
    uint16_t mask;
520

521
    if (sensor >= MAX_SENSORS) {
522
        return;
523
    }
524
    if (bit >= 16) {
525
        return;
526
    }
527

528
    mask = (1 << bit);
529
    sens = ibs->sensors + sensor;
530
    if (val) {
531
        sens->states |= mask & sens->states_suppt;
532
        if (sens->assert_states & mask) {
533
            return; /* Already asserted */
534
        }
535
        sens->assert_states |= mask & sens->assert_suppt;
536
        if (sens->assert_enable & mask & sens->assert_states) {
537
            /* Send an event on assert */
538
            gen_event(ibs, sensor, 0, evd1, evd2, evd3);
539
        }
540
    } else {
541
        sens->states &= ~(mask & sens->states_suppt);
542
        if (sens->deassert_states & mask) {
543
            return; /* Already deasserted */
544
        }
545
        sens->deassert_states |= mask & sens->deassert_suppt;
546
        if (sens->deassert_enable & mask & sens->deassert_states) {
547
            /* Send an event on deassert */
548
            gen_event(ibs, sensor, 1, evd1, evd2, evd3);
549
        }
550
    }
551
}
552

553
static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
554
{
555
    unsigned int i, pos;
556
    IPMISensor *sens;
557

558
    for (i = 0; i < MAX_SENSORS; i++) {
559
        memset(s->sensors + i, 0, sizeof(*sens));
560
    }
561

562
    pos = 0;
563
    for (i = 0; !sdr_find_entry(&s->sdr, i, &pos, NULL); i++) {
564
        struct ipmi_sdr_compact *sdr =
565
            (struct ipmi_sdr_compact *) &s->sdr.sdr[pos];
566
        unsigned int len = sdr->header.rec_length;
567

568
        if (len < 20) {
569
            continue;
570
        }
571
        if (sdr->header.rec_type != IPMI_SDR_COMPACT_TYPE) {
572
            continue; /* Not a sensor SDR we set from */
573
        }
574

575
        if (sdr->sensor_owner_number >= MAX_SENSORS) {
576
            continue;
577
        }
578
        sens = s->sensors + sdr->sensor_owner_number;
579

580
        IPMI_SENSOR_SET_PRESENT(sens, 1);
581
        IPMI_SENSOR_SET_SCAN_ON(sens, (sdr->sensor_init >> 6) & 1);
582
        IPMI_SENSOR_SET_EVENTS_ON(sens, (sdr->sensor_init >> 5) & 1);
583
        sens->assert_suppt = sdr->assert_mask[0] | (sdr->assert_mask[1] << 8);
584
        sens->deassert_suppt =
585
            sdr->deassert_mask[0] | (sdr->deassert_mask[1] << 8);
586
        sens->states_suppt =
587
            sdr->discrete_mask[0] | (sdr->discrete_mask[1] << 8);
588
        sens->sensor_type = sdr->sensor_type;
589
        sens->evt_reading_type_code = sdr->reading_type & 0x7f;
590

591
        /* Enable all the events that are supported. */
592
        sens->assert_enable = sens->assert_suppt;
593
        sens->deassert_enable = sens->deassert_suppt;
594
    }
595
}
596

597
int ipmi_sim_register_netfn(IPMIBmcSim *s, unsigned int netfn,
598
                        const IPMINetfn *netfnd)
599
{
600
    if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
601
        return -1;
602
    }
603
    s->netfns[netfn / 2] = netfnd;
604
    return 0;
605
}
606

607
static const IPMICmdHandler *ipmi_get_handler(IPMIBmcSim *ibs,
608
                                              unsigned int netfn,
609
                                              unsigned int cmd)
610
{
611
    const IPMICmdHandler *hdl;
612

613
    if (netfn & 1 || netfn >= MAX_NETFNS || !ibs->netfns[netfn / 2]) {
614
        return NULL;
615
    }
616

617
    if (cmd >= ibs->netfns[netfn / 2]->cmd_nums) {
618
        return NULL;
619
    }
620

621
    hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd];
622
    if (!hdl->cmd_handler) {
623
        return NULL;
624
    }
625

626
    return hdl;
627
}
628

629
static void next_timeout(IPMIBmcSim *ibs)
630
{
631
    int64_t next;
632
    if (ibs->watchdog_running) {
633
        next = ibs->watchdog_expiry;
634
    } else {
635
        /* Wait a minute */
636
        next = ipmi_getmonotime() + 60 * 1000000000LL;
637
    }
638
    timer_mod_ns(ibs->timer, next);
639
}
640

641
static void ipmi_sim_handle_command(IPMIBmc *b,
642
                                    uint8_t *cmd, unsigned int cmd_len,
643
                                    unsigned int max_cmd_len,
644
                                    uint8_t msg_id)
645
{
646
    IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
647
    IPMIInterface *s = ibs->parent.intf;
648
    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
649
    const IPMICmdHandler *hdl;
650
    RspBuffer rsp = RSP_BUFFER_INITIALIZER;
651

652
    /* Set up the response, set the low bit of NETFN. */
653
    /* Note that max_rsp_len must be at least 3 */
654
    if (sizeof(rsp.buffer) < 3) {
655
        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
656
        goto out;
657
    }
658

659
    rsp_buffer_push(&rsp, cmd[0] | 0x04);
660
    rsp_buffer_push(&rsp, cmd[1]);
661
    rsp_buffer_push(&rsp, 0); /* Assume success */
662

663
    /* If it's too short or it was truncated, return an error. */
664
    if (cmd_len < 2) {
665
        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
666
        goto out;
667
    }
668
    if (cmd_len > max_cmd_len) {
669
        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
670
        goto out;
671
    }
672

673
    if ((cmd[0] & 0x03) != 0) {
674
        /* Only have stuff on LUN 0 */
675
        rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN);
676
        goto out;
677
    }
678

679
    hdl = ipmi_get_handler(ibs, cmd[0] >> 2, cmd[1]);
680
    if (!hdl) {
681
        rsp_buffer_set_error(&rsp, IPMI_CC_INVALID_CMD);
682
        goto out;
683
    }
684

685
    if (cmd_len < hdl->cmd_len_min) {
686
        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
687
        goto out;
688
    }
689

690
    hdl->cmd_handler(ibs, cmd, cmd_len, &rsp);
691

692
 out:
693
    k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
694

695
    next_timeout(ibs);
696
}
697

698
static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
699
{
700
    IPMIInterface *s = ibs->parent.intf;
701
    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
702

703
    if (!ibs->watchdog_running) {
704
        goto out;
705
    }
706

707
    if (!ibs->watchdog_preaction_ran) {
708
        switch (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs)) {
709
        case IPMI_BMC_WATCHDOG_PRE_NMI:
710
            ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
711
            k->do_hw_op(s, IPMI_SEND_NMI, 0);
712
            sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
713
                                    0xc8, (2 << 4) | 0xf, 0xff);
714
            break;
715

716
        case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
717
            ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
718
            k->set_atn(s, 1, attn_irq_enabled(ibs));
719
            sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
720
                                    0xc8, (3 << 4) | 0xf, 0xff);
721
            break;
722

723
        default:
724
            goto do_full_expiry;
725
        }
726

727
        ibs->watchdog_preaction_ran = 1;
728
        /* Issued the pretimeout, do the rest of the timeout now. */
729
        ibs->watchdog_expiry = ipmi_getmonotime();
730
        ibs->watchdog_expiry += ibs->watchdog_pretimeout * 1000000000LL;
731
        goto out;
732
    }
733

734
 do_full_expiry:
735
    ibs->watchdog_running = 0; /* Stop the watchdog on a timeout */
736
    ibs->watchdog_expired |= (1 << IPMI_BMC_WATCHDOG_GET_USE(ibs));
737
    switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
738
    case IPMI_BMC_WATCHDOG_ACTION_NONE:
739
        sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
740
                                0xc0, ibs->watchdog_use & 0xf, 0xff);
741
        break;
742

743
    case IPMI_BMC_WATCHDOG_ACTION_RESET:
744
        sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
745
                                0xc1, ibs->watchdog_use & 0xf, 0xff);
746
        k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
747
        break;
748

749
    case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
750
        sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
751
                                0xc2, ibs->watchdog_use & 0xf, 0xff);
752
        k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
753
        break;
754

755
    case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
756
        sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
757
                                0xc3, ibs->watchdog_use & 0xf, 0xff);
758
        k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
759
        break;
760
    }
761

762
 out:
763
    next_timeout(ibs);
764
}
765

766
static void chassis_capabilities(IPMIBmcSim *ibs,
767
                                 uint8_t *cmd, unsigned int cmd_len,
768
                                 RspBuffer *rsp)
769
{
770
    rsp_buffer_push(rsp, 0);
771
    rsp_buffer_push(rsp, ibs->parent.slave_addr);
772
    rsp_buffer_push(rsp, ibs->parent.slave_addr);
773
    rsp_buffer_push(rsp, ibs->parent.slave_addr);
774
    rsp_buffer_push(rsp, ibs->parent.slave_addr);
775
}
776

777
static void chassis_status(IPMIBmcSim *ibs,
778
                           uint8_t *cmd, unsigned int cmd_len,
779
                           RspBuffer *rsp)
780
{
781
    rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */
782
    rsp_buffer_push(rsp, 0);
783
    rsp_buffer_push(rsp, 0);
784
    rsp_buffer_push(rsp, 0);
785
}
786

787
static void chassis_control(IPMIBmcSim *ibs,
788
                            uint8_t *cmd, unsigned int cmd_len,
789
                            RspBuffer *rsp)
790
{
791
    IPMIInterface *s = ibs->parent.intf;
792
    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
793

794
    switch (cmd[2] & 0xf) {
795
    case 0: /* power down */
796
        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0));
797
        break;
798
    case 1: /* power up */
799
        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0));
800
        break;
801
    case 2: /* power cycle */
802
        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0));
803
        break;
804
    case 3: /* hard reset */
805
        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0));
806
        break;
807
    case 4: /* pulse diagnostic interrupt */
808
        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0));
809
        break;
810
    case 5: /* soft shutdown via ACPI by overtemp emulation */
811
        rsp_buffer_set_error(rsp, k->do_hw_op(s,
812
                                          IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0));
813
        break;
814
    default:
815
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
816
        return;
817
    }
818
}
819

820
static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
821
                           uint8_t *cmd, unsigned int cmd_len,
822
                           RspBuffer *rsp)
823

824
{
825
    rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */
826
    rsp_buffer_push(rsp, 0);  /* Channel 0 */
827
}
828

829
static void get_device_id(IPMIBmcSim *ibs,
830
                          uint8_t *cmd, unsigned int cmd_len,
831
                          RspBuffer *rsp)
832
{
833
    rsp_buffer_push(rsp, ibs->device_id);
834
    rsp_buffer_push(rsp, ibs->device_rev & 0xf);
835
    rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
836
    rsp_buffer_push(rsp, ibs->fwrev2);
837
    rsp_buffer_push(rsp, ibs->ipmi_version);
838
    rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */
839
    rsp_buffer_push(rsp, ibs->mfg_id & 0xff);
840
    rsp_buffer_push(rsp, (ibs->mfg_id >> 8) & 0xff);
841
    rsp_buffer_push(rsp, (ibs->mfg_id >> 16) & 0xff);
842
    rsp_buffer_push(rsp, ibs->product_id & 0xff);
843
    rsp_buffer_push(rsp, (ibs->product_id >> 8) & 0xff);
844
}
845

846
static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
847
{
848
    IPMIInterface *s = ibs->parent.intf;
849
    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
850
    bool irqs_on;
851

852
    ibs->bmc_global_enables = val;
853

854
    irqs_on = val & (IPMI_BMC_EVBUF_FULL_INT_BIT |
855
                     IPMI_BMC_RCV_MSG_QUEUE_INT_BIT);
856

857
    k->set_irq_enable(s, irqs_on);
858
}
859

860
static void cold_reset(IPMIBmcSim *ibs,
861
                       uint8_t *cmd, unsigned int cmd_len,
862
                       RspBuffer *rsp)
863
{
864
    IPMIInterface *s = ibs->parent.intf;
865
    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
866

867
    /* Disable all interrupts */
868
    set_global_enables(ibs, 1 << IPMI_BMC_EVENT_LOG_BIT);
869

870
    if (k->reset) {
871
        k->reset(s, true);
872
    }
873
}
874

875
static void warm_reset(IPMIBmcSim *ibs,
876
                       uint8_t *cmd, unsigned int cmd_len,
877
                       RspBuffer *rsp)
878
{
879
    IPMIInterface *s = ibs->parent.intf;
880
    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
881

882
    if (k->reset) {
883
        k->reset(s, false);
884
    }
885
}
886
static void set_acpi_power_state(IPMIBmcSim *ibs,
887
                                 uint8_t *cmd, unsigned int cmd_len,
888
                                 RspBuffer *rsp)
889
{
890
    ibs->acpi_power_state[0] = cmd[2];
891
    ibs->acpi_power_state[1] = cmd[3];
892
}
893

894
static void get_acpi_power_state(IPMIBmcSim *ibs,
895
                                 uint8_t *cmd, unsigned int cmd_len,
896
                                 RspBuffer *rsp)
897
{
898
    rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
899
    rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
900
}
901

902
static void get_device_guid(IPMIBmcSim *ibs,
903
                            uint8_t *cmd, unsigned int cmd_len,
904
                            RspBuffer *rsp)
905
{
906
    unsigned int i;
907

908
    /* An uninitialized uuid is all zeros, use that to know if it is set. */
909
    for (i = 0; i < 16; i++) {
910
        if (ibs->uuid.data[i]) {
911
            goto uuid_set;
912
        }
913
    }
914
    /* No uuid is set, return an error. */
915
    rsp_buffer_set_error(rsp, IPMI_CC_INVALID_CMD);
916
    return;
917

918
 uuid_set:
919
    for (i = 0; i < 16; i++) {
920
        rsp_buffer_push(rsp, ibs->uuid.data[i]);
921
    }
922
}
923

924
static void set_bmc_global_enables(IPMIBmcSim *ibs,
925
                                   uint8_t *cmd, unsigned int cmd_len,
926
                                   RspBuffer *rsp)
927
{
928
    set_global_enables(ibs, cmd[2]);
929
}
930

931
static void get_bmc_global_enables(IPMIBmcSim *ibs,
932
                                   uint8_t *cmd, unsigned int cmd_len,
933
                                   RspBuffer *rsp)
934
{
935
    rsp_buffer_push(rsp, ibs->bmc_global_enables);
936
}
937

938
static void clr_msg_flags(IPMIBmcSim *ibs,
939
                          uint8_t *cmd, unsigned int cmd_len,
940
                          RspBuffer *rsp)
941
{
942
    IPMIInterface *s = ibs->parent.intf;
943
    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
944

945
    ibs->msg_flags &= ~cmd[2];
946
    k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
947
}
948

949
static void get_msg_flags(IPMIBmcSim *ibs,
950
                          uint8_t *cmd, unsigned int cmd_len,
951
                          RspBuffer *rsp)
952
{
953
    rsp_buffer_push(rsp, ibs->msg_flags);
954
}
955

956
static void read_evt_msg_buf(IPMIBmcSim *ibs,
957
                             uint8_t *cmd, unsigned int cmd_len,
958
                             RspBuffer *rsp)
959
{
960
    IPMIInterface *s = ibs->parent.intf;
961
    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
962
    unsigned int i;
963

964
    if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
965
        rsp_buffer_set_error(rsp, 0x80);
966
        return;
967
    }
968
    for (i = 0; i < 16; i++) {
969
        rsp_buffer_push(rsp, ibs->evtbuf[i]);
970
    }
971
    ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
972
    k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
973
}
974

975
static void get_msg(IPMIBmcSim *ibs,
976
                    uint8_t *cmd, unsigned int cmd_len,
977
                    RspBuffer *rsp)
978
{
979
    IPMIRcvBufEntry *msg;
980

981
    if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
982
        rsp_buffer_set_error(rsp, 0x80); /* Queue empty */
983
        goto out;
984
    }
985
    rsp_buffer_push(rsp, 0); /* Channel 0 */
986
    msg = QTAILQ_FIRST(&ibs->rcvbufs);
987
    rsp_buffer_pushmore(rsp, msg->buf, msg->len);
988
    QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
989
    g_free(msg);
990

991
    if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
992
        IPMIInterface *s = ibs->parent.intf;
993
        IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
994

995
        ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
996
        k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
997
    }
998

999
out:
1000
    return;
1001
}
1002

1003
static unsigned char
1004
ipmb_checksum(unsigned char *data, int size, unsigned char csum)
1005
{
1006
    for (; size > 0; size--, data++) {
1007
            csum += *data;
1008
    }
1009

1010
    return -csum;
1011
}
1012

1013
static void send_msg(IPMIBmcSim *ibs,
1014
                     uint8_t *cmd, unsigned int cmd_len,
1015
                     RspBuffer *rsp)
1016
{
1017
    IPMIInterface *s = ibs->parent.intf;
1018
    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1019
    IPMIRcvBufEntry *msg;
1020
    uint8_t *buf;
1021
    uint8_t netfn, rqLun, rsLun, rqSeq;
1022

1023
    if (cmd[2] != 0) {
1024
        /* We only handle channel 0 with no options */
1025
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1026
        return;
1027
    }
1028

1029
    if (cmd_len < 10) {
1030
        rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
1031
        return;
1032
    }
1033

1034
    if (cmd[3] != 0x40) {
1035
        /* We only emulate a MC at address 0x40. */
1036
        rsp_buffer_set_error(rsp, 0x83); /* NAK on write */
1037
        return;
1038
    }
1039

1040
    cmd += 3; /* Skip the header. */
1041
    cmd_len -= 3;
1042

1043
    /*
1044
     * At this point we "send" the message successfully.  Any error will
1045
     * be returned in the response.
1046
     */
1047
    if (ipmb_checksum(cmd, cmd_len, 0) != 0 ||
1048
        cmd[3] != 0x20) { /* Improper response address */
1049
        return; /* No response */
1050
    }
1051

1052
    netfn = cmd[1] >> 2;
1053
    rqLun = cmd[4] & 0x3;
1054
    rsLun = cmd[1] & 0x3;
1055
    rqSeq = cmd[4] >> 2;
1056

1057
    if (rqLun != 2) {
1058
        /* We only support LUN 2 coming back to us. */
1059
        return;
1060
    }
1061

1062
    msg = g_malloc(sizeof(*msg));
1063
    msg->buf[0] = ((netfn | 1) << 2) | rqLun; /* NetFN, and make a response */
1064
    msg->buf[1] = ipmb_checksum(msg->buf, 1, 0);
1065
    msg->buf[2] = cmd[0]; /* rsSA */
1066
    msg->buf[3] = (rqSeq << 2) | rsLun;
1067
    msg->buf[4] = cmd[5]; /* Cmd */
1068
    msg->buf[5] = 0; /* Completion Code */
1069
    msg->len = 6;
1070

1071
    if ((cmd[1] >> 2) != IPMI_NETFN_APP || cmd[5] != IPMI_CMD_GET_DEVICE_ID) {
1072
        /* Not a command we handle. */
1073
        msg->buf[5] = IPMI_CC_INVALID_CMD;
1074
        goto end_msg;
1075
    }
1076

1077
    buf = msg->buf + msg->len; /* After the CC */
1078
    buf[0] = 0;
1079
    buf[1] = 0;
1080
    buf[2] = 0;
1081
    buf[3] = 0;
1082
    buf[4] = 0x51;
1083
    buf[5] = 0;
1084
    buf[6] = 0;
1085
    buf[7] = 0;
1086
    buf[8] = 0;
1087
    buf[9] = 0;
1088
    buf[10] = 0;
1089
    msg->len += 11;
1090

1091
 end_msg:
1092
    msg->buf[msg->len] = ipmb_checksum(msg->buf, msg->len, 0);
1093
    msg->len++;
1094
    QTAILQ_INSERT_TAIL(&ibs->rcvbufs, msg, entry);
1095
    ibs->msg_flags |= IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE;
1096
    k->set_atn(s, 1, attn_irq_enabled(ibs));
1097
}
1098

1099
static void do_watchdog_reset(IPMIBmcSim *ibs)
1100
{
1101
    if (IPMI_BMC_WATCHDOG_GET_ACTION(ibs) ==
1102
        IPMI_BMC_WATCHDOG_ACTION_NONE) {
1103
        ibs->watchdog_running = 0;
1104
        return;
1105
    }
1106
    ibs->watchdog_preaction_ran = 0;
1107

1108

1109
    /* Timeout is in tenths of a second, offset is in seconds */
1110
    ibs->watchdog_expiry = ipmi_getmonotime();
1111
    ibs->watchdog_expiry += ibs->watchdog_timeout * 100000000LL;
1112
    if (IPMI_BMC_WATCHDOG_GET_PRE_ACTION(ibs) != IPMI_BMC_WATCHDOG_PRE_NONE) {
1113
        ibs->watchdog_expiry -= ibs->watchdog_pretimeout * 1000000000LL;
1114
    }
1115
    ibs->watchdog_running = 1;
1116
}
1117

1118
static void reset_watchdog_timer(IPMIBmcSim *ibs,
1119
                                 uint8_t *cmd, unsigned int cmd_len,
1120
                                 RspBuffer *rsp)
1121
{
1122
    if (!ibs->watchdog_initialized) {
1123
        rsp_buffer_set_error(rsp, 0x80);
1124
        return;
1125
    }
1126
    do_watchdog_reset(ibs);
1127
}
1128

1129
static void set_watchdog_timer(IPMIBmcSim *ibs,
1130
                               uint8_t *cmd, unsigned int cmd_len,
1131
                               RspBuffer *rsp)
1132
{
1133
    IPMIInterface *s = ibs->parent.intf;
1134
    IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
1135
    unsigned int val;
1136

1137
    val = cmd[2] & 0x7; /* Validate use */
1138
    if (val == 0 || val > 5) {
1139
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1140
        return;
1141
    }
1142
    val = cmd[3] & 0x7; /* Validate action */
1143
    switch (val) {
1144
    case IPMI_BMC_WATCHDOG_ACTION_NONE:
1145
        break;
1146

1147
    case IPMI_BMC_WATCHDOG_ACTION_RESET:
1148
        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1));
1149
        break;
1150

1151
    case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
1152
        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1));
1153
        break;
1154

1155
    case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
1156
        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1));
1157
        break;
1158

1159
    default:
1160
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1161
    }
1162
    if (rsp->buffer[2]) {
1163
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1164
        return;
1165
    }
1166

1167
    val = (cmd[3] >> 4) & 0x7; /* Validate preaction */
1168
    switch (val) {
1169
    case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
1170
    case IPMI_BMC_WATCHDOG_PRE_NONE:
1171
        break;
1172

1173
    case IPMI_BMC_WATCHDOG_PRE_NMI:
1174
        if (k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
1175
            /* NMI not supported. */
1176
            rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1177
            return;
1178
        }
1179
        break;
1180

1181
    default:
1182
        /* We don't support PRE_SMI */
1183
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1184
        return;
1185
    }
1186

1187
    ibs->watchdog_initialized = 1;
1188
    ibs->watchdog_use = cmd[2] & IPMI_BMC_WATCHDOG_USE_MASK;
1189
    ibs->watchdog_action = cmd[3] & IPMI_BMC_WATCHDOG_ACTION_MASK;
1190
    ibs->watchdog_pretimeout = cmd[4];
1191
    ibs->watchdog_expired &= ~cmd[5];
1192
    ibs->watchdog_timeout = cmd[6] | (((uint16_t) cmd[7]) << 8);
1193
    if (ibs->watchdog_running & IPMI_BMC_WATCHDOG_GET_DONT_STOP(ibs)) {
1194
        do_watchdog_reset(ibs);
1195
    } else {
1196
        ibs->watchdog_running = 0;
1197
    }
1198
}
1199

1200
static void get_watchdog_timer(IPMIBmcSim *ibs,
1201
                               uint8_t *cmd, unsigned int cmd_len,
1202
                               RspBuffer *rsp)
1203
{
1204
    rsp_buffer_push(rsp, ibs->watchdog_use);
1205
    rsp_buffer_push(rsp, ibs->watchdog_action);
1206
    rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
1207
    rsp_buffer_push(rsp, ibs->watchdog_expired);
1208
    rsp_buffer_push(rsp, ibs->watchdog_timeout & 0xff);
1209
    rsp_buffer_push(rsp, (ibs->watchdog_timeout >> 8) & 0xff);
1210
    if (ibs->watchdog_running) {
1211
        long timeout;
1212
        timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
1213
                   / 100000000);
1214
        rsp_buffer_push(rsp, timeout & 0xff);
1215
        rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
1216
    } else {
1217
        rsp_buffer_push(rsp, 0);
1218
        rsp_buffer_push(rsp, 0);
1219
    }
1220
}
1221

1222
static void get_sdr_rep_info(IPMIBmcSim *ibs,
1223
                             uint8_t *cmd, unsigned int cmd_len,
1224
                             RspBuffer *rsp)
1225
{
1226
    unsigned int i;
1227

1228
    rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */
1229
    rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
1230
    rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
1231
    rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
1232
    rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
1233
    for (i = 0; i < 4; i++) {
1234
        rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
1235
    }
1236
    for (i = 0; i < 4; i++) {
1237
        rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
1238
    }
1239
    /* Only modal support, reserve supported */
1240
    rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
1241
}
1242

1243
static void reserve_sdr_rep(IPMIBmcSim *ibs,
1244
                            uint8_t *cmd, unsigned int cmd_len,
1245
                            RspBuffer *rsp)
1246
{
1247
    rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
1248
    rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
1249
}
1250

1251
static void get_sdr(IPMIBmcSim *ibs,
1252
                    uint8_t *cmd, unsigned int cmd_len,
1253
                    RspBuffer *rsp)
1254
{
1255
    unsigned int pos;
1256
    uint16_t nextrec;
1257
    struct ipmi_sdr_header *sdrh;
1258

1259
    if (cmd[6]) {
1260
        if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1261
            rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1262
            return;
1263
        }
1264
    }
1265

1266
    pos = 0;
1267
    if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
1268
                       &pos, &nextrec)) {
1269
        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1270
        return;
1271
    }
1272

1273
    sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
1274

1275
    if (cmd[6] > ipmi_sdr_length(sdrh)) {
1276
        rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE);
1277
        return;
1278
    }
1279

1280
    rsp_buffer_push(rsp, nextrec & 0xff);
1281
    rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
1282

1283
    if (cmd[7] == 0xff) {
1284
        cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
1285
    }
1286

1287
    if ((cmd[7] + rsp->len) > sizeof(rsp->buffer)) {
1288
        rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES);
1289
        return;
1290
    }
1291

1292
    rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
1293
}
1294

1295
static void add_sdr(IPMIBmcSim *ibs,
1296
                    uint8_t *cmd, unsigned int cmd_len,
1297
                    RspBuffer *rsp)
1298
{
1299
    uint16_t recid;
1300
    struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
1301

1302
    if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
1303
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1304
        return;
1305
    }
1306
    rsp_buffer_push(rsp, recid & 0xff);
1307
    rsp_buffer_push(rsp, (recid >> 8) & 0xff);
1308
}
1309

1310
static void clear_sdr_rep(IPMIBmcSim *ibs,
1311
                          uint8_t *cmd, unsigned int cmd_len,
1312
                          RspBuffer *rsp)
1313
{
1314
    if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
1315
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1316
        return;
1317
    }
1318

1319
    if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1320
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1321
        return;
1322
    }
1323
    if (cmd[7] == 0xaa) {
1324
        ibs->sdr.next_free = 0;
1325
        ibs->sdr.overflow = 0;
1326
        set_timestamp(ibs, ibs->sdr.last_clear);
1327
        rsp_buffer_push(rsp, 1); /* Erasure complete */
1328
        sdr_inc_reservation(&ibs->sdr);
1329
    } else if (cmd[7] == 0) {
1330
        rsp_buffer_push(rsp, 1); /* Erasure complete */
1331
    } else {
1332
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1333
        return;
1334
    }
1335
}
1336

1337
static void get_sel_info(IPMIBmcSim *ibs,
1338
                         uint8_t *cmd, unsigned int cmd_len,
1339
                         RspBuffer *rsp)
1340
{
1341
    unsigned int i, val;
1342

1343
    rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */
1344
    rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
1345
    rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
1346
    val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
1347
    rsp_buffer_push(rsp, val & 0xff);
1348
    rsp_buffer_push(rsp, (val >> 8) & 0xff);
1349
    for (i = 0; i < 4; i++) {
1350
        rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
1351
    }
1352
    for (i = 0; i < 4; i++) {
1353
        rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
1354
    }
1355
    /* Only support Reserve SEL */
1356
    rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
1357
}
1358

1359
static void get_fru_area_info(IPMIBmcSim *ibs,
1360
                         uint8_t *cmd, unsigned int cmd_len,
1361
                         RspBuffer *rsp)
1362
{
1363
    uint8_t fruid;
1364
    uint16_t fru_entry_size;
1365

1366
    fruid = cmd[2];
1367

1368
    if (fruid >= ibs->fru.nentries) {
1369
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1370
        return;
1371
    }
1372

1373
    fru_entry_size = ibs->fru.areasize;
1374

1375
    rsp_buffer_push(rsp, fru_entry_size & 0xff);
1376
    rsp_buffer_push(rsp, fru_entry_size >> 8 & 0xff);
1377
    rsp_buffer_push(rsp, 0x0);
1378
}
1379

1380
static void read_fru_data(IPMIBmcSim *ibs,
1381
                         uint8_t *cmd, unsigned int cmd_len,
1382
                         RspBuffer *rsp)
1383
{
1384
    uint8_t fruid;
1385
    uint16_t offset;
1386
    int i;
1387
    uint8_t *fru_entry;
1388
    unsigned int count;
1389

1390
    fruid = cmd[2];
1391
    offset = (cmd[3] | cmd[4] << 8);
1392

1393
    if (fruid >= ibs->fru.nentries) {
1394
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1395
        return;
1396
    }
1397

1398
    if (offset >= ibs->fru.areasize - 1) {
1399
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1400
        return;
1401
    }
1402

1403
    fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1404

1405
    count = MIN(cmd[5], ibs->fru.areasize - offset);
1406

1407
    rsp_buffer_push(rsp, count & 0xff);
1408
    for (i = 0; i < count; i++) {
1409
        rsp_buffer_push(rsp, fru_entry[offset + i]);
1410
    }
1411
}
1412

1413
static void write_fru_data(IPMIBmcSim *ibs,
1414
                         uint8_t *cmd, unsigned int cmd_len,
1415
                         RspBuffer *rsp)
1416
{
1417
    uint8_t fruid;
1418
    uint16_t offset;
1419
    uint8_t *fru_entry;
1420
    unsigned int count;
1421

1422
    fruid = cmd[2];
1423
    offset = (cmd[3] | cmd[4] << 8);
1424

1425
    if (fruid >= ibs->fru.nentries) {
1426
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1427
        return;
1428
    }
1429

1430
    if (offset >= ibs->fru.areasize - 1) {
1431
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1432
        return;
1433
    }
1434

1435
    fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
1436

1437
    count = MIN(cmd_len - 5, ibs->fru.areasize - offset);
1438

1439
    memcpy(fru_entry + offset, cmd + 5, count);
1440

1441
    rsp_buffer_push(rsp, count & 0xff);
1442
}
1443

1444
static void reserve_sel(IPMIBmcSim *ibs,
1445
                        uint8_t *cmd, unsigned int cmd_len,
1446
                        RspBuffer *rsp)
1447
{
1448
    rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
1449
    rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
1450
}
1451

1452
static void get_sel_entry(IPMIBmcSim *ibs,
1453
                          uint8_t *cmd, unsigned int cmd_len,
1454
                          RspBuffer *rsp)
1455
{
1456
    unsigned int val;
1457

1458
    if (cmd[6]) {
1459
        if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1460
            rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1461
            return;
1462
        }
1463
    }
1464
    if (ibs->sel.next_free == 0) {
1465
        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1466
        return;
1467
    }
1468
    if (cmd[6] > 15) {
1469
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1470
        return;
1471
    }
1472
    if (cmd[7] == 0xff) {
1473
        cmd[7] = 16;
1474
    } else if ((cmd[7] + cmd[6]) > 16) {
1475
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1476
        return;
1477
    } else {
1478
        cmd[7] += cmd[6];
1479
    }
1480

1481
    val = cmd[4] | (cmd[5] << 8);
1482
    if (val == 0xffff) {
1483
        val = ibs->sel.next_free - 1;
1484
    } else if (val >= ibs->sel.next_free) {
1485
        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1486
        return;
1487
    }
1488
    if ((val + 1) == ibs->sel.next_free) {
1489
        rsp_buffer_push(rsp, 0xff);
1490
        rsp_buffer_push(rsp, 0xff);
1491
    } else {
1492
        rsp_buffer_push(rsp, (val + 1) & 0xff);
1493
        rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
1494
    }
1495
    for (; cmd[6] < cmd[7]; cmd[6]++) {
1496
        rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
1497
    }
1498
}
1499

1500
static void add_sel_entry(IPMIBmcSim *ibs,
1501
                          uint8_t *cmd, unsigned int cmd_len,
1502
                          RspBuffer *rsp)
1503
{
1504
    if (sel_add_event(ibs, cmd + 2)) {
1505
        rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1506
        return;
1507
    }
1508
    /* sel_add_event fills in the record number. */
1509
    rsp_buffer_push(rsp, cmd[2]);
1510
    rsp_buffer_push(rsp, cmd[3]);
1511
}
1512

1513
static void clear_sel(IPMIBmcSim *ibs,
1514
                      uint8_t *cmd, unsigned int cmd_len,
1515
                      RspBuffer *rsp)
1516
{
1517
    if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
1518
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
1519
        return;
1520
    }
1521

1522
    if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
1523
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1524
        return;
1525
    }
1526
    if (cmd[7] == 0xaa) {
1527
        ibs->sel.next_free = 0;
1528
        ibs->sel.overflow = 0;
1529
        set_timestamp(ibs, ibs->sdr.last_clear);
1530
        rsp_buffer_push(rsp, 1); /* Erasure complete */
1531
        sel_inc_reservation(&ibs->sel);
1532
    } else if (cmd[7] == 0) {
1533
        rsp_buffer_push(rsp, 1); /* Erasure complete */
1534
    } else {
1535
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1536
        return;
1537
    }
1538
}
1539

1540
static void get_sel_time(IPMIBmcSim *ibs,
1541
                         uint8_t *cmd, unsigned int cmd_len,
1542
                         RspBuffer *rsp)
1543
{
1544
    uint32_t val;
1545
    struct ipmi_time now;
1546

1547
    ipmi_gettime(&now);
1548
    val = now.tv_sec + ibs->sel.time_offset;
1549
    rsp_buffer_push(rsp, val & 0xff);
1550
    rsp_buffer_push(rsp, (val >> 8) & 0xff);
1551
    rsp_buffer_push(rsp, (val >> 16) & 0xff);
1552
    rsp_buffer_push(rsp, (val >> 24) & 0xff);
1553
}
1554

1555
static void set_sel_time(IPMIBmcSim *ibs,
1556
                         uint8_t *cmd, unsigned int cmd_len,
1557
                         RspBuffer *rsp)
1558
{
1559
    uint32_t val;
1560
    struct ipmi_time now;
1561

1562
    val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
1563
    ipmi_gettime(&now);
1564
    ibs->sel.time_offset = now.tv_sec - ((long) val);
1565
}
1566

1567
static void platform_event_msg(IPMIBmcSim *ibs,
1568
                               uint8_t *cmd, unsigned int cmd_len,
1569
                               RspBuffer *rsp)
1570
{
1571
    uint8_t event[16];
1572

1573
    event[2] = 2; /* System event record */
1574
    event[7] = cmd[2]; /* Generator ID */
1575
    event[8] = 0;
1576
    event[9] = cmd[3]; /* EvMRev */
1577
    event[10] = cmd[4]; /* Sensor type */
1578
    event[11] = cmd[5]; /* Sensor number */
1579
    event[12] = cmd[6]; /* Event dir / Event type */
1580
    event[13] = cmd[7]; /* Event data 1 */
1581
    event[14] = cmd[8]; /* Event data 2 */
1582
    event[15] = cmd[9]; /* Event data 3 */
1583

1584
    if (sel_add_event(ibs, event)) {
1585
        rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
1586
    }
1587
}
1588

1589
static void set_sensor_evt_enable(IPMIBmcSim *ibs,
1590
                                  uint8_t *cmd, unsigned int cmd_len,
1591
                                  RspBuffer *rsp)
1592
{
1593
    IPMISensor *sens;
1594

1595
    if ((cmd[2] >= MAX_SENSORS) ||
1596
            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1597
        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1598
        return;
1599
    }
1600
    sens = ibs->sensors + cmd[2];
1601
    switch ((cmd[3] >> 4) & 0x3) {
1602
    case 0: /* Do not change */
1603
        break;
1604
    case 1: /* Enable bits */
1605
        if (cmd_len > 4) {
1606
            sens->assert_enable |= cmd[4];
1607
        }
1608
        if (cmd_len > 5) {
1609
            sens->assert_enable |= cmd[5] << 8;
1610
        }
1611
        if (cmd_len > 6) {
1612
            sens->deassert_enable |= cmd[6];
1613
        }
1614
        if (cmd_len > 7) {
1615
            sens->deassert_enable |= cmd[7] << 8;
1616
        }
1617
        break;
1618
    case 2: /* Disable bits */
1619
        if (cmd_len > 4) {
1620
            sens->assert_enable &= ~cmd[4];
1621
        }
1622
        if (cmd_len > 5) {
1623
            sens->assert_enable &= ~(cmd[5] << 8);
1624
        }
1625
        if (cmd_len > 6) {
1626
            sens->deassert_enable &= ~cmd[6];
1627
        }
1628
        if (cmd_len > 7) {
1629
            sens->deassert_enable &= ~(cmd[7] << 8);
1630
        }
1631
        break;
1632
    case 3:
1633
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1634
        return;
1635
    }
1636
    IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
1637
}
1638

1639
static void get_sensor_evt_enable(IPMIBmcSim *ibs,
1640
                                  uint8_t *cmd, unsigned int cmd_len,
1641
                                  RspBuffer *rsp)
1642
{
1643
    IPMISensor *sens;
1644

1645
    if ((cmd[2] >= MAX_SENSORS) ||
1646
        !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1647
        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1648
        return;
1649
    }
1650
    sens = ibs->sensors + cmd[2];
1651
    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1652
    rsp_buffer_push(rsp, sens->assert_enable & 0xff);
1653
    rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
1654
    rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
1655
    rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
1656
}
1657

1658
static void rearm_sensor_evts(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

1671
    if ((cmd[3] & 0x80) == 0) {
1672
        /* Just clear everything */
1673
        sens->states = 0;
1674
        return;
1675
    }
1676
}
1677

1678
static void get_sensor_evt_status(IPMIBmcSim *ibs,
1679
                                  uint8_t *cmd, unsigned int cmd_len,
1680
                                  RspBuffer *rsp)
1681
{
1682
    IPMISensor *sens;
1683

1684
    if ((cmd[2] >= MAX_SENSORS) ||
1685
        !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1686
        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1687
        return;
1688
    }
1689
    sens = ibs->sensors + cmd[2];
1690
    rsp_buffer_push(rsp, sens->reading);
1691
    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1692
    rsp_buffer_push(rsp, sens->assert_states & 0xff);
1693
    rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
1694
    rsp_buffer_push(rsp, sens->deassert_states & 0xff);
1695
    rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
1696
}
1697

1698
static void get_sensor_reading(IPMIBmcSim *ibs,
1699
                               uint8_t *cmd, unsigned int cmd_len,
1700
                               RspBuffer *rsp)
1701
{
1702
    IPMISensor *sens;
1703

1704
    if ((cmd[2] >= MAX_SENSORS) ||
1705
            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1706
        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1707
        return;
1708
    }
1709
    sens = ibs->sensors + cmd[2];
1710
    rsp_buffer_push(rsp, sens->reading);
1711
    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
1712
    rsp_buffer_push(rsp, sens->states & 0xff);
1713
    if (IPMI_SENSOR_IS_DISCRETE(sens)) {
1714
        rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
1715
    }
1716
}
1717

1718
static void set_sensor_type(IPMIBmcSim *ibs,
1719
                            uint8_t *cmd, unsigned int cmd_len,
1720
                            RspBuffer *rsp)
1721
{
1722
    IPMISensor *sens;
1723

1724

1725
    if ((cmd[2] >= MAX_SENSORS) ||
1726
            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1727
        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1728
        return;
1729
    }
1730
    sens = ibs->sensors + cmd[2];
1731
    sens->sensor_type = cmd[3];
1732
    sens->evt_reading_type_code = cmd[4] & 0x7f;
1733
}
1734

1735
static void get_sensor_type(IPMIBmcSim *ibs,
1736
                            uint8_t *cmd, unsigned int cmd_len,
1737
                            RspBuffer *rsp)
1738
{
1739
    IPMISensor *sens;
1740

1741

1742
    if ((cmd[2] >= MAX_SENSORS) ||
1743
            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1744
        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1745
        return;
1746
    }
1747
    sens = ibs->sensors + cmd[2];
1748
    rsp_buffer_push(rsp, sens->sensor_type);
1749
    rsp_buffer_push(rsp, sens->evt_reading_type_code);
1750
}
1751

1752
/*
1753
 * bytes   parameter
1754
 *    1    sensor number
1755
 *    2    operation (see below for bits meaning)
1756
 *    3    sensor reading
1757
 *  4:5    assertion states (optional)
1758
 *  6:7    deassertion states (optional)
1759
 *  8:10   event data 1,2,3 (optional)
1760
 */
1761
static void set_sensor_reading(IPMIBmcSim *ibs,
1762
                               uint8_t *cmd, unsigned int cmd_len,
1763
                               RspBuffer *rsp)
1764
{
1765
    IPMISensor *sens;
1766
    uint8_t evd1 = 0;
1767
    uint8_t evd2 = 0;
1768
    uint8_t evd3 = 0;
1769
    uint8_t new_reading = 0;
1770
    uint16_t new_assert_states = 0;
1771
    uint16_t new_deassert_states = 0;
1772
    bool change_reading = false;
1773
    bool change_assert = false;
1774
    bool change_deassert = false;
1775
    enum {
1776
        SENSOR_GEN_EVENT_NONE,
1777
        SENSOR_GEN_EVENT_DATA,
1778
        SENSOR_GEN_EVENT_BMC,
1779
    } do_gen_event = SENSOR_GEN_EVENT_NONE;
1780

1781
    if ((cmd[2] >= MAX_SENSORS) ||
1782
            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1783
        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1784
        return;
1785
    }
1786

1787
    sens = ibs->sensors + cmd[2];
1788

1789
    /* [1:0] Sensor Reading operation */
1790
    switch ((cmd[3]) & 0x3) {
1791
    case 0: /* Do not change */
1792
        break;
1793
    case 1: /* write given value to sensor reading byte */
1794
        new_reading = cmd[4];
1795
        if (sens->reading != new_reading) {
1796
            change_reading = true;
1797
        }
1798
        break;
1799
    case 2:
1800
    case 3:
1801
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1802
        return;
1803
    }
1804

1805
    /* [3:2] Deassertion bits operation */
1806
    switch ((cmd[3] >> 2) & 0x3) {
1807
    case 0: /* Do not change */
1808
        break;
1809
    case 1: /* write given value */
1810
        if (cmd_len > 7) {
1811
            new_deassert_states = cmd[7];
1812
            change_deassert = true;
1813
        }
1814
        if (cmd_len > 8) {
1815
            new_deassert_states |= (cmd[8] << 8);
1816
        }
1817
        break;
1818

1819
    case 2: /* mask on */
1820
        if (cmd_len > 7) {
1821
            new_deassert_states = (sens->deassert_states | cmd[7]);
1822
            change_deassert = true;
1823
        }
1824
        if (cmd_len > 8) {
1825
            new_deassert_states |= (sens->deassert_states | (cmd[8] << 8));
1826
        }
1827
        break;
1828

1829
    case 3: /* mask off */
1830
        if (cmd_len > 7) {
1831
            new_deassert_states = (sens->deassert_states & cmd[7]);
1832
            change_deassert = true;
1833
        }
1834
        if (cmd_len > 8) {
1835
            new_deassert_states |= (sens->deassert_states & (cmd[8] << 8));
1836
        }
1837
        break;
1838
    }
1839

1840
    if (change_deassert && (new_deassert_states == sens->deassert_states)) {
1841
        change_deassert = false;
1842
    }
1843

1844
    /* [5:4] Assertion bits operation */
1845
    switch ((cmd[3] >> 4) & 0x3) {
1846
    case 0: /* Do not change */
1847
        break;
1848
    case 1: /* write given value */
1849
        if (cmd_len > 5) {
1850
            new_assert_states = cmd[5];
1851
            change_assert = true;
1852
        }
1853
        if (cmd_len > 6) {
1854
            new_assert_states |= (cmd[6] << 8);
1855
        }
1856
        break;
1857

1858
    case 2: /* mask on */
1859
        if (cmd_len > 5) {
1860
            new_assert_states = (sens->assert_states | cmd[5]);
1861
            change_assert = true;
1862
        }
1863
        if (cmd_len > 6) {
1864
            new_assert_states |= (sens->assert_states | (cmd[6] << 8));
1865
        }
1866
        break;
1867

1868
    case 3: /* mask off */
1869
        if (cmd_len > 5) {
1870
            new_assert_states = (sens->assert_states & cmd[5]);
1871
            change_assert = true;
1872
        }
1873
        if (cmd_len > 6) {
1874
            new_assert_states |= (sens->assert_states & (cmd[6] << 8));
1875
        }
1876
        break;
1877
    }
1878

1879
    if (change_assert && (new_assert_states == sens->assert_states)) {
1880
        change_assert = false;
1881
    }
1882

1883
    if (cmd_len > 9) {
1884
        evd1 = cmd[9];
1885
    }
1886
    if (cmd_len > 10) {
1887
        evd2 = cmd[10];
1888
    }
1889
    if (cmd_len > 11) {
1890
        evd3 = cmd[11];
1891
    }
1892

1893
    /* [7:6] Event Data Bytes operation */
1894
    switch ((cmd[3] >> 6) & 0x3) {
1895
    case 0: /*
1896
             * Don’t use Event Data bytes from this command. BMC will
1897
             * generate it's own Event Data bytes based on its sensor
1898
             * implementation.
1899
             */
1900
        evd1 = evd2 = evd3 = 0x0;
1901
        do_gen_event = SENSOR_GEN_EVENT_BMC;
1902
        break;
1903
    case 1: /*
1904
             * Write given values to event data bytes including bits
1905
             * [3:0] Event Data 1.
1906
             */
1907
        do_gen_event = SENSOR_GEN_EVENT_DATA;
1908
        break;
1909
    case 2: /*
1910
             * Write given values to event data bytes excluding bits
1911
             * [3:0] Event Data 1.
1912
             */
1913
        evd1 &= 0xf0;
1914
        do_gen_event = SENSOR_GEN_EVENT_DATA;
1915
        break;
1916
    case 3:
1917
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1918
        return;
1919
    }
1920

1921
    /*
1922
     * Event Data Bytes operation and parameter are inconsistent. The
1923
     * Specs are not clear on that topic but generating an error seems
1924
     * correct.
1925
     */
1926
    if (do_gen_event == SENSOR_GEN_EVENT_DATA && cmd_len < 10) {
1927
        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1928
        return;
1929
    }
1930

1931
    /* commit values */
1932
    if (change_reading) {
1933
        sens->reading = new_reading;
1934
    }
1935

1936
    if (change_assert) {
1937
        sens->assert_states = new_assert_states;
1938
    }
1939

1940
    if (change_deassert) {
1941
        sens->deassert_states = new_deassert_states;
1942
    }
1943

1944
    /* TODO: handle threshold sensor */
1945
    if (!IPMI_SENSOR_IS_DISCRETE(sens)) {
1946
        return;
1947
    }
1948

1949
    switch (do_gen_event) {
1950
    case SENSOR_GEN_EVENT_DATA: {
1951
        unsigned int bit = evd1 & 0xf;
1952
        uint16_t mask = (1 << bit);
1953

1954
        if (sens->assert_states & mask & sens->assert_enable) {
1955
            gen_event(ibs, cmd[2], 0, evd1, evd2, evd3);
1956
        }
1957

1958
        if (sens->deassert_states & mask & sens->deassert_enable) {
1959
            gen_event(ibs, cmd[2], 1, evd1, evd2, evd3);
1960
        }
1961
        break;
1962
    }
1963
    case SENSOR_GEN_EVENT_BMC:
1964
        /*
1965
         * TODO: generate event and event data bytes depending on the
1966
         * sensor
1967
         */
1968
        break;
1969
    case SENSOR_GEN_EVENT_NONE:
1970
        break;
1971
    }
1972
}
1973

1974
static const IPMICmdHandler chassis_cmds[] = {
1975
    [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
1976
    [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
1977
    [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
1978
    [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
1979
};
1980
static const IPMINetfn chassis_netfn = {
1981
    .cmd_nums = ARRAY_SIZE(chassis_cmds),
1982
    .cmd_handlers = chassis_cmds
1983
};
1984

1985
static const IPMICmdHandler sensor_event_cmds[] = {
1986
    [IPMI_CMD_PLATFORM_EVENT_MSG] = { platform_event_msg, 10 },
1987
    [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
1988
    [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
1989
    [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
1990
    [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
1991
    [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
1992
    [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
1993
    [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
1994
    [IPMI_CMD_SET_SENSOR_READING] = { set_sensor_reading, 5 },
1995
};
1996
static const IPMINetfn sensor_event_netfn = {
1997
    .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
1998
    .cmd_handlers = sensor_event_cmds
1999
};
2000

2001
static const IPMICmdHandler app_cmds[] = {
2002
    [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
2003
    [IPMI_CMD_COLD_RESET] = { cold_reset },
2004
    [IPMI_CMD_WARM_RESET] = { warm_reset },
2005
    [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
2006
    [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
2007
    [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
2008
    [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
2009
    [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
2010
    [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
2011
    [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
2012
    [IPMI_CMD_GET_MSG] = { get_msg },
2013
    [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
2014
    [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
2015
    [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
2016
    [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
2017
    [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
2018
};
2019
static const IPMINetfn app_netfn = {
2020
    .cmd_nums = ARRAY_SIZE(app_cmds),
2021
    .cmd_handlers = app_cmds
2022
};
2023

2024
static const IPMICmdHandler storage_cmds[] = {
2025
    [IPMI_CMD_GET_FRU_AREA_INFO] = { get_fru_area_info, 3 },
2026
    [IPMI_CMD_READ_FRU_DATA] = { read_fru_data, 5 },
2027
    [IPMI_CMD_WRITE_FRU_DATA] = { write_fru_data, 5 },
2028
    [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
2029
    [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
2030
    [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
2031
    [IPMI_CMD_ADD_SDR] = { add_sdr },
2032
    [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
2033
    [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
2034
    [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
2035
    [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
2036
    [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
2037
    [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
2038
    [IPMI_CMD_GET_SEL_TIME] = { get_sel_time },
2039
    [IPMI_CMD_SET_SEL_TIME] = { set_sel_time, 6 },
2040
};
2041

2042
static const IPMINetfn storage_netfn = {
2043
    .cmd_nums = ARRAY_SIZE(storage_cmds),
2044
    .cmd_handlers = storage_cmds
2045
};
2046

2047
static void register_cmds(IPMIBmcSim *s)
2048
{
2049
    ipmi_sim_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
2050
    ipmi_sim_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
2051
    ipmi_sim_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
2052
    ipmi_sim_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
2053
}
2054

2055
static uint8_t init_sdrs[] = {
2056
    /* Watchdog device */
2057
    0x00, 0x00, 0x51, 0x02,   35, 0x20, 0x00, 0x00,
2058
    0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
2059
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2060
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
2061
    'W',  'a',  't',  'c',  'h',  'd',  'o',  'g',
2062
};
2063

2064
static void ipmi_sdr_init(IPMIBmcSim *ibs)
2065
{
2066
    unsigned int i;
2067
    int len;
2068
    size_t sdrs_size;
2069
    uint8_t *sdrs;
2070

2071
    sdrs_size = sizeof(init_sdrs);
2072
    sdrs = init_sdrs;
2073
    if (ibs->sdr_filename &&
2074
        !g_file_get_contents(ibs->sdr_filename, (gchar **) &sdrs, &sdrs_size,
2075
                             NULL)) {
2076
        error_report("failed to load sdr file '%s'", ibs->sdr_filename);
2077
        sdrs_size = sizeof(init_sdrs);
2078
        sdrs = init_sdrs;
2079
    }
2080

2081
    for (i = 0; i < sdrs_size; i += len) {
2082
        struct ipmi_sdr_header *sdrh;
2083

2084
        if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
2085
            error_report("Problem with recid 0x%4.4x", i);
2086
            break;
2087
        }
2088
        sdrh = (struct ipmi_sdr_header *) &sdrs[i];
2089
        len = ipmi_sdr_length(sdrh);
2090
        if (i + len > sdrs_size) {
2091
            error_report("Problem with recid 0x%4.4x", i);
2092
            break;
2093
        }
2094
        sdr_add_entry(ibs, sdrh, len, NULL);
2095
    }
2096

2097
    if (sdrs != init_sdrs) {
2098
        g_free(sdrs);
2099
    }
2100
}
2101

2102
static const VMStateDescription vmstate_ipmi_sim = {
2103
    .name = TYPE_IPMI_BMC_SIMULATOR,
2104
    .version_id = 1,
2105
    .minimum_version_id = 1,
2106
    .fields = (const VMStateField[]) {
2107
        VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
2108
        VMSTATE_UINT8(msg_flags, IPMIBmcSim),
2109
        VMSTATE_BOOL(watchdog_initialized, IPMIBmcSim),
2110
        VMSTATE_UINT8(watchdog_use, IPMIBmcSim),
2111
        VMSTATE_UINT8(watchdog_action, IPMIBmcSim),
2112
        VMSTATE_UINT8(watchdog_pretimeout, IPMIBmcSim),
2113
        VMSTATE_UINT8(watchdog_expired, IPMIBmcSim),
2114
        VMSTATE_UINT16(watchdog_timeout, IPMIBmcSim),
2115
        VMSTATE_BOOL(watchdog_running, IPMIBmcSim),
2116
        VMSTATE_BOOL(watchdog_preaction_ran, IPMIBmcSim),
2117
        VMSTATE_INT64(watchdog_expiry, IPMIBmcSim),
2118
        VMSTATE_UINT8_ARRAY(evtbuf, IPMIBmcSim, 16),
2119
        VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].status, IPMIBmcSim),
2120
        VMSTATE_UINT8(sensors[IPMI_WATCHDOG_SENSOR].reading, IPMIBmcSim),
2121
        VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].states, IPMIBmcSim),
2122
        VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_states, IPMIBmcSim),
2123
        VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
2124
                       IPMIBmcSim),
2125
        VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
2126
        VMSTATE_END_OF_LIST()
2127
    }
2128
};
2129

2130
static void ipmi_fru_init(IPMIFru *fru)
2131
{
2132
    int fsize;
2133
    int size = 0;
2134

2135
    if (!fru->filename) {
2136
        goto out;
2137
    }
2138

2139
    fsize = get_image_size(fru->filename);
2140
    if (fsize > 0) {
2141
        size = QEMU_ALIGN_UP(fsize, fru->areasize);
2142
        fru->data = g_malloc0(size);
2143
        if (load_image_size(fru->filename, fru->data, fsize) != fsize) {
2144
            error_report("Could not load file '%s'", fru->filename);
2145
            g_free(fru->data);
2146
            fru->data = NULL;
2147
        }
2148
    }
2149

2150
out:
2151
    if (!fru->data) {
2152
        /* give one default FRU */
2153
        size = fru->areasize;
2154
        fru->data = g_malloc0(size);
2155
    }
2156

2157
    fru->nentries = size / fru->areasize;
2158
}
2159

2160
static void ipmi_sim_realize(DeviceState *dev, Error **errp)
2161
{
2162
    IPMIBmc *b = IPMI_BMC(dev);
2163
    unsigned int i;
2164
    IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
2165

2166
    QTAILQ_INIT(&ibs->rcvbufs);
2167

2168
    ibs->bmc_global_enables = (1 << IPMI_BMC_EVENT_LOG_BIT);
2169
    ibs->device_id = 0x20;
2170
    ibs->ipmi_version = 0x02; /* IPMI 2.0 */
2171
    ibs->restart_cause = 0;
2172
    for (i = 0; i < 4; i++) {
2173
        ibs->sel.last_addition[i] = 0xff;
2174
        ibs->sel.last_clear[i] = 0xff;
2175
        ibs->sdr.last_addition[i] = 0xff;
2176
        ibs->sdr.last_clear[i] = 0xff;
2177
    }
2178

2179
    ipmi_sdr_init(ibs);
2180

2181
    ipmi_fru_init(&ibs->fru);
2182

2183
    ibs->acpi_power_state[0] = 0;
2184
    ibs->acpi_power_state[1] = 0;
2185

2186
    ipmi_init_sensors_from_sdrs(ibs);
2187
    register_cmds(ibs);
2188

2189
    ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
2190

2191
    vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
2192
}
2193

2194
static Property ipmi_sim_properties[] = {
2195
    DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim, fru.areasize, 1024),
2196
    DEFINE_PROP_STRING("frudatafile", IPMIBmcSim, fru.filename),
2197
    DEFINE_PROP_STRING("sdrfile", IPMIBmcSim, sdr_filename),
2198
    DEFINE_PROP_UINT8("device_id", IPMIBmcSim, device_id, 0x20),
2199
    DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim, ipmi_version, 0x02),
2200
    DEFINE_PROP_UINT8("device_rev", IPMIBmcSim, device_rev, 0),
2201
    DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim, fwrev1, 0),
2202
    DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim, fwrev2, 0),
2203
    DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim, mfg_id, 0),
2204
    DEFINE_PROP_UINT16("product_id", IPMIBmcSim, product_id, 0),
2205
    DEFINE_PROP_UUID_NODEFAULT("guid", IPMIBmcSim, uuid),
2206
    DEFINE_PROP_END_OF_LIST(),
2207
};
2208

2209
static void ipmi_sim_class_init(ObjectClass *oc, void *data)
2210
{
2211
    DeviceClass *dc = DEVICE_CLASS(oc);
2212
    IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
2213

2214
    dc->hotpluggable = false;
2215
    dc->realize = ipmi_sim_realize;
2216
    device_class_set_props(dc, ipmi_sim_properties);
2217
    bk->handle_command = ipmi_sim_handle_command;
2218
}
2219

2220
static const TypeInfo ipmi_sim_type = {
2221
    .name          = TYPE_IPMI_BMC_SIMULATOR,
2222
    .parent        = TYPE_IPMI_BMC,
2223
    .instance_size = sizeof(IPMIBmcSim),
2224
    .class_init    = ipmi_sim_class_init,
2225
};
2226

2227
static void ipmi_sim_register_types(void)
2228
{
2229
    type_register_static(&ipmi_sim_type);
2230
}
2231

2232
type_init(ipmi_sim_register_types)
2233

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.