libpldm: platform: implement requester flow for GetPDR
For the requester, need to encode request data and send responder,
waiting for recive responder data to decode, so need to implement
encode/decode(Requester flow only) for GetPDR.
The GetPDR command is used to retrieve individual PDRs from a PDR
repository and refer to DSP0248(26.2).
Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: Ia686c780c06f6d5d1f0f8a140cf009c633c9b7b8
diff --git a/libpldm/platform.c b/libpldm/platform.c
index 3cbc137..9c06854 100644
--- a/libpldm/platform.c
+++ b/libpldm/platform.c
@@ -2,6 +2,7 @@
#include <string.h>
#include "platform.h"
+#include "utils.h"
int encode_set_state_effecter_states_resp(uint8_t instance_id,
uint8_t completion_code,
@@ -167,3 +168,96 @@
return PLDM_SUCCESS;
}
+
+int encode_get_pdr_req(uint8_t instance_id, uint32_t record_hndl,
+ uint32_t data_transfer_hndl, uint8_t transfer_op_flag,
+ uint16_t request_cnt, uint16_t record_chg_num,
+ struct pldm_msg *msg, size_t payload_length)
+{
+ struct pldm_header_info header = {0};
+ int rc = PLDM_SUCCESS;
+
+ if (msg == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+ struct pldm_get_pdr_req *request =
+ (struct pldm_get_pdr_req *)msg->payload;
+
+ header.msg_type = PLDM_REQUEST;
+ header.instance = instance_id;
+ header.pldm_type = PLDM_PLATFORM;
+ header.command = PLDM_GET_PDR;
+
+ if ((rc = pack_pldm_header(&header, &(msg->hdr))) > PLDM_SUCCESS) {
+ return rc;
+ }
+
+ if (payload_length != PLDM_GET_PDR_REQ_BYTES) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ request->record_handle = htole32(record_hndl);
+ request->data_transfer_handle = htole32(data_transfer_hndl);
+ request->transfer_op_flag = transfer_op_flag;
+ request->request_count = htole16(request_cnt);
+ request->record_change_number = htole16(record_chg_num);
+
+ return PLDM_SUCCESS;
+}
+
+int decode_get_pdr_resp(const struct pldm_msg *msg, size_t payload_length,
+ uint8_t *completion_code, uint32_t *next_record_hndl,
+ uint32_t *next_data_transfer_hndl,
+ uint8_t *transfer_flag, uint16_t *resp_cnt,
+ uint8_t *record_data, size_t record_data_length,
+ uint8_t *transfer_crc)
+{
+ if (msg == NULL || completion_code == NULL ||
+ next_record_hndl == NULL || next_data_transfer_hndl == NULL ||
+ transfer_flag == NULL || resp_cnt == NULL || record_data == NULL ||
+ transfer_crc == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ *completion_code = msg->payload[0];
+ if (PLDM_SUCCESS != *completion_code) {
+ return *completion_code;
+ }
+
+ if (payload_length < PLDM_GET_PDR_MIN_RESP_BYTES) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ struct pldm_get_pdr_resp *response =
+ (struct pldm_get_pdr_resp *)msg->payload;
+
+ *next_record_hndl = le32toh(response->next_record_handle);
+ *next_data_transfer_hndl = le32toh(response->next_data_transfer_handle);
+ *transfer_flag = response->transfer_flag;
+ *resp_cnt = le16toh(response->response_count);
+
+ if (*transfer_flag != PLDM_END &&
+ (int)payload_length != PLDM_GET_PDR_MIN_RESP_BYTES + *resp_cnt) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ if (*transfer_flag == PLDM_END &&
+ (int)payload_length !=
+ PLDM_GET_PDR_MIN_RESP_BYTES + *resp_cnt + 1) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ if (*resp_cnt > 0) {
+ if (record_data_length < *resp_cnt) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+ memcpy(record_data, response->record_data, *resp_cnt);
+ }
+
+ if (*transfer_flag == PLDM_END) {
+ *transfer_crc =
+ msg->payload[PLDM_GET_PDR_MIN_RESP_BYTES + *resp_cnt];
+ }
+
+ return PLDM_SUCCESS;
+}
diff --git a/libpldm/platform.h b/libpldm/platform.h
index 6fdbf06..1062240 100644
--- a/libpldm/platform.h
+++ b/libpldm/platform.h
@@ -230,6 +230,56 @@
/* Requester */
+/* GetPDR */
+
+/** @brief Create a PLDM request message for GetPDR
+ *
+ * @param[in] instance_id - Message's instance id
+ * @param[in] record_hndl - The recordHandle value for the PDR to be retrieved
+ * @param[in] data_transfer_hndl - Handle used to identify a particular
+ * multipart PDR data transfer operation
+ * @param[in] transfer_op_flag - Flag to indicate the first or subsequent
+ * portion of transfer
+ * @param[in] request_cnt - The maximum number of record bytes requested
+ * @param[in] record_chg_num - Used to determine whether the PDR has changed
+ * while PDR transfer is going on
+ * @param[out] msg - Message will be written to this
+ * @param[in] payload_length - Length of request message payload
+ * @return pldm_completion_codes
+ * @note Caller is responsible for memory alloc and dealloc of param
+ * 'msg.payload'
+ */
+int encode_get_pdr_req(uint8_t instance_id, uint32_t record_hndl,
+ uint32_t data_transfer_hndl, uint8_t transfer_op_flag,
+ uint16_t request_cnt, uint16_t record_chg_num,
+ struct pldm_msg *msg, size_t payload_length);
+
+/** @brief Decode GetPDR response data
+ *
+ * @param[in] msg - Request message
+ * @param[in] payload_length - Length of request message payload
+ * @param[out] completion_code - PLDM completion code
+ * @param[out] next_record_hndl - The recordHandle for the PDR that is next in
+ * the PDR Repository
+ * @param[out] next_data_transfer_hndl - A handle that identifies the next
+ * portion of the PDR data to be transferred, if any
+ * @param[out] transfer_flag - Indicates the portion of PDR data being
+ * transferred
+ * @param[out] resp_cnt - The number of recordData bytes returned in this
+ * response
+ * @param[out] record_data - PDR data bytes of length resp_cnt
+ * @param[in] record_data_length - Length of record_data
+ * @param[out] transfer_crc - A CRC-8 for the overall PDR. This is present only
+ * in the last part of a PDR being transferred
+ * @return pldm_completion_codes
+ */
+int decode_get_pdr_resp(const struct pldm_msg *msg, size_t payload_length,
+ uint8_t *completion_code, uint32_t *next_record_hndl,
+ uint32_t *next_data_transfer_hndl,
+ uint8_t *transfer_flag, uint16_t *resp_cnt,
+ uint8_t *record_data, size_t record_data_length,
+ uint8_t *transfer_crc);
+
/* SetStateEffecterStates */
/** @brief Create a PLDM request message for SetStateEffecterStates