[Skiboot] [PATCH 04/19] core/pldm: Add PLDM responder support

Christophe Lombard clombard at linux.vnet.ibm.com
Sat Feb 26 01:28:33 AEDT 2022


PLDM defines data representations and commands that abstract the platform
management hardware.

A PLDM Terminus (or responder) is defined as the point of communication
termination for PLDM messages and the PLDM functions associated with those
messages.
A PLDM terminus is not required to process more than one request at a time
(that is, it can be "single threaded" and does not have to accept and act
on new requests until it has finished responding to any previous request).

Some PLDM control and discovery requests (PLDM_TYPE = PLDM_BASE) are
mandatory a PLDM terminus has to answer.

These following mandatory PLDM command codes for PLDM messaging control
and discovery will be defined in next patches.
    GetTID          0x02
    GetPLDMVersion  0x03
    GetPLDMTypes    0x04
    GetPLDMCommands 0x05

Signed-off-by: Christophe Lombard <clombard at linux.vnet.ibm.com>
---
 core/pldm/Makefile.inc     |  13 ++++
 core/pldm/pldm-common.c    | 123 +++++++++++++++++++++++++++++++++++++
 core/pldm/pldm-responder.c | 117 +++++++++++++++++++++++++++++++++++
 core/pldm/pldm.h           |  48 +++++++++++++++
 include/pldm.h             |  13 ++++
 5 files changed, 314 insertions(+)
 create mode 100644 core/pldm/Makefile.inc
 create mode 100644 core/pldm/pldm-common.c
 create mode 100644 core/pldm/pldm-responder.c
 create mode 100644 core/pldm/pldm.h
 create mode 100644 include/pldm.h

