1 #include "event_manager.hpp"
2
3 #include "terminus_manager.hpp"
4
5 #include <libpldm/platform.h>
6 #include <libpldm/utils.h>
7
8 #include <phosphor-logging/lg2.hpp>
9 #include <xyz/openbmc_project/Dump/Create/common.hpp>
10 #include <xyz/openbmc_project/Logging/Entry/server.hpp>
11
12 #include <cerrno>
13 #include <memory>
14
15 PHOSPHOR_LOG2_USING;
16
17 using DumpCreate = sdbusplus::common::xyz::openbmc_project::dump::Create;
18
19 namespace pldm
20 {
21 namespace platform_mc
22 {
23 namespace fs = std::filesystem;
24
handlePlatformEvent(pldm_tid_t tid,uint16_t eventId,uint8_t eventClass,const uint8_t * eventData,size_t eventDataSize)25 int EventManager::handlePlatformEvent(
26 pldm_tid_t tid, uint16_t eventId, uint8_t eventClass,
27 const uint8_t* eventData, size_t eventDataSize)
28 {
29 /* Only handle the event of the discovered termini*/
30 if (!termini.contains(tid))
31 {
32 lg2::error("Terminus ID {TID} is not in the managing list.", "TID",
33 tid);
34 return PLDM_ERROR;
35 }
36
37 /* EventClass sensorEvent `Table 11 - PLDM Event Types` DSP0248 */
38 if (eventClass == PLDM_SENSOR_EVENT)
39 {
40 uint16_t sensorId = 0;
41 uint8_t sensorEventClassType = 0;
42 size_t eventClassDataOffset = 0;
43 auto rc = decode_sensor_event_data(eventData, eventDataSize, &sensorId,
44 &sensorEventClassType,
45 &eventClassDataOffset);
46 if (rc)
47 {
48 lg2::error(
49 "Failed to decode sensor event data from terminus ID {TID}, event class {CLASS}, event ID {EVENTID} with return code {RC}.",
50 "TID", tid, "CLASS", eventClass, "EVENTID", eventId, "RC", rc);
51 return rc;
52 }
53 switch (sensorEventClassType)
54 {
55 case PLDM_NUMERIC_SENSOR_STATE:
56 {
57 const uint8_t* sensorData = eventData + eventClassDataOffset;
58 size_t sensorDataLength = eventDataSize - eventClassDataOffset;
59 return processNumericSensorEvent(tid, sensorId, sensorData,
60 sensorDataLength);
61 }
62 case PLDM_STATE_SENSOR_STATE:
63 case PLDM_SENSOR_OP_STATE:
64 default:
65 lg2::info(
66 "Unsupported class type {CLASSTYPE} for the sensor event from terminus ID {TID} sensorId {SID}",
67 "CLASSTYPE", sensorEventClassType, "TID", tid, "SID",
68 sensorId);
69 return PLDM_ERROR;
70 }
71 }
72
73 /* EventClass CPEREvent as `Table 11 - PLDM Event Types` DSP0248 V1.3.0 */
74 if (eventClass == PLDM_CPER_EVENT)
75 {
76 return processCperEvent(tid, eventId, eventData, eventDataSize);
77 }
78
79 /* EventClass pldmMessagePollEvent `Table 11 - PLDM Event Types` DSP0248 */
80 if (eventClass == PLDM_MESSAGE_POLL_EVENT)
81 {
82 lg2::info("Received pldmMessagePollEvent for terminus {TID}", "TID",
83 tid);
84 pldm_message_poll_event poll_event{};
85 auto rc = decode_pldm_message_poll_event_data(eventData, eventDataSize,
86 &poll_event);
87 if (rc)
88 {
89 lg2::error(
90 "Failed to decode PldmMessagePollEvent event, error {RC} ",
91 "RC", rc);
92 return rc;
93 }
94
95 auto it = termini.find(tid);
96 if (it != termini.end())
97 {
98 auto& terminus = it->second; // Reference for clarity
99 terminus->pollEvent = true;
100 terminus->pollEventId = poll_event.event_id;
101 terminus->pollDataTransferHandle = poll_event.data_transfer_handle;
102 }
103
104 return PLDM_SUCCESS;
105 }
106
107 lg2::info("Unsupported class type {CLASSTYPE}", "CLASSTYPE", eventClass);
108
109 return PLDM_ERROR;
110 }
111
triggerNumericSensorThresholdEvent(NumericSensorThresholdHandler handler,uint8_t previousEventState,uint8_t nextEventState,double value)112 int triggerNumericSensorThresholdEvent(NumericSensorThresholdHandler handler,
113 uint8_t previousEventState,
114 uint8_t nextEventState, double value)
115 {
116 static const std::map<
117 uint8_t, std::tuple<pldm::utils::Level, pldm::utils::Direction>>
118 sensorEventMap = {
119 {PLDM_SENSOR_UPPERFATAL,
120 {pldm::utils::Level::HARDSHUTDOWN, pldm::utils::Direction::HIGH}},
121 {PLDM_SENSOR_UPPERCRITICAL,
122 {pldm::utils::Level::CRITICAL, pldm::utils::Direction::HIGH}},
123 {PLDM_SENSOR_UPPERWARNING,
124 {pldm::utils::Level::WARNING, pldm::utils::Direction::HIGH}},
125 {PLDM_SENSOR_LOWERWARNING,
126 {pldm::utils::Level::WARNING, pldm::utils::Direction::LOW}},
127 {PLDM_SENSOR_LOWERCRITICAL,
128 {pldm::utils::Level::CRITICAL, pldm::utils::Direction::LOW}},
129 {PLDM_SENSOR_LOWERFATAL,
130 {pldm::utils::Level::HARDSHUTDOWN, pldm::utils::Direction::LOW}},
131 };
132 static const std::array<uint8_t, 7> stateOrder = {
133 PLDM_SENSOR_LOWERFATAL, PLDM_SENSOR_LOWERCRITICAL,
134 PLDM_SENSOR_LOWERWARNING, PLDM_SENSOR_NORMAL,
135 PLDM_SENSOR_UPPERWARNING, PLDM_SENSOR_UPPERCRITICAL,
136 PLDM_SENSOR_UPPERFATAL};
137 constexpr auto normalIt = stateOrder.begin() + 3;
138 const auto normalState = *normalIt;
139 auto prevIt =
140 std::find(stateOrder.begin(), stateOrder.end(), previousEventState);
141 if (prevIt == stateOrder.end())
142 {
143 lg2::error("Undefined previous threshold event state: {EVENT}", "EVENT",
144 previousEventState);
145 return PLDM_ERROR;
146 }
147 auto nextIt =
148 std::find(stateOrder.begin(), stateOrder.end(), nextEventState);
149 if (nextIt == stateOrder.end())
150 {
151 lg2::error("Undefined current threshold event state: {EVENT}", "EVENT",
152 nextEventState);
153 return PLDM_ERROR;
154 }
155 if (prevIt == nextIt)
156 {
157 // Nothing to do. Return success early
158 return PLDM_SUCCESS;
159 }
160
161 // This is a rare condition. But if we are going wildy across the thresholds
162 // crossing PLDM_SENSOR_NORMAL (Example going from PLDM_SENSOR_LOWERFATAL to
163 // PLDM_SENSOR_UPPERFATAL in one event, then split it up into two)
164 if ((prevIt < normalIt && nextIt > normalIt) ||
165 (prevIt > normalIt && nextIt < normalIt))
166 {
167 int rc = triggerNumericSensorThresholdEvent(handler, *prevIt,
168 normalState, value);
169 if (rc != PLDM_SUCCESS)
170 {
171 lg2::error("Error handling {PREV} to current for numeric sensor",
172 "PREV", int(*prevIt));
173 return rc;
174 }
175 return triggerNumericSensorThresholdEvent(handler, normalState, *nextIt,
176 value);
177 }
178 bool goingUp = prevIt < nextIt;
179 bool gettingBetter = (prevIt < nextIt && prevIt < normalIt) ||
180 (prevIt > nextIt && prevIt > normalIt);
181
182 for (auto currIt = prevIt; currIt != nextIt; goingUp ? ++currIt : --currIt)
183 {
184 if (currIt == normalIt)
185 {
186 continue;
187 }
188 const auto& event = sensorEventMap.at(*currIt);
189
190 if (gettingBetter)
191 {
192 if (currIt != prevIt)
193 {
194 // Just trigger an event in case it was missed before
195 // we deassert. The implementation of triggerThresholdEvent
196 // should just no-op if it is already triggered.
197 handler(std::get<0>(event), std::get<1>(event), value, true,
198 true);
199 }
200 handler(std::get<0>(event), std::get<1>(event), value, false,
201 false);
202 }
203 else
204 {
205 handler(std::get<0>(event), std::get<1>(event), value, true, true);
206 }
207 }
208 if (nextIt != normalIt)
209 {
210 const auto& event = sensorEventMap.at(*nextIt);
211 return handler(std::get<0>(event), std::get<1>(event), value, true,
212 true);
213 }
214 return PLDM_SUCCESS;
215 }
216
processNumericSensorEvent(pldm_tid_t tid,uint16_t sensorId,const uint8_t * sensorData,size_t sensorDataLength)217 int EventManager::processNumericSensorEvent(pldm_tid_t tid, uint16_t sensorId,
218 const uint8_t* sensorData,
219 size_t sensorDataLength)
220 {
221 uint8_t eventState = 0;
222 uint8_t previousEventState = 0;
223 uint8_t sensorDataSize = 0;
224 uint32_t presentReading;
225 auto rc = decode_numeric_sensor_data(
226 sensorData, sensorDataLength, &eventState, &previousEventState,
227 &sensorDataSize, &presentReading);
228 if (rc)
229 {
230 lg2::error(
231 "Failed to decode numericSensorState event for terminus ID {TID}, error {RC} ",
232 "TID", tid, "RC", rc);
233 return rc;
234 }
235
236 double value = static_cast<double>(presentReading);
237 lg2::error(
238 "processNumericSensorEvent tid {TID}, sensorID {SID} value {VAL} previousState {PSTATE} eventState {ESTATE}",
239 "TID", tid, "SID", sensorId, "VAL", value, "PSTATE", previousEventState,
240 "ESTATE", eventState);
241
242 if (!termini.contains(tid) || !termini[tid])
243 {
244 lg2::error("Terminus ID {TID} is not in the managing list.", "TID",
245 tid);
246 return PLDM_ERROR;
247 }
248
249 auto& terminus = termini[tid];
250
251 auto sensor = terminus->getSensorObject(sensorId);
252 if (!sensor)
253 {
254 lg2::error(
255 "Terminus ID {TID} has no sensor object with sensor ID {SID}.",
256 "TID", tid, "SID", sensorId);
257 return PLDM_ERROR;
258 }
259 auto sensorHandler =
260 [&sensor](pldm::utils::Level level, pldm::utils::Direction direction,
261 double rawValue, bool newAlarm, bool assert) {
262 return sensor->triggerThresholdEvent(level, direction, rawValue,
263 newAlarm, assert);
264 };
265 rc = triggerNumericSensorThresholdEvent(sensorHandler, previousEventState,
266 eventState, value);
267 if (rc)
268 {
269 lg2::error(
270 "Terminus ID {TID} sensor {SID} threshold handling had errors",
271 "TID", tid, "SID", sensorId);
272 return rc;
273 }
274 return PLDM_SUCCESS;
275 }
276
processCperEvent(pldm_tid_t tid,uint16_t eventId,const uint8_t * eventData,const size_t eventDataSize)277 int EventManager::processCperEvent(pldm_tid_t tid, uint16_t eventId,
278 const uint8_t* eventData,
279 const size_t eventDataSize)
280 {
281 if (eventDataSize < PLDM_PLATFORM_CPER_EVENT_MIN_LENGTH)
282 {
283 lg2::error(
284 "Error : Invalid CPER Event data length for eventId {EVENTID}.",
285 "EVENTID", eventId);
286 return PLDM_ERROR;
287 }
288 const size_t cperEventDataSize =
289 eventDataSize - PLDM_PLATFORM_CPER_EVENT_MIN_LENGTH;
290 const size_t msgDataLen =
291 sizeof(pldm_platform_cper_event) + cperEventDataSize;
292 std::string terminusName = "";
293 auto msgData = std::make_unique<unsigned char[]>(msgDataLen);
294 auto cperEvent = new (msgData.get()) pldm_platform_cper_event;
295
296 auto rc = decode_pldm_platform_cper_event(eventData, eventDataSize,
297 cperEvent, msgDataLen);
298
299 if (rc)
300 {
301 lg2::error(
302 "Failed to decode CPER event for eventId {EVENTID} of terminus ID {TID} error {RC}.",
303 "EVENTID", eventId, "TID", tid, "RC", rc);
304 return rc;
305 }
306
307 if (termini.contains(tid) && termini[tid])
308 {
309 auto tmp = termini[tid]->getTerminusName();
310 if (tmp && !tmp.value().empty())
311 {
312 terminusName = static_cast<std::string>(tmp.value());
313 }
314 }
315 else
316 {
317 lg2::error("Terminus ID {TID} is not in the managing list.", "TID",
318 tid);
319 return PLDM_ERROR;
320 }
321
322 // Save event data to file
323 std::filesystem::path dirName{"/var/cper"};
324 if (!std::filesystem::exists(dirName))
325 {
326 try
327 {
328 std::filesystem::create_directory(dirName);
329 }
330 catch (const std::filesystem::filesystem_error& e)
331 {
332 lg2::error("Failed to create /var/cper directory: {ERROR}", "ERROR",
333 e);
334 return PLDM_ERROR;
335 }
336 }
337
338 std::string fileName{dirName.string() + "/cper-XXXXXX"};
339 auto fd = mkstemp(fileName.data());
340 if (fd < 0)
341 {
342 lg2::error("Failed to generate temp file, error {ERRORNO}", "ERRORNO",
343 std::strerror(errno));
344 return PLDM_ERROR;
345 }
346 close(fd);
347
348 std::ofstream ofs;
349 ofs.exceptions(std::ofstream::failbit | std::ofstream::badbit |
350 std::ofstream::eofbit);
351
352 try
353 {
354 ofs.open(fileName);
355 ofs.write(reinterpret_cast<const char*>(
356 pldm_platform_cper_event_event_data(cperEvent)),
357 cperEvent->event_data_length);
358 if (cperEvent->format_type == PLDM_PLATFORM_CPER_EVENT_WITH_HEADER)
359 {
360 rc = createCperDumpEntry("CPER", fileName, terminusName);
361 }
362 else
363 {
364 rc = createCperDumpEntry("CPERSection", fileName, terminusName);
365 }
366 ofs.close();
367 }
368 catch (const std::ofstream::failure& e)
369 {
370 lg2::error("Failed to save CPER to '{FILENAME}', error - {ERROR}.",
371 "FILENAME", fileName, "ERROR", e);
372 return PLDM_ERROR;
373 }
374 return rc;
375 }
376
createCperDumpEntry(const std::string & dataType,const std::string & dataPath,const std::string & typeName)377 int EventManager::createCperDumpEntry(const std::string& dataType,
378 const std::string& dataPath,
379 const std::string& typeName)
380 {
381 auto createDump =
382 [](std::map<std::string, std::variant<std::string, uint64_t>>&
383 addData) {
384 static constexpr auto dumpObjPath =
385 "/xyz/openbmc_project/dump/faultlog";
386 auto& bus = pldm::utils::DBusHandler::getBus();
387
388 try
389 {
390 auto service = pldm::utils::DBusHandler().getService(
391 dumpObjPath, DumpCreate::interface);
392 auto method = bus.new_method_call(
393 service.c_str(), dumpObjPath, DumpCreate::interface,
394 DumpCreate::method_names::create_dump);
395 method.append(addData);
396 bus.call_noreply(method);
397 }
398 catch (const std::exception& e)
399 {
400 lg2::error(
401 "Failed to create D-Bus Dump entry, error - {ERROR}.",
402 "ERROR", e);
403 }
404 };
405
406 std::map<std::string, std::variant<std::string, uint64_t>> addData;
407 addData["Type"] = dataType;
408 addData["PrimaryLogId"] = dataPath;
409 addData["AdditionalTypeName"] = typeName;
410 createDump(addData);
411 return PLDM_SUCCESS;
412 }
413
getNextPartParameters(uint16_t eventId,std::vector<uint8_t> eventMessage,uint8_t transferFlag,uint32_t eventDataIntegrityChecksum,uint32_t nextDataTransferHandle,uint8_t * transferOperationFlag,uint32_t * dataTransferHandle,uint32_t * eventIdToAcknowledge)414 int EventManager::getNextPartParameters(
415 uint16_t eventId, std::vector<uint8_t> eventMessage, uint8_t transferFlag,
416 uint32_t eventDataIntegrityChecksum, uint32_t nextDataTransferHandle,
417 uint8_t* transferOperationFlag, uint32_t* dataTransferHandle,
418 uint32_t* eventIdToAcknowledge)
419 {
420 if (transferFlag != PLDM_PLATFORM_TRANSFER_START_AND_END &&
421 transferFlag != PLDM_PLATFORM_TRANSFER_END)
422 {
423 *transferOperationFlag = PLDM_GET_NEXTPART;
424 *dataTransferHandle = nextDataTransferHandle;
425 *eventIdToAcknowledge = PLDM_PLATFORM_EVENT_ID_FRAGMENT;
426 return PLDM_SUCCESS;
427 }
428
429 if (transferFlag == PLDM_PLATFORM_TRANSFER_END)
430 {
431 if (eventDataIntegrityChecksum !=
432 pldm_edac_crc32(eventMessage.data(), eventMessage.size()))
433 {
434 lg2::error("pollForPlatformEventMessage invalid checksum.");
435 return PLDM_ERROR_INVALID_DATA;
436 }
437 }
438
439 /* End of one event. Set request transfer flag to ACK */
440 *transferOperationFlag = PLDM_ACKNOWLEDGEMENT_ONLY;
441 *dataTransferHandle = 0;
442 *eventIdToAcknowledge = eventId;
443
444 return PLDM_SUCCESS;
445 }
446
callPolledEventHandlers(pldm_tid_t tid,uint8_t eventClass,uint16_t eventId,std::vector<uint8_t> & eventMessage)447 void EventManager::callPolledEventHandlers(pldm_tid_t tid, uint8_t eventClass,
448 uint16_t eventId,
449 std::vector<uint8_t>& eventMessage)
450 {
451 try
452 {
453 const auto& handlers = eventHandlers.at(eventClass);
454 for (const auto& handler : handlers)
455 {
456 auto rc =
457 handler(tid, eventId, eventMessage.data(), eventMessage.size());
458 if (rc != PLDM_SUCCESS)
459 {
460 lg2::error(
461 "Failed to handle platform event msg for terminus {TID}, event {EVENTID} return {RET}",
462 "TID", tid, "EVENTID", eventId, "RET", rc);
463 }
464 }
465 }
466 catch (const std::out_of_range& e)
467 {
468 lg2::error(
469 "Failed to handle platform event msg for terminus {TID}, event {EVENTID} error - {ERROR}",
470 "TID", tid, "EVENTID", eventId, "ERROR", e);
471 }
472 }
473
pollForPlatformEventTask(pldm_tid_t tid,uint32_t pollDataTransferHandle)474 exec::task<int> EventManager::pollForPlatformEventTask(
475 pldm_tid_t tid, uint32_t pollDataTransferHandle)
476 {
477 uint8_t rc = 0;
478 // Set once, doesn't need resetting
479 uint8_t transferOperationFlag = PLDM_GET_FIRSTPART;
480 uint32_t dataTransferHandle = pollDataTransferHandle;
481 uint32_t eventIdToAcknowledge = PLDM_PLATFORM_EVENT_ID_NULL;
482 uint8_t formatVersion = 0x1; // Constant, no need to reset
483 uint16_t eventId = PLDM_PLATFORM_EVENT_ID_ACK;
484 uint16_t polledEventId = PLDM_PLATFORM_EVENT_ID_NONE;
485 pldm_tid_t polledEventTid = 0;
486 uint8_t polledEventClass = 0;
487
488 std::vector<uint8_t> eventMessage{};
489
490 // Reset and mark terminus as available
491 updateAvailableState(tid, true);
492
493 while (eventId != PLDM_PLATFORM_EVENT_ID_NONE)
494 {
495 uint8_t completionCode = 0;
496 pldm_tid_t eventTid = PLDM_PLATFORM_EVENT_ID_NONE;
497 eventId = PLDM_PLATFORM_EVENT_ID_NONE;
498 uint32_t nextDataTransferHandle = 0;
499 uint8_t transferFlag = 0;
500 uint8_t eventClass = 0;
501 uint32_t eventDataSize = 0;
502 uint8_t* eventData = nullptr;
503 uint32_t eventDataIntegrityChecksum = 0;
504
505 /* Stop event polling */
506 if (!getAvailableState(tid))
507 {
508 lg2::info(
509 "Terminus ID {TID} is not available for PLDM request from {NOW}.",
510 "TID", tid, "NOW", pldm::utils::getCurrentSystemTime());
511 co_await stdexec::just_stopped();
512 }
513
514 rc = co_await pollForPlatformEventMessage(
515 tid, formatVersion, transferOperationFlag, dataTransferHandle,
516 eventIdToAcknowledge, completionCode, eventTid, eventId,
517 nextDataTransferHandle, transferFlag, eventClass, eventDataSize,
518 eventData, eventDataIntegrityChecksum);
519 if (rc || completionCode != PLDM_SUCCESS)
520 {
521 lg2::error(
522 "Failed to pollForPlatformEventMessage for terminus {TID}, event {EVENTID}, error {RC}, complete code {CC}",
523 "TID", tid, "EVENTID", eventId, "RC", rc, "CC", completionCode);
524 co_return rc;
525 }
526
527 if (eventDataSize > 0)
528 {
529 eventMessage.insert(eventMessage.end(), eventData,
530 eventData + eventDataSize);
531 }
532
533 if (transferOperationFlag == PLDM_ACKNOWLEDGEMENT_ONLY)
534 {
535 /* Handle the polled event after finish ACK it */
536 if (eventHandlers.contains(polledEventClass))
537 {
538 callPolledEventHandlers(polledEventTid, polledEventClass,
539 polledEventId, eventMessage);
540 }
541 eventMessage.clear();
542
543 if (eventId == PLDM_PLATFORM_EVENT_ID_ACK)
544 {
545 transferOperationFlag = PLDM_GET_FIRSTPART;
546 dataTransferHandle = 0;
547 eventIdToAcknowledge = PLDM_PLATFORM_EVENT_ID_NULL;
548 }
549 }
550 else
551 {
552 auto ret = getNextPartParameters(
553 eventId, eventMessage, transferFlag, eventDataIntegrityChecksum,
554 nextDataTransferHandle, &transferOperationFlag,
555 &dataTransferHandle, &eventIdToAcknowledge);
556 if (ret)
557 {
558 lg2::error(
559 "Failed to process data of pollForPlatformEventMessage for terminus {TID}, event {EVENTID} return {RET}",
560 "TID", tid, "EVENTID", eventId, "RET", ret);
561 co_return PLDM_ERROR_INVALID_DATA;
562 }
563
564 /* Store the polled event INFO to handle after ACK */
565 if ((transferFlag == PLDM_PLATFORM_TRANSFER_START_AND_END) ||
566 (transferFlag == PLDM_PLATFORM_TRANSFER_END))
567 {
568 polledEventTid = eventTid;
569 polledEventId = eventId;
570 polledEventClass = eventClass;
571 }
572 }
573 }
574
575 co_return PLDM_SUCCESS;
576 }
577
pollForPlatformEventMessage(pldm_tid_t tid,uint8_t formatVersion,uint8_t transferOperationFlag,uint32_t dataTransferHandle,uint16_t eventIdToAcknowledge,uint8_t & completionCode,uint8_t & eventTid,uint16_t & eventId,uint32_t & nextDataTransferHandle,uint8_t & transferFlag,uint8_t & eventClass,uint32_t & eventDataSize,uint8_t * & eventData,uint32_t & eventDataIntegrityChecksum)578 exec::task<int> EventManager::pollForPlatformEventMessage(
579 pldm_tid_t tid, uint8_t formatVersion, uint8_t transferOperationFlag,
580 uint32_t dataTransferHandle, uint16_t eventIdToAcknowledge,
581 uint8_t& completionCode, uint8_t& eventTid, uint16_t& eventId,
582 uint32_t& nextDataTransferHandle, uint8_t& transferFlag,
583 uint8_t& eventClass, uint32_t& eventDataSize, uint8_t*& eventData,
584 uint32_t& eventDataIntegrityChecksum)
585 {
586 Request request(
587 sizeof(pldm_msg_hdr) + PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_REQ_BYTES);
588 auto requestMsg = new (request.data()) pldm_msg;
589 auto rc = encode_poll_for_platform_event_message_req(
590 0, formatVersion, transferOperationFlag, dataTransferHandle,
591 eventIdToAcknowledge, requestMsg, request.size());
592 if (rc)
593 {
594 lg2::error(
595 "Failed to encode request PollForPlatformEventMessage for terminus ID {TID}, error {RC} ",
596 "TID", tid, "RC", rc);
597 co_return rc;
598 }
599
600 /* Stop event polling */
601 if (!getAvailableState(tid))
602 {
603 lg2::info(
604 "Terminus ID {TID} is not available for PLDM request from {NOW}.",
605 "TID", tid, "NOW", pldm::utils::getCurrentSystemTime());
606 co_await stdexec::just_stopped();
607 }
608
609 const pldm_msg* responseMsg = nullptr;
610 size_t responseLen = 0;
611 rc = co_await terminusManager.sendRecvPldmMsg(tid, request, &responseMsg,
612 &responseLen);
613 if (rc)
614 {
615 lg2::error(
616 "Failed to send PollForPlatformEventMessage message for terminus {TID}, error {RC}",
617 "TID", tid, "RC", rc);
618 co_return rc;
619 }
620
621 rc = decode_poll_for_platform_event_message_resp(
622 responseMsg, responseLen, &completionCode, &eventTid, &eventId,
623 &nextDataTransferHandle, &transferFlag, &eventClass, &eventDataSize,
624 (void**)&eventData, &eventDataIntegrityChecksum);
625 if (rc)
626 {
627 lg2::error(
628 "Failed to decode response PollForPlatformEventMessage for terminus ID {TID}, error {RC} ",
629 "TID", tid, "RC", rc);
630 co_return rc;
631 }
632 if (completionCode != PLDM_SUCCESS)
633 {
634 lg2::error(
635 "Error : PollForPlatformEventMessage for terminus ID {TID}, complete code {CC}.",
636 "TID", tid, "CC", completionCode);
637 co_return rc;
638 }
639
640 co_return completionCode;
641 }
642
643 } // namespace platform_mc
644 } // namespace pldm
645