requester: Add PollForPlatformEventMessage APIs
Added encode/decode APIs for PollForPlatformEventMessage command(0x0B)
which is defined in DSP0248 Version 1.2.1 sec:16.7.
Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
Signed-off-by: Dung Cao <dung@os.amperecomputing.com>
Change-Id: I0a707256d0ff6133d48a384dc252bce736b802f7
diff --git a/include/libpldm/platform.h b/include/libpldm/platform.h
index dd4e9b8..514dbe9 100644
--- a/include/libpldm/platform.h
+++ b/include/libpldm/platform.h
@@ -35,6 +35,9 @@
#define PLDM_EVENT_MESSAGE_SUPPORTED_REQ_BYTES 1
#define PLDM_EVENT_MESSAGE_SUPPORTED_MIN_RESP_BYTES 4
+#define PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_REQ_BYTES 8
+#define PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_MIN_RESP_BYTES 4
+
/* Minimum response length */
#define PLDM_GET_PDR_MIN_RESP_BYTES 12
#define PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES 5
@@ -139,6 +142,7 @@
enum pldm_platform_commands {
PLDM_SET_EVENT_RECEIVER = 0x04,
PLDM_PLATFORM_EVENT_MESSAGE = 0x0A,
+ PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE = 0x0B,
PLDM_EVENT_MESSAGE_SUPPORTED = 0x0C,
PLDM_EVENT_MESSAGE_BUFFER_SIZE = 0x0D,
PLDM_GET_SENSOR_READING = 0x11,
@@ -1005,6 +1009,27 @@
uint8_t event_data[1];
} __attribute__((packed));
+/** @struct pldm_poll_for_platform_event_message_req
+ *
+ * structure representing PollForPlatformEventMessage command request data
+ */
+struct pldm_poll_for_platform_event_message_req {
+ uint8_t format_version;
+ uint8_t transfer_operation_flag;
+ uint32_t data_transfer_handle;
+ uint16_t event_id_to_acknowledge;
+};
+
+/** @struct pldm_poll_for_platform_event_message_min_resp
+ *
+ * structure representing PollForPlatformEventMessage command response data
+ */
+struct pldm_poll_for_platform_event_message_min_resp {
+ uint8_t completion_code;
+ uint8_t tid;
+ uint16_t event_id;
+};
+
/** @struct pldm_platform_event_message_response
*
* structure representing PlatformEventMessage command response data
@@ -1027,7 +1052,7 @@
/** @struct pldm_pdr_repository_chg_event_change_record_data
*
* structure representing pldmPDRRepositoryChgEvent class eventData's change
- * record data
+ * record data
*/
struct pldm_pdr_repository_change_record_data {
uint8_t event_data_operation;
@@ -1608,6 +1633,49 @@
uint8_t event_class, const uint8_t *event_data, size_t event_data_length,
struct pldm_msg *msg, size_t payload_length);
+/** @brief Encode PollForPlatformEventMessage request data
+ * @param[in] instance_id - Message's instance id
+ * @param[in] format_version - Version of the event format
+ * @param[in] transfer_operation_flag - Tranfer operation
+ * @param[in] data_transfer_handle - The data transfer handle
+ * @param[in] event_id_to_acknowledge - the event data to acknowleadge
+ * @param[out] msg - Request message
+ * @return pldm_completion_codes
+ * @note Caller is responsible for memory alloc and dealloc of param
+ * 'msg.payload'
+ */
+int encode_poll_for_platform_event_message_req(uint8_t instance_id,
+ uint8_t format_version,
+ uint8_t transfer_operation_flag,
+ uint32_t data_transfer_handle,
+ uint16_t event_id_to_acknowledge,
+ struct pldm_msg *msg,
+ size_t payload_length);
+
+/** @brief Decode PollForPlatformEventMessage response data
+ * @param[in] msg - Request message
+ * @param[in] payload_length - Length of Response message payload
+ * @param[out] completion_code - the completion code
+ * @param[out] tid - the tid
+ * @param[out] event_id - The event id
+ * @param[out] next_data_transfer_handle - The next data transfer handle
+ * @param[out] transfer_flag - The transfer flag
+ * @param[out] event_class - The event class
+ * @param[out] event_data_size - The event data size
+ * @param[out] event_data - The event data. The event_data pointer points into
+ * msg.payload and therefore has the same lifetime as msg.payload.
+ * @param[out] event_data_integrity_checksum - The checksum
+ * command
+ * @return pldm_completion_codes
+ * @note Caller is responsible for memory alloc and dealloc of param
+ * 'msg.payload'
+ */
+int decode_poll_for_platform_event_message_resp(
+ const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code,
+ uint8_t *tid, uint16_t *event_id, uint32_t *next_data_transfer_handle,
+ uint8_t *transfer_flag, uint8_t *event_class, uint32_t *event_data_size,
+ void **event_data, uint32_t *event_data_integrity_checksum);
+
/** @brief Decode PlatformEventMessage response data
* @param[in] msg - Request message
* @param[in] payload_length - Length of Response message payload
diff --git a/src/platform.c b/src/platform.c
index 35a5a72..eae38c1 100644
--- a/src/platform.c
+++ b/src/platform.c
@@ -5,6 +5,7 @@
#include "pldm_types.h"
#include <endian.h>
#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
static int pldm_platform_pdr_hdr_validate(struct pldm_value_pdr_hdr *ctx,
@@ -2062,3 +2063,114 @@
return PLDM_SUCCESS;
}
+
+int encode_poll_for_platform_event_message_req(uint8_t instance_id,
+ uint8_t format_version,
+ uint8_t transfer_operation_flag,
+ uint32_t data_transfer_handle,
+ uint16_t event_id_to_acknowledge,
+ struct pldm_msg *msg,
+ size_t payload_length)
+{
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+ int rc;
+
+ if (msg == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ struct pldm_header_info header = {0};
+ header.msg_type = PLDM_REQUEST;
+ header.instance = instance_id;
+ header.pldm_type = PLDM_PLATFORM;
+ header.command = PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE;
+
+ rc = pack_pldm_header(&header, &(msg->hdr));
+ if (rc != PLDM_SUCCESS) {
+ return rc;
+ }
+
+ rc = pldm_msgbuf_init(
+ buf, PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_MIN_RESP_BYTES,
+ msg->payload, payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_insert(buf, format_version);
+ pldm_msgbuf_insert(buf, transfer_operation_flag);
+ pldm_msgbuf_insert(buf, data_transfer_handle);
+ pldm_msgbuf_insert(buf, event_id_to_acknowledge);
+
+ return pldm_msgbuf_destroy(buf);
+}
+
+int decode_poll_for_platform_event_message_resp(
+ const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code,
+ uint8_t *tid, uint16_t *event_id, uint32_t *next_data_transfer_handle,
+ uint8_t *transfer_flag, uint8_t *event_class, uint32_t *event_data_size,
+ void **event_data, uint32_t *event_data_integrity_checksum)
+{
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+ int rc;
+
+ if (msg == NULL || completion_code == NULL || tid == NULL ||
+ event_id == NULL || next_data_transfer_handle == NULL ||
+ transfer_flag == NULL || event_class == NULL ||
+ event_data_size == NULL || event_data == NULL ||
+ event_data_integrity_checksum == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ rc = pldm_msgbuf_init(
+ buf, PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_MIN_RESP_BYTES,
+ msg->payload, payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ rc = pldm_msgbuf_extract(buf, completion_code);
+ if (rc) {
+ return rc;
+ }
+ if (PLDM_SUCCESS != *completion_code) {
+ return *completion_code;
+ }
+
+ pldm_msgbuf_extract(buf, tid);
+ rc = pldm_msgbuf_extract(buf, event_id);
+ if (rc) {
+ return rc;
+ }
+ if ((*event_id == 0) || (*event_id == 0xffff)) {
+ return PLDM_SUCCESS;
+ }
+
+ pldm_msgbuf_extract(buf, next_data_transfer_handle);
+ rc = pldm_msgbuf_extract(buf, transfer_flag);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_extract(buf, event_class);
+ rc = pldm_msgbuf_extract(buf, event_data_size);
+ if (rc) {
+ return rc;
+ }
+ if (*event_data_size > payload_length) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (*event_data_size > 0) {
+ pldm_msgbuf_span_required(buf, *event_data_size, event_data);
+ }
+
+ if (*transfer_flag == PLDM_END ||
+ *transfer_flag == PLDM_START_AND_END) {
+ pldm_msgbuf_extract(buf, event_data_integrity_checksum);
+ }
+
+ return pldm_msgbuf_destroy_consumed(buf);
+}
diff --git a/tests/libpldm_platform_test.cpp b/tests/libpldm_platform_test.cpp
index e7f4253..7746b59 100644
--- a/tests/libpldm_platform_test.cpp
+++ b/tests/libpldm_platform_test.cpp
@@ -8,6 +8,7 @@
#include "libpldm/base.h"
#include "libpldm/entity.h"
#include "libpldm/platform.h"
+#include "msgbuf.h"
#include "pldm_types.h"
#include <gtest/gtest.h>
@@ -1181,6 +1182,257 @@
EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
}
+TEST(PollForPlatformEventMessage, testGoodEncodeRequest)
+{
+ uint8_t formatVersion = 0x01;
+ uint8_t transferOperationFlag = 0x1;
+ uint32_t dataTransferHandle = 0xffffffff;
+ uint16_t eventIdToAcknowledge = 0x0;
+
+ std::array<uint8_t,
+ hdrSize + PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_REQ_BYTES>
+ requestMsg{};
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_poll_for_platform_event_message_req(
+ 0, formatVersion, transferOperationFlag, dataTransferHandle,
+ eventIdToAcknowledge, request,
+ PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_REQ_BYTES);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf* buf = &_buf;
+ rc = pldm_msgbuf_init(buf, PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_REQ_BYTES,
+ request->payload,
+ PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_REQ_BYTES);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ uint8_t retFormatVersion;
+ uint8_t retTransferOperationFlag;
+ uint32_t retDataTransferHandle;
+ uint16_t retEventIdToAcknowledge;
+
+ pldm_msgbuf_extract_uint8(buf, &retFormatVersion);
+ pldm_msgbuf_extract_uint8(buf, &retTransferOperationFlag);
+ pldm_msgbuf_extract_uint32(buf, &retDataTransferHandle);
+ pldm_msgbuf_extract_uint16(buf, &retEventIdToAcknowledge);
+
+ EXPECT_EQ(retFormatVersion, formatVersion);
+ EXPECT_EQ(retTransferOperationFlag, transferOperationFlag);
+ EXPECT_EQ(retDataTransferHandle, dataTransferHandle);
+ EXPECT_EQ(retEventIdToAcknowledge, eventIdToAcknowledge);
+ EXPECT_EQ(pldm_msgbuf_destroy(buf), PLDM_SUCCESS);
+}
+
+TEST(PollForPlatformEventMessage, testBadEncodeRequest)
+{
+ uint8_t formatVersion = 0x01;
+ uint8_t transferOperationFlag = 0x1;
+ uint32_t dataTransferHandle = 0xffffffff;
+ uint16_t eventIdToAcknowledge = 0x0;
+
+ std::array<uint8_t,
+ hdrSize + PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_REQ_BYTES>
+ requestMsg{};
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_poll_for_platform_event_message_req(
+ 0, formatVersion, transferOperationFlag, dataTransferHandle,
+ eventIdToAcknowledge, nullptr,
+ PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_REQ_BYTES);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ encode_poll_for_platform_event_message_req(
+ 0, formatVersion, transferOperationFlag, dataTransferHandle,
+ eventIdToAcknowledge, request, hdrSize);
+}
+
+TEST(PollForPlatformEventMessage, testGoodDecodeRespond)
+{
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint8_t tId = 0x9;
+ uint16_t eventId = 159;
+ uint32_t nextDataTransferHandle = 0x11223344;
+ uint8_t transferFlag = PLDM_START_AND_END;
+ uint8_t eventClass = 0x5;
+ uint8_t eventData[5] = {0x55, 0x44, 0x33, 0x22, 0x11};
+ constexpr uint32_t eventDataSize = 0x00000005;
+ uint32_t eventDataIntegrityChecksum = 0x66778899;
+
+ std::vector<uint8_t> responseMsg{
+ 0x1,
+ 0x0,
+ 0x0,
+ PLDM_SUCCESS,
+ 0x9, // tid
+ 159,
+ 0x0, // event id
+ 0x44,
+ 0x33,
+ 0x22,
+ 0x11, // next_data_transfer_handle
+ PLDM_START_AND_END, // transfer_flag
+ 0x05, // event class
+ 0x05,
+ 0x00,
+ 0x00,
+ 0x00, // event_data_size
+ 0x55,
+ 0x44,
+ 0x33,
+ 0x22,
+ 0x11, // event_data[5]
+ 0x99,
+ 0x88,
+ 0x77,
+ 0x66 // event_data_integrity_checksum
+ };
+ const uint32_t respMsgLen = 23;
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ uint8_t retCompletionCode;
+ uint8_t retTid = 0;
+ uint16_t retEventId = 0;
+ uint32_t retNextDataTransferHandle = 0;
+ uint8_t retTransferFlag = 0;
+ uint8_t retEventClass = 0;
+ uint32_t retEventDataSize = 0;
+ uint8_t* retEventData = nullptr;
+ uint32_t retEventDataIntegrityChecksum = 0;
+
+ auto rc = decode_poll_for_platform_event_message_resp(
+ response, respMsgLen, &retCompletionCode, &retTid, &retEventId,
+ &retNextDataTransferHandle, &retTransferFlag, &retEventClass,
+ &retEventDataSize, (void**)&retEventData,
+ &retEventDataIntegrityChecksum);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(retCompletionCode, completionCode);
+ EXPECT_EQ(retTid, tId);
+ EXPECT_EQ(retEventId, eventId);
+ EXPECT_EQ(retNextDataTransferHandle, nextDataTransferHandle);
+ EXPECT_EQ(retTransferFlag, transferFlag);
+ EXPECT_EQ(retEventClass, eventClass);
+ EXPECT_EQ(retEventDataSize, eventDataSize);
+ EXPECT_EQ(retEventDataIntegrityChecksum, eventDataIntegrityChecksum);
+ EXPECT_EQ(0, memcmp(eventData, retEventData, eventDataSize));
+}
+
+TEST(PollForPlatformEventMessage, testGoodDecodeAckOnlyRespond)
+{
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint8_t tId = 0x9;
+ uint16_t eventId = 0xffff;
+
+ std::vector<uint8_t> responseMsg{
+ 0x1, 0x0, 0x0, PLDM_SUCCESS,
+ 0x9, // tid
+ 0xff,
+ 0xff // event id
+ };
+ const uint32_t respMsgLen = 4;
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ uint8_t retCompletionCode;
+ uint8_t retTid = 0;
+ uint16_t retEventId = 0;
+ uint32_t retNextDataTransferHandle = 0;
+ uint8_t retTransferFlag = 0;
+ uint8_t retEventClass = 0;
+ uint32_t retEventDataSize = 0;
+ uint8_t* retEventData = nullptr;
+ uint32_t retEventDataIntegrityChecksum = 0;
+
+ auto rc = decode_poll_for_platform_event_message_resp(
+ response, respMsgLen, &retCompletionCode, &retTid, &retEventId,
+ &retNextDataTransferHandle, &retTransferFlag, &retEventClass,
+ &retEventDataSize, (void**)&retEventData,
+ &retEventDataIntegrityChecksum);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(retCompletionCode, completionCode);
+ EXPECT_EQ(retTid, tId);
+ EXPECT_EQ(retEventId, eventId);
+
+ eventId = 0x0000;
+ responseMsg[5] = 0x00;
+ responseMsg[6] = 0x00;
+ response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ rc = decode_poll_for_platform_event_message_resp(
+ response, respMsgLen, &retCompletionCode, &retTid, &retEventId,
+ &retNextDataTransferHandle, &retTransferFlag, &retEventClass,
+ &retEventDataSize, (void**)&retEventData,
+ &retEventDataIntegrityChecksum);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(retCompletionCode, completionCode);
+ EXPECT_EQ(retTid, tId);
+ EXPECT_EQ(retEventId, eventId);
+}
+
+TEST(PollForPlatformEventMessage, testBadDecodeRespond)
+{
+ std::vector<uint8_t> responseMsg{
+ 0x1,
+ 0x0,
+ 0x0,
+ PLDM_SUCCESS,
+ 0x9, // tid
+ 159,
+ 0x0, // event id
+ 0x44,
+ 0x33,
+ 0x22,
+ 0x11, // next_data_transfer_handle
+ PLDM_START_AND_END, // transfer_flag
+ 0x05, // event class
+ 0x05,
+ 0x00,
+ 0x00,
+ 0x00, // event_data_size
+ 0x55,
+ 0x44,
+ 0x33,
+ 0x22,
+ 0x11, // event_data[5]
+ 0x99,
+ 0x88,
+ 0x77,
+ 0x66 // event_data_integrity_checksum
+ };
+ // const uint32_t respMsgLen = 23;
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = decode_poll_for_platform_event_message_resp(
+ nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ uint8_t retCompletionCode;
+ uint8_t retTid = 0;
+ uint16_t retEventId = 0;
+ uint32_t retNextDataTransferHandle = 0;
+ uint8_t retTransferFlag = 0;
+ uint8_t retEventClass = 0;
+ uint32_t retEventDataSize = 0;
+ uint8_t* retEventData = nullptr;
+ uint32_t retEventDataIntegrityChecksum = 0;
+
+ rc = decode_poll_for_platform_event_message_resp(
+ response, PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_MIN_RESP_BYTES - 1,
+ &retCompletionCode, &retTid, &retEventId, &retNextDataTransferHandle,
+ &retTransferFlag, &retEventClass, &retEventDataSize,
+ (void**)&retEventData, &retEventDataIntegrityChecksum);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(PlatformEventMessage, testGoodStateSensorDecodeRequest)
{
std::array<uint8_t,