qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

ipmi.h (9099B)


      1 /*
      2  * IPMI base class
      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 #ifndef HW_IPMI_H
     26 #define HW_IPMI_H
     27 
     28 #include "exec/memory.h"
     29 #include "hw/qdev-core.h"
     30 #include "qom/object.h"
     31 
     32 #define MAX_IPMI_MSG_SIZE 300
     33 
     34 enum ipmi_op {
     35     IPMI_RESET_CHASSIS,
     36     IPMI_POWEROFF_CHASSIS,
     37     IPMI_POWERON_CHASSIS,
     38     IPMI_POWERCYCLE_CHASSIS,
     39     IPMI_PULSE_DIAG_IRQ,
     40     IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP,
     41     IPMI_SEND_NMI
     42 };
     43 
     44 #define IPMI_CC_INVALID_CMD                              0xc1
     45 #define IPMI_CC_COMMAND_INVALID_FOR_LUN                  0xc2
     46 #define IPMI_CC_TIMEOUT                                  0xc3
     47 #define IPMI_CC_OUT_OF_SPACE                             0xc4
     48 #define IPMI_CC_INVALID_RESERVATION                      0xc5
     49 #define IPMI_CC_REQUEST_DATA_TRUNCATED                   0xc6
     50 #define IPMI_CC_REQUEST_DATA_LENGTH_INVALID              0xc7
     51 #define IPMI_CC_PARM_OUT_OF_RANGE                        0xc9
     52 #define IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES              0xca
     53 #define IPMI_CC_REQ_ENTRY_NOT_PRESENT                    0xcb
     54 #define IPMI_CC_INVALID_DATA_FIELD                       0xcc
     55 #define IPMI_CC_BMC_INIT_IN_PROGRESS                     0xd2
     56 #define IPMI_CC_COMMAND_NOT_SUPPORTED                    0xd5
     57 #define IPMI_CC_UNSPECIFIED                              0xff
     58 
     59 #define IPMI_NETFN_APP                0x06
     60 #define IPMI_NETFN_OEM                0x3a
     61 
     62 #define IPMI_DEBUG 1
     63 
     64 /* Specified in the SMBIOS spec. */
     65 #define IPMI_SMBIOS_KCS         0x01
     66 #define IPMI_SMBIOS_SMIC        0x02
     67 #define IPMI_SMBIOS_BT          0x03
     68 #define IPMI_SMBIOS_SSIF        0x04
     69 
     70 /*
     71  * Used for transferring information to interfaces that add
     72  * entries to firmware tables.
     73  */
     74 typedef struct IPMIFwInfo {
     75     const char *interface_name;
     76     int interface_type;
     77     uint8_t ipmi_spec_major_revision;
     78     uint8_t ipmi_spec_minor_revision;
     79     uint8_t i2c_slave_address;
     80     uint32_t uuid;
     81 
     82     uint64_t base_address;
     83     uint64_t register_length;
     84     uint8_t register_spacing;
     85     enum {
     86         IPMI_MEMSPACE_IO,
     87         IPMI_MEMSPACE_MEM32,
     88         IPMI_MEMSPACE_MEM64,
     89         IPMI_MEMSPACE_SMBUS
     90     } memspace;
     91 
     92     int interrupt_number;
     93     enum {
     94         IPMI_LEVEL_IRQ,
     95         IPMI_EDGE_IRQ
     96     } irq_type;
     97 } IPMIFwInfo;
     98 
     99 /*
    100  * Called by each instantiated IPMI interface device to get it's uuid.
    101  */
    102 uint32_t ipmi_next_uuid(void);
    103 
    104 /* IPMI Interface types (KCS, SMIC, BT) are prefixed with this */
    105 #define TYPE_IPMI_INTERFACE_PREFIX "ipmi-interface-"
    106 
    107 /*
    108  * An IPMI Interface, the interface for talking between the target
    109  * and the BMC.
    110  */
    111 #define TYPE_IPMI_INTERFACE "ipmi-interface"
    112 #define IPMI_INTERFACE(obj) \
    113      INTERFACE_CHECK(IPMIInterface, (obj), TYPE_IPMI_INTERFACE)
    114 typedef struct IPMIInterfaceClass IPMIInterfaceClass;
    115 DECLARE_CLASS_CHECKERS(IPMIInterfaceClass, IPMI_INTERFACE,
    116                        TYPE_IPMI_INTERFACE)
    117 
    118 typedef struct IPMIInterface IPMIInterface;
    119 
    120 struct IPMIInterfaceClass {
    121     InterfaceClass parent;
    122 
    123     /*
    124      * min_size is the requested I/O size and must be a power of 2.
    125      * This is so PCI (or other busses) can request a bigger range.
    126      * Use 0 for the default.
    127      */
    128     void (*init)(struct IPMIInterface *s, unsigned int min_size, Error **errp);
    129 
    130     /*
    131      * Perform various operations on the hardware.  If checkonly is
    132      * true, it will return if the operation can be performed, but it
    133      * will not do the operation.
    134      */
    135     int (*do_hw_op)(struct IPMIInterface *s, enum ipmi_op op, int checkonly);
    136 
    137     /*
    138      * Enable/disable irqs on the interface when the BMC requests this.
    139      */
    140     void (*set_irq_enable)(struct IPMIInterface *s, int val);
    141 
    142     /*
    143      * Handle an event that occurred on the interface, generally the.
    144      * target writing to a register.
    145      */
    146     void (*handle_if_event)(struct IPMIInterface *s);
    147 
    148     /*
    149      * The interfaces use this to perform certain ops
    150      */
    151     void (*set_atn)(struct IPMIInterface *s, int val, int irq);
    152 
    153     /*
    154      * Got an IPMI warm/cold reset.
    155      */
    156     void (*reset)(struct IPMIInterface *s, bool is_cold);
    157 
    158     /*
    159      * Handle a response from the bmc.
    160      */
    161     void (*handle_rsp)(struct IPMIInterface *s, uint8_t msg_id,
    162                        unsigned char *rsp, unsigned int rsp_len);
    163 
    164     /*
    165      * Set by the owner to hold the backend data for the interface.
    166      */
    167     void *(*get_backend_data)(struct IPMIInterface *s);
    168 
    169     /*
    170      * Return the firmware info for a device.
    171      */
    172     void (*get_fwinfo)(struct IPMIInterface *s, IPMIFwInfo *info);
    173 };
    174 
    175 /*
    176  * Define a BMC simulator (or perhaps a connection to a real BMC)
    177  */
    178 #define TYPE_IPMI_BMC "ipmi-bmc"
    179 OBJECT_DECLARE_TYPE(IPMIBmc, IPMIBmcClass,
    180                     IPMI_BMC)
    181 
    182 struct IPMIBmc {
    183     DeviceState parent;
    184 
    185     uint8_t slave_addr;
    186 
    187     IPMIInterface *intf;
    188 };
    189 
    190 struct IPMIBmcClass {
    191     DeviceClass parent;
    192 
    193     /* Called when the system resets to report to the bmc. */
    194     void (*handle_reset)(struct IPMIBmc *s);
    195 
    196     /*
    197      * Handle a command to the bmc.
    198      */
    199     void (*handle_command)(struct IPMIBmc *s,
    200                            uint8_t *cmd, unsigned int cmd_len,
    201                            unsigned int max_cmd_len,
    202                            uint8_t msg_id);
    203 };
    204 
    205 /*
    206  * Add a link property to obj that points to a BMC.
    207  */
    208 void ipmi_bmc_find_and_link(Object *obj, Object **bmc);
    209 
    210 #ifdef IPMI_DEBUG
    211 #define ipmi_debug(fs, ...) \
    212     fprintf(stderr, "IPMI (%s): " fs, __func__, ##__VA_ARGS__)
    213 #else
    214 #define ipmi_debug(fs, ...)
    215 #endif
    216 
    217 struct ipmi_sdr_header {
    218     uint8_t  rec_id[2];
    219     uint8_t  sdr_version;               /* 0x51 */
    220     uint8_t  rec_type;
    221     uint8_t  rec_length;
    222 };
    223 #define IPMI_SDR_HEADER_SIZE     sizeof(struct ipmi_sdr_header)
    224 
    225 #define ipmi_sdr_recid(sdr) ((sdr)->rec_id[0] | ((sdr)->rec_id[1] << 8))
    226 #define ipmi_sdr_length(sdr) ((sdr)->rec_length + IPMI_SDR_HEADER_SIZE)
    227 
    228 /*
    229  * 43.2 SDR Type 02h. Compact Sensor Record
    230  */
    231 #define IPMI_SDR_COMPACT_TYPE    2
    232 
    233 struct ipmi_sdr_compact {
    234     struct ipmi_sdr_header header;
    235 
    236     uint8_t  sensor_owner_id;
    237     uint8_t  sensor_owner_lun;
    238     uint8_t  sensor_owner_number;       /* byte 8 */
    239     uint8_t  entity_id;
    240     uint8_t  entity_instance;
    241     uint8_t  sensor_init;
    242     uint8_t  sensor_caps;
    243     uint8_t  sensor_type;
    244     uint8_t  reading_type;
    245     uint8_t  assert_mask[2];            /* byte 16 */
    246     uint8_t  deassert_mask[2];
    247     uint8_t  discrete_mask[2];
    248     uint8_t  sensor_unit1;
    249     uint8_t  sensor_unit2;
    250     uint8_t  sensor_unit3;
    251     uint8_t  sensor_direction[2];       /* byte 24 */
    252     uint8_t  positive_threshold;
    253     uint8_t  negative_threshold;
    254     uint8_t  reserved[3];
    255     uint8_t  oem;
    256     uint8_t  id_str_len;                /* byte 32 */
    257     uint8_t  id_string[16];
    258 };
    259 
    260 typedef uint8_t ipmi_sdr_compact_buffer[sizeof(struct ipmi_sdr_compact)];
    261 
    262 int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
    263                       const struct ipmi_sdr_compact **sdr, uint16_t *nextrec);
    264 void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log);
    265 
    266 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
    267 OBJECT_DECLARE_SIMPLE_TYPE(IPMIBmcSim, IPMI_BMC_SIMULATOR)
    268 
    269 
    270 typedef struct RspBuffer {
    271     uint8_t buffer[MAX_IPMI_MSG_SIZE];
    272     unsigned int len;
    273 } RspBuffer;
    274 
    275 static inline void rsp_buffer_set_error(RspBuffer *rsp, uint8_t byte)
    276 {
    277     rsp->buffer[2] = byte;
    278 }
    279 
    280 /* Add a byte to the response. */
    281 static inline void rsp_buffer_push(RspBuffer *rsp, uint8_t byte)
    282 {
    283     if (rsp->len >= sizeof(rsp->buffer)) {
    284         rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
    285         return;
    286     }
    287     rsp->buffer[rsp->len++] = byte;
    288 }
    289 
    290 typedef struct IPMICmdHandler {
    291     void (*cmd_handler)(IPMIBmcSim *s,
    292                         uint8_t *cmd, unsigned int cmd_len,
    293                         RspBuffer *rsp);
    294     unsigned int cmd_len_min;
    295 } IPMICmdHandler;
    296 
    297 typedef struct IPMINetfn {
    298     unsigned int cmd_nums;
    299     const IPMICmdHandler *cmd_handlers;
    300 } IPMINetfn;
    301 
    302 int ipmi_sim_register_netfn(IPMIBmcSim *s, unsigned int netfn,
    303                             const IPMINetfn *netfnd);
    304 
    305 #endif