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                     // Delete all the remote terminus information
91                     for (const auto& terminusInfo : this->tlPDRInfo)
92                     {
93                         if (terminusInfo.first != TERMINUS_HANDLE)
94                         {
95                             this->tlPDRInfo.erase(terminusInfo.first);
96                         }
97                     }
98 
99                     pldm_pdr_remove_remote_pdrs(repo);
100                     pldm_entity_association_tree_destroy_root(entityTree);
101                     pldm_entity_association_tree_copy_root(bmcEntityTree,
102                                                            entityTree);
103                     this->sensorMap.clear();
104                     this->responseReceived = false;
105                 }
106             }
107         });
108 }
109 
110 void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
111 {
112     pdrRecordHandles.clear();
113     pdrRecordHandles = std::move(recordHandles);
114 
115     // Defer the actual fetch of PDRs from the host (by queuing the call on the
116     // main event loop). That way, we can respond to the platform event msg from
117     // the host firmware.
118     pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
119         event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
120                          std::placeholders::_1));
121 }
122 
123 void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
124 {
125     getHostPDR();
126 }
127 
128 void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
129 {
130     pdrFetchEvent.reset();
131 
132     std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
133                                     PLDM_GET_PDR_REQ_BYTES);
134     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
135     uint32_t recordHandle{};
136     if (!nextRecordHandle)
137     {
138         if (!pdrRecordHandles.empty())
139         {
140             recordHandle = pdrRecordHandles.front();
141             pdrRecordHandles.pop_front();
142         }
143     }
144     else
145     {
146         recordHandle = nextRecordHandle;
147     }
148     auto instanceId = requester.getInstanceId(mctp_eid);
149 
150     auto rc =
151         encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
152                            UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
153     if (rc != PLDM_SUCCESS)
154     {
155         requester.markFree(mctp_eid, instanceId);
156         std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl;
157         return;
158     }
159 
160     rc = handler->registerRequest(
161         mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
162         std::move(requestMsg),
163         std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
164     if (rc)
165     {
166         std::cerr << "Failed to send the GetPDR request to Host \n";
167     }
168 }
169 
170 int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
171                                            pdr::EventState state)
172 {
173     auto rc = stateSensorHandler.eventAction(entry, state);
174     if (rc != PLDM_SUCCESS)
175     {
176         std::cerr << "Failed to fetch and update D-bus property, rc = " << rc
177                   << std::endl;
178         return rc;
179     }
180     return PLDM_SUCCESS;
181 }
182 bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent)
183 {
184     auto found = parents.find(type);
185     if (found != parents.end())
186     {
187         parent.entity_type = found->second.entity_type;
188         parent.entity_instance_num = found->second.entity_instance_num;
189         return true;
190     }
191 
192     return false;
193 }
194 
195 void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
196 {
197     size_t numEntities{};
198     pldm_entity* entities = nullptr;
199     bool merged = false;
200     auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
201         const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
202 
203     pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
204                                         &entities);
205     for (size_t i = 0; i < numEntities; ++i)
206     {
207         pldm_entity parent{};
208         if (getParent(entities[i].entity_type, parent))
209         {
210             auto node = pldm_entity_association_tree_find(entityTree, &parent);
211             if (node)
212             {
213                 pldm_entity_association_tree_add(entityTree, &entities[i],
214                                                  0xFFFF, node,
215                                                  entityPdr->association_type);
216                 merged = true;
217             }
218         }
219     }
220 
221     if (merged)
222     {
223         // Update our PDR repo with the merged entity association PDRs
224         pldm_entity_node* node = nullptr;
225         pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
226         if (node == nullptr)
227         {
228             std::cerr
229                 << "\ncould not find referrence of the entity in the tree \n";
230         }
231         else
232         {
233             pldm_entity_association_pdr_add_from_node(node, repo, &entities,
234                                                       numEntities, true);
235         }
236     }
237     free(entities);
238 }
239 
240 void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
241                                                uint8_t eventDataFormat)
242 {
243     assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
244 
245     // Extract from the PDR repo record handles of PDRs we want the host
246     // to pull up.
247     std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
248     std::vector<uint8_t> numsOfChangeEntries(1);
249     std::vector<std::vector<ChangeEntry>> changeEntries(
250         numsOfChangeEntries.size());
251     for (auto pdrType : pdrTypes)
252     {
253         const pldm_pdr_record* record{};
254         do
255         {
256             record = pldm_pdr_find_record_by_type(repo, pdrType, record,
257                                                   nullptr, nullptr);
258             if (record && pldm_pdr_record_is_remote(record))
259             {
260                 changeEntries[0].push_back(
261                     pldm_pdr_get_record_handle(repo, record));
262             }
263         } while (record);
264     }
265     if (changeEntries.empty())
266     {
267         return;
268     }
269     numsOfChangeEntries[0] = changeEntries[0].size();
270 
271     // Encode PLDM platform event msg to indicate a PDR repo change.
272     size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
273                      PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
274                      changeEntries[0].size() * sizeof(uint32_t);
275     std::vector<uint8_t> eventDataVec{};
276     eventDataVec.resize(maxSize);
277     auto eventData =
278         reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
279             eventDataVec.data());
280     size_t actualSize{};
281     auto firstEntry = changeEntries[0].data();
282     auto rc = encode_pldm_pdr_repository_chg_event_data(
283         eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
284         &firstEntry, eventData, &actualSize, maxSize);
285     if (rc != PLDM_SUCCESS)
286     {
287         std::cerr
288             << "Failed to encode_pldm_pdr_repository_chg_event_data, rc = "
289             << rc << std::endl;
290         return;
291     }
292     auto instanceId = requester.getInstanceId(mctp_eid);
293     std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
294                                     PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
295                                     actualSize);
296     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
297     rc = encode_platform_event_message_req(
298         instanceId, 1, 0, PLDM_PDR_REPOSITORY_CHG_EVENT, eventDataVec.data(),
299         actualSize, request,
300         actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
301     if (rc != PLDM_SUCCESS)
302     {
303         requester.markFree(mctp_eid, instanceId);
304         std::cerr << "Failed to encode_platform_event_message_req, rc = " << rc
305                   << std::endl;
306         return;
307     }
308 
309     auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/,
310                                                   const pldm_msg* response,
311                                                   size_t respMsgLen) {
312         if (response == nullptr || !respMsgLen)
313         {
314             std::cerr << "Failed to receive response for the PDR repository "
315                          "changed event"
316                       << "\n";
317             return;
318         }
319 
320         uint8_t completionCode{};
321         uint8_t status{};
322         auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
323         auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
324                                                      &completionCode, &status);
325         if (rc || completionCode)
326         {
327             std::cerr << "Failed to decode_platform_event_message_resp: "
328                       << "rc=" << rc
329                       << ", cc=" << static_cast<unsigned>(completionCode)
330                       << std::endl;
331         }
332     };
333 
334     rc = handler->registerRequest(
335         mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
336         std::move(requestMsg), std::move(platformEventMessageResponseHandler));
337     if (rc)
338     {
339         std::cerr << "Failed to send the PDR repository changed event request"
340                   << "\n";
341     }
342 }
343 
344 void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs)
345 {
346     for (const auto& pdr : stateSensorPDRs)
347     {
348         SensorEntry sensorEntry{};
349         const auto& [terminusHandle, sensorID, sensorInfo] =
350             responder::pdr_utils::parseStateSensorPDR(pdr);
351         sensorEntry.sensorID = sensorID;
352         try
353         {
354             sensorEntry.terminusID = std::get<0>(tlPDRInfo.at(terminusHandle));
355         }
356         // If there is no mapping for terminusHandle assign the reserved TID
357         // value of 0xFF to indicate that.
358         catch (const std::out_of_range& e)
359         {
360             sensorEntry.terminusID = PLDM_TID_RESERVED;
361         }
362         sensorMap.emplace(sensorEntry, std::move(sensorInfo));
363     }
364 }
365 
366 void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/,
367                                      const pldm_msg* response,
368                                      size_t respMsgLen)
369 {
370     static bool merged = false;
371     static PDRList stateSensorPDRs{};
372     uint32_t nextRecordHandle{};
373     uint8_t tlEid = 0;
374     bool tlValid = true;
375     uint32_t rh = 0;
376     uint16_t terminusHandle = 0;
377     uint8_t tid = 0;
378 
379     uint8_t completionCode{};
380     uint32_t nextDataTransferHandle{};
381     uint8_t transferFlag{};
382     uint16_t respCount{};
383     uint8_t transferCRC{};
384     if (response == nullptr || !respMsgLen)
385     {
386         std::cerr << "Failed to receive response for the GetPDR"
387                      " command \n";
388         return;
389     }
390 
391     auto rc = decode_get_pdr_resp(
392         response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode,
393         &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount,
394         nullptr, 0, &transferCRC);
395     std::vector<uint8_t> responsePDRMsg;
396     responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr));
397     memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr));
398     if (rc != PLDM_SUCCESS)
399     {
400         std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc << std::endl;
401         return;
402     }
403     else
404     {
405         std::vector<uint8_t> pdr(respCount, 0);
406         rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
407                                  &nextRecordHandle, &nextDataTransferHandle,
408                                  &transferFlag, &respCount, pdr.data(),
409                                  respCount, &transferCRC);
410         if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
411         {
412             std::cerr << "Failed to decode_get_pdr_resp: "
413                       << "rc=" << rc
414                       << ", cc=" << static_cast<unsigned>(completionCode)
415                       << std::endl;
416             return;
417         }
418         else
419         {
420             // when nextRecordHandle is 0, we need the recordHandle of the last
421             // PDR and not 0-1.
422             if (!nextRecordHandle)
423             {
424                 rh = nextRecordHandle;
425             }
426             else
427             {
428                 rh = nextRecordHandle - 1;
429             }
430 
431             auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
432             if (!rh)
433             {
434                 rh = pdrHdr->record_handle;
435             }
436 
437             if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
438             {
439                 this->mergeEntityAssociations(pdr);
440                 merged = true;
441             }
442             else
443             {
444                 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
445                 {
446                     auto tlpdr =
447                         reinterpret_cast<const pldm_terminus_locator_pdr*>(
448                             pdr.data());
449 
450                     terminusHandle = tlpdr->terminus_handle;
451                     tid = tlpdr->tid;
452                     auto terminus_locator_type = tlpdr->terminus_locator_type;
453                     if (terminus_locator_type ==
454                         PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
455                     {
456                         auto locatorValue = reinterpret_cast<
457                             const pldm_terminus_locator_type_mctp_eid*>(
458                             tlpdr->terminus_locator_value);
459                         tlEid = static_cast<uint8_t>(locatorValue->eid);
460                     }
461                     if (tlpdr->validity == 0)
462                     {
463                         tlValid = false;
464                     }
465                     tlPDRInfo.insert_or_assign(
466                         tlpdr->terminus_handle,
467                         std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity));
468                 }
469                 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
470                 {
471                     stateSensorPDRs.emplace_back(pdr);
472                 }
473 
474                 // if the TLPDR is invalid update the repo accordingly
475                 if (!tlValid)
476                 {
477                     pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
478                                            tlValid);
479                 }
480                 else
481                 {
482                     pldm_pdr_add(repo, pdr.data(), respCount, rh, true);
483                 }
484             }
485         }
486     }
487     if (!nextRecordHandle)
488     {
489         /*received last record*/
490         this->parseStateSensorPDRs(stateSensorPDRs);
491         if (isHostUp())
492         {
493             this->setHostSensorState(stateSensorPDRs);
494         }
495         stateSensorPDRs.clear();
496         if (merged)
497         {
498             merged = false;
499             deferredPDRRepoChgEvent =
500                 std::make_unique<sdeventplus::source::Defer>(
501                     event,
502                     std::bind(
503                         std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
504                         this, std::placeholders::_1));
505         }
506     }
507     else
508     {
509         deferredFetchPDREvent = std::make_unique<sdeventplus::source::Defer>(
510             event,
511             std::bind(std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
512                       this, nextRecordHandle, std::placeholders::_1));
513     }
514 }
515 
516 void HostPDRHandler::_processPDRRepoChgEvent(
517     sdeventplus::source::EventBase& /*source */)
518 {
519     deferredPDRRepoChgEvent.reset();
520     this->sendPDRRepositoryChgEvent(
521         std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
522         FORMAT_IS_PDR_HANDLES);
523 }
524 
525 void HostPDRHandler::_processFetchPDREvent(
526     uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
527 {
528     deferredFetchPDREvent.reset();
529     if (!this->pdrRecordHandles.empty())
530     {
531         nextRecordHandle = this->pdrRecordHandles.front();
532         this->pdrRecordHandles.pop_front();
533     }
534     this->getHostPDR(nextRecordHandle);
535 }
536 
537 void HostPDRHandler::setHostFirmwareCondition()
538 {
539     responseReceived = false;
540     auto instanceId = requester.getInstanceId(mctp_eid);
541     std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
542                                     PLDM_GET_VERSION_REQ_BYTES);
543     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
544     auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
545                                      PLDM_BASE, request);
546     if (rc != PLDM_SUCCESS)
547     {
548         std::cerr << "GetPLDMVersion encode failure. PLDM error code = "
549                   << std::hex << std::showbase << rc << "\n";
550         requester.markFree(mctp_eid, instanceId);
551         return;
552     }
553 
554     auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
555                                         const pldm_msg* response,
556                                         size_t respMsgLen) {
557         if (response == nullptr || !respMsgLen)
558         {
559             std::cerr << "Failed to receive response for "
560                       << "getPLDMVersion command, Host seems to be off \n";
561             return;
562         }
563         std::cout << "Getting the response. PLDM RC = " << std::hex
564                   << std::showbase
565                   << static_cast<uint16_t>(response->payload[0]) << "\n";
566         this->responseReceived = true;
567         getHostPDR();
568     };
569     rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
570                                   PLDM_GET_PLDM_VERSION, std::move(requestMsg),
571                                   std::move(getPLDMVersionHandler));
572     if (rc)
573     {
574         std::cerr << "Failed to discover Host state. Assuming Host as off \n";
575     }
576 }
577 
578 bool HostPDRHandler::isHostUp()
579 {
580     return responseReceived;
581 }
582 
583 void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs)
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 (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
601         {
602             if (terminusHandle == pdr->terminus_handle)
603             {
604                 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
605                 {
606                     mctp_eid = std::get<1>(terminusInfo);
607                 }
608 
609                 bitfield8_t sensorRearm;
610                 sensorRearm.byte = 0;
611                 uint8_t tid = std::get<0>(terminusInfo);
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