[Skiboot] [PATCH] Add BMC platform to enable correct OEM IPMI commands

Stewart Smith stewart at linux.vnet.ibm.com
Tue Nov 8 15:43:19 AEDT 2016


An out of tree platform (p8dtu) uses a different IPMI OEM command
for IPMI_PARTIAL_ADD_ESEL. This exposed some assumptions about the BMC
implementation in our core code.

Now, with platform.bmc, each platform can dictate (or detect) the BMC
that is present. We allow it to be set at runtime rather than purely
statically in struct platform as it's possible to have differing BMC
implementations on the one machine (e.g. AMI BMC or OpenBMC).

Signed-off-by: Stewart Smith <stewart at linux.vnet.ibm.com>
---
 core/platform.c              | 11 +++++++++++
 hw/ipmi/ipmi-sel.c           | 13 +++++++++++--
 include/ipmi.h               |  4 ----
 include/platform.h           | 22 ++++++++++++++++++++++
 platforms/astbmc/astbmc.h    |  2 ++
 platforms/astbmc/common.c    | 17 +++++++++++++++++
 platforms/astbmc/firestone.c |  1 +
 platforms/astbmc/garrison.c  |  1 +
 platforms/astbmc/habanero.c  |  1 +
 platforms/astbmc/palmetto.c  |  1 +
 10 files changed, 67 insertions(+), 6 deletions(-)

diff --git a/core/platform.c b/core/platform.c
index 9171fa3..ab7eaba 100644
--- a/core/platform.c
+++ b/core/platform.c
@@ -28,6 +28,7 @@
 
 bool manufacturing_mode = false;
 struct platform	platform;
+const struct bmc_platform *bmc_platform = NULL;
 
 DEFINE_LOG_ENTRY(OPAL_RC_ABNORMAL_REBOOT, OPAL_PLATFORM_ERR_EVT, OPAL_CEC,
 		 OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT,
@@ -128,6 +129,13 @@ static struct platform generic_platform = {
 	.cec_power_down	= generic_cec_power_down,
 };
 
+void set_bmc_platform(const struct bmc_platform *bmc)
+{
+	if (bmc)
+		prlog(PR_NOTICE, "PLAT: Detected BMC platform %s\n", bmc->name);
+	bmc_platform = bmc;
+}
+
 void probe_platform(void)
 {
 	struct platform *platforms = &__platforms_start;
@@ -154,8 +162,11 @@ void probe_platform(void)
 	}
 
 	prlog(PR_NOTICE, "PLAT: Detected %s platform\n", platform.name);
+
+	set_bmc_platform(platform.bmc);
 }
 
+
 int start_preload_resource(enum resource_id id, uint32_t subid,
 			   void *buf, size_t *len)
 {
diff --git a/hw/ipmi/ipmi-sel.c b/hw/ipmi/ipmi-sel.c
index 369cebc..49d8044 100644
--- a/hw/ipmi/ipmi-sel.c
+++ b/hw/ipmi/ipmi-sel.c
@@ -386,7 +386,11 @@ static void ipmi_elog_poll(struct ipmi_msg *msg)
 		req_size = IPMI_MAX_REQ_SIZE;
 	}
 
