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