blob: 5ee626a9754b7d80b576620f31841dde3612cba0 [file] [log] [blame]
Patrick Williams05e95592021-09-02 09:28:14 -05001#include "pldm.hpp"
2
Rashmica Guptadb38e912023-05-25 10:33:46 +10003#include "libpldm/instance-id.h"
4
Patrick Williams05e95592021-09-02 09:28:14 -05005#include "file.hpp"
6
Patrick Williams05e95592021-09-02 09:28:14 -05007#include <libpldm/entity.h>
Andrew Jeffery97476a12024-06-19 21:07:29 +09308#include <libpldm/oem/ibm/state_set.h>
Patrick Williams05e95592021-09-02 09:28:14 -05009#include <libpldm/platform.h>
10#include <libpldm/state_set.h>
11
12#include <phosphor-logging/log.hpp>
Chris Cainbae4d072022-02-28 09:46:50 -060013#include <sdbusplus/bus.hpp>
14#include <sdeventplus/clock.hpp>
15#include <sdeventplus/exception.hpp>
16#include <sdeventplus/source/io.hpp>
17#include <sdeventplus/source/time.hpp>
18
19#include <algorithm>
Patrick Williams48002492024-02-13 21:43:32 -060020#include <format>
Patrick Williams05e95592021-09-02 09:28:14 -050021
22namespace pldm
23{
24
Patrick Williams05e95592021-09-02 09:28:14 -050025using namespace phosphor::logging;
26
Chris Cainbae4d072022-02-28 09:46:50 -060027using namespace sdeventplus;
28using namespace sdeventplus::source;
29constexpr auto clockId = sdeventplus::ClockId::RealTime;
30using Clock = sdeventplus::Clock<clockId>;
31using Timer = Time<clockId>;
Chris Cain755af102024-02-27 16:09:51 -060032bool Interface::throttleTraces = false;
Chris Cainbae4d072022-02-28 09:46:50 -060033
Eddie Jamescbad2192021-10-07 09:39:39 -050034void Interface::fetchSensorInfo(uint16_t stateSetId,
35 SensorToInstance& sensorInstanceMap,
36 SensorOffset& sensorOffset)
Patrick Williams05e95592021-09-02 09:28:14 -050037{
Eddie Jamescbad2192021-10-07 09:39:39 -050038 PdrList pdrs{};
Chris Cainbae4d072022-02-28 09:46:50 -060039 static bool tracedError = false;
Eddie Jamescbad2192021-10-07 09:39:39 -050040
41 auto& bus = open_power::occ::utils::getBus();
42 try
43 {
44 auto method = bus.new_method_call(
45 "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
46 "xyz.openbmc_project.PLDM.PDR", "FindStateSensorPDR");
Chris Cainbae4d072022-02-28 09:46:50 -060047 method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId);
Eddie Jamescbad2192021-10-07 09:39:39 -050048
49 auto responseMsg = bus.call(method);
50 responseMsg.read(pdrs);
51 }
Patrick Williamsaf408082022-07-22 19:26:54 -050052 catch (const sdbusplus::exception_t& e)
Eddie Jamescbad2192021-10-07 09:39:39 -050053 {
Chris Cainbae4d072022-02-28 09:46:50 -060054 if (!tracedError)
55 {
56 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -060057 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -060058 "fetchSensorInfo: Failed to find stateSetID:{} PDR: {}",
59 stateSetId, e.what())
60 .c_str());
61 tracedError = true;
62 }
Eddie Jamescbad2192021-10-07 09:39:39 -050063 }
64
65 if (pdrs.empty())
66 {
Chris Cainbae4d072022-02-28 09:46:50 -060067 if (!tracedError)
68 {
69 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -060070 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -060071 "fetchSensorInfo: state sensor PDRs ({}) not present",
72 stateSetId)
73 .c_str());
74 tracedError = true;
75 }
Eddie Jamescbad2192021-10-07 09:39:39 -050076 return;
77 }
78
Chris Cainbae4d072022-02-28 09:46:50 -060079 // Found PDR
80 if (tracedError)
81 {
82 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -060083 std::format("fetchSensorInfo: found {} PDRs", pdrs.size()).c_str());
Chris Cainbae4d072022-02-28 09:46:50 -060084 tracedError = false;
85 }
86
Patrick Williams05e95592021-09-02 09:28:14 -050087 bool offsetFound = false;
George Liuf3a4a692021-12-28 13:59:51 +080088 auto stateSensorPDR =
Patrick Williams05e95592021-09-02 09:28:14 -050089 reinterpret_cast<const pldm_state_sensor_pdr*>(pdrs.front().data());
George Liuf3a4a692021-12-28 13:59:51 +080090 auto possibleStatesPtr = stateSensorPDR->possible_states;
91 for (auto offset = 0; offset < stateSensorPDR->composite_sensor_count;
92 offset++)
Patrick Williams05e95592021-09-02 09:28:14 -050093 {
94 auto possibleStates =
95 reinterpret_cast<const state_sensor_possible_states*>(
96 possibleStatesPtr);
97
Eddie Jamescbad2192021-10-07 09:39:39 -050098 if (possibleStates->state_set_id == stateSetId)
Patrick Williams05e95592021-09-02 09:28:14 -050099 {
100 sensorOffset = offset;
101 offsetFound = true;
102 break;
103 }
104 possibleStatesPtr += sizeof(possibleStates->state_set_id) +
105 sizeof(possibleStates->possible_states_size) +
106 possibleStates->possible_states_size;
107 }
108
109 if (!offsetFound)
110 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500111 log<level::ERR>("pldm: state sensor PDR not found");
Patrick Williams05e95592021-09-02 09:28:14 -0500112 return;
113 }
114
115 // To order SensorID based on the EntityInstance.
116 // Note that when a proc is on a DCM, the PDRs for these sensors
117 // could have the same instance IDs but different container IDs.
118 std::map<uint32_t, SensorID> entityInstMap{};
119 for (auto& pdr : pdrs)
120 {
121 auto pdrPtr =
122 reinterpret_cast<const pldm_state_sensor_pdr*>(pdr.data());
Chris Cain72d01aa2022-06-14 16:28:03 -0500123 uint32_t key = pdrPtr->sensor_id;
Patrick Williams05e95592021-09-02 09:28:14 -0500124 entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->sensor_id));
125 }
126
127 open_power::occ::instanceID count = start;
Patrick Williamsa49c9872023-05-10 07:50:35 -0500128 for (const auto& pair : entityInstMap)
Patrick Williams05e95592021-09-02 09:28:14 -0500129 {
130 sensorInstanceMap.emplace(pair.second, count);
131 count++;
132 }
133}
134
Patrick Williamsaf408082022-07-22 19:26:54 -0500135void Interface::sensorEvent(sdbusplus::message_t& msg)
Patrick Williams05e95592021-09-02 09:28:14 -0500136{
137 if (!isOCCSensorCacheValid())
138 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500139 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
140 sensorToOCCInstance, OCCSensorOffset);
141 }
Patrick Williams05e95592021-09-02 09:28:14 -0500142
Eddie Jamescbad2192021-10-07 09:39:39 -0500143 if (sensorToSBEInstance.empty())
144 {
145 fetchSensorInfo(PLDM_OEM_IBM_SBE_HRESET_STATE, sensorToSBEInstance,
146 SBESensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -0500147 }
148
Chris Cain72d01aa2022-06-14 16:28:03 -0500149 TerminusID sensorTid{};
Patrick Williams05e95592021-09-02 09:28:14 -0500150 SensorID sensorId{};
151 SensorOffset msgSensorOffset{};
152 EventState eventState{};
153 EventState previousEventState{};
154
Chris Cain72d01aa2022-06-14 16:28:03 -0500155 msg.read(sensorTid, sensorId, msgSensorOffset, eventState,
156 previousEventState);
Patrick Williams05e95592021-09-02 09:28:14 -0500157
Eddie Jamescbad2192021-10-07 09:39:39 -0500158 if (msgSensorOffset == OCCSensorOffset)
Patrick Williams05e95592021-09-02 09:28:14 -0500159 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500160 auto sensorEntry = sensorToOCCInstance.find(sensorId);
Patrick Williams05e95592021-09-02 09:28:14 -0500161
Eddie James432dc482021-11-19 15:29:31 -0600162 if (sensorEntry != sensorToOCCInstance.end())
Eddie Jamescbad2192021-10-07 09:39:39 -0500163 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500164 const uint8_t instance = sensorEntry->second;
Chris Cain755af102024-02-27 16:09:51 -0600165 bool validEvent = true;
Chris Cain7b00cde2023-03-14 15:47:12 -0500166 bool isRunning = false;
Eddie James432dc482021-11-19 15:29:31 -0600167 if (eventState ==
168 static_cast<EventState>(
169 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE))
170 {
171 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600172 std::format("PLDM: OCC{} is RUNNING", instance).c_str());
Chris Cain7b00cde2023-03-14 15:47:12 -0500173 isRunning = true;
Eddie James432dc482021-11-19 15:29:31 -0600174 }
175 else if (eventState ==
176 static_cast<EventState>(
177 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED))
178 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500179 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600180 std::format("PLDM: OCC{} has now STOPPED", instance)
Chris Cain8b508bf2022-05-26 14:01:31 -0500181 .c_str());
Eddie James432dc482021-11-19 15:29:31 -0600182 }
Chris Cainbae4d072022-02-28 09:46:50 -0600183 else if (eventState ==
184 static_cast<EventState>(
185 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT))
186 {
Chris Cain755af102024-02-27 16:09:51 -0600187 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600188 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600189 "PLDM: OCC{} has now STOPPED and system is in SAFE MODE",
Chris Cain8b508bf2022-05-26 14:01:31 -0500190 instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600191 .c_str());
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500192
193 // Setting safe mode true
194 safeModeCallBack(true);
Chris Cainbae4d072022-02-28 09:46:50 -0600195 }
196 else
197 {
Chris Cain755af102024-02-27 16:09:51 -0600198 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -0600199 std::format("PLDM: Unexpected PLDM state {} for OCC{}",
Chris Cain8b508bf2022-05-26 14:01:31 -0500200 eventState, instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600201 .c_str());
Chris Cain755af102024-02-27 16:09:51 -0600202 validEvent = false;
Chris Cainbae4d072022-02-28 09:46:50 -0600203 }
Chris Cain755af102024-02-27 16:09:51 -0600204 if (validEvent)
205 {
206 if ((pldmFd > 0) && (instance == pldmResponseOcc))
207 {
208 // Waiting for a response for this OCC, can stop waiting
209 pldmClose();
210 }
211 callBack(instance, isRunning);
212 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500213 return;
214 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500215 }
Eddie James432dc482021-11-19 15:29:31 -0600216
217 if (msgSensorOffset == SBESensorOffset)
Eddie Jamescbad2192021-10-07 09:39:39 -0500218 {
219 auto sensorEntry = sensorToSBEInstance.find(sensorId);
220
Eddie James432dc482021-11-19 15:29:31 -0600221 if (sensorEntry != sensorToSBEInstance.end())
Eddie Jamescbad2192021-10-07 09:39:39 -0500222 {
Chris Cain12d0b822022-04-22 17:29:18 -0500223 const uint8_t instance = sensorEntry->second;
224 auto match = std::find(outstandingHResets.begin(),
225 outstandingHResets.end(), instance);
226 if (match != outstandingHResets.end())
Eddie James432dc482021-11-19 15:29:31 -0600227 {
Chris Cain12d0b822022-04-22 17:29:18 -0500228 outstandingHResets.erase(match);
229 if (eventState == static_cast<EventState>(SBE_HRESET_NOT_READY))
230 {
231 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600232 std::format("pldm: HRESET is NOT READY (OCC{})",
Chris Cain12d0b822022-04-22 17:29:18 -0500233 instance)
234 .c_str());
235 }
236 else if (eventState ==
237 static_cast<EventState>(SBE_HRESET_READY))
238 {
239 sbeCallBack(instance, true);
240 }
241 else if (eventState ==
242 static_cast<EventState>(SBE_HRESET_FAILED))
243 {
244 sbeCallBack(instance, false);
245 }
Eddie James432dc482021-11-19 15:29:31 -0600246 }
Chris Cain12d0b822022-04-22 17:29:18 -0500247 // else request was not from us
Eddie Jamescbad2192021-10-07 09:39:39 -0500248 }
249 }
Patrick Williams05e95592021-09-02 09:28:14 -0500250}
251
Patrick Williamsaf408082022-07-22 19:26:54 -0500252void Interface::hostStateEvent(sdbusplus::message_t& msg)
Chris Cain157467d2022-06-24 11:25:23 -0500253{
254 std::map<std::string, std::variant<std::string>> properties{};
255 std::string interface;
256 msg.read(interface, properties);
257 const auto stateEntry = properties.find("CurrentHostState");
258 if (stateEntry != properties.end())
259 {
260 auto stateEntryValue = stateEntry->second;
261 auto propVal = std::get<std::string>(stateEntryValue);
262 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
263 {
264 clearData();
265 }
266 }
267}
268
Chris Cainbae4d072022-02-28 09:46:50 -0600269void Interface::clearData()
270{
Chris Cain72d01aa2022-06-14 16:28:03 -0500271 if (!sensorToOCCInstance.empty())
272 {
273 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600274 std::format("clearData: Clearing sensorToOCCInstance ({} entries)",
Chris Cain72d01aa2022-06-14 16:28:03 -0500275 sensorToOCCInstance.size())
276 .c_str());
277 for (auto entry : sensorToOCCInstance)
278 {
279 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600280 std::format("clearData: OCC{} / sensorID: 0x{:04X}",
Chris Cain72d01aa2022-06-14 16:28:03 -0500281 entry.second, entry.first)
282 .c_str());
Chris Cain082a6ca2023-03-21 10:27:26 -0500283 callBack(entry.second, false);
Chris Cain72d01aa2022-06-14 16:28:03 -0500284 }
285 sensorToOCCInstance.clear();
286 }
287 if (!occInstanceToEffecter.empty())
288 {
289 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600290 std::format(
Chris Cain72d01aa2022-06-14 16:28:03 -0500291 "clearData: Clearing occInstanceToEffecter ({} entries)",
292 occInstanceToEffecter.size())
293 .c_str());
294 occInstanceToEffecter.clear();
295 }
296 if (!sensorToSBEInstance.empty())
297 {
298 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600299 std::format("clearData: Clearing sensorToSBEInstance ({} entries)",
Chris Cain72d01aa2022-06-14 16:28:03 -0500300 sensorToSBEInstance.size())
301 .c_str());
302 sensorToSBEInstance.clear();
303 }
304 if (!sbeInstanceToEffecter.empty())
305 {
306 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600307 std::format(
Chris Cain72d01aa2022-06-14 16:28:03 -0500308 "clearData: Clearing sbeInstanceToEffecter ({} entries)",
309 sbeInstanceToEffecter.size())
310 .c_str());
311 sbeInstanceToEffecter.clear();
312 }
Chris Cainbae4d072022-02-28 09:46:50 -0600313}
314
Eddie James432dc482021-11-19 15:29:31 -0600315void Interface::fetchEffecterInfo(uint16_t stateSetId,
Eddie Jamescbad2192021-10-07 09:39:39 -0500316 InstanceToEffecter& instanceToEffecterMap,
317 CompositeEffecterCount& effecterCount,
318 uint8_t& stateIdPos)
Patrick Williams05e95592021-09-02 09:28:14 -0500319{
Eddie Jamescbad2192021-10-07 09:39:39 -0500320 PdrList pdrs{};
321
322 auto& bus = open_power::occ::utils::getBus();
323 try
324 {
325 auto method = bus.new_method_call(
326 "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
327 "xyz.openbmc_project.PLDM.PDR", "FindStateEffecterPDR");
Chris Cainbae4d072022-02-28 09:46:50 -0600328 method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId);
Eddie Jamescbad2192021-10-07 09:39:39 -0500329
330 auto responseMsg = bus.call(method);
331 responseMsg.read(pdrs);
332 }
Patrick Williamsaf408082022-07-22 19:26:54 -0500333 catch (const sdbusplus::exception_t& e)
Eddie Jamescbad2192021-10-07 09:39:39 -0500334 {
335 log<level::ERR>("pldm: Failed to fetch the state effecter PDRs",
336 entry("ERROR=%s", e.what()));
337 }
338
339 if (!pdrs.size())
340 {
341 log<level::ERR>("pldm: state effecter PDRs not present");
342 return;
343 }
344
Patrick Williams05e95592021-09-02 09:28:14 -0500345 bool offsetFound = false;
George Liuf3a4a692021-12-28 13:59:51 +0800346 auto stateEffecterPDR =
Patrick Williams05e95592021-09-02 09:28:14 -0500347 reinterpret_cast<const pldm_state_effecter_pdr*>(pdrs.front().data());
George Liuf3a4a692021-12-28 13:59:51 +0800348 auto possibleStatesPtr = stateEffecterPDR->possible_states;
349 for (auto offset = 0; offset < stateEffecterPDR->composite_effecter_count;
350 offset++)
Patrick Williams05e95592021-09-02 09:28:14 -0500351 {
352 auto possibleStates =
353 reinterpret_cast<const state_effecter_possible_states*>(
354 possibleStatesPtr);
355
Eddie Jamescbad2192021-10-07 09:39:39 -0500356 if (possibleStates->state_set_id == stateSetId)
Patrick Williams05e95592021-09-02 09:28:14 -0500357 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500358 stateIdPos = offset;
George Liuf3a4a692021-12-28 13:59:51 +0800359 effecterCount = stateEffecterPDR->composite_effecter_count;
Patrick Williams05e95592021-09-02 09:28:14 -0500360 offsetFound = true;
361 break;
362 }
363 possibleStatesPtr += sizeof(possibleStates->state_set_id) +
364 sizeof(possibleStates->possible_states_size) +
365 possibleStates->possible_states_size;
366 }
367
368 if (!offsetFound)
369 {
370 return;
371 }
372
Chris Cain0f516522022-02-07 14:48:28 -0600373 std::map<uint32_t, EffecterID> entityInstMap{};
Patrick Williams05e95592021-09-02 09:28:14 -0500374 for (auto& pdr : pdrs)
375 {
376 auto pdrPtr =
377 reinterpret_cast<const pldm_state_effecter_pdr*>(pdr.data());
Chris Cain72d01aa2022-06-14 16:28:03 -0500378 uint32_t key = pdrPtr->effecter_id;
Patrick Williams05e95592021-09-02 09:28:14 -0500379 entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->effecter_id));
380 }
381
382 open_power::occ::instanceID position = start;
Patrick Williamsa49c9872023-05-10 07:50:35 -0500383 for (const auto& pair : entityInstMap)
Patrick Williams05e95592021-09-02 09:28:14 -0500384 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500385 instanceToEffecterMap.emplace(position, pair.second);
Patrick Williams05e95592021-09-02 09:28:14 -0500386 position++;
387 }
388}
389
390std::vector<uint8_t>
Chris Cain8b508bf2022-05-26 14:01:31 -0500391 Interface::prepareSetEffecterReq(EffecterID effecterId,
Patrick Williams05e95592021-09-02 09:28:14 -0500392 CompositeEffecterCount effecterCount,
Eddie Jamescbad2192021-10-07 09:39:39 -0500393 uint8_t stateIdPos, uint8_t stateSetValue)
Patrick Williams05e95592021-09-02 09:28:14 -0500394{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100395 if (!getPldmInstanceId())
Chris Cain8b508bf2022-05-26 14:01:31 -0500396 {
397 return std::vector<uint8_t>();
398 }
399
Patrick Williams05e95592021-09-02 09:28:14 -0500400 std::vector<uint8_t> request(
401 sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(effecterCount) +
402 (effecterCount * sizeof(set_effecter_state_field)));
403 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
404 std::vector<set_effecter_state_field> stateField;
405
406 for (uint8_t effecterPos = 0; effecterPos < effecterCount; effecterPos++)
407 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500408 if (effecterPos == stateIdPos)
Patrick Williams05e95592021-09-02 09:28:14 -0500409 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500410 stateField.emplace_back(
411 set_effecter_state_field{PLDM_REQUEST_SET, stateSetValue});
Patrick Williams05e95592021-09-02 09:28:14 -0500412 }
413 else
414 {
415 stateField.emplace_back(
416 set_effecter_state_field{PLDM_NO_CHANGE, 0});
417 }
418 }
419 auto rc = encode_set_state_effecter_states_req(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100420 pldmInstanceID.value(), effecterId, effecterCount, stateField.data(),
Chris Cain8b508bf2022-05-26 14:01:31 -0500421 requestMsg);
Patrick Williams05e95592021-09-02 09:28:14 -0500422 if (rc != PLDM_SUCCESS)
423 {
424 log<level::ERR>("encode set effecter states request returned error ",
425 entry("RC=%d", rc));
426 request.clear();
427 }
428 return request;
429}
430
431void Interface::resetOCC(open_power::occ::instanceID occInstanceId)
432{
Chris Cainbae4d072022-02-28 09:46:50 -0600433 if (open_power::occ::utils::isHostRunning())
Patrick Williams05e95592021-09-02 09:28:14 -0500434 {
Chris Cainbae4d072022-02-28 09:46:50 -0600435 if (!isPDREffecterCacheValid())
436 {
437 fetchEffecterInfo(PLDM_STATE_SET_BOOT_RESTART_CAUSE,
438 occInstanceToEffecter, OCCEffecterCount,
439 bootRestartPosition);
440 }
Patrick Williams05e95592021-09-02 09:28:14 -0500441
Chris Cainbae4d072022-02-28 09:46:50 -0600442 // Find the matching effecter for the OCC instance
443 auto effecterEntry = occInstanceToEffecter.find(occInstanceId);
444 if (effecterEntry == occInstanceToEffecter.end())
445 {
446 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600447 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600448 "pldm: Failed to find a matching effecter for OCC instance {}",
449 occInstanceId)
450 .c_str());
451
452 return;
453 }
454
Chris Cainbae4d072022-02-28 09:46:50 -0600455 // Prepare the SetStateEffecterStates request to reset the OCC
456 auto request = prepareSetEffecterReq(
Chris Cain8b508bf2022-05-26 14:01:31 -0500457 effecterEntry->second, OCCEffecterCount, bootRestartPosition,
458 PLDM_STATE_SET_BOOT_RESTART_CAUSE_WARM_RESET);
Chris Cainbae4d072022-02-28 09:46:50 -0600459
460 if (request.empty())
461 {
462 log<level::ERR>(
463 "pldm: SetStateEffecterStates OCC reset request empty");
464 return;
465 }
466
467 // Send request to reset the OCCs/PM Complex (ignore response)
468 sendPldm(request, occInstanceId, false);
469 }
470 else
Patrick Williams05e95592021-09-02 09:28:14 -0500471 {
472 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600473 std::format("resetOCC: HOST is not running (OCC{})", occInstanceId)
Chris Cain0f516522022-02-07 14:48:28 -0600474 .c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600475 clearData();
Patrick Williams05e95592021-09-02 09:28:14 -0500476 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500477}
478
479void Interface::sendHRESET(open_power::occ::instanceID sbeInstanceId)
480{
Chris Cainbae4d072022-02-28 09:46:50 -0600481 if (open_power::occ::utils::isHostRunning())
Eddie Jamescbad2192021-10-07 09:39:39 -0500482 {
Chris Cainbae4d072022-02-28 09:46:50 -0600483 if (sbeInstanceToEffecter.empty())
484 {
485 fetchEffecterInfo(PLDM_OEM_IBM_SBE_MAINTENANCE_STATE,
486 sbeInstanceToEffecter, SBEEffecterCount,
487 sbeMaintenanceStatePosition);
488 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500489
Chris Cainbae4d072022-02-28 09:46:50 -0600490 auto effecterEntry = sbeInstanceToEffecter.find(sbeInstanceId);
491 if (effecterEntry == sbeInstanceToEffecter.end())
492 {
493 log<level::ERR>(
494 "pldm: Failed to find a matching effecter for SBE instance",
495 entry("SBE=%d", sbeInstanceId));
496 return;
497 }
498
Chris Cainbae4d072022-02-28 09:46:50 -0600499 // Prepare the SetStateEffecterStates request to HRESET the SBE
500 auto request = prepareSetEffecterReq(
Chris Cain8b508bf2022-05-26 14:01:31 -0500501 effecterEntry->second, SBEEffecterCount,
Chris Cainbae4d072022-02-28 09:46:50 -0600502 sbeMaintenanceStatePosition, SBE_RETRY_REQUIRED);
503
504 if (request.empty())
505 {
506 log<level::ERR>(
507 "pldm: SetStateEffecterStates HRESET request empty");
508 return;
509 }
510
511 // Send request to issue HRESET of SBE (ignore response)
512 sendPldm(request, sbeInstanceId, false);
Chris Cain12d0b822022-04-22 17:29:18 -0500513 outstandingHResets.insert(sbeInstanceId);
Chris Cainbae4d072022-02-28 09:46:50 -0600514 }
515 else
Eddie Jamescbad2192021-10-07 09:39:39 -0500516 {
Patrick Williams48002492024-02-13 21:43:32 -0600517 log<level::ERR>(std::format("sendHRESET: HOST is not running (OCC{})",
Chris Cainbae4d072022-02-28 09:46:50 -0600518 sbeInstanceId)
519 .c_str());
520 clearData();
Eddie Jamescbad2192021-10-07 09:39:39 -0500521 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500522}
523
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100524bool Interface::getPldmInstanceId()
Eddie Jamescbad2192021-10-07 09:39:39 -0500525{
Rashmica Guptadb38e912023-05-25 10:33:46 +1000526 pldm_instance_id_t id;
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100527 if (!pldmInstanceID)
Patrick Williams05e95592021-09-02 09:28:14 -0500528 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500529 // Request new instance ID
Rashmica Guptadb38e912023-05-25 10:33:46 +1000530 int rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
531 if (rc == -EAGAIN)
Chris Cain8b508bf2022-05-26 14:01:31 -0500532 {
Rashmica Guptadb38e912023-05-25 10:33:46 +1000533 std::this_thread::sleep_for(std::chrono::milliseconds(100));
534 rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
Chris Cain8b508bf2022-05-26 14:01:31 -0500535 }
Rashmica Guptadb38e912023-05-25 10:33:46 +1000536
537 if (rc)
Chris Cain8b508bf2022-05-26 14:01:31 -0500538 {
539 log<level::ERR>(
Rashmica Guptadb38e912023-05-25 10:33:46 +1000540 std::format(
541 "getPldmInstanceId: Failed to alloc ID for TID {}. RC{}",
542 tid, rc)
Chris Cain8b508bf2022-05-26 14:01:31 -0500543 .c_str());
544 return false;
545 }
Rashmica Guptadb38e912023-05-25 10:33:46 +1000546 pldmInstanceID.emplace(id);
547 if (!throttleTraces)
548 {
549 log<level::INFO>(
550 std::format("got id {} and set PldmInstanceId to {}", id,
551 pldmInstanceID.value())
552 .c_str());
553 }
Patrick Williams05e95592021-09-02 09:28:14 -0500554 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500555 return true;
556}
Patrick Williams05e95592021-09-02 09:28:14 -0500557
Rashmica Guptadb38e912023-05-25 10:33:46 +1000558void Interface::freePldmInstanceId()
559{
560 if (pldmInstanceID)
561 {
562 int rc = pldm_instance_id_free(pldmInstanceIdDb, tid,
563 pldmInstanceID.value());
564 if (rc)
565 {
566 log<level::ERR>(
567 std::format(
568 "freePldmInstanceId: Failed to free ID {} for TID {}. RC{}",
569 pldmInstanceID.value(), tid, rc)
570 .c_str());
571 return;
572 }
573 if (!throttleTraces)
574 {
575 log<level::INFO>(
576 std::format("Freed PLDM instance ID {}", pldmInstanceID.value())
577 .c_str());
578 }
579 pldmInstanceID = std::nullopt;
580 }
581}
582
Chris Cainbae4d072022-02-28 09:46:50 -0600583void Interface::sendPldm(const std::vector<uint8_t>& request,
584 const uint8_t instance, const bool rspExpected)
Eddie Jamescbad2192021-10-07 09:39:39 -0500585{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100586 if (!pldmInstanceID)
Chris Cain8b508bf2022-05-26 14:01:31 -0500587 {
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100588 log<level::ERR>("sendPldm: No PLDM Instance ID found!");
Chris Cain8b508bf2022-05-26 14:01:31 -0500589 return;
590 }
591
Chris Cainc9dc4412023-03-06 15:56:34 -0600592 // Connect to MCTP socket
Chris Cainbae4d072022-02-28 09:46:50 -0600593 pldmFd = pldm_open();
594 auto openErrno = errno;
595 if (pldmFd == PLDM_REQUESTER_OPEN_FAIL)
Patrick Williams05e95592021-09-02 09:28:14 -0500596 {
Chris Caind1b68262022-02-28 09:56:50 -0600597 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600598 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600599 "sendPldm: Failed to connect to MCTP socket, errno={}/{}",
600 openErrno, strerror(openErrno))
Chris Caind1b68262022-02-28 09:56:50 -0600601 .c_str());
Rashmica Guptadb38e912023-05-25 10:33:46 +1000602 freePldmInstanceId();
Patrick Williams05e95592021-09-02 09:28:14 -0500603 return;
604 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500605
Patrick Williams05e95592021-09-02 09:28:14 -0500606 // Send the PLDM request message to HBRT
Chris Cainbae4d072022-02-28 09:46:50 -0600607 if (rspExpected)
Patrick Williams05e95592021-09-02 09:28:14 -0500608 {
Chris Cainbae4d072022-02-28 09:46:50 -0600609 // Register callback when response is available
610 registerPldmRspCallback();
611
612 // Send PLDM request
Chris Cain755af102024-02-27 16:09:51 -0600613 if (!throttleTraces)
614 {
615 log<level::INFO>(
616 std::format(
617 "sendPldm: calling pldm_send(OCC{}, instance:{}, {} bytes)",
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100618 instance, pldmInstanceID.value(), request.size())
Chris Cain755af102024-02-27 16:09:51 -0600619 .c_str());
620 }
Chris Cainbae4d072022-02-28 09:46:50 -0600621 pldmResponseReceived = false;
622 pldmResponseTimeout = false;
623 pldmResponseOcc = instance;
Patrick Williamsa49c9872023-05-10 07:50:35 -0500624 auto pldmRc = pldm_send(mctpEid, pldmFd, request.data(),
625 request.size());
Chris Cainbae4d072022-02-28 09:46:50 -0600626 auto sendErrno = errno;
627 if (pldmRc != PLDM_REQUESTER_SUCCESS)
628 {
629 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600630 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600631 "sendPldm: pldm_send failed with rc={} and errno={}/{}",
Chris Cain5161a022023-08-15 10:07:12 -0500632 static_cast<
633 std::underlying_type_t<pldm_requester_error_codes>>(
634 pldmRc),
635 sendErrno, strerror(sendErrno))
Chris Cainbae4d072022-02-28 09:46:50 -0600636 .c_str());
637 pldmClose();
638 return;
639 }
640
641 // start timer waiting for the response
642 using namespace std::literals::chrono_literals;
Chris Cainbd551de2022-04-26 13:41:16 -0500643 pldmRspTimer.restartOnce(8s);
Chris Cainbae4d072022-02-28 09:46:50 -0600644
645 // Wait for response/timeout
646 }
647 else // not expecting the response
648 {
Chris Cain755af102024-02-27 16:09:51 -0600649 if (!throttleTraces)
650 {
651 log<level::INFO>(
652 std::format(
653 "sendPldm: calling pldm_send(mctpID:{}, fd:{}, {} bytes) for OCC{}",
654 mctpEid, pldmFd, request.size(), instance)
655 .c_str());
656 }
Chris Cainbae4d072022-02-28 09:46:50 -0600657 auto rc = pldm_send(mctpEid, pldmFd, request.data(), request.size());
658 auto sendErrno = errno;
Chris Caind1b68262022-02-28 09:56:50 -0600659 if (rc)
660 {
661 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600662 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600663 "sendPldm: pldm_send(mctpID:{}, fd:{}, {} bytes) failed with rc={} and errno={}/{}",
Chris Cain5161a022023-08-15 10:07:12 -0500664 mctpEid, pldmFd, request.size(),
665 static_cast<
666 std::underlying_type_t<pldm_requester_error_codes>>(rc),
667 sendErrno, strerror(sendErrno))
Chris Caind1b68262022-02-28 09:56:50 -0600668 .c_str());
669 }
Chris Cainbae4d072022-02-28 09:46:50 -0600670 pldmClose();
671 }
672}
Patrick Williams05e95592021-09-02 09:28:14 -0500673
Chris Cainbae4d072022-02-28 09:46:50 -0600674// Attaches the FD to event loop and registers the callback handler
675void Interface::registerPldmRspCallback()
676{
677 decltype(eventSource.get()) sourcePtr = nullptr;
678 auto rc = sd_event_add_io(event.get(), &sourcePtr, pldmFd, EPOLLIN,
679 pldmRspCallback, this);
680 if (rc < 0)
681 {
682 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600683 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600684 "registerPldmRspCallback: sd_event_add_io: Error({})={} : fd={}",
685 rc, strerror(-rc), pldmFd)
686 .c_str());
Chris Caind1b68262022-02-28 09:56:50 -0600687 }
688 else
Patrick Williams05e95592021-09-02 09:28:14 -0500689 {
Chris Cainbae4d072022-02-28 09:46:50 -0600690 // puts sourcePtr in the event source.
691 eventSource.reset(sourcePtr);
692 }
693}
694
695// Add a timer to the event loop, default 30s.
696void Interface::pldmRspExpired()
697{
698 if (!pldmResponseReceived)
699 {
Chris Cain755af102024-02-27 16:09:51 -0600700 if (!throttleTraces)
701 {
702 log<level::WARNING>(
703 std::format(
704 "pldmRspExpired: timerCallback - timeout waiting for pldm response for OCC{}",
705 pldmResponseOcc)
706 .c_str());
707 }
Chris Cainbae4d072022-02-28 09:46:50 -0600708 pldmResponseTimeout = true;
709 if (pldmFd)
710 {
711 pldmClose();
712 }
713 }
714 return;
715};
716
717void Interface::pldmClose()
718{
Rashmica Guptadb38e912023-05-25 10:33:46 +1000719 freePldmInstanceId();
Chris Cainbae4d072022-02-28 09:46:50 -0600720 if (pldmRspTimer.isEnabled())
721 {
722 // stop PLDM response timer
723 pldmRspTimer.setEnabled(false);
724 }
Pavithra Barithaya159a2272023-09-27 06:10:55 -0500725 pldm_close();
Chris Cainbae4d072022-02-28 09:46:50 -0600726 pldmFd = -1;
727 eventSource.reset();
728}
729
730int Interface::pldmRspCallback(sd_event_source* /*es*/, int fd,
731 uint32_t revents, void* userData)
732{
733 if (!(revents & EPOLLIN))
734 {
735 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600736 std::format("pldmRspCallback - revents={:08X}", revents).c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600737 return -1;
738 }
739
740 auto pldmIface = static_cast<Interface*>(userData);
741
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100742 if (!pldmIface->pldmInstanceID)
Chris Cain8b508bf2022-05-26 14:01:31 -0500743 {
744 log<level::ERR>(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100745 "pldmRspCallback: No outstanding PLDM Instance ID found");
Chris Cain8b508bf2022-05-26 14:01:31 -0500746 return -1;
747 }
748
Chris Cainbae4d072022-02-28 09:46:50 -0600749 uint8_t* responseMsg = nullptr;
750 size_t responseMsgSize{};
751
Chris Cain755af102024-02-27 16:09:51 -0600752 if (!throttleTraces)
753 {
754 log<level::INFO>(
755 std::format("pldmRspCallback: calling pldm_recv() instance:{}",
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100756 pldmIface->pldmInstanceID.value())
Chris Cain755af102024-02-27 16:09:51 -0600757 .c_str());
758 }
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100759 auto rc = pldm_recv(mctpEid, fd, pldmIface->pldmInstanceID.value(),
Chris Cain8b508bf2022-05-26 14:01:31 -0500760 &responseMsg, &responseMsgSize);
Chris Cainbae4d072022-02-28 09:46:50 -0600761 int lastErrno = errno;
762 if (rc)
763 {
Chris Cain755af102024-02-27 16:09:51 -0600764 if (!throttleTraces)
765 {
766 log<level::ERR>(
767 std::format(
768 "pldmRspCallback: pldm_recv failed with rc={}, errno={}/{}",
769 static_cast<
770 std::underlying_type_t<pldm_requester_error_codes>>(rc),
771 lastErrno, strerror(lastErrno))
772 .c_str());
773 }
Chris Cainbae4d072022-02-28 09:46:50 -0600774 return -1;
775 }
Chris Cain8b508bf2022-05-26 14:01:31 -0500776
777 // We got the response for the PLDM request msg that was sent
Chris Cain755af102024-02-27 16:09:51 -0600778 if (!throttleTraces)
779 {
780 log<level::INFO>(
781 std::format("pldmRspCallback: pldm_recv() rsp was {} bytes",
782 responseMsgSize)
783 .c_str());
784 }
Chris Cainbae4d072022-02-28 09:46:50 -0600785
786 if (pldmIface->pldmRspTimer.isEnabled())
787 {
788 // stop PLDM response timer
789 pldmIface->pldmRspTimer.setEnabled(false);
790 }
791
Chris Cain8b508bf2022-05-26 14:01:31 -0500792 // instance ID should be freed
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100793 pldmIface->pldmInstanceID = std::nullopt;
Chris Cain8b508bf2022-05-26 14:01:31 -0500794
Chris Cainbae4d072022-02-28 09:46:50 -0600795 // Set pointer to autodelete
796 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{responseMsg,
797 std::free};
798
Chris Cainbae4d072022-02-28 09:46:50 -0600799 auto response = reinterpret_cast<pldm_msg*>(responseMsgPtr.get());
800 if (response->payload[0] != PLDM_SUCCESS)
801 {
802 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600803 std::format("pldmRspCallback: payload[0] was not success: {}",
Chris Cainbae4d072022-02-28 09:46:50 -0600804 response->payload[0])
805 .c_str());
806 pldmIface->pldmClose();
807 return -1;
808 }
809
810 // Decode the response
811 uint8_t compCode = 0, sensorCount = 1;
812 get_sensor_state_field field[6];
813 responseMsgSize -= sizeof(pldm_msg_hdr);
814 auto msgRc = decode_get_state_sensor_readings_resp(
815 response, responseMsgSize, &compCode, &sensorCount, field);
816 if ((msgRc != PLDM_SUCCESS) || (compCode != PLDM_SUCCESS))
817 {
818 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600819 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600820 "pldmRspCallback: decode_get_state_sensor_readings failed with rc={} and compCode={}",
821 msgRc, compCode)
822 .c_str());
823 pldmIface->pldmClose();
824 return -1;
825 }
826
827 pldmIface->pldmClose();
828
829 const uint8_t instance = pldmIface->pldmResponseOcc;
830 const uint8_t occSensorState = field[0].present_state;
831 pldmIface->pldmResponseReceived = true;
832
833 if (occSensorState == PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE)
834 {
835 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600836 std::format("pldmRspCallback: OCC{} is RUNNING", instance).c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600837 pldmIface->callBack(instance, true);
838 }
Chris Cain733b2012022-05-04 11:54:06 -0500839 else if (occSensorState ==
840 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT)
841 {
Chris Cain755af102024-02-27 16:09:51 -0600842 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600843 std::format(
Chris Cain733b2012022-05-04 11:54:06 -0500844 "pldmRspCallback: OCC{} has now STOPPED and system is in SAFE MODE",
845 instance)
846 .c_str());
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500847
848 // Setting safe mode true
849 pldmIface->safeModeCallBack(true);
850
Chris Cain733b2012022-05-04 11:54:06 -0500851 pldmIface->callBack(instance, false);
852 }
Chris Cain755af102024-02-27 16:09:51 -0600853 else if (occSensorState ==
854 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED)
Chris Cainbae4d072022-02-28 09:46:50 -0600855 {
856 log<level::INFO>(
Chris Cain755af102024-02-27 16:09:51 -0600857 std::format("pldmRspCallback: OCC{} is not running", instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600858 .c_str());
Chris Cain755af102024-02-27 16:09:51 -0600859 pldmIface->callBack(instance, false);
860 }
861 else
862 {
863 const size_t rspLength = responseMsgSize + sizeof(pldm_msg_hdr);
864 std::vector<std::uint8_t> pldmResponse(rspLength);
865 memcpy(&pldmResponse[0], reinterpret_cast<std::uint8_t*>(response),
866 rspLength);
867 if (!throttleTraces)
Chris Cainc9dc4412023-03-06 15:56:34 -0600868 {
Chris Cain755af102024-02-27 16:09:51 -0600869 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -0600870 std::format(
Chris Cain755af102024-02-27 16:09:51 -0600871 "pldmRspCallback: Unexpected State: {} - PLDM response ({} bytes) for OCC{}:",
872 occSensorState, rspLength, instance)
Chris Cainc9dc4412023-03-06 15:56:34 -0600873 .c_str());
874 dump_hex(pldmResponse);
875 }
Chris Cainbae4d072022-02-28 09:46:50 -0600876 }
877
878 return 0;
879};
880
881std::vector<uint8_t> Interface::encodeGetStateSensorRequest(uint8_t instance,
882 uint16_t sensorId)
883{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100884 if (!getPldmInstanceId())
Chris Cain8b508bf2022-05-26 14:01:31 -0500885 {
886 log<level::ERR>(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100887 "encodeGetStateSensorRequest: failed to getPldmInstanceId");
Chris Cain8b508bf2022-05-26 14:01:31 -0500888 return std::vector<uint8_t>();
889 }
890
Chris Cainbae4d072022-02-28 09:46:50 -0600891 bitfield8_t sRearm = {0};
Patrick Williamsa49c9872023-05-10 07:50:35 -0500892 const size_t msgSize = sizeof(pldm_msg_hdr) +
893 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES;
Chris Cainbae4d072022-02-28 09:46:50 -0600894 std::vector<uint8_t> request(msgSize);
Chris Cain8b508bf2022-05-26 14:01:31 -0500895
Chris Cainbae4d072022-02-28 09:46:50 -0600896 auto msg = reinterpret_cast<pldm_msg*>(request.data());
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100897 auto msgRc = encode_get_state_sensor_readings_req(pldmInstanceID.value(),
Chris Cain8b508bf2022-05-26 14:01:31 -0500898 sensorId, sRearm, 0, msg);
Chris Cainbae4d072022-02-28 09:46:50 -0600899 if (msgRc != PLDM_SUCCESS)
900 {
901 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600902 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600903 "encodeGetStateSensorRequest: Failed to encode sensorId:0x{:08X} for OCC{} (rc={})",
904 sensorId, instance, msgRc)
905 .c_str());
906 }
907 return request;
908}
909
910// Initiate query of the specified OCC Active Sensor
911void Interface::checkActiveSensor(uint8_t instance)
912{
913 static bool tracedOnce = false;
914 if (pldmFd > 0)
915 {
Chris Cain755af102024-02-27 16:09:51 -0600916 if (!throttleTraces && !tracedOnce)
Chris Caind1b68262022-02-28 09:56:50 -0600917 {
Chris Cain755af102024-02-27 16:09:51 -0600918 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -0600919 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600920 "checkActiveSensor: already waiting on OCC{} (fd={})",
921 pldmResponseOcc, pldmFd)
Chris Caind1b68262022-02-28 09:56:50 -0600922 .c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600923 tracedOnce = true;
Chris Caind1b68262022-02-28 09:56:50 -0600924 }
Chris Cainbae4d072022-02-28 09:46:50 -0600925 return;
926 }
927 tracedOnce = false;
928
929 if (!isOCCSensorCacheValid())
930 {
931 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
932 sensorToOCCInstance, OCCSensorOffset);
933 }
934
935 // look up sensor id (key) based on instance
936 auto entry = std::find_if(
937 sensorToOCCInstance.begin(), sensorToOCCInstance.end(),
938 [instance](const auto& entry) { return instance == entry.second; });
939 if (entry != sensorToOCCInstance.end())
940 {
941 // Query the OCC Active Sensor state for this instance
Chris Cain755af102024-02-27 16:09:51 -0600942 if (!throttleTraces)
943 {
944 log<level::INFO>(
945 std::format("checkActiveSensor: OCC{} / sensorID: 0x{:04X}",
946 instance, entry->first)
947 .c_str());
948 }
Chris Cainbae4d072022-02-28 09:46:50 -0600949
Chris Cainbae4d072022-02-28 09:46:50 -0600950 // Encode GetStateSensorReadings PLDM message
951 auto request = encodeGetStateSensorRequest(instance, entry->first);
952 if (request.empty())
953 {
954 return;
955 }
956
957 // Send request to PLDM and setup callback for response
958 sendPldm(request, instance, true);
959 }
960 else
961 {
Chris Cain755af102024-02-27 16:09:51 -0600962 if (!throttleTraces)
963 {
964 log<level::ERR>(
965 std::format(
966 "checkActiveSensor: Unable to find PLDM sensor for OCC{}",
967 instance)
968 .c_str());
969 log<level::INFO>(
970 "checkActiveSensor: fetching STATE_SET_OPERATIONAL_RUNNING_STATUS");
971 }
Chris Cain8cf74962022-06-29 08:45:16 -0500972 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
973 sensorToOCCInstance, OCCSensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -0500974 }
Patrick Williams05e95592021-09-02 09:28:14 -0500975}
976
Chris Cain755af102024-02-27 16:09:51 -0600977void Interface::setTraceThrottle(const bool throttle)
978{
979 if (throttle != throttleTraces)
980 {
981 if (throttle)
982 {
983 log<level::WARNING>("PLDM traces being throttled");
984 }
985 else
986 {
987 log<level::INFO>("PLDM traces no longer being throttled");
988 }
989 throttleTraces = throttle;
990 }
991}
992
Patrick Williams05e95592021-09-02 09:28:14 -0500993} // namespace pldm