blob: 67c8cc40274d3d27b057291c585b8c52cabbe819 [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>
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -050012#include <libpldm/transport/af-mctp.h>
Rashmica Gupta52328cb2023-02-15 10:38:16 +110013#include <libpldm/transport/mctp-demux.h>
14#include <poll.h>
Patrick Williams05e95592021-09-02 09:28:14 -050015
16#include <phosphor-logging/log.hpp>
Chris Cainbae4d072022-02-28 09:46:50 -060017#include <sdbusplus/bus.hpp>
18#include <sdeventplus/clock.hpp>
19#include <sdeventplus/exception.hpp>
20#include <sdeventplus/source/io.hpp>
21#include <sdeventplus/source/time.hpp>
22
23#include <algorithm>
Patrick Williams48002492024-02-13 21:43:32 -060024#include <format>
Patrick Williams05e95592021-09-02 09:28:14 -050025
26namespace pldm
27{
28
Patrick Williams05e95592021-09-02 09:28:14 -050029using namespace phosphor::logging;
30
Chris Cainbae4d072022-02-28 09:46:50 -060031using namespace sdeventplus;
32using namespace sdeventplus::source;
33constexpr auto clockId = sdeventplus::ClockId::RealTime;
34using Clock = sdeventplus::Clock<clockId>;
35using Timer = Time<clockId>;
Chris Cain755af102024-02-27 16:09:51 -060036bool Interface::throttleTraces = false;
Chris Cainbae4d072022-02-28 09:46:50 -060037
Eddie Jamescbad2192021-10-07 09:39:39 -050038void Interface::fetchSensorInfo(uint16_t stateSetId,
39 SensorToInstance& sensorInstanceMap,
40 SensorOffset& sensorOffset)
Patrick Williams05e95592021-09-02 09:28:14 -050041{
Eddie Jamescbad2192021-10-07 09:39:39 -050042 PdrList pdrs{};
Chris Cainbae4d072022-02-28 09:46:50 -060043 static bool tracedError = false;
Eddie Jamescbad2192021-10-07 09:39:39 -050044
45 auto& bus = open_power::occ::utils::getBus();
46 try
47 {
48 auto method = bus.new_method_call(
49 "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
50 "xyz.openbmc_project.PLDM.PDR", "FindStateSensorPDR");
Chris Cainbae4d072022-02-28 09:46:50 -060051 method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId);
Eddie Jamescbad2192021-10-07 09:39:39 -050052
53 auto responseMsg = bus.call(method);
54 responseMsg.read(pdrs);
55 }
Patrick Williamsaf408082022-07-22 19:26:54 -050056 catch (const sdbusplus::exception_t& e)
Eddie Jamescbad2192021-10-07 09:39:39 -050057 {
Chris Cainbae4d072022-02-28 09:46:50 -060058 if (!tracedError)
59 {
60 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -060061 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -060062 "fetchSensorInfo: Failed to find stateSetID:{} PDR: {}",
63 stateSetId, e.what())
64 .c_str());
65 tracedError = true;
66 }
Eddie Jamescbad2192021-10-07 09:39:39 -050067 }
68
69 if (pdrs.empty())
70 {
Chris Cainbae4d072022-02-28 09:46:50 -060071 if (!tracedError)
72 {
73 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -060074 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -060075 "fetchSensorInfo: state sensor PDRs ({}) not present",
76 stateSetId)
77 .c_str());
78 tracedError = true;
79 }
Eddie Jamescbad2192021-10-07 09:39:39 -050080 return;
81 }
82
Chris Cainbae4d072022-02-28 09:46:50 -060083 // Found PDR
84 if (tracedError)
85 {
86 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -060087 std::format("fetchSensorInfo: found {} PDRs", pdrs.size()).c_str());
Chris Cainbae4d072022-02-28 09:46:50 -060088 tracedError = false;
89 }
90
Patrick Williams05e95592021-09-02 09:28:14 -050091 bool offsetFound = false;
George Liuf3a4a692021-12-28 13:59:51 +080092 auto stateSensorPDR =
Patrick Williams05e95592021-09-02 09:28:14 -050093 reinterpret_cast<const pldm_state_sensor_pdr*>(pdrs.front().data());
George Liuf3a4a692021-12-28 13:59:51 +080094 auto possibleStatesPtr = stateSensorPDR->possible_states;
95 for (auto offset = 0; offset < stateSensorPDR->composite_sensor_count;
96 offset++)
Patrick Williams05e95592021-09-02 09:28:14 -050097 {
98 auto possibleStates =
99 reinterpret_cast<const state_sensor_possible_states*>(
100 possibleStatesPtr);
101
Eddie Jamescbad2192021-10-07 09:39:39 -0500102 if (possibleStates->state_set_id == stateSetId)
Patrick Williams05e95592021-09-02 09:28:14 -0500103 {
104 sensorOffset = offset;
105 offsetFound = true;
106 break;
107 }
108 possibleStatesPtr += sizeof(possibleStates->state_set_id) +
109 sizeof(possibleStates->possible_states_size) +
110 possibleStates->possible_states_size;
111 }
112
113 if (!offsetFound)
114 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500115 log<level::ERR>("pldm: state sensor PDR not found");
Patrick Williams05e95592021-09-02 09:28:14 -0500116 return;
117 }
118
119 // To order SensorID based on the EntityInstance.
120 // Note that when a proc is on a DCM, the PDRs for these sensors
121 // could have the same instance IDs but different container IDs.
122 std::map<uint32_t, SensorID> entityInstMap{};
123 for (auto& pdr : pdrs)
124 {
125 auto pdrPtr =
126 reinterpret_cast<const pldm_state_sensor_pdr*>(pdr.data());
Chris Cain72d01aa2022-06-14 16:28:03 -0500127 uint32_t key = pdrPtr->sensor_id;
Patrick Williams05e95592021-09-02 09:28:14 -0500128 entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->sensor_id));
129 }
130
131 open_power::occ::instanceID count = start;
Patrick Williamsa49c9872023-05-10 07:50:35 -0500132 for (const auto& pair : entityInstMap)
Patrick Williams05e95592021-09-02 09:28:14 -0500133 {
134 sensorInstanceMap.emplace(pair.second, count);
135 count++;
136 }
137}
138
Patrick Williamsaf408082022-07-22 19:26:54 -0500139void Interface::sensorEvent(sdbusplus::message_t& msg)
Patrick Williams05e95592021-09-02 09:28:14 -0500140{
141 if (!isOCCSensorCacheValid())
142 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500143 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
144 sensorToOCCInstance, OCCSensorOffset);
145 }
Patrick Williams05e95592021-09-02 09:28:14 -0500146
Eddie Jamescbad2192021-10-07 09:39:39 -0500147 if (sensorToSBEInstance.empty())
148 {
149 fetchSensorInfo(PLDM_OEM_IBM_SBE_HRESET_STATE, sensorToSBEInstance,
150 SBESensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -0500151 }
152
Chris Cain72d01aa2022-06-14 16:28:03 -0500153 TerminusID sensorTid{};
Patrick Williams05e95592021-09-02 09:28:14 -0500154 SensorID sensorId{};
155 SensorOffset msgSensorOffset{};
156 EventState eventState{};
157 EventState previousEventState{};
158
Chris Cain72d01aa2022-06-14 16:28:03 -0500159 msg.read(sensorTid, sensorId, msgSensorOffset, eventState,
160 previousEventState);
Patrick Williams05e95592021-09-02 09:28:14 -0500161
Eddie Jamescbad2192021-10-07 09:39:39 -0500162 if (msgSensorOffset == OCCSensorOffset)
Patrick Williams05e95592021-09-02 09:28:14 -0500163 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500164 auto sensorEntry = sensorToOCCInstance.find(sensorId);
Patrick Williams05e95592021-09-02 09:28:14 -0500165
Eddie James432dc482021-11-19 15:29:31 -0600166 if (sensorEntry != sensorToOCCInstance.end())
Eddie Jamescbad2192021-10-07 09:39:39 -0500167 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500168 const uint8_t instance = sensorEntry->second;
Chris Cain755af102024-02-27 16:09:51 -0600169 bool validEvent = true;
Chris Cain7b00cde2023-03-14 15:47:12 -0500170 bool isRunning = false;
Eddie James432dc482021-11-19 15:29:31 -0600171 if (eventState ==
172 static_cast<EventState>(
173 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE))
174 {
175 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600176 std::format("PLDM: OCC{} is RUNNING", instance).c_str());
Chris Cain7b00cde2023-03-14 15:47:12 -0500177 isRunning = true;
Eddie James432dc482021-11-19 15:29:31 -0600178 }
179 else if (eventState ==
180 static_cast<EventState>(
181 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED))
182 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500183 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600184 std::format("PLDM: OCC{} has now STOPPED", instance)
Chris Cain8b508bf2022-05-26 14:01:31 -0500185 .c_str());
Eddie James432dc482021-11-19 15:29:31 -0600186 }
Chris Cainbae4d072022-02-28 09:46:50 -0600187 else if (eventState ==
188 static_cast<EventState>(
189 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT))
190 {
Chris Cain755af102024-02-27 16:09:51 -0600191 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600192 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600193 "PLDM: OCC{} has now STOPPED and system is in SAFE MODE",
Chris Cain8b508bf2022-05-26 14:01:31 -0500194 instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600195 .c_str());
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500196
197 // Setting safe mode true
198 safeModeCallBack(true);
Chris Cainbae4d072022-02-28 09:46:50 -0600199 }
200 else
201 {
Chris Cain755af102024-02-27 16:09:51 -0600202 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -0600203 std::format("PLDM: Unexpected PLDM state {} for OCC{}",
Chris Cain8b508bf2022-05-26 14:01:31 -0500204 eventState, instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600205 .c_str());
Chris Cain755af102024-02-27 16:09:51 -0600206 validEvent = false;
Chris Cainbae4d072022-02-28 09:46:50 -0600207 }
Chris Cain755af102024-02-27 16:09:51 -0600208 if (validEvent)
209 {
210 if ((pldmFd > 0) && (instance == pldmResponseOcc))
211 {
212 // Waiting for a response for this OCC, can stop waiting
213 pldmClose();
214 }
215 callBack(instance, isRunning);
216 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500217 return;
218 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500219 }
Eddie James432dc482021-11-19 15:29:31 -0600220
221 if (msgSensorOffset == SBESensorOffset)
Eddie Jamescbad2192021-10-07 09:39:39 -0500222 {
223 auto sensorEntry = sensorToSBEInstance.find(sensorId);
224
Eddie James432dc482021-11-19 15:29:31 -0600225 if (sensorEntry != sensorToSBEInstance.end())
Eddie Jamescbad2192021-10-07 09:39:39 -0500226 {
Chris Cain12d0b822022-04-22 17:29:18 -0500227 const uint8_t instance = sensorEntry->second;
228 auto match = std::find(outstandingHResets.begin(),
229 outstandingHResets.end(), instance);
230 if (match != outstandingHResets.end())
Eddie James432dc482021-11-19 15:29:31 -0600231 {
Chris Cain12d0b822022-04-22 17:29:18 -0500232 outstandingHResets.erase(match);
233 if (eventState == static_cast<EventState>(SBE_HRESET_NOT_READY))
234 {
235 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600236 std::format("pldm: HRESET is NOT READY (OCC{})",
Chris Cain12d0b822022-04-22 17:29:18 -0500237 instance)
238 .c_str());
239 }
240 else if (eventState ==
241 static_cast<EventState>(SBE_HRESET_READY))
242 {
243 sbeCallBack(instance, true);
244 }
245 else if (eventState ==
246 static_cast<EventState>(SBE_HRESET_FAILED))
247 {
248 sbeCallBack(instance, false);
249 }
Eddie James432dc482021-11-19 15:29:31 -0600250 }
Chris Cain12d0b822022-04-22 17:29:18 -0500251 // else request was not from us
Eddie Jamescbad2192021-10-07 09:39:39 -0500252 }
253 }
Patrick Williams05e95592021-09-02 09:28:14 -0500254}
255
Patrick Williamsaf408082022-07-22 19:26:54 -0500256void Interface::hostStateEvent(sdbusplus::message_t& msg)
Chris Cain157467d2022-06-24 11:25:23 -0500257{
258 std::map<std::string, std::variant<std::string>> properties{};
259 std::string interface;
260 msg.read(interface, properties);
261 const auto stateEntry = properties.find("CurrentHostState");
262 if (stateEntry != properties.end())
263 {
264 auto stateEntryValue = stateEntry->second;
265 auto propVal = std::get<std::string>(stateEntryValue);
266 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
267 {
268 clearData();
269 }
270 }
271}
272
Chris Cainbae4d072022-02-28 09:46:50 -0600273void Interface::clearData()
274{
Chris Cain72d01aa2022-06-14 16:28:03 -0500275 if (!sensorToOCCInstance.empty())
276 {
277 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600278 std::format("clearData: Clearing sensorToOCCInstance ({} entries)",
Chris Cain72d01aa2022-06-14 16:28:03 -0500279 sensorToOCCInstance.size())
280 .c_str());
281 for (auto entry : sensorToOCCInstance)
282 {
283 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600284 std::format("clearData: OCC{} / sensorID: 0x{:04X}",
Chris Cain72d01aa2022-06-14 16:28:03 -0500285 entry.second, entry.first)
286 .c_str());
Chris Cain082a6ca2023-03-21 10:27:26 -0500287 callBack(entry.second, false);
Chris Cain72d01aa2022-06-14 16:28:03 -0500288 }
289 sensorToOCCInstance.clear();
290 }
291 if (!occInstanceToEffecter.empty())
292 {
293 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600294 std::format(
Chris Cain72d01aa2022-06-14 16:28:03 -0500295 "clearData: Clearing occInstanceToEffecter ({} entries)",
296 occInstanceToEffecter.size())
297 .c_str());
298 occInstanceToEffecter.clear();
299 }
300 if (!sensorToSBEInstance.empty())
301 {
302 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600303 std::format("clearData: Clearing sensorToSBEInstance ({} entries)",
Chris Cain72d01aa2022-06-14 16:28:03 -0500304 sensorToSBEInstance.size())
305 .c_str());
306 sensorToSBEInstance.clear();
307 }
308 if (!sbeInstanceToEffecter.empty())
309 {
310 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600311 std::format(
Chris Cain72d01aa2022-06-14 16:28:03 -0500312 "clearData: Clearing sbeInstanceToEffecter ({} entries)",
313 sbeInstanceToEffecter.size())
314 .c_str());
315 sbeInstanceToEffecter.clear();
316 }
Chris Cainbae4d072022-02-28 09:46:50 -0600317}
318
Patrick Williamsd7542c82024-08-16 15:20:28 -0400319void Interface::fetchEffecterInfo(
320 uint16_t stateSetId, InstanceToEffecter& instanceToEffecterMap,
321 CompositeEffecterCount& effecterCount, uint8_t& stateIdPos)
Patrick Williams05e95592021-09-02 09:28:14 -0500322{
Eddie Jamescbad2192021-10-07 09:39:39 -0500323 PdrList pdrs{};
324
325 auto& bus = open_power::occ::utils::getBus();
326 try
327 {
328 auto method = bus.new_method_call(
329 "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
330 "xyz.openbmc_project.PLDM.PDR", "FindStateEffecterPDR");
Chris Cainbae4d072022-02-28 09:46:50 -0600331 method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId);
Eddie Jamescbad2192021-10-07 09:39:39 -0500332
333 auto responseMsg = bus.call(method);
334 responseMsg.read(pdrs);
335 }
Patrick Williamsaf408082022-07-22 19:26:54 -0500336 catch (const sdbusplus::exception_t& e)
Eddie Jamescbad2192021-10-07 09:39:39 -0500337 {
338 log<level::ERR>("pldm: Failed to fetch the state effecter PDRs",
339 entry("ERROR=%s", e.what()));
340 }
341
342 if (!pdrs.size())
343 {
344 log<level::ERR>("pldm: state effecter PDRs not present");
345 return;
346 }
347
Patrick Williams05e95592021-09-02 09:28:14 -0500348 bool offsetFound = false;
George Liuf3a4a692021-12-28 13:59:51 +0800349 auto stateEffecterPDR =
Patrick Williams05e95592021-09-02 09:28:14 -0500350 reinterpret_cast<const pldm_state_effecter_pdr*>(pdrs.front().data());
George Liuf3a4a692021-12-28 13:59:51 +0800351 auto possibleStatesPtr = stateEffecterPDR->possible_states;
352 for (auto offset = 0; offset < stateEffecterPDR->composite_effecter_count;
353 offset++)
Patrick Williams05e95592021-09-02 09:28:14 -0500354 {
355 auto possibleStates =
356 reinterpret_cast<const state_effecter_possible_states*>(
357 possibleStatesPtr);
358
Eddie Jamescbad2192021-10-07 09:39:39 -0500359 if (possibleStates->state_set_id == stateSetId)
Patrick Williams05e95592021-09-02 09:28:14 -0500360 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500361 stateIdPos = offset;
George Liuf3a4a692021-12-28 13:59:51 +0800362 effecterCount = stateEffecterPDR->composite_effecter_count;
Patrick Williams05e95592021-09-02 09:28:14 -0500363 offsetFound = true;
364 break;
365 }
366 possibleStatesPtr += sizeof(possibleStates->state_set_id) +
367 sizeof(possibleStates->possible_states_size) +
368 possibleStates->possible_states_size;
369 }
370
371 if (!offsetFound)
372 {
373 return;
374 }
375
Chris Cain0f516522022-02-07 14:48:28 -0600376 std::map<uint32_t, EffecterID> entityInstMap{};
Patrick Williams05e95592021-09-02 09:28:14 -0500377 for (auto& pdr : pdrs)
378 {
379 auto pdrPtr =
380 reinterpret_cast<const pldm_state_effecter_pdr*>(pdr.data());
Chris Cain72d01aa2022-06-14 16:28:03 -0500381 uint32_t key = pdrPtr->effecter_id;
Patrick Williams05e95592021-09-02 09:28:14 -0500382 entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->effecter_id));
383 }
384
385 open_power::occ::instanceID position = start;
Patrick Williamsa49c9872023-05-10 07:50:35 -0500386 for (const auto& pair : entityInstMap)
Patrick Williams05e95592021-09-02 09:28:14 -0500387 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500388 instanceToEffecterMap.emplace(position, pair.second);
Patrick Williams05e95592021-09-02 09:28:14 -0500389 position++;
390 }
391}
392
Patrick Williamsd7542c82024-08-16 15:20:28 -0400393std::vector<uint8_t> Interface::prepareSetEffecterReq(
394 EffecterID effecterId, CompositeEffecterCount effecterCount,
395 uint8_t stateIdPos, uint8_t stateSetValue)
Patrick Williams05e95592021-09-02 09:28:14 -0500396{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100397 if (!getPldmInstanceId())
Chris Cain8b508bf2022-05-26 14:01:31 -0500398 {
399 return std::vector<uint8_t>();
400 }
401
Patrick Williams05e95592021-09-02 09:28:14 -0500402 std::vector<uint8_t> request(
403 sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(effecterCount) +
404 (effecterCount * sizeof(set_effecter_state_field)));
405 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
406 std::vector<set_effecter_state_field> stateField;
407
408 for (uint8_t effecterPos = 0; effecterPos < effecterCount; effecterPos++)
409 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500410 if (effecterPos == stateIdPos)
Patrick Williams05e95592021-09-02 09:28:14 -0500411 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500412 stateField.emplace_back(
413 set_effecter_state_field{PLDM_REQUEST_SET, stateSetValue});
Patrick Williams05e95592021-09-02 09:28:14 -0500414 }
415 else
416 {
417 stateField.emplace_back(
418 set_effecter_state_field{PLDM_NO_CHANGE, 0});
419 }
420 }
421 auto rc = encode_set_state_effecter_states_req(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100422 pldmInstanceID.value(), effecterId, effecterCount, stateField.data(),
Chris Cain8b508bf2022-05-26 14:01:31 -0500423 requestMsg);
Patrick Williams05e95592021-09-02 09:28:14 -0500424 if (rc != PLDM_SUCCESS)
425 {
426 log<level::ERR>("encode set effecter states request returned error ",
427 entry("RC=%d", rc));
428 request.clear();
429 }
430 return request;
431}
432
433void Interface::resetOCC(open_power::occ::instanceID occInstanceId)
434{
Chris Cainbae4d072022-02-28 09:46:50 -0600435 if (open_power::occ::utils::isHostRunning())
Patrick Williams05e95592021-09-02 09:28:14 -0500436 {
Chris Cainbae4d072022-02-28 09:46:50 -0600437 if (!isPDREffecterCacheValid())
438 {
439 fetchEffecterInfo(PLDM_STATE_SET_BOOT_RESTART_CAUSE,
440 occInstanceToEffecter, OCCEffecterCount,
441 bootRestartPosition);
442 }
Patrick Williams05e95592021-09-02 09:28:14 -0500443
Chris Cainbae4d072022-02-28 09:46:50 -0600444 // Find the matching effecter for the OCC instance
445 auto effecterEntry = occInstanceToEffecter.find(occInstanceId);
446 if (effecterEntry == occInstanceToEffecter.end())
447 {
448 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600449 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600450 "pldm: Failed to find a matching effecter for OCC instance {}",
451 occInstanceId)
452 .c_str());
453
454 return;
455 }
456
Chris Cainbae4d072022-02-28 09:46:50 -0600457 // Prepare the SetStateEffecterStates request to reset the OCC
458 auto request = prepareSetEffecterReq(
Chris Cain8b508bf2022-05-26 14:01:31 -0500459 effecterEntry->second, OCCEffecterCount, bootRestartPosition,
460 PLDM_STATE_SET_BOOT_RESTART_CAUSE_WARM_RESET);
Chris Cainbae4d072022-02-28 09:46:50 -0600461
462 if (request.empty())
463 {
464 log<level::ERR>(
465 "pldm: SetStateEffecterStates OCC reset request empty");
466 return;
467 }
468
469 // Send request to reset the OCCs/PM Complex (ignore response)
470 sendPldm(request, occInstanceId, false);
471 }
472 else
Patrick Williams05e95592021-09-02 09:28:14 -0500473 {
474 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600475 std::format("resetOCC: HOST is not running (OCC{})", occInstanceId)
Chris Cain0f516522022-02-07 14:48:28 -0600476 .c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600477 clearData();
Patrick Williams05e95592021-09-02 09:28:14 -0500478 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500479}
480
481void Interface::sendHRESET(open_power::occ::instanceID sbeInstanceId)
482{
Chris Cainbae4d072022-02-28 09:46:50 -0600483 if (open_power::occ::utils::isHostRunning())
Eddie Jamescbad2192021-10-07 09:39:39 -0500484 {
Chris Cainbae4d072022-02-28 09:46:50 -0600485 if (sbeInstanceToEffecter.empty())
486 {
487 fetchEffecterInfo(PLDM_OEM_IBM_SBE_MAINTENANCE_STATE,
488 sbeInstanceToEffecter, SBEEffecterCount,
489 sbeMaintenanceStatePosition);
490 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500491
Chris Cainbae4d072022-02-28 09:46:50 -0600492 auto effecterEntry = sbeInstanceToEffecter.find(sbeInstanceId);
493 if (effecterEntry == sbeInstanceToEffecter.end())
494 {
495 log<level::ERR>(
496 "pldm: Failed to find a matching effecter for SBE instance",
497 entry("SBE=%d", sbeInstanceId));
498 return;
499 }
500
Chris Cainbae4d072022-02-28 09:46:50 -0600501 // Prepare the SetStateEffecterStates request to HRESET the SBE
502 auto request = prepareSetEffecterReq(
Chris Cain8b508bf2022-05-26 14:01:31 -0500503 effecterEntry->second, SBEEffecterCount,
Chris Cainbae4d072022-02-28 09:46:50 -0600504 sbeMaintenanceStatePosition, SBE_RETRY_REQUIRED);
505
506 if (request.empty())
507 {
508 log<level::ERR>(
509 "pldm: SetStateEffecterStates HRESET request empty");
510 return;
511 }
512
513 // Send request to issue HRESET of SBE (ignore response)
514 sendPldm(request, sbeInstanceId, false);
Chris Cain12d0b822022-04-22 17:29:18 -0500515 outstandingHResets.insert(sbeInstanceId);
Chris Cainbae4d072022-02-28 09:46:50 -0600516 }
517 else
Eddie Jamescbad2192021-10-07 09:39:39 -0500518 {
Patrick Williams48002492024-02-13 21:43:32 -0600519 log<level::ERR>(std::format("sendHRESET: HOST is not running (OCC{})",
Chris Cainbae4d072022-02-28 09:46:50 -0600520 sbeInstanceId)
521 .c_str());
522 clearData();
Eddie Jamescbad2192021-10-07 09:39:39 -0500523 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500524}
525
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100526bool Interface::getPldmInstanceId()
Eddie Jamescbad2192021-10-07 09:39:39 -0500527{
Rashmica Guptadb38e912023-05-25 10:33:46 +1000528 pldm_instance_id_t id;
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100529 if (!pldmInstanceID)
Patrick Williams05e95592021-09-02 09:28:14 -0500530 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500531 // Request new instance ID
Rashmica Guptadb38e912023-05-25 10:33:46 +1000532 int rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
533 if (rc == -EAGAIN)
Chris Cain8b508bf2022-05-26 14:01:31 -0500534 {
Rashmica Guptadb38e912023-05-25 10:33:46 +1000535 std::this_thread::sleep_for(std::chrono::milliseconds(100));
536 rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
Chris Cain8b508bf2022-05-26 14:01:31 -0500537 }
Rashmica Guptadb38e912023-05-25 10:33:46 +1000538
539 if (rc)
Chris Cain8b508bf2022-05-26 14:01:31 -0500540 {
541 log<level::ERR>(
Rashmica Guptadb38e912023-05-25 10:33:46 +1000542 std::format(
543 "getPldmInstanceId: Failed to alloc ID for TID {}. RC{}",
544 tid, rc)
Chris Cain8b508bf2022-05-26 14:01:31 -0500545 .c_str());
546 return false;
547 }
Rashmica Guptadb38e912023-05-25 10:33:46 +1000548 pldmInstanceID.emplace(id);
549 if (!throttleTraces)
550 {
551 log<level::INFO>(
552 std::format("got id {} and set PldmInstanceId to {}", id,
553 pldmInstanceID.value())
554 .c_str());
555 }
Patrick Williams05e95592021-09-02 09:28:14 -0500556 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500557 return true;
558}
Patrick Williams05e95592021-09-02 09:28:14 -0500559
Rashmica Guptadb38e912023-05-25 10:33:46 +1000560void Interface::freePldmInstanceId()
561{
562 if (pldmInstanceID)
563 {
564 int rc = pldm_instance_id_free(pldmInstanceIdDb, tid,
565 pldmInstanceID.value());
566 if (rc)
567 {
568 log<level::ERR>(
569 std::format(
570 "freePldmInstanceId: Failed to free ID {} for TID {}. RC{}",
571 pldmInstanceID.value(), tid, rc)
572 .c_str());
573 return;
574 }
575 if (!throttleTraces)
576 {
577 log<level::INFO>(
578 std::format("Freed PLDM instance ID {}", pldmInstanceID.value())
579 .c_str());
580 }
581 pldmInstanceID = std::nullopt;
582 }
583}
584
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500585[[maybe_unused]] int Interface::openMctpDemuxTransport()
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100586{
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500587 impl.mctpDemux = nullptr;
588 int rc = pldm_transport_mctp_demux_init(&impl.mctpDemux);
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100589 if (rc)
590 {
591 log<level::ERR>(
592 std::format(
593 "openMctpDemuxTransport: Failed to init MCTP demux transport, errno={}/{}",
594 rc, strerror(rc))
595 .c_str());
596 return -1;
597 }
598
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500599 if (pldm_transport_mctp_demux_map_tid(impl.mctpDemux, mctpEid, mctpEid))
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100600 {
601 log<level::ERR>(
602 std::format(
603 "openMctpDemuxTransport: Failed to setup tid to eid mapping, errno={}/{}",
604 errno, strerror(errno))
605 .c_str());
606 pldmClose();
607 return -1;
608 }
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500609 pldmTransport = pldm_transport_mctp_demux_core(impl.mctpDemux);
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100610
611 struct pollfd pollfd;
612 if (pldm_transport_mctp_demux_init_pollfd(pldmTransport, &pollfd))
613 {
614 log<level::ERR>(
615 std::format(
616 "openMctpDemuxTransport: Failed to get pollfd , errno={}/{}",
617 errno, strerror(errno))
618 .c_str());
619 pldmClose();
620 return -1;
621 }
622 pldmFd = pollfd.fd;
623 if (!throttleTraces)
624 {
625 log<level::INFO>(
626 std::format("openMctpDemuxTransport: pldmFd has fd={}", pldmFd)
627 .c_str());
628 }
629 return 0;
630}
631
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500632[[maybe_unused]] int Interface::openAfMctpTransport()
633{
634 impl.afMctp = nullptr;
635 int rc = pldm_transport_af_mctp_init(&impl.afMctp);
636 if (rc)
637 {
638 log<level::ERR>(
639 std::format(
640 "openAfMctpTransport: Failed to init af MCTP transport, errno={}/{}",
641 rc, strerror(rc))
642 .c_str());
643 return -1;
644 }
645
646 if (pldm_transport_af_mctp_map_tid(impl.afMctp, mctpEid, mctpEid))
647 {
648 log<level::ERR>(
649 std::format(
650 "openAfMctpTransport: Failed to setup tid to eid mapping, errno={}/{}",
651 errno, strerror(errno))
652 .c_str());
653 pldmClose();
654 return -1;
655 }
656 pldmTransport = pldm_transport_af_mctp_core(impl.afMctp);
657
658 struct pollfd pollfd;
659 if (pldm_transport_af_mctp_init_pollfd(pldmTransport, &pollfd))
660 {
661 log<level::ERR>(
662 std::format(
663 "openAfMctpTransport: Failed to get pollfd , errno={}/{}",
664 errno, strerror(errno))
665 .c_str());
666 pldmClose();
667 return -1;
668 }
669 pldmFd = pollfd.fd;
670 if (!throttleTraces)
671 {
672 log<level::INFO>(
673 std::format("openAfMctpTransport: pldmFd has fd={}", pldmFd)
674 .c_str());
675 }
676 return 0;
677}
678
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100679int Interface::pldmOpen()
680{
681 if (pldmTransport)
682 {
683 log<level::ERR>(
684 std::format("pldmOpen: pldmTransport already setup!, errno={}/{}",
685 errno, strerror(errno))
686 .c_str());
687 return -1;
688 }
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500689#if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX)
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100690 return openMctpDemuxTransport();
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500691#elif defined(PLDM_TRANSPORT_WITH_AF_MCTP)
692 return openAfMctpTransport();
693#else
694 return -1;
695#endif
696
697 return 0;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100698}
699
Chris Cainbae4d072022-02-28 09:46:50 -0600700void Interface::sendPldm(const std::vector<uint8_t>& request,
701 const uint8_t instance, const bool rspExpected)
Eddie Jamescbad2192021-10-07 09:39:39 -0500702{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100703 if (!pldmInstanceID)
Chris Cain8b508bf2022-05-26 14:01:31 -0500704 {
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100705 log<level::ERR>("sendPldm: No PLDM Instance ID found!");
Chris Cain8b508bf2022-05-26 14:01:31 -0500706 return;
707 }
708
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100709 auto rc = pldmOpen();
710 if (rc)
Patrick Williams05e95592021-09-02 09:28:14 -0500711 {
Chris Caind1b68262022-02-28 09:56:50 -0600712 log<level::ERR>(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100713 std::format("sendPldm: pldmOpen failed rc={}", rc).c_str());
Rashmica Guptadb38e912023-05-25 10:33:46 +1000714 freePldmInstanceId();
Patrick Williams05e95592021-09-02 09:28:14 -0500715 return;
716 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500717
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100718 pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEid);
Patrick Williams05e95592021-09-02 09:28:14 -0500719 // Send the PLDM request message to HBRT
Chris Cainbae4d072022-02-28 09:46:50 -0600720 if (rspExpected)
Patrick Williams05e95592021-09-02 09:28:14 -0500721 {
Chris Cainbae4d072022-02-28 09:46:50 -0600722 // Register callback when response is available
723 registerPldmRspCallback();
724
725 // Send PLDM request
Chris Cain755af102024-02-27 16:09:51 -0600726 if (!throttleTraces)
727 {
728 log<level::INFO>(
729 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100730 "sendPldm: calling pldm_transport_send_msg(OCC{}, instance:{}, {} bytes)",
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100731 instance, pldmInstanceID.value(), request.size())
Chris Cain755af102024-02-27 16:09:51 -0600732 .c_str());
733 }
Chris Cainbae4d072022-02-28 09:46:50 -0600734 pldmResponseReceived = false;
735 pldmResponseTimeout = false;
736 pldmResponseOcc = instance;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100737 auto pldmRc = pldm_transport_send_msg(pldmTransport, pldmTID,
738 request.data(), request.size());
Chris Cainbae4d072022-02-28 09:46:50 -0600739 auto sendErrno = errno;
740 if (pldmRc != PLDM_REQUESTER_SUCCESS)
741 {
742 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600743 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100744 "sendPldm: pldm_transport_send_msg failed with rc={} and errno={}/{}",
Chris Cain5161a022023-08-15 10:07:12 -0500745 static_cast<
746 std::underlying_type_t<pldm_requester_error_codes>>(
747 pldmRc),
748 sendErrno, strerror(sendErrno))
Chris Cainbae4d072022-02-28 09:46:50 -0600749 .c_str());
750 pldmClose();
751 return;
752 }
753
754 // start timer waiting for the response
755 using namespace std::literals::chrono_literals;
Chris Cainbd551de2022-04-26 13:41:16 -0500756 pldmRspTimer.restartOnce(8s);
Chris Cainbae4d072022-02-28 09:46:50 -0600757
758 // Wait for response/timeout
759 }
760 else // not expecting the response
761 {
Chris Cain755af102024-02-27 16:09:51 -0600762 if (!throttleTraces)
763 {
764 log<level::INFO>(
765 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100766 "sendPldm: calling pldm_transport_send_msg(mctpID:{}, fd:{}, {} bytes) for OCC{}",
Chris Cain755af102024-02-27 16:09:51 -0600767 mctpEid, pldmFd, request.size(), instance)
768 .c_str());
769 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100770 auto rc = pldm_transport_send_msg(pldmTransport, pldmTID,
771 request.data(), request.size());
Chris Cainbae4d072022-02-28 09:46:50 -0600772 auto sendErrno = errno;
Chris Caind1b68262022-02-28 09:56:50 -0600773 if (rc)
774 {
775 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600776 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100777 "sendPldm: pldm_transport_send_msg(mctpID:{}, fd:{}, {} bytes) failed with rc={} and errno={}/{}",
Chris Cain5161a022023-08-15 10:07:12 -0500778 mctpEid, pldmFd, request.size(),
779 static_cast<
780 std::underlying_type_t<pldm_requester_error_codes>>(rc),
781 sendErrno, strerror(sendErrno))
Chris Caind1b68262022-02-28 09:56:50 -0600782 .c_str());
783 }
Chris Cainbae4d072022-02-28 09:46:50 -0600784 pldmClose();
785 }
786}
Patrick Williams05e95592021-09-02 09:28:14 -0500787
Chris Cainbae4d072022-02-28 09:46:50 -0600788// Attaches the FD to event loop and registers the callback handler
789void Interface::registerPldmRspCallback()
790{
791 decltype(eventSource.get()) sourcePtr = nullptr;
792 auto rc = sd_event_add_io(event.get(), &sourcePtr, pldmFd, EPOLLIN,
793 pldmRspCallback, this);
794 if (rc < 0)
795 {
796 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600797 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600798 "registerPldmRspCallback: sd_event_add_io: Error({})={} : fd={}",
799 rc, strerror(-rc), pldmFd)
800 .c_str());
Chris Caind1b68262022-02-28 09:56:50 -0600801 }
802 else
Patrick Williams05e95592021-09-02 09:28:14 -0500803 {
Chris Cainbae4d072022-02-28 09:46:50 -0600804 // puts sourcePtr in the event source.
805 eventSource.reset(sourcePtr);
806 }
807}
808
809// Add a timer to the event loop, default 30s.
810void Interface::pldmRspExpired()
811{
812 if (!pldmResponseReceived)
813 {
Chris Cain755af102024-02-27 16:09:51 -0600814 if (!throttleTraces)
815 {
816 log<level::WARNING>(
817 std::format(
818 "pldmRspExpired: timerCallback - timeout waiting for pldm response for OCC{}",
819 pldmResponseOcc)
820 .c_str());
821 }
Chris Cainbae4d072022-02-28 09:46:50 -0600822 pldmResponseTimeout = true;
823 if (pldmFd)
824 {
825 pldmClose();
826 }
827 }
828 return;
829};
830
831void Interface::pldmClose()
832{
Rashmica Guptadb38e912023-05-25 10:33:46 +1000833 freePldmInstanceId();
Chris Cainbae4d072022-02-28 09:46:50 -0600834 if (pldmRspTimer.isEnabled())
835 {
836 // stop PLDM response timer
837 pldmRspTimer.setEnabled(false);
838 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100839
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500840#if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX)
841 pldm_transport_mctp_demux_destroy(impl.mctpDemux);
842 impl.mctpDemux = NULL;
843#elif defined(PLDM_TRANSPORT_WITH_AF_MCTP)
844 pldm_transport_af_mctp_destroy(impl.afMctp);
845 impl.afMctp = NULL;
846#endif
Chris Cainbae4d072022-02-28 09:46:50 -0600847 pldmFd = -1;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100848 pldmTransport = NULL;
Chris Cainbae4d072022-02-28 09:46:50 -0600849 eventSource.reset();
850}
851
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100852int Interface::pldmRspCallback(sd_event_source* /*es*/,
853 __attribute__((unused)) int fd, uint32_t revents,
854 void* userData)
Chris Cainbae4d072022-02-28 09:46:50 -0600855{
856 if (!(revents & EPOLLIN))
857 {
858 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600859 std::format("pldmRspCallback - revents={:08X}", revents).c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600860 return -1;
861 }
862
863 auto pldmIface = static_cast<Interface*>(userData);
864
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100865 if (!pldmIface->pldmInstanceID)
Chris Cain8b508bf2022-05-26 14:01:31 -0500866 {
867 log<level::ERR>(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100868 "pldmRspCallback: No outstanding PLDM Instance ID found");
Chris Cain8b508bf2022-05-26 14:01:31 -0500869 return -1;
870 }
871
Chris Cainbae4d072022-02-28 09:46:50 -0600872 uint8_t* responseMsg = nullptr;
873 size_t responseMsgSize{};
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100874 pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEid);
Chris Cainbae4d072022-02-28 09:46:50 -0600875
Chris Cain755af102024-02-27 16:09:51 -0600876 if (!throttleTraces)
877 {
878 log<level::INFO>(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100879 std::format(
880 "pldmRspCallback: calling pldm_transport_recv_msg() instance:{}",
881 pldmIface->pldmInstanceID.value())
Chris Cain755af102024-02-27 16:09:51 -0600882 .c_str());
883 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100884 auto rc = pldm_transport_recv_msg(pldmIface->pldmTransport, &pldmTID,
885 (void**)&responseMsg, &responseMsgSize);
Chris Cainbae4d072022-02-28 09:46:50 -0600886 int lastErrno = errno;
887 if (rc)
888 {
Chris Cain755af102024-02-27 16:09:51 -0600889 if (!throttleTraces)
890 {
891 log<level::ERR>(
892 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100893 "pldmRspCallback: pldm_transport_recv_msg failed with rc={}, errno={}/{}",
Chris Cain755af102024-02-27 16:09:51 -0600894 static_cast<
895 std::underlying_type_t<pldm_requester_error_codes>>(rc),
896 lastErrno, strerror(lastErrno))
897 .c_str());
898 }
Chris Cainbae4d072022-02-28 09:46:50 -0600899 return -1;
900 }
Chris Cain8b508bf2022-05-26 14:01:31 -0500901
902 // We got the response for the PLDM request msg that was sent
Chris Cain755af102024-02-27 16:09:51 -0600903 if (!throttleTraces)
904 {
905 log<level::INFO>(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100906 std::format(
907 "pldmRspCallback: pldm_transport_recv_msg() rsp was {} bytes",
908 responseMsgSize)
Chris Cain755af102024-02-27 16:09:51 -0600909 .c_str());
910 }
Chris Cainbae4d072022-02-28 09:46:50 -0600911
912 if (pldmIface->pldmRspTimer.isEnabled())
913 {
914 // stop PLDM response timer
915 pldmIface->pldmRspTimer.setEnabled(false);
916 }
917
Chris Cain8b508bf2022-05-26 14:01:31 -0500918 // instance ID should be freed
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100919 pldmIface->pldmInstanceID = std::nullopt;
Chris Cain8b508bf2022-05-26 14:01:31 -0500920
Chris Cainbae4d072022-02-28 09:46:50 -0600921 // Set pointer to autodelete
Patrick Williamsd7542c82024-08-16 15:20:28 -0400922 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{
923 responseMsg, std::free};
Chris Cainbae4d072022-02-28 09:46:50 -0600924
Chris Cainbae4d072022-02-28 09:46:50 -0600925 auto response = reinterpret_cast<pldm_msg*>(responseMsgPtr.get());
926 if (response->payload[0] != PLDM_SUCCESS)
927 {
928 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600929 std::format("pldmRspCallback: payload[0] was not success: {}",
Chris Cainbae4d072022-02-28 09:46:50 -0600930 response->payload[0])
931 .c_str());
932 pldmIface->pldmClose();
933 return -1;
934 }
935
936 // Decode the response
937 uint8_t compCode = 0, sensorCount = 1;
938 get_sensor_state_field field[6];
939 responseMsgSize -= sizeof(pldm_msg_hdr);
940 auto msgRc = decode_get_state_sensor_readings_resp(
941 response, responseMsgSize, &compCode, &sensorCount, field);
942 if ((msgRc != PLDM_SUCCESS) || (compCode != PLDM_SUCCESS))
943 {
944 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600945 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600946 "pldmRspCallback: decode_get_state_sensor_readings failed with rc={} and compCode={}",
947 msgRc, compCode)
948 .c_str());
949 pldmIface->pldmClose();
950 return -1;
951 }
952
953 pldmIface->pldmClose();
954
955 const uint8_t instance = pldmIface->pldmResponseOcc;
956 const uint8_t occSensorState = field[0].present_state;
957 pldmIface->pldmResponseReceived = true;
958
959 if (occSensorState == PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE)
960 {
961 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600962 std::format("pldmRspCallback: OCC{} is RUNNING", instance).c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600963 pldmIface->callBack(instance, true);
964 }
Chris Cain733b2012022-05-04 11:54:06 -0500965 else if (occSensorState ==
966 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT)
967 {
Chris Cain755af102024-02-27 16:09:51 -0600968 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600969 std::format(
Chris Cain733b2012022-05-04 11:54:06 -0500970 "pldmRspCallback: OCC{} has now STOPPED and system is in SAFE MODE",
971 instance)
972 .c_str());
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500973
974 // Setting safe mode true
975 pldmIface->safeModeCallBack(true);
976
Chris Cain733b2012022-05-04 11:54:06 -0500977 pldmIface->callBack(instance, false);
978 }
Chris Cain755af102024-02-27 16:09:51 -0600979 else if (occSensorState ==
980 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED)
Chris Cainbae4d072022-02-28 09:46:50 -0600981 {
982 log<level::INFO>(
Chris Cain755af102024-02-27 16:09:51 -0600983 std::format("pldmRspCallback: OCC{} is not running", instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600984 .c_str());
Chris Cain755af102024-02-27 16:09:51 -0600985 pldmIface->callBack(instance, false);
986 }
987 else
988 {
989 const size_t rspLength = responseMsgSize + sizeof(pldm_msg_hdr);
990 std::vector<std::uint8_t> pldmResponse(rspLength);
991 memcpy(&pldmResponse[0], reinterpret_cast<std::uint8_t*>(response),
992 rspLength);
993 if (!throttleTraces)
Chris Cainc9dc4412023-03-06 15:56:34 -0600994 {
Chris Cain755af102024-02-27 16:09:51 -0600995 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -0600996 std::format(
Chris Cain755af102024-02-27 16:09:51 -0600997 "pldmRspCallback: Unexpected State: {} - PLDM response ({} bytes) for OCC{}:",
998 occSensorState, rspLength, instance)
Chris Cainc9dc4412023-03-06 15:56:34 -0600999 .c_str());
1000 dump_hex(pldmResponse);
1001 }
Chris Cainbae4d072022-02-28 09:46:50 -06001002 }
1003
1004 return 0;
1005};
1006
Patrick Williamsd7542c82024-08-16 15:20:28 -04001007std::vector<uint8_t>
1008 Interface::encodeGetStateSensorRequest(uint8_t instance, uint16_t sensorId)
Chris Cainbae4d072022-02-28 09:46:50 -06001009{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +11001010 if (!getPldmInstanceId())
Chris Cain8b508bf2022-05-26 14:01:31 -05001011 {
1012 log<level::ERR>(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +11001013 "encodeGetStateSensorRequest: failed to getPldmInstanceId");
Chris Cain8b508bf2022-05-26 14:01:31 -05001014 return std::vector<uint8_t>();
1015 }
1016
Chris Cainbae4d072022-02-28 09:46:50 -06001017 bitfield8_t sRearm = {0};
Patrick Williamsd7542c82024-08-16 15:20:28 -04001018 const size_t msgSize =
1019 sizeof(pldm_msg_hdr) + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES;
Chris Cainbae4d072022-02-28 09:46:50 -06001020 std::vector<uint8_t> request(msgSize);
Chris Cain8b508bf2022-05-26 14:01:31 -05001021
Chris Cainbae4d072022-02-28 09:46:50 -06001022 auto msg = reinterpret_cast<pldm_msg*>(request.data());
Rashmica Guptaaeba51c2023-02-17 12:30:46 +11001023 auto msgRc = encode_get_state_sensor_readings_req(pldmInstanceID.value(),
Chris Cain8b508bf2022-05-26 14:01:31 -05001024 sensorId, sRearm, 0, msg);
Chris Cainbae4d072022-02-28 09:46:50 -06001025 if (msgRc != PLDM_SUCCESS)
1026 {
1027 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -06001028 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -06001029 "encodeGetStateSensorRequest: Failed to encode sensorId:0x{:08X} for OCC{} (rc={})",
1030 sensorId, instance, msgRc)
1031 .c_str());
1032 }
1033 return request;
1034}
1035
1036// Initiate query of the specified OCC Active Sensor
1037void Interface::checkActiveSensor(uint8_t instance)
1038{
1039 static bool tracedOnce = false;
1040 if (pldmFd > 0)
1041 {
Chris Cain755af102024-02-27 16:09:51 -06001042 if (!throttleTraces && !tracedOnce)
Chris Caind1b68262022-02-28 09:56:50 -06001043 {
Chris Cain755af102024-02-27 16:09:51 -06001044 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -06001045 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -06001046 "checkActiveSensor: already waiting on OCC{} (fd={})",
1047 pldmResponseOcc, pldmFd)
Chris Caind1b68262022-02-28 09:56:50 -06001048 .c_str());
Chris Cainbae4d072022-02-28 09:46:50 -06001049 tracedOnce = true;
Chris Caind1b68262022-02-28 09:56:50 -06001050 }
Chris Cainbae4d072022-02-28 09:46:50 -06001051 return;
1052 }
1053 tracedOnce = false;
1054
1055 if (!isOCCSensorCacheValid())
1056 {
1057 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
1058 sensorToOCCInstance, OCCSensorOffset);
1059 }
1060
1061 // look up sensor id (key) based on instance
1062 auto entry = std::find_if(
1063 sensorToOCCInstance.begin(), sensorToOCCInstance.end(),
1064 [instance](const auto& entry) { return instance == entry.second; });
1065 if (entry != sensorToOCCInstance.end())
1066 {
1067 // Query the OCC Active Sensor state for this instance
Chris Cain755af102024-02-27 16:09:51 -06001068 if (!throttleTraces)
1069 {
1070 log<level::INFO>(
1071 std::format("checkActiveSensor: OCC{} / sensorID: 0x{:04X}",
1072 instance, entry->first)
1073 .c_str());
1074 }
Chris Cainbae4d072022-02-28 09:46:50 -06001075
Chris Cainbae4d072022-02-28 09:46:50 -06001076 // Encode GetStateSensorReadings PLDM message
1077 auto request = encodeGetStateSensorRequest(instance, entry->first);
1078 if (request.empty())
1079 {
1080 return;
1081 }
1082
1083 // Send request to PLDM and setup callback for response
1084 sendPldm(request, instance, true);
1085 }
1086 else
1087 {
Chris Cain755af102024-02-27 16:09:51 -06001088 if (!throttleTraces)
1089 {
1090 log<level::ERR>(
1091 std::format(
1092 "checkActiveSensor: Unable to find PLDM sensor for OCC{}",
1093 instance)
1094 .c_str());
1095 log<level::INFO>(
1096 "checkActiveSensor: fetching STATE_SET_OPERATIONAL_RUNNING_STATUS");
1097 }
Chris Cain8cf74962022-06-29 08:45:16 -05001098 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
1099 sensorToOCCInstance, OCCSensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -05001100 }
Patrick Williams05e95592021-09-02 09:28:14 -05001101}
1102
Chris Cain755af102024-02-27 16:09:51 -06001103void Interface::setTraceThrottle(const bool throttle)
1104{
1105 if (throttle != throttleTraces)
1106 {
1107 if (throttle)
1108 {
1109 log<level::WARNING>("PLDM traces being throttled");
1110 }
1111 else
1112 {
1113 log<level::INFO>("PLDM traces no longer being throttled");
1114 }
1115 throttleTraces = throttle;
1116 }
1117}
1118
Patrick Williams05e95592021-09-02 09:28:14 -05001119} // namespace pldm