aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Stanley <joel@jms.id.au>2015-02-05 13:40:04 +1030
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-02-09 14:15:57 +1100
commit77e4b445025b05d4da12862e34a47519d0a64868 (patch)
treece3f89e0458b892bf1e366e6a84ff4eb9ab6a26d
parentbe8e03e7861a9e7b9dcbc9cf0bae6aaa57916940 (diff)
downloadskiboot-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.c3
-rw-r--r--hw/ipmi/ipmi-sel.c78
-rw-r--r--include/ipmi.h3
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