diff mbox series

[V2,09/15] core/pldm: Decode the GetPDR request

Message ID 20220429094744.72855-10-clombard@linux.vnet.ibm.com
State Superseded
Headers show
Series Complete PLDM responder and enable PLDM support | expand

Commit Message

Christophe Lombard April 29, 2022, 9:47 a.m. UTC
The GetPDR command is used to retrieve individual PDRs from a PDR
repository. The record is identified by the PDR recordHandle value
that is passed in the request.

Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
---
 core/pldm/pldm-responder.c | 127 +++++++++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)

Comments

Frederic Barrat April 26, 2023, 2:47 p.m. UTC | #1
On 29/04/2022 11:47, Christophe Lombard wrote:
> The GetPDR command is used to retrieve individual PDRs from a PDR
> repository. The record is identified by the PDR recordHandle value
> that is passed in the request.
> 
> Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
> ---
>   core/pldm/pldm-responder.c | 127 +++++++++++++++++++++++++++++++++++++
>   1 file changed, 127 insertions(+)
> 
> diff --git a/core/pldm/pldm-responder.c b/core/pldm/pldm-responder.c
> index 8c543b6c..e8773beb 100644
> --- a/core/pldm/pldm-responder.c
> +++ b/core/pldm/pldm-responder.c
> @@ -776,6 +776,132 @@ static struct pldm_cmd pldm_platform_set_state_effecter_states = {
>   	.handler = platform_set_state_effecter_states_handler,
>   };
>   
> +struct get_pdr_req {
> +	uint32_t record_handle;
> +	uint32_t data_transfer_handle;
> +	uint8_t transfer_op_flag;
> +	uint16_t request_count;
> +	uint16_t record_change_number;
> +};
> +
> +/*
> + * GetPDR (0x51)
> + * The GetPDR command is used to retrieve individual PDRs from a PDR
> + * Repository. The record is identified by the PDR recordHandle value
> + * that is passed in the request.
> + */
> +static int platform_get_pdr_handle(const struct pldm_rx_data *req)
> +{
> +	size_t payload_len, response_length;
> +	uint32_t next_record_handle;
> +	struct get_pdr_req pdr_req;
> +	uint8_t *pdr_data = NULL;
> +	uint32_t pdr_data_size = 0;
> +	char *response_msg;
> +	int rc;
> +
> +	payload_len = req->msg_len - sizeof(struct pldm_msg_hdr);
> +	rc = decode_get_pdr_req(req->msg,
> +				payload_len,
> +				&pdr_req.record_handle,
> +				&pdr_req.data_transfer_handle,
> +				&pdr_req.transfer_op_flag,
> +				&pdr_req.request_count,
> +				&pdr_req.record_change_number);
> +	if (rc) {
> +		prlog(PR_ERR, "Failed to decode GetPDR request, rc = %d\n", rc);
> +		pldm_cc_resp(req, req->hdrinf.pldm_type,
> +			     req->hdrinf.command, PLDM_ERROR);
> +		return OPAL_INTERNAL_ERROR;
> +	}
> +
> +	if (pdr_req.data_transfer_handle != 0) {
> +		/* We don't support multipart transfers */
> +		prlog(PR_ERR, "Got invalid data transfer handle 0x%x in GetPDR request\n",
> +			      pdr_req.data_transfer_handle);
> +		pldm_cc_resp(req, req->hdrinf.pldm_type,
> +			     req->hdrinf.command,
> +			     PLDM_PLATFORM_INVALID_DATA_TRANSFER_HANDLE);
> +		return OPAL_PARAMETER;
> +	}
> +
> +	if (pdr_req.transfer_op_flag != PLDM_GET_FIRSTPART) {
> +		prlog(PR_ERR, "Got invalid transfer op flag 0x%x in GetPDR request\n",
> +			      pdr_req.transfer_op_flag);
> +		pldm_cc_resp(req, req->hdrinf.pldm_type,
> +			     req->hdrinf.command,
> +			     PLDM_PLATFORM_INVALID_TRANSFER_OPERATION_FLAG);
> +		return OPAL_PARAMETER;
> +	}
> +
> +	if (pdr_req.record_change_number != 0) {
> +		prlog(PR_ERR, "Got invalid record change number 0x%x in GetPDR request\n",
> +			      pdr_req.record_change_number);
> +		pldm_cc_resp(req, req->hdrinf.pldm_type,
> +			     req->hdrinf.command,
> +			     PLDM_PLATFORM_INVALID_RECORD_CHANGE_NUMBER);
> +		return OPAL_PARAMETER;
> +	}
> +
> +	/* find PDR record by record handle */
> +	prlog(PR_INFO, "BMC requesting PDR handle %d\n", pdr_req.record_handle);
> +
> +	rc = pldm_platform_pdr_find_record(pdr_req.record_handle,
> +					   &pdr_data,
> +					   &pdr_data_size,
> +					   &next_record_handle);
> +	if (rc) {
> +		prlog(PR_ERR, "Got invalid record handle 0x%x in GetPDR request\n",
> +			      pdr_req.record_handle);
> +		pldm_cc_resp(req, req->hdrinf.pldm_type,
> +			     req->hdrinf.command,
> +			     PLDM_PLATFORM_INVALID_RECORD_HANDLE);
> +		return OPAL_PARAMETER;
> +	}
> +
> +	response_length = sizeof(struct pldm_msg_hdr) +
> +			  sizeof(struct pldm_get_pdr_resp) +
> +			  pdr_data_size;
> +	response_msg = malloc(response_length);
> +	memset(response_msg, 0, response_length);

An updated version of this patch reads:
	response_msg = zalloc(response_length);
	memset(response_msg, 0, response_length);

so the memset is now useless.


> +
> +	/* create a PLDM response message for GetPDR */
> +	rc = encode_get_pdr_resp(req->hdrinf.instance,
> +				 PLDM_SUCCESS,
> +				 next_record_handle,
> +				 0, /* No remaining data */
> +				 PLDM_START_AND_END,
> +				 pdr_data_size,
> +				 pdr_data,
> +				 0, /* CRC not used for START_AND_END */
> +				 (struct pldm_msg *)response_msg);
> +	if (rc != PLDM_SUCCESS) {
> +		prlog(PR_ERR, "Encode GetPDR Error, rc: %d\n", rc);
> +		pldm_cc_resp(req, req->hdrinf.pldm_type,
> +			     req->hdrinf.command, PLDM_ERROR);
> +		free(response_msg);
> +		return OPAL_PARAMETER;
> +	}
> +
> +	/* send PLDM message over MCTP */
> +	rc = pldm_send(req->source_eid, response_msg, response_length - 1);


The "-1" is troubling.I think I see where it's coming from (the 
record_data field of struct pldm_get_pdr_resp). It would be cleared to 
compute the correct size in "response_length" above. That's also a 
pattern we see several times, so it may be worth checking that we do the 
same and right thing everywhere.

   Fred


