[Skiboot] [RFC PATCH] Enable PLDM by default and select it dynamically

Nicholas Piggin npiggin at gmail.com
Mon May 19 12:11:21 AEST 2025


This is an initial hack at enabling PLDM by default and selecting
between it and IPMI at boot time depending on detected capabilities.
Not tested at all.

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 Makefile                  |  2 +-
 core/init.c               | 31 ++++++++++++++----------------
 core/pldm/pldm-mctp.c     |  9 +++++++++
 hw/ast-bmc/ast-mctp.c     | 40 +++++++++++++++++++++++++++++----------
 hw/bt.c                   | 10 ++++++----
 include/ast.h             | 11 +++++++++++
 include/bt.h              |  2 +-
 include/pldm.h            |  9 +++++++++
 platforms/astbmc/astbmc.h |  1 -
 platforms/astbmc/common.c | 40 +++++++++++++++++++++++++++++++--------
 platforms/qemu/qemu.c     | 17 +++++++++--------
 11 files changed, 122 insertions(+), 50 deletions(-)

diff --git a/Makefile b/Makefile
index 03a0a8773..d67413926 100644
--- a/Makefile
+++ b/Makefile
@@ -62,7 +62,7 @@ CONFIG_FSP?=1
 # Try to build without POWER8 support
 CONFIG_P8?=1
 # Try to build without PLDM code
-CONFIG_PLDM?=0
+CONFIG_PLDM?=1
 
 #
 # Where is the source directory, must be a full path (no ~)
diff --git a/core/init.c b/core/init.c
index fae6ec62f..dc369c517 100644
--- a/core/init.c
+++ b/core/init.c
@@ -563,12 +563,11 @@ void __noreturn load_and_boot_kernel(bool is_reboot)
 
 	trustedboot_exit_boot_services();
 
