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 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 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 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 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 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 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 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