-	ipmi_init_msg(msg, IPMI_DEFAULT_INTERFACE, IPMI_PARTIAL_ADD_ESEL,
+	/* By this stage we need to know how to send ESELs */
+	assert(bmc_platform && bmc_platform->ipmi_oem_cmd);
+
+	ipmi_init_msg(msg, IPMI_DEFAULT_INTERFACE,
+		      bmc_platform->ipmi_oem_cmd(IPMI_OEM_PARTIAL_ADD_ESEL),
 		      ipmi_elog_poll, elog_buf, req_size, 2);
 
 	msg->data[0] = reservation_id & 0xff;
@@ -462,8 +466,13 @@ static void sel_pnor(uint8_t access)
 		if (granted)
 			occ_pnor_set_owner(PNOR_OWNER_EXTERNAL);
 
+		if (!bmc_platform || !bmc_platform->ipmi_oem_cmd) {
+			prlog(PR_NOTICE, "PNOR access request ignored, BMC not detected yet\n");
+			break;
+		}
+
 		/* Ack the request */
-		msg = ipmi_mkmsg_simple(IPMI_PNOR_ACCESS_STATUS, &granted, 1);
+		msg = ipmi_mkmsg_simple(bmc_platform->ipmi_oem_cmd(IPMI_OEM_PNOR_ACCESS_STATUS), &granted, 1);
 		ipmi_queue_msg(msg);
 		break;
 	case RELEASE_PNOR:
diff --git a/include/ipmi.h b/include/ipmi.h
index a6791e4..7a30449 100644
--- a/include/ipmi.h
+++ b/include/ipmi.h
@@ -120,10 +120,6 @@
 #define IPMI_GET_BT_CAPS		IPMI_CODE(IPMI_NETFN_APP, 0x36)
 #define IPMI_SET_SENSOR_READING		IPMI_CODE(IPMI_NETFN_SE, 0x30)
 
-/* AMI OEM comamnds. AMI uses NETFN 0x3a and 0x32 */
-#define IPMI_PARTIAL_ADD_ESEL		IPMI_CODE(0x32, 0xf0)
-#define IPMI_PNOR_ACCESS_STATUS 	IPMI_CODE(0x3a, 0x07)
-
 /*
  * IPMI response codes.
  */
diff --git a/include/platform.h b/include/platform.h
index ff75adf..ea094c8 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -31,6 +31,18 @@ enum resource_id {
 #define RESOURCE_SUBID_NONE 0
 #define RESOURCE_SUBID_SUPPORTED 1
 
+enum ipmi_oem_cmds {
+	IPMI_OEM_PARTIAL_ADD_ESEL,
+	IPMI_OEM_PNOR_ACCESS_STATUS
+};
+
+struct bmc_platform {
+	const char *name;
+
+	/* Map IPMI_OEM_X to vendor command for this BMC */
+	uint32_t (*ipmi_oem_cmd)(enum ipmi_oem_cmds cmd);
+};
+
 /*
  * Each platform can provide a set of hooks
  * that can affect the generic code
@@ -39,6 +51,13 @@ struct platform {
 	const char	*name;
 
 	/*
+	 * If BMC is constant, bmc platform specified here.
+	 * Platforms can also call set_bmc_platform() if BMC platform is
+	 * not a constant.
+	 */
+	const struct bmc_platform *bmc;
+
+	/*
 	 * Probe platform, return true on a match, called before
 	 * any allocation has been performed outside of the heap
 	 * so the platform can perform additional memory reservations
@@ -174,6 +193,7 @@ extern struct platform __platforms_start;
 extern struct platform __platforms_end;
 
 extern struct platform	platform;
+extern const struct bmc_platform *bmc_platform;
 
 extern bool manufacturing_mode;
 
@@ -189,4 +209,6 @@ extern int resource_loaded(enum resource_id id, uint32_t idx);
 
 extern int wait_for_resource_loaded(enum resource_id id, uint32_t idx);
 
+extern void set_bmc_platform(const struct bmc_platform *bmc);
+
 #endif /* __PLATFORM_H */
diff --git a/platforms/astbmc/astbmc.h b/platforms/astbmc/astbmc.h
index 322282e..fbba095 100644
--- a/platforms/astbmc/astbmc.h
+++ b/platforms/astbmc/astbmc.h
@@ -41,6 +41,8 @@ struct slot_table_entry {
 	const struct slot_table_entry *children;
 };
 
+extern const struct bmc_platform astbmc_ami;
+
 extern void astbmc_early_init(void);
 extern int64_t astbmc_ipmi_reboot(void);
 extern int64_t astbmc_ipmi_power_down(uint64_t request);
diff --git a/platforms/astbmc/common.c b/platforms/astbmc/common.c
index e1a8a4d..94978d6 100644
--- a/platforms/astbmc/common.c
+++ b/platforms/astbmc/common.c
@@ -357,3 +357,20 @@ void astbmc_early_init(void)
 
 	prd_init();
 }
+
+static uint32_t ami_ipmi_oem_cmd(enum ipmi_oem_cmds cmd)
+{
+	switch (cmd) {
+	case IPMI_OEM_PARTIAL_ADD_ESEL:
+		return IPMI_CODE(0x32, 0xf0);
+	case IPMI_OEM_PNOR_ACCESS_STATUS:
+		return IPMI_CODE(0x3a, 0x07);
+	}
+
+	return 0;
+}
+
+const struct bmc_platform astbmc_ami = {
+	.name = "AMI",
+	.ipmi_oem_cmd = ami_ipmi_oem_cmd,
+};
diff --git a/platforms/astbmc/firestone.c b/platforms/astbmc/firestone.c
index c4e6b2a..3c36660 100644
--- a/platforms/astbmc/firestone.c
+++ b/platforms/astbmc/firestone.c
@@ -146,6 +146,7 @@ static bool firestone_probe(void)
 
 DECLARE_PLATFORM(firestone) = {
 	.name			= "Firestone",
+	.bmc			= &astbmc_ami,
 	.probe			= firestone_probe,
 	.init			= astbmc_init,
 	.pci_get_slot_info	= slot_table_get_slot_info,
diff --git a/platforms/astbmc/garrison.c b/platforms/astbmc/garrison.c
index f400a51..ba7211f 100644
--- a/platforms/astbmc/garrison.c
+++ b/platforms/astbmc/garrison.c
@@ -293,6 +293,7 @@ static bool garrison_probe(void)
 
 DECLARE_PLATFORM(garrison) = {
 	.name			= "Garrison",
+	.bmc			= &astbmc_ami,
 	.probe			= garrison_probe,
 	.init			= astbmc_init,
 	.pci_get_slot_info	= slot_table_get_slot_info,
diff --git a/platforms/astbmc/habanero.c b/platforms/astbmc/habanero.c
index 738aa63..4640e3a 100644
--- a/platforms/astbmc/habanero.c
+++ b/platforms/astbmc/habanero.c
@@ -141,6 +141,7 @@ static bool habanero_probe(void)
 
 DECLARE_PLATFORM(habanero) = {
 	.name			= "Habanero",
+	.bmc			= &astbmc_ami,
 	.probe			= habanero_probe,
 	.init			= astbmc_init,
 	.pci_get_slot_info	= slot_table_get_slot_info,
diff --git a/platforms/astbmc/palmetto.c b/platforms/astbmc/palmetto.c
index 033f103..58ed861 100644
--- a/platforms/astbmc/palmetto.c
+++ b/platforms/astbmc/palmetto.c
@@ -46,6 +46,7 @@ static bool palmetto_probe(void)
 DECLARE_PLATFORM(palmetto) = {
 	.name			= "Palmetto",
 	.probe			= palmetto_probe,
+	.bmc			= &astbmc_ami,
 	.init			= astbmc_init,
 	.external_irq		= astbmc_ext_irq_serirq_cpld,
 	.cec_power_down         = astbmc_ipmi_power_down,
-- 
2.7.4



More information about the Skiboot mailing list