1 #include "config.h" 2 3 #include "host_pdr_handler.hpp" 4 5 #include "libpldm/requester/pldm.h" 6 7 #include <assert.h> 8 9 #include <nlohmann/json.hpp> 10 #include <sdeventplus/clock.hpp> 11 #include <sdeventplus/exception.hpp> 12 #include <sdeventplus/source/io.hpp> 13 #include <sdeventplus/source/time.hpp> 14 15 #include <fstream> 16 17 namespace pldm 18 { 19 20 using namespace pldm::dbus_api; 21 using namespace pldm::responder::events; 22 using namespace pldm::utils; 23 using namespace sdbusplus::bus::match::rules; 24 using Json = nlohmann::json; 25 namespace fs = std::filesystem; 26 constexpr auto fruJson = "host_frus.json"; 27 const Json emptyJson{}; 28 const std::vector<Json> emptyJsonList{}; 29 30 template <typename T> 31 uint16_t extractTerminusHandle(std::vector<uint8_t>& pdr) 32 { 33 T* var = nullptr; 34 if (std::is_same<T, pldm_pdr_fru_record_set>::value) 35 { 36 var = (T*)(pdr.data() + sizeof(pldm_pdr_hdr)); 37 } 38 else 39 { 40 var = (T*)(pdr.data()); 41 } 42 if (var != nullptr) 43 { 44 return var->terminus_handle; 45 } 46 return TERMINUS_HANDLE; 47 } 48 49 HostPDRHandler::HostPDRHandler( 50 int mctp_fd, uint8_t mctp_eid, sdeventplus::Event& event, pldm_pdr* repo, 51 const std::string& eventsJsonsDir, pldm_entity_association_tree* entityTree, 52 pldm_entity_association_tree* bmcEntityTree, Requester& requester, 53 pldm::requester::Handler<pldm::requester::Request>* handler) : 54 mctp_fd(mctp_fd), 55 mctp_eid(mctp_eid), event(event), repo(repo), 56 stateSensorHandler(eventsJsonsDir), entityTree(entityTree), 57 bmcEntityTree(bmcEntityTree), requester(requester), handler(handler) 58 { 59 fs::path hostFruJson(fs::path(HOST_JSONS_DIR) / fruJson); 60 if (fs::exists(hostFruJson)) 61 { 62 // Note parent entities for entities sent down by the host firmware. 63 // This will enable a merge of entity associations. 64 try 65 { 66 std::ifstream jsonFile(hostFruJson); 67 auto data = Json::parse(jsonFile, nullptr, false); 68 if (data.is_discarded()) 69 { 70 std::cerr << "Parsing Host FRU json file failed" << std::endl; 71 } 72 else 73 { 74 auto entities = data.value("entities", emptyJsonList); 75 for (auto& entity : entities) 76 { 77 EntityType entityType = entity.value("entity_type", 0); 78 auto parent = entity.value("parent", emptyJson); 79 pldm_entity p{}; 80 p.entity_type = parent.value("entity_type", 0); 81 p.entity_instance_num = parent.value("entity_instance", 0); 82 parents.emplace(entityType, std::move(p)); 83 } 84 } 85 } 86 catch (const std::exception& e) 87 { 88 std::cerr << "Parsing Host FRU json file failed, exception = " 89 << e.what() << std::endl; 90 } 91 } 92 93 hostOffMatch = std::make_unique<sdbusplus::bus::match_t>( 94 pldm::utils::DBusHandler::getBus(), 95 propertiesChanged("/xyz/openbmc_project/state/host0", 96 "xyz.openbmc_project.State.Host"), 97 [this, repo, entityTree, bmcEntityTree](sdbusplus::message_t& msg) { 98 DbusChangedProps props{}; 99 std::string intf; 100 msg.read(intf, props); 101 const auto itr = props.find("CurrentHostState"); 102 if (itr != props.end()) 103 { 104 PropertyValue value = itr->second; 105 auto propVal = std::get<std::string>(value); 106 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off") 107 { 108 // Delete all the remote terminus information 109 std::erase_if(tlPDRInfo, [](const auto& item) { 110 auto const& [key, value] = item; 111 return key != TERMINUS_HANDLE; 112 }); 113 pldm_pdr_remove_remote_pdrs(repo); 114 pldm_entity_association_tree_destroy_root(entityTree); 115 pldm_entity_association_tree_copy_root(bmcEntityTree, 116 entityTree); 117 this->sensorMap.clear(); 118 this->responseReceived = false; 119 } 120 } 121 }); 122 } 123 124 void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles) 125 { 126 pdrRecordHandles.clear(); 127 pdrRecordHandles = std::move(recordHandles); 128 129 // Defer the actual fetch of PDRs from the host (by queuing the call on the 130 // main event loop). That way, we can respond to the platform event msg from 131 // the host firmware. 132 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>( 133 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this, 134 std::placeholders::_1)); 135 } 136 137 void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/) 138 { 139 getHostPDR(); 140 } 141 142 void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle) 143 { 144 pdrFetchEvent.reset(); 145 146 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 147 PLDM_GET_PDR_REQ_BYTES); 148 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 149 uint32_t recordHandle{}; 150 if (!nextRecordHandle) 151 { 152 if (!pdrRecordHandles.empty()) 153 { 154 recordHandle = pdrRecordHandles.front(); 155 pdrRecordHandles.pop_front(); 156 } 157 } 158 else 159 { 160 recordHandle = nextRecordHandle; 161 } 162 auto instanceId = requester.getInstanceId(mctp_eid); 163 164 auto rc = 165 encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART, 166 UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES); 167 if (rc != PLDM_SUCCESS) 168 { 169 requester.markFree(mctp_eid, instanceId); 170 std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl; 171 return; 172 } 173 174 rc = handler->registerRequest( 175 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR, 176 std::move(requestMsg), 177 std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this))); 178 if (rc) 179 { 180 std::cerr << "Failed to send the GetPDR request to Host \n"; 181 } 182 } 183 184 int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry, 185 pdr::EventState state) 186 { 187 auto rc = stateSensorHandler.eventAction(entry, state); 188 if (rc != PLDM_SUCCESS) 189 { 190 std::cerr << "Failed to fetch and update D-bus property, rc = " << rc 191 << std::endl; 192 return rc; 193 } 194 return PLDM_SUCCESS; 195 } 196 bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent) 197 { 198 auto found = parents.find(type); 199 if (found != parents.end()) 200 { 201 parent.entity_type = found->second.entity_type; 202 parent.entity_instance_num = found->second.entity_instance_num; 203 return true; 204 } 205 206 return false; 207 } 208 209 void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr) 210 { 211 size_t numEntities{}; 212 pldm_entity* entities = nullptr; 213 bool merged = false; 214 auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>( 215 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr)); 216 217 pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities, 218 &entities); 219 for (size_t i = 0; i < numEntities; ++i) 220 { 221 pldm_entity parent{}; 222 if (getParent(entities[i].entity_type, parent)) 223 { 224 auto node = pldm_entity_association_tree_find(entityTree, &parent); 225 if (node) 226 { 227 pldm_entity_association_tree_add(entityTree, &entities[i], 228 0xFFFF, node, 229 entityPdr->association_type); 230 merged = true; 231 } 232 } 233 } 234 235 if (merged) 236 { 237 // Update our PDR repo with the merged entity association PDRs 238 pldm_entity_node* node = nullptr; 239 pldm_find_entity_ref_in_tree(entityTree, entities[0], &node); 240 if (node == nullptr) 241 { 242 std::cerr 243 << "\ncould not find referrence of the entity in the tree \n"; 244 } 245 else 246 { 247 pldm_entity_association_pdr_add_from_node( 248 node, repo, &entities, numEntities, true, TERMINUS_HANDLE); 249 } 250 } 251 free(entities); 252 } 253 254 void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes, 255 uint8_t eventDataFormat) 256 { 257 assert(eventDataFormat == FORMAT_IS_PDR_HANDLES); 258 259 // Extract from the PDR repo record handles of PDRs we want the host 260 // to pull up. 261 std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED}; 262 std::vector<uint8_t> numsOfChangeEntries(1); 263 std::vector<std::vector<ChangeEntry>> changeEntries( 264 numsOfChangeEntries.size()); 265 for (auto pdrType : pdrTypes) 266 { 267 const pldm_pdr_record* record{}; 268 do 269 { 270 record = pldm_pdr_find_record_by_type(repo, pdrType, record, 271 nullptr, nullptr); 272 if (record && pldm_pdr_record_is_remote(record)) 273 { 274 changeEntries[0].push_back( 275 pldm_pdr_get_record_handle(repo, record)); 276 } 277 } while (record); 278 } 279 if (changeEntries.empty()) 280 { 281 return; 282 } 283 numsOfChangeEntries[0] = changeEntries[0].size(); 284 285 // Encode PLDM platform event msg to indicate a PDR repo change. 286 size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH + 287 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH + 288 changeEntries[0].size() * sizeof(uint32_t); 289 std::vector<uint8_t> eventDataVec{}; 290 eventDataVec.resize(maxSize); 291 auto eventData = 292 reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>( 293 eventDataVec.data()); 294 size_t actualSize{}; 295 auto firstEntry = changeEntries[0].data(); 296 auto rc = encode_pldm_pdr_repository_chg_event_data( 297 eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(), 298 &firstEntry, eventData, &actualSize, maxSize); 299 if (rc != PLDM_SUCCESS) 300 { 301 std::cerr 302 << "Failed to encode_pldm_pdr_repository_chg_event_data, rc = " 303 << rc << std::endl; 304 return; 305 } 306 auto instanceId = requester.getInstanceId(mctp_eid); 307 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 308 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES + 309 actualSize); 310 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 311 rc = encode_platform_event_message_req( 312 instanceId, 1, 0, PLDM_PDR_REPOSITORY_CHG_EVENT, eventDataVec.data(), 313 actualSize, request, 314 actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES); 315 if (rc != PLDM_SUCCESS) 316 { 317 requester.markFree(mctp_eid, instanceId); 318 std::cerr << "Failed to encode_platform_event_message_req, rc = " << rc 319 << std::endl; 320 return; 321 } 322 323 auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/, 324 const pldm_msg* response, 325 size_t respMsgLen) { 326 if (response == nullptr || !respMsgLen) 327 { 328 std::cerr << "Failed to receive response for the PDR repository " 329 "changed event" 330 << "\n"; 331 return; 332 } 333 334 uint8_t completionCode{}; 335 uint8_t status{}; 336 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response); 337 auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen, 338 &completionCode, &status); 339 if (rc || completionCode) 340 { 341 std::cerr << "Failed to decode_platform_event_message_resp: " 342 << "rc=" << rc 343 << ", cc=" << static_cast<unsigned>(completionCode) 344 << std::endl; 345 } 346 }; 347 348 rc = handler->registerRequest( 349 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE, 350 std::move(requestMsg), std::move(platformEventMessageResponseHandler)); 351 if (rc) 352 { 353 std::cerr << "Failed to send the PDR repository changed event request" 354 << "\n"; 355 } 356 } 357 358 void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs) 359 { 360 for (const auto& pdr : stateSensorPDRs) 361 { 362 SensorEntry sensorEntry{}; 363 const auto& [terminusHandle, sensorID, sensorInfo] = 364 responder::pdr_utils::parseStateSensorPDR(pdr); 365 sensorEntry.sensorID = sensorID; 366 try 367 { 368 sensorEntry.terminusID = std::get<0>(tlPDRInfo.at(terminusHandle)); 369 } 370 // If there is no mapping for terminusHandle assign the reserved TID 371 // value of 0xFF to indicate that. 372 catch (const std::out_of_range& e) 373 { 374 sensorEntry.terminusID = PLDM_TID_RESERVED; 375 } 376 sensorMap.emplace(sensorEntry, std::move(sensorInfo)); 377 } 378 } 379 380 void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/, 381 const pldm_msg* response, 382 size_t respMsgLen) 383 { 384 static bool merged = false; 385 static PDRList stateSensorPDRs{}; 386 uint32_t nextRecordHandle{}; 387 uint8_t tlEid = 0; 388 bool tlValid = true; 389 uint32_t rh = 0; 390 uint16_t terminusHandle = 0; 391 uint16_t pdrTerminusHandle = 0; 392 uint8_t tid = 0; 393 394 uint8_t completionCode{}; 395 uint32_t nextDataTransferHandle{}; 396 uint8_t transferFlag{}; 397 uint16_t respCount{}; 398 uint8_t transferCRC{}; 399 if (response == nullptr || !respMsgLen) 400 { 401 std::cerr << "Failed to receive response for the GetPDR" 402 " command \n"; 403 return; 404 } 405 406 auto rc = decode_get_pdr_resp( 407 response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode, 408 &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount, 409 nullptr, 0, &transferCRC); 410 std::vector<uint8_t> responsePDRMsg; 411 responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr)); 412 memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr)); 413 if (rc != PLDM_SUCCESS) 414 { 415 std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc << std::endl; 416 return; 417 } 418 else 419 { 420 std::vector<uint8_t> pdr(respCount, 0); 421 rc = decode_get_pdr_resp(response, respMsgLen, &completionCode, 422 &nextRecordHandle, &nextDataTransferHandle, 423 &transferFlag, &respCount, pdr.data(), 424 respCount, &transferCRC); 425 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 426 { 427 std::cerr << "Failed to decode_get_pdr_resp: " 428 << "rc=" << rc 429 << ", cc=" << static_cast<unsigned>(completionCode) 430 << std::endl; 431 return; 432 } 433 else 434 { 435 // when nextRecordHandle is 0, we need the recordHandle of the last 436 // PDR and not 0-1. 437 if (!nextRecordHandle) 438 { 439 rh = nextRecordHandle; 440 } 441 else 442 { 443 rh = nextRecordHandle - 1; 444 } 445 446 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data()); 447 if (!rh) 448 { 449 rh = pdrHdr->record_handle; 450 } 451 452 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION) 453 { 454 this->mergeEntityAssociations(pdr); 455 merged = true; 456 } 457 else 458 { 459 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR) 460 { 461 pdrTerminusHandle = 462 extractTerminusHandle<pldm_terminus_locator_pdr>(pdr); 463 auto tlpdr = 464 reinterpret_cast<const pldm_terminus_locator_pdr*>( 465 pdr.data()); 466 467 terminusHandle = tlpdr->terminus_handle; 468 tid = tlpdr->tid; 469 auto terminus_locator_type = tlpdr->terminus_locator_type; 470 if (terminus_locator_type == 471 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID) 472 { 473 auto locatorValue = reinterpret_cast< 474 const pldm_terminus_locator_type_mctp_eid*>( 475 tlpdr->terminus_locator_value); 476 tlEid = static_cast<uint8_t>(locatorValue->eid); 477 } 478 if (tlpdr->validity == 0) 479 { 480 tlValid = false; 481 } 482 tlPDRInfo.insert_or_assign( 483 tlpdr->terminus_handle, 484 std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity)); 485 } 486 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR) 487 { 488 pdrTerminusHandle = 489 extractTerminusHandle<pldm_state_sensor_pdr>(pdr); 490 stateSensorPDRs.emplace_back(pdr); 491 } 492 else if (pdrHdr->type == PLDM_PDR_FRU_RECORD_SET) 493 { 494 pdrTerminusHandle = 495 extractTerminusHandle<pldm_pdr_fru_record_set>(pdr); 496 } 497 else if (pdrHdr->type == PLDM_STATE_EFFECTER_PDR) 498 { 499 pdrTerminusHandle = 500 extractTerminusHandle<pldm_state_effecter_pdr>(pdr); 501 } 502 else if (pdrHdr->type == PLDM_NUMERIC_EFFECTER_PDR) 503 { 504 pdrTerminusHandle = 505 extractTerminusHandle<pldm_numeric_effecter_value_pdr>( 506 pdr); 507 } 508 // if the TLPDR is invalid update the repo accordingly 509 if (!tlValid) 510 { 511 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid, 512 tlValid); 513 } 514 else 515 { 516 pldm_pdr_add(repo, pdr.data(), respCount, rh, true, 517 pdrTerminusHandle); 518 } 519 } 520 } 521 } 522 if (!nextRecordHandle) 523 { 524 /*received last record*/ 525 this->parseStateSensorPDRs(stateSensorPDRs); 526 if (isHostUp()) 527 { 528 this->setHostSensorState(stateSensorPDRs); 529 } 530 stateSensorPDRs.clear(); 531 if (merged) 532 { 533 merged = false; 534 deferredPDRRepoChgEvent = 535 std::make_unique<sdeventplus::source::Defer>( 536 event, 537 std::bind( 538 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)), 539 this, std::placeholders::_1)); 540 } 541 } 542 else 543 { 544 deferredFetchPDREvent = std::make_unique<sdeventplus::source::Defer>( 545 event, 546 std::bind(std::mem_fn((&HostPDRHandler::_processFetchPDREvent)), 547 this, nextRecordHandle, std::placeholders::_1)); 548 } 549 } 550 551 void HostPDRHandler::_processPDRRepoChgEvent( 552 sdeventplus::source::EventBase& /*source */) 553 { 554 deferredPDRRepoChgEvent.reset(); 555 this->sendPDRRepositoryChgEvent( 556 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)), 557 FORMAT_IS_PDR_HANDLES); 558 } 559 560 void HostPDRHandler::_processFetchPDREvent( 561 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */) 562 { 563 deferredFetchPDREvent.reset(); 564 if (!this->pdrRecordHandles.empty()) 565 { 566 nextRecordHandle = this->pdrRecordHandles.front(); 567 this->pdrRecordHandles.pop_front(); 568 } 569 this->getHostPDR(nextRecordHandle); 570 } 571 572 void HostPDRHandler::setHostFirmwareCondition() 573 { 574 responseReceived = false; 575 auto instanceId = requester.getInstanceId(mctp_eid); 576 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 577 PLDM_GET_VERSION_REQ_BYTES); 578 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 579 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART, 580 PLDM_BASE, request); 581 if (rc != PLDM_SUCCESS) 582 { 583 std::cerr << "GetPLDMVersion encode failure. PLDM error code = " 584 << std::hex << std::showbase << rc << "\n"; 585 requester.markFree(mctp_eid, instanceId); 586 return; 587 } 588 589 auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/, 590 const pldm_msg* response, 591 size_t respMsgLen) { 592 if (response == nullptr || !respMsgLen) 593 { 594 std::cerr << "Failed to receive response for " 595 << "getPLDMVersion command, Host seems to be off \n"; 596 return; 597 } 598 std::cout << "Getting the response. PLDM RC = " << std::hex 599 << std::showbase 600 << static_cast<uint16_t>(response->payload[0]) << "\n"; 601 this->responseReceived = true; 602 getHostPDR(); 603 }; 604 rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE, 605 PLDM_GET_PLDM_VERSION, std::move(requestMsg), 606 std::move(getPLDMVersionHandler)); 607 if (rc) 608 { 609 std::cerr << "Failed to discover Host state. Assuming Host as off \n"; 610 } 611 } 612 613 bool HostPDRHandler::isHostUp() 614 { 615 return responseReceived; 616 } 617 618 void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs) 619 { 620 for (const auto& stateSensorPDR : stateSensorPDRs) 621 { 622 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>( 623 stateSensorPDR.data()); 624 625 if (!pdr) 626 { 627 std::cerr << "Failed to get State sensor PDR" << std::endl; 628 pldm::utils::reportError( 629 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 630 return; 631 } 632 633 uint16_t sensorId = pdr->sensor_id; 634 635 for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo) 636 { 637 if (terminusHandle == pdr->terminus_handle) 638 { 639 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID) 640 { 641 mctp_eid = std::get<1>(terminusInfo); 642 } 643 644 bitfield8_t sensorRearm; 645 sensorRearm.byte = 0; 646 uint8_t tid = std::get<0>(terminusInfo); 647 648 auto instanceId = requester.getInstanceId(mctp_eid); 649 std::vector<uint8_t> requestMsg( 650 sizeof(pldm_msg_hdr) + 651 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES); 652 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 653 auto rc = encode_get_state_sensor_readings_req( 654 instanceId, sensorId, sensorRearm, 0, request); 655 656 if (rc != PLDM_SUCCESS) 657 { 658 requester.markFree(mctp_eid, instanceId); 659 std::cerr << "Failed to " 660 "encode_get_state_sensor_readings_req, rc = " 661 << rc << std::endl; 662 pldm::utils::reportError( 663 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 664 return; 665 } 666 667 auto getStateSensorReadingRespHandler = [=, this]( 668 mctp_eid_t /*eid*/, 669 const pldm_msg* 670 response, 671 size_t respMsgLen) { 672 if (response == nullptr || !respMsgLen) 673 { 674 std::cerr << "Failed to receive response for " 675 "getStateSensorReading command \n"; 676 return; 677 } 678 std::array<get_sensor_state_field, 8> stateField{}; 679 uint8_t completionCode = 0; 680 uint8_t comp_sensor_count = 0; 681 682 auto rc = decode_get_state_sensor_readings_resp( 683 response, respMsgLen, &completionCode, 684 &comp_sensor_count, stateField.data()); 685 686 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 687 { 688 std::cerr 689 << "Failed to " 690 "decode_get_state_sensor_readings_resp, rc = " 691 << rc 692 << " cc=" << static_cast<unsigned>(completionCode) 693 << std::endl; 694 pldm::utils::reportError( 695 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 696 } 697 698 uint8_t eventState; 699 uint8_t previousEventState; 700 uint8_t sensorOffset = comp_sensor_count - 1; 701 702 for (size_t i = 0; i < comp_sensor_count; i++) 703 { 704 eventState = stateField[i].present_state; 705 previousEventState = stateField[i].previous_state; 706 707 emitStateSensorEventSignal(tid, sensorId, sensorOffset, 708 eventState, 709 previousEventState); 710 711 SensorEntry sensorEntry{tid, sensorId}; 712 713 pldm::pdr::EntityInfo entityInfo{}; 714 pldm::pdr::CompositeSensorStates 715 compositeSensorStates{}; 716 717 try 718 { 719 std::tie(entityInfo, compositeSensorStates) = 720 lookupSensorInfo(sensorEntry); 721 } 722 catch (const std::out_of_range& e) 723 { 724 try 725 { 726 sensorEntry.terminusID = PLDM_TID_RESERVED; 727 std::tie(entityInfo, compositeSensorStates) = 728 lookupSensorInfo(sensorEntry); 729 } 730 catch (const std::out_of_range& e) 731 { 732 std::cerr << "No mapping for the events" 733 << std::endl; 734 } 735 } 736 737 if (sensorOffset > compositeSensorStates.size()) 738 { 739 std::cerr 740 << " Error Invalid data, Invalid sensor offset" 741 << std::endl; 742 return; 743 } 744 745 const auto& possibleStates = 746 compositeSensorStates[sensorOffset]; 747 if (possibleStates.find(eventState) == 748 possibleStates.end()) 749 { 750 std::cerr 751 << " Error invalid_data, Invalid event state" 752 << std::endl; 753 return; 754 } 755 const auto& [containerId, entityType, entityInstance] = 756 entityInfo; 757 pldm::responder::events::StateSensorEntry 758 stateSensorEntry{containerId, entityType, 759 entityInstance, sensorOffset}; 760 handleStateSensorEvent(stateSensorEntry, eventState); 761 } 762 }; 763 764 rc = handler->registerRequest( 765 mctp_eid, instanceId, PLDM_PLATFORM, 766 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg), 767 std::move(getStateSensorReadingRespHandler)); 768 769 if (rc != PLDM_SUCCESS) 770 { 771 std::cerr << " Failed to send request to get State sensor " 772 "reading on Host " 773 << std::endl; 774 } 775 } 776 } 777 } 778 } 779 } // namespace pldm 780