@@ -7,7 +7,7 @@ SUBDIRS += $(PLDM_DIR)
CPPFLAGS += -I$(SRC)/pldm/include/
CPPFLAGS += -I$(SRC)/pldm/include/libpldm/oem/ibm/
-PLDM_OBJS = pldm-mctp.o
+PLDM_OBJS = pldm-mctp.o pldm-responder.o
PLDM = $(PLDM_DIR)/built-in.a
$(PLDM): $(PLDM_OBJS:%=$(PLDM_DIR)/%)
@@ -53,6 +53,17 @@ int pldm_mctp_message_rx(uint8_t eid, bool tag_owner, uint8_t msg_tag,
goto out;
}
+ switch (rx->hdrinf.msg_type) {
+ case PLDM_REQUEST:
+ rc = pldm_responder_handle_request(rx);
+ break;
+ default:
+ prlog(PR_ERR, "%s: message not supported (msg type: 0%x)\n",
+ __func__, rx->hdrinf.msg_type);
+ rc = OPAL_PARAMETER;
+ break;
+ }
+
out:
free(rx);
return rc;
@@ -60,14 +71,16 @@ out:
int pldm_mctp_init(void)
{
- int nbr_elt = 1, rc = OPAL_SUCCESS;
+ int nbr_elt = 2, rc = OPAL_SUCCESS;
int (*pldm_config[])(void) = {
ast_mctp_init, /* MCTP Binding */
+ pldm_responder_init, /* Register mandatory commands we'll respond to */
};
const char *pldm_config_error[] = {
"Failed to bind MCTP",
+ "Failed to register mandatory commands",
};
prlog(PR_NOTICE, "%s - Getting PLDM data\n", __func__);
new file mode 100644
@@ -0,0 +1,154 @@
+// 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 <libpldm/utils.h>
+#include "pldm.h"
+
+struct pldm_type {
+ const char *name;
+ int pldm_type_id;
+ ver32_t version;
+
+ struct list_head commands;
+ struct list_node link;
+};
+
+struct pldm_cmd {
+ const char *name;
+ int pldm_cmd_id;
+
+ int (*handler)(const struct pldm_rx_data *rx);
+
+ struct list_node link; /* link in the msg type's command list */
+};
+
+/*
+ * Send a response with just a completion code and no payload
+ */
+static int cc_resp(const struct pldm_rx_data *rx, uint8_t type,
+ uint8_t command, uint8_t cc)
+{
+ size_t data_size = PLDM_MSG_SIZE(uint8_t);
+ struct pldm_tx_data *tx;
+ int rc;
+
+ /* Encode the cc response */
+ tx = zalloc(sizeof(struct pldm_tx_data) + data_size);
+ if (!tx)
+ return OPAL_NO_MEM;
+ tx->data_size = data_size;
+ tx->tag_owner = true;
+ tx->msg_tag = rx->msg_tag;
+
+ encode_cc_only_resp(rx->hdrinf.instance,
+ type,
+ command,
+ cc,
+ (struct pldm_msg *)tx->data);
+
+ rc = pldm_mctp_message_tx(tx);
+ if (rc) {
+ prlog(PR_ERR, "Failed to send response message containing only cc, "
+ "rc = %d, cc = %d\n", rc, cc);
+ free(tx);
+ return OPAL_HARDWARE;
+ }
+
+ free(tx);
+ return OPAL_SUCCESS;
+}
+
+/*
+ * 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 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_responder_handle_request(struct pldm_rx_data *rx)
+{
+ const struct pldm_type *type;
+ const struct pldm_cmd *cmd;
+
+ prlog(PR_INFO, "Receive PLDM request from BMC, type: 0x%x, command: 0x%x\n",
+ rx->hdrinf.pldm_type, rx->hdrinf.command);
+
+ type = find_type(rx->hdrinf.pldm_type);
+ if (!type) {
+ prlog(PR_ERR, "Type not supported, type: 0x%x\n",
+ rx->hdrinf.pldm_type);
+ cc_resp(rx, rx->hdrinf.pldm_type,
+ rx->hdrinf.command,
+ PLDM_ERROR_INVALID_PLDM_TYPE);
+ return OPAL_UNSUPPORTED;
+ }
+
+ cmd = find_cmd(type, rx->hdrinf.command);
+ if (!cmd) {
+ prlog(PR_ERR, "Command not supported, type: 0x%x, command: 0x%x\n",
+ rx->hdrinf.pldm_type, rx->hdrinf.command);
+ cc_resp(rx, rx->hdrinf.pldm_type,
+ rx->hdrinf.command,
+ PLDM_ERROR_UNSUPPORTED_PLDM_CMD);
+ return OPAL_UNSUPPORTED;
+ }
+
+ return cmd->handler(rx);
+}
+
+int pldm_responder_init(void)
+{
+ /* Register mandatory commands we'll respond to - DSP0240 */
+ add_type(&pldm_base_type);
+
+ return OPAL_SUCCESS;
+}
@@ -9,6 +9,8 @@
#include <base.h>
#include <pldm.h>
+#define PLDM_MSG_SIZE(x) (sizeof(struct pldm_msg_hdr) + sizeof(x))
+
struct pldm_tx_data {
/* Contains an message header and payload of an MCTP packet.
* Size of data[]
@@ -41,4 +43,8 @@ int pldm_mctp_message_tx(struct pldm_tx_data *tx);
int pldm_mctp_message_rx(uint8_t eid, bool tag_owner, uint8_t msg_tag,
const uint8_t *buf, int len);
+/* Responder support */
+int pldm_responder_handle_request(struct pldm_rx_data *rx);
+int pldm_responder_init(void);
+
#endif /* __COREPLDM_H__ */