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                     std::erase_if(tlPDRInfo, [](const auto& item) {
92                         auto const& [key, value] = item;
93                         return key != TERMINUS_HANDLE;
94                     });
95                     pldm_pdr_remove_remote_pdrs(repo);
96                     pldm_entity_association_tree_destroy_root(entityTree);
97                     pldm_entity_association_tree_copy_root(bmcEntityTree,
98                                                            entityTree);
99                     this->sensorMap.clear();
100                     this->responseReceived = false;
101                 }
102             }
103         });
104 }
105 
106 void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
107 {
108     pdrRecordHandles.clear();
109     pdrRecordHandles = std::move(recordHandles);
110 
111     // Defer the actual fetch of PDRs from the host (by queuing the call on the
112     // main event loop). That way, we can respond to the platform event msg from
113     // the host firmware.
114     pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
115         event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
116                          std::placeholders::_1));
117 }
118 
119 void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
120 {
121     getHostPDR();
122 }
123 
124 void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
125 {
126     pdrFetchEvent.reset();
127 
128     std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
129                                     PLDM_GET_PDR_REQ_BYTES);
130     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
131     uint32_t recordHandle{};
132     if (!nextRecordHandle)
133     {
134         if (!pdrRecordHandles.empty())
135         {
136             recordHandle = pdrRecordHandles.front();
137             pdrRecordHandles.pop_front();
138         }
139     }
140     else
141     {
142         recordHandle = nextRecordHandle;
143     }
144     auto instanceId = requester.getInstanceId(mctp_eid);
145 
146     auto rc =
147         encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
148                            UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
149     if (rc != PLDM_SUCCESS)
150     {
151         requester.markFree(mctp_eid, instanceId);
152         std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl;
153         return;
154     }
155 
156     rc = handler->registerRequest(
157         mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
158         std::move(requestMsg),
159         std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
160     if (rc)
161     {
162         std::cerr << "Failed to send the GetPDR request to Host \n";
163     }
164 }
165 
166 int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
167                                            pdr::EventState state)
168 {
169     auto rc = stateSensorHandler.eventAction(entry, state);
170     if (rc != PLDM_SUCCESS)
171     {
172         std::cerr << "Failed to fetch and update D-bus property, rc = " << rc
173                   << std::endl;
174         return rc;
175     }
176     return PLDM_SUCCESS;
177 }
178 bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent)
179 {
180     auto found = parents.find(type);
181     if (found != parents.end())
182     {
183         parent.entity_type = found->second.entity_type;
184         parent.entity_instance_num = found->second.entity_instance_num;
185         return true;
186     }
187 
188     return false;
189 }
190 
191 void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
192 {
193     size_t numEntities{};
194     pldm_entity* entities = nullptr;
195     bool merged = false;
196     auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
197         const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
198 
199     pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
200                                         &entities);
201     for (size_t i = 0; i < numEntities; ++i)
202     {
203         pldm_entity parent{};
204         if (getParent(entities[i].entity_type, parent))
205         {
206             auto node = pldm_entity_association_tree_find(entityTree, &parent);
207             if (node)
208             {
209                 pldm_entity_association_tree_add(entityTree, &entities[i],
210                                                  0xFFFF, node,
211                                                  entityPdr->association_type);
212                 merged = true;
213             }
214         }
215     }
216 
217     if (merged)
218     {
219         // Update our PDR repo with the merged entity association PDRs
220         pldm_entity_node* node = nullptr;
221         pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
222         if (node == nullptr)
223         {
224             std::cerr
225                 << "\ncould not find referrence of the entity in the tree \n";
226         }
227         else
228         {
229             pldm_entity_association_pdr_add_from_node(node, repo, &entities,
230                                                       numEntities, true);
231         }
232     }
233     free(entities);
234 }
235 
236 void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
237                                                uint8_t eventDataFormat)
238 {
239     assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
240 
241     // Extract from the PDR repo record handles of PDRs we want the host
242     // to pull up.
243     std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
244     std::vector<uint8_t> numsOfChangeEntries(1);
245     std::vector<std::vector<ChangeEntry>> changeEntries(
246         numsOfChangeEntries.size());
247     for (auto pdrType : pdrTypes)
248     {
249         const pldm_pdr_record* record{};
250         do
251         {
252             record = pldm_pdr_find_record_by_type(repo, pdrType, record,
253                                                   nullptr, nullptr);
254             if (record && pldm_pdr_record_is_remote(record))
255             {
256                 changeEntries[0].push_back(
257                     pldm_pdr_get_record_handle(repo, record));
258             }
259         } while (record);
260     }
261     if (changeEntries.empty())
262     {
263         return;
264     }
265     numsOfChangeEntries[0] = changeEntries[0].size();
266 
267     // Encode PLDM platform event msg to indicate a PDR repo change.
268     size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
269                      PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
270                      changeEntries[0].size() * sizeof(uint32_t);
271     std::vector<uint8_t> eventDataVec{};
272     eventDataVec.resize(maxSize);
273     auto eventData =
274         reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
275             eventDataVec.data());
276     size_t actualSize{};
277     auto firstEntry = changeEntries[0].data();
278     auto rc = encode_pldm_pdr_repository_chg_event_data(
279         eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
280         &firstEntry, eventData, &actualSize, maxSize);
281     if (rc != PLDM_SUCCESS)
282     {
283         std::cerr
284             << "Failed to encode_pldm_pdr_repository_chg_event_data, rc = "
285             << rc << std::endl;
286         return;
287     }
288     auto instanceId = requester.getInstanceId(mctp_eid);
289     std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
290                                     PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
291                                     actualSize);
292     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
293     rc = encode_platform_event_message_req(
294         instanceId, 1, 0, PLDM_PDR_REPOSITORY_CHG_EVENT, eventDataVec.data(),
295         actualSize, request,
296         actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
297     if (rc != PLDM_SUCCESS)
298     {
299         requester.markFree(mctp_eid, instanceId);
300         std::cerr << "Failed to encode_platform_event_message_req, rc = " << rc
301                   << std::endl;
302         return;
303     }
304 
305     auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/,
306                                                   const pldm_msg* response,
307                                                   size_t respMsgLen) {
308         if (response == nullptr || !respMsgLen)
309         {
310             std::cerr << "Failed to receive response for the PDR repository "
311                          "changed event"
312                       << "\n";
313             return;
314         }
315 
316         uint8_t completionCode{};
317         uint8_t status{};
318         auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
319         auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
320                                                      &completionCode, &status);
321         if (rc || completionCode)
322         {
323             std::cerr << "Failed to decode_platform_event_message_resp: "
324                       << "rc=" << rc
325                       << ", cc=" << static_cast<unsigned>(completionCode)
326                       << std::endl;
327         }
328     };
329 
330     rc = handler->registerRequest(
331         mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
332         std::move(requestMsg), std::move(platformEventMessageResponseHandler));
333     if (rc)
334     {
335         std::cerr << "Failed to send the PDR repository changed event request"
336                   << "\n";
337     }
338 }
339 
340 void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs)
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 = std::get<0>(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     uint32_t nextRecordHandle{};
369     uint8_t tlEid = 0;
370     bool tlValid = true;
371     uint32_t rh = 0;
372     uint16_t terminusHandle = 0;
373     uint8_t tid = 0;
374 
375     uint8_t completionCode{};
376     uint32_t nextDataTransferHandle{};
377     uint8_t transferFlag{};
378     uint16_t respCount{};
379     uint8_t transferCRC{};
380     if (response == nullptr || !respMsgLen)
381     {
382         std::cerr << "Failed to receive response for the GetPDR"
383                      " command \n";
384         return;
385     }
386 
387     auto rc = decode_get_pdr_resp(
388         response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode,
389         &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount,
390         nullptr, 0, &transferCRC);
391     std::vector<uint8_t> responsePDRMsg;
392     responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr));
393     memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr));
394     if (rc != PLDM_SUCCESS)
395     {
396         std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc << std::endl;
397         return;
398     }
399     else
400     {
401         std::vector<uint8_t> pdr(respCount, 0);
402         rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
403                                  &nextRecordHandle, &nextDataTransferHandle,
404                                  &transferFlag, &respCount, pdr.data(),
405                                  respCount, &transferCRC);
406         if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
407         {
408             std::cerr << "Failed to decode_get_pdr_resp: "
409                       << "rc=" << rc
410                       << ", cc=" << static_cast<unsigned>(completionCode)
411                       << std::endl;
412             return;
413         }
414         else
415         {
416             // when nextRecordHandle is 0, we need the recordHandle of the last
417             // PDR and not 0-1.
418             if (!nextRecordHandle)
419             {
420                 rh = nextRecordHandle;
421             }
422             else
423             {
424                 rh = nextRecordHandle - 1;
425             }
426 
427             auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
428             if (!rh)
429             {
430                 rh = pdrHdr->record_handle;
431             }
432 
433             if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
434             {
435                 this->mergeEntityAssociations(pdr);
436                 merged = true;
437             }
438             else
439             {
440                 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
441                 {
442                     auto tlpdr =
443                         reinterpret_cast<const pldm_terminus_locator_pdr*>(
444                             pdr.data());
445 
446                     terminusHandle = tlpdr->terminus_handle;
447                     tid = tlpdr->tid;
448                     auto terminus_locator_type = tlpdr->terminus_locator_type;
449                     if (terminus_locator_type ==
450                         PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
451                     {
452                         auto locatorValue = reinterpret_cast<
453                             const pldm_terminus_locator_type_mctp_eid*>(
454                             tlpdr->terminus_locator_value);
455                         tlEid = static_cast<uint8_t>(locatorValue->eid);
456                     }
457                     if (tlpdr->validity == 0)
458                     {
459                         tlValid = false;
460                     }
461                     tlPDRInfo.insert_or_assign(
462                         tlpdr->terminus_handle,
463                         std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity));
464                 }
465                 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
466                 {
467                     stateSensorPDRs.emplace_back(pdr);
468                 }
469 
470                 // if the TLPDR is invalid update the repo accordingly
471                 if (!tlValid)
472                 {
473                     pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
474                                            tlValid);
475                 }
476                 else
477                 {
478                     pldm_pdr_add(repo, pdr.data(), respCount, rh, true);
479                 }
480             }
481         }
482     }
483     if (!nextRecordHandle)
484     {
485         /*received last record*/
486         this->parseStateSensorPDRs(stateSensorPDRs);
487         if (isHostUp())
488         {
489             this->setHostSensorState(stateSensorPDRs);
490         }
491         stateSensorPDRs.clear();
492         if (merged)
493         {
494             merged = false;
495             deferredPDRRepoChgEvent =
496                 std::make_unique<sdeventplus::source::Defer>(
497                     event,
498                     std::bind(
499                         std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
500                         this, std::placeholders::_1));
501         }
502     }
503     else
504     {
505         deferredFetchPDREvent = std::make_unique<sdeventplus::source::Defer>(
506             event,
507             std::bind(std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
508                       this, nextRecordHandle, std::placeholders::_1));
509     }
510 }
511 
512 void HostPDRHandler::_processPDRRepoChgEvent(
513     sdeventplus::source::EventBase& /*source */)
514 {
515     deferredPDRRepoChgEvent.reset();
516     this->sendPDRRepositoryChgEvent(
517         std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
518         FORMAT_IS_PDR_HANDLES);
519 }
520 
521 void HostPDRHandler::_processFetchPDREvent(
522     uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
523 {
524     deferredFetchPDREvent.reset();
525     if (!this->pdrRecordHandles.empty())
526     {
527         nextRecordHandle = this->pdrRecordHandles.front();
528         this->pdrRecordHandles.pop_front();
529     }
530     this->getHostPDR(nextRecordHandle);
531 }
532 
533 void HostPDRHandler::setHostFirmwareCondition()
534 {
535     responseReceived = false;
536     auto instanceId = requester.getInstanceId(mctp_eid);
537     std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
538                                     PLDM_GET_VERSION_REQ_BYTES);
539     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
540     auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
541                                      PLDM_BASE, request);
542     if (rc != PLDM_SUCCESS)
543     {
544         std::cerr << "GetPLDMVersion encode failure. PLDM error code = "
545                   << std::hex << std::showbase << rc << "\n";
546         requester.markFree(mctp_eid, instanceId);
547         return;
548     }
549 
550     auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
551                                         const pldm_msg* response,
552                                         size_t respMsgLen) {
553         if (response == nullptr || !respMsgLen)
554         {
555             std::cerr << "Failed to receive response for "
556                       << "getPLDMVersion command, Host seems to be off \n";
557             return;
558         }
559         std::cout << "Getting the response. PLDM RC = " << std::hex
560                   << std::showbase
561                   << static_cast<uint16_t>(response->payload[0]) << "\n";
562         this->responseReceived = true;
563         getHostPDR();
564     };
565     rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
566                                   PLDM_GET_PLDM_VERSION, std::move(requestMsg),
567                                   std::move(getPLDMVersionHandler));
568     if (rc)
569     {
570         std::cerr << "Failed to discover Host state. Assuming Host as off \n";
571     }
572 }
573 
574 bool HostPDRHandler::isHostUp()
575 {
576     return responseReceived;
577 }
578 
579 void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs)
580 {
581     for (const auto& stateSensorPDR : stateSensorPDRs)
582     {
583         auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
584             stateSensorPDR.data());
585 
586         if (!pdr)
587         {
588             std::cerr << "Failed to get State sensor PDR" << std::endl;
589             pldm::utils::reportError(
590                 "xyz.openbmc_project.bmc.pldm.InternalFailure");
591             return;
592         }
593 
594         uint16_t sensorId = pdr->sensor_id;
595 
596         for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
597         {
598             if (terminusHandle == pdr->terminus_handle)
599             {
600                 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
601                 {
602                     mctp_eid = std::get<1>(terminusInfo);
603                 }
604 
605                 bitfield8_t sensorRearm;
606                 sensorRearm.byte = 0;
607                 uint8_t tid = std::get<0>(terminusInfo);
608 
609                 auto instanceId = requester.getInstanceId(mctp_eid);
610                 std::vector<uint8_t> requestMsg(
611                     sizeof(pldm_msg_hdr) +
612                     PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
613                 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
614                 auto rc = encode_get_state_sensor_readings_req(
615                     instanceId, sensorId, sensorRearm, 0, request);
616 
617                 if (rc != PLDM_SUCCESS)
618                 {
619                     requester.markFree(mctp_eid, instanceId);
620                     std::cerr << "Failed to "
621                                  "encode_get_state_sensor_readings_req, rc = "
622                               << rc << std::endl;
623                     pldm::utils::reportError(
624                         "xyz.openbmc_project.bmc.pldm.InternalFailure");
625                     return;
626                 }
627 
628                 auto getStateSensorReadingRespHandler = [=, this](
629                                                             mctp_eid_t /*eid*/,
630                                                             const pldm_msg*
631                                                                 response,
632                                                             size_t respMsgLen) {
633                     if (response == nullptr || !respMsgLen)
634                     {
635                         std::cerr << "Failed to receive response for "
636                                      "getStateSensorReading command \n";
637                         return;
638                     }
639                     std::array<get_sensor_state_field, 8> stateField{};
640                     uint8_t completionCode = 0;
641                     uint8_t comp_sensor_count = 0;
642 
643                     auto rc = decode_get_state_sensor_readings_resp(
644                         response, respMsgLen, &completionCode,
645                         &comp_sensor_count, stateField.data());
646 
647                     if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
648                     {
649                         std::cerr
650                             << "Failed to "
651                                "decode_get_state_sensor_readings_resp, rc = "
652                             << rc
653                             << " cc=" << static_cast<unsigned>(completionCode)
654                             << std::endl;
655                         pldm::utils::reportError(
656                             "xyz.openbmc_project.bmc.pldm.InternalFailure");
657                     }
658 
659                     uint8_t eventState;
660                     uint8_t previousEventState;
661                     uint8_t sensorOffset = comp_sensor_count - 1;
662 
663                     for (size_t i = 0; i < comp_sensor_count; i++)
664                     {
665                         eventState = stateField[i].present_state;
666                         previousEventState = stateField[i].previous_state;
667 
668                         emitStateSensorEventSignal(tid, sensorId, sensorOffset,
669                                                    eventState,
670                                                    previousEventState);
671 
672                         SensorEntry sensorEntry{tid, sensorId};
673 
674                         pldm::pdr::EntityInfo entityInfo{};
675                         pldm::pdr::CompositeSensorStates
676                             compositeSensorStates{};
677 
678                         try
679                         {
680                             std::tie(entityInfo, compositeSensorStates) =
681                                 lookupSensorInfo(sensorEntry);
682                         }
683                         catch (const std::out_of_range& e)
684                         {
685                             try
686                             {
687                                 sensorEntry.terminusID = PLDM_TID_RESERVED;
688                                 std::tie(entityInfo, compositeSensorStates) =
689                                     lookupSensorInfo(sensorEntry);
690                             }
691                             catch (const std::out_of_range& e)
692                             {
693                                 std::cerr << "No mapping for the events"
694                                           << std::endl;
695                             }
696                         }
697 
698                         if (sensorOffset > compositeSensorStates.size())
699                         {
700                             std::cerr
701                                 << " Error Invalid data, Invalid sensor offset"
702                                 << std::endl;
703                             return;
704                         }
705 
706                         const auto& possibleStates =
707                             compositeSensorStates[sensorOffset];
708                         if (possibleStates.find(eventState) ==
709                             possibleStates.end())
710                         {
711                             std::cerr
712                                 << " Error invalid_data, Invalid event state"
713                                 << std::endl;
714                             return;
715                         }
716                         const auto& [containerId, entityType, entityInstance] =
717                             entityInfo;
718                         pldm::responder::events::StateSensorEntry
719                             stateSensorEntry{containerId, entityType,
720                                              entityInstance, sensorOffset};
721                         handleStateSensorEvent(stateSensorEntry, eventState);
722                     }
723                 };
724 
725                 rc = handler->registerRequest(
726                     mctp_eid, instanceId, PLDM_PLATFORM,
727                     PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
728                     std::move(getStateSensorReadingRespHandler));
729 
730                 if (rc != PLDM_SUCCESS)
731                 {
732                     std::cerr << " Failed to send request to get State sensor "
733                                  "reading on Host "
734                               << std::endl;
735                 }
736             }
737         }
738     }
739 }
740 } // namespace pldm
741