-#ifdef CONFIG_PLDM
-	pldm_platform_send_progress_state_change(
-		PLDM_STATE_SET_BOOT_PROG_STATE_STARTING_OP_SYS);
-#else
-	ipmi_set_fw_progress_sensor(IPMI_FW_OS_BOOT);
-#endif
+	if (use_pldm())
+		pldm_platform_send_progress_state_change(
+			PLDM_STATE_SET_BOOT_PROG_STATE_STARTING_OP_SYS);
+	else
+		ipmi_set_fw_progress_sensor(IPMI_FW_OS_BOOT);
 
 	if (!is_reboot) {
 		/* We wait for the nvram read to complete here so we can
@@ -1413,19 +1412,17 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)
 	/* Setup ibm,firmware-versions if able */
 	if (platform.bmc) {
 		flash_dt_add_fw_version();
-#ifdef CONFIG_PLDM
-		pldm_fru_dt_add_bmc_version();
-#else
-		ipmi_dt_add_bmc_info();
-#endif
+		if (use_pldm())
+			pldm_fru_dt_add_bmc_version();
+		else
+			ipmi_dt_add_bmc_info();
 	}
 
-#ifdef CONFIG_PLDM
-	pldm_platform_send_progress_state_change(
-		PLDM_STATE_SET_BOOT_PROG_STATE_PCI_RESORUCE_CONFIG);
-#else
-	ipmi_set_fw_progress_sensor(IPMI_FW_PCI_INIT);
-#endif
+	if (use_pldm())
+		pldm_platform_send_progress_state_change(
+			PLDM_STATE_SET_BOOT_PROG_STATE_PCI_RESORUCE_CONFIG);
+	else
+		ipmi_set_fw_progress_sensor(IPMI_FW_PCI_INIT);
 
 	/*
 	 * These last few things must be done as late as possible
diff --git a/core/pldm/pldm-mctp.c b/core/pldm/pldm-mctp.c
index fb7d8a1cb..a0f62e41b 100644
--- a/core/pldm/pldm-mctp.c
+++ b/core/pldm/pldm-mctp.c
@@ -72,6 +72,13 @@ out:
 	return rc;
 }
 
+static bool using_pldm;
+
+bool use_pldm(void)
+{
+	return using_pldm;
+}
+
 int pldm_mctp_init(void)
 {
 	int nbr_elt = 8, rc = OPAL_SUCCESS;
@@ -108,6 +115,8 @@ int pldm_mctp_init(void)
 		}
 	}
 
+	using_pldm = true;
+
 out:
 	prlog(PR_NOTICE, "%s - done, rc: %d\n", __func__, rc);
 	return rc;
diff --git a/hw/ast-bmc/ast-mctp.c b/hw/ast-bmc/ast-mctp.c
index 22578e0a5..0d07abd0d 100644
--- a/hw/ast-bmc/ast-mctp.c
+++ b/hw/ast-bmc/ast-mctp.c
@@ -32,6 +32,16 @@ static struct lock mctp_lock = LOCK_UNLOCKED;
 #define KCS_STATUS_BMC_READY 0x80
 #define KCS_STATUS_OBF       0x01
 
+/*
+ * Current OpenBMC systems put the MCTP buffer 1MB down from
+ * the end of the LPC FW range.
+ *
+ * The size of the FW range is: 0x1000_0000 so the window be at:
+ *
+ *   0x1000_0000 - 2**20 == 0xff00000
+ */
+#define MCTP_FW_ADDR 0xff00000
+
 #define HOST_MAX_INCOMING_MESSAGE_ALLOCATION 131072
 #define DESIRED_MTU 32768
 
@@ -170,15 +180,7 @@ static int astlpc_binding(void)
 	if (!ops_data)
 		return OPAL_NO_MEM;
 
-	/*
-	 * Current OpenBMC systems put the MCTP buffer 1MB down from
-	 * the end of the LPC FW range.
-	 *
-	 * The size of the FW range is: 0x1000_0000 so the window be at:
-	 *
-	 *   0x1000_0000 - 2**20 == 0xff00000
-	 */
-	ops_data->lpc_fw_addr = 0xff00000;
+	ops_data->lpc_fw_addr = MCTP_FW_ADDR;
 
 	/* values chosen by the OpenBMC driver */
 	ops_data->kcs_data_addr = KCS_DATA_REG;
@@ -306,6 +308,24 @@ static void message_rx(uint8_t eid, bool tag_owner,
 	}
 }
 
+#define ASTLPC_MCTP_MAGIC	0x4d435450
+
+bool ast_mctp_available(void)
+{
+	uint32_t data;
+
+	if (!dt_find_compatible_node(dt_root, NULL, "mctp"))
+		return false;
+	if (lpc_probe_read(OPAL_LPC_IO, KCS_STATUS_REG, &data, 1))
+		return false;
+	if (lpc_probe_read(OPAL_LPC_FW, MCTP_FW_ADDR, &data, 4))
+		return false;
+	if (data != cpu_to_be32(ASTLPC_MCTP_MAGIC))
+		return false;
+
+	return true;
+}
+
 /*
  * Initialize mctp binding for hbrt and provide interfaces for sending
  * and receiving mctp messages.
@@ -315,9 +335,9 @@ int ast_mctp_init(void)
 	uint32_t kcs_serial_irq;
 	struct dt_node *n;
 
-	/* Search mctp node */
 	n = dt_find_compatible_node(dt_root, NULL, "mctp");
 	if (!n) {
+		/* Caller should have checked available already */
 		prlog(PR_ERR, "No MCTP device\n");
 		return OPAL_PARAMETER;
 	}
diff --git a/hw/bt.c b/hw/bt.c
index b41e5ab81..ee7c8893b 100644
--- a/hw/bt.c
+++ b/hw/bt.c
@@ -678,7 +678,7 @@ static struct lpc_client bt_lpc_client = {
 	.interrupt = bt_irq,
 };
 
