blob: 4e57eceb0fa7c949518e6b5a563259f0656790f3 [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 Cainf0295f52024-09-12 15:41:14 -050037enum pldm_msg_type Interface::msgType = MSG_UNDEFINED;
38open_power::occ::instanceID Interface::resetInstance = 0;
Chris Cainbae4d072022-02-28 09:46:50 -060039
Eddie Jamescbad2192021-10-07 09:39:39 -050040void Interface::fetchSensorInfo(uint16_t stateSetId,
41 SensorToInstance& sensorInstanceMap,
42 SensorOffset& sensorOffset)
Patrick Williams05e95592021-09-02 09:28:14 -050043{
Eddie Jamescbad2192021-10-07 09:39:39 -050044 PdrList pdrs{};
Chris Cainbae4d072022-02-28 09:46:50 -060045 static bool tracedError = false;
Eddie Jamescbad2192021-10-07 09:39:39 -050046
47 auto& bus = open_power::occ::utils::getBus();
48 try
49 {
50 auto method = bus.new_method_call(
51 "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
52 "xyz.openbmc_project.PLDM.PDR", "FindStateSensorPDR");
Chris Cainbae4d072022-02-28 09:46:50 -060053 method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId);
Eddie Jamescbad2192021-10-07 09:39:39 -050054
55 auto responseMsg = bus.call(method);
56 responseMsg.read(pdrs);
57 }
Patrick Williamsaf408082022-07-22 19:26:54 -050058 catch (const sdbusplus::exception_t& e)
Eddie Jamescbad2192021-10-07 09:39:39 -050059 {
Chris Cainbae4d072022-02-28 09:46:50 -060060 if (!tracedError)
61 {
62 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -060063 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -060064 "fetchSensorInfo: Failed to find stateSetID:{} PDR: {}",
65 stateSetId, e.what())
66 .c_str());
67 tracedError = true;
68 }
Eddie Jamescbad2192021-10-07 09:39:39 -050069 }
70
71 if (pdrs.empty())
72 {
Chris Cainbae4d072022-02-28 09:46:50 -060073 if (!tracedError)
74 {
75 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -060076 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -060077 "fetchSensorInfo: state sensor PDRs ({}) not present",
78 stateSetId)
79 .c_str());
80 tracedError = true;
81 }
Eddie Jamescbad2192021-10-07 09:39:39 -050082 return;
83 }
84
Chris Cainbae4d072022-02-28 09:46:50 -060085 // Found PDR
86 if (tracedError)
87 {
88 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -060089 std::format("fetchSensorInfo: found {} PDRs", pdrs.size()).c_str());
Chris Cainbae4d072022-02-28 09:46:50 -060090 tracedError = false;
91 }
92
Patrick Williams05e95592021-09-02 09:28:14 -050093 bool offsetFound = false;
George Liuf3a4a692021-12-28 13:59:51 +080094 auto stateSensorPDR =
Patrick Williams05e95592021-09-02 09:28:14 -050095 reinterpret_cast<const pldm_state_sensor_pdr*>(pdrs.front().data());
George Liuf3a4a692021-12-28 13:59:51 +080096 auto possibleStatesPtr = stateSensorPDR->possible_states;
97 for (auto offset = 0; offset < stateSensorPDR->composite_sensor_count;
98 offset++)
Patrick Williams05e95592021-09-02 09:28:14 -050099 {
100 auto possibleStates =
101 reinterpret_cast<const state_sensor_possible_states*>(
102 possibleStatesPtr);
103
Eddie Jamescbad2192021-10-07 09:39:39 -0500104 if (possibleStates->state_set_id == stateSetId)
Patrick Williams05e95592021-09-02 09:28:14 -0500105 {
106 sensorOffset = offset;
107 offsetFound = true;
108 break;
109 }
110 possibleStatesPtr += sizeof(possibleStates->state_set_id) +
111 sizeof(possibleStates->possible_states_size) +
112 possibleStates->possible_states_size;
113 }
114
115 if (!offsetFound)
116 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500117 log<level::ERR>("pldm: state sensor PDR not found");
Patrick Williams05e95592021-09-02 09:28:14 -0500118 return;
119 }
120
121 // To order SensorID based on the EntityInstance.
122 // Note that when a proc is on a DCM, the PDRs for these sensors
123 // could have the same instance IDs but different container IDs.
124 std::map<uint32_t, SensorID> entityInstMap{};
125 for (auto& pdr : pdrs)
126 {
127 auto pdrPtr =
128 reinterpret_cast<const pldm_state_sensor_pdr*>(pdr.data());
Chris Cain72d01aa2022-06-14 16:28:03 -0500129 uint32_t key = pdrPtr->sensor_id;
Patrick Williams05e95592021-09-02 09:28:14 -0500130 entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->sensor_id));
131 }
132
133 open_power::occ::instanceID count = start;
Patrick Williamsa49c9872023-05-10 07:50:35 -0500134 for (const auto& pair : entityInstMap)
Patrick Williams05e95592021-09-02 09:28:14 -0500135 {
136 sensorInstanceMap.emplace(pair.second, count);
137 count++;
138 }
139}
140
Patrick Williamsaf408082022-07-22 19:26:54 -0500141void Interface::sensorEvent(sdbusplus::message_t& msg)
Patrick Williams05e95592021-09-02 09:28:14 -0500142{
143 if (!isOCCSensorCacheValid())
144 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500145 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
146 sensorToOCCInstance, OCCSensorOffset);
147 }
Patrick Williams05e95592021-09-02 09:28:14 -0500148
Eddie Jamescbad2192021-10-07 09:39:39 -0500149 if (sensorToSBEInstance.empty())
150 {
151 fetchSensorInfo(PLDM_OEM_IBM_SBE_HRESET_STATE, sensorToSBEInstance,
152 SBESensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -0500153 }
154
Chris Cain72d01aa2022-06-14 16:28:03 -0500155 TerminusID sensorTid{};
Patrick Williams05e95592021-09-02 09:28:14 -0500156 SensorID sensorId{};
157 SensorOffset msgSensorOffset{};
158 EventState eventState{};
159 EventState previousEventState{};
160
Chris Cain72d01aa2022-06-14 16:28:03 -0500161 msg.read(sensorTid, sensorId, msgSensorOffset, eventState,
162 previousEventState);
Patrick Williams05e95592021-09-02 09:28:14 -0500163
Eddie Jamescbad2192021-10-07 09:39:39 -0500164 if (msgSensorOffset == OCCSensorOffset)
Patrick Williams05e95592021-09-02 09:28:14 -0500165 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500166 auto sensorEntry = sensorToOCCInstance.find(sensorId);
Patrick Williams05e95592021-09-02 09:28:14 -0500167
Eddie James432dc482021-11-19 15:29:31 -0600168 if (sensorEntry != sensorToOCCInstance.end())
Eddie Jamescbad2192021-10-07 09:39:39 -0500169 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500170 const uint8_t instance = sensorEntry->second;
Chris Cain755af102024-02-27 16:09:51 -0600171 bool validEvent = true;
Chris Cain7b00cde2023-03-14 15:47:12 -0500172 bool isRunning = false;
Eddie James432dc482021-11-19 15:29:31 -0600173 if (eventState ==
174 static_cast<EventState>(
175 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE))
176 {
177 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600178 std::format("PLDM: OCC{} is RUNNING", instance).c_str());
Chris Cain7b00cde2023-03-14 15:47:12 -0500179 isRunning = true;
Eddie James432dc482021-11-19 15:29:31 -0600180 }
181 else if (eventState ==
182 static_cast<EventState>(
183 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED))
184 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500185 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600186 std::format("PLDM: OCC{} has now STOPPED", instance)
Chris Cain8b508bf2022-05-26 14:01:31 -0500187 .c_str());
Eddie James432dc482021-11-19 15:29:31 -0600188 }
Chris Cainbae4d072022-02-28 09:46:50 -0600189 else if (eventState ==
190 static_cast<EventState>(
191 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT))
192 {
Chris Cain755af102024-02-27 16:09:51 -0600193 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600194 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600195 "PLDM: OCC{} has now STOPPED and system is in SAFE MODE",
Chris Cain8b508bf2022-05-26 14:01:31 -0500196 instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600197 .c_str());
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500198
199 // Setting safe mode true
200 safeModeCallBack(true);
Chris Cainbae4d072022-02-28 09:46:50 -0600201 }
202 else
203 {
Chris Cain755af102024-02-27 16:09:51 -0600204 log<level::WARNING>(
Chris Cainf0295f52024-09-12 15:41:14 -0500205 std::format(
206 "PLDM: Unexpected OCC Active sensor state {} for OCC{}",
207 eventState, instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600208 .c_str());
Chris Cain755af102024-02-27 16:09:51 -0600209 validEvent = false;
Chris Cainbae4d072022-02-28 09:46:50 -0600210 }
Chris Cain755af102024-02-27 16:09:51 -0600211 if (validEvent)
212 {
213 if ((pldmFd > 0) && (instance == pldmResponseOcc))
214 {
215 // Waiting for a response for this OCC, can stop waiting
216 pldmClose();
217 }
Chris Cainf0295f52024-09-12 15:41:14 -0500218 occActiveCallBack(instance, isRunning);
Chris Cain755af102024-02-27 16:09:51 -0600219 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500220 return;
221 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500222 }
Eddie James432dc482021-11-19 15:29:31 -0600223
224 if (msgSensorOffset == SBESensorOffset)
Eddie Jamescbad2192021-10-07 09:39:39 -0500225 {
226 auto sensorEntry = sensorToSBEInstance.find(sensorId);
227
Eddie James432dc482021-11-19 15:29:31 -0600228 if (sensorEntry != sensorToSBEInstance.end())
Eddie Jamescbad2192021-10-07 09:39:39 -0500229 {
Chris Cain12d0b822022-04-22 17:29:18 -0500230 const uint8_t instance = sensorEntry->second;
231 auto match = std::find(outstandingHResets.begin(),
232 outstandingHResets.end(), instance);
233 if (match != outstandingHResets.end())
Eddie James432dc482021-11-19 15:29:31 -0600234 {
Chris Cain12d0b822022-04-22 17:29:18 -0500235 outstandingHResets.erase(match);
236 if (eventState == static_cast<EventState>(SBE_HRESET_NOT_READY))
237 {
Chris Cainf0295f52024-09-12 15:41:14 -0500238 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600239 std::format("pldm: HRESET is NOT READY (OCC{})",
Chris Cain12d0b822022-04-22 17:29:18 -0500240 instance)
241 .c_str());
Chris Cainf0295f52024-09-12 15:41:14 -0500242 // Stop OCC comm - OCC not usable until it becomes READY
243 occActiveCallBack(instance, false);
244 // Collect SBE FFDC
245 sbeCallBack(instance, false);
246 // Try PM Complex reset
247 log<level::ERR>(
248 std::format(
249 "sensorEvent: Requesting OCC reset for OCC{}",
250 instance)
251 .c_str());
252 resetOCC(resetInstance);
Chris Cain12d0b822022-04-22 17:29:18 -0500253 }
254 else if (eventState ==
255 static_cast<EventState>(SBE_HRESET_READY))
256 {
257 sbeCallBack(instance, true);
258 }
259 else if (eventState ==
260 static_cast<EventState>(SBE_HRESET_FAILED))
261 {
262 sbeCallBack(instance, false);
263 }
Chris Cainf0295f52024-09-12 15:41:14 -0500264 else
265 {
266 if (eventState ==
267 static_cast<EventState>(SBE_HRESET_FAILED))
268 log<level::ERR>(
269 std::format(
270 "pldm: Unexpected HRESET state {} (OCC{})",
271 eventState, instance)
272 .c_str());
273 sbeCallBack(instance, false);
274 }
Eddie James432dc482021-11-19 15:29:31 -0600275 }
Chris Cain12d0b822022-04-22 17:29:18 -0500276 // else request was not from us
Eddie Jamescbad2192021-10-07 09:39:39 -0500277 }
278 }
Patrick Williams05e95592021-09-02 09:28:14 -0500279}
280
Patrick Williamsaf408082022-07-22 19:26:54 -0500281void Interface::hostStateEvent(sdbusplus::message_t& msg)
Chris Cain157467d2022-06-24 11:25:23 -0500282{
283 std::map<std::string, std::variant<std::string>> properties{};
284 std::string interface;
285 msg.read(interface, properties);
286 const auto stateEntry = properties.find("CurrentHostState");
287 if (stateEntry != properties.end())
288 {
289 auto stateEntryValue = stateEntry->second;
290 auto propVal = std::get<std::string>(stateEntryValue);
291 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
292 {
293 clearData();
294 }
295 }
296}
297
Chris Cainbae4d072022-02-28 09:46:50 -0600298void Interface::clearData()
299{
Chris Cain72d01aa2022-06-14 16:28:03 -0500300 if (!sensorToOCCInstance.empty())
301 {
302 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600303 std::format("clearData: Clearing sensorToOCCInstance ({} entries)",
Chris Cain72d01aa2022-06-14 16:28:03 -0500304 sensorToOCCInstance.size())
305 .c_str());
306 for (auto entry : sensorToOCCInstance)
307 {
308 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600309 std::format("clearData: OCC{} / sensorID: 0x{:04X}",
Chris Cain72d01aa2022-06-14 16:28:03 -0500310 entry.second, entry.first)
311 .c_str());
Chris Cainf0295f52024-09-12 15:41:14 -0500312 occActiveCallBack(entry.second, false);
Chris Cain72d01aa2022-06-14 16:28:03 -0500313 }
314 sensorToOCCInstance.clear();
315 }
316 if (!occInstanceToEffecter.empty())
317 {
318 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600319 std::format(
Chris Cain72d01aa2022-06-14 16:28:03 -0500320 "clearData: Clearing occInstanceToEffecter ({} entries)",
321 occInstanceToEffecter.size())
322 .c_str());
323 occInstanceToEffecter.clear();
324 }
325 if (!sensorToSBEInstance.empty())
326 {
327 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600328 std::format("clearData: Clearing sensorToSBEInstance ({} entries)",
Chris Cain72d01aa2022-06-14 16:28:03 -0500329 sensorToSBEInstance.size())
330 .c_str());
331 sensorToSBEInstance.clear();
332 }
333 if (!sbeInstanceToEffecter.empty())
334 {
335 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600336 std::format(
Chris Cain72d01aa2022-06-14 16:28:03 -0500337 "clearData: Clearing sbeInstanceToEffecter ({} entries)",
338 sbeInstanceToEffecter.size())
339 .c_str());
340 sbeInstanceToEffecter.clear();
341 }
Chris Cainbae4d072022-02-28 09:46:50 -0600342}
343
Patrick Williamsd7542c82024-08-16 15:20:28 -0400344void Interface::fetchEffecterInfo(
345 uint16_t stateSetId, InstanceToEffecter& instanceToEffecterMap,
346 CompositeEffecterCount& effecterCount, uint8_t& stateIdPos)
Patrick Williams05e95592021-09-02 09:28:14 -0500347{
Eddie Jamescbad2192021-10-07 09:39:39 -0500348 PdrList pdrs{};
349
350 auto& bus = open_power::occ::utils::getBus();
351 try
352 {
353 auto method = bus.new_method_call(
354 "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
355 "xyz.openbmc_project.PLDM.PDR", "FindStateEffecterPDR");
Chris Cainbae4d072022-02-28 09:46:50 -0600356 method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId);
Eddie Jamescbad2192021-10-07 09:39:39 -0500357
358 auto responseMsg = bus.call(method);
359 responseMsg.read(pdrs);
360 }
Patrick Williamsaf408082022-07-22 19:26:54 -0500361 catch (const sdbusplus::exception_t& e)
Eddie Jamescbad2192021-10-07 09:39:39 -0500362 {
363 log<level::ERR>("pldm: Failed to fetch the state effecter PDRs",
364 entry("ERROR=%s", e.what()));
365 }
366
367 if (!pdrs.size())
368 {
369 log<level::ERR>("pldm: state effecter PDRs not present");
370 return;
371 }
372
Patrick Williams05e95592021-09-02 09:28:14 -0500373 bool offsetFound = false;
George Liuf3a4a692021-12-28 13:59:51 +0800374 auto stateEffecterPDR =
Patrick Williams05e95592021-09-02 09:28:14 -0500375 reinterpret_cast<const pldm_state_effecter_pdr*>(pdrs.front().data());
George Liuf3a4a692021-12-28 13:59:51 +0800376 auto possibleStatesPtr = stateEffecterPDR->possible_states;
377 for (auto offset = 0; offset < stateEffecterPDR->composite_effecter_count;
378 offset++)
Patrick Williams05e95592021-09-02 09:28:14 -0500379 {
380 auto possibleStates =
381 reinterpret_cast<const state_effecter_possible_states*>(
382 possibleStatesPtr);
383
Eddie Jamescbad2192021-10-07 09:39:39 -0500384 if (possibleStates->state_set_id == stateSetId)
Patrick Williams05e95592021-09-02 09:28:14 -0500385 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500386 stateIdPos = offset;
George Liuf3a4a692021-12-28 13:59:51 +0800387 effecterCount = stateEffecterPDR->composite_effecter_count;
Patrick Williams05e95592021-09-02 09:28:14 -0500388 offsetFound = true;
389 break;
390 }
391 possibleStatesPtr += sizeof(possibleStates->state_set_id) +
392 sizeof(possibleStates->possible_states_size) +
393 possibleStates->possible_states_size;
394 }
395
396 if (!offsetFound)
397 {
398 return;
399 }
400
Chris Cain0f516522022-02-07 14:48:28 -0600401 std::map<uint32_t, EffecterID> entityInstMap{};
Patrick Williams05e95592021-09-02 09:28:14 -0500402 for (auto& pdr : pdrs)
403 {
404 auto pdrPtr =
405 reinterpret_cast<const pldm_state_effecter_pdr*>(pdr.data());
Chris Cain72d01aa2022-06-14 16:28:03 -0500406 uint32_t key = pdrPtr->effecter_id;
Patrick Williams05e95592021-09-02 09:28:14 -0500407 entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->effecter_id));
408 }
409
410 open_power::occ::instanceID position = start;
Patrick Williamsa49c9872023-05-10 07:50:35 -0500411 for (const auto& pair : entityInstMap)
Patrick Williams05e95592021-09-02 09:28:14 -0500412 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500413 instanceToEffecterMap.emplace(position, pair.second);
Patrick Williams05e95592021-09-02 09:28:14 -0500414 position++;
415 }
416}
417
Patrick Williamsd7542c82024-08-16 15:20:28 -0400418std::vector<uint8_t> Interface::prepareSetEffecterReq(
419 EffecterID effecterId, CompositeEffecterCount effecterCount,
420 uint8_t stateIdPos, uint8_t stateSetValue)
Patrick Williams05e95592021-09-02 09:28:14 -0500421{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100422 if (!getPldmInstanceId())
Chris Cain8b508bf2022-05-26 14:01:31 -0500423 {
424 return std::vector<uint8_t>();
425 }
426
Patrick Williams05e95592021-09-02 09:28:14 -0500427 std::vector<uint8_t> request(
428 sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(effecterCount) +
429 (effecterCount * sizeof(set_effecter_state_field)));
430 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
431 std::vector<set_effecter_state_field> stateField;
432
433 for (uint8_t effecterPos = 0; effecterPos < effecterCount; effecterPos++)
434 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500435 if (effecterPos == stateIdPos)
Patrick Williams05e95592021-09-02 09:28:14 -0500436 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500437 stateField.emplace_back(
438 set_effecter_state_field{PLDM_REQUEST_SET, stateSetValue});
Patrick Williams05e95592021-09-02 09:28:14 -0500439 }
440 else
441 {
442 stateField.emplace_back(
443 set_effecter_state_field{PLDM_NO_CHANGE, 0});
444 }
445 }
446 auto rc = encode_set_state_effecter_states_req(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100447 pldmInstanceID.value(), effecterId, effecterCount, stateField.data(),
Chris Cain8b508bf2022-05-26 14:01:31 -0500448 requestMsg);
Patrick Williams05e95592021-09-02 09:28:14 -0500449 if (rc != PLDM_SUCCESS)
450 {
451 log<level::ERR>("encode set effecter states request returned error ",
452 entry("RC=%d", rc));
453 request.clear();
454 }
455 return request;
456}
457
458void Interface::resetOCC(open_power::occ::instanceID occInstanceId)
459{
Chris Cainbae4d072022-02-28 09:46:50 -0600460 if (open_power::occ::utils::isHostRunning())
Patrick Williams05e95592021-09-02 09:28:14 -0500461 {
Chris Cainbae4d072022-02-28 09:46:50 -0600462 if (!isPDREffecterCacheValid())
463 {
464 fetchEffecterInfo(PLDM_STATE_SET_BOOT_RESTART_CAUSE,
465 occInstanceToEffecter, OCCEffecterCount,
466 bootRestartPosition);
467 }
Patrick Williams05e95592021-09-02 09:28:14 -0500468
Chris Cainbae4d072022-02-28 09:46:50 -0600469 // Find the matching effecter for the OCC instance
470 auto effecterEntry = occInstanceToEffecter.find(occInstanceId);
471 if (effecterEntry == occInstanceToEffecter.end())
472 {
473 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600474 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600475 "pldm: Failed to find a matching effecter for OCC instance {}",
476 occInstanceId)
477 .c_str());
478
479 return;
480 }
481
Chris Cainbae4d072022-02-28 09:46:50 -0600482 // Prepare the SetStateEffecterStates request to reset the OCC
483 auto request = prepareSetEffecterReq(
Chris Cain8b508bf2022-05-26 14:01:31 -0500484 effecterEntry->second, OCCEffecterCount, bootRestartPosition,
485 PLDM_STATE_SET_BOOT_RESTART_CAUSE_WARM_RESET);
Chris Cainbae4d072022-02-28 09:46:50 -0600486
487 if (request.empty())
488 {
489 log<level::ERR>(
490 "pldm: SetStateEffecterStates OCC reset request empty");
491 return;
492 }
493
Chris Cainf0295f52024-09-12 15:41:14 -0500494 // Send request to reset the OCCs/PM Complex (and wait for response)
495 msgType = MSG_OCC_RESET;
496 resetInstance = occInstanceId;
497 sendPldm(request, occInstanceId, true);
Chris Cainbae4d072022-02-28 09:46:50 -0600498 }
499 else
Patrick Williams05e95592021-09-02 09:28:14 -0500500 {
501 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600502 std::format("resetOCC: HOST is not running (OCC{})", occInstanceId)
Chris Cain0f516522022-02-07 14:48:28 -0600503 .c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600504 clearData();
Patrick Williams05e95592021-09-02 09:28:14 -0500505 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500506}
507
508void Interface::sendHRESET(open_power::occ::instanceID sbeInstanceId)
509{
Chris Cainbae4d072022-02-28 09:46:50 -0600510 if (open_power::occ::utils::isHostRunning())
Eddie Jamescbad2192021-10-07 09:39:39 -0500511 {
Chris Cainbae4d072022-02-28 09:46:50 -0600512 if (sbeInstanceToEffecter.empty())
513 {
514 fetchEffecterInfo(PLDM_OEM_IBM_SBE_MAINTENANCE_STATE,
515 sbeInstanceToEffecter, SBEEffecterCount,
516 sbeMaintenanceStatePosition);
517 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500518
Chris Cainbae4d072022-02-28 09:46:50 -0600519 auto effecterEntry = sbeInstanceToEffecter.find(sbeInstanceId);
520 if (effecterEntry == sbeInstanceToEffecter.end())
521 {
522 log<level::ERR>(
523 "pldm: Failed to find a matching effecter for SBE instance",
524 entry("SBE=%d", sbeInstanceId));
525 return;
526 }
527
Chris Cainbae4d072022-02-28 09:46:50 -0600528 // Prepare the SetStateEffecterStates request to HRESET the SBE
529 auto request = prepareSetEffecterReq(
Chris Cain8b508bf2022-05-26 14:01:31 -0500530 effecterEntry->second, SBEEffecterCount,
Chris Cainbae4d072022-02-28 09:46:50 -0600531 sbeMaintenanceStatePosition, SBE_RETRY_REQUIRED);
532
533 if (request.empty())
534 {
535 log<level::ERR>(
536 "pldm: SetStateEffecterStates HRESET request empty");
537 return;
538 }
539
Chris Cainf0295f52024-09-12 15:41:14 -0500540 // Send request to issue HRESET of SBE (and wait for response)
541 msgType = MSG_HRESET;
542 resetInstance = sbeInstanceId;
543 sendPldm(request, sbeInstanceId, true);
Chris Cain12d0b822022-04-22 17:29:18 -0500544 outstandingHResets.insert(sbeInstanceId);
Chris Cainbae4d072022-02-28 09:46:50 -0600545 }
546 else
Eddie Jamescbad2192021-10-07 09:39:39 -0500547 {
Patrick Williams48002492024-02-13 21:43:32 -0600548 log<level::ERR>(std::format("sendHRESET: HOST is not running (OCC{})",
Chris Cainbae4d072022-02-28 09:46:50 -0600549 sbeInstanceId)
550 .c_str());
551 clearData();
Eddie Jamescbad2192021-10-07 09:39:39 -0500552 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500553}
554
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100555bool Interface::getPldmInstanceId()
Eddie Jamescbad2192021-10-07 09:39:39 -0500556{
Rashmica Guptadb38e912023-05-25 10:33:46 +1000557 pldm_instance_id_t id;
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100558 if (!pldmInstanceID)
Patrick Williams05e95592021-09-02 09:28:14 -0500559 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500560 // Request new instance ID
Rashmica Guptadb38e912023-05-25 10:33:46 +1000561 int rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
562 if (rc == -EAGAIN)
Chris Cain8b508bf2022-05-26 14:01:31 -0500563 {
Rashmica Guptadb38e912023-05-25 10:33:46 +1000564 std::this_thread::sleep_for(std::chrono::milliseconds(100));
565 rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
Chris Cain8b508bf2022-05-26 14:01:31 -0500566 }
Rashmica Guptadb38e912023-05-25 10:33:46 +1000567
568 if (rc)
Chris Cain8b508bf2022-05-26 14:01:31 -0500569 {
570 log<level::ERR>(
Rashmica Guptadb38e912023-05-25 10:33:46 +1000571 std::format(
572 "getPldmInstanceId: Failed to alloc ID for TID {}. RC{}",
573 tid, rc)
Chris Cain8b508bf2022-05-26 14:01:31 -0500574 .c_str());
575 return false;
576 }
Rashmica Guptadb38e912023-05-25 10:33:46 +1000577 pldmInstanceID.emplace(id);
578 if (!throttleTraces)
579 {
580 log<level::INFO>(
581 std::format("got id {} and set PldmInstanceId to {}", id,
582 pldmInstanceID.value())
583 .c_str());
584 }
Patrick Williams05e95592021-09-02 09:28:14 -0500585 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500586 return true;
587}
Patrick Williams05e95592021-09-02 09:28:14 -0500588
Rashmica Guptadb38e912023-05-25 10:33:46 +1000589void Interface::freePldmInstanceId()
590{
591 if (pldmInstanceID)
592 {
593 int rc = pldm_instance_id_free(pldmInstanceIdDb, tid,
594 pldmInstanceID.value());
595 if (rc)
596 {
597 log<level::ERR>(
598 std::format(
599 "freePldmInstanceId: Failed to free ID {} for TID {}. RC{}",
600 pldmInstanceID.value(), tid, rc)
601 .c_str());
602 return;
603 }
604 if (!throttleTraces)
605 {
606 log<level::INFO>(
607 std::format("Freed PLDM instance ID {}", pldmInstanceID.value())
608 .c_str());
609 }
610 pldmInstanceID = std::nullopt;
611 }
612}
613
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500614[[maybe_unused]] int Interface::openMctpDemuxTransport()
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100615{
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500616 impl.mctpDemux = nullptr;
617 int rc = pldm_transport_mctp_demux_init(&impl.mctpDemux);
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100618 if (rc)
619 {
620 log<level::ERR>(
621 std::format(
622 "openMctpDemuxTransport: Failed to init MCTP demux transport, errno={}/{}",
623 rc, strerror(rc))
624 .c_str());
625 return -1;
626 }
627
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500628 if (pldm_transport_mctp_demux_map_tid(impl.mctpDemux, mctpEid, mctpEid))
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100629 {
630 log<level::ERR>(
631 std::format(
632 "openMctpDemuxTransport: Failed to setup tid to eid mapping, errno={}/{}",
633 errno, strerror(errno))
634 .c_str());
635 pldmClose();
636 return -1;
637 }
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500638 pldmTransport = pldm_transport_mctp_demux_core(impl.mctpDemux);
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100639
640 struct pollfd pollfd;
641 if (pldm_transport_mctp_demux_init_pollfd(pldmTransport, &pollfd))
642 {
643 log<level::ERR>(
644 std::format(
645 "openMctpDemuxTransport: Failed to get pollfd , errno={}/{}",
646 errno, strerror(errno))
647 .c_str());
648 pldmClose();
649 return -1;
650 }
651 pldmFd = pollfd.fd;
652 if (!throttleTraces)
653 {
654 log<level::INFO>(
655 std::format("openMctpDemuxTransport: pldmFd has fd={}", pldmFd)
656 .c_str());
657 }
658 return 0;
659}
660
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500661[[maybe_unused]] int Interface::openAfMctpTransport()
662{
663 impl.afMctp = nullptr;
664 int rc = pldm_transport_af_mctp_init(&impl.afMctp);
665 if (rc)
666 {
667 log<level::ERR>(
668 std::format(
669 "openAfMctpTransport: Failed to init af MCTP transport, errno={}/{}",
670 rc, strerror(rc))
671 .c_str());
672 return -1;
673 }
674
675 if (pldm_transport_af_mctp_map_tid(impl.afMctp, mctpEid, mctpEid))
676 {
677 log<level::ERR>(
678 std::format(
679 "openAfMctpTransport: Failed to setup tid to eid mapping, errno={}/{}",
680 errno, strerror(errno))
681 .c_str());
682 pldmClose();
683 return -1;
684 }
685 pldmTransport = pldm_transport_af_mctp_core(impl.afMctp);
686
687 struct pollfd pollfd;
688 if (pldm_transport_af_mctp_init_pollfd(pldmTransport, &pollfd))
689 {
690 log<level::ERR>(
691 std::format(
692 "openAfMctpTransport: Failed to get pollfd , errno={}/{}",
693 errno, strerror(errno))
694 .c_str());
695 pldmClose();
696 return -1;
697 }
698 pldmFd = pollfd.fd;
699 if (!throttleTraces)
700 {
701 log<level::INFO>(
702 std::format("openAfMctpTransport: pldmFd has fd={}", pldmFd)
703 .c_str());
704 }
705 return 0;
706}
707
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100708int Interface::pldmOpen()
709{
710 if (pldmTransport)
711 {
712 log<level::ERR>(
713 std::format("pldmOpen: pldmTransport already setup!, errno={}/{}",
714 errno, strerror(errno))
715 .c_str());
716 return -1;
717 }
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500718#if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX)
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100719 return openMctpDemuxTransport();
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500720#elif defined(PLDM_TRANSPORT_WITH_AF_MCTP)
721 return openAfMctpTransport();
722#else
Chris Cainf0295f52024-09-12 15:41:14 -0500723 log<level::ERR>(
724 std::format("pldmOpen: Undefined pldmTransport!, errno={}/{}", errno,
725 strerror(errno))
726 .c_str());
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500727 return -1;
728#endif
729
730 return 0;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100731}
732
Chris Cainbae4d072022-02-28 09:46:50 -0600733void Interface::sendPldm(const std::vector<uint8_t>& request,
734 const uint8_t instance, const bool rspExpected)
Eddie Jamescbad2192021-10-07 09:39:39 -0500735{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100736 if (!pldmInstanceID)
Chris Cain8b508bf2022-05-26 14:01:31 -0500737 {
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100738 log<level::ERR>("sendPldm: No PLDM Instance ID found!");
Chris Cain8b508bf2022-05-26 14:01:31 -0500739 return;
740 }
741
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100742 auto rc = pldmOpen();
743 if (rc)
Patrick Williams05e95592021-09-02 09:28:14 -0500744 {
Eddie James88811ad2024-08-27 13:39:05 -0500745 if (!throttleTraces)
746 {
747 log<level::ERR>(
748 std::format("sendPldm: pldmOpen failed rc={}", rc).c_str());
749 }
Rashmica Guptadb38e912023-05-25 10:33:46 +1000750 freePldmInstanceId();
Patrick Williams05e95592021-09-02 09:28:14 -0500751 return;
752 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500753
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100754 pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEid);
Patrick Williams05e95592021-09-02 09:28:14 -0500755 // Send the PLDM request message to HBRT
Chris Cainbae4d072022-02-28 09:46:50 -0600756 if (rspExpected)
Patrick Williams05e95592021-09-02 09:28:14 -0500757 {
Chris Cainbae4d072022-02-28 09:46:50 -0600758 // Register callback when response is available
759 registerPldmRspCallback();
760
Chris Cainf0295f52024-09-12 15:41:14 -0500761 using namespace std::literals::chrono_literals;
762 std::chrono::duration timeout = 8s;
763 if ((msgType == MSG_OCC_RESET) || (msgType == MSG_HRESET))
764 {
765 timeout = 30s;
766 }
767
Chris Cainbae4d072022-02-28 09:46:50 -0600768 // Send PLDM request
Chris Cain755af102024-02-27 16:09:51 -0600769 if (!throttleTraces)
770 {
771 log<level::INFO>(
772 std::format(
Chris Cainf0295f52024-09-12 15:41:14 -0500773 "sendPldm: calling pldm_transport_send_msg(OCC{}, instance:{}, {} bytes, timeout {})",
774 instance, pldmInstanceID.value(), request.size(), timeout)
Chris Cain755af102024-02-27 16:09:51 -0600775 .c_str());
776 }
Chris Cainbae4d072022-02-28 09:46:50 -0600777 pldmResponseReceived = false;
778 pldmResponseTimeout = false;
779 pldmResponseOcc = instance;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100780 auto pldmRc = pldm_transport_send_msg(pldmTransport, pldmTID,
781 request.data(), request.size());
Chris Cainbae4d072022-02-28 09:46:50 -0600782 auto sendErrno = errno;
783 if (pldmRc != PLDM_REQUESTER_SUCCESS)
784 {
785 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600786 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100787 "sendPldm: pldm_transport_send_msg failed with rc={} and errno={}/{}",
Chris Cain5161a022023-08-15 10:07:12 -0500788 static_cast<
789 std::underlying_type_t<pldm_requester_error_codes>>(
790 pldmRc),
791 sendErrno, strerror(sendErrno))
Chris Cainbae4d072022-02-28 09:46:50 -0600792 .c_str());
793 pldmClose();
794 return;
795 }
796
797 // start timer waiting for the response
Chris Cainf0295f52024-09-12 15:41:14 -0500798 pldmRspTimer.restartOnce(timeout);
Chris Cainbae4d072022-02-28 09:46:50 -0600799
800 // Wait for response/timeout
801 }
802 else // not expecting the response
803 {
Chris Cain755af102024-02-27 16:09:51 -0600804 if (!throttleTraces)
805 {
806 log<level::INFO>(
807 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100808 "sendPldm: calling pldm_transport_send_msg(mctpID:{}, fd:{}, {} bytes) for OCC{}",
Chris Cain755af102024-02-27 16:09:51 -0600809 mctpEid, pldmFd, request.size(), instance)
810 .c_str());
811 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100812 auto rc = pldm_transport_send_msg(pldmTransport, pldmTID,
813 request.data(), request.size());
Chris Cainbae4d072022-02-28 09:46:50 -0600814 auto sendErrno = errno;
Chris Caind1b68262022-02-28 09:56:50 -0600815 if (rc)
816 {
817 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600818 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100819 "sendPldm: pldm_transport_send_msg(mctpID:{}, fd:{}, {} bytes) failed with rc={} and errno={}/{}",
Chris Cain5161a022023-08-15 10:07:12 -0500820 mctpEid, pldmFd, request.size(),
821 static_cast<
822 std::underlying_type_t<pldm_requester_error_codes>>(rc),
823 sendErrno, strerror(sendErrno))
Chris Caind1b68262022-02-28 09:56:50 -0600824 .c_str());
825 }
Chris Cainbae4d072022-02-28 09:46:50 -0600826 pldmClose();
827 }
828}
Patrick Williams05e95592021-09-02 09:28:14 -0500829
Chris Cainbae4d072022-02-28 09:46:50 -0600830// Attaches the FD to event loop and registers the callback handler
831void Interface::registerPldmRspCallback()
832{
833 decltype(eventSource.get()) sourcePtr = nullptr;
Chris Cainf0295f52024-09-12 15:41:14 -0500834 int rc = 0;
835 if ((msgType == MSG_OCC_RESET) || (msgType == MSG_HRESET))
836 {
837 rc = sd_event_add_io(event.get(), &sourcePtr, pldmFd, EPOLLIN,
838 pldmResetCallback, this);
839 }
840 else
841 {
842 rc = sd_event_add_io(event.get(), &sourcePtr, pldmFd, EPOLLIN,
843 pldmRspCallback, this);
844 }
Chris Cainbae4d072022-02-28 09:46:50 -0600845 if (rc < 0)
846 {
847 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600848 std::format(
Chris Cainf0295f52024-09-12 15:41:14 -0500849 "registerPldmRspCallback: sd_event_add_io: Error({})={} : fd={} (msgType={})",
850 rc, strerror(-rc), pldmFd, msgType)
Chris Cainbae4d072022-02-28 09:46:50 -0600851 .c_str());
Chris Caind1b68262022-02-28 09:56:50 -0600852 }
853 else
Patrick Williams05e95592021-09-02 09:28:14 -0500854 {
Chris Cainbae4d072022-02-28 09:46:50 -0600855 // puts sourcePtr in the event source.
856 eventSource.reset(sourcePtr);
857 }
858}
859
860// Add a timer to the event loop, default 30s.
861void Interface::pldmRspExpired()
862{
863 if (!pldmResponseReceived)
864 {
Chris Cain755af102024-02-27 16:09:51 -0600865 if (!throttleTraces)
866 {
867 log<level::WARNING>(
868 std::format(
Chris Cainf0295f52024-09-12 15:41:14 -0500869 "pldmRspExpired: timerCallback - timeout waiting for pldm response to msg:{} for OCC{}",
870 msgType, pldmResponseOcc)
Chris Cain755af102024-02-27 16:09:51 -0600871 .c_str());
872 }
Chris Cainbae4d072022-02-28 09:46:50 -0600873 pldmResponseTimeout = true;
874 if (pldmFd)
875 {
876 pldmClose();
877 }
Chris Cainf0295f52024-09-12 15:41:14 -0500878 if (msgType == MSG_OCC_RESET)
879 {
880 // reset not acked, try again
881 log<level::ERR>(
882 std::format("pldmRspExpired: retrying reset request for OCC{}",
883 pldmResponseOcc)
884 .c_str());
885 resetOCC(pldmResponseOcc);
886 }
Chris Cainbae4d072022-02-28 09:46:50 -0600887 }
888 return;
889};
890
891void Interface::pldmClose()
892{
Rashmica Guptadb38e912023-05-25 10:33:46 +1000893 freePldmInstanceId();
Chris Cainbae4d072022-02-28 09:46:50 -0600894 if (pldmRspTimer.isEnabled())
895 {
896 // stop PLDM response timer
897 pldmRspTimer.setEnabled(false);
898 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100899
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500900#if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX)
901 pldm_transport_mctp_demux_destroy(impl.mctpDemux);
902 impl.mctpDemux = NULL;
903#elif defined(PLDM_TRANSPORT_WITH_AF_MCTP)
904 pldm_transport_af_mctp_destroy(impl.afMctp);
905 impl.afMctp = NULL;
906#endif
Chris Cainbae4d072022-02-28 09:46:50 -0600907 pldmFd = -1;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100908 pldmTransport = NULL;
Chris Cainbae4d072022-02-28 09:46:50 -0600909 eventSource.reset();
910}
911
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100912int Interface::pldmRspCallback(sd_event_source* /*es*/,
913 __attribute__((unused)) int fd, uint32_t revents,
914 void* userData)
Chris Cainbae4d072022-02-28 09:46:50 -0600915{
916 if (!(revents & EPOLLIN))
917 {
918 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600919 std::format("pldmRspCallback - revents={:08X}", revents).c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600920 return -1;
921 }
922
923 auto pldmIface = static_cast<Interface*>(userData);
924
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100925 if (!pldmIface->pldmInstanceID)
Chris Cain8b508bf2022-05-26 14:01:31 -0500926 {
927 log<level::ERR>(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100928 "pldmRspCallback: No outstanding PLDM Instance ID found");
Chris Cain8b508bf2022-05-26 14:01:31 -0500929 return -1;
930 }
931
Chris Cainbae4d072022-02-28 09:46:50 -0600932 uint8_t* responseMsg = nullptr;
933 size_t responseMsgSize{};
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100934 pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEid);
Chris Cainbae4d072022-02-28 09:46:50 -0600935
Chris Cain755af102024-02-27 16:09:51 -0600936 if (!throttleTraces)
937 {
938 log<level::INFO>(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100939 std::format(
940 "pldmRspCallback: calling pldm_transport_recv_msg() instance:{}",
941 pldmIface->pldmInstanceID.value())
Chris Cain755af102024-02-27 16:09:51 -0600942 .c_str());
943 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100944 auto rc = pldm_transport_recv_msg(pldmIface->pldmTransport, &pldmTID,
945 (void**)&responseMsg, &responseMsgSize);
Chris Cainbae4d072022-02-28 09:46:50 -0600946 int lastErrno = errno;
947 if (rc)
948 {
Chris Cain755af102024-02-27 16:09:51 -0600949 if (!throttleTraces)
950 {
951 log<level::ERR>(
952 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100953 "pldmRspCallback: pldm_transport_recv_msg failed with rc={}, errno={}/{}",
Chris Cain755af102024-02-27 16:09:51 -0600954 static_cast<
955 std::underlying_type_t<pldm_requester_error_codes>>(rc),
956 lastErrno, strerror(lastErrno))
957 .c_str());
958 }
Chris Cainbae4d072022-02-28 09:46:50 -0600959 return -1;
960 }
Chris Cain8b508bf2022-05-26 14:01:31 -0500961
962 // We got the response for the PLDM request msg that was sent
Chris Cain755af102024-02-27 16:09:51 -0600963 if (!throttleTraces)
964 {
965 log<level::INFO>(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100966 std::format(
967 "pldmRspCallback: pldm_transport_recv_msg() rsp was {} bytes",
968 responseMsgSize)
Chris Cain755af102024-02-27 16:09:51 -0600969 .c_str());
970 }
Chris Cainbae4d072022-02-28 09:46:50 -0600971
972 if (pldmIface->pldmRspTimer.isEnabled())
973 {
974 // stop PLDM response timer
975 pldmIface->pldmRspTimer.setEnabled(false);
976 }
977
Chris Cain8b508bf2022-05-26 14:01:31 -0500978 // instance ID should be freed
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100979 pldmIface->pldmInstanceID = std::nullopt;
Chris Cain8b508bf2022-05-26 14:01:31 -0500980
Chris Cainbae4d072022-02-28 09:46:50 -0600981 // Set pointer to autodelete
Patrick Williamsd7542c82024-08-16 15:20:28 -0400982 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{
983 responseMsg, std::free};
Chris Cainbae4d072022-02-28 09:46:50 -0600984
Chris Cainbae4d072022-02-28 09:46:50 -0600985 auto response = reinterpret_cast<pldm_msg*>(responseMsgPtr.get());
986 if (response->payload[0] != PLDM_SUCCESS)
987 {
988 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600989 std::format("pldmRspCallback: payload[0] was not success: {}",
Chris Cainbae4d072022-02-28 09:46:50 -0600990 response->payload[0])
991 .c_str());
992 pldmIface->pldmClose();
993 return -1;
994 }
995
996 // Decode the response
997 uint8_t compCode = 0, sensorCount = 1;
998 get_sensor_state_field field[6];
999 responseMsgSize -= sizeof(pldm_msg_hdr);
1000 auto msgRc = decode_get_state_sensor_readings_resp(
1001 response, responseMsgSize, &compCode, &sensorCount, field);
1002 if ((msgRc != PLDM_SUCCESS) || (compCode != PLDM_SUCCESS))
1003 {
1004 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -06001005 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -06001006 "pldmRspCallback: decode_get_state_sensor_readings failed with rc={} and compCode={}",
1007 msgRc, compCode)
1008 .c_str());
1009 pldmIface->pldmClose();
1010 return -1;
1011 }
1012
1013 pldmIface->pldmClose();
1014
1015 const uint8_t instance = pldmIface->pldmResponseOcc;
1016 const uint8_t occSensorState = field[0].present_state;
1017 pldmIface->pldmResponseReceived = true;
1018
1019 if (occSensorState == PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE)
1020 {
1021 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -06001022 std::format("pldmRspCallback: OCC{} is RUNNING", instance).c_str());
Chris Cainf0295f52024-09-12 15:41:14 -05001023 pldmIface->occActiveCallBack(instance, true);
Chris Cainbae4d072022-02-28 09:46:50 -06001024 }
Chris Cain733b2012022-05-04 11:54:06 -05001025 else if (occSensorState ==
1026 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT)
1027 {
Chris Cain755af102024-02-27 16:09:51 -06001028 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -06001029 std::format(
Chris Cain733b2012022-05-04 11:54:06 -05001030 "pldmRspCallback: OCC{} has now STOPPED and system is in SAFE MODE",
1031 instance)
1032 .c_str());
Sheldon Bailey31a2f132022-05-20 11:31:52 -05001033
1034 // Setting safe mode true
1035 pldmIface->safeModeCallBack(true);
1036
Chris Cainf0295f52024-09-12 15:41:14 -05001037 pldmIface->occActiveCallBack(instance, false);
Chris Cain733b2012022-05-04 11:54:06 -05001038 }
Chris Cain755af102024-02-27 16:09:51 -06001039 else if (occSensorState ==
1040 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED)
Chris Cainbae4d072022-02-28 09:46:50 -06001041 {
1042 log<level::INFO>(
Chris Cain755af102024-02-27 16:09:51 -06001043 std::format("pldmRspCallback: OCC{} is not running", instance)
Chris Cainbae4d072022-02-28 09:46:50 -06001044 .c_str());
Chris Cainf0295f52024-09-12 15:41:14 -05001045 pldmIface->occActiveCallBack(instance, false);
Chris Cain755af102024-02-27 16:09:51 -06001046 }
1047 else
1048 {
1049 const size_t rspLength = responseMsgSize + sizeof(pldm_msg_hdr);
1050 std::vector<std::uint8_t> pldmResponse(rspLength);
1051 memcpy(&pldmResponse[0], reinterpret_cast<std::uint8_t*>(response),
1052 rspLength);
1053 if (!throttleTraces)
Chris Cainc9dc4412023-03-06 15:56:34 -06001054 {
Chris Cain755af102024-02-27 16:09:51 -06001055 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -06001056 std::format(
Chris Cain755af102024-02-27 16:09:51 -06001057 "pldmRspCallback: Unexpected State: {} - PLDM response ({} bytes) for OCC{}:",
1058 occSensorState, rspLength, instance)
Chris Cainc9dc4412023-03-06 15:56:34 -06001059 .c_str());
1060 dump_hex(pldmResponse);
1061 }
Chris Cainbae4d072022-02-28 09:46:50 -06001062 }
1063
1064 return 0;
1065};
1066
Chris Cainf0295f52024-09-12 15:41:14 -05001067int Interface::pldmResetCallback(sd_event_source* /*es*/,
1068 __attribute__((unused)) int fd,
1069 uint32_t revents, void* userData)
1070{
1071 if (!(revents & EPOLLIN))
1072 {
1073 log<level::INFO>(
1074 std::format("pldmResetCallback - revents={:08X}", revents).c_str());
1075 return -1;
1076 }
1077
1078 auto pldmIface = static_cast<Interface*>(userData);
1079
1080 if (!pldmIface->pldmInstanceID)
1081 {
1082 log<level::ERR>(
1083 "pldmResetCallback: No outstanding PLDM Instance ID found");
1084 return -1;
1085 }
1086
1087 uint8_t* responseMsg = nullptr;
1088 size_t responseMsgSize{};
1089 pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEid);
1090
1091 if (!throttleTraces)
1092 {
1093 log<level::INFO>(
1094 std::format(
1095 "pldmResetCallback: calling pldm_transport_recv_msg() instance:{}",
1096 pldmIface->pldmInstanceID.value())
1097 .c_str());
1098 }
1099 auto rc = pldm_transport_recv_msg(pldmIface->pldmTransport, &pldmTID,
1100 (void**)&responseMsg, &responseMsgSize);
1101 int lastErrno = errno;
1102 if (rc)
1103 {
1104 if (!throttleTraces)
1105 {
1106 log<level::ERR>(
1107 std::format(
1108 "pldmResetCallback: pldm_transport_recv_msg failed with rc={}, errno={}/{}",
1109 static_cast<
1110 std::underlying_type_t<pldm_requester_error_codes>>(rc),
1111 lastErrno, strerror(lastErrno))
1112 .c_str());
1113 }
1114 return -1;
1115 }
1116
1117 // We got the response for the PLDM request msg that was sent
1118 if (!throttleTraces)
1119 {
1120 log<level::INFO>(
1121 std::format(
1122 "pldmResetCallback: pldm_transport_recv_msg() rsp was {} bytes",
1123 responseMsgSize)
1124 .c_str());
1125 }
1126
1127 if (pldmIface->pldmRspTimer.isEnabled())
1128 {
1129 // stop PLDM response timer
1130 pldmIface->pldmRspTimer.setEnabled(false);
1131 }
1132
1133 // instance ID should be freed
1134 pldmIface->pldmInstanceID = std::nullopt;
1135
1136 // Set pointer to autodelete
1137 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{
1138 responseMsg, std::free};
1139
1140 auto response = reinterpret_cast<pldm_msg*>(responseMsgPtr.get());
1141 if (response->payload[0] != PLDM_SUCCESS)
1142 {
1143 log<level::ERR>(
1144 std::format(
1145 "pldmResetCallback: Reset FAILED ({}) - payload[0] was not success: {}",
1146 msgType, response->payload[0])
1147 .c_str());
1148 pldmIface->pldmClose();
1149
1150 if (msgType == MSG_OCC_RESET)
1151 {
1152 // Retry reset request
1153 log<level::ERR>(
1154 std::format(
1155 "pldmResetCallback: retrying reset request for OCC{}",
1156 resetInstance)
1157 .c_str());
1158 pldmIface->resetOCC(resetInstance);
1159 }
1160 return -1;
1161 }
1162 else
1163 {
1164 log<level::INFO>(
1165 "pldmResetCallback: Reset has been successfully started");
1166 }
1167
1168 pldmIface->pldmClose();
1169
1170 pldmIface->pldmResponseReceived = true;
1171
1172 return 0;
1173}
1174
Patrick Williamsd7542c82024-08-16 15:20:28 -04001175std::vector<uint8_t>
1176 Interface::encodeGetStateSensorRequest(uint8_t instance, uint16_t sensorId)
Chris Cainbae4d072022-02-28 09:46:50 -06001177{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +11001178 if (!getPldmInstanceId())
Chris Cain8b508bf2022-05-26 14:01:31 -05001179 {
1180 log<level::ERR>(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +11001181 "encodeGetStateSensorRequest: failed to getPldmInstanceId");
Chris Cain8b508bf2022-05-26 14:01:31 -05001182 return std::vector<uint8_t>();
1183 }
1184
Chris Cainbae4d072022-02-28 09:46:50 -06001185 bitfield8_t sRearm = {0};
Patrick Williamsd7542c82024-08-16 15:20:28 -04001186 const size_t msgSize =
1187 sizeof(pldm_msg_hdr) + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES;
Chris Cainbae4d072022-02-28 09:46:50 -06001188 std::vector<uint8_t> request(msgSize);
Chris Cain8b508bf2022-05-26 14:01:31 -05001189
Chris Cainbae4d072022-02-28 09:46:50 -06001190 auto msg = reinterpret_cast<pldm_msg*>(request.data());
Rashmica Guptaaeba51c2023-02-17 12:30:46 +11001191 auto msgRc = encode_get_state_sensor_readings_req(pldmInstanceID.value(),
Chris Cain8b508bf2022-05-26 14:01:31 -05001192 sensorId, sRearm, 0, msg);
Chris Cainbae4d072022-02-28 09:46:50 -06001193 if (msgRc != PLDM_SUCCESS)
1194 {
1195 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -06001196 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -06001197 "encodeGetStateSensorRequest: Failed to encode sensorId:0x{:08X} for OCC{} (rc={})",
1198 sensorId, instance, msgRc)
1199 .c_str());
1200 }
1201 return request;
1202}
1203
1204// Initiate query of the specified OCC Active Sensor
1205void Interface::checkActiveSensor(uint8_t instance)
1206{
1207 static bool tracedOnce = false;
1208 if (pldmFd > 0)
1209 {
Chris Cain755af102024-02-27 16:09:51 -06001210 if (!throttleTraces && !tracedOnce)
Chris Caind1b68262022-02-28 09:56:50 -06001211 {
Chris Cain755af102024-02-27 16:09:51 -06001212 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -06001213 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -06001214 "checkActiveSensor: already waiting on OCC{} (fd={})",
1215 pldmResponseOcc, pldmFd)
Chris Caind1b68262022-02-28 09:56:50 -06001216 .c_str());
Chris Cainbae4d072022-02-28 09:46:50 -06001217 tracedOnce = true;
Chris Caind1b68262022-02-28 09:56:50 -06001218 }
Chris Cainbae4d072022-02-28 09:46:50 -06001219 return;
1220 }
1221 tracedOnce = false;
1222
1223 if (!isOCCSensorCacheValid())
1224 {
1225 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
1226 sensorToOCCInstance, OCCSensorOffset);
1227 }
1228
1229 // look up sensor id (key) based on instance
1230 auto entry = std::find_if(
1231 sensorToOCCInstance.begin(), sensorToOCCInstance.end(),
1232 [instance](const auto& entry) { return instance == entry.second; });
1233 if (entry != sensorToOCCInstance.end())
1234 {
1235 // Query the OCC Active Sensor state for this instance
Chris Cain755af102024-02-27 16:09:51 -06001236 if (!throttleTraces)
1237 {
1238 log<level::INFO>(
1239 std::format("checkActiveSensor: OCC{} / sensorID: 0x{:04X}",
1240 instance, entry->first)
1241 .c_str());
1242 }
Chris Cainbae4d072022-02-28 09:46:50 -06001243
Chris Cainbae4d072022-02-28 09:46:50 -06001244 // Encode GetStateSensorReadings PLDM message
1245 auto request = encodeGetStateSensorRequest(instance, entry->first);
1246 if (request.empty())
1247 {
1248 return;
1249 }
1250
1251 // Send request to PLDM and setup callback for response
Chris Cainf0295f52024-09-12 15:41:14 -05001252 msgType = MSG_SENSOR_STATUS;
Chris Cainbae4d072022-02-28 09:46:50 -06001253 sendPldm(request, instance, true);
1254 }
1255 else
1256 {
Chris Cain755af102024-02-27 16:09:51 -06001257 if (!throttleTraces)
1258 {
1259 log<level::ERR>(
1260 std::format(
1261 "checkActiveSensor: Unable to find PLDM sensor for OCC{}",
1262 instance)
1263 .c_str());
1264 log<level::INFO>(
1265 "checkActiveSensor: fetching STATE_SET_OPERATIONAL_RUNNING_STATUS");
1266 }
Chris Cain8cf74962022-06-29 08:45:16 -05001267 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
1268 sensorToOCCInstance, OCCSensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -05001269 }
Patrick Williams05e95592021-09-02 09:28:14 -05001270}
1271
Chris Cain755af102024-02-27 16:09:51 -06001272void Interface::setTraceThrottle(const bool throttle)
1273{
1274 if (throttle != throttleTraces)
1275 {
1276 if (throttle)
1277 {
1278 log<level::WARNING>("PLDM traces being throttled");
1279 }
1280 else
1281 {
1282 log<level::INFO>("PLDM traces no longer being throttled");
1283 }
1284 throttleTraces = throttle;
1285 }
1286}
1287
Patrick Williams05e95592021-09-02 09:28:14 -05001288} // namespace pldm