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                     this->responseReceived = false;
96                 }
97             }
98         });
99 }
100 
101 void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
102 {
103     pdrRecordHandles.clear();
104     pdrRecordHandles = std::move(recordHandles);
105 
106     // Defer the actual fetch of PDRs from the host (by queuing the call on the
107     // main event loop). That way, we can respond to the platform event msg from
108     // the host firmware.
109     pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
110         event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
111                          std::placeholders::_1));
112 }
113 
114 void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
115 {
116     getHostPDR();
117 }
118 
119 void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
120 {
121     pdrFetchEvent.reset();
122 
123     std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
124                                     PLDM_GET_PDR_REQ_BYTES);
125     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
126     uint32_t recordHandle{};
127     if (!nextRecordHandle)
128     {
129         if (!pdrRecordHandles.empty())
130         {
131             recordHandle = pdrRecordHandles.front();
132             pdrRecordHandles.pop_front();
133         }
134     }
135     else
136     {
137         recordHandle = nextRecordHandle;
138     }
139     auto instanceId = requester.getInstanceId(mctp_eid);
140 
141     auto rc =
142         encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
143                            UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
144     if (rc != PLDM_SUCCESS)
145     {
146         requester.markFree(mctp_eid, instanceId);
147         std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl;
148         return;
149     }
150 
151     rc = handler->registerRequest(
152         mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
153         std::move(requestMsg),
154         std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
155     if (rc)
156     {
157         std::cerr << "Failed to send the GetPDR request to Host \n";
158     }
159 }
160 
161 int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
162                                            pdr::EventState state)
163 {
164     auto rc = stateSensorHandler.eventAction(entry, state);
165     if (rc != PLDM_SUCCESS)
166     {
167         std::cerr << "Failed to fetch and update D-bus property, rc = " << rc
168                   << std::endl;
169         return rc;
170     }
171     return PLDM_SUCCESS;
172 }
173 bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent)
174 {
175     auto found = parents.find(type);
176     if (found != parents.end())
177     {
178         parent.entity_type = found->second.entity_type;
179         parent.entity_instance_num = found->second.entity_instance_num;
180         return true;
181     }
182 
183     return false;
184 }
185 
186 void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
187 {
188     size_t numEntities{};
189     pldm_entity* entities = nullptr;
190     bool merged = false;
191     auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
192         const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
193 
194     pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
195                                         &entities);
196     for (size_t i = 0; i < numEntities; ++i)
197     {
198         pldm_entity parent{};
199         if (getParent(entities[i].entity_type, parent))
200         {
201             auto node = pldm_entity_association_tree_find(entityTree, &parent);
202             if (node)
203             {
204                 pldm_entity_association_tree_add(entityTree, &entities[i],
205                                                  0xFFFF, node,
206                                                  entityPdr->association_type);
207                 merged = true;
208             }
209         }
210     }
211 
212     if (merged)
213     {
214         // Update our PDR repo with the merged entity association PDRs
215         pldm_entity_node* node = nullptr;
216         pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
217         if (node == nullptr)
218         {
219             std::cerr
220                 << "\ncould not find referrence of the entity in the tree \n";
221         }
222         else
223         {
224             pldm_entity_association_pdr_add_from_node(node, repo, &entities,
225                                                       numEntities, true);
226         }
227     }
228     free(entities);
229 }
230 
231 void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
232                                                uint8_t eventDataFormat)
233 {
234     assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
235 
236     // Extract from the PDR repo record handles of PDRs we want the host
237     // to pull up.
238     std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
239     std::vector<uint8_t> numsOfChangeEntries(1);
240     std::vector<std::vector<ChangeEntry>> changeEntries(
241         numsOfChangeEntries.size());
242     for (auto pdrType : pdrTypes)
243     {
244         const pldm_pdr_record* record{};
245         do
246         {
247             record = pldm_pdr_find_record_by_type(repo, pdrType, record,
248                                                   nullptr, nullptr);
249             if (record && pldm_pdr_record_is_remote(record))
250             {
251                 changeEntries[0].push_back(
252                     pldm_pdr_get_record_handle(repo, record));
253             }
254         } while (record);
255     }
256     if (changeEntries.empty())
257     {
258         return;
259     }
260     numsOfChangeEntries[0] = changeEntries[0].size();
261 
262     // Encode PLDM platform event msg to indicate a PDR repo change.
263     size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
264                      PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
265                      changeEntries[0].size() * sizeof(uint32_t);
266     std::vector<uint8_t> eventDataVec{};
267     eventDataVec.resize(maxSize);
268     auto eventData =
269         reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
270             eventDataVec.data());
271     size_t actualSize{};
272     auto firstEntry = changeEntries[0].data();
273     auto rc = encode_pldm_pdr_repository_chg_event_data(
274         eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
275         &firstEntry, eventData, &actualSize, maxSize);
276     if (rc != PLDM_SUCCESS)
277     {
278         std::cerr
279             << "Failed to encode_pldm_pdr_repository_chg_event_data, rc = "
280             << rc << std::endl;
281         return;
282     }
283     auto instanceId = requester.getInstanceId(mctp_eid);
284     std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
285                                     PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
286                                     actualSize);
287     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
288     rc = encode_platform_event_message_req(
289         instanceId, 1, 0, PLDM_PDR_REPOSITORY_CHG_EVENT, eventDataVec.data(),
290         actualSize, request,
291         actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
292     if (rc != PLDM_SUCCESS)
293     {
294         requester.markFree(mctp_eid, instanceId);
295         std::cerr << "Failed to encode_platform_event_message_req, rc = " << rc
296                   << std::endl;
297         return;
298     }
299 
300     auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/,
301                                                   const pldm_msg* response,
302                                                   size_t respMsgLen) {
303         if (response == nullptr || !respMsgLen)
304         {
305             std::cerr << "Failed to receive response for the PDR repository "
306                          "changed event"
307                       << "\n";
308             return;
309         }
310 
311         uint8_t completionCode{};
312         uint8_t status{};
313         auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
314         auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
315                                                      &completionCode, &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