summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorgan Jang <Morgan_Jang@wiwynn.com>2019-11-06 10:24:47 +0800
committerPatrick Georgi <pgeorgi@google.com>2019-11-27 13:44:50 +0000
commit9ede3d51e59e6affff28a77168cb9a4c65bba51c (patch)
treea528ae577d5dbdd78c48bb4817a0f421388435d2
parentab8edda14a622ab46bdfd01b877d75c7bd385a4d (diff)
downloadcoreboot-9ede3d51e59e6affff28a77168cb9a4c65bba51c.tar.gz
coreboot-9ede3d51e59e6affff28a77168cb9a4c65bba51c.tar.bz2
coreboot-9ede3d51e59e6affff28a77168cb9a4c65bba51c.zip
src/drivers/ipmi: Implement BMC Get Self Test Result function
According to IPMI SPEC, it is recommended that BIOS includes provisions for checking and reporting on the basic health of BMC by executing the Get Self Test Results command and checking the result. TEST=Check the result in response data to confirm the BMC status is fine or not. Change-Id: I20349cec2e8e9420d177d725de2a5560d354fe47 Signed-off-by: Morgan Jang <Morgan_Jang@wiwynn.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/36638 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: David Hendricks <david.hendricks@gmail.com> (cherry picked from commit 50155024141f48cf3048272073d352906a2be0b6) Reviewed-on: https://review.coreboot.org/c/coreboot/+/37087
-rw-r--r--src/drivers/ipmi/ipmi_kcs.h13
-rw-r--r--src/drivers/ipmi/ipmi_kcs_ops.c59
2 files changed, 72 insertions, 0 deletions
diff --git a/src/drivers/ipmi/ipmi_kcs.h b/src/drivers/ipmi/ipmi_kcs.h
index f35802e27bfe..b3775219c3cd 100644
--- a/src/drivers/ipmi/ipmi_kcs.h
+++ b/src/drivers/ipmi/ipmi_kcs.h
@@ -22,6 +22,12 @@
#define IPMI_BMC_GET_DEVICE_ID 0x01
#define IPMI_IPMI_VERSION_MINOR(x) ((x) >> 4)
#define IPMI_IPMI_VERSION_MAJOR(x) ((x) & 0xf)
+#define IPMI_BMC_GET_SELFTEST_RESULTS 0x04
+#define IPMI_APP_SELFTEST_RESERVED 0xFF
+#define IPMI_APP_SELFTEST_NO_ERROR 0x55
+#define IPMI_APP_SELFTEST_NOT_IMPLEMENTED 0x56
+#define IPMI_APP_SELFTEST_ERROR 0x57
+#define IPMI_APP_SELFTEST_FATAL_HW_ERROR 0x58
#define IPMI_NETFN_FIRMWARE 0x08
#define IPMI_NETFN_STORAGE 0x0a
@@ -52,4 +58,11 @@ struct ipmi_devid_rsp {
uint8_t product_id[2];
} __packed;
+/* Get Self Test Results */
+struct ipmi_selftest_rsp {
+ struct ipmi_rsp resp;
+ uint8_t result;
+ uint8_t param;
+} __packed;
+
#endif
diff --git a/src/drivers/ipmi/ipmi_kcs_ops.c b/src/drivers/ipmi/ipmi_kcs_ops.c
index 90f19dddb81b..5cb8995df948 100644
--- a/src/drivers/ipmi/ipmi_kcs_ops.c
+++ b/src/drivers/ipmi/ipmi_kcs_ops.c
@@ -59,11 +59,34 @@ static int ipmi_get_device_id(struct device *dev, struct ipmi_devid_rsp *rsp)
return 0;
}
+static int ipmi_get_bmc_self_test_result(struct device *dev, struct ipmi_selftest_rsp *rsp)
+{
+ int ret;
+
+ ret = ipmi_kcs_message(dev->path.pnp.port, IPMI_NETFN_APPLICATION, 0,
+ IPMI_BMC_GET_SELFTEST_RESULTS, NULL, 0, (u8 *)rsp,
+ sizeof(*rsp));
+
+ if (ret < sizeof(struct ipmi_rsp) || rsp->resp.completion_code) {
+ printk(BIOS_ERR, "IPMI: %s command failed (ret=%d resp=0x%x)\n",
+ __func__, ret, rsp->resp.completion_code);
+ return 1;
+ }
+ if (ret != sizeof(*rsp)) {
+ printk(BIOS_ERR, "IPMI: %s response truncated\n", __func__);
+ return 1;
+ }
+
+ return 0;
+}
+
static void ipmi_kcs_init(struct device *dev)
{
struct ipmi_devid_rsp rsp;
uint32_t man_id = 0, prod_id = 0;
struct drivers_ipmi_config *conf = NULL;
+ struct ipmi_selftest_rsp selftestrsp;
+ uint8_t retry_count;
if (!dev->enabled)
return;
@@ -92,6 +115,42 @@ static void ipmi_kcs_init(struct device *dev)
}
}
+ printk(BIOS_INFO, "Get BMC self test result...");
+ for (retry_count = 0; retry_count < conf->bmc_boot_timeout; retry_count++) {
+ if (!ipmi_get_bmc_self_test_result(dev, &selftestrsp))
+ break;
+
+ mdelay(1000);
+ }
+
+ switch (selftestrsp.result) {
+ case IPMI_APP_SELFTEST_NO_ERROR: /* 0x55 */
+ printk(BIOS_DEBUG, "No Error\n");
+ break;
+ case IPMI_APP_SELFTEST_NOT_IMPLEMENTED: /* 0x56 */
+ printk(BIOS_DEBUG, "Function Not Implemented\n");
+ break;
+ case IPMI_APP_SELFTEST_ERROR: /* 0x57 */
+ printk(BIOS_ERR, "BMC: Corrupted or inaccessible data or device\n");
+ /* Don't write tables if communication failed */
+ dev->enabled = 0;
+ break;
+ case IPMI_APP_SELFTEST_FATAL_HW_ERROR: /* 0x58 */
+ printk(BIOS_ERR, "BMC: Fatal Hardware Error\n");
+ /* Don't write tables if communication failed */
+ dev->enabled = 0;
+ break;
+ case IPMI_APP_SELFTEST_RESERVED: /* 0xFF */
+ printk(BIOS_DEBUG, "Reserved\n");
+ break;
+
+ default: /* Other Device Specific Hardware Error */
+ printk(BIOS_ERR, "BMC: Device Specific Error\n");
+ /* Don't write tables if communication failed */
+ dev->enabled = 0;
+ break;
+ }
+
if (!ipmi_get_device_id(dev, &rsp)) {
/* Queried the IPMI revision from BMC */
ipmi_revision_minor = IPMI_IPMI_VERSION_MINOR(rsp.ipmi_version);