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