Commit ed8da05c authored by Cédric Le Goater's avatar Cédric Le Goater Committed by David Gibson
Browse files

ipmi: Add support to customize OEM functions



The routine ipmi_register_oem_netfn() lets external modules register
command handlers for OEM functions. Required for the PowerNV machine.

Cc: Corey Minyard <cminyard@mvista.com>
Reviewed-by: default avatarCorey Minyard <cminyard@mvista.com>
Signed-off-by: default avatarCédric Le Goater <clg@kaod.org>
Message-Id: <20191028070027.22752-2-clg@kaod.org>
Acked-by: default avatarCorey Minyard <cminyard@mvista.com>
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
parent 1c27b252
Loading
Loading
Loading
Loading
+6 −44
Original line number Diff line number Diff line
@@ -167,32 +167,14 @@ typedef struct IPMISensor {
#define MAX_SENSORS 20
#define IPMI_WATCHDOG_SENSOR 0

typedef struct IPMIBmcSim IPMIBmcSim;
typedef struct RspBuffer RspBuffer;

#define MAX_NETFNS 64

typedef struct IPMICmdHandler {
    void (*cmd_handler)(IPMIBmcSim *s,
                        uint8_t *cmd, unsigned int cmd_len,
                        RspBuffer *rsp);
    unsigned int cmd_len_min;
} IPMICmdHandler;

typedef struct IPMINetfn {
    unsigned int cmd_nums;
    const IPMICmdHandler *cmd_handlers;
} IPMINetfn;

typedef struct IPMIRcvBufEntry {
    QTAILQ_ENTRY(IPMIRcvBufEntry) entry;
    uint8_t len;
    uint8_t buf[MAX_IPMI_MSG_SIZE];
} IPMIRcvBufEntry;

#define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
#define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
                                        TYPE_IPMI_BMC_SIMULATOR)
struct IPMIBmcSim {
    IPMIBmc parent;

@@ -279,28 +261,8 @@ struct IPMIBmcSim {
#define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN      2
#define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE     3

struct RspBuffer {
    uint8_t buffer[MAX_IPMI_MSG_SIZE];
    unsigned int len;
};

#define RSP_BUFFER_INITIALIZER { }

static inline void rsp_buffer_set_error(RspBuffer *rsp, uint8_t byte)
{
    rsp->buffer[2] = byte;
}

/* Add a byte to the response. */
static inline void rsp_buffer_push(RspBuffer *rsp, uint8_t byte)
{
    if (rsp->len >= sizeof(rsp->buffer)) {
        rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
        return;
    }
    rsp->buffer[rsp->len++] = byte;
}

static inline void rsp_buffer_pushmore(RspBuffer *rsp, uint8_t *bytes,
                                       unsigned int n)
{
@@ -630,7 +592,7 @@ static void ipmi_init_sensors_from_sdrs(IPMIBmcSim *s)
    }
}

static int ipmi_register_netfn(IPMIBmcSim *s, unsigned int netfn,
int ipmi_sim_register_netfn(IPMIBmcSim *s, unsigned int netfn,
                        const IPMINetfn *netfnd)
{
    if ((netfn & 1) || (netfn >= MAX_NETFNS) || (s->netfns[netfn / 2])) {
@@ -1860,10 +1822,10 @@ static const IPMINetfn storage_netfn = {

static void register_cmds(IPMIBmcSim *s)
{
    ipmi_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
    ipmi_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
    ipmi_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
    ipmi_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
    ipmi_sim_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
    ipmi_sim_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
    ipmi_sim_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
    ipmi_sim_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
}

static uint8_t init_sdrs[] = {
+42 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ enum ipmi_op {
#define IPMI_CC_COMMAND_NOT_SUPPORTED                    0xd5

#define IPMI_NETFN_APP                0x06
#define IPMI_NETFN_OEM                0x3a

#define IPMI_DEBUG 1

@@ -265,4 +266,45 @@ int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
                      const struct ipmi_sdr_compact **sdr, uint16_t *nextrec);
void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log);

#define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
#define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
                                        TYPE_IPMI_BMC_SIMULATOR)

typedef struct IPMIBmcSim IPMIBmcSim;

typedef struct RspBuffer {
    uint8_t buffer[MAX_IPMI_MSG_SIZE];
    unsigned int len;
} RspBuffer;

static inline void rsp_buffer_set_error(RspBuffer *rsp, uint8_t byte)
{
    rsp->buffer[2] = byte;
}

/* Add a byte to the response. */
static inline void rsp_buffer_push(RspBuffer *rsp, uint8_t byte)
{
    if (rsp->len >= sizeof(rsp->buffer)) {
        rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
        return;
    }
    rsp->buffer[rsp->len++] = byte;
}

typedef struct IPMICmdHandler {
    void (*cmd_handler)(IPMIBmcSim *s,
                        uint8_t *cmd, unsigned int cmd_len,
                        RspBuffer *rsp);
    unsigned int cmd_len_min;
} IPMICmdHandler;

typedef struct IPMINetfn {
    unsigned int cmd_nums;
    const IPMICmdHandler *cmd_handlers;
} IPMINetfn;

int ipmi_sim_register_netfn(IPMIBmcSim *s, unsigned int netfn,
                            const IPMINetfn *netfnd);

#endif