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