[Skiboot] [PATCH 3/5] ipmi: Implement Read Event and SEL parsing
Joel Stanley
joel at jms.id.au
Fri Jan 30 11:31:49 AEDT 2015
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 at jms.id.au>
---
core/ipmi.c | 3 +-
hw/ipmi/ipmi-sel.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/ipmi.h | 3 ++
3 files changed, 89 insertions(+), 1 deletion(-)
diff --git a/core/ipmi.c b/core/ipmi.c
index 35bfead..b5ada0e 100644
--- a/core/ipmi.c
+++ b/core/ipmi.c
@@ -108,7 +108,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 d6f7f47..301e559 100644
--- a/hw/ipmi/ipmi-sel.c
+++ b/hw/ipmi/ipmi-sel.c
@@ -22,6 +22,33 @@
#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_MANUF_0 0x8E
+#define SEL_MANUF_1 0xCB
+#define SEL_MANUF_2 0xC8
+
+#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
@@ -148,3 +175,60 @@ 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 ||
+ sel.manuf_id[0] != SEL_MANUF_0 ||
+ sel.manuf_id[1] != SEL_MANUF_1 ||
+ sel.manuf_id[2] != SEL_MANUF_2) {
+ 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 048e6cf..c1f0493 100644
--- a/include/ipmi.h
+++ b/include/ipmi.h
@@ -213,4 +213,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
--
2.1.4
More information about the Skiboot
mailing list