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 
handlePlatformEvent(pldm_tid_t tid,uint16_t eventId,uint8_t eventClass,const uint8_t * eventData,size_t eventDataSize)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 {
25*bd0277e4SThu Nguyen     /* Only handle the event of the discovered termini*/
26*bd0277e4SThu Nguyen     if (!termini.contains(tid))
27*bd0277e4SThu Nguyen     {
28*bd0277e4SThu Nguyen         lg2::error("Terminus ID {TID} is not in the managing list.", "TID",
29*bd0277e4SThu Nguyen                    tid);
30*bd0277e4SThu Nguyen         return PLDM_ERROR;
31*bd0277e4SThu Nguyen     }
32*bd0277e4SThu Nguyen 
3377e6fe7aSGilbert Chen     /* EventClass sensorEvent `Table 11 - PLDM Event Types` DSP0248 */
3477e6fe7aSGilbert Chen     if (eventClass == PLDM_SENSOR_EVENT)
3577e6fe7aSGilbert Chen     {
3677e6fe7aSGilbert Chen         uint16_t sensorId = 0;
3777e6fe7aSGilbert Chen         uint8_t sensorEventClassType = 0;
3877e6fe7aSGilbert Chen         size_t eventClassDataOffset = 0;
3977e6fe7aSGilbert Chen         auto rc = decode_sensor_event_data(eventData, eventDataSize, &sensorId,
4077e6fe7aSGilbert Chen                                            &sensorEventClassType,
4177e6fe7aSGilbert Chen                                            &eventClassDataOffset);
4277e6fe7aSGilbert Chen         if (rc)
4377e6fe7aSGilbert Chen         {
4477e6fe7aSGilbert Chen             lg2::error(
4577e6fe7aSGilbert Chen                 "Failed to decode sensor event data from terminus ID {TID}, event class {CLASS}, event ID {EVENTID} with return code {RC}.",
4677e6fe7aSGilbert Chen                 "TID", tid, "CLASS", eventClass, "EVENTID", eventId, "RC", rc);
4777e6fe7aSGilbert Chen             return rc;
4877e6fe7aSGilbert Chen         }
4977e6fe7aSGilbert Chen         switch (sensorEventClassType)
5077e6fe7aSGilbert Chen         {
5177e6fe7aSGilbert Chen             case PLDM_NUMERIC_SENSOR_STATE:
5277e6fe7aSGilbert Chen             {
5377e6fe7aSGilbert Chen                 const uint8_t* sensorData = eventData + eventClassDataOffset;
5477e6fe7aSGilbert Chen                 size_t sensorDataLength = eventDataSize - eventClassDataOffset;
5577e6fe7aSGilbert Chen                 return processNumericSensorEvent(tid, sensorId, sensorData,
5677e6fe7aSGilbert Chen                                                  sensorDataLength);
5777e6fe7aSGilbert Chen             }
5877e6fe7aSGilbert Chen             case PLDM_STATE_SENSOR_STATE:
5977e6fe7aSGilbert Chen             case PLDM_SENSOR_OP_STATE:
6077e6fe7aSGilbert Chen             default:
6177e6fe7aSGilbert Chen                 lg2::info(
6277e6fe7aSGilbert Chen                     "Unsupported class type {CLASSTYPE} for the sensor event from terminus ID {TID} sensorId {SID}",
6377e6fe7aSGilbert Chen                     "CLASSTYPE", sensorEventClassType, "TID", tid, "SID",
6477e6fe7aSGilbert Chen                     sensorId);
6577e6fe7aSGilbert Chen                 return PLDM_ERROR;
6677e6fe7aSGilbert Chen         }
6777e6fe7aSGilbert Chen     }
6877e6fe7aSGilbert Chen 
699fc79128SThu Nguyen     /* EventClass CPEREvent as `Table 11 - PLDM Event Types` DSP0248 V1.3.0 */
709fc79128SThu Nguyen     if (eventClass == PLDM_CPER_EVENT)
719fc79128SThu Nguyen     {
729fc79128SThu Nguyen         return processCperEvent(tid, eventId, eventData, eventDataSize);
739fc79128SThu Nguyen     }
749fc79128SThu Nguyen 
7577e6fe7aSGilbert Chen     lg2::info("Unsupported class type {CLASSTYPE}", "CLASSTYPE", eventClass);
7677e6fe7aSGilbert Chen 
7777e6fe7aSGilbert Chen     return PLDM_ERROR;
7877e6fe7aSGilbert Chen }
7977e6fe7aSGilbert Chen 
processNumericSensorEvent(pldm_tid_t tid,uint16_t sensorId,const uint8_t * sensorData,size_t sensorDataLength)8077e6fe7aSGilbert Chen int EventManager::processNumericSensorEvent(pldm_tid_t tid, uint16_t sensorId,
8177e6fe7aSGilbert Chen                                             const uint8_t* sensorData,
8277e6fe7aSGilbert Chen                                             size_t sensorDataLength)
8377e6fe7aSGilbert Chen {
8477e6fe7aSGilbert Chen     uint8_t eventState = 0;
8577e6fe7aSGilbert Chen     uint8_t previousEventState = 0;
8677e6fe7aSGilbert Chen     uint8_t sensorDataSize = 0;
8777e6fe7aSGilbert Chen     uint32_t presentReading;
8877e6fe7aSGilbert Chen     auto rc = decode_numeric_sensor_data(
8977e6fe7aSGilbert Chen         sensorData, sensorDataLength, &eventState, &previousEventState,
9077e6fe7aSGilbert Chen         &sensorDataSize, &presentReading);
9177e6fe7aSGilbert Chen     if (rc)
9277e6fe7aSGilbert Chen     {
9377e6fe7aSGilbert Chen         lg2::error(
9477e6fe7aSGilbert Chen             "Failed to decode numericSensorState event for terminus ID {TID}, error {RC} ",
9577e6fe7aSGilbert Chen             "TID", tid, "RC", rc);
9677e6fe7aSGilbert Chen         return rc;
9777e6fe7aSGilbert Chen     }
9877e6fe7aSGilbert Chen 
9977e6fe7aSGilbert Chen     double value = static_cast<double>(presentReading);
10077e6fe7aSGilbert Chen     lg2::error(
10177e6fe7aSGilbert Chen         "processNumericSensorEvent tid {TID}, sensorID {SID} value {VAL} previousState {PSTATE} eventState {ESTATE}",
10277e6fe7aSGilbert Chen         "TID", tid, "SID", sensorId, "VAL", value, "PSTATE", previousEventState,
10377e6fe7aSGilbert Chen         "ESTATE", eventState);
10477e6fe7aSGilbert Chen 
10577e6fe7aSGilbert Chen     if (!termini.contains(tid) || !termini[tid])
10677e6fe7aSGilbert Chen     {
10777e6fe7aSGilbert Chen         lg2::error("Terminus ID {TID} is not in the managing list.", "TID",
10877e6fe7aSGilbert Chen                    tid);
10977e6fe7aSGilbert Chen         return PLDM_ERROR;
11077e6fe7aSGilbert Chen     }
11177e6fe7aSGilbert Chen 
11277e6fe7aSGilbert Chen     auto& terminus = termini[tid];
11377e6fe7aSGilbert Chen 
11477e6fe7aSGilbert Chen     auto sensor = terminus->getSensorObject(sensorId);
11577e6fe7aSGilbert Chen     if (!sensor)
11677e6fe7aSGilbert Chen     {
11777e6fe7aSGilbert Chen         lg2::error(
11877e6fe7aSGilbert Chen             "Terminus ID {TID} has no sensor object with sensor ID {SID}.",
11977e6fe7aSGilbert Chen             "TID", tid, "SID", sensorId);
12077e6fe7aSGilbert Chen         return PLDM_ERROR;
12177e6fe7aSGilbert Chen     }
12277e6fe7aSGilbert Chen 
12377e6fe7aSGilbert Chen     switch (previousEventState)
12477e6fe7aSGilbert Chen     {
12577e6fe7aSGilbert Chen         case PLDM_SENSOR_UNKNOWN:
12677e6fe7aSGilbert Chen         case PLDM_SENSOR_NORMAL:
12777e6fe7aSGilbert Chen         {
12877e6fe7aSGilbert Chen             switch (eventState)
12977e6fe7aSGilbert Chen             {
13077e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
13177e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
13277e6fe7aSGilbert Chen                 {
13377e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
13477e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
13577e6fe7aSGilbert Chen                                                   value, true, true);
13677e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
13777e6fe7aSGilbert Chen                         pldm::utils::Level::CRITICAL,
13877e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
13977e6fe7aSGilbert Chen                 }
14077e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
14177e6fe7aSGilbert Chen                 {
14277e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
14377e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
14477e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
14577e6fe7aSGilbert Chen                 }
14677e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
14777e6fe7aSGilbert Chen                     break;
14877e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
14977e6fe7aSGilbert Chen                 {
15077e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
15177e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
15277e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
15377e6fe7aSGilbert Chen                 }
15477e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
15577e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
15677e6fe7aSGilbert Chen                 {
15777e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
15877e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
15977e6fe7aSGilbert Chen                                                   value, true, true);
16077e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
16177e6fe7aSGilbert Chen                         pldm::utils::Level::CRITICAL,
16277e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
16377e6fe7aSGilbert Chen                 }
16477e6fe7aSGilbert Chen                 default:
16577e6fe7aSGilbert Chen                     break;
16677e6fe7aSGilbert Chen             }
16777e6fe7aSGilbert Chen             break;
16877e6fe7aSGilbert Chen         }
16977e6fe7aSGilbert Chen         case PLDM_SENSOR_LOWERWARNING:
17077e6fe7aSGilbert Chen         {
17177e6fe7aSGilbert Chen             switch (eventState)
17277e6fe7aSGilbert Chen             {
17377e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
17477e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
17577e6fe7aSGilbert Chen                     break;
17677e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
17777e6fe7aSGilbert Chen                 {
17877e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
17977e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
18077e6fe7aSGilbert Chen                                                   value, false, false);
18177e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
18277e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
18377e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
18477e6fe7aSGilbert Chen                 }
18577e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
18677e6fe7aSGilbert Chen                 {
18777e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
18877e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
18977e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, false, false);
19077e6fe7aSGilbert Chen                 }
19177e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
19277e6fe7aSGilbert Chen                     break;
19377e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
19477e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
19577e6fe7aSGilbert Chen                 {
19677e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
19777e6fe7aSGilbert Chen                         pldm::utils::Level::CRITICAL,
19877e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
19977e6fe7aSGilbert Chen                 }
20077e6fe7aSGilbert Chen                 default:
20177e6fe7aSGilbert Chen                     break;
20277e6fe7aSGilbert Chen             }
20377e6fe7aSGilbert Chen             break;
20477e6fe7aSGilbert Chen         }
20577e6fe7aSGilbert Chen         case PLDM_SENSOR_LOWERCRITICAL:
20677e6fe7aSGilbert Chen         case PLDM_SENSOR_LOWERFATAL:
20777e6fe7aSGilbert Chen         {
20877e6fe7aSGilbert Chen             switch (eventState)
20977e6fe7aSGilbert Chen             {
21077e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
21177e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
21277e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
21377e6fe7aSGilbert Chen                     break;
21477e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
21577e6fe7aSGilbert Chen                 {
21677e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::CRITICAL,
21777e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
21877e6fe7aSGilbert Chen                                                   value, false, false);
21977e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
22077e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
22177e6fe7aSGilbert Chen                                                   value, true, true);
22277e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
22377e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
22477e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, false, false);
22577e6fe7aSGilbert Chen                 }
22677e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
22777e6fe7aSGilbert Chen                 {
22877e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::CRITICAL,
22977e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
23077e6fe7aSGilbert Chen                                                   value, false, false);
23177e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
23277e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
23377e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
23477e6fe7aSGilbert Chen                 }
23577e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
23677e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
23777e6fe7aSGilbert Chen                 default:
23877e6fe7aSGilbert Chen                     break;
23977e6fe7aSGilbert Chen             }
24077e6fe7aSGilbert Chen             break;
24177e6fe7aSGilbert Chen         }
24277e6fe7aSGilbert Chen         case PLDM_SENSOR_UPPERFATAL:
24377e6fe7aSGilbert Chen         case PLDM_SENSOR_UPPERCRITICAL:
24477e6fe7aSGilbert Chen         {
24577e6fe7aSGilbert Chen             switch (eventState)
24677e6fe7aSGilbert Chen             {
24777e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
24877e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
24977e6fe7aSGilbert Chen                     break;
25077e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
25177e6fe7aSGilbert Chen                 {
25277e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::CRITICAL,
25377e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
25477e6fe7aSGilbert Chen                                                   value, false, false);
25577e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
25677e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
25777e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
25877e6fe7aSGilbert Chen                 }
25977e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
26077e6fe7aSGilbert Chen                 {
26177e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::CRITICAL,
26277e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
26377e6fe7aSGilbert Chen                                                   value, false, false);
26477e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
26577e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
26677e6fe7aSGilbert Chen                                                   value, true, true);
26777e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
26877e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
26977e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, false, false);
27077e6fe7aSGilbert Chen                 }
27177e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
27277e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
27377e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
27477e6fe7aSGilbert Chen                 default:
27577e6fe7aSGilbert Chen                     break;
27677e6fe7aSGilbert Chen             }
27777e6fe7aSGilbert Chen             break;
27877e6fe7aSGilbert Chen         }
27977e6fe7aSGilbert Chen         case PLDM_SENSOR_UPPERWARNING:
28077e6fe7aSGilbert Chen         {
28177e6fe7aSGilbert Chen             switch (eventState)
28277e6fe7aSGilbert Chen             {
28377e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
28477e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
28577e6fe7aSGilbert Chen                 {
28677e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
28777e6fe7aSGilbert Chen                         pldm::utils::Level::CRITICAL,
28877e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
28977e6fe7aSGilbert Chen                 }
29077e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
29177e6fe7aSGilbert Chen                     break;
29277e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
29377e6fe7aSGilbert Chen                 {
29477e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
29577e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
29677e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, false, false);
29777e6fe7aSGilbert Chen                 }
29877e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
29977e6fe7aSGilbert Chen                 {
30077e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
30177e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
30277e6fe7aSGilbert Chen                                                   value, false, false);
30377e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
30477e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
30577e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
30677e6fe7aSGilbert Chen                 }
30777e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
30877e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
30977e6fe7aSGilbert Chen                 default:
31077e6fe7aSGilbert Chen                     break;
31177e6fe7aSGilbert Chen             }
31277e6fe7aSGilbert Chen             break;
31377e6fe7aSGilbert Chen         }
31477e6fe7aSGilbert Chen         default:
31577e6fe7aSGilbert Chen             break;
31677e6fe7aSGilbert Chen     }
31777e6fe7aSGilbert Chen 
31877e6fe7aSGilbert Chen     return PLDM_SUCCESS;
31977e6fe7aSGilbert Chen }
32077e6fe7aSGilbert Chen 
processCperEvent(pldm_tid_t tid,uint16_t eventId,const uint8_t * eventData,const size_t eventDataSize)3219fc79128SThu Nguyen int EventManager::processCperEvent(pldm_tid_t tid, uint16_t eventId,
3229fc79128SThu Nguyen                                    const uint8_t* eventData,
3239fc79128SThu Nguyen                                    const size_t eventDataSize)
3249fc79128SThu Nguyen {
3259fc79128SThu Nguyen     if (eventDataSize < PLDM_PLATFORM_CPER_EVENT_MIN_LENGTH)
3269fc79128SThu Nguyen     {
3279fc79128SThu Nguyen         lg2::error(
3289fc79128SThu Nguyen             "Error : Invalid CPER Event data length for eventId {EVENTID}.",
3299fc79128SThu Nguyen             "EVENTID", eventId);
3309fc79128SThu Nguyen         return PLDM_ERROR;
3319fc79128SThu Nguyen     }
3329fc79128SThu Nguyen     const size_t cperEventDataSize =
3339fc79128SThu Nguyen         eventDataSize - PLDM_PLATFORM_CPER_EVENT_MIN_LENGTH;
3349fc79128SThu Nguyen     const size_t msgDataLen =
3359fc79128SThu Nguyen         sizeof(pldm_platform_cper_event) + cperEventDataSize;
3369fc79128SThu Nguyen     std::string terminusName = "";
3379fc79128SThu Nguyen     auto msgData = std::make_unique<unsigned char[]>(msgDataLen);
3389fc79128SThu Nguyen     auto cperEvent = new (msgData.get()) pldm_platform_cper_event;
3399fc79128SThu Nguyen 
3409fc79128SThu Nguyen     auto rc = decode_pldm_platform_cper_event(eventData, eventDataSize,
3419fc79128SThu Nguyen                                               cperEvent, msgDataLen);
3429fc79128SThu Nguyen 
3439fc79128SThu Nguyen     if (rc)
3449fc79128SThu Nguyen     {
3459fc79128SThu Nguyen         lg2::error(
3469fc79128SThu Nguyen             "Failed to decode CPER event for eventId {EVENTID} of terminus ID {TID} error {RC}.",
3479fc79128SThu Nguyen             "EVENTID", eventId, "TID", tid, "RC", rc);
3489fc79128SThu Nguyen         return rc;
3499fc79128SThu Nguyen     }
3509fc79128SThu Nguyen 
3519fc79128SThu Nguyen     if (termini.contains(tid) && !termini[tid])
3529fc79128SThu Nguyen     {
3539fc79128SThu Nguyen         auto tmp = termini[tid]->getTerminusName();
3549fc79128SThu Nguyen         if (tmp && !tmp.value().empty())
3559fc79128SThu Nguyen         {
3569fc79128SThu Nguyen             terminusName = static_cast<std::string>(tmp.value());
3579fc79128SThu Nguyen         }
3589fc79128SThu Nguyen     }
359*bd0277e4SThu Nguyen     else
360*bd0277e4SThu Nguyen     {
361*bd0277e4SThu Nguyen         lg2::error("Terminus ID {TID} is not in the managing list.", "TID",
362*bd0277e4SThu Nguyen                    tid);
363*bd0277e4SThu Nguyen         return PLDM_ERROR;
364*bd0277e4SThu Nguyen     }
3659fc79128SThu Nguyen 
3669fc79128SThu Nguyen     // Save event data to file
3679fc79128SThu Nguyen     std::filesystem::path dirName{"/var/cper"};
3689fc79128SThu Nguyen     if (!std::filesystem::exists(dirName))
3699fc79128SThu Nguyen     {
3709fc79128SThu Nguyen         try
3719fc79128SThu Nguyen         {
3729fc79128SThu Nguyen             std::filesystem::create_directory(dirName);
3739fc79128SThu Nguyen         }
3749fc79128SThu Nguyen         catch (const std::filesystem::filesystem_error& e)
3759fc79128SThu Nguyen         {
3769fc79128SThu Nguyen             lg2::error("Failed to create /var/cper directory: {ERROR}", "ERROR",
3779fc79128SThu Nguyen                        e);
3789fc79128SThu Nguyen             return PLDM_ERROR;
3799fc79128SThu Nguyen         }
3809fc79128SThu Nguyen     }
3819fc79128SThu Nguyen 
3829fc79128SThu Nguyen     std::string fileName{dirName.string() + "/cper-XXXXXX"};
3839fc79128SThu Nguyen     auto fd = mkstemp(fileName.data());
3849fc79128SThu Nguyen     if (fd < 0)
3859fc79128SThu Nguyen     {
3869fc79128SThu Nguyen         lg2::error("Failed to generate temp file, error {ERRORNO}", "ERRORNO",
3879fc79128SThu Nguyen                    std::strerror(errno));
3889fc79128SThu Nguyen         return PLDM_ERROR;
3899fc79128SThu Nguyen     }
3909fc79128SThu Nguyen     close(fd);
3919fc79128SThu Nguyen 
3929fc79128SThu Nguyen     std::ofstream ofs;
3939fc79128SThu Nguyen     ofs.exceptions(std::ofstream::failbit | std::ofstream::badbit |
3949fc79128SThu Nguyen                    std::ofstream::eofbit);
3959fc79128SThu Nguyen 
3969fc79128SThu Nguyen     try
3979fc79128SThu Nguyen     {
3989fc79128SThu Nguyen         ofs.open(fileName);
3999fc79128SThu Nguyen         ofs.write(reinterpret_cast<const char*>(
4009fc79128SThu Nguyen                       pldm_platform_cper_event_event_data(cperEvent)),
4019fc79128SThu Nguyen                   cperEvent->event_data_length);
4029fc79128SThu Nguyen         if (cperEvent->format_type == PLDM_PLATFORM_CPER_EVENT_WITH_HEADER)
4039fc79128SThu Nguyen         {
4049fc79128SThu Nguyen             rc = createCperDumpEntry("CPER", fileName, terminusName);
4059fc79128SThu Nguyen         }
4069fc79128SThu Nguyen         else
4079fc79128SThu Nguyen         {
4089fc79128SThu Nguyen             rc = createCperDumpEntry("CPERSection", fileName, terminusName);
4099fc79128SThu Nguyen         }
4109fc79128SThu Nguyen         ofs.close();
4119fc79128SThu Nguyen     }
4129fc79128SThu Nguyen     catch (const std::ofstream::failure& e)
4139fc79128SThu Nguyen     {
4149fc79128SThu Nguyen         lg2::error("Failed to save CPER to '{FILENAME}', error - {ERROR}.",
4159fc79128SThu Nguyen                    "FILENAME", fileName, "ERROR", e);
4169fc79128SThu Nguyen         return PLDM_ERROR;
4179fc79128SThu Nguyen     }
4189fc79128SThu Nguyen     return rc;
4199fc79128SThu Nguyen }
4209fc79128SThu Nguyen 
createCperDumpEntry(const std::string & dataType,const std::string & dataPath,const std::string & typeName)4219fc79128SThu Nguyen int EventManager::createCperDumpEntry(const std::string& dataType,
4229fc79128SThu Nguyen                                       const std::string& dataPath,
4239fc79128SThu Nguyen                                       const std::string& typeName)
4249fc79128SThu Nguyen {
4259fc79128SThu Nguyen     auto createDump =
4269fc79128SThu Nguyen         [](std::map<std::string, std::variant<std::string, uint64_t>>&
4279fc79128SThu Nguyen                addData) {
4289fc79128SThu Nguyen             static constexpr auto dumpObjPath =
4299fc79128SThu Nguyen                 "/xyz/openbmc_project/dump/faultlog";
4309fc79128SThu Nguyen             static constexpr auto dumpInterface =
4319fc79128SThu Nguyen                 "xyz.openbmc_project.Dump.Create";
4329fc79128SThu Nguyen             auto& bus = pldm::utils::DBusHandler::getBus();
4339fc79128SThu Nguyen 
4349fc79128SThu Nguyen             try
4359fc79128SThu Nguyen             {
4369fc79128SThu Nguyen                 auto service = pldm::utils::DBusHandler().getService(
4379fc79128SThu Nguyen                     dumpObjPath, dumpInterface);
4389fc79128SThu Nguyen                 auto method = bus.new_method_call(service.c_str(), dumpObjPath,
4399fc79128SThu Nguyen                                                   dumpInterface, "CreateDump");
4409fc79128SThu Nguyen                 method.append(addData);
4419fc79128SThu Nguyen                 bus.call_noreply(method);
4429fc79128SThu Nguyen             }
4439fc79128SThu Nguyen             catch (const std::exception& e)
4449fc79128SThu Nguyen             {
4459fc79128SThu Nguyen                 lg2::error(
4469fc79128SThu Nguyen                     "Failed to create D-Bus Dump entry, error - {ERROR}.",
4479fc79128SThu Nguyen                     "ERROR", e);
4489fc79128SThu Nguyen             }
4499fc79128SThu Nguyen         };
4509fc79128SThu Nguyen 
4519fc79128SThu Nguyen     std::map<std::string, std::variant<std::string, uint64_t>> addData;
4529fc79128SThu Nguyen     addData["Type"] = dataType;
4539fc79128SThu Nguyen     addData["PrimaryLogId"] = dataPath;
4549fc79128SThu Nguyen     addData["AdditionalTypeName"] = typeName;
4559fc79128SThu Nguyen     createDump(addData);
4569fc79128SThu Nguyen     return PLDM_SUCCESS;
4579fc79128SThu Nguyen }
4589fc79128SThu Nguyen 
45977e6fe7aSGilbert Chen } // namespace platform_mc
46077e6fe7aSGilbert Chen } // namespace pldm
461