diff mbox series

[V3,08/21] core/pldm: Encode GetPLDMVersion response

Message ID 20220318143619.83489-9-clombard@linux.vnet.ibm.com
State Superseded
Headers show
Series Implement MCTP and PLDM features | expand

Commit Message

Christophe Lombard March 18, 2022, 2:36 p.m. UTC
The GetPLDMVersion command can be used to retrieve the PLDM base
specification versions that the PLDM terminus supports, as well as the
PLDM Type specification versions supported for each PLDM Type.

The reported version for Type 0 (PLDMbase) shall be encoded as 0xF1F1F000.

Reviewed-by: Abhishek Singh Tomar <abhishek at linux.ibm.com>
Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
---
 core/pldm/pldm-responder.c | 63 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)
diff mbox series

Patch

diff --git a/core/pldm/pldm-responder.c b/core/pldm/pldm-responder.c
index 88cf47ba..dd11a05d 100644
--- a/core/pldm/pldm-responder.c
+++ b/core/pldm/pldm-responder.c
@@ -166,6 +166,7 @@  static struct pldm_cmd base_get_types = {
 /*
  * Extended error codes defined for the Base command set.
  */
+#define INVALID_TRANSFER_OPERATION_FLAG		0x80
 #define INVALID_PLDM_TYPE_IN_REQUEST_DATA	0x83
 #define INVALID_PLDM_VERSION_IN_REQUEST_DATA	0x84
 
@@ -232,6 +233,67 @@  static struct pldm_cmd base_get_commands = {
 	.handler = get_commands_handler,
 };
 
+/*
+ * GetPLDMVersion (0x03)
+ * The GetPLDMVersion command can be used to retrieve the PLDM base
+ * specification versions that the PLDM terminus supports, as well as
+ * the PLDM Type specification versions supported for each PLDM Type.
+ */
+static int get_version_handler(const struct pldm_rx_data *req)
+{
+	const struct pldm_type *type;
+	uint32_t tmp[2];
+	char resp_buf[PKT_SIZE(struct pldm_get_version_resp) + sizeof(tmp)];
+	uint8_t type_id, opflag;
+	size_t payload_len;
+	uint32_t xfer_handle;
+	int rc;
+
+	payload_len = req->msg_len - sizeof(struct pldm_msg_hdr);
+	rc = decode_get_version_req(req->msg, payload_len,
+				    &xfer_handle,
+				    &opflag,
+				    &type_id);
+	if (rc) {
+		pldm_cc_resp(req, PLDM_ERROR);
+		return OPAL_INTERNAL_ERROR;
+	}
+
+	/* reject multipart requests */
+	if (opflag != PLDM_GET_FIRSTPART) {
+		pldm_cc_resp(req, INVALID_TRANSFER_OPERATION_FLAG);
+		return OPAL_PARAMETER;
+	}
+
+	type = find_type(type_id);
+	if (!type) {
+		pldm_cc_resp(req, INVALID_PLDM_TYPE_IN_REQUEST_DATA);
+		return OPAL_PARAMETER;
+	}
+
+	/* pack a scratch buffer with our version(s) and CRC32 the lot */
+	memcpy(&tmp[0], &type->version, 4);
+
+	tmp[1] = cpu_to_le32(pldm_crc32(&type->version, 4));
+
+	memset(resp_buf, 0, sizeof(resp_buf));
+	encode_get_version_resp(req->hdrinf.instance,
+				PLDM_SUCCESS,
+				0x0, /* no handle */
+				PLDM_START_AND_END,
+				(ver32_t *) tmp,
+				sizeof(tmp),
+				(void *) resp_buf);
+	pldm_send(req->source_eid, resp_buf, sizeof(resp_buf));
+
+	return 0;
+}
+static struct pldm_cmd base_get_version = {
+	.name = "GetPLDMVersion",
+	.pldm_cmd_id = PLDM_GET_PLDM_VERSION,
+	.handler = get_version_handler,
+};
+
 int pldm_rx_handle_request(struct pldm_rx_data *rx)
 {
 	const struct pldm_type *t;
@@ -260,6 +322,7 @@  int pldm_mctp_responder_init(void)
 	pldm_add_cmd(&pldm_base_type, &base_get_tid);
 	pldm_add_cmd(&pldm_base_type, &base_get_types);
 	pldm_add_cmd(&pldm_base_type, &base_get_commands);
+	pldm_add_cmd(&pldm_base_type, &base_get_version);
 
 	return OPAL_SUCCESS;
 }