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