ipmi_bmc_sim.c (68728B)
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. */ 105struct ipmi_time { 106 long tv_sec; 107 long tv_nsec; 108}; 109 110#define MAX_SEL_SIZE 128 111 112typedef 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 124typedef 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 134typedef struct IPMIFru { 135 char *filename; 136 unsigned int nentries; 137 uint16_t areasize; 138 uint8_t *data; 139} IPMIFru; 140 141typedef 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 174typedef struct IPMIRcvBufEntry { 175 QTAILQ_ENTRY(IPMIRcvBufEntry) entry; 176 uint8_t len; 177 uint8_t buf[MAX_IPMI_MSG_SIZE]; 178} IPMIRcvBufEntry; 179 180struct 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 268static 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 280static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs); 281 282static 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 291static int64_t ipmi_getmonotime(void) 292{ 293 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 294} 295 296static void ipmi_timeout(void *opaque) 297{ 298 IPMIBmcSim *ibs = opaque; 299 300 ipmi_sim_handle_timeout(ibs); 301} 302 303static 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 316static void sdr_inc_reservation(IPMISdr *sdr) 317{ 318 sdr->reservation++; 319 if (sdr->reservation == 0) { 320 sdr->reservation = 1; 321 } 322} 323 324static 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 359static 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 387int 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 403static 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. */ 412static 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 435static 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 442static 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 451void 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} 475static 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 514static 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 553static 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 597int 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 607static 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 629static 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 641static 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 698static 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 766static 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 777static 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 787static 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 820static 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 829static 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 846static 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 860static 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 875static 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} 886static 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 894static 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 902static 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 924static 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 931static 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 938static 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 949static 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 956static 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 975static 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 999out: 1000 return; 1001} 1002 1003static unsigned char 1004ipmb_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 1013static 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 1099static 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 1118static 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 1129static 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 1200static 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 1222static 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 1243static 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 1251static 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 1295static 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 1310static 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 1337static 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 1359static 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 1380static 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 1413static 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 1444static 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 1452static 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 1500static 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 1513static 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 1540static 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 1555static 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 1567static 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 1589static 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 1639static 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 1658static 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 1678static 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 1698static 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 1718static 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 1735static 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 */ 1761static 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 1974static 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}; 1980static const IPMINetfn chassis_netfn = { 1981 .cmd_nums = ARRAY_SIZE(chassis_cmds), 1982 .cmd_handlers = chassis_cmds 1983}; 1984 1985static 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}; 1996static const IPMINetfn sensor_event_netfn = { 1997 .cmd_nums = ARRAY_SIZE(sensor_event_cmds), 1998 .cmd_handlers = sensor_event_cmds 1999}; 2000 2001static 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}; 2019static const IPMINetfn app_netfn = { 2020 .cmd_nums = ARRAY_SIZE(app_cmds), 2021 .cmd_handlers = app_cmds 2022}; 2023 2024static 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 2042static const IPMINetfn storage_netfn = { 2043 .cmd_nums = ARRAY_SIZE(storage_cmds), 2044 .cmd_handlers = storage_cmds 2045}; 2046 2047static 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 2055static 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 2064static 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 2102static const VMStateDescription vmstate_ipmi_sim = { 2103 .name = TYPE_IPMI_BMC_SIMULATOR, 2104 .version_id = 1, 2105 .minimum_version_id = 1, 2106 .fields = (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 2130static 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 2150out: 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 2160static 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 2194static 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 2209static 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 2220static 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 2227static void ipmi_sim_register_types(void) 2228{ 2229 type_register_static(&ipmi_sim_type); 2230} 2231 2232type_init(ipmi_sim_register_types)