-void bt_init(void)
+int bt_init(void)
 {
 	struct dt_node *n;
 	const struct dt_property *prop;
@@ -695,18 +695,18 @@ void bt_init(void)
 	n = dt_find_compatible_node(dt_root, NULL, "ipmi-bt");
 	if (!n) {
 		prerror("No BT device\n");
-		return;
+		return OPAL_PARAMETER;
 	}
 
 	/* Get IO base */
 	prop = dt_find_property(n, "reg");
 	if (!prop) {
 		prerror("Can't find reg property\n");
-		return;
+		return OPAL_PARAMETER;
 	}
 	if (dt_property_get_cell(prop, 0) != OPAL_LPC_IO) {
 		prerror("Only supports IO addresses\n");
-		return;
+		return OPAL_PARAMETER;
 	}
 	bt.base_addr = dt_property_get_cell(prop, 1);
 	init_timer(&bt.poller, bt_poll, NULL);
@@ -743,4 +743,6 @@ void bt_init(void)
 	get_bt_caps();
 
 	prlog(PR_DEBUG, "Using LPC IRQ %d\n", irq);
+
+	return OPAL_SUCCESS;
 }
diff --git a/include/ast.h b/include/ast.h
index 71237fbb7..ef7f5c81f 100644
--- a/include/ast.h
+++ b/include/ast.h
@@ -24,6 +24,9 @@
 
 /* LPC registers */
 #define LPC_BASE		0x1e789000
+#define LPC_HICR4		(LPC_BASE + 0x10)
+#define  LPC_HICR4_BT_ENABLE	(1 << 0)
+#define  LPC_HICR4_KCS_ENABLE	(1 << 2)
 #define LPC_HICR6		(LPC_BASE + 0x80)
 #define LPC_HICR7		(LPC_BASE + 0x88)
 #define LPC_HICR8		(LPC_BASE + 0x8c)
@@ -116,6 +119,14 @@ enum mctp_msg_type {
 
 int ast_mctp_message_tx(bool tag_owner, uint8_t msg_tag,
 			uint8_t *msg, int msg_len);
+#ifdef CONFIG_PLDM
+bool ast_mctp_available(void);
+#else
+static inline bool ast_mctp_available(void)
+{
+	return false;
+}
+#endif
 int ast_mctp_init(void);
 void ast_mctp_exit(void);
 
diff --git a/include/bt.h b/include/bt.h
index dd2e7b65a..b9932cf76 100644
--- a/include/bt.h
+++ b/include/bt.h
@@ -5,6 +5,6 @@
 #define __BT_H
 
 /* Initialise the BT interface */
-void bt_init(void);
+int bt_init(void);
 
 #endif
diff --git a/include/pldm.h b/include/pldm.h
index 54c9bd4bc..a11885ca2 100644
--- a/include/pldm.h
+++ b/include/pldm.h
@@ -8,6 +8,15 @@
 #include <skiboot.h>
 #include <pldm/include/libpldm/state_set.h>
 
+#ifdef CONFIG_PLDM
+bool use_pldm(void);
+#else
+static inline bool use_pldm(void)
+{
+	return false;
+}
+#endif
+
 /**
  * Handle PLDM messages received from MCTP
  */
diff --git a/platforms/astbmc/astbmc.h b/platforms/astbmc/astbmc.h
index 7783fe20c..c9bba3a81 100644
--- a/platforms/astbmc/astbmc.h
+++ b/platforms/astbmc/astbmc.h
@@ -97,7 +97,6 @@ extern void astbmc_early_init(void);
 extern int64_t astbmc_ipmi_reboot(void);
 extern int64_t astbmc_ipmi_power_down(uint64_t request);
 #ifdef CONFIG_PLDM
-extern int astbmc_pldm_init(void);
 extern int pnor_pldm_init(void);
 #endif
 extern void astbmc_init(void);
diff --git a/platforms/astbmc/common.c b/platforms/astbmc/common.c
index 8d1ceb921..6e15baf4e 100644
--- a/platforms/astbmc/common.c
+++ b/platforms/astbmc/common.c
@@ -137,9 +137,9 @@ static int astbmc_fru_init(void)
 	return 0;
 }
 