> +	if (rc) {
> +		prlog(PR_ERR, "Failed to send GetPDR response, rc = %d\n", rc);
> +		free(response_msg);
> +		return OPAL_HARDWARE;
> +	}
> +
> +	free(response_msg);
> +
> +	return OPAL_SUCCESS;
> +}
> +
> +static struct pldm_cmd pldm_platform_get_pdr = {
> +	.name = "PLDM_GET_PDR",
> +	.pldm_cmd_id = PLDM_GET_PDR,
> +	.handler = platform_get_pdr_handle,
> +};
> +
>   int pldm_rx_handle_request(struct pldm_rx_data *rx)
>   {
>   	const struct pldm_type *t;
> @@ -822,6 +948,7 @@ int pldm_mctp_responder_init(void)
>   	pldm_add_cmd(&pldm_platform_type, &pldm_platform_event_message);
>   	pldm_add_cmd(&pldm_platform_type, &pldm_platform_get_state_sensor_readings);
>   	pldm_add_cmd(&pldm_platform_type, &pldm_platform_set_state_effecter_states);
> +	pldm_add_cmd(&pldm_platform_type, &pldm_platform_get_pdr);
>   
>   	return OPAL_SUCCESS;
>   }
diff mbox series

Patch

diff --git a/core/pldm/pldm-responder.c b/core/pldm/pldm-responder.c
index 8c543b6c..e8773beb 100644
--- a/core/pldm/pldm-responder.c
+++ b/core/pldm/pldm-responder.c
@@ -776,6 +776,132 @@  static struct pldm_cmd pldm_platform_set_state_effecter_states = {
 	.handler = platform_set_state_effecter_states_handler,
 };
 
