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