xref: /openbmc/openpower-occ-control/pldm.cpp (revision aeba51cd)
1815f9f55STom Joseph #include "pldm.hpp"
2815f9f55STom Joseph 
300325238STom Joseph #include "file.hpp"
400325238STom Joseph 
5815f9f55STom Joseph #include <libpldm/entity.h>
697476a1eSAndrew Jeffery #include <libpldm/oem/ibm/state_set.h>
7815f9f55STom Joseph #include <libpldm/platform.h>
8815f9f55STom Joseph #include <libpldm/state_set.h>
9815f9f55STom Joseph 
10815f9f55STom Joseph #include <phosphor-logging/log.hpp>
11bae4d07eSChris Cain #include <sdbusplus/bus.hpp>
12bae4d07eSChris Cain #include <sdeventplus/clock.hpp>
13bae4d07eSChris Cain #include <sdeventplus/exception.hpp>
14bae4d07eSChris Cain #include <sdeventplus/source/io.hpp>
15bae4d07eSChris Cain #include <sdeventplus/source/time.hpp>
16bae4d07eSChris Cain 
17bae4d07eSChris Cain #include <algorithm>
1848002498SPatrick Williams #include <format>
19815f9f55STom Joseph 
20815f9f55STom Joseph namespace pldm
21815f9f55STom Joseph {
22815f9f55STom Joseph 
23815f9f55STom Joseph using namespace phosphor::logging;
24815f9f55STom Joseph 
25bae4d07eSChris Cain using namespace sdeventplus;
26bae4d07eSChris Cain using namespace sdeventplus::source;
27bae4d07eSChris Cain constexpr auto clockId = sdeventplus::ClockId::RealTime;
28bae4d07eSChris Cain using Clock = sdeventplus::Clock<clockId>;
29bae4d07eSChris Cain using Timer = Time<clockId>;
30755af102SChris Cain bool Interface::throttleTraces = false;
31bae4d07eSChris Cain 
fetchSensorInfo(uint16_t stateSetId,SensorToInstance & sensorInstanceMap,SensorOffset & sensorOffset)32cbad219eSEddie James void Interface::fetchSensorInfo(uint16_t stateSetId,
33cbad219eSEddie James                                 SensorToInstance& sensorInstanceMap,
34815f9f55STom Joseph                                 SensorOffset& sensorOffset)
35815f9f55STom Joseph {
36cbad219eSEddie James     PdrList pdrs{};
37bae4d07eSChris Cain     static bool tracedError = false;
38cbad219eSEddie James 
39cbad219eSEddie James     auto& bus = open_power::occ::utils::getBus();
40cbad219eSEddie James     try
41cbad219eSEddie James     {
42cbad219eSEddie James         auto method = bus.new_method_call(
43cbad219eSEddie James             "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
44cbad219eSEddie James             "xyz.openbmc_project.PLDM.PDR", "FindStateSensorPDR");
45bae4d07eSChris Cain         method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId);
46cbad219eSEddie James 
47cbad219eSEddie James         auto responseMsg = bus.call(method);
48cbad219eSEddie James         responseMsg.read(pdrs);
49cbad219eSEddie James     }
50af40808fSPatrick Williams     catch (const sdbusplus::exception_t& e)
51cbad219eSEddie James     {
52bae4d07eSChris Cain         if (!tracedError)
53bae4d07eSChris Cain         {
54bae4d07eSChris Cain             log<level::ERR>(
5548002498SPatrick Williams                 std::format(
56bae4d07eSChris Cain                     "fetchSensorInfo: Failed to find stateSetID:{} PDR: {}",
57bae4d07eSChris Cain                     stateSetId, e.what())
58bae4d07eSChris Cain                     .c_str());
59bae4d07eSChris Cain             tracedError = true;
60bae4d07eSChris Cain         }
61cbad219eSEddie James     }
62cbad219eSEddie James 
63cbad219eSEddie James     if (pdrs.empty())
64cbad219eSEddie James     {
65bae4d07eSChris Cain         if (!tracedError)
66bae4d07eSChris Cain         {
67bae4d07eSChris Cain             log<level::ERR>(
6848002498SPatrick Williams                 std::format(
69bae4d07eSChris Cain                     "fetchSensorInfo: state sensor PDRs ({}) not present",
70bae4d07eSChris Cain                     stateSetId)
71bae4d07eSChris Cain                     .c_str());
72bae4d07eSChris Cain             tracedError = true;
73bae4d07eSChris Cain         }
74cbad219eSEddie James         return;
75cbad219eSEddie James     }
76cbad219eSEddie James 
77bae4d07eSChris Cain     // Found PDR
78bae4d07eSChris Cain     if (tracedError)
79bae4d07eSChris Cain     {
80bae4d07eSChris Cain         log<level::INFO>(
8148002498SPatrick Williams             std::format("fetchSensorInfo: found {} PDRs", pdrs.size()).c_str());
82bae4d07eSChris Cain         tracedError = false;
83bae4d07eSChris Cain     }
84bae4d07eSChris Cain 
85815f9f55STom Joseph     bool offsetFound = false;
86f3a4a69fSGeorge Liu     auto stateSensorPDR =
87815f9f55STom Joseph         reinterpret_cast<const pldm_state_sensor_pdr*>(pdrs.front().data());
88f3a4a69fSGeorge Liu     auto possibleStatesPtr = stateSensorPDR->possible_states;
89f3a4a69fSGeorge Liu     for (auto offset = 0; offset < stateSensorPDR->composite_sensor_count;
90f3a4a69fSGeorge Liu          offset++)
91815f9f55STom Joseph     {
92815f9f55STom Joseph         auto possibleStates =
93815f9f55STom Joseph             reinterpret_cast<const state_sensor_possible_states*>(
94815f9f55STom Joseph                 possibleStatesPtr);
95815f9f55STom Joseph 
96cbad219eSEddie James         if (possibleStates->state_set_id == stateSetId)
97815f9f55STom Joseph         {
98815f9f55STom Joseph             sensorOffset = offset;
99815f9f55STom Joseph             offsetFound = true;
100815f9f55STom Joseph             break;
101815f9f55STom Joseph         }
102815f9f55STom Joseph         possibleStatesPtr += sizeof(possibleStates->state_set_id) +
103815f9f55STom Joseph                              sizeof(possibleStates->possible_states_size) +
104815f9f55STom Joseph                              possibleStates->possible_states_size;
105815f9f55STom Joseph     }
106815f9f55STom Joseph 
107815f9f55STom Joseph     if (!offsetFound)
108815f9f55STom Joseph     {
109cbad219eSEddie James         log<level::ERR>("pldm: state sensor PDR not found");
110815f9f55STom Joseph         return;
111815f9f55STom Joseph     }
112815f9f55STom Joseph 
1131339ab60SMatt Spinler     // To order SensorID based on the EntityInstance.
1141339ab60SMatt Spinler     // Note that when a proc is on a DCM, the PDRs for these sensors
1151339ab60SMatt Spinler     // could have the same instance IDs but different container IDs.
1161339ab60SMatt Spinler     std::map<uint32_t, SensorID> entityInstMap{};
117815f9f55STom Joseph     for (auto& pdr : pdrs)
118815f9f55STom Joseph     {
119815f9f55STom Joseph         auto pdrPtr =
120815f9f55STom Joseph             reinterpret_cast<const pldm_state_sensor_pdr*>(pdr.data());
12172d01aabSChris Cain         uint32_t key = pdrPtr->sensor_id;
1221339ab60SMatt Spinler         entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->sensor_id));
123815f9f55STom Joseph     }
124815f9f55STom Joseph 
125815f9f55STom Joseph     open_power::occ::instanceID count = start;
126a49c987eSPatrick Williams     for (const auto& pair : entityInstMap)
127815f9f55STom Joseph     {
128815f9f55STom Joseph         sensorInstanceMap.emplace(pair.second, count);
129815f9f55STom Joseph         count++;
130815f9f55STom Joseph     }
131815f9f55STom Joseph }
132815f9f55STom Joseph 
sensorEvent(sdbusplus::message_t & msg)133af40808fSPatrick Williams void Interface::sensorEvent(sdbusplus::message_t& msg)
134815f9f55STom Joseph {
135815f9f55STom Joseph     if (!isOCCSensorCacheValid())
136815f9f55STom Joseph     {
137cbad219eSEddie James         fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
138cbad219eSEddie James                         sensorToOCCInstance, OCCSensorOffset);
139815f9f55STom Joseph     }
140815f9f55STom Joseph 
141cbad219eSEddie James     if (sensorToSBEInstance.empty())
142815f9f55STom Joseph     {
143cbad219eSEddie James         fetchSensorInfo(PLDM_OEM_IBM_SBE_HRESET_STATE, sensorToSBEInstance,
144cbad219eSEddie James                         SBESensorOffset);
145815f9f55STom Joseph     }
146815f9f55STom Joseph 
14772d01aabSChris Cain     TerminusID sensorTid{};
148815f9f55STom Joseph     SensorID sensorId{};
149815f9f55STom Joseph     SensorOffset msgSensorOffset{};
150815f9f55STom Joseph     EventState eventState{};
151815f9f55STom Joseph     EventState previousEventState{};
152815f9f55STom Joseph 
15372d01aabSChris Cain     msg.read(sensorTid, sensorId, msgSensorOffset, eventState,
15472d01aabSChris Cain              previousEventState);
155815f9f55STom Joseph 
156cbad219eSEddie James     if (msgSensorOffset == OCCSensorOffset)
157815f9f55STom Joseph     {
158cbad219eSEddie James         auto sensorEntry = sensorToOCCInstance.find(sensorId);
159cbad219eSEddie James 
160432dc486SEddie James         if (sensorEntry != sensorToOCCInstance.end())
161cbad219eSEddie James         {
1628b508bfbSChris Cain             const uint8_t instance = sensorEntry->second;
163755af102SChris Cain             bool validEvent = true;
1647b00cde2SChris Cain             bool isRunning = false;
165cbad219eSEddie James             if (eventState ==
166cbad219eSEddie James                 static_cast<EventState>(
167815f9f55STom Joseph                     PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE))
168815f9f55STom Joseph             {
169a8857c50SChris Cain                 log<level::INFO>(
17048002498SPatrick Williams                     std::format("PLDM: OCC{} is RUNNING", instance).c_str());
1717b00cde2SChris Cain                 isRunning = true;
172815f9f55STom Joseph             }
173815f9f55STom Joseph             else if (eventState ==
174815f9f55STom Joseph                      static_cast<EventState>(
175815f9f55STom Joseph                          PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED))
176815f9f55STom Joseph             {
1778b508bfbSChris Cain                 log<level::INFO>(
17848002498SPatrick Williams                     std::format("PLDM: OCC{} has now STOPPED", instance)
179a8857c50SChris Cain                         .c_str());
180815f9f55STom Joseph             }
181bae4d07eSChris Cain             else if (eventState ==
182bae4d07eSChris Cain                      static_cast<EventState>(
183bae4d07eSChris Cain                          PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT))
184bae4d07eSChris Cain             {
185755af102SChris Cain                 log<level::ERR>(
18648002498SPatrick Williams                     std::format(
187bae4d07eSChris Cain                         "PLDM: OCC{} has now STOPPED and system is in SAFE MODE",
1888b508bfbSChris Cain                         instance)
189bae4d07eSChris Cain                         .c_str());
19031a2f13aSSheldon Bailey 
19131a2f13aSSheldon Bailey                 // Setting safe mode true
19231a2f13aSSheldon Bailey                 safeModeCallBack(true);
193bae4d07eSChris Cain             }
194bae4d07eSChris Cain             else
195bae4d07eSChris Cain             {
196755af102SChris Cain                 log<level::WARNING>(
19748002498SPatrick Williams                     std::format("PLDM: Unexpected PLDM state {} for OCC{}",
1988b508bfbSChris Cain                                 eventState, instance)
199bae4d07eSChris Cain                         .c_str());
200755af102SChris Cain                 validEvent = false;
201bae4d07eSChris Cain             }
202755af102SChris Cain             if (validEvent)
203755af102SChris Cain             {
204755af102SChris Cain                 if ((pldmFd > 0) && (instance == pldmResponseOcc))
205755af102SChris Cain                 {
206755af102SChris Cain                     // Waiting for a response for this OCC, can stop waiting
207755af102SChris Cain                     pldmClose();
208755af102SChris Cain                 }
2097b00cde2SChris Cain                 callBack(instance, isRunning);
210755af102SChris Cain             }
211432dc486SEddie James             return;
212cbad219eSEddie James         }
213432dc486SEddie James     }
214432dc486SEddie James 
215432dc486SEddie James     if (msgSensorOffset == SBESensorOffset)
216cbad219eSEddie James     {
217cbad219eSEddie James         auto sensorEntry = sensorToSBEInstance.find(sensorId);
218815f9f55STom Joseph 
219432dc486SEddie James         if (sensorEntry != sensorToSBEInstance.end())
220cbad219eSEddie James         {
22112d0b828SChris Cain             const uint8_t instance = sensorEntry->second;
22212d0b828SChris Cain             auto match = std::find(outstandingHResets.begin(),
22312d0b828SChris Cain                                    outstandingHResets.end(), instance);
22412d0b828SChris Cain             if (match != outstandingHResets.end())
22512d0b828SChris Cain             {
22612d0b828SChris Cain                 outstandingHResets.erase(match);
227cbad219eSEddie James                 if (eventState == static_cast<EventState>(SBE_HRESET_NOT_READY))
228cbad219eSEddie James                 {
229bae4d07eSChris Cain                     log<level::INFO>(
23048002498SPatrick Williams                         std::format("pldm: HRESET is NOT READY (OCC{})",
23112d0b828SChris Cain                                     instance)
232bae4d07eSChris Cain                             .c_str());
233cbad219eSEddie James                 }
23412d0b828SChris Cain                 else if (eventState ==
23512d0b828SChris Cain                          static_cast<EventState>(SBE_HRESET_READY))
236cbad219eSEddie James                 {
23712d0b828SChris Cain                     sbeCallBack(instance, true);
238cbad219eSEddie James                 }
23912d0b828SChris Cain                 else if (eventState ==
24012d0b828SChris Cain                          static_cast<EventState>(SBE_HRESET_FAILED))
241cbad219eSEddie James                 {
24212d0b828SChris Cain                     sbeCallBack(instance, false);
243cbad219eSEddie James                 }
244cbad219eSEddie James             }
24512d0b828SChris Cain             // else request was not from us
24612d0b828SChris Cain         }
247cbad219eSEddie James     }
248432dc486SEddie James }
249cbad219eSEddie James 
hostStateEvent(sdbusplus::message_t & msg)250af40808fSPatrick Williams void Interface::hostStateEvent(sdbusplus::message_t& msg)
251157467d0SChris Cain {
252157467d0SChris Cain     std::map<std::string, std::variant<std::string>> properties{};
253157467d0SChris Cain     std::string interface;
254157467d0SChris Cain     msg.read(interface, properties);
255157467d0SChris Cain     const auto stateEntry = properties.find("CurrentHostState");
256157467d0SChris Cain     if (stateEntry != properties.end())
257157467d0SChris Cain     {
258157467d0SChris Cain         auto stateEntryValue = stateEntry->second;
259157467d0SChris Cain         auto propVal = std::get<std::string>(stateEntryValue);
260157467d0SChris Cain         if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
261157467d0SChris Cain         {
262157467d0SChris Cain             clearData();
263157467d0SChris Cain         }
264157467d0SChris Cain     }
265157467d0SChris Cain }
266157467d0SChris Cain 
clearData()267bae4d07eSChris Cain void Interface::clearData()
268bae4d07eSChris Cain {
26972d01aabSChris Cain     if (!sensorToOCCInstance.empty())
27072d01aabSChris Cain     {
27172d01aabSChris Cain         log<level::INFO>(
27248002498SPatrick Williams             std::format("clearData: Clearing sensorToOCCInstance ({} entries)",
27372d01aabSChris Cain                         sensorToOCCInstance.size())
27472d01aabSChris Cain                 .c_str());
27572d01aabSChris Cain         for (auto entry : sensorToOCCInstance)
27672d01aabSChris Cain         {
27772d01aabSChris Cain             log<level::INFO>(
27848002498SPatrick Williams                 std::format("clearData: OCC{} / sensorID: 0x{:04X}",
27972d01aabSChris Cain                             entry.second, entry.first)
28072d01aabSChris Cain                     .c_str());
281082a6ca7SChris Cain             callBack(entry.second, false);
28272d01aabSChris Cain         }
283815f9f55STom Joseph         sensorToOCCInstance.clear();
28472d01aabSChris Cain     }
28572d01aabSChris Cain     if (!occInstanceToEffecter.empty())
28672d01aabSChris Cain     {
28772d01aabSChris Cain         log<level::DEBUG>(
28848002498SPatrick Williams             std::format(
28972d01aabSChris Cain                 "clearData: Clearing occInstanceToEffecter ({} entries)",
29072d01aabSChris Cain                 occInstanceToEffecter.size())
29172d01aabSChris Cain                 .c_str());
29200325238STom Joseph         occInstanceToEffecter.clear();
29372d01aabSChris Cain     }
29472d01aabSChris Cain     if (!sensorToSBEInstance.empty())
29572d01aabSChris Cain     {
29672d01aabSChris Cain         log<level::DEBUG>(
29748002498SPatrick Williams             std::format("clearData: Clearing sensorToSBEInstance ({} entries)",
29872d01aabSChris Cain                         sensorToSBEInstance.size())
29972d01aabSChris Cain                 .c_str());
300cbad219eSEddie James         sensorToSBEInstance.clear();
30172d01aabSChris Cain     }
30272d01aabSChris Cain     if (!sbeInstanceToEffecter.empty())
30372d01aabSChris Cain     {
30472d01aabSChris Cain         log<level::DEBUG>(
30548002498SPatrick Williams             std::format(
30672d01aabSChris Cain                 "clearData: Clearing sbeInstanceToEffecter ({} entries)",
30772d01aabSChris Cain                 sbeInstanceToEffecter.size())
30872d01aabSChris Cain                 .c_str());
309cbad219eSEddie James         sbeInstanceToEffecter.clear();
310815f9f55STom Joseph     }
31172d01aabSChris Cain }
312815f9f55STom Joseph 
fetchEffecterInfo(uint16_t stateSetId,InstanceToEffecter & instanceToEffecterMap,CompositeEffecterCount & effecterCount,uint8_t & stateIdPos)313432dc486SEddie James void Interface::fetchEffecterInfo(uint16_t stateSetId,
314cbad219eSEddie James                                   InstanceToEffecter& instanceToEffecterMap,
315cbad219eSEddie James                                   CompositeEffecterCount& effecterCount,
316cbad219eSEddie James                                   uint8_t& stateIdPos)
31700325238STom Joseph {
318cbad219eSEddie James     PdrList pdrs{};
319cbad219eSEddie James 
320cbad219eSEddie James     auto& bus = open_power::occ::utils::getBus();
321cbad219eSEddie James     try
322cbad219eSEddie James     {
323cbad219eSEddie James         auto method = bus.new_method_call(
324cbad219eSEddie James             "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
325cbad219eSEddie James             "xyz.openbmc_project.PLDM.PDR", "FindStateEffecterPDR");
326bae4d07eSChris Cain         method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId);
327cbad219eSEddie James 
328cbad219eSEddie James         auto responseMsg = bus.call(method);
329cbad219eSEddie James         responseMsg.read(pdrs);
330cbad219eSEddie James     }
331af40808fSPatrick Williams     catch (const sdbusplus::exception_t& e)
332cbad219eSEddie James     {
333cbad219eSEddie James         log<level::ERR>("pldm: Failed to fetch the state effecter PDRs",
334cbad219eSEddie James                         entry("ERROR=%s", e.what()));
335cbad219eSEddie James     }
336cbad219eSEddie James 
337cbad219eSEddie James     if (!pdrs.size())
338cbad219eSEddie James     {
339cbad219eSEddie James         log<level::ERR>("pldm: state effecter PDRs not present");
340cbad219eSEddie James         return;
341cbad219eSEddie James     }
342cbad219eSEddie James 
34300325238STom Joseph     bool offsetFound = false;
344f3a4a69fSGeorge Liu     auto stateEffecterPDR =
34500325238STom Joseph         reinterpret_cast<const pldm_state_effecter_pdr*>(pdrs.front().data());
346f3a4a69fSGeorge Liu     auto possibleStatesPtr = stateEffecterPDR->possible_states;
347f3a4a69fSGeorge Liu     for (auto offset = 0; offset < stateEffecterPDR->composite_effecter_count;
348f3a4a69fSGeorge Liu          offset++)
34900325238STom Joseph     {
35000325238STom Joseph         auto possibleStates =
35100325238STom Joseph             reinterpret_cast<const state_effecter_possible_states*>(
35200325238STom Joseph                 possibleStatesPtr);
35300325238STom Joseph 
354cbad219eSEddie James         if (possibleStates->state_set_id == stateSetId)
35500325238STom Joseph         {
356cbad219eSEddie James             stateIdPos = offset;
357f3a4a69fSGeorge Liu             effecterCount = stateEffecterPDR->composite_effecter_count;
35800325238STom Joseph             offsetFound = true;
35900325238STom Joseph             break;
36000325238STom Joseph         }
36100325238STom Joseph         possibleStatesPtr += sizeof(possibleStates->state_set_id) +
36200325238STom Joseph                              sizeof(possibleStates->possible_states_size) +
36300325238STom Joseph                              possibleStates->possible_states_size;
36400325238STom Joseph     }
36500325238STom Joseph 
36600325238STom Joseph     if (!offsetFound)
36700325238STom Joseph     {
36800325238STom Joseph         return;
36900325238STom Joseph     }
37000325238STom Joseph 
3710f516528SChris Cain     std::map<uint32_t, EffecterID> entityInstMap{};
37200325238STom Joseph     for (auto& pdr : pdrs)
37300325238STom Joseph     {
37400325238STom Joseph         auto pdrPtr =
37500325238STom Joseph             reinterpret_cast<const pldm_state_effecter_pdr*>(pdr.data());
37672d01aabSChris Cain         uint32_t key = pdrPtr->effecter_id;
3771339ab60SMatt Spinler         entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->effecter_id));
37800325238STom Joseph     }
37900325238STom Joseph 
38000325238STom Joseph     open_power::occ::instanceID position = start;
381a49c987eSPatrick Williams     for (const auto& pair : entityInstMap)
38200325238STom Joseph     {
383cbad219eSEddie James         instanceToEffecterMap.emplace(position, pair.second);
38400325238STom Joseph         position++;
38500325238STom Joseph     }
38600325238STom Joseph }
38700325238STom Joseph 
38800325238STom Joseph std::vector<uint8_t>
prepareSetEffecterReq(EffecterID effecterId,CompositeEffecterCount effecterCount,uint8_t stateIdPos,uint8_t stateSetValue)3898b508bfbSChris Cain     Interface::prepareSetEffecterReq(EffecterID effecterId,
39000325238STom Joseph                                      CompositeEffecterCount effecterCount,
391cbad219eSEddie James                                      uint8_t stateIdPos, uint8_t stateSetValue)
39200325238STom Joseph {
393*aeba51cdSRashmica Gupta     if (!getPldmInstanceId())
3948b508bfbSChris Cain     {
3958b508bfbSChris Cain         return std::vector<uint8_t>();
3968b508bfbSChris Cain     }
3978b508bfbSChris Cain 
39800325238STom Joseph     std::vector<uint8_t> request(
39900325238STom Joseph         sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(effecterCount) +
40000325238STom Joseph         (effecterCount * sizeof(set_effecter_state_field)));
40100325238STom Joseph     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
40200325238STom Joseph     std::vector<set_effecter_state_field> stateField;
40300325238STom Joseph 
40400325238STom Joseph     for (uint8_t effecterPos = 0; effecterPos < effecterCount; effecterPos++)
40500325238STom Joseph     {
406cbad219eSEddie James         if (effecterPos == stateIdPos)
40700325238STom Joseph         {
408cbad219eSEddie James             stateField.emplace_back(
409cbad219eSEddie James                 set_effecter_state_field{PLDM_REQUEST_SET, stateSetValue});
41000325238STom Joseph         }
41100325238STom Joseph         else
41200325238STom Joseph         {
41300325238STom Joseph             stateField.emplace_back(
41400325238STom Joseph                 set_effecter_state_field{PLDM_NO_CHANGE, 0});
41500325238STom Joseph         }
41600325238STom Joseph     }
41700325238STom Joseph     auto rc = encode_set_state_effecter_states_req(
418*aeba51cdSRashmica Gupta         pldmInstanceID.value(), effecterId, effecterCount, stateField.data(),
4198b508bfbSChris Cain         requestMsg);
42000325238STom Joseph     if (rc != PLDM_SUCCESS)
42100325238STom Joseph     {
42200325238STom Joseph         log<level::ERR>("encode set effecter states request returned error ",
42300325238STom Joseph                         entry("RC=%d", rc));
42400325238STom Joseph         request.clear();
42500325238STom Joseph     }
42600325238STom Joseph     return request;
42700325238STom Joseph }
42800325238STom Joseph 
resetOCC(open_power::occ::instanceID occInstanceId)42900325238STom Joseph void Interface::resetOCC(open_power::occ::instanceID occInstanceId)
43000325238STom Joseph {
431bae4d07eSChris Cain     if (open_power::occ::utils::isHostRunning())
432bae4d07eSChris Cain     {
43300325238STom Joseph         if (!isPDREffecterCacheValid())
43400325238STom Joseph         {
435432dc486SEddie James             fetchEffecterInfo(PLDM_STATE_SET_BOOT_RESTART_CAUSE,
436432dc486SEddie James                               occInstanceToEffecter, OCCEffecterCount,
437432dc486SEddie James                               bootRestartPosition);
43800325238STom Joseph         }
43900325238STom Joseph 
44000325238STom Joseph         // Find the matching effecter for the OCC instance
44100325238STom Joseph         auto effecterEntry = occInstanceToEffecter.find(occInstanceId);
44200325238STom Joseph         if (effecterEntry == occInstanceToEffecter.end())
44300325238STom Joseph         {
44400325238STom Joseph             log<level::ERR>(
44548002498SPatrick Williams                 std::format(
4460f516528SChris Cain                     "pldm: Failed to find a matching effecter for OCC instance {}",
4470f516528SChris Cain                     occInstanceId)
4480f516528SChris Cain                     .c_str());
44900325238STom Joseph 
45000325238STom Joseph             return;
45100325238STom Joseph         }
45200325238STom Joseph 
453cbad219eSEddie James         // Prepare the SetStateEffecterStates request to reset the OCC
454cbad219eSEddie James         auto request = prepareSetEffecterReq(
4558b508bfbSChris Cain             effecterEntry->second, OCCEffecterCount, bootRestartPosition,
4568b508bfbSChris Cain             PLDM_STATE_SET_BOOT_RESTART_CAUSE_WARM_RESET);
457cbad219eSEddie James 
458cbad219eSEddie James         if (request.empty())
459cbad219eSEddie James         {
460bae4d07eSChris Cain             log<level::ERR>(
461bae4d07eSChris Cain                 "pldm: SetStateEffecterStates OCC reset request empty");
462cbad219eSEddie James             return;
463cbad219eSEddie James         }
464cbad219eSEddie James 
465bae4d07eSChris Cain         // Send request to reset the OCCs/PM Complex (ignore response)
466bae4d07eSChris Cain         sendPldm(request, occInstanceId, false);
467bae4d07eSChris Cain     }
468bae4d07eSChris Cain     else
469bae4d07eSChris Cain     {
470bae4d07eSChris Cain         log<level::ERR>(
47148002498SPatrick Williams             std::format("resetOCC: HOST is not running (OCC{})", occInstanceId)
472bae4d07eSChris Cain                 .c_str());
473bae4d07eSChris Cain         clearData();
474bae4d07eSChris Cain     }
475cbad219eSEddie James }
476cbad219eSEddie James 
sendHRESET(open_power::occ::instanceID sbeInstanceId)477cbad219eSEddie James void Interface::sendHRESET(open_power::occ::instanceID sbeInstanceId)
478cbad219eSEddie James {
479bae4d07eSChris Cain     if (open_power::occ::utils::isHostRunning())
480bae4d07eSChris Cain     {
481cbad219eSEddie James         if (sbeInstanceToEffecter.empty())
482cbad219eSEddie James         {
483432dc486SEddie James             fetchEffecterInfo(PLDM_OEM_IBM_SBE_MAINTENANCE_STATE,
484cbad219eSEddie James                               sbeInstanceToEffecter, SBEEffecterCount,
485cbad219eSEddie James                               sbeMaintenanceStatePosition);
486cbad219eSEddie James         }
487cbad219eSEddie James 
488cbad219eSEddie James         auto effecterEntry = sbeInstanceToEffecter.find(sbeInstanceId);
489cbad219eSEddie James         if (effecterEntry == sbeInstanceToEffecter.end())
490cbad219eSEddie James         {
491cbad219eSEddie James             log<level::ERR>(
492cbad219eSEddie James                 "pldm: Failed to find a matching effecter for SBE instance",
493cbad219eSEddie James                 entry("SBE=%d", sbeInstanceId));
494cbad219eSEddie James             return;
495cbad219eSEddie James         }
496cbad219eSEddie James 
497cbad219eSEddie James         // Prepare the SetStateEffecterStates request to HRESET the SBE
498cbad219eSEddie James         auto request = prepareSetEffecterReq(
4998b508bfbSChris Cain             effecterEntry->second, SBEEffecterCount,
500cbad219eSEddie James             sbeMaintenanceStatePosition, SBE_RETRY_REQUIRED);
501cbad219eSEddie James 
502cbad219eSEddie James         if (request.empty())
503cbad219eSEddie James         {
504bae4d07eSChris Cain             log<level::ERR>(
505bae4d07eSChris Cain                 "pldm: SetStateEffecterStates HRESET request empty");
506cbad219eSEddie James             return;
507cbad219eSEddie James         }
508cbad219eSEddie James 
509bae4d07eSChris Cain         // Send request to issue HRESET of SBE (ignore response)
510bae4d07eSChris Cain         sendPldm(request, sbeInstanceId, false);
51112d0b828SChris Cain         outstandingHResets.insert(sbeInstanceId);
512bae4d07eSChris Cain     }
513bae4d07eSChris Cain     else
514bae4d07eSChris Cain     {
51548002498SPatrick Williams         log<level::ERR>(std::format("sendHRESET: HOST is not running (OCC{})",
516bae4d07eSChris Cain                                     sbeInstanceId)
517bae4d07eSChris Cain                             .c_str());
518bae4d07eSChris Cain         clearData();
519bae4d07eSChris Cain     }
520cbad219eSEddie James }
521cbad219eSEddie James 
getPldmInstanceId()522*aeba51cdSRashmica Gupta bool Interface::getPldmInstanceId()
523cbad219eSEddie James {
524*aeba51cdSRashmica Gupta     if (!pldmInstanceID)
5258b508bfbSChris Cain     {
5268b508bfbSChris Cain         // Request new instance ID
52748330578SChris Cain         auto& bus = open_power::occ::utils::getBus();
52800325238STom Joseph         try
52900325238STom Joseph         {
53000325238STom Joseph             auto method = bus.new_method_call(
53100325238STom Joseph                 "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
53200325238STom Joseph                 "xyz.openbmc_project.PLDM.Requester", "GetInstanceId");
53300325238STom Joseph             method.append(mctpEid);
53400325238STom Joseph             auto reply = bus.call(method);
5358b508bfbSChris Cain             uint8_t newInstanceId;
5368b508bfbSChris Cain             reply.read(newInstanceId);
537*aeba51cdSRashmica Gupta             pldmInstanceID = newInstanceId;
538755af102SChris Cain             if (!throttleTraces)
539755af102SChris Cain             {
54048002498SPatrick Williams                 log<level::INFO>(std::format("pldm: got new InstanceId: {}",
541*aeba51cdSRashmica Gupta                                              pldmInstanceID.value())
5428b508bfbSChris Cain                                      .c_str());
54300325238STom Joseph             }
544755af102SChris Cain         }
545af40808fSPatrick Williams         catch (const sdbusplus::exception_t& e)
54600325238STom Joseph         {
547bd551de3SChris Cain             log<level::ERR>(
54848002498SPatrick Williams                 std::format("pldm: GetInstanceId failed: {}", e.what())
5498b508bfbSChris Cain                     .c_str());
550cbad219eSEddie James             return false;
55100325238STom Joseph         }
5528b508bfbSChris Cain     }
55300325238STom Joseph 
554cbad219eSEddie James     return true;
555cbad219eSEddie James }
55600325238STom Joseph 
sendPldm(const std::vector<uint8_t> & request,const uint8_t instance,const bool rspExpected)557bae4d07eSChris Cain void Interface::sendPldm(const std::vector<uint8_t>& request,
558bae4d07eSChris Cain                          const uint8_t instance, const bool rspExpected)
55900325238STom Joseph {
560*aeba51cdSRashmica Gupta     if (!pldmInstanceID)
5618b508bfbSChris Cain     {
562*aeba51cdSRashmica Gupta         log<level::ERR>("sendPldm: No PLDM Instance ID found!");
5638b508bfbSChris Cain         return;
5648b508bfbSChris Cain     }
5658b508bfbSChris Cain 
566c9dc4418SChris Cain     // Connect to MCTP socket
567bae4d07eSChris Cain     pldmFd = pldm_open();
568bae4d07eSChris Cain     auto openErrno = errno;
569bae4d07eSChris Cain     if (pldmFd == PLDM_REQUESTER_OPEN_FAIL)
57000325238STom Joseph     {
571d1b6826aSChris Cain         log<level::ERR>(
57248002498SPatrick Williams             std::format(
573bae4d07eSChris Cain                 "sendPldm: Failed to connect to MCTP socket, errno={}/{}",
574bae4d07eSChris Cain                 openErrno, strerror(openErrno))
575d1b6826aSChris Cain                 .c_str());
57600325238STom Joseph         return;
57700325238STom Joseph     }
578cbad219eSEddie James 
57900325238STom Joseph     // Send the PLDM request message to HBRT
580bae4d07eSChris Cain     if (rspExpected)
581d1b6826aSChris Cain     {
582bae4d07eSChris Cain         // Register callback when response is available
583bae4d07eSChris Cain         registerPldmRspCallback();
584bae4d07eSChris Cain 
585bae4d07eSChris Cain         // Send PLDM request
586755af102SChris Cain         if (!throttleTraces)
587755af102SChris Cain         {
588bae4d07eSChris Cain             log<level::INFO>(
58948002498SPatrick Williams                 std::format(
590bae4d07eSChris Cain                     "sendPldm: calling pldm_send(OCC{}, instance:{}, {} bytes)",
591*aeba51cdSRashmica Gupta                     instance, pldmInstanceID.value(), request.size())
592bae4d07eSChris Cain                     .c_str());
593755af102SChris Cain         }
594bae4d07eSChris Cain         pldmResponseReceived = false;
595bae4d07eSChris Cain         pldmResponseTimeout = false;
596bae4d07eSChris Cain         pldmResponseOcc = instance;
597a49c987eSPatrick Williams         auto pldmRc = pldm_send(mctpEid, pldmFd, request.data(),
598a49c987eSPatrick Williams                                 request.size());
599bae4d07eSChris Cain         auto sendErrno = errno;
600bae4d07eSChris Cain         if (pldmRc != PLDM_REQUESTER_SUCCESS)
601bae4d07eSChris Cain         {
602bae4d07eSChris Cain             log<level::ERR>(
60348002498SPatrick Williams                 std::format(
604bae4d07eSChris Cain                     "sendPldm: pldm_send failed with rc={} and errno={}/{}",
6055161a028SChris Cain                     static_cast<
6065161a028SChris Cain                         std::underlying_type_t<pldm_requester_error_codes>>(
6075161a028SChris Cain                         pldmRc),
6085161a028SChris Cain                     sendErrno, strerror(sendErrno))
609bae4d07eSChris Cain                     .c_str());
610bae4d07eSChris Cain             pldmClose();
611bae4d07eSChris Cain             return;
612bae4d07eSChris Cain         }
613bae4d07eSChris Cain 
614bae4d07eSChris Cain         // start timer waiting for the response
615bae4d07eSChris Cain         using namespace std::literals::chrono_literals;
616bd551de3SChris Cain         pldmRspTimer.restartOnce(8s);
617bae4d07eSChris Cain 
618bae4d07eSChris Cain         // Wait for response/timeout
619bae4d07eSChris Cain     }
620bae4d07eSChris Cain     else // not expecting the response
621bae4d07eSChris Cain     {
622755af102SChris Cain         if (!throttleTraces)
623755af102SChris Cain         {
624bae4d07eSChris Cain             log<level::INFO>(
62548002498SPatrick Williams                 std::format(
626bae4d07eSChris Cain                     "sendPldm: calling pldm_send(mctpID:{}, fd:{}, {} bytes) for OCC{}",
627bae4d07eSChris Cain                     mctpEid, pldmFd, request.size(), instance)
628bae4d07eSChris Cain                     .c_str());
629755af102SChris Cain         }
630bae4d07eSChris Cain         auto rc = pldm_send(mctpEid, pldmFd, request.data(), request.size());
631bae4d07eSChris Cain         auto sendErrno = errno;
63200325238STom Joseph         if (rc)
63300325238STom Joseph         {
634d1b6826aSChris Cain             log<level::ERR>(
63548002498SPatrick Williams                 std::format(
636bae4d07eSChris Cain                     "sendPldm: pldm_send(mctpID:{}, fd:{}, {} bytes) failed with rc={} and errno={}/{}",
6375161a028SChris Cain                     mctpEid, pldmFd, request.size(),
6385161a028SChris Cain                     static_cast<
6395161a028SChris Cain                         std::underlying_type_t<pldm_requester_error_codes>>(rc),
6405161a028SChris Cain                     sendErrno, strerror(sendErrno))
641d1b6826aSChris Cain                     .c_str());
64200325238STom Joseph         }
6438b508bfbSChris Cain         else
6448b508bfbSChris Cain         {
6458b508bfbSChris Cain             // Not waiting for response, instance ID should be freed
646*aeba51cdSRashmica Gupta             pldmInstanceID = std::nullopt;
6478b508bfbSChris Cain         }
648bae4d07eSChris Cain         pldmClose();
649bae4d07eSChris Cain     }
650bae4d07eSChris Cain }
65100325238STom Joseph 
652bae4d07eSChris Cain // Attaches the FD to event loop and registers the callback handler
registerPldmRspCallback()653bae4d07eSChris Cain void Interface::registerPldmRspCallback()
654bae4d07eSChris Cain {
655bae4d07eSChris Cain     decltype(eventSource.get()) sourcePtr = nullptr;
656bae4d07eSChris Cain     auto rc = sd_event_add_io(event.get(), &sourcePtr, pldmFd, EPOLLIN,
657bae4d07eSChris Cain                               pldmRspCallback, this);
658bae4d07eSChris Cain     if (rc < 0)
65900325238STom Joseph     {
66000325238STom Joseph         log<level::ERR>(
66148002498SPatrick Williams             std::format(
662bae4d07eSChris Cain                 "registerPldmRspCallback: sd_event_add_io: Error({})={} : fd={}",
663bae4d07eSChris Cain                 rc, strerror(-rc), pldmFd)
664d1b6826aSChris Cain                 .c_str());
665d1b6826aSChris Cain     }
666d1b6826aSChris Cain     else
667d1b6826aSChris Cain     {
668bae4d07eSChris Cain         // puts sourcePtr in the event source.
669bae4d07eSChris Cain         eventSource.reset(sourcePtr);
670bae4d07eSChris Cain     }
671bae4d07eSChris Cain }
672bae4d07eSChris Cain 
673bae4d07eSChris Cain // Add a timer to the event loop, default 30s.
pldmRspExpired()674bae4d07eSChris Cain void Interface::pldmRspExpired()
675bae4d07eSChris Cain {
676bae4d07eSChris Cain     if (!pldmResponseReceived)
677bae4d07eSChris Cain     {
678755af102SChris Cain         if (!throttleTraces)
679755af102SChris Cain         {
680082a6ca7SChris Cain             log<level::WARNING>(
68148002498SPatrick Williams                 std::format(
682bae4d07eSChris Cain                     "pldmRspExpired: timerCallback - timeout waiting for pldm response for OCC{}",
683bae4d07eSChris Cain                     pldmResponseOcc)
684d1b6826aSChris Cain                     .c_str());
685755af102SChris Cain         }
686bae4d07eSChris Cain         pldmResponseTimeout = true;
687bae4d07eSChris Cain         if (pldmFd)
688bae4d07eSChris Cain         {
689bae4d07eSChris Cain             pldmClose();
690bae4d07eSChris Cain         }
691bae4d07eSChris Cain     }
692bae4d07eSChris Cain     return;
693bae4d07eSChris Cain };
694bae4d07eSChris Cain 
pldmClose()695bae4d07eSChris Cain void Interface::pldmClose()
696bae4d07eSChris Cain {
697bae4d07eSChris Cain     if (pldmRspTimer.isEnabled())
698bae4d07eSChris Cain     {
699bae4d07eSChris Cain         // stop PLDM response timer
700bae4d07eSChris Cain         pldmRspTimer.setEnabled(false);
701bae4d07eSChris Cain     }
702159a2279SPavithra Barithaya     pldm_close();
703bae4d07eSChris Cain     pldmFd = -1;
704bae4d07eSChris Cain     eventSource.reset();
705bae4d07eSChris Cain }
706bae4d07eSChris Cain 
pldmRspCallback(sd_event_source *,int fd,uint32_t revents,void * userData)707bae4d07eSChris Cain int Interface::pldmRspCallback(sd_event_source* /*es*/, int fd,
708bae4d07eSChris Cain                                uint32_t revents, void* userData)
709bae4d07eSChris Cain {
710bae4d07eSChris Cain     if (!(revents & EPOLLIN))
711bae4d07eSChris Cain     {
712bae4d07eSChris Cain         log<level::INFO>(
71348002498SPatrick Williams             std::format("pldmRspCallback - revents={:08X}", revents).c_str());
714bae4d07eSChris Cain         return -1;
715bae4d07eSChris Cain     }
716bae4d07eSChris Cain 
717bae4d07eSChris Cain     auto pldmIface = static_cast<Interface*>(userData);
718bae4d07eSChris Cain 
719*aeba51cdSRashmica Gupta     if (!pldmIface->pldmInstanceID)
7208b508bfbSChris Cain     {
7218b508bfbSChris Cain         log<level::ERR>(
722*aeba51cdSRashmica Gupta             "pldmRspCallback: No outstanding PLDM Instance ID found");
7238b508bfbSChris Cain         return -1;
7248b508bfbSChris Cain     }
7258b508bfbSChris Cain 
726bae4d07eSChris Cain     uint8_t* responseMsg = nullptr;
727bae4d07eSChris Cain     size_t responseMsgSize{};
728bae4d07eSChris Cain 
729755af102SChris Cain     if (!throttleTraces)
730755af102SChris Cain     {
731bae4d07eSChris Cain         log<level::INFO>(
73248002498SPatrick Williams             std::format("pldmRspCallback: calling pldm_recv() instance:{}",
733*aeba51cdSRashmica Gupta                         pldmIface->pldmInstanceID.value())
734bae4d07eSChris Cain                 .c_str());
735755af102SChris Cain     }
736*aeba51cdSRashmica Gupta     auto rc = pldm_recv(mctpEid, fd, pldmIface->pldmInstanceID.value(),
7378b508bfbSChris Cain                         &responseMsg, &responseMsgSize);
738bae4d07eSChris Cain     int lastErrno = errno;
739d1b6826aSChris Cain     if (rc)
740d1b6826aSChris Cain     {
741755af102SChris Cain         if (!throttleTraces)
742755af102SChris Cain         {
743d1b6826aSChris Cain             log<level::ERR>(
74448002498SPatrick Williams                 std::format(
7455161a028SChris Cain                     "pldmRspCallback: pldm_recv failed with rc={}, errno={}/{}",
746755af102SChris Cain                     static_cast<
747755af102SChris Cain                         std::underlying_type_t<pldm_requester_error_codes>>(rc),
748bae4d07eSChris Cain                     lastErrno, strerror(lastErrno))
749bae4d07eSChris Cain                     .c_str());
750755af102SChris Cain         }
751bae4d07eSChris Cain         return -1;
752bae4d07eSChris Cain     }
7538b508bfbSChris Cain 
7548b508bfbSChris Cain     // We got the response for the PLDM request msg that was sent
755755af102SChris Cain     if (!throttleTraces)
756755af102SChris Cain     {
757bae4d07eSChris Cain         log<level::INFO>(
75848002498SPatrick Williams             std::format("pldmRspCallback: pldm_recv() rsp was {} bytes",
759bae4d07eSChris Cain                         responseMsgSize)
760bae4d07eSChris Cain                 .c_str());
761755af102SChris Cain     }
762bae4d07eSChris Cain 
763bae4d07eSChris Cain     if (pldmIface->pldmRspTimer.isEnabled())
764bae4d07eSChris Cain     {
765bae4d07eSChris Cain         // stop PLDM response timer
766bae4d07eSChris Cain         pldmIface->pldmRspTimer.setEnabled(false);
767bae4d07eSChris Cain     }
768bae4d07eSChris Cain 
7698b508bfbSChris Cain     // instance ID should be freed
770*aeba51cdSRashmica Gupta     pldmIface->pldmInstanceID = std::nullopt;
7718b508bfbSChris Cain 
772bae4d07eSChris Cain     // Set pointer to autodelete
773bae4d07eSChris Cain     std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{responseMsg,
774bae4d07eSChris Cain                                                                   std::free};
775bae4d07eSChris Cain 
776bae4d07eSChris Cain     auto response = reinterpret_cast<pldm_msg*>(responseMsgPtr.get());
777bae4d07eSChris Cain     if (response->payload[0] != PLDM_SUCCESS)
778bae4d07eSChris Cain     {
779bae4d07eSChris Cain         log<level::ERR>(
78048002498SPatrick Williams             std::format("pldmRspCallback: payload[0] was not success: {}",
781bae4d07eSChris Cain                         response->payload[0])
782bae4d07eSChris Cain                 .c_str());
783bae4d07eSChris Cain         pldmIface->pldmClose();
784bae4d07eSChris Cain         return -1;
785bae4d07eSChris Cain     }
786bae4d07eSChris Cain 
787bae4d07eSChris Cain     // Decode the response
788bae4d07eSChris Cain     uint8_t compCode = 0, sensorCount = 1;
789bae4d07eSChris Cain     get_sensor_state_field field[6];
790bae4d07eSChris Cain     responseMsgSize -= sizeof(pldm_msg_hdr);
791bae4d07eSChris Cain     auto msgRc = decode_get_state_sensor_readings_resp(
792bae4d07eSChris Cain         response, responseMsgSize, &compCode, &sensorCount, field);
793bae4d07eSChris Cain     if ((msgRc != PLDM_SUCCESS) || (compCode != PLDM_SUCCESS))
794bae4d07eSChris Cain     {
795bae4d07eSChris Cain         log<level::ERR>(
79648002498SPatrick Williams             std::format(
797bae4d07eSChris Cain                 "pldmRspCallback: decode_get_state_sensor_readings failed with rc={} and compCode={}",
798bae4d07eSChris Cain                 msgRc, compCode)
799bae4d07eSChris Cain                 .c_str());
800bae4d07eSChris Cain         pldmIface->pldmClose();
801bae4d07eSChris Cain         return -1;
802bae4d07eSChris Cain     }
803bae4d07eSChris Cain 
804bae4d07eSChris Cain     pldmIface->pldmClose();
805bae4d07eSChris Cain 
806bae4d07eSChris Cain     const uint8_t instance = pldmIface->pldmResponseOcc;
807bae4d07eSChris Cain     const uint8_t occSensorState = field[0].present_state;
808bae4d07eSChris Cain     pldmIface->pldmResponseReceived = true;
809bae4d07eSChris Cain 
810bae4d07eSChris Cain     if (occSensorState == PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE)
811bae4d07eSChris Cain     {
812bae4d07eSChris Cain         log<level::INFO>(
81348002498SPatrick Williams             std::format("pldmRspCallback: OCC{} is RUNNING", instance).c_str());
814bae4d07eSChris Cain         pldmIface->callBack(instance, true);
815bae4d07eSChris Cain     }
816733b201fSChris Cain     else if (occSensorState ==
817733b201fSChris Cain              PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT)
818733b201fSChris Cain     {
819755af102SChris Cain         log<level::ERR>(
82048002498SPatrick Williams             std::format(
821733b201fSChris Cain                 "pldmRspCallback: OCC{} has now STOPPED and system is in SAFE MODE",
822733b201fSChris Cain                 instance)
823733b201fSChris Cain                 .c_str());
82431a2f13aSSheldon Bailey 
82531a2f13aSSheldon Bailey         // Setting safe mode true
82631a2f13aSSheldon Bailey         pldmIface->safeModeCallBack(true);
82731a2f13aSSheldon Bailey 
828733b201fSChris Cain         pldmIface->callBack(instance, false);
829733b201fSChris Cain     }
830755af102SChris Cain     else if (occSensorState ==
831755af102SChris Cain              PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED)
832bae4d07eSChris Cain     {
833bae4d07eSChris Cain         log<level::INFO>(
834755af102SChris Cain             std::format("pldmRspCallback: OCC{} is not running", instance)
835bae4d07eSChris Cain                 .c_str());
836755af102SChris Cain         pldmIface->callBack(instance, false);
837755af102SChris Cain     }
838755af102SChris Cain     else
839c9dc4418SChris Cain     {
840c9dc4418SChris Cain         const size_t rspLength = responseMsgSize + sizeof(pldm_msg_hdr);
841c9dc4418SChris Cain         std::vector<std::uint8_t> pldmResponse(rspLength);
842c9dc4418SChris Cain         memcpy(&pldmResponse[0], reinterpret_cast<std::uint8_t*>(response),
843c9dc4418SChris Cain                rspLength);
844755af102SChris Cain         if (!throttleTraces)
845755af102SChris Cain         {
846755af102SChris Cain             log<level::WARNING>(
84748002498SPatrick Williams                 std::format(
848755af102SChris Cain                     "pldmRspCallback: Unexpected State: {} - PLDM response ({} bytes) for OCC{}:",
849755af102SChris Cain                     occSensorState, rspLength, instance)
850c9dc4418SChris Cain                     .c_str());
851c9dc4418SChris Cain             dump_hex(pldmResponse);
852c9dc4418SChris Cain         }
853bae4d07eSChris Cain     }
854bae4d07eSChris Cain 
855bae4d07eSChris Cain     return 0;
856bae4d07eSChris Cain };
857bae4d07eSChris Cain 
encodeGetStateSensorRequest(uint8_t instance,uint16_t sensorId)858bae4d07eSChris Cain std::vector<uint8_t> Interface::encodeGetStateSensorRequest(uint8_t instance,
859bae4d07eSChris Cain                                                             uint16_t sensorId)
860bae4d07eSChris Cain {
861*aeba51cdSRashmica Gupta     if (!getPldmInstanceId())
8628b508bfbSChris Cain     {
8638b508bfbSChris Cain         log<level::ERR>(
864*aeba51cdSRashmica Gupta             "encodeGetStateSensorRequest: failed to getPldmInstanceId");
8658b508bfbSChris Cain         return std::vector<uint8_t>();
8668b508bfbSChris Cain     }
8678b508bfbSChris Cain 
868bae4d07eSChris Cain     bitfield8_t sRearm = {0};
869a49c987eSPatrick Williams     const size_t msgSize = sizeof(pldm_msg_hdr) +
870a49c987eSPatrick Williams                            PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES;
871bae4d07eSChris Cain     std::vector<uint8_t> request(msgSize);
8728b508bfbSChris Cain 
873bae4d07eSChris Cain     auto msg = reinterpret_cast<pldm_msg*>(request.data());
874*aeba51cdSRashmica Gupta     auto msgRc = encode_get_state_sensor_readings_req(pldmInstanceID.value(),
8758b508bfbSChris Cain                                                       sensorId, sRearm, 0, msg);
876bae4d07eSChris Cain     if (msgRc != PLDM_SUCCESS)
877bae4d07eSChris Cain     {
878bae4d07eSChris Cain         log<level::ERR>(
87948002498SPatrick Williams             std::format(
880bae4d07eSChris Cain                 "encodeGetStateSensorRequest: Failed to encode sensorId:0x{:08X} for OCC{} (rc={})",
881bae4d07eSChris Cain                 sensorId, instance, msgRc)
882d1b6826aSChris Cain                 .c_str());
883d1b6826aSChris Cain     }
884bae4d07eSChris Cain     return request;
885bae4d07eSChris Cain }
886bae4d07eSChris Cain 
887bae4d07eSChris Cain // Initiate query of the specified OCC Active Sensor
checkActiveSensor(uint8_t instance)888bae4d07eSChris Cain void Interface::checkActiveSensor(uint8_t instance)
889bae4d07eSChris Cain {
890bae4d07eSChris Cain     static bool tracedOnce = false;
891bae4d07eSChris Cain     if (pldmFd > 0)
892bae4d07eSChris Cain     {
893755af102SChris Cain         if (!throttleTraces && !tracedOnce)
894bae4d07eSChris Cain         {
895755af102SChris Cain             log<level::WARNING>(
89648002498SPatrick Williams                 std::format(
897bae4d07eSChris Cain                     "checkActiveSensor: already waiting on OCC{} (fd={})",
898bae4d07eSChris Cain                     pldmResponseOcc, pldmFd)
899bae4d07eSChris Cain                     .c_str());
900bae4d07eSChris Cain             tracedOnce = true;
901bae4d07eSChris Cain         }
902bae4d07eSChris Cain         return;
903bae4d07eSChris Cain     }
904bae4d07eSChris Cain     tracedOnce = false;
905bae4d07eSChris Cain 
906bae4d07eSChris Cain     if (!isOCCSensorCacheValid())
907bae4d07eSChris Cain     {
908bae4d07eSChris Cain         fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
909bae4d07eSChris Cain                         sensorToOCCInstance, OCCSensorOffset);
910bae4d07eSChris Cain     }
911bae4d07eSChris Cain 
912bae4d07eSChris Cain     // look up sensor id (key) based on instance
913bae4d07eSChris Cain     auto entry = std::find_if(
914bae4d07eSChris Cain         sensorToOCCInstance.begin(), sensorToOCCInstance.end(),
915bae4d07eSChris Cain         [instance](const auto& entry) { return instance == entry.second; });
916bae4d07eSChris Cain     if (entry != sensorToOCCInstance.end())
917bae4d07eSChris Cain     {
918bae4d07eSChris Cain         // Query the OCC Active Sensor state for this instance
919755af102SChris Cain         if (!throttleTraces)
920755af102SChris Cain         {
921bae4d07eSChris Cain             log<level::INFO>(
92248002498SPatrick Williams                 std::format("checkActiveSensor: OCC{} / sensorID: 0x{:04X}",
923bae4d07eSChris Cain                             instance, entry->first)
924bae4d07eSChris Cain                     .c_str());
925755af102SChris Cain         }
926bae4d07eSChris Cain 
927bae4d07eSChris Cain         // Encode GetStateSensorReadings PLDM message
928bae4d07eSChris Cain         auto request = encodeGetStateSensorRequest(instance, entry->first);
929bae4d07eSChris Cain         if (request.empty())
930bae4d07eSChris Cain         {
931bae4d07eSChris Cain             return;
932bae4d07eSChris Cain         }
933bae4d07eSChris Cain 
934bae4d07eSChris Cain         // Send request to PLDM and setup callback for response
935bae4d07eSChris Cain         sendPldm(request, instance, true);
936bae4d07eSChris Cain     }
937bae4d07eSChris Cain     else
938bae4d07eSChris Cain     {
939755af102SChris Cain         if (!throttleTraces)
940755af102SChris Cain         {
941bae4d07eSChris Cain             log<level::ERR>(
94248002498SPatrick Williams                 std::format(
943bae4d07eSChris Cain                     "checkActiveSensor: Unable to find PLDM sensor for OCC{}",
944bae4d07eSChris Cain                     instance)
945bae4d07eSChris Cain                     .c_str());
9468cf7496bSChris Cain             log<level::INFO>(
9478cf7496bSChris Cain                 "checkActiveSensor: fetching STATE_SET_OPERATIONAL_RUNNING_STATUS");
948755af102SChris Cain         }
9498cf7496bSChris Cain         fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
9508cf7496bSChris Cain                         sensorToOCCInstance, OCCSensorOffset);
95100325238STom Joseph     }
95200325238STom Joseph }
95300325238STom Joseph 
setTraceThrottle(const bool throttle)954755af102SChris Cain void Interface::setTraceThrottle(const bool throttle)
955755af102SChris Cain {
956755af102SChris Cain     if (throttle != throttleTraces)
957755af102SChris Cain     {
958755af102SChris Cain         if (throttle)
959755af102SChris Cain         {
960755af102SChris Cain             log<level::WARNING>("PLDM traces being throttled");
961755af102SChris Cain         }
962755af102SChris Cain         else
963755af102SChris Cain         {
964755af102SChris Cain             log<level::INFO>("PLDM traces no longer being throttled");
965755af102SChris Cain         }
966755af102SChris Cain         throttleTraces = throttle;
967755af102SChris Cain     }
968755af102SChris Cain }
969755af102SChris Cain 
970815f9f55STom Joseph } // namespace pldm
971