177e6fe7aSGilbert Chen #include "event_manager.hpp"
277e6fe7aSGilbert Chen 
377e6fe7aSGilbert Chen #include "libpldm/utils.h"
477e6fe7aSGilbert Chen 
577e6fe7aSGilbert Chen #include "terminus_manager.hpp"
677e6fe7aSGilbert Chen 
777e6fe7aSGilbert Chen #include <phosphor-logging/lg2.hpp>
877e6fe7aSGilbert Chen #include <xyz/openbmc_project/Logging/Entry/server.hpp>
977e6fe7aSGilbert Chen 
1077e6fe7aSGilbert Chen #include <cerrno>
1177e6fe7aSGilbert Chen #include <memory>
1277e6fe7aSGilbert Chen 
1377e6fe7aSGilbert Chen PHOSPHOR_LOG2_USING;
1477e6fe7aSGilbert Chen 
1577e6fe7aSGilbert Chen namespace pldm
1677e6fe7aSGilbert Chen {
1777e6fe7aSGilbert Chen namespace platform_mc
1877e6fe7aSGilbert Chen {
1977e6fe7aSGilbert Chen namespace fs = std::filesystem;
2077e6fe7aSGilbert Chen 
2177e6fe7aSGilbert Chen int EventManager::handlePlatformEvent(
2277e6fe7aSGilbert Chen     pldm_tid_t tid, uint16_t eventId, uint8_t eventClass,
2377e6fe7aSGilbert Chen     const uint8_t* eventData, size_t eventDataSize)
2477e6fe7aSGilbert Chen {
2577e6fe7aSGilbert Chen     /* EventClass sensorEvent `Table 11 - PLDM Event Types` DSP0248 */
2677e6fe7aSGilbert Chen     if (eventClass == PLDM_SENSOR_EVENT)
2777e6fe7aSGilbert Chen     {
2877e6fe7aSGilbert Chen         uint16_t sensorId = 0;
2977e6fe7aSGilbert Chen         uint8_t sensorEventClassType = 0;
3077e6fe7aSGilbert Chen         size_t eventClassDataOffset = 0;
3177e6fe7aSGilbert Chen         auto rc = decode_sensor_event_data(eventData, eventDataSize, &sensorId,
3277e6fe7aSGilbert Chen                                            &sensorEventClassType,
3377e6fe7aSGilbert Chen                                            &eventClassDataOffset);
3477e6fe7aSGilbert Chen         if (rc)
3577e6fe7aSGilbert Chen         {
3677e6fe7aSGilbert Chen             lg2::error(
3777e6fe7aSGilbert Chen                 "Failed to decode sensor event data from terminus ID {TID}, event class {CLASS}, event ID {EVENTID} with return code {RC}.",
3877e6fe7aSGilbert Chen                 "TID", tid, "CLASS", eventClass, "EVENTID", eventId, "RC", rc);
3977e6fe7aSGilbert Chen             return rc;
4077e6fe7aSGilbert Chen         }
4177e6fe7aSGilbert Chen         switch (sensorEventClassType)
4277e6fe7aSGilbert Chen         {
4377e6fe7aSGilbert Chen             case PLDM_NUMERIC_SENSOR_STATE:
4477e6fe7aSGilbert Chen             {
4577e6fe7aSGilbert Chen                 const uint8_t* sensorData = eventData + eventClassDataOffset;
4677e6fe7aSGilbert Chen                 size_t sensorDataLength = eventDataSize - eventClassDataOffset;
4777e6fe7aSGilbert Chen                 return processNumericSensorEvent(tid, sensorId, sensorData,
4877e6fe7aSGilbert Chen                                                  sensorDataLength);
4977e6fe7aSGilbert Chen             }
5077e6fe7aSGilbert Chen             case PLDM_STATE_SENSOR_STATE:
5177e6fe7aSGilbert Chen             case PLDM_SENSOR_OP_STATE:
5277e6fe7aSGilbert Chen             default:
5377e6fe7aSGilbert Chen                 lg2::info(
5477e6fe7aSGilbert Chen                     "Unsupported class type {CLASSTYPE} for the sensor event from terminus ID {TID} sensorId {SID}",
5577e6fe7aSGilbert Chen                     "CLASSTYPE", sensorEventClassType, "TID", tid, "SID",
5677e6fe7aSGilbert Chen                     sensorId);
5777e6fe7aSGilbert Chen                 return PLDM_ERROR;
5877e6fe7aSGilbert Chen         }
5977e6fe7aSGilbert Chen     }
6077e6fe7aSGilbert Chen 
61*9fc79128SThu Nguyen     /* EventClass CPEREvent as `Table 11 - PLDM Event Types` DSP0248 V1.3.0 */
62*9fc79128SThu Nguyen     if (eventClass == PLDM_CPER_EVENT)
63*9fc79128SThu Nguyen     {
64*9fc79128SThu Nguyen         return processCperEvent(tid, eventId, eventData, eventDataSize);
65*9fc79128SThu Nguyen     }
66*9fc79128SThu Nguyen 
6777e6fe7aSGilbert Chen     lg2::info("Unsupported class type {CLASSTYPE}", "CLASSTYPE", eventClass);
6877e6fe7aSGilbert Chen 
6977e6fe7aSGilbert Chen     return PLDM_ERROR;
7077e6fe7aSGilbert Chen }
7177e6fe7aSGilbert Chen 
7277e6fe7aSGilbert Chen int EventManager::processNumericSensorEvent(pldm_tid_t tid, uint16_t sensorId,
7377e6fe7aSGilbert Chen                                             const uint8_t* sensorData,
7477e6fe7aSGilbert Chen                                             size_t sensorDataLength)
7577e6fe7aSGilbert Chen {
7677e6fe7aSGilbert Chen     uint8_t eventState = 0;
7777e6fe7aSGilbert Chen     uint8_t previousEventState = 0;
7877e6fe7aSGilbert Chen     uint8_t sensorDataSize = 0;
7977e6fe7aSGilbert Chen     uint32_t presentReading;
8077e6fe7aSGilbert Chen     auto rc = decode_numeric_sensor_data(
8177e6fe7aSGilbert Chen         sensorData, sensorDataLength, &eventState, &previousEventState,
8277e6fe7aSGilbert Chen         &sensorDataSize, &presentReading);
8377e6fe7aSGilbert Chen     if (rc)
8477e6fe7aSGilbert Chen     {
8577e6fe7aSGilbert Chen         lg2::error(
8677e6fe7aSGilbert Chen             "Failed to decode numericSensorState event for terminus ID {TID}, error {RC} ",
8777e6fe7aSGilbert Chen             "TID", tid, "RC", rc);
8877e6fe7aSGilbert Chen         return rc;
8977e6fe7aSGilbert Chen     }
9077e6fe7aSGilbert Chen 
9177e6fe7aSGilbert Chen     double value = static_cast<double>(presentReading);
9277e6fe7aSGilbert Chen     lg2::error(
9377e6fe7aSGilbert Chen         "processNumericSensorEvent tid {TID}, sensorID {SID} value {VAL} previousState {PSTATE} eventState {ESTATE}",
9477e6fe7aSGilbert Chen         "TID", tid, "SID", sensorId, "VAL", value, "PSTATE", previousEventState,
9577e6fe7aSGilbert Chen         "ESTATE", eventState);
9677e6fe7aSGilbert Chen 
9777e6fe7aSGilbert Chen     if (!termini.contains(tid) || !termini[tid])
9877e6fe7aSGilbert Chen     {
9977e6fe7aSGilbert Chen         lg2::error("Terminus ID {TID} is not in the managing list.", "TID",
10077e6fe7aSGilbert Chen                    tid);
10177e6fe7aSGilbert Chen         return PLDM_ERROR;
10277e6fe7aSGilbert Chen     }
10377e6fe7aSGilbert Chen 
10477e6fe7aSGilbert Chen     auto& terminus = termini[tid];
10577e6fe7aSGilbert Chen 
10677e6fe7aSGilbert Chen     auto sensor = terminus->getSensorObject(sensorId);
10777e6fe7aSGilbert Chen     if (!sensor)
10877e6fe7aSGilbert Chen     {
10977e6fe7aSGilbert Chen         lg2::error(
11077e6fe7aSGilbert Chen             "Terminus ID {TID} has no sensor object with sensor ID {SID}.",
11177e6fe7aSGilbert Chen             "TID", tid, "SID", sensorId);
11277e6fe7aSGilbert Chen         return PLDM_ERROR;
11377e6fe7aSGilbert Chen     }
11477e6fe7aSGilbert Chen 
11577e6fe7aSGilbert Chen     switch (previousEventState)
11677e6fe7aSGilbert Chen     {
11777e6fe7aSGilbert Chen         case PLDM_SENSOR_UNKNOWN:
11877e6fe7aSGilbert Chen         case PLDM_SENSOR_NORMAL:
11977e6fe7aSGilbert Chen         {
12077e6fe7aSGilbert Chen             switch (eventState)
12177e6fe7aSGilbert Chen             {
12277e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
12377e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
12477e6fe7aSGilbert Chen                 {
12577e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
12677e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
12777e6fe7aSGilbert Chen                                                   value, true, true);
12877e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
12977e6fe7aSGilbert Chen                         pldm::utils::Level::CRITICAL,
13077e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
13177e6fe7aSGilbert Chen                 }
13277e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
13377e6fe7aSGilbert Chen                 {
13477e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
13577e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
13677e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
13777e6fe7aSGilbert Chen                 }
13877e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
13977e6fe7aSGilbert Chen                     break;
14077e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
14177e6fe7aSGilbert Chen                 {
14277e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
14377e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
14477e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
14577e6fe7aSGilbert Chen                 }
14677e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
14777e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
14877e6fe7aSGilbert Chen                 {
14977e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
15077e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
15177e6fe7aSGilbert Chen                                                   value, true, true);
15277e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
15377e6fe7aSGilbert Chen                         pldm::utils::Level::CRITICAL,
15477e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
15577e6fe7aSGilbert Chen                 }
15677e6fe7aSGilbert Chen                 default:
15777e6fe7aSGilbert Chen                     break;
15877e6fe7aSGilbert Chen             }
15977e6fe7aSGilbert Chen             break;
16077e6fe7aSGilbert Chen         }
16177e6fe7aSGilbert Chen         case PLDM_SENSOR_LOWERWARNING:
16277e6fe7aSGilbert Chen         {
16377e6fe7aSGilbert Chen             switch (eventState)
16477e6fe7aSGilbert Chen             {
16577e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
16677e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
16777e6fe7aSGilbert Chen                     break;
16877e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
16977e6fe7aSGilbert Chen                 {
17077e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
17177e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
17277e6fe7aSGilbert Chen                                                   value, false, false);
17377e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
17477e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
17577e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
17677e6fe7aSGilbert Chen                 }
17777e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
17877e6fe7aSGilbert Chen                 {
17977e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
18077e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
18177e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, false, false);
18277e6fe7aSGilbert Chen                 }
18377e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
18477e6fe7aSGilbert Chen                     break;
18577e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
18677e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
18777e6fe7aSGilbert Chen                 {
18877e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
18977e6fe7aSGilbert Chen                         pldm::utils::Level::CRITICAL,
19077e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
19177e6fe7aSGilbert Chen                 }
19277e6fe7aSGilbert Chen                 default:
19377e6fe7aSGilbert Chen                     break;
19477e6fe7aSGilbert Chen             }
19577e6fe7aSGilbert Chen             break;
19677e6fe7aSGilbert Chen         }
19777e6fe7aSGilbert Chen         case PLDM_SENSOR_LOWERCRITICAL:
19877e6fe7aSGilbert Chen         case PLDM_SENSOR_LOWERFATAL:
19977e6fe7aSGilbert Chen         {
20077e6fe7aSGilbert Chen             switch (eventState)
20177e6fe7aSGilbert Chen             {
20277e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
20377e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
20477e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
20577e6fe7aSGilbert Chen                     break;
20677e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
20777e6fe7aSGilbert Chen                 {
20877e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::CRITICAL,
20977e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
21077e6fe7aSGilbert Chen                                                   value, false, false);
21177e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
21277e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
21377e6fe7aSGilbert Chen                                                   value, true, true);
21477e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
21577e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
21677e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, false, false);
21777e6fe7aSGilbert Chen                 }
21877e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
21977e6fe7aSGilbert Chen                 {
22077e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::CRITICAL,
22177e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
22277e6fe7aSGilbert Chen                                                   value, false, false);
22377e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
22477e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
22577e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
22677e6fe7aSGilbert Chen                 }
22777e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
22877e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
22977e6fe7aSGilbert Chen                 default:
23077e6fe7aSGilbert Chen                     break;
23177e6fe7aSGilbert Chen             }
23277e6fe7aSGilbert Chen             break;
23377e6fe7aSGilbert Chen         }
23477e6fe7aSGilbert Chen         case PLDM_SENSOR_UPPERFATAL:
23577e6fe7aSGilbert Chen         case PLDM_SENSOR_UPPERCRITICAL:
23677e6fe7aSGilbert Chen         {
23777e6fe7aSGilbert Chen             switch (eventState)
23877e6fe7aSGilbert Chen             {
23977e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
24077e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
24177e6fe7aSGilbert Chen                     break;
24277e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
24377e6fe7aSGilbert Chen                 {
24477e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::CRITICAL,
24577e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
24677e6fe7aSGilbert Chen                                                   value, false, false);
24777e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
24877e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
24977e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
25077e6fe7aSGilbert Chen                 }
25177e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
25277e6fe7aSGilbert Chen                 {
25377e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::CRITICAL,
25477e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
25577e6fe7aSGilbert Chen                                                   value, false, false);
25677e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
25777e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
25877e6fe7aSGilbert Chen                                                   value, true, true);
25977e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
26077e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
26177e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, false, false);
26277e6fe7aSGilbert Chen                 }
26377e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
26477e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
26577e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
26677e6fe7aSGilbert Chen                 default:
26777e6fe7aSGilbert Chen                     break;
26877e6fe7aSGilbert Chen             }
26977e6fe7aSGilbert Chen             break;
27077e6fe7aSGilbert Chen         }
27177e6fe7aSGilbert Chen         case PLDM_SENSOR_UPPERWARNING:
27277e6fe7aSGilbert Chen         {
27377e6fe7aSGilbert Chen             switch (eventState)
27477e6fe7aSGilbert Chen             {
27577e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
27677e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
27777e6fe7aSGilbert Chen                 {
27877e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
27977e6fe7aSGilbert Chen                         pldm::utils::Level::CRITICAL,
28077e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
28177e6fe7aSGilbert Chen                 }
28277e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
28377e6fe7aSGilbert Chen                     break;
28477e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
28577e6fe7aSGilbert Chen                 {
28677e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
28777e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
28877e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, false, false);
28977e6fe7aSGilbert Chen                 }
29077e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
29177e6fe7aSGilbert Chen                 {
29277e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
29377e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
29477e6fe7aSGilbert Chen                                                   value, false, false);
29577e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
29677e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
29777e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
29877e6fe7aSGilbert Chen                 }
29977e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
30077e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
30177e6fe7aSGilbert Chen                 default:
30277e6fe7aSGilbert Chen                     break;
30377e6fe7aSGilbert Chen             }
30477e6fe7aSGilbert Chen             break;
30577e6fe7aSGilbert Chen         }
30677e6fe7aSGilbert Chen         default:
30777e6fe7aSGilbert Chen             break;
30877e6fe7aSGilbert Chen     }
30977e6fe7aSGilbert Chen 
31077e6fe7aSGilbert Chen     return PLDM_SUCCESS;
31177e6fe7aSGilbert Chen }
31277e6fe7aSGilbert Chen 
313*9fc79128SThu Nguyen int EventManager::processCperEvent(pldm_tid_t tid, uint16_t eventId,
314*9fc79128SThu Nguyen                                    const uint8_t* eventData,
315*9fc79128SThu Nguyen                                    const size_t eventDataSize)
316*9fc79128SThu Nguyen {
317*9fc79128SThu Nguyen     if (eventDataSize < PLDM_PLATFORM_CPER_EVENT_MIN_LENGTH)
318*9fc79128SThu Nguyen     {
319*9fc79128SThu Nguyen         lg2::error(
320*9fc79128SThu Nguyen             "Error : Invalid CPER Event data length for eventId {EVENTID}.",
321*9fc79128SThu Nguyen             "EVENTID", eventId);
322*9fc79128SThu Nguyen         return PLDM_ERROR;
323*9fc79128SThu Nguyen     }
324*9fc79128SThu Nguyen     const size_t cperEventDataSize =
325*9fc79128SThu Nguyen         eventDataSize - PLDM_PLATFORM_CPER_EVENT_MIN_LENGTH;
326*9fc79128SThu Nguyen     const size_t msgDataLen =
327*9fc79128SThu Nguyen         sizeof(pldm_platform_cper_event) + cperEventDataSize;
328*9fc79128SThu Nguyen     std::string terminusName = "";
329*9fc79128SThu Nguyen     auto msgData = std::make_unique<unsigned char[]>(msgDataLen);
330*9fc79128SThu Nguyen     auto cperEvent = new (msgData.get()) pldm_platform_cper_event;
331*9fc79128SThu Nguyen 
332*9fc79128SThu Nguyen     auto rc = decode_pldm_platform_cper_event(eventData, eventDataSize,
333*9fc79128SThu Nguyen                                               cperEvent, msgDataLen);
334*9fc79128SThu Nguyen 
335*9fc79128SThu Nguyen     if (rc)
336*9fc79128SThu Nguyen     {
337*9fc79128SThu Nguyen         lg2::error(
338*9fc79128SThu Nguyen             "Failed to decode CPER event for eventId {EVENTID} of terminus ID {TID} error {RC}.",
339*9fc79128SThu Nguyen             "EVENTID", eventId, "TID", tid, "RC", rc);
340*9fc79128SThu Nguyen         return rc;
341*9fc79128SThu Nguyen     }
342*9fc79128SThu Nguyen 
343*9fc79128SThu Nguyen     if (termini.contains(tid) && !termini[tid])
344*9fc79128SThu Nguyen     {
345*9fc79128SThu Nguyen         auto tmp = termini[tid]->getTerminusName();
346*9fc79128SThu Nguyen         if (tmp && !tmp.value().empty())
347*9fc79128SThu Nguyen         {
348*9fc79128SThu Nguyen             terminusName = static_cast<std::string>(tmp.value());
349*9fc79128SThu Nguyen         }
350*9fc79128SThu Nguyen     }
351*9fc79128SThu Nguyen 
352*9fc79128SThu Nguyen     // Save event data to file
353*9fc79128SThu Nguyen     std::filesystem::path dirName{"/var/cper"};
354*9fc79128SThu Nguyen     if (!std::filesystem::exists(dirName))
355*9fc79128SThu Nguyen     {
356*9fc79128SThu Nguyen         try
357*9fc79128SThu Nguyen         {
358*9fc79128SThu Nguyen             std::filesystem::create_directory(dirName);
359*9fc79128SThu Nguyen         }
360*9fc79128SThu Nguyen         catch (const std::filesystem::filesystem_error& e)
361*9fc79128SThu Nguyen         {
362*9fc79128SThu Nguyen             lg2::error("Failed to create /var/cper directory: {ERROR}", "ERROR",
363*9fc79128SThu Nguyen                        e);
364*9fc79128SThu Nguyen             return PLDM_ERROR;
365*9fc79128SThu Nguyen         }
366*9fc79128SThu Nguyen     }
367*9fc79128SThu Nguyen 
368*9fc79128SThu Nguyen     std::string fileName{dirName.string() + "/cper-XXXXXX"};
369*9fc79128SThu Nguyen     auto fd = mkstemp(fileName.data());
370*9fc79128SThu Nguyen     if (fd < 0)
371*9fc79128SThu Nguyen     {
372*9fc79128SThu Nguyen         lg2::error("Failed to generate temp file, error {ERRORNO}", "ERRORNO",
373*9fc79128SThu Nguyen                    std::strerror(errno));
374*9fc79128SThu Nguyen         return PLDM_ERROR;
375*9fc79128SThu Nguyen     }
376*9fc79128SThu Nguyen     close(fd);
377*9fc79128SThu Nguyen 
378*9fc79128SThu Nguyen     std::ofstream ofs;
379*9fc79128SThu Nguyen     ofs.exceptions(std::ofstream::failbit | std::ofstream::badbit |
380*9fc79128SThu Nguyen                    std::ofstream::eofbit);
381*9fc79128SThu Nguyen 
382*9fc79128SThu Nguyen     try
383*9fc79128SThu Nguyen     {
384*9fc79128SThu Nguyen         ofs.open(fileName);
385*9fc79128SThu Nguyen         ofs.write(reinterpret_cast<const char*>(
386*9fc79128SThu Nguyen                       pldm_platform_cper_event_event_data(cperEvent)),
387*9fc79128SThu Nguyen                   cperEvent->event_data_length);
388*9fc79128SThu Nguyen         if (cperEvent->format_type == PLDM_PLATFORM_CPER_EVENT_WITH_HEADER)
389*9fc79128SThu Nguyen         {
390*9fc79128SThu Nguyen             rc = createCperDumpEntry("CPER", fileName, terminusName);
391*9fc79128SThu Nguyen         }
392*9fc79128SThu Nguyen         else
393*9fc79128SThu Nguyen         {
394*9fc79128SThu Nguyen             rc = createCperDumpEntry("CPERSection", fileName, terminusName);
395*9fc79128SThu Nguyen         }
396*9fc79128SThu Nguyen         ofs.close();
397*9fc79128SThu Nguyen     }
398*9fc79128SThu Nguyen     catch (const std::ofstream::failure& e)
399*9fc79128SThu Nguyen     {
400*9fc79128SThu Nguyen         lg2::error("Failed to save CPER to '{FILENAME}', error - {ERROR}.",
401*9fc79128SThu Nguyen                    "FILENAME", fileName, "ERROR", e);
402*9fc79128SThu Nguyen         return PLDM_ERROR;
403*9fc79128SThu Nguyen     }
404*9fc79128SThu Nguyen     return rc;
405*9fc79128SThu Nguyen }
406*9fc79128SThu Nguyen 
407*9fc79128SThu Nguyen int EventManager::createCperDumpEntry(const std::string& dataType,
408*9fc79128SThu Nguyen                                       const std::string& dataPath,
409*9fc79128SThu Nguyen                                       const std::string& typeName)
410*9fc79128SThu Nguyen {
411*9fc79128SThu Nguyen     auto createDump =
412*9fc79128SThu Nguyen         [](std::map<std::string, std::variant<std::string, uint64_t>>&
413*9fc79128SThu Nguyen                addData) {
414*9fc79128SThu Nguyen             static constexpr auto dumpObjPath =
415*9fc79128SThu Nguyen                 "/xyz/openbmc_project/dump/faultlog";
416*9fc79128SThu Nguyen             static constexpr auto dumpInterface =
417*9fc79128SThu Nguyen                 "xyz.openbmc_project.Dump.Create";
418*9fc79128SThu Nguyen             auto& bus = pldm::utils::DBusHandler::getBus();
419*9fc79128SThu Nguyen 
420*9fc79128SThu Nguyen             try
421*9fc79128SThu Nguyen             {
422*9fc79128SThu Nguyen                 auto service = pldm::utils::DBusHandler().getService(
423*9fc79128SThu Nguyen                     dumpObjPath, dumpInterface);
424*9fc79128SThu Nguyen                 auto method = bus.new_method_call(service.c_str(), dumpObjPath,
425*9fc79128SThu Nguyen                                                   dumpInterface, "CreateDump");
426*9fc79128SThu Nguyen                 method.append(addData);
427*9fc79128SThu Nguyen                 bus.call_noreply(method);
428*9fc79128SThu Nguyen             }
429*9fc79128SThu Nguyen             catch (const std::exception& e)
430*9fc79128SThu Nguyen             {
431*9fc79128SThu Nguyen                 lg2::error(
432*9fc79128SThu Nguyen                     "Failed to create D-Bus Dump entry, error - {ERROR}.",
433*9fc79128SThu Nguyen                     "ERROR", e);
434*9fc79128SThu Nguyen             }
435*9fc79128SThu Nguyen         };
436*9fc79128SThu Nguyen 
437*9fc79128SThu Nguyen     std::map<std::string, std::variant<std::string, uint64_t>> addData;
438*9fc79128SThu Nguyen     addData["Type"] = dataType;
439*9fc79128SThu Nguyen     addData["PrimaryLogId"] = dataPath;
440*9fc79128SThu Nguyen     addData["AdditionalTypeName"] = typeName;
441*9fc79128SThu Nguyen     createDump(addData);
442*9fc79128SThu Nguyen     return PLDM_SUCCESS;
443*9fc79128SThu Nguyen }
444*9fc79128SThu Nguyen 
44577e6fe7aSGilbert Chen } // namespace platform_mc
44677e6fe7aSGilbert Chen } // namespace pldm
447