diff --git a/common/utils.cpp b/common/utils.cpp index cf52f86ac1..b181ba52a2 100644 --- a/common/utils.cpp +++ b/common/utils.cpp @@ -20,6 +20,13 @@ #include #include +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include + PHOSPHOR_LOG2_USING; namespace pldm @@ -610,6 +617,88 @@ int emitRDEDeviceDetectedSignal( return PLDM_SUCCESS; } +void emitPldmMessagePollEventSignal( + uint8_t formatVersion, uint8_t tid, const std::string& tName, + uint8_t eventClass, uint32_t dataTransferHandle, uint16_t eventId, + uint16_t eventDataSize, int fd) { + + try + { + auto& bus = DBusHandler::getBus(); + auto msg = bus.new_signal("/xyz/openbmc_project/pldm", + "xyz.openbmc_project.PLDM.Event", + "PldmMessagePollEvent"); + + // Generate the current timestamp in microseconds + uint64_t timestamp = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + + // Please follow/comply_with the signature in yaml file + msg.append(timestamp, + tid, + tName, + formatVersion, + eventClass, + eventId, + dataTransferHandle, + eventDataSize, + sdbusplus::message::unix_fd(fd)); + msg.signal_send(); + } + catch (const std::exception& e) + { + lg2::error("Failed to emit PLDM pldmMessagePollEvent signal: {ERROR}", + "ERROR", e.what()); + return; + } + + lg2::info("Emitting PLDM Message Poll Event signal: FormatVersion={FV}, TID={TID}, " + "TerminusName={NAME}, EventClass={CLASS}, EventId={ID}, " + "DataTransferHandlee={DTH}, " + "Size={SIZE}, FD={FD}", + "FV", formatVersion, + "TID", tid, + "NAME", tName, + "CLASS", lg2::hex, eventClass, + "ID", lg2::hex, eventId, + "DTH", lg2::hex, dataTransferHandle, + "SIZE", lg2::hex, eventDataSize, + "FD", fd); +} + +int create_mem_fd(const std::vector& data) +{ + // Create the anonymous file in RAM + int fd = memfd_create("event_data", MFD_CLOEXEC); + if (fd == -1) { + lg2::error("Failed to create memfd, errno: {ERRNO}", + "ERRNO", errno); + return -1; + } + + size_t dataSize = data.size(); + lg2::info("truncate memfd to size {SIZE}", "SIZE", dataSize); + + if (ftruncate(fd, dataSize) == -1) { + lg2::error("Failed to truncate memfd to size {SIZE}, errno: {ERRNO}", + "SIZE", dataSize, "ERRNO", errno); + close(fd); + return -1; + } + + if (write(fd, data.data(), dataSize) == -1) { + lg2::error("Failed to write to memfd, errno: {ERRNO}", "ERRNO", errno); + close(fd); + return -1; + } + + // Reset the file offset to the beginning for the receiver + lseek(fd, 0, SEEK_SET); + + return fd; +} + void recoverMctpEndpoint(const std::string& endpointObjPath) { auto& bus = DBusHandler::getBus(); diff --git a/common/utils.hpp b/common/utils.hpp index 3f00a9b374..6b74445373 100644 --- a/common/utils.hpp +++ b/common/utils.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -580,6 +581,32 @@ int emitRDEDeviceDetectedSignal( uint8_t tid, eid mctpEid, pldm::UUID devUUID, const std::vector>& pdrPayloads); +/** @brief Emit a D-Bus signal for a PLDM Message Poll event. + * + * This signal notifies subscribers that a message poll event has been + * received from a specific terminal, providing the necessary metadata + * to retrieve the event data. + * + * @param[in] formatVersion - The version of the event format (from PLDM spec) + * @param[in] tid - Terminal ID of the source + * @param[in] tName - Terminal name or identifier string + * @param[in] eventClass - The class of the event being polled + * @param[in] dataTransferHandle - Handle used to identify the data transfer + * @param[in] eventId - The unique identifier for the event + * @param[in] eventDataSize - The size of the event data in bytes + * @param[in] fd - File descriptor for the data transfer, if applicable + */ +void emitPldmMessagePollEventSignal( + uint8_t formatVersion, uint8_t tid, const std::string& tName, + uint8_t eventClass, uint32_t dataTransferHandle, + uint16_t eventId, uint16_t eventDataSize, int fd); + +/** @brief Create a memfd and write data to it + * @param[in] data - data to write to the memfd + * @return fd - the file descriptor of the memfd + */ +int create_mem_fd(const std::vector& data); + /** * @brief call Recover() method to recover an MCTP Endpoint * @param[in] MCTP Endpoint's object path diff --git a/platform-mc/event_manager.cpp b/platform-mc/event_manager.cpp index 8388836c6f..a8f32418dc 100644 --- a/platform-mc/event_manager.cpp +++ b/platform-mc/event_manager.cpp @@ -525,9 +525,25 @@ int EventManager::getNextPartParameters( return PLDM_SUCCESS; } +std::string EventManager::getTerminusName(pldm_tid_t tid) const +{ + auto it = termini.find(tid); + if (it != termini.end()) + { + auto& terminus = it->second; + auto tNameOpt = terminus->getTerminusName(); + if (tNameOpt) + { + return std::string(*tNameOpt); + } + } + // Fallback: Return TID as a string if name isn't available + return std::to_string(tid); +} + void EventManager::callPolledEventHandlers(pldm_tid_t tid, uint8_t eventClass, - uint16_t eventId, - std::vector& eventMessage) + uint8_t formatVersion, uint32_t dataTransferHandle, + uint16_t eventId, std::vector& eventMessage) { try { @@ -541,6 +557,18 @@ void EventManager::callPolledEventHandlers(pldm_tid_t tid, uint8_t eventClass, lg2::error( "Failed to handle platform event msg for terminus {TID}, event {EVENTID} return {RET}", "TID", tid, "EVENTID", eventId, "RET", rc); + } else { + lg2::info("Handle platform event msg for terminus {TID}, event {EVENTID}, size {EVSIZE}", + "TID", tid, "EVENTID", lg2::hex, eventId, "EVSIZE", lg2::hex, eventMessage.size()); + + int fd = pldm::utils::create_mem_fd(eventMessage); + if (fd != -1) { + std::string tName = getTerminusName(tid); + pldm::utils::emitPldmMessagePollEventSignal( + formatVersion, tid, tName, eventClass, dataTransferHandle, + eventId, eventMessage.size(), fd); + close(fd); + } } } } @@ -617,6 +645,7 @@ exec::task EventManager::pollForPlatformEventTask( if (eventHandlers.contains(polledEventClass)) { callPolledEventHandlers(polledEventTid, polledEventClass, + formatVersion, pollDataTransferHandle, polledEventId, eventMessage); } eventMessage.clear(); diff --git a/platform-mc/event_manager.hpp b/platform-mc/event_manager.hpp index 083725d57f..f65bb62800 100644 --- a/platform-mc/event_manager.hpp +++ b/platform-mc/event_manager.hpp @@ -212,13 +212,23 @@ class EventManager * * @param[in] tid - terminus ID * @param[out] eventClass - Event class + * @param[in] formatVersion - The PLDM version/format of the event data + * @param[in] dataTransferHandle - Handle identifying the specific data block + * in the event transfer * @param[out] eventId - Event ID * @param[in] eventMessage - event data of response message * */ void callPolledEventHandlers(pldm_tid_t tid, uint8_t eventClass, - uint16_t eventId, - std::vector& eventMessage); + uint8_t formatVersion, uint32_t dataTransferHandle, + uint16_t eventId, std::vector& eventMessage); + + /** @brief Get the terminus name for a given TID + * + * @param[in] tid - Terminal ID + * @return The terminus name as a string, or a fallback string if not found + */ + std::string getTerminusName(pldm_tid_t tid) const; /** @brief Reference of terminusManager */ TerminusManager& terminusManager;