[PATCH] Retrieve BMC version info via IPMI

Sam Mendoza-Jonas sam at mendozajonas.com
Tue Feb 9 13:24:00 AEDT 2016


On BMC machines the "Get Device ID" and "Get BMC Golden Side Version"
IPMI commands are available. If possible retrieve some interesting
version numbers and display them in the System Information screen.

Signed-off-by: Sam Mendoza-Jonas <sam at mendozajonas.com>
---
Note: This sits directly on top of the recent series
named "Support for BMC platform versions".

 discover/ipmi.h               |  4 ++
 discover/platform-powerpc.c   | 91 +++++++++++++++++++++++++++++++++++++++++++
 lib/pb-protocol/pb-protocol.c | 40 ++++++++++++++++++-
 lib/types/types.h             |  4 ++
 ui/ncurses/nc-sysinfo.c       | 16 ++++++++
 5 files changed, 154 insertions(+), 1 deletion(-)

diff --git a/discover/ipmi.h b/discover/ipmi.h
index eb2a183..611cd49 100644
--- a/discover/ipmi.h
+++ b/discover/ipmi.h
@@ -9,7 +9,9 @@
 enum ipmi_netfn {
 	IPMI_NETFN_CHASSIS	= 0x0,
 	IPMI_NETFN_SE		= 0x04,
+	IPMI_NETFN_APP		= 0x06,
 	IPMI_NETFN_TRANSPORT	= 0x0c,
+	IPMI_NETFN_AMI		= 0x3a,
 };
 
 enum ipmi_cmd {
@@ -17,6 +19,8 @@ enum ipmi_cmd {
 	IPMI_CMD_CHASSIS_GET_SYSTEM_BOOT_OPTIONS	= 0x09,
 	IPMI_CMD_SENSOR_SET				= 0x30,
 	IPMI_CMD_TRANSPORT_GET_LAN_PARAMS		= 0x02,
+	IPMI_CMD_APP_GET_DEVICE_ID			= 0x01,
+	IPMI_CMD_APP_GET_DEVICE_ID_GOLDEN		= 0x1a,
 };
 
 enum ipmi_sensor_ids {
diff --git a/discover/platform-powerpc.c b/discover/platform-powerpc.c
index 8434d6f..b942c99 100644
--- a/discover/platform-powerpc.c
+++ b/discover/platform-powerpc.c
@@ -1018,6 +1018,94 @@ static void get_ipmi_bmc_mac(struct platform *p, uint8_t *buf)
 		}
 		pb_debug("\n");
 	}
