[Skiboot] [PATCH v2] ipmi: Add BMC firmware version to device tree

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Mon May 7 14:18:23 AEST 2018


BMC Get device ID command gives BMC firmware version details. Lets add this
to device tree. User space tools will use this information to display BMC
version details.

Stewart,
  I have added bmc information under /ibm,firmware-version node as its firmware
  version. But may be we should add new node (/bmc/firmware). So that we can
  keep BMC related information separately. Let me know your thoughts on this.

Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
---
 hw/ipmi/Makefile.inc      |   2 +-
 hw/ipmi/ipmi-info.c       | 112 ++++++++++++++++++++++++++++++++++++++++++++++
 include/ipmi.h            |   7 +++
 platforms/astbmc/common.c |   6 +++
 4 files changed, 126 insertions(+), 1 deletion(-)
 create mode 100644 hw/ipmi/ipmi-info.c

diff --git a/hw/ipmi/Makefile.inc b/hw/ipmi/Makefile.inc
index 34d6bd319..b0af7a624 100644
--- a/hw/ipmi/Makefile.inc
+++ b/hw/ipmi/Makefile.inc
@@ -1,7 +1,7 @@
 SUBDIRS += hw/ipmi
 
 IPMI_OBJS  = ipmi-rtc.o ipmi-power.o ipmi-fru.o ipmi-sel.o
-IPMI_OBJS += ipmi-watchdog.o ipmi-sensor.o ipmi-attn.o
+IPMI_OBJS += ipmi-watchdog.o ipmi-sensor.o ipmi-attn.o ipmi-info.o
 
 IPMI = hw/ipmi/built-in.a
 $(IPMI): $(IPMI_OBJS:%=hw/ipmi/%)
diff --git a/hw/ipmi/ipmi-info.c b/hw/ipmi/ipmi-info.c
new file mode 100644
index 000000000..56370037b
--- /dev/null
+++ b/hw/ipmi/ipmi-info.c
@@ -0,0 +1,112 @@
+/* Copyright 2018 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *	http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <device.h>
+#include <skiboot.h>
+#include <stdlib.h>
+#include <ipmi.h>
+#include <mem_region-malloc.h>
+#include <opal.h>
+#include <timebase.h>
+
+/*
+ * Respones data from IPMI Get device ID command (As defined in
+ * Section 20.1 Get Device ID Command - IPMI standard spec).
+ */
+struct ipmi_dev_id {
+	uint8_t	dev_id;
+	uint8_t	dev_revision;
+	uint8_t	fw_rev1;
+	uint8_t	fw_rev2;
+	uint8_t	ipmi_ver;
+	uint8_t	add_dev_support;
+	uint8_t	manufactur_id[3];
+	uint8_t	product_id[2];
+	uint8_t	aux_fw_rev[4];
+};
+static struct ipmi_dev_id *ipmi_dev_id;
+
+/* Got response from BMC? */
+static bool bmc_info_waiting = false;
+static bool bmc_info_valid = false;
+
+/* This will free ipmi_dev_id structure */
+void ipmi_dt_add_bmc_info(void)
+{
+	char buf[8];
+	struct dt_node *dt_fw_version;
+
+	while (bmc_info_waiting)
+		time_wait_ms(5);
+
+	if (!bmc_info_valid)
+		return;
+
+	dt_fw_version = dt_find_by_name(dt_root, "ibm,firmware-versions");
+	if (!dt_fw_version) {
+		free(ipmi_dev_id);
+		return;
+	}
+
+	memset(buf, 0, sizeof(buf));
+	snprintf(buf, sizeof(buf), "%x.%02x",
+		 ipmi_dev_id->fw_rev1, ipmi_dev_id->fw_rev2);
+	dt_add_property_string(dt_fw_version, "bmc-firmware-version", buf);
+
+	free(ipmi_dev_id);
+}
+
+static void ipmi_get_bmc_info_resp(struct ipmi_msg *msg)
+{
+	bmc_info_waiting = false;
+
+	if (msg->cc != IPMI_CC_NO_ERROR) {
+		prlog(PR_ERR, "IPMI: IPMI_BMC_GET_DEVICE_ID cmd returned error"
+		      " [rc : 0x%x]\n", msg->data[0]);
+		return;
+	}
+
+	bmc_info_valid = true;
+	memcpy(ipmi_dev_id, msg->data, msg->resp_size);
+	ipmi_free_msg(msg);
+}
+
+int ipmi_get_bmc_info_request(void)
+{
+	int rc;
+	struct ipmi_msg *msg;
+
+	ipmi_dev_id = zalloc(sizeof(struct ipmi_dev_id));
+	assert(ipmi_dev_id);
+
+	msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_BMC_GET_DEVICE_ID,
+			 ipmi_get_bmc_info_resp, NULL, NULL,
+			 0, sizeof(struct ipmi_dev_id));
+	if (!msg)
+		return OPAL_NO_MEM;
+
+	msg->error = ipmi_get_bmc_info_resp;
+	prlog(PR_INFO, "IPMI: Requesting IPMI_BMC_GET_DEVICE_ID\n");
+	rc = ipmi_queue_msg(msg);
+	if (rc) {
+		prlog(PR_ERR, "IPMI: Failed to queue IPMI_BMC_GET_DEVICE_ID\n");
+		ipmi_free_msg(msg);
+		return rc;
+	}
+
+	bmc_info_waiting = true;
+	return rc;
+}
diff --git a/include/ipmi.h b/include/ipmi.h
index 3389eaf59..0acfbf563 100644
--- a/include/ipmi.h
+++ b/include/ipmi.h
@@ -109,6 +109,7 @@
 #define IPMI_GET_SEL_TIME		IPMI_CODE(IPMI_NETFN_STORAGE, 0x48)
 #define IPMI_SET_SEL_TIME		IPMI_CODE(IPMI_NETFN_STORAGE, 0x49)
 #define IPMI_CHASSIS_CONTROL		IPMI_CODE(IPMI_NETFN_CHASSIS, 0x02)
