libpldm: Add encode API for GetPDRRepositoryInfo response

The spec of GetPDRRepositoryInfo command refers to
DSP0248_1.2.0: 26.1 Table 67

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I6ee56689603552703568756d79c7db31a6a68e51
diff --git a/libpldm/platform.c b/libpldm/platform.c
index 812e8b7..8e33239 100644
--- a/libpldm/platform.c
+++ b/libpldm/platform.c
@@ -314,6 +314,52 @@
 	return PLDM_SUCCESS;
 }
 
+int encode_get_pdr_repository_info_resp(
+    uint8_t instance_id, uint8_t completion_code, uint8_t repository_state,
+    const uint8_t *update_time, const uint8_t *oem_update_time,
+    uint32_t record_count, uint32_t repository_size,
+    uint32_t largest_record_size, uint8_t data_transfer_handle_timeout,
+    struct pldm_msg *msg)
+{
+	if (msg == NULL) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	struct pldm_header_info header = {0};
+	header.msg_type = PLDM_RESPONSE;
+	header.instance = instance_id;
+	header.pldm_type = PLDM_PLATFORM;
+	header.command = PLDM_GET_PDR_REPOSITORY_INFO;
+
+	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
+	if (rc != PLDM_SUCCESS) {
+		return rc;
+	}
+
+	struct pldm_pdr_repository_info_resp *response =
+	    (struct pldm_pdr_repository_info_resp *)msg->payload;
+	response->completion_code = completion_code;
+
+	if (response->completion_code == PLDM_SUCCESS) {
+		response->repository_state = repository_state;
+		if (update_time != NULL) {
+			memcpy(response->update_time, update_time,
+			       PLDM_TIMESTAMP104_SIZE);
+		}
+		if (oem_update_time != NULL) {
+			memcpy(response->oem_update_time, oem_update_time,
+			       PLDM_TIMESTAMP104_SIZE);
+		}
+		response->record_count = htole32(record_count);
+		response->repository_size = htole32(repository_size);
+		response->largest_record_size = htole32(largest_record_size);
+		response->data_transfer_handle_timeout =
+		    data_transfer_handle_timeout;
+	}
+
+	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,
diff --git a/libpldm/platform.h b/libpldm/platform.h
index 0c392a8..962bad0 100644
--- a/libpldm/platform.h
+++ b/libpldm/platform.h
@@ -31,6 +31,7 @@
 #define PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES 5
 #define PLDM_GET_SENSOR_READING_MIN_RESP_BYTES 8
 #define PLDM_GET_STATE_SENSOR_READINGS_MIN_RESP_BYTES 2
+#define PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES 41
 
 /* Minimum length for PLDM PlatformEventMessage request */
 #define PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES 3
@@ -119,6 +120,7 @@
 	PLDM_SET_NUMERIC_EFFECTER_VALUE = 0x31,
 	PLDM_GET_NUMERIC_EFFECTER_VALUE = 0x32,
 	PLDM_SET_STATE_EFFECTER_STATES = 0x39,
+	PLDM_GET_PDR_REPOSITORY_INFO = 0x50,
 	PLDM_GET_PDR = 0x51,
 	PLDM_PLATFORM_EVENT_MESSAGE = 0x0A
 };
@@ -280,6 +282,19 @@
 	PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE
 };
 
+/** @brief PLDM respository state */
+enum pldm_repository_state {
+	PLDM_AVAILABLE,
+	PLDM_UPDATE_IN_PROGRESS,
+	PLDM_FAILED
+};
+
+/** @brief PLDM respository data transfer handler timeout */
+enum pldm_repository_data_transfer_handler_timeout {
+	PLDM_NO_TIMEOUT,
+	PLDM_DEFALUT_MINIMUM_TIMEOUT
+};
+
 /** @struct pldm_pdr_hdr
  *
  *  Structure representing PLDM common PDR header
@@ -550,6 +565,21 @@
 	set_effecter_state_field field[8];
 } __attribute__((packed));
 
+/** @struct pldm_get_pdr_repository_info_resp
+ *
+ *  Structure representing GetPDRRepositoryInfo response packet
+ */
+struct pldm_pdr_repository_info_resp {
+	uint8_t completion_code;
+	uint8_t repository_state;
+	uint8_t update_time[PLDM_TIMESTAMP104_SIZE];
+	uint8_t oem_update_time[PLDM_TIMESTAMP104_SIZE];
+	uint32_t record_count;
+	uint32_t repository_size;
+	uint32_t largest_record_size;
+	uint8_t data_transfer_handle_timeout;
+} __attribute__((packed));
+
 /** @struct pldm_get_pdr_resp
  *
  *  structure representing GetPDR response packet
@@ -995,6 +1025,32 @@
 
 /* Requester */
 