-#ifdef CONFIG_PLDM
-int astbmc_pldm_init(void)
+static int astbmc_pldm_init(void)
 {
+#ifdef CONFIG_PLDM
 	int rc = OPAL_SUCCESS;
 
 	/* PLDM over MCTP */
@@ -165,16 +165,22 @@ int astbmc_pldm_init(void)
 		prlog(PR_WARNING, "Failed to configure PLDM\n");
 
 	return rc;
-}
+#else
+	assert(0); /* Not reached */
 #endif
+}
 
-void astbmc_init(void)
+static int astbmc_ipmi_init(void)
 {
+	int rc;
+
 	/* Register the BT interface with the IPMI layer
 	 *
 	 * Initialise this first to enable PNOR access
 	 */
-	bt_init();
+	rc = bt_init();
+	if (rc)
+		return rc;
 
 	/* Initialize PNOR/NVRAM */
 	pnor_init();
@@ -201,6 +207,24 @@ void astbmc_init(void)
 
 	/* Setup UART console for use by Linux via OPAL API */
 	set_opal_console(&uart_opal_con);
+
+	return OPAL_SUCCESS;
+}
+
+void astbmc_init(void)
+{
+	prlog(PR_ERR, "PLAT: Checking platform management\n");
+	if (ast_mctp_available()) {
+		if (astbmc_pldm_init() == OPAL_SUCCESS) {
+			prlog(PR_NOTICE, "PLAT: Using PLDM for platform management\n");
+			return;
+		}
+	}
+	if (astbmc_ipmi_init() == OPAL_SUCCESS) {
+		prlog(PR_NOTICE, "PLAT: Using IPMI for platform management\n");
+		return;
+	}
+	prlog(PR_ERR, "PLAT: Unable to initialise platform management\n");
 }
 
 int64_t astbmc_ipmi_power_down(uint64_t request)
@@ -600,9 +624,9 @@ void astbmc_early_init(void)
 
 void astbmc_exit(void)
 {
-#ifdef CONFIG_PLDM
-	return;
-#endif
+	if (use_pldm())
+		return;
+
 	ipmi_wdt_final_reset();
 
 	ipmi_set_boot_count();
diff --git a/platforms/qemu/qemu.c b/platforms/qemu/qemu.c
index c6c6a5007..d40e8381a 100644
--- a/platforms/qemu/qemu.c
+++ b/platforms/qemu/qemu.c
@@ -10,6 +10,7 @@
 #include <platforms/astbmc/astbmc.h>
 
 static bool bt_device_present;
+static bool kcs_device_present;
 
 ST_PLUGGABLE(qemu_slot0, "pcie.0");
 ST_PLUGGABLE(qemu_slot1, "pcie.1");
@@ -51,6 +52,11 @@ static bool qemu_probe_common(const char *compat)
 		bt_device_present = true;
 	}
 
+	/* check if the KCS device was defined by QEMU */
+	dt_for_each_compatible(dt_root, n, "kcs") {
+		kcs_device_present = true;
+	}
+
 	slot_table_init(qemu_phb_table);
 
 	return true;
@@ -83,15 +89,10 @@ static bool qemu_probe_powernv11(void)
 
 static void qemu_init(void)
 {
-	if (!bt_device_present) {
-		set_opal_console(&uart_opal_con);
-	} else {
-#ifdef CONFIG_PLDM
-		/* need to be checked according platform: P10, P11 ... */
-		astbmc_pldm_init();
-#else
+	if (bt_device_present || kcs_device_present) {
 		astbmc_init();
-#endif
+	} else {
+		set_opal_console(&uart_opal_con);
 	}
 }
 
-- 
2.47.1



More information about the Skiboot mailing list