summaryrefslogtreecommitdiff
path: root/src/drivers/ipmi
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/ipmi')
-rw-r--r--src/drivers/ipmi/Kconfig11
-rw-r--r--src/drivers/ipmi/Makefile.inc1
-rw-r--r--src/drivers/ipmi/ipmi_kcs_ops.c7
-rw-r--r--src/drivers/ipmi/ipmi_supermicro_oem.h10
-rw-r--r--src/drivers/ipmi/supermicro_oem.c70
5 files changed, 99 insertions, 0 deletions
diff --git a/src/drivers/ipmi/Kconfig b/src/drivers/ipmi/Kconfig
index 1137dcf8d5..012f67887c 100644
--- a/src/drivers/ipmi/Kconfig
+++ b/src/drivers/ipmi/Kconfig
@@ -42,3 +42,14 @@ config IPMI_KCS_TIMEOUT_MS
The time unit is millisecond for each IPMI KCS transfer.
IPMI spec v2.0 rev 1.1 Sec. 9.15, a five-second timeout or
greater is recommended.
+
+config DRIVERS_IPMI_SUPERMICRO_OEM
+ bool "Supermicro IPMI OEM BMC support"
+ depends on IPMI_KCS
+ default n
+ help
+ Tested on X11SSH only. Different BMCs might not support these OEM
+ commands.
+ The following features are implemented:
+ * Communicates the BIOS version to the BMC
+ * Communicates the BIOS date to the BMC
diff --git a/src/drivers/ipmi/Makefile.inc b/src/drivers/ipmi/Makefile.inc
index 06a3433ae0..e4bcf313eb 100644
--- a/src/drivers/ipmi/Makefile.inc
+++ b/src/drivers/ipmi/Makefile.inc
@@ -2,6 +2,7 @@ ramstage-$(CONFIG_IPMI_KCS) += ipmi_kcs.c
ramstage-$(CONFIG_IPMI_KCS) += ipmi_kcs_ops.c
ramstage-$(CONFIG_IPMI_KCS) += ipmi_ops.c
ramstage-$(CONFIG_IPMI_KCS) += ipmi_fru.c
+ramstage-$(CONFIG_DRIVERS_IPMI_SUPERMICRO_OEM) += supermicro_oem.c
romstage-$(CONFIG_IPMI_KCS_ROMSTAGE) += ipmi_kcs_ops_premem.c
romstage-$(CONFIG_IPMI_KCS_ROMSTAGE) += ipmi_kcs.c
romstage-$(CONFIG_IPMI_KCS_ROMSTAGE) += ipmi_ops.c
diff --git a/src/drivers/ipmi/ipmi_kcs_ops.c b/src/drivers/ipmi/ipmi_kcs_ops.c
index 640bfa1c17..38311ee7eb 100644
--- a/src/drivers/ipmi/ipmi_kcs_ops.c
+++ b/src/drivers/ipmi/ipmi_kcs_ops.c
@@ -23,6 +23,7 @@
#include <delay.h>
#include <timer.h>
#include "ipmi_kcs.h"
+#include "ipmi_supermicro_oem.h"
#include "chip.h"
/* 4 bit encoding */
@@ -167,6 +168,12 @@ static void ipmi_kcs_init(struct device *dev)
/* Don't write tables if communication failed */
dev->enabled = 0;
}
+
+ if (!dev->enabled)
+ return;
+
+ if (CONFIG(DRIVERS_IPMI_SUPERMICRO_OEM))
+ supermicro_ipmi_oem(dev->path.pnp.port);
}
#if CONFIG(HAVE_ACPI_TABLES)
diff --git a/src/drivers/ipmi/ipmi_supermicro_oem.h b/src/drivers/ipmi/ipmi_supermicro_oem.h
new file mode 100644
index 0000000000..5babadb13f
--- /dev/null
+++ b/src/drivers/ipmi/ipmi_supermicro_oem.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __IPMI_SUPERMICRO_OEM_H
+#define __IPMI_SUPERMICRO_OEM_H
+
+#include <stdint.h>
+
+void supermicro_ipmi_oem(const uint16_t kcs_port);
+
+#endif /* __IPMI_SUPERMICRO_OEM_H */
diff --git a/src/drivers/ipmi/supermicro_oem.c b/src/drivers/ipmi/supermicro_oem.c
new file mode 100644
index 0000000000..87b7fe243a
--- /dev/null
+++ b/src/drivers/ipmi/supermicro_oem.c
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <types.h>
+
+#include <console/console.h>
+#include <drivers/ipmi/ipmi_kcs.h>
+#include <string.h>
+#include <build.h>
+#include "ipmi_supermicro_oem.h"
+
+#define IPMI_NETFN_OEM 0x30
+#define IPMI_LUN0_AC_SET_BIOS_VER 0x100
+#define IPMI_LUN0_AC_SET_BIOS_DATE 0x101
+#define IPMI_LUN0_SET_BIOS_STRING 0xac
+
+struct ipmi_oem_set_bios_str {
+ uint16_t ver;
+ char str[16]; // NULL terminated string
+} __packed;
+
+static void set_coreboot_ver(const uint16_t kcs_port)
+{
+ const char *coreboot_ver = COREBOOT_VERSION;
+ struct ipmi_oem_set_bios_str bios_ver;
+ struct ipmi_rsp rsp;
+ int ret;
+ size_t i;
+
+ /* Only 8 charactars are visible in UI. Cut of on first dash */
+ for (i = 0; i < 15; i++) {
+ if (coreboot_ver[i] == '-')
+ break;
+ bios_ver.str[i] = coreboot_ver[i];
+ }
+ bios_ver.str[i] = 0;
+ bios_ver.ver = IPMI_LUN0_AC_SET_BIOS_VER;
+
+ ret = ipmi_kcs_message(kcs_port, IPMI_NETFN_OEM, 0, IPMI_LUN0_SET_BIOS_STRING,
+ (const unsigned char *) &bios_ver, sizeof(bios_ver),
+ (unsigned char *) &rsp, sizeof(rsp));
+ if (ret < sizeof(rsp) || rsp.completion_code) {
+ printk(BIOS_ERR, "BMC_IPMI: %s command failed (ret=%d resp=0x%x)\n",
+ __func__, ret, rsp.completion_code);
+ }
+}
+
+static void set_coreboot_date(const uint16_t kcs_port)
+{
+ struct ipmi_oem_set_bios_str bios_ver;
+ struct ipmi_rsp rsp;
+ int ret;
+
+ strncpy(bios_ver.str, COREBOOT_DMI_DATE, 15);
+ bios_ver.str[15] = 0;
+ bios_ver.ver = IPMI_LUN0_AC_SET_BIOS_DATE;
+
+ ret = ipmi_kcs_message(kcs_port, IPMI_NETFN_OEM, 0, IPMI_LUN0_SET_BIOS_STRING,
+ (const unsigned char *) &bios_ver, sizeof(bios_ver),
+ (unsigned char *) &rsp, sizeof(rsp));
+ if (ret < sizeof(rsp) || rsp.completion_code) {
+ printk(BIOS_ERR, "BMC_IPMI: %s command failed (ret=%d resp=0x%x)\n",
+ __func__, ret, rsp.completion_code);
+ }
+}
+
+void supermicro_ipmi_oem(const uint16_t kcs_port)
+{
+ set_coreboot_ver(kcs_port);
+ set_coreboot_date(kcs_port);
+}