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