+/*GetPDRRepositoryInfo*/
+
+/** @brief Encode GetPDRRepositoryInfo response data
+ *
+ *  @param[in] instance_id - Message's instance id
+ *  @param[in] completion_code - PLDM completion code
+ *  @param[in] repository_state - PLDM repository state
+ *  @param[in] update_time - When the standard PDR repository data was
+ *                           originally created
+ *  @param[in] oem_update_time - when OEM PDRs in the PDR Repository were
+ *                               originally created
+ *  @param[in] record_count - Total number of PDRs in this repository
+ *  @param[in] repository_size - Size of the PDR Repository in bytes
+ *  @param[in] largest_record_size - Size of the largest record in the PDR
+ * Repository in bytes
+ *  @param[in] data_transfer_handle_timeout - Data transmission timeout
+ *  @param[out] msg - Message will be written to this
+ *  @return pldm_completion_codes
+ */
+int encode_get_pdr_repository_info_resp(
+    uint8_t instance_id, uint8_t completion_code, uint8_t repository_state,
+    const uint8_t *update_time, const uint8_t *oem_update_time,
+    uint32_t record_count, uint32_t repository_size,
+    uint32_t largest_record_size, uint8_t data_transfer_handle_timeout,
+    struct pldm_msg *msg);
+
 /* GetPDR */
 
 /** @brief Create a PLDM request message for GetPDR
diff --git a/libpldm/tests/libpldm_platform_test.cpp b/libpldm/tests/libpldm_platform_test.cpp
index cab6a07..c785e3f 100644
--- a/libpldm/tests/libpldm_platform_test.cpp
+++ b/libpldm/tests/libpldm_platform_test.cpp
@@ -381,6 +381,59 @@
     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
 }
 
+TEST(GetPDRRepositoryInfo, testGoodEncodeResponse)
+{
+    uint8_t completionCode = 0;
+    uint8_t repositoryState = PLDM_AVAILABLE;
+    uint8_t updateTime[PLDM_TIMESTAMP104_SIZE] = {0};
+    uint8_t oemUpdateTime[PLDM_TIMESTAMP104_SIZE] = {0};
+    uint32_t recordCount = 100;
+    uint32_t repositorySize = 100;
+    uint32_t largestRecordSize = UINT32_MAX;
+    uint8_t dataTransferHandleTimeout = PLDM_NO_TIMEOUT;
+
+    std::vector<uint8_t> responseMsg(hdrSize +
+                                     PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES);
+    auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+    auto rc = encode_get_pdr_repository_info_resp(
+        0, PLDM_SUCCESS, repositoryState, updateTime, oemUpdateTime,
+        recordCount, repositorySize, largestRecordSize,
+        dataTransferHandleTimeout, response);
+
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+    struct pldm_pdr_repository_info_resp* resp =
+        reinterpret_cast<struct pldm_pdr_repository_info_resp*>(
+            response->payload);
+
+    EXPECT_EQ(completionCode, resp->completion_code);
+    EXPECT_EQ(repositoryState, resp->repository_state);
+    EXPECT_EQ(0, memcmp(updateTime, resp->update_time, PLDM_TIMESTAMP104_SIZE));
+    EXPECT_EQ(0, memcmp(oemUpdateTime, resp->oem_update_time,
+                        PLDM_TIMESTAMP104_SIZE));
+    EXPECT_EQ(recordCount, le32toh(resp->record_count));
+    EXPECT_EQ(repositorySize, le32toh(resp->repository_size));
+    EXPECT_EQ(largestRecordSize, le32toh(resp->largest_record_size));
+    EXPECT_EQ(dataTransferHandleTimeout, resp->data_transfer_handle_timeout);
+}
+
+TEST(GetPDRRepositoryInfo, testBadEncodeResponse)
+{
+    uint8_t repositoryState = PLDM_AVAILABLE;
+    uint8_t updateTime[PLDM_TIMESTAMP104_SIZE] = {0};
+    uint8_t oemUpdateTime[PLDM_TIMESTAMP104_SIZE] = {0};
+    uint32_t recordCount = 100;
+    uint32_t repositorySize = 100;
+    uint32_t largestRecordSize = UINT32_MAX;
+    uint8_t dataTransferHandleTimeout = PLDM_NO_TIMEOUT;
+
+    auto rc = encode_get_pdr_repository_info_resp(
+        0, PLDM_SUCCESS, repositoryState, updateTime, oemUpdateTime,
+        recordCount, repositorySize, largestRecordSize,
+        dataTransferHandleTimeout, nullptr);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
 TEST(SetNumericEffecterValue, testGoodDecodeRequest)
 {
     std::array<uint8_t,