platform: Add decode_pldm_cper_event_data() API

Support decoder for `cperEvent` event class as table `Table 27 -
CPEREvent class eventData format` in DSP0248 V1.3.0.

Change-Id: I6165980e0570bbb21158af9e6adee15894b3bf3a
Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
diff --git a/tests/dsp/platform.cpp b/tests/dsp/platform.cpp
index f5ae4fd..dfc5506 100644
--- a/tests/dsp/platform.cpp
+++ b/tests/dsp/platform.cpp
@@ -5190,3 +5190,125 @@
     EXPECT_EQ(-EBADMSG, rc);
     free(decodedPdr);
 }
+
+#ifdef LIBPLDM_API_TESTING
+TEST(PlatformEventMessage, testGoodCperEventDataDecodeRequest)
+{
+    constexpr const size_t eventDataSize = 4;
+    constexpr const size_t eventSize =
+        PLDM_PLATFORM_CPER_EVENT_MIN_LENGTH + eventDataSize;
+    std::array<uint8_t, eventSize> eventData{
+        0x1,                   // format version
+        0x0,                   // format type
+        0x4,  0x0,             // event data length
+        0x44, 0x33, 0x22, 0x11 // data
+    };
+
+    uint8_t expectedFormatVersion = 1;
+    uint8_t expectedFormatType = 0;
+    uint16_t expectedEventDataLength = 4;
+    uint8_t expectCperEventData[] = {0x44, 0x33, 0x22, 0x11};
+
+    size_t cperEventSize =
+        sizeof(struct pldm_platform_cper_event) + eventDataSize;
+    auto cper_event = reinterpret_cast<struct pldm_platform_cper_event*>(
+        malloc(cperEventSize));
+
+    auto rc = decode_pldm_platform_cper_event_data(
+        reinterpret_cast<const void*>(eventData.data()), eventData.size(),
+        cper_event, cperEventSize);
+
+    EXPECT_EQ(rc, 0);
+    EXPECT_EQ(cper_event->format_version, expectedFormatVersion);
+    EXPECT_EQ(cper_event->format_type, expectedFormatType);
+    EXPECT_EQ(cper_event->event_data_length, expectedEventDataLength);
+
+    auto cperEventData = pldm_platform_cper_event_event_data(cper_event);
+    EXPECT_NE(cperEventData, nullptr);
+    if (cperEventData)
+    {
+        EXPECT_EQ(0, memcmp(expectCperEventData, cperEventData,
+                            expectedEventDataLength));
+    }
+
+    free(cper_event);
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(PlatformEventMessage, testBadCperEventDataDecodeRequest)
+{
+
+    constexpr const size_t eventDataSize = 4;
+    constexpr const size_t eventSize =
+        PLDM_PLATFORM_CPER_EVENT_MIN_LENGTH + eventDataSize;
+    std::array<uint8_t, eventSize> eventData{
+        0x1,                   // format version
+        0x0,                   // format type
+        0x4,  0x0,             // event data length
+        0x44, 0x33, 0x22, 0x11 // data
+    };
+
+    size_t cperEventSize =
+        sizeof(struct pldm_platform_cper_event) + eventDataSize;
+    auto cperEvent = reinterpret_cast<struct pldm_platform_cper_event*>(
+        malloc(cperEventSize));
+
+    auto rc = decode_pldm_platform_cper_event_data(NULL, eventData.size(),
+                                                   cperEvent, cperEventSize);
+    EXPECT_EQ(rc, -EINVAL);
+
+    rc = decode_pldm_platform_cper_event_data(
+        reinterpret_cast<const void*>(eventData.data()), eventData.size(), NULL,
+        cperEventSize);
+    EXPECT_EQ(rc, -EINVAL);
+
+#ifdef NDEBUG
+    rc = decode_pldm_platform_cper_event_data(
+        reinterpret_cast<uint8_t*>(eventData.data()), eventData.size() - 1,
+        cperEvent, cperEventSize);
+    EXPECT_EQ(rc, -EBADMSG);
+#else
+    EXPECT_DEATH(decode_pldm_platform_cper_event_data(
+                     reinterpret_cast<uint8_t*>(eventData.data()),
+                     eventData.size() - 1, cperEvent, cperEventSize),
+                 "ctx->remaining >= 0");
+#endif
+
+    rc = decode_pldm_platform_cper_event_data(
+        reinterpret_cast<uint8_t*>(eventData.data()), eventData.size(),
+        cperEvent, cperEventSize - 1);
+    EXPECT_EQ(rc, -EOVERFLOW);
+
+    rc = decode_pldm_platform_cper_event_data(
+        reinterpret_cast<uint8_t*>(eventData.data()), eventData.size(),
+        cperEvent, cperEventSize + 1);
+    EXPECT_EQ(rc, 0);
+
+    // Invalid CPER Event Format Type
+    eventData[1] = 0x2;
+    rc = decode_pldm_platform_cper_event_data(
+        reinterpret_cast<const void*>(eventData.data()), eventData.size(),
+        cperEvent, cperEventSize);
+
+    EXPECT_EQ(rc, -EPROTO);
+
+    // Invalid cper event data size
+    eventData[1] = 0x1;
+    eventData[2] = 3;
+    rc = decode_pldm_platform_cper_event_data(
+        reinterpret_cast<const void*>(eventData.data()), eventData.size(),
+        cperEvent, cperEventSize);
+
+    EXPECT_EQ(rc, -EBADMSG);
+
+    eventData[2] = 5;
+    rc = decode_pldm_platform_cper_event_data(
+        reinterpret_cast<const void*>(eventData.data()), eventData.size(),
+        cperEvent, cperEventSize);
+
+    EXPECT_EQ(rc, -EOVERFLOW);
+
+    free(cperEvent);
+}
+#endif