diff options
author | Joel Stanley <joel@jms.id.au> | 2015-02-05 13:40:04 +1030 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-02-09 14:15:57 +1100 |
commit | 77e4b445025b05d4da12862e34a47519d0a64868 (patch) | |
tree | ce3f89e0458b892bf1e366e6a84ff4eb9ab6a26d | |
parent | be8e03e7861a9e7b9dcbc9cf0bae6aaa57916940 (diff) | |
download | skiboot-77e4b445025b05d4da12862e34a47519d0a64868.zip skiboot-77e4b445025b05d4da12862e34a47519d0a64868.tar.gz skiboot-77e4b445025b05d4da12862e34a47519d0a64868.tar.bz2 |
ipmi: Implement Read Event and SEL parsing
The read event mechanism is used when the BMC has an asynchronous message
for the host. It sets a flag that we read with Get Message Flags, and then
we read the message using Read Event. This event message contains a SEL
message. There are two OEM SEL messages we expect from the AMI BMC:
- graceful power operations. This is when the BMC wants the host to
power down or reboot.
- PNOR Locking. When the BMC wants to access the PNOR, it requests
that the host not touch it.
This patch implements the parsing.
Signed-off-by: Joel Stanley <joel@jms.id.au>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r-- | core/ipmi.c | 3 | ||||
-rw-r--r-- | hw/ipmi/ipmi-sel.c | 78 | ||||
-rw-r--r-- | include/ipmi.h | 3 |
3 files changed, 83 insertions, 1 deletions
diff --git a/core/ipmi.c b/core/ipmi.c index 04c381a..e4dfefd 100644 --- a/core/ipmi.c +++ b/core/ipmi.c @@ -142,7 +142,8 @@ static void ipmi_read_event_complete(struct ipmi_msg *msg) prlog(PR_DEBUG, "IPMI read event %02x complete: %d bytes. cc: %02x\n", msg->cmd, msg->resp_size, msg->cc); - /* TODO: Handle power control & PNOR handshake events */ + /* Handle power control & PNOR handshake events */ + ipmi_parse_sel(msg); ipmi_free_msg(msg); } diff --git a/hw/ipmi/ipmi-sel.c b/hw/ipmi/ipmi-sel.c index 5832228..4c66bd1 100644 --- a/hw/ipmi/ipmi-sel.c +++ b/hw/ipmi/ipmi-sel.c @@ -24,6 +24,30 @@ #include <errorlog.h> #include <pel.h> +/* OEM SEL fields */ +#define SEL_OEM_ID_0 0x55 +#define SEL_OEM_ID_1 0x55 +#define SEL_RECORD_TYPE_OEM 0xC0 +#define SEL_RECORD_TYPE_EVENT 0x02 + +#define SEL_NETFN_IBM 0x3a + +/* OEM SEL Commands */ +#define CMD_AMI_POWER 0x04 +#define CMD_AMI_PNOR_ACCESS 0x07 + +struct oem_sel { + /* SEL header */ + uint8_t id[2]; + uint8_t type; + uint8_t manuf_id[3]; + uint8_t timestamp[4]; + /* OEM SEL data (6 bytes) follows */ + uint8_t netfun; + uint8_t cmd; + uint8_t data[4]; +}; + /* As far as I can tell the size of PEL record is unbounded (due to * the possible presence of the user defined section). We chose this * size because it's what FSP uses, but we could probably reduce @@ -150,3 +174,57 @@ int ipmi_elog_commit(struct errorlog *elog_buf) return 0; } + +static void dump_sel(struct oem_sel *sel) +{ + const int level = PR_DEBUG; + + prlog(level, "\tid %02x%02x\n", sel->id[0], sel->id[1]); + prlog(level, "\ttype %02x\n", sel->type); + prlog(level, "\tmanuf %02x %02x %02x\n", + sel->manuf_id[0], sel->manuf_id[1], sel->manuf_id[2]); + prlog(level, "\ttime %02x %02x %02x %02x\n", + sel->timestamp[0], sel->timestamp[1], + sel->timestamp[2], sel->timestamp[3]); + prlog(level, "\tnetfun %02x\n", sel->netfun); + prlog(level, "\tcmd %02x\n", sel->cmd); + prlog(level, "\tdata %02x %02x %02x %02x\n", sel->data[0], + sel->data[1], sel->data[2], sel->data[3]); +} + +void ipmi_parse_sel(struct ipmi_msg *msg) +{ + struct oem_sel sel; + + prlog(PR_INFO, "SEL received (size: %d)\n", msg->resp_size); + assert(msg->resp_size <= 16); + + memcpy(&sel, msg->data, msg->resp_size); + + dump_sel(&sel); + + /* We do not process system event records */ + if (sel.type == SEL_RECORD_TYPE_EVENT) { + prlog(PR_INFO, "IPMI: dropping System Event Record SEL\n"); + return; + } + + /* Only accept OEM SEL messages */ + if (sel.id[0] != SEL_OEM_ID_0 || + sel.id[1] != SEL_OEM_ID_1 || + sel.type != SEL_RECORD_TYPE_OEM) { + prlog(PR_WARNING, "IPMI: unknown SEL %02x%02x (type %02x)\n", + sel.id[0], sel.id[1], sel.type); + return; + } + + switch (sel.cmd) { + case CMD_AMI_POWER: + break; + case CMD_AMI_PNOR_ACCESS: + break; + default: + printf("IPMI: unknown OEM SEL command %02x received\n", + sel.cmd); + } +} diff --git a/include/ipmi.h b/include/ipmi.h index 68bf5a7..df8cf99 100644 --- a/include/ipmi.h +++ b/include/ipmi.h @@ -223,4 +223,7 @@ void ipmi_fru_init(uint8_t fru_dev_id); struct errorlog; int ipmi_elog_commit(struct errorlog *elog_buf); +/* Callback to parse an OEM SEL message */ +void ipmi_parse_sel(struct ipmi_msg *msg); + #endif |