blob: 67847c8ebab6c8f44757a86e4921ff748a5a924d [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>
Rashmica Gupta52328cb2023-02-15 10:38:16 +110011#include <libpldm/transport.h>
12#include <libpldm/transport/mctp-demux.h>
13#include <poll.h>
Patrick Williams05e95592021-09-02 09:28:14 -050014
15#include <phosphor-logging/log.hpp>
Chris Cainbae4d072022-02-28 09:46:50 -060016#include <sdbusplus/bus.hpp>
17#include <sdeventplus/clock.hpp>
18#include <sdeventplus/exception.hpp>
19#include <sdeventplus/source/io.hpp>
20#include <sdeventplus/source/time.hpp>
21
22#include <algorithm>
Patrick Williams48002492024-02-13 21:43:32 -060023#include <format>
Patrick Williams05e95592021-09-02 09:28:14 -050024
25namespace pldm
26{
27
Patrick Williams05e95592021-09-02 09:28:14 -050028using namespace phosphor::logging;
29
Chris Cainbae4d072022-02-28 09:46:50 -060030using namespace sdeventplus;
31using namespace sdeventplus::source;
32constexpr auto clockId = sdeventplus::ClockId::RealTime;
33using Clock = sdeventplus::Clock<clockId>;
34using Timer = Time<clockId>;
Chris Cain755af102024-02-27 16:09:51 -060035bool Interface::throttleTraces = false;
Chris Cainbae4d072022-02-28 09:46:50 -060036
Eddie Jamescbad2192021-10-07 09:39:39 -050037void Interface::fetchSensorInfo(uint16_t stateSetId,
38 SensorToInstance& sensorInstanceMap,
39 SensorOffset& sensorOffset)
Patrick Williams05e95592021-09-02 09:28:14 -050040{
Eddie Jamescbad2192021-10-07 09:39:39 -050041 PdrList pdrs{};
Chris Cainbae4d072022-02-28 09:46:50 -060042 static bool tracedError = false;
Eddie Jamescbad2192021-10-07 09:39:39 -050043
44 auto& bus = open_power::occ::utils::getBus();
45 try
46 {
47 auto method = bus.new_method_call(
48 "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
49 "xyz.openbmc_project.PLDM.PDR", "FindStateSensorPDR");
Chris Cainbae4d072022-02-28 09:46:50 -060050 method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId);
Eddie Jamescbad2192021-10-07 09:39:39 -050051
52 auto responseMsg = bus.call(method);
53 responseMsg.read(pdrs);
54 }
Patrick Williamsaf408082022-07-22 19:26:54 -050055 catch (const sdbusplus::exception_t& e)
Eddie Jamescbad2192021-10-07 09:39:39 -050056 {
Chris Cainbae4d072022-02-28 09:46:50 -060057 if (!tracedError)
58 {
59 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -060060 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -060061 "fetchSensorInfo: Failed to find stateSetID:{} PDR: {}",
62 stateSetId, e.what())
63 .c_str());
64 tracedError = true;
65 }
Eddie Jamescbad2192021-10-07 09:39:39 -050066 }
67
68 if (pdrs.empty())
69 {
Chris Cainbae4d072022-02-28 09:46:50 -060070 if (!tracedError)
71 {
72 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -060073 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -060074 "fetchSensorInfo: state sensor PDRs ({}) not present",
75 stateSetId)
76 .c_str());
77 tracedError = true;
78 }
Eddie Jamescbad2192021-10-07 09:39:39 -050079 return;
80 }
81
Chris Cainbae4d072022-02-28 09:46:50 -060082 // Found PDR
83 if (tracedError)
84 {
85 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -060086 std::format("fetchSensorInfo: found {} PDRs", pdrs.size()).c_str());
Chris Cainbae4d072022-02-28 09:46:50 -060087 tracedError = false;
88 }
89
Patrick Williams05e95592021-09-02 09:28:14 -050090 bool offsetFound = false;
George Liuf3a4a692021-12-28 13:59:51 +080091 auto stateSensorPDR =
Patrick Williams05e95592021-09-02 09:28:14 -050092 reinterpret_cast<const pldm_state_sensor_pdr*>(pdrs.front().data());
George Liuf3a4a692021-12-28 13:59:51 +080093 auto possibleStatesPtr = stateSensorPDR->possible_states;
94 for (auto offset = 0; offset < stateSensorPDR->composite_sensor_count;
95 offset++)
Patrick Williams05e95592021-09-02 09:28:14 -050096 {
97 auto possibleStates =
98 reinterpret_cast<const state_sensor_possible_states*>(
99 possibleStatesPtr);
100
Eddie Jamescbad2192021-10-07 09:39:39 -0500101 if (possibleStates->state_set_id == stateSetId)
Patrick Williams05e95592021-09-02 09:28:14 -0500102 {
103 sensorOffset = offset;
104 offsetFound = true;
105 break;
106 }
107 possibleStatesPtr += sizeof(possibleStates->state_set_id) +
108 sizeof(possibleStates->possible_states_size) +
109 possibleStates->possible_states_size;
110 }
111
112 if (!offsetFound)
113 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500114 log<level::ERR>("pldm: state sensor PDR not found");
Patrick Williams05e95592021-09-02 09:28:14 -0500115 return;
116 }
117
118 // To order SensorID based on the EntityInstance.
119 // Note that when a proc is on a DCM, the PDRs for these sensors
120 // could have the same instance IDs but different container IDs.
121 std::map<uint32_t, SensorID> entityInstMap{};
122 for (auto& pdr : pdrs)
123 {
124 auto pdrPtr =
125 reinterpret_cast<const pldm_state_sensor_pdr*>(pdr.data());
Chris Cain72d01aa2022-06-14 16:28:03 -0500126 uint32_t key = pdrPtr->sensor_id;
Patrick Williams05e95592021-09-02 09:28:14 -0500127 entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->sensor_id));
128 }
129
130 open_power::occ::instanceID count = start;
Patrick Williamsa49c9872023-05-10 07:50:35 -0500131 for (const auto& pair : entityInstMap)
Patrick Williams05e95592021-09-02 09:28:14 -0500132 {
133 sensorInstanceMap.emplace(pair.second, count);
134 count++;
135 }
136}
137
Patrick Williamsaf408082022-07-22 19:26:54 -0500138void Interface::sensorEvent(sdbusplus::message_t& msg)
Patrick Williams05e95592021-09-02 09:28:14 -0500139{
140 if (!isOCCSensorCacheValid())
141 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500142 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
143 sensorToOCCInstance, OCCSensorOffset);
144 }
Patrick Williams05e95592021-09-02 09:28:14 -0500145
Eddie Jamescbad2192021-10-07 09:39:39 -0500146 if (sensorToSBEInstance.empty())
147 {
148 fetchSensorInfo(PLDM_OEM_IBM_SBE_HRESET_STATE, sensorToSBEInstance,
149 SBESensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -0500150 }
151
Chris Cain72d01aa2022-06-14 16:28:03 -0500152 TerminusID sensorTid{};
Patrick Williams05e95592021-09-02 09:28:14 -0500153 SensorID sensorId{};
154 SensorOffset msgSensorOffset{};
155 EventState eventState{};
156 EventState previousEventState{};
157
Chris Cain72d01aa2022-06-14 16:28:03 -0500158 msg.read(sensorTid, sensorId, msgSensorOffset, eventState,
159 previousEventState);
Patrick Williams05e95592021-09-02 09:28:14 -0500160
Eddie Jamescbad2192021-10-07 09:39:39 -0500161 if (msgSensorOffset == OCCSensorOffset)
Patrick Williams05e95592021-09-02 09:28:14 -0500162 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500163 auto sensorEntry = sensorToOCCInstance.find(sensorId);
Patrick Williams05e95592021-09-02 09:28:14 -0500164
Eddie James432dc482021-11-19 15:29:31 -0600165 if (sensorEntry != sensorToOCCInstance.end())
Eddie Jamescbad2192021-10-07 09:39:39 -0500166 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500167 const uint8_t instance = sensorEntry->second;
Chris Cain755af102024-02-27 16:09:51 -0600168 bool validEvent = true;
Chris Cain7b00cde2023-03-14 15:47:12 -0500169 bool isRunning = false;
Eddie James432dc482021-11-19 15:29:31 -0600170 if (eventState ==
171 static_cast<EventState>(
172 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE))
173 {
174 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600175 std::format("PLDM: OCC{} is RUNNING", instance).c_str());
Chris Cain7b00cde2023-03-14 15:47:12 -0500176 isRunning = true;
Eddie James432dc482021-11-19 15:29:31 -0600177 }
178 else if (eventState ==
179 static_cast<EventState>(
180 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED))
181 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500182 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600183 std::format("PLDM: OCC{} has now STOPPED", instance)
Chris Cain8b508bf2022-05-26 14:01:31 -0500184 .c_str());
Eddie James432dc482021-11-19 15:29:31 -0600185 }
Chris Cainbae4d072022-02-28 09:46:50 -0600186 else if (eventState ==
187 static_cast<EventState>(
188 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT))
189 {
Chris Cain755af102024-02-27 16:09:51 -0600190 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600191 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600192 "PLDM: OCC{} has now STOPPED and system is in SAFE MODE",
Chris Cain8b508bf2022-05-26 14:01:31 -0500193 instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600194 .c_str());
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500195
196 // Setting safe mode true
197 safeModeCallBack(true);
Chris Cainbae4d072022-02-28 09:46:50 -0600198 }
199 else
200 {
Chris Cain755af102024-02-27 16:09:51 -0600201 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -0600202 std::format("PLDM: Unexpected PLDM state {} for OCC{}",
Chris Cain8b508bf2022-05-26 14:01:31 -0500203 eventState, instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600204 .c_str());
Chris Cain755af102024-02-27 16:09:51 -0600205 validEvent = false;
Chris Cainbae4d072022-02-28 09:46:50 -0600206 }
Chris Cain755af102024-02-27 16:09:51 -0600207 if (validEvent)
208 {
209 if ((pldmFd > 0) && (instance == pldmResponseOcc))
210 {
211 // Waiting for a response for this OCC, can stop waiting
212 pldmClose();
213 }
214 callBack(instance, isRunning);
215 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500216 return;
217 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500218 }
Eddie James432dc482021-11-19 15:29:31 -0600219
220 if (msgSensorOffset == SBESensorOffset)
Eddie Jamescbad2192021-10-07 09:39:39 -0500221 {
222 auto sensorEntry = sensorToSBEInstance.find(sensorId);
223
Eddie James432dc482021-11-19 15:29:31 -0600224 if (sensorEntry != sensorToSBEInstance.end())
Eddie Jamescbad2192021-10-07 09:39:39 -0500225 {
Chris Cain12d0b822022-04-22 17:29:18 -0500226 const uint8_t instance = sensorEntry->second;
227 auto match = std::find(outstandingHResets.begin(),
228 outstandingHResets.end(), instance);
229 if (match != outstandingHResets.end())
Eddie James432dc482021-11-19 15:29:31 -0600230 {
Chris Cain12d0b822022-04-22 17:29:18 -0500231 outstandingHResets.erase(match);
232 if (eventState == static_cast<EventState>(SBE_HRESET_NOT_READY))
233 {
234 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600235 std::format("pldm: HRESET is NOT READY (OCC{})",
Chris Cain12d0b822022-04-22 17:29:18 -0500236 instance)
237 .c_str());
238 }
239 else if (eventState ==
240 static_cast<EventState>(SBE_HRESET_READY))
241 {
242 sbeCallBack(instance, true);
243 }
244 else if (eventState ==
245 static_cast<EventState>(SBE_HRESET_FAILED))
246 {
247 sbeCallBack(instance, false);
248 }
Eddie James432dc482021-11-19 15:29:31 -0600249 }
Chris Cain12d0b822022-04-22 17:29:18 -0500250 // else request was not from us
Eddie Jamescbad2192021-10-07 09:39:39 -0500251 }
252 }
Patrick Williams05e95592021-09-02 09:28:14 -0500253}
254
Patrick Williamsaf408082022-07-22 19:26:54 -0500255void Interface::hostStateEvent(sdbusplus::message_t& msg)
Chris Cain157467d2022-06-24 11:25:23 -0500256{
257 std::map<std::string, std::variant<std::string>> properties{};
258 std::string interface;
259 msg.read(interface, properties);
260 const auto stateEntry = properties.find("CurrentHostState");
261 if (stateEntry != properties.end())
262 {
263 auto stateEntryValue = stateEntry->second;
264 auto propVal = std::get<std::string>(stateEntryValue);
265 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
266 {
267 clearData();
268 }
269 }
270}
271
Chris Cainbae4d072022-02-28 09:46:50 -0600272void Interface::clearData()
273{
Chris Cain72d01aa2022-06-14 16:28:03 -0500274 if (!sensorToOCCInstance.empty())
275 {
276 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600277 std::format("clearData: Clearing sensorToOCCInstance ({} entries)",
Chris Cain72d01aa2022-06-14 16:28:03 -0500278 sensorToOCCInstance.size())
279 .c_str());
280 for (auto entry : sensorToOCCInstance)
281 {
282 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600283 std::format("clearData: OCC{} / sensorID: 0x{:04X}",
Chris Cain72d01aa2022-06-14 16:28:03 -0500284 entry.second, entry.first)
285 .c_str());
Chris Cain082a6ca2023-03-21 10:27:26 -0500286 callBack(entry.second, false);
Chris Cain72d01aa2022-06-14 16:28:03 -0500287 }
288 sensorToOCCInstance.clear();
289 }
290 if (!occInstanceToEffecter.empty())
291 {
292 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600293 std::format(
Chris Cain72d01aa2022-06-14 16:28:03 -0500294 "clearData: Clearing occInstanceToEffecter ({} entries)",
295 occInstanceToEffecter.size())
296 .c_str());
297 occInstanceToEffecter.clear();
298 }
299 if (!sensorToSBEInstance.empty())
300 {
301 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600302 std::format("clearData: Clearing sensorToSBEInstance ({} entries)",
Chris Cain72d01aa2022-06-14 16:28:03 -0500303 sensorToSBEInstance.size())
304 .c_str());
305 sensorToSBEInstance.clear();
306 }
307 if (!sbeInstanceToEffecter.empty())
308 {
309 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600310 std::format(
Chris Cain72d01aa2022-06-14 16:28:03 -0500311 "clearData: Clearing sbeInstanceToEffecter ({} entries)",
312 sbeInstanceToEffecter.size())
313 .c_str());
314 sbeInstanceToEffecter.clear();
315 }
Chris Cainbae4d072022-02-28 09:46:50 -0600316}
317
Patrick Williamsd7542c82024-08-16 15:20:28 -0400318void Interface::fetchEffecterInfo(
319 uint16_t stateSetId, InstanceToEffecter& instanceToEffecterMap,
320 CompositeEffecterCount& effecterCount, uint8_t& stateIdPos)
Patrick Williams05e95592021-09-02 09:28:14 -0500321{
Eddie Jamescbad2192021-10-07 09:39:39 -0500322 PdrList pdrs{};
323
324 auto& bus = open_power::occ::utils::getBus();
325 try
326 {
327 auto method = bus.new_method_call(
328 "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
329 "xyz.openbmc_project.PLDM.PDR", "FindStateEffecterPDR");
Chris Cainbae4d072022-02-28 09:46:50 -0600330 method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId);
Eddie Jamescbad2192021-10-07 09:39:39 -0500331
332 auto responseMsg = bus.call(method);
333 responseMsg.read(pdrs);
334 }
Patrick Williamsaf408082022-07-22 19:26:54 -0500335 catch (const sdbusplus::exception_t& e)
Eddie Jamescbad2192021-10-07 09:39:39 -0500336 {
337 log<level::ERR>("pldm: Failed to fetch the state effecter PDRs",
338 entry("ERROR=%s", e.what()));
339 }
340
341 if (!pdrs.size())
342 {
343 log<level::ERR>("pldm: state effecter PDRs not present");
344 return;
345 }
346
Patrick Williams05e95592021-09-02 09:28:14 -0500347 bool offsetFound = false;
George Liuf3a4a692021-12-28 13:59:51 +0800348 auto stateEffecterPDR =
Patrick Williams05e95592021-09-02 09:28:14 -0500349 reinterpret_cast<const pldm_state_effecter_pdr*>(pdrs.front().data());
George Liuf3a4a692021-12-28 13:59:51 +0800350 auto possibleStatesPtr = stateEffecterPDR->possible_states;
351 for (auto offset = 0; offset < stateEffecterPDR->composite_effecter_count;
352 offset++)
Patrick Williams05e95592021-09-02 09:28:14 -0500353 {
354 auto possibleStates =
355 reinterpret_cast<const state_effecter_possible_states*>(
356 possibleStatesPtr);
357
Eddie Jamescbad2192021-10-07 09:39:39 -0500358 if (possibleStates->state_set_id == stateSetId)
Patrick Williams05e95592021-09-02 09:28:14 -0500359 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500360 stateIdPos = offset;
George Liuf3a4a692021-12-28 13:59:51 +0800361 effecterCount = stateEffecterPDR->composite_effecter_count;
Patrick Williams05e95592021-09-02 09:28:14 -0500362 offsetFound = true;
363 break;
364 }
365 possibleStatesPtr += sizeof(possibleStates->state_set_id) +
366 sizeof(possibleStates->possible_states_size) +
367 possibleStates->possible_states_size;
368 }
369
370 if (!offsetFound)
371 {
372 return;
373 }
374
Chris Cain0f516522022-02-07 14:48:28 -0600375 std::map<uint32_t, EffecterID> entityInstMap{};
Patrick Williams05e95592021-09-02 09:28:14 -0500376 for (auto& pdr : pdrs)
377 {
378 auto pdrPtr =
379 reinterpret_cast<const pldm_state_effecter_pdr*>(pdr.data());
Chris Cain72d01aa2022-06-14 16:28:03 -0500380 uint32_t key = pdrPtr->effecter_id;
Patrick Williams05e95592021-09-02 09:28:14 -0500381 entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->effecter_id));
382 }
383
384 open_power::occ::instanceID position = start;
Patrick Williamsa49c9872023-05-10 07:50:35 -0500385 for (const auto& pair : entityInstMap)
Patrick Williams05e95592021-09-02 09:28:14 -0500386 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500387 instanceToEffecterMap.emplace(position, pair.second);
Patrick Williams05e95592021-09-02 09:28:14 -0500388 position++;
389 }
390}
391
Patrick Williamsd7542c82024-08-16 15:20:28 -0400392std::vector<uint8_t> Interface::prepareSetEffecterReq(
393 EffecterID effecterId, CompositeEffecterCount effecterCount,
394 uint8_t stateIdPos, uint8_t stateSetValue)
Patrick Williams05e95592021-09-02 09:28:14 -0500395{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100396 if (!getPldmInstanceId())
Chris Cain8b508bf2022-05-26 14:01:31 -0500397 {
398 return std::vector<uint8_t>();
399 }
400
Patrick Williams05e95592021-09-02 09:28:14 -0500401 std::vector<uint8_t> request(
402 sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(effecterCount) +
403 (effecterCount * sizeof(set_effecter_state_field)));
404 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
405 std::vector<set_effecter_state_field> stateField;
406
407 for (uint8_t effecterPos = 0; effecterPos < effecterCount; effecterPos++)
408 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500409 if (effecterPos == stateIdPos)
Patrick Williams05e95592021-09-02 09:28:14 -0500410 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500411 stateField.emplace_back(
412 set_effecter_state_field{PLDM_REQUEST_SET, stateSetValue});
Patrick Williams05e95592021-09-02 09:28:14 -0500413 }
414 else
415 {
416 stateField.emplace_back(
417 set_effecter_state_field{PLDM_NO_CHANGE, 0});
418 }
419 }
420 auto rc = encode_set_state_effecter_states_req(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100421 pldmInstanceID.value(), effecterId, effecterCount, stateField.data(),
Chris Cain8b508bf2022-05-26 14:01:31 -0500422 requestMsg);
Patrick Williams05e95592021-09-02 09:28:14 -0500423 if (rc != PLDM_SUCCESS)
424 {
425 log<level::ERR>("encode set effecter states request returned error ",
426 entry("RC=%d", rc));
427 request.clear();
428 }
429 return request;
430}
431
432void Interface::resetOCC(open_power::occ::instanceID occInstanceId)
433{
Chris Cainbae4d072022-02-28 09:46:50 -0600434 if (open_power::occ::utils::isHostRunning())
Patrick Williams05e95592021-09-02 09:28:14 -0500435 {
Chris Cainbae4d072022-02-28 09:46:50 -0600436 if (!isPDREffecterCacheValid())
437 {
438 fetchEffecterInfo(PLDM_STATE_SET_BOOT_RESTART_CAUSE,
439 occInstanceToEffecter, OCCEffecterCount,
440 bootRestartPosition);
441 }
Patrick Williams05e95592021-09-02 09:28:14 -0500442
Chris Cainbae4d072022-02-28 09:46:50 -0600443 // Find the matching effecter for the OCC instance
444 auto effecterEntry = occInstanceToEffecter.find(occInstanceId);
445 if (effecterEntry == occInstanceToEffecter.end())
446 {
447 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600448 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600449 "pldm: Failed to find a matching effecter for OCC instance {}",
450 occInstanceId)
451 .c_str());
452
453 return;
454 }
455
Chris Cainbae4d072022-02-28 09:46:50 -0600456 // Prepare the SetStateEffecterStates request to reset the OCC
457 auto request = prepareSetEffecterReq(
Chris Cain8b508bf2022-05-26 14:01:31 -0500458 effecterEntry->second, OCCEffecterCount, bootRestartPosition,
459 PLDM_STATE_SET_BOOT_RESTART_CAUSE_WARM_RESET);
Chris Cainbae4d072022-02-28 09:46:50 -0600460
461 if (request.empty())
462 {
463 log<level::ERR>(
464 "pldm: SetStateEffecterStates OCC reset request empty");
465 return;
466 }
467
468 // Send request to reset the OCCs/PM Complex (ignore response)
469 sendPldm(request, occInstanceId, false);
470 }
471 else
Patrick Williams05e95592021-09-02 09:28:14 -0500472 {
473 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600474 std::format("resetOCC: HOST is not running (OCC{})", occInstanceId)
Chris Cain0f516522022-02-07 14:48:28 -0600475 .c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600476 clearData();
Patrick Williams05e95592021-09-02 09:28:14 -0500477 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500478}
479
480void Interface::sendHRESET(open_power::occ::instanceID sbeInstanceId)
481{
Chris Cainbae4d072022-02-28 09:46:50 -0600482 if (open_power::occ::utils::isHostRunning())
Eddie Jamescbad2192021-10-07 09:39:39 -0500483 {
Chris Cainbae4d072022-02-28 09:46:50 -0600484 if (sbeInstanceToEffecter.empty())
485 {
486 fetchEffecterInfo(PLDM_OEM_IBM_SBE_MAINTENANCE_STATE,
487 sbeInstanceToEffecter, SBEEffecterCount,
488 sbeMaintenanceStatePosition);
489 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500490
Chris Cainbae4d072022-02-28 09:46:50 -0600491 auto effecterEntry = sbeInstanceToEffecter.find(sbeInstanceId);
492 if (effecterEntry == sbeInstanceToEffecter.end())
493 {
494 log<level::ERR>(
495 "pldm: Failed to find a matching effecter for SBE instance",
496 entry("SBE=%d", sbeInstanceId));
497 return;
498 }
499
Chris Cainbae4d072022-02-28 09:46:50 -0600500 // Prepare the SetStateEffecterStates request to HRESET the SBE
501 auto request = prepareSetEffecterReq(
Chris Cain8b508bf2022-05-26 14:01:31 -0500502 effecterEntry->second, SBEEffecterCount,
Chris Cainbae4d072022-02-28 09:46:50 -0600503 sbeMaintenanceStatePosition, SBE_RETRY_REQUIRED);
504
505 if (request.empty())
506 {
507 log<level::ERR>(
508 "pldm: SetStateEffecterStates HRESET request empty");
509 return;
510 }
511
512 // Send request to issue HRESET of SBE (ignore response)
513 sendPldm(request, sbeInstanceId, false);
Chris Cain12d0b822022-04-22 17:29:18 -0500514 outstandingHResets.insert(sbeInstanceId);
Chris Cainbae4d072022-02-28 09:46:50 -0600515 }
516 else
Eddie Jamescbad2192021-10-07 09:39:39 -0500517 {
Patrick Williams48002492024-02-13 21:43:32 -0600518 log<level::ERR>(std::format("sendHRESET: HOST is not running (OCC{})",
Chris Cainbae4d072022-02-28 09:46:50 -0600519 sbeInstanceId)
520 .c_str());
521 clearData();
Eddie Jamescbad2192021-10-07 09:39:39 -0500522 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500523}
524
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100525bool Interface::getPldmInstanceId()
Eddie Jamescbad2192021-10-07 09:39:39 -0500526{
Rashmica Guptadb38e912023-05-25 10:33:46 +1000527 pldm_instance_id_t id;
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100528 if (!pldmInstanceID)
Patrick Williams05e95592021-09-02 09:28:14 -0500529 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500530 // Request new instance ID
Rashmica Guptadb38e912023-05-25 10:33:46 +1000531 int rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
532 if (rc == -EAGAIN)
Chris Cain8b508bf2022-05-26 14:01:31 -0500533 {
Rashmica Guptadb38e912023-05-25 10:33:46 +1000534 std::this_thread::sleep_for(std::chrono::milliseconds(100));
535 rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
Chris Cain8b508bf2022-05-26 14:01:31 -0500536 }
Rashmica Guptadb38e912023-05-25 10:33:46 +1000537
538 if (rc)
Chris Cain8b508bf2022-05-26 14:01:31 -0500539 {
540 log<level::ERR>(
Rashmica Guptadb38e912023-05-25 10:33:46 +1000541 std::format(
542 "getPldmInstanceId: Failed to alloc ID for TID {}. RC{}",
543 tid, rc)
Chris Cain8b508bf2022-05-26 14:01:31 -0500544 .c_str());
545 return false;
546 }
Rashmica Guptadb38e912023-05-25 10:33:46 +1000547 pldmInstanceID.emplace(id);
548 if (!throttleTraces)
549 {
550 log<level::INFO>(
551 std::format("got id {} and set PldmInstanceId to {}", id,
552 pldmInstanceID.value())
553 .c_str());
554 }
Patrick Williams05e95592021-09-02 09:28:14 -0500555 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500556 return true;
557}
Patrick Williams05e95592021-09-02 09:28:14 -0500558
Rashmica Guptadb38e912023-05-25 10:33:46 +1000559void Interface::freePldmInstanceId()
560{
561 if (pldmInstanceID)
562 {
563 int rc = pldm_instance_id_free(pldmInstanceIdDb, tid,
564 pldmInstanceID.value());
565 if (rc)
566 {
567 log<level::ERR>(
568 std::format(
569 "freePldmInstanceId: Failed to free ID {} for TID {}. RC{}",
570 pldmInstanceID.value(), tid, rc)
571 .c_str());
572 return;
573 }
574 if (!throttleTraces)
575 {
576 log<level::INFO>(
577 std::format("Freed PLDM instance ID {}", pldmInstanceID.value())
578 .c_str());
579 }
580 pldmInstanceID = std::nullopt;
581 }
582}
583
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100584int Interface::openMctpDemuxTransport()
585{
586 mctpDemux = nullptr;
587 int rc = pldm_transport_mctp_demux_init(&mctpDemux);
588 if (rc)
589 {
590 log<level::ERR>(
591 std::format(
592 "openMctpDemuxTransport: Failed to init MCTP demux transport, errno={}/{}",
593 rc, strerror(rc))
594 .c_str());
595 return -1;
596 }
597
598 if (pldm_transport_mctp_demux_map_tid(mctpDemux, mctpEid, mctpEid))
599 {
600 log<level::ERR>(
601 std::format(
602 "openMctpDemuxTransport: Failed to setup tid to eid mapping, errno={}/{}",
603 errno, strerror(errno))
604 .c_str());
605 pldmClose();
606 return -1;
607 }
608 pldmTransport = pldm_transport_mctp_demux_core(mctpDemux);
609
610 struct pollfd pollfd;
611 if (pldm_transport_mctp_demux_init_pollfd(pldmTransport, &pollfd))
612 {
613 log<level::ERR>(
614 std::format(
615 "openMctpDemuxTransport: Failed to get pollfd , errno={}/{}",
616 errno, strerror(errno))
617 .c_str());
618 pldmClose();
619 return -1;
620 }
621 pldmFd = pollfd.fd;
622 if (!throttleTraces)
623 {
624 log<level::INFO>(
625 std::format("openMctpDemuxTransport: pldmFd has fd={}", pldmFd)
626 .c_str());
627 }
628 return 0;
629}
630
631int Interface::pldmOpen()
632{
633 if (pldmTransport)
634 {
635 log<level::ERR>(
636 std::format("pldmOpen: pldmTransport already setup!, errno={}/{}",
637 errno, strerror(errno))
638 .c_str());
639 return -1;
640 }
641 return openMctpDemuxTransport();
642}
643
Chris Cainbae4d072022-02-28 09:46:50 -0600644void Interface::sendPldm(const std::vector<uint8_t>& request,
645 const uint8_t instance, const bool rspExpected)
Eddie Jamescbad2192021-10-07 09:39:39 -0500646{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100647 if (!pldmInstanceID)
Chris Cain8b508bf2022-05-26 14:01:31 -0500648 {
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100649 log<level::ERR>("sendPldm: No PLDM Instance ID found!");
Chris Cain8b508bf2022-05-26 14:01:31 -0500650 return;
651 }
652
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100653 auto rc = pldmOpen();
654 if (rc)
Patrick Williams05e95592021-09-02 09:28:14 -0500655 {
Chris Caind1b68262022-02-28 09:56:50 -0600656 log<level::ERR>(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100657 std::format("sendPldm: pldmOpen failed rc={}", rc).c_str());
Rashmica Guptadb38e912023-05-25 10:33:46 +1000658 freePldmInstanceId();
Patrick Williams05e95592021-09-02 09:28:14 -0500659 return;
660 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500661
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100662 pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEid);
Patrick Williams05e95592021-09-02 09:28:14 -0500663 // Send the PLDM request message to HBRT
Chris Cainbae4d072022-02-28 09:46:50 -0600664 if (rspExpected)
Patrick Williams05e95592021-09-02 09:28:14 -0500665 {
Chris Cainbae4d072022-02-28 09:46:50 -0600666 // Register callback when response is available
667 registerPldmRspCallback();
668
669 // Send PLDM request
Chris Cain755af102024-02-27 16:09:51 -0600670 if (!throttleTraces)
671 {
672 log<level::INFO>(
673 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100674 "sendPldm: calling pldm_transport_send_msg(OCC{}, instance:{}, {} bytes)",
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100675 instance, pldmInstanceID.value(), request.size())
Chris Cain755af102024-02-27 16:09:51 -0600676 .c_str());
677 }
Chris Cainbae4d072022-02-28 09:46:50 -0600678 pldmResponseReceived = false;
679 pldmResponseTimeout = false;
680 pldmResponseOcc = instance;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100681 auto pldmRc = pldm_transport_send_msg(pldmTransport, pldmTID,
682 request.data(), request.size());
Chris Cainbae4d072022-02-28 09:46:50 -0600683 auto sendErrno = errno;
684 if (pldmRc != PLDM_REQUESTER_SUCCESS)
685 {
686 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600687 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100688 "sendPldm: pldm_transport_send_msg failed with rc={} and errno={}/{}",
Chris Cain5161a022023-08-15 10:07:12 -0500689 static_cast<
690 std::underlying_type_t<pldm_requester_error_codes>>(
691 pldmRc),
692 sendErrno, strerror(sendErrno))
Chris Cainbae4d072022-02-28 09:46:50 -0600693 .c_str());
694 pldmClose();
695 return;
696 }
697
698 // start timer waiting for the response
699 using namespace std::literals::chrono_literals;
Chris Cainbd551de2022-04-26 13:41:16 -0500700 pldmRspTimer.restartOnce(8s);
Chris Cainbae4d072022-02-28 09:46:50 -0600701
702 // Wait for response/timeout
703 }
704 else // not expecting the response
705 {
Chris Cain755af102024-02-27 16:09:51 -0600706 if (!throttleTraces)
707 {
708 log<level::INFO>(
709 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100710 "sendPldm: calling pldm_transport_send_msg(mctpID:{}, fd:{}, {} bytes) for OCC{}",
Chris Cain755af102024-02-27 16:09:51 -0600711 mctpEid, pldmFd, request.size(), instance)
712 .c_str());
713 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100714 auto rc = pldm_transport_send_msg(pldmTransport, pldmTID,
715 request.data(), request.size());
Chris Cainbae4d072022-02-28 09:46:50 -0600716 auto sendErrno = errno;
Chris Caind1b68262022-02-28 09:56:50 -0600717 if (rc)
718 {
719 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600720 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100721 "sendPldm: pldm_transport_send_msg(mctpID:{}, fd:{}, {} bytes) failed with rc={} and errno={}/{}",
Chris Cain5161a022023-08-15 10:07:12 -0500722 mctpEid, pldmFd, request.size(),
723 static_cast<
724 std::underlying_type_t<pldm_requester_error_codes>>(rc),
725 sendErrno, strerror(sendErrno))
Chris Caind1b68262022-02-28 09:56:50 -0600726 .c_str());
727 }
Chris Cainbae4d072022-02-28 09:46:50 -0600728 pldmClose();
729 }
730}
Patrick Williams05e95592021-09-02 09:28:14 -0500731
Chris Cainbae4d072022-02-28 09:46:50 -0600732// Attaches the FD to event loop and registers the callback handler
733void Interface::registerPldmRspCallback()
734{
735 decltype(eventSource.get()) sourcePtr = nullptr;
736 auto rc = sd_event_add_io(event.get(), &sourcePtr, pldmFd, EPOLLIN,
737 pldmRspCallback, this);
738 if (rc < 0)
739 {
740 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600741 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600742 "registerPldmRspCallback: sd_event_add_io: Error({})={} : fd={}",
743 rc, strerror(-rc), pldmFd)
744 .c_str());
Chris Caind1b68262022-02-28 09:56:50 -0600745 }
746 else
Patrick Williams05e95592021-09-02 09:28:14 -0500747 {
Chris Cainbae4d072022-02-28 09:46:50 -0600748 // puts sourcePtr in the event source.
749 eventSource.reset(sourcePtr);
750 }
751}
752
753// Add a timer to the event loop, default 30s.
754void Interface::pldmRspExpired()
755{
756 if (!pldmResponseReceived)
757 {
Chris Cain755af102024-02-27 16:09:51 -0600758 if (!throttleTraces)
759 {
760 log<level::WARNING>(
761 std::format(
762 "pldmRspExpired: timerCallback - timeout waiting for pldm response for OCC{}",
763 pldmResponseOcc)
764 .c_str());
765 }
Chris Cainbae4d072022-02-28 09:46:50 -0600766 pldmResponseTimeout = true;
767 if (pldmFd)
768 {
769 pldmClose();
770 }
771 }
772 return;
773};
774
775void Interface::pldmClose()
776{
Rashmica Guptadb38e912023-05-25 10:33:46 +1000777 freePldmInstanceId();
Chris Cainbae4d072022-02-28 09:46:50 -0600778 if (pldmRspTimer.isEnabled())
779 {
780 // stop PLDM response timer
781 pldmRspTimer.setEnabled(false);
782 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100783
784 pldm_transport_mctp_demux_destroy(mctpDemux);
785 mctpDemux = NULL;
Chris Cainbae4d072022-02-28 09:46:50 -0600786 pldmFd = -1;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100787 pldmTransport = NULL;
Chris Cainbae4d072022-02-28 09:46:50 -0600788 eventSource.reset();
789}
790
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100791int Interface::pldmRspCallback(sd_event_source* /*es*/,
792 __attribute__((unused)) int fd, uint32_t revents,
793 void* userData)
Chris Cainbae4d072022-02-28 09:46:50 -0600794{
795 if (!(revents & EPOLLIN))
796 {
797 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600798 std::format("pldmRspCallback - revents={:08X}", revents).c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600799 return -1;
800 }
801
802 auto pldmIface = static_cast<Interface*>(userData);
803
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100804 if (!pldmIface->pldmInstanceID)
Chris Cain8b508bf2022-05-26 14:01:31 -0500805 {
806 log<level::ERR>(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100807 "pldmRspCallback: No outstanding PLDM Instance ID found");
Chris Cain8b508bf2022-05-26 14:01:31 -0500808 return -1;
809 }
810
Chris Cainbae4d072022-02-28 09:46:50 -0600811 uint8_t* responseMsg = nullptr;
812 size_t responseMsgSize{};
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100813 pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEid);
Chris Cainbae4d072022-02-28 09:46:50 -0600814
Chris Cain755af102024-02-27 16:09:51 -0600815 if (!throttleTraces)
816 {
817 log<level::INFO>(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100818 std::format(
819 "pldmRspCallback: calling pldm_transport_recv_msg() instance:{}",
820 pldmIface->pldmInstanceID.value())
Chris Cain755af102024-02-27 16:09:51 -0600821 .c_str());
822 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100823 auto rc = pldm_transport_recv_msg(pldmIface->pldmTransport, &pldmTID,
824 (void**)&responseMsg, &responseMsgSize);
Chris Cainbae4d072022-02-28 09:46:50 -0600825 int lastErrno = errno;
826 if (rc)
827 {
Chris Cain755af102024-02-27 16:09:51 -0600828 if (!throttleTraces)
829 {
830 log<level::ERR>(
831 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100832 "pldmRspCallback: pldm_transport_recv_msg failed with rc={}, errno={}/{}",
Chris Cain755af102024-02-27 16:09:51 -0600833 static_cast<
834 std::underlying_type_t<pldm_requester_error_codes>>(rc),
835 lastErrno, strerror(lastErrno))
836 .c_str());
837 }
Chris Cainbae4d072022-02-28 09:46:50 -0600838 return -1;
839 }
Chris Cain8b508bf2022-05-26 14:01:31 -0500840
841 // We got the response for the PLDM request msg that was sent
Chris Cain755af102024-02-27 16:09:51 -0600842 if (!throttleTraces)
843 {
844 log<level::INFO>(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100845 std::format(
846 "pldmRspCallback: pldm_transport_recv_msg() rsp was {} bytes",
847 responseMsgSize)
Chris Cain755af102024-02-27 16:09:51 -0600848 .c_str());
849 }
Chris Cainbae4d072022-02-28 09:46:50 -0600850
851 if (pldmIface->pldmRspTimer.isEnabled())
852 {
853 // stop PLDM response timer
854 pldmIface->pldmRspTimer.setEnabled(false);
855 }
856
Chris Cain8b508bf2022-05-26 14:01:31 -0500857 // instance ID should be freed
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100858 pldmIface->pldmInstanceID = std::nullopt;
Chris Cain8b508bf2022-05-26 14:01:31 -0500859
Chris Cainbae4d072022-02-28 09:46:50 -0600860 // Set pointer to autodelete
Patrick Williamsd7542c82024-08-16 15:20:28 -0400861 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{
862 responseMsg, std::free};
Chris Cainbae4d072022-02-28 09:46:50 -0600863
Chris Cainbae4d072022-02-28 09:46:50 -0600864 auto response = reinterpret_cast<pldm_msg*>(responseMsgPtr.get());
865 if (response->payload[0] != PLDM_SUCCESS)
866 {
867 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600868 std::format("pldmRspCallback: payload[0] was not success: {}",
Chris Cainbae4d072022-02-28 09:46:50 -0600869 response->payload[0])
870 .c_str());
871 pldmIface->pldmClose();
872 return -1;
873 }
874
875 // Decode the response
876 uint8_t compCode = 0, sensorCount = 1;
877 get_sensor_state_field field[6];
878 responseMsgSize -= sizeof(pldm_msg_hdr);
879 auto msgRc = decode_get_state_sensor_readings_resp(
880 response, responseMsgSize, &compCode, &sensorCount, field);
881 if ((msgRc != PLDM_SUCCESS) || (compCode != PLDM_SUCCESS))
882 {
883 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600884 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600885 "pldmRspCallback: decode_get_state_sensor_readings failed with rc={} and compCode={}",
886 msgRc, compCode)
887 .c_str());
888 pldmIface->pldmClose();
889 return -1;
890 }
891
892 pldmIface->pldmClose();
893
894 const uint8_t instance = pldmIface->pldmResponseOcc;
895 const uint8_t occSensorState = field[0].present_state;
896 pldmIface->pldmResponseReceived = true;
897
898 if (occSensorState == PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE)
899 {
900 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600901 std::format("pldmRspCallback: OCC{} is RUNNING", instance).c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600902 pldmIface->callBack(instance, true);
903 }
Chris Cain733b2012022-05-04 11:54:06 -0500904 else if (occSensorState ==
905 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT)
906 {
Chris Cain755af102024-02-27 16:09:51 -0600907 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600908 std::format(
Chris Cain733b2012022-05-04 11:54:06 -0500909 "pldmRspCallback: OCC{} has now STOPPED and system is in SAFE MODE",
910 instance)
911 .c_str());
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500912
913 // Setting safe mode true
914 pldmIface->safeModeCallBack(true);
915
Chris Cain733b2012022-05-04 11:54:06 -0500916 pldmIface->callBack(instance, false);
917 }
Chris Cain755af102024-02-27 16:09:51 -0600918 else if (occSensorState ==
919 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED)
Chris Cainbae4d072022-02-28 09:46:50 -0600920 {
921 log<level::INFO>(
Chris Cain755af102024-02-27 16:09:51 -0600922 std::format("pldmRspCallback: OCC{} is not running", instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600923 .c_str());
Chris Cain755af102024-02-27 16:09:51 -0600924 pldmIface->callBack(instance, false);
925 }
926 else
927 {
928 const size_t rspLength = responseMsgSize + sizeof(pldm_msg_hdr);
929 std::vector<std::uint8_t> pldmResponse(rspLength);
930 memcpy(&pldmResponse[0], reinterpret_cast<std::uint8_t*>(response),
931 rspLength);
932 if (!throttleTraces)
Chris Cainc9dc4412023-03-06 15:56:34 -0600933 {
Chris Cain755af102024-02-27 16:09:51 -0600934 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -0600935 std::format(
Chris Cain755af102024-02-27 16:09:51 -0600936 "pldmRspCallback: Unexpected State: {} - PLDM response ({} bytes) for OCC{}:",
937 occSensorState, rspLength, instance)
Chris Cainc9dc4412023-03-06 15:56:34 -0600938 .c_str());
939 dump_hex(pldmResponse);
940 }
Chris Cainbae4d072022-02-28 09:46:50 -0600941 }
942
943 return 0;
944};
945
Patrick Williamsd7542c82024-08-16 15:20:28 -0400946std::vector<uint8_t>
947 Interface::encodeGetStateSensorRequest(uint8_t instance, uint16_t sensorId)
Chris Cainbae4d072022-02-28 09:46:50 -0600948{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100949 if (!getPldmInstanceId())
Chris Cain8b508bf2022-05-26 14:01:31 -0500950 {
951 log<level::ERR>(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100952 "encodeGetStateSensorRequest: failed to getPldmInstanceId");
Chris Cain8b508bf2022-05-26 14:01:31 -0500953 return std::vector<uint8_t>();
954 }
955
Chris Cainbae4d072022-02-28 09:46:50 -0600956 bitfield8_t sRearm = {0};
Patrick Williamsd7542c82024-08-16 15:20:28 -0400957 const size_t msgSize =
958 sizeof(pldm_msg_hdr) + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES;
Chris Cainbae4d072022-02-28 09:46:50 -0600959 std::vector<uint8_t> request(msgSize);
Chris Cain8b508bf2022-05-26 14:01:31 -0500960
Chris Cainbae4d072022-02-28 09:46:50 -0600961 auto msg = reinterpret_cast<pldm_msg*>(request.data());
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100962 auto msgRc = encode_get_state_sensor_readings_req(pldmInstanceID.value(),
Chris Cain8b508bf2022-05-26 14:01:31 -0500963 sensorId, sRearm, 0, msg);
Chris Cainbae4d072022-02-28 09:46:50 -0600964 if (msgRc != PLDM_SUCCESS)
965 {
966 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600967 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600968 "encodeGetStateSensorRequest: Failed to encode sensorId:0x{:08X} for OCC{} (rc={})",
969 sensorId, instance, msgRc)
970 .c_str());
971 }
972 return request;
973}
974
975// Initiate query of the specified OCC Active Sensor
976void Interface::checkActiveSensor(uint8_t instance)
977{
978 static bool tracedOnce = false;
979 if (pldmFd > 0)
980 {
Chris Cain755af102024-02-27 16:09:51 -0600981 if (!throttleTraces && !tracedOnce)
Chris Caind1b68262022-02-28 09:56:50 -0600982 {
Chris Cain755af102024-02-27 16:09:51 -0600983 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -0600984 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600985 "checkActiveSensor: already waiting on OCC{} (fd={})",
986 pldmResponseOcc, pldmFd)
Chris Caind1b68262022-02-28 09:56:50 -0600987 .c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600988 tracedOnce = true;
Chris Caind1b68262022-02-28 09:56:50 -0600989 }
Chris Cainbae4d072022-02-28 09:46:50 -0600990 return;
991 }
992 tracedOnce = false;
993
994 if (!isOCCSensorCacheValid())
995 {
996 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
997 sensorToOCCInstance, OCCSensorOffset);
998 }
999
1000 // look up sensor id (key) based on instance
1001 auto entry = std::find_if(
1002 sensorToOCCInstance.begin(), sensorToOCCInstance.end(),
1003 [instance](const auto& entry) { return instance == entry.second; });
1004 if (entry != sensorToOCCInstance.end())
1005 {
1006 // Query the OCC Active Sensor state for this instance
Chris Cain755af102024-02-27 16:09:51 -06001007 if (!throttleTraces)
1008 {
1009 log<level::INFO>(
1010 std::format("checkActiveSensor: OCC{} / sensorID: 0x{:04X}",
1011 instance, entry->first)
1012 .c_str());
1013 }
Chris Cainbae4d072022-02-28 09:46:50 -06001014
Chris Cainbae4d072022-02-28 09:46:50 -06001015 // Encode GetStateSensorReadings PLDM message
1016 auto request = encodeGetStateSensorRequest(instance, entry->first);
1017 if (request.empty())
1018 {
1019 return;
1020 }
1021
1022 // Send request to PLDM and setup callback for response
1023 sendPldm(request, instance, true);
1024 }
1025 else
1026 {
Chris Cain755af102024-02-27 16:09:51 -06001027 if (!throttleTraces)
1028 {
1029 log<level::ERR>(
1030 std::format(
1031 "checkActiveSensor: Unable to find PLDM sensor for OCC{}",
1032 instance)
1033 .c_str());
1034 log<level::INFO>(
1035 "checkActiveSensor: fetching STATE_SET_OPERATIONAL_RUNNING_STATUS");
1036 }
Chris Cain8cf74962022-06-29 08:45:16 -05001037 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
1038 sensorToOCCInstance, OCCSensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -05001039 }
Patrick Williams05e95592021-09-02 09:28:14 -05001040}
1041
Chris Cain755af102024-02-27 16:09:51 -06001042void Interface::setTraceThrottle(const bool throttle)
1043{
1044 if (throttle != throttleTraces)
1045 {
1046 if (throttle)
1047 {
1048 log<level::WARNING>("PLDM traces being throttled");
1049 }
1050 else
1051 {
1052 log<level::INFO>("PLDM traces no longer being throttled");
1053 }
1054 throttleTraces = throttle;
1055 }
1056}
1057
Patrick Williams05e95592021-09-02 09:28:14 -05001058} // namespace pldm