diff --git a/core/pldm/Makefile.inc b/core/pldm/Makefile.inc
new file mode 100644
index 00000000..3909c86f
--- /dev/null
+++ b/core/pldm/Makefile.inc
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+# Copyright 2022 IBM Corp
+
+PLDM_DIR ?= core/pldm
+SUBDIRS += $(PLDM_DIR)
+
+CPPFLAGS += -I$(SRC)/pldm/libpldm/
+CPPFLAGS += -I$(SRC)/pldm/ibm/libpldm/
+
+PLDM_OBJS = pldm-common.o pldm-responder.o
+
+PLDM = $(PLDM_DIR)/built-in.a
+$(PLDM): $(PLDM_OBJS:%=$(PLDM_DIR)/%)
diff --git a/core/pldm/pldm-common.c b/core/pldm/pldm-common.c
new file mode 100644
index 00000000..76cb1aa5
--- /dev/null
+++ b/core/pldm/pldm-common.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+// Copyright 2022 IBM Corp.
+
+#define pr_fmt(fmt) "PLDM: " fmt
+
+#include <cpu.h>
+#include <opal.h>
+#include <stdio.h>
+#include <string.h>
+#include <ast.h>
+#include "pldm.h"
+
+/*
+ * Print content of PLDM message in hex mode.
+ * 15 bytes per line.
+ * Ex: pldm_send: 000: 08 01 00 00 02 00 01
+ */
+void printbuf(const char *name, const char *msg, int len)
+{
+	int i, j;
+	char linebuf[128];
+
+	linebuf[0] = 0;
+
+	for (i = 0; i < len; i += j) {
+		linebuf[0] = 0;
+		for (j = 0; i + j < len && j < 15; j++) {
+			char s[5];
+
+			snprintf(s, 5, "%02x ", msg[i + j]);
+			strcat(linebuf, s);
+		}
+		prlog(PR_TRACE, "%s: %03x: %s\n", name, i, linebuf);
+	}
+}
+
+/*
+ * Send PLDM message over MCTP
+ */
+int pldm_send(uint8_t *buf, int len)
+{
+	uint8_t *msg;
+	int rc;
+
+	/* Message TYPE: PLDM = 0x01 (000_0001b) - DSP0240 */
+	msg = malloc(len + 1);
+	msg[0] = 0x01;
+	memcpy(&msg[1], buf, len);
+
+	rc = ast_mctp_message_tx(BMC_EID, msg, len + 1);
+	free(msg);
+
+	return rc;
+}
+
+/*
+ * Handle messages received from MCTP
+ */
+static int pldm_handle(uint8_t eid, const uint8_t *buf, int len)
+{
+	struct pldm_rx_data rx;
+
+	if (len < sizeof(rx.msg->hdr)) {
+		prerror("%s: packet is smaller than pldm header\n", __func__);
+		return OPAL_EMPTY;
+	}
+
+	memset(&rx, 0, sizeof(rx));
+	rx.msg = (struct pldm_msg *) buf;
+	rx.source_eid = eid;
+	rx.msg_len = len;
+
+	if (unpack_pldm_header(&rx.msg->hdr, &rx.hdrinf)) {
+		prerror("%s: unable to decode header\n", __func__);
+		return OPAL_EMPTY;
+	}
+
+	switch (rx.hdrinf.msg_type) {
+	case PLDM_REQUEST:
+		return pldm_rx_handle_request(&rx);
+	break;
+	default:
+	break;
+	}
+
+	return OPAL_UNSUPPORTED;
+}
+
+/*
+ * MCTP message rx callback
+ */
+void pldm_rx_message(uint8_t eid, void *data __unused, void *vmsg,
+		     size_t len)
+{
+	uint8_t *msg = vmsg;
+
+	prlog(PR_DEBUG, "message received: msg: %p, len %zd (eid: %d)\n",
+			 msg, len, eid);
+
+	/* pldm message type */
+	if ((msg[0] & 0x7f) != 0x01) {
+		prerror("not a pldm message type\n");
+		return;
+	}
+
+	pldm_handle(eid, &msg[1], len - 1);
+}
+
+int pldm_mctp_init(void)
+{
+	int rc;
+
+	/* MCTP Binding */
+	rc = ast_mctp_init(pldm_rx_message);
+	if (rc)
+		goto out;
+
+	/* Register mandatory commands we'll respond to */
+	rc = pldm_mctp_responder_init();
+
+out:
+	return rc;
+}
diff --git a/core/pldm/pldm-responder.c b/core/pldm/pldm-responder.c
new file mode 100644
index 00000000..12e5b2c3
--- /dev/null
+++ b/core/pldm/pldm-responder.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+// Copyright 2022 IBM Corp.
+
+#define pr_fmt(fmt) "PLDM: " fmt
+
+#include <bitmap.h>
+#include <cpu.h>
+#include <opal.h>
+#include <stdio.h>
+#include <string.h>
+#include <pldm/libpldm/utils.h>
+#include "pldm.h"
+
+struct pldm_cmd {
+	const char *name;
+	int pldm_cmd_id;
+
+	int (*handler)(const struct pldm_rx_data *req);
+
+	struct list_node link; /* link in the msg type's command list */
+};
+
+/*
+ * Send a response with just a completion code and no payload
+ */
+static void pldm_cc_resp(const struct pldm_rx_data *req, int code)
+{
+	char resp_buf[PKT_SIZE(uint8_t)];
+
+	memset(resp_buf, 0, sizeof(resp_buf));
+
+	encode_cc_only_resp(req->hdrinf.instance,
+			    req->hdrinf.pldm_type,
+			    req->hdrinf.command,
+			    code,
+			    (void *) resp_buf);
+
+	pldm_send(resp_buf, sizeof(resp_buf)); /* a copy will be made */
+}
+
+/*
+ * PLDM Type / Command wrangling.
+ */
+LIST_HEAD(pldm_type_list);
+
+static const struct pldm_type *find_type(int type_id)
+{
+	struct pldm_type *iter;
+
+	list_for_each(&pldm_type_list, iter, link) {
+		if (iter->pldm_type_id == type_id)
+			return iter;
+	}
+
+	return NULL;
+}
+
+static const struct pldm_cmd *find_cmd(const struct pldm_type *type, int cmd)
+{
+	struct pldm_cmd *iter;
+
+	list_for_each(&type->commands, iter, link)
+		if (iter->pldm_cmd_id == cmd)
+			return iter;
+
+	return NULL;
+}
+
+static void pldm_add_type(struct pldm_type *new_type)
+{
+	assert(new_type->pldm_type_id < 32); /* limited by GetPLDMTypes */
+	assert(!find_type(new_type->pldm_type_id));
+
+	list_head_init(&new_type->commands);
+	list_add_tail(&pldm_type_list, &new_type->link);
+
+	prlog(PR_DEBUG, "Registered type %s (%d)\n",
+	      new_type->name, new_type->pldm_type_id);
+}
+
+/*
+ * PLDM Base commands support
+ */
+
+static struct pldm_type pldm_base_type = {
+	.name = "base",
+	.pldm_type_id = PLDM_BASE,
+	.version = { 0xF1, 0xF0, 0xF0, 0x00 },
+};
+
+int pldm_rx_handle_request(struct pldm_rx_data *rx)
+{
+	const struct pldm_type *t;
+	const struct pldm_cmd *c;
+
+	t = find_type(rx->hdrinf.pldm_type);
+	if (!t) {
+		pldm_cc_resp(rx, PLDM_ERROR_INVALID_PLDM_TYPE);
+		return OPAL_UNSUPPORTED;
+	}
+
+	c = find_cmd(t, rx->hdrinf.command);
+	if (!c) {
+		pldm_cc_resp(rx, PLDM_ERROR_UNSUPPORTED_PLDM_CMD);
+		return OPAL_UNSUPPORTED;
+	}
+
+	return c->handler(rx);
+}
+
+int pldm_mctp_responder_init(void)
+{
+	/* Register mandatory commands we'll respond to - DSP0240 */
+	pldm_add_type(&pldm_base_type);
+
+	return OPAL_SUCCESS;
+}
diff --git a/core/pldm/pldm.h b/core/pldm/pldm.h
new file mode 100644
index 00000000..10dccc3d
--- /dev/null
+++ b/core/pldm/pldm.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ * Copyright 2022 IBM Corp.
+ */
+
+#ifndef __COREPLDM_H__
+#define __COREPLDM_H__
+
+#include <pldm/libpldm/base.h>
+#include <pldm.h>
+
+/* Common support */
+
+void printbuf(const char *name, const char *msg, int len);
+
+/*
+ * For the EIDs: the valid range is 8-254.
+ * BMC EID default = 8.
+ */
+# define BMC_EID  8
+
+#define PKT_SIZE(x) (sizeof(struct pldm_msg_hdr) + sizeof(x))
+
+struct pldm_rx_data {
+	struct pldm_header_info hdrinf; /* parsed message header */
+
+	struct pldm_msg *msg;
+	int msg_len;
+	int source_eid;
+};
+
+struct pldm_type {
+	const char *name;
+	int pldm_type_id;
+	ver32_t version;
+
+	struct list_head commands;
+	struct list_node link;
+};
+
+int pldm_send(uint8_t *resp_buf, int len);
+void pldm_rx_message(uint8_t eid, void *data __unused, void *vmsg,
+		     size_t len);
+
+/* Responder support */
+int pldm_rx_handle_request(struct pldm_rx_data *rx);
+int pldm_mctp_responder_init(void);
+
+#endif /* __COREPLDM_H__ */
diff --git a/include/pldm.h b/include/pldm.h
new file mode 100644
index 00000000..d542e0eb
--- /dev/null
+++ b/include/pldm.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ * Copyright 2022 IBM Corp.
+ */
+
+#ifndef __PLDM_H__
+#define __PLDM_H__
+
+/**
+ * PLDM over MCTP initialization
+ */
+int pldm_mctp_init(void);
+
+#endif /* __PLDM_H__ */
-- 
2.35.1



More information about the Skiboot mailing list