+struct get_pdr_req {
+	uint32_t record_handle;
+	uint32_t data_transfer_handle;
+	uint8_t transfer_op_flag;
+	uint16_t request_count;
+	uint16_t record_change_number;
+};
+
+/*
+ * GetPDR (0x51)
+ * The GetPDR command is used to retrieve individual PDRs from a PDR
+ * Repository. The record is identified by the PDR recordHandle value
+ * that is passed in the request.
+ */
+static int platform_get_pdr_handle(const struct pldm_rx_data *req)
+{
+	size_t payload_len, response_length;
+	uint32_t next_record_handle;
+	struct get_pdr_req pdr_req;
+	uint8_t *pdr_data = NULL;
+	uint32_t pdr_data_size = 0;
+	char *response_msg;
+	int rc;
+
+	payload_len = req->msg_len - sizeof(struct pldm_msg_hdr);
+	rc = decode_get_pdr_req(req->msg,
+				payload_len,
+				&pdr_req.record_handle,
+				&pdr_req.data_transfer_handle,
+				&pdr_req.transfer_op_flag,
+				&pdr_req.request_count,
+				&pdr_req.record_change_number);
+	if (rc) {
+		prlog(PR_ERR, "Failed to decode GetPDR request, rc = %d\n", rc);
+		pldm_cc_resp(req, req->hdrinf.pldm_type,
+			     req->hdrinf.command, PLDM_ERROR);
+		return OPAL_INTERNAL_ERROR;
+	}
+
+	if (pdr_req.data_transfer_handle != 0) {
+		/* We don't support multipart transfers */
+		prlog(PR_ERR, "Got invalid data transfer handle 0x%x in GetPDR request\n",
+			      pdr_req.data_transfer_handle);
+		pldm_cc_resp(req, req->hdrinf.pldm_type,
+			     req->hdrinf.command,
+			     PLDM_PLATFORM_INVALID_DATA_TRANSFER_HANDLE);
+		return OPAL_PARAMETER;
+	}
+
+	if (pdr_req.transfer_op_flag != PLDM_GET_FIRSTPART) {
+		prlog(PR_ERR, "Got invalid transfer op flag 0x%x in GetPDR request\n",
+			      pdr_req.transfer_op_flag);
+		pldm_cc_resp(req, req->hdrinf.pldm_type,
+			     req->hdrinf.command,
+			     PLDM_PLATFORM_INVALID_TRANSFER_OPERATION_FLAG);
+		return OPAL_PARAMETER;
+	}
+
+	if (pdr_req.record_change_number != 0) {
+		prlog(PR_ERR, "Got invalid record change number 0x%x in GetPDR request\n",
+			      pdr_req.record_change_number);
+		pldm_cc_resp(req, req->hdrinf.pldm_type,
+			     req->hdrinf.command,
+			     PLDM_PLATFORM_INVALID_RECORD_CHANGE_NUMBER);
+		return OPAL_PARAMETER;
+	}
+
+	/* find PDR record by record handle */
+	prlog(PR_INFO, "BMC requesting PDR handle %d\n", pdr_req.record_handle);
+
+	rc = pldm_platform_pdr_find_record(pdr_req.record_handle,
+					   &pdr_data,
+					   &pdr_data_size,
+					   &next_record_handle);
+	if (rc) {
+		prlog(PR_ERR, "Got invalid record handle 0x%x in GetPDR request\n",
+			      pdr_req.record_handle);
+		pldm_cc_resp(req, req->hdrinf.pldm_type,
+			     req->hdrinf.command,
+			     PLDM_PLATFORM_INVALID_RECORD_HANDLE);
+		return OPAL_PARAMETER;
+	}
+
+	response_length = sizeof(struct pldm_msg_hdr) +
+			  sizeof(struct pldm_get_pdr_resp) +
+			  pdr_data_size;
+	response_msg = malloc(response_length);
+	memset(response_msg, 0, response_length);
+
+	/* create a PLDM response message for GetPDR */
+	rc = encode_get_pdr_resp(req->hdrinf.instance,
+				 PLDM_SUCCESS,
+				 next_record_handle,
+				 0, /* No remaining data */
+				 PLDM_START_AND_END,
+				 pdr_data_size,
+				 pdr_data,
+				 0, /* CRC not used for START_AND_END */
+				 (struct pldm_msg *)response_msg);
+	if (rc != PLDM_SUCCESS) {
+		prlog(PR_ERR, "Encode GetPDR Error, rc: %d\n", rc);
+		pldm_cc_resp(req, req->hdrinf.pldm_type,
+			     req->hdrinf.command, PLDM_ERROR);
+		free(response_msg);
+		return OPAL_PARAMETER;
+	}
+
+	/* send PLDM message over MCTP */
+	rc = pldm_send(req->source_eid, response_msg, response_length - 1);
+	if (rc) {
+		prlog(PR_ERR, "Failed to send GetPDR response, rc = %d\n", rc);
+		free(response_msg);
+		return OPAL_HARDWARE;
+	}
+
+	free(response_msg);
+
+	return OPAL_SUCCESS;
+}
+
+static struct pldm_cmd pldm_platform_get_pdr = {
+	.name = "PLDM_GET_PDR",
+	.pldm_cmd_id = PLDM_GET_PDR,
+	.handler = platform_get_pdr_handle,
+};
+
 int pldm_rx_handle_request(struct pldm_rx_data *rx)
 {
 	const struct pldm_type *t;
@@ -822,6 +948,7 @@  int pldm_mctp_responder_init(void)
 	pldm_add_cmd(&pldm_platform_type, &pldm_platform_event_message);
 	pldm_add_cmd(&pldm_platform_type, &pldm_platform_get_state_sensor_readings);
 	pldm_add_cmd(&pldm_platform_type, &pldm_platform_set_state_effecter_states);
+	pldm_add_cmd(&pldm_platform_type, &pldm_platform_get_pdr);
 
 	return OPAL_SUCCESS;
 }