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