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