+#define IPMI_BMC_GET_DEVICE_ID		IPMI_CODE(IPMI_NETFN_APP, 0x01)
 #define IPMI_SET_POWER_STATE		IPMI_CODE(IPMI_NETFN_APP, 0x06)
 #define IPMI_GET_POWER_STATE		IPMI_CODE(IPMI_NETFN_APP, 0x07)
 #define IPMI_RESET_WDT			IPMI_CODE(IPMI_NETFN_APP, 0x22)
@@ -278,4 +279,10 @@ int ipmi_set_boot_count(void);
 /* Terminate immediate */
 void __attribute__((noreturn)) ipmi_terminate(const char *msg);
 
+/* Get BMC firmware info */
+extern int ipmi_get_bmc_info_request(void);
+
+/* Add BMC firmware info to device tree */
+extern void ipmi_dt_add_bmc_info(void);
+
 #endif
diff --git a/platforms/astbmc/common.c b/platforms/astbmc/common.c
index 243ad9461..8b24abe5c 100644
--- a/platforms/astbmc/common.c
+++ b/platforms/astbmc/common.c
@@ -137,6 +137,9 @@ void astbmc_init(void)
 	/* Preload PNOR VERSION section */
 	flash_fw_version_preload();
 
+	/* Request BMC information */
+	ipmi_get_bmc_info_request();
+
 	/* As soon as IPMI is up, inform BMC we are in "S0" */
 	ipmi_set_power_state(IPMI_PWR_SYS_S0_WORKING, IPMI_PWR_NOCHANGE);
 
@@ -150,6 +153,9 @@ void astbmc_init(void)
 
 	/* Add ibm,firmware-versions node */
 	flash_dt_add_fw_version();
+
+	/* Add BMC firmware info to device tree */
+	ipmi_dt_add_bmc_info();
 }
 
 int64_t astbmc_ipmi_power_down(uint64_t request)
-- 
2.14.3



More information about the Skiboot mailing list