+
+}
+
+/*
+ * Retrieve info from the "Get Device ID" IPMI commands.
+ * See Chapter 20.1 in the IPMIv2 specification.
+ */
+static void get_ipmi_bmc_versions(struct platform *p, struct system_info *info)
+{
+	struct platform_powerpc *platform = p->platform_data;
+	uint16_t resp_len = 16;
+	uint8_t resp[16], bcd;
+	uint32_t aux_version;
+	int i, rc;
+
+	/* Retrieve info from current side */
+	rc = ipmi_transaction(platform->ipmi, IPMI_NETFN_APP,
+			IPMI_CMD_APP_GET_DEVICE_ID,
+			NULL, 0,
+			resp, &resp_len,
+			ipmi_timeout);
+
+	pb_debug("BMC version resp [%d][%d]:\n", rc, resp_len);
+	if (resp_len > 0) {
+		for (i = 0; i < resp_len; i++) {
+		        pb_debug(" %x", resp[i]);
+		}
+		pb_debug("\n");
+	}
+
+	if (rc == 0 && resp_len == 16) {
+		info->bmc_current = talloc_array(info, char *, 4);
+		info->n_bmc_current = 4;
+
+		info->bmc_current[0] = talloc_asprintf(info, "Device ID: 0x%x",
+						resp[1]);
+		info->bmc_current[1] = talloc_asprintf(info, "Device Rev: 0x%x",
+						resp[2]);
+		bcd = resp[4] & 0x0f;
+		bcd += 10 * (resp[4] >> 4);
+		aux_version = *(uint32_t *)(&resp[12]);
+		info->bmc_current[2] = talloc_asprintf(info,
+						"Firmware version: %u.%u.%u",
+						resp[3], bcd, aux_version);
+		bcd = resp[5] & 0x0f;
+		bcd += 10 * (resp[5] >> 4);
+		info->bmc_current[3] = talloc_asprintf(info, "IPMI version: %u",
+						bcd);
+	} else
+		pb_log("Failed to retrieve Device ID from IPMI");
+
+	/* Retrieve info from golden side */
+	memset(resp, 0, sizeof(resp));
+	resp_len = 16;
+	rc = ipmi_transaction(platform->ipmi, IPMI_NETFN_AMI,
+			IPMI_CMD_APP_GET_DEVICE_ID_GOLDEN,
+			NULL, 0,
+			resp, &resp_len,
+			ipmi_timeout);
+
+	pb_debug("BMC golden resp [%d][%d]:\n", rc, resp_len);
+	if (resp_len > 0) {
+		for (i = 0; i < resp_len; i++) {
+		        pb_debug(" %x", resp[i]);
+		}
+		pb_debug("\n");
+	}
+
+	if (rc == 0 && resp_len == 16) {
+		info->bmc_golden = talloc_array(info, char *, 4);
+		info->n_bmc_golden = 4;
+
+		info->bmc_golden[0] = talloc_asprintf(info, "Device ID: 0x%x",
+						resp[1]);
+		info->bmc_golden[1] = talloc_asprintf(info, "Device Rev: 0x%x",
+						resp[2]);
+		bcd = resp[4] & 0x0f;
+		bcd += 10 * (resp[4] >> 4);
+		aux_version = *(uint32_t *)(&resp[12]);
+		info->bmc_golden[2] = talloc_asprintf(info,
+						"Firmware version: %u.%u.%u",
+						resp[3], bcd, aux_version);
+		bcd = resp[5] & 0x0f;
+		bcd += 10 * (resp[5] >> 4);
+		info->bmc_golden[3] = talloc_asprintf(info, "IPMI version: %u",
+						bcd);
+	} else
+		pb_log("Failed to retrieve Golden Device ID from IPMI");
 }
 
 static int load_config(struct platform *p, struct config *config)
@@ -1092,6 +1180,9 @@ static int get_sysinfo(struct platform *p, struct system_info *sysinfo)
 	if (platform->ipmi)
 		get_ipmi_bmc_mac(p, sysinfo->bmc_mac);
 
+	if (platform->ipmi)
+		get_ipmi_bmc_versions(p, sysinfo);
+
 	if (platform->get_platform_versions)
 		platform->get_platform_versions(sysinfo);
 
diff --git a/lib/pb-protocol/pb-protocol.c b/lib/pb-protocol/pb-protocol.c
index e99ce86..3953ee1 100644
--- a/lib/pb-protocol/pb-protocol.c
+++ b/lib/pb-protocol/pb-protocol.c
@@ -232,6 +232,13 @@ int pb_protocol_system_info_len(const struct system_info *sysinfo)
 	for (i = 0; i < sysinfo->n_other; i++)
 		len += 4 + optional_strlen(sysinfo->platform_other[i]);
 
+	len +=	4;
+	for (i = 0; i < sysinfo->n_bmc_current; i++)
+		len += 4 + optional_strlen(sysinfo->bmc_current[i]);
+	len +=	4;
+	for (i = 0; i < sysinfo->n_bmc_golden; i++)
+		len += 4 + optional_strlen(sysinfo->bmc_golden[i]);
+
 	for (i = 0; i < sysinfo->n_interfaces; i++) {
 		struct interface_info *if_info = sysinfo->interfaces[i];
 		len +=	4 + if_info->hwaddr_size +
@@ -412,6 +419,16 @@ int pb_protocol_serialise_system_info(const struct system_info *sysinfo,
 	for (i = 0; i < sysinfo->n_other; i++)
 		pos += pb_protocol_serialise_string(pos, sysinfo->platform_other[i]);
 
+	*(uint32_t *)pos = __cpu_to_be32(sysinfo->n_bmc_current);
+	pos += sizeof(uint32_t);
+	for (i = 0; i < sysinfo->n_bmc_current; i++)
+		pos += pb_protocol_serialise_string(pos, sysinfo->bmc_current[i]);
+
+	*(uint32_t *)pos = __cpu_to_be32(sysinfo->n_bmc_golden);
+	pos += sizeof(uint32_t);
+	for (i = 0; i < sysinfo->n_bmc_golden; i++)
+		pos += pb_protocol_serialise_string(pos, sysinfo->bmc_golden[i]);
+
 	*(uint32_t *)pos = __cpu_to_be32(sysinfo->n_interfaces);
 	pos += sizeof(uint32_t);
 
@@ -827,7 +844,7 @@ int pb_protocol_deserialise_system_info(struct system_info *sysinfo,
 	if (read_string(sysinfo, &pos, &len, &sysinfo->identifier))
 		goto out;
 
-	/* versions strings for openpower platforms */
+	/* Platform version strings for openpower platforms */
 	if (read_u32(&pos, &len, &sysinfo->n_current))
 		goto out;
 	sysinfo->platform_current = talloc_array(sysinfo, char *,
@@ -848,6 +865,27 @@ int pb_protocol_deserialise_system_info(struct system_info *sysinfo,
 		sysinfo->platform_other[i] = talloc_strdup(sysinfo, tmp);
 	}
 
+	/* BMC version strings for openpower platforms */
+	if (read_u32(&pos, &len, &sysinfo->n_bmc_current))
+		goto out;
+	sysinfo->bmc_current = talloc_array(sysinfo, char *,
+						sysinfo->n_bmc_current);
+	for (i = 0; i < sysinfo->n_bmc_current; i++) {
+		if (read_string(sysinfo, &pos, &len, &tmp))
+			goto out;
+		sysinfo->bmc_current[i] = talloc_strdup(sysinfo, tmp);
+	}
+
+	if (read_u32(&pos, &len, &sysinfo->n_bmc_golden))
+		goto out;
+	sysinfo->bmc_golden = talloc_array(sysinfo, char *,
+						sysinfo->n_bmc_golden);
+	for (i = 0; i < sysinfo->n_bmc_golden; i++) {
+		if (read_string(sysinfo, &pos, &len, &tmp))
+			goto out;
+		sysinfo->bmc_golden[i] = talloc_strdup(sysinfo, tmp);
+	}
+
 	/* number of interfaces */
 	if (read_u32(&pos, &len, &sysinfo->n_interfaces))
 		goto out;
diff --git a/lib/types/types.h b/lib/types/types.h
index db4d892..63c1c7c 100644
--- a/lib/types/types.h
+++ b/lib/types/types.h
@@ -97,6 +97,10 @@ struct system_info {
 	char			**platform_other;
 	unsigned int		n_current;
 	unsigned int		n_other;
+	char			**bmc_current;
+	char			**bmc_golden;
+	unsigned int		n_bmc_current;
+	unsigned int		n_bmc_golden;
 	uint8_t			*bmc_mac;
 	struct interface_info	**interfaces;
 	unsigned int		n_interfaces;
diff --git a/ui/ncurses/nc-sysinfo.c b/ui/ncurses/nc-sysinfo.c
index c01b352..ca609cc 100644
--- a/ui/ncurses/nc-sysinfo.c
+++ b/ui/ncurses/nc-sysinfo.c
@@ -81,6 +81,22 @@ static void sysinfo_screen_populate(struct sysinfo_screen *screen,
 		}
 	}
 
+	if (sysinfo->n_bmc_current) {
+		line(NULL);
+		line("%s", _("BMC current side:"));
+		for (i = 0; i < sysinfo->n_bmc_current; i++) {
+			line("\t%s", sysinfo->bmc_current[i] ?: "");
+		}
+	}
+
+	if (sysinfo->n_bmc_golden) {
+		line(NULL);
+		line("%s", _("BMC golden side:"));
+		for (i = 0; i < sysinfo->n_bmc_golden; i++) {
+			line("\t%s", sysinfo->bmc_golden[i] ?: "");
+		}
+	}
+
 	if (sysinfo->n_blockdevs) {
 		line(NULL);
 		line(_("Storage devices"));
-- 
2.7.1



More information about the Petitboot mailing list