blob: b573d6665fc0d921b4331b1ae1bcdd4d0bffe17c [file] [log] [blame]
Patrick Williams05e95592021-09-02 09:28:14 -05001#include "pldm.hpp"
2
Rashmica Guptadb38e912023-05-25 10:33:46 +10003#include "libpldm/instance-id.h"
4
Patrick Williams05e95592021-09-02 09:28:14 -05005#include "file.hpp"
6
Patrick Williams05e95592021-09-02 09:28:14 -05007#include <libpldm/entity.h>
Andrew Jeffery97476a12024-06-19 21:07:29 +09308#include <libpldm/oem/ibm/state_set.h>
Patrick Williams05e95592021-09-02 09:28:14 -05009#include <libpldm/platform.h>
10#include <libpldm/state_set.h>
Rashmica Gupta52328cb2023-02-15 10:38:16 +110011#include <libpldm/transport.h>
12#include <libpldm/transport/mctp-demux.h>
13#include <poll.h>
Patrick Williams05e95592021-09-02 09:28:14 -050014
15#include <phosphor-logging/log.hpp>
Chris Cainbae4d072022-02-28 09:46:50 -060016#include <sdbusplus/bus.hpp>
17#include <sdeventplus/clock.hpp>
18#include <sdeventplus/exception.hpp>
19#include <sdeventplus/source/io.hpp>
20#include <sdeventplus/source/time.hpp>
21
22#include <algorithm>
Patrick Williams48002492024-02-13 21:43:32 -060023#include <format>
Patrick Williams05e95592021-09-02 09:28:14 -050024
25namespace pldm
26{
27
Patrick Williams05e95592021-09-02 09:28:14 -050028using namespace phosphor::logging;
29
Chris Cainbae4d072022-02-28 09:46:50 -060030using namespace sdeventplus;
31using namespace sdeventplus::source;
32constexpr auto clockId = sdeventplus::ClockId::RealTime;
33using Clock = sdeventplus::Clock<clockId>;
34using Timer = Time<clockId>;
Chris Cain755af102024-02-27 16:09:51 -060035bool Interface::throttleTraces = false;
Chris Cainbae4d072022-02-28 09:46:50 -060036
Eddie Jamescbad2192021-10-07 09:39:39 -050037void Interface::fetchSensorInfo(uint16_t stateSetId,
38 SensorToInstance& sensorInstanceMap,
39 SensorOffset& sensorOffset)
Patrick Williams05e95592021-09-02 09:28:14 -050040{
Eddie Jamescbad2192021-10-07 09:39:39 -050041 PdrList pdrs{};
Chris Cainbae4d072022-02-28 09:46:50 -060042 static bool tracedError = false;
Eddie Jamescbad2192021-10-07 09:39:39 -050043
44 auto& bus = open_power::occ::utils::getBus();
45 try
46 {
47 auto method = bus.new_method_call(
48 "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
49 "xyz.openbmc_project.PLDM.PDR", "FindStateSensorPDR");
Chris Cainbae4d072022-02-28 09:46:50 -060050 method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId);
Eddie Jamescbad2192021-10-07 09:39:39 -050051
52 auto responseMsg = bus.call(method);
53 responseMsg.read(pdrs);
54 }
Patrick Williamsaf408082022-07-22 19:26:54 -050055 catch (const sdbusplus::exception_t& e)
Eddie Jamescbad2192021-10-07 09:39:39 -050056 {
Chris Cainbae4d072022-02-28 09:46:50 -060057 if (!tracedError)
58 {
59 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -060060 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -060061 "fetchSensorInfo: Failed to find stateSetID:{} PDR: {}",
62 stateSetId, e.what())
63 .c_str());
64 tracedError = true;
65 }
Eddie Jamescbad2192021-10-07 09:39:39 -050066 }
67
68 if (pdrs.empty())
69 {
Chris Cainbae4d072022-02-28 09:46:50 -060070 if (!tracedError)
71 {
72 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -060073 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -060074 "fetchSensorInfo: state sensor PDRs ({}) not present",
75 stateSetId)
76 .c_str());
77 tracedError = true;
78 }
Eddie Jamescbad2192021-10-07 09:39:39 -050079 return;
80 }
81
Chris Cainbae4d072022-02-28 09:46:50 -060082 // Found PDR
83 if (tracedError)
84 {
85 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -060086 std::format("fetchSensorInfo: found {} PDRs", pdrs.size()).c_str());
Chris Cainbae4d072022-02-28 09:46:50 -060087 tracedError = false;
88 }
89
Patrick Williams05e95592021-09-02 09:28:14 -050090 bool offsetFound = false;
George Liuf3a4a692021-12-28 13:59:51 +080091 auto stateSensorPDR =
Patrick Williams05e95592021-09-02 09:28:14 -050092 reinterpret_cast<const pldm_state_sensor_pdr*>(pdrs.front().data());
George Liuf3a4a692021-12-28 13:59:51 +080093 auto possibleStatesPtr = stateSensorPDR->possible_states;
94 for (auto offset = 0; offset < stateSensorPDR->composite_sensor_count;
95 offset++)
Patrick Williams05e95592021-09-02 09:28:14 -050096 {
97 auto possibleStates =
98 reinterpret_cast<const state_sensor_possible_states*>(
99 possibleStatesPtr);
100
Eddie Jamescbad2192021-10-07 09:39:39 -0500101 if (possibleStates->state_set_id == stateSetId)
Patrick Williams05e95592021-09-02 09:28:14 -0500102 {
103 sensorOffset = offset;
104 offsetFound = true;
105 break;
106 }
107 possibleStatesPtr += sizeof(possibleStates->state_set_id) +
108 sizeof(possibleStates->possible_states_size) +
109 possibleStates->possible_states_size;
110 }
111
112 if (!offsetFound)
113 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500114 log<level::ERR>("pldm: state sensor PDR not found");
Patrick Williams05e95592021-09-02 09:28:14 -0500115 return;
116 }
117
118 // To order SensorID based on the EntityInstance.
119 // Note that when a proc is on a DCM, the PDRs for these sensors
120 // could have the same instance IDs but different container IDs.
121 std::map<uint32_t, SensorID> entityInstMap{};
122 for (auto& pdr : pdrs)
123 {
124 auto pdrPtr =
125 reinterpret_cast<const pldm_state_sensor_pdr*>(pdr.data());
Chris Cain72d01aa2022-06-14 16:28:03 -0500126 uint32_t key = pdrPtr->sensor_id;
Patrick Williams05e95592021-09-02 09:28:14 -0500127 entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->sensor_id));
128 }
129
130 open_power::occ::instanceID count = start;
Patrick Williamsa49c9872023-05-10 07:50:35 -0500131 for (const auto& pair : entityInstMap)
Patrick Williams05e95592021-09-02 09:28:14 -0500132 {
133 sensorInstanceMap.emplace(pair.second, count);
134 count++;
135 }
136}
137
Patrick Williamsaf408082022-07-22 19:26:54 -0500138void Interface::sensorEvent(sdbusplus::message_t& msg)
Patrick Williams05e95592021-09-02 09:28:14 -0500139{
140 if (!isOCCSensorCacheValid())
141 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500142 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
143 sensorToOCCInstance, OCCSensorOffset);
144 }
Patrick Williams05e95592021-09-02 09:28:14 -0500145
Eddie Jamescbad2192021-10-07 09:39:39 -0500146 if (sensorToSBEInstance.empty())
147 {
148 fetchSensorInfo(PLDM_OEM_IBM_SBE_HRESET_STATE, sensorToSBEInstance,
149 SBESensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -0500150 }
151
Chris Cain72d01aa2022-06-14 16:28:03 -0500152 TerminusID sensorTid{};
Patrick Williams05e95592021-09-02 09:28:14 -0500153 SensorID sensorId{};
154 SensorOffset msgSensorOffset{};
155 EventState eventState{};
156 EventState previousEventState{};
157
Chris Cain72d01aa2022-06-14 16:28:03 -0500158 msg.read(sensorTid, sensorId, msgSensorOffset, eventState,
159 previousEventState);
Patrick Williams05e95592021-09-02 09:28:14 -0500160
Eddie Jamescbad2192021-10-07 09:39:39 -0500161 if (msgSensorOffset == OCCSensorOffset)
Patrick Williams05e95592021-09-02 09:28:14 -0500162 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500163 auto sensorEntry = sensorToOCCInstance.find(sensorId);
Patrick Williams05e95592021-09-02 09:28:14 -0500164
Eddie James432dc482021-11-19 15:29:31 -0600165 if (sensorEntry != sensorToOCCInstance.end())
Eddie Jamescbad2192021-10-07 09:39:39 -0500166 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500167 const uint8_t instance = sensorEntry->second;
Chris Cain755af102024-02-27 16:09:51 -0600168 bool validEvent = true;
Chris Cain7b00cde2023-03-14 15:47:12 -0500169 bool isRunning = false;
Eddie James432dc482021-11-19 15:29:31 -0600170 if (eventState ==
171 static_cast<EventState>(
172 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE))
173 {
174 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600175 std::format("PLDM: OCC{} is RUNNING", instance).c_str());
Chris Cain7b00cde2023-03-14 15:47:12 -0500176 isRunning = true;
Eddie James432dc482021-11-19 15:29:31 -0600177 }
178 else if (eventState ==
179 static_cast<EventState>(
180 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED))
181 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500182 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600183 std::format("PLDM: OCC{} has now STOPPED", instance)
Chris Cain8b508bf2022-05-26 14:01:31 -0500184 .c_str());
Eddie James432dc482021-11-19 15:29:31 -0600185 }
Chris Cainbae4d072022-02-28 09:46:50 -0600186 else if (eventState ==
187 static_cast<EventState>(
188 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT))
189 {
Chris Cain755af102024-02-27 16:09:51 -0600190 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600191 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600192 "PLDM: OCC{} has now STOPPED and system is in SAFE MODE",
Chris Cain8b508bf2022-05-26 14:01:31 -0500193 instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600194 .c_str());
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500195
196 // Setting safe mode true
197 safeModeCallBack(true);
Chris Cainbae4d072022-02-28 09:46:50 -0600198 }
199 else
200 {
Chris Cain755af102024-02-27 16:09:51 -0600201 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -0600202 std::format("PLDM: Unexpected PLDM state {} for OCC{}",
Chris Cain8b508bf2022-05-26 14:01:31 -0500203 eventState, instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600204 .c_str());
Chris Cain755af102024-02-27 16:09:51 -0600205 validEvent = false;
Chris Cainbae4d072022-02-28 09:46:50 -0600206 }
Chris Cain755af102024-02-27 16:09:51 -0600207 if (validEvent)
208 {
209 if ((pldmFd > 0) && (instance == pldmResponseOcc))
210 {
211 // Waiting for a response for this OCC, can stop waiting
212 pldmClose();
213 }
214 callBack(instance, isRunning);
215 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500216 return;
217 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500218 }
Eddie James432dc482021-11-19 15:29:31 -0600219
220 if (msgSensorOffset == SBESensorOffset)
Eddie Jamescbad2192021-10-07 09:39:39 -0500221 {
222 auto sensorEntry = sensorToSBEInstance.find(sensorId);
223
Eddie James432dc482021-11-19 15:29:31 -0600224 if (sensorEntry != sensorToSBEInstance.end())
Eddie Jamescbad2192021-10-07 09:39:39 -0500225 {
Chris Cain12d0b822022-04-22 17:29:18 -0500226 const uint8_t instance = sensorEntry->second;
227 auto match = std::find(outstandingHResets.begin(),
228 outstandingHResets.end(), instance);
229 if (match != outstandingHResets.end())
Eddie James432dc482021-11-19 15:29:31 -0600230 {
Chris Cain12d0b822022-04-22 17:29:18 -0500231 outstandingHResets.erase(match);
232 if (eventState == static_cast<EventState>(SBE_HRESET_NOT_READY))
233 {
234 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600235 std::format("pldm: HRESET is NOT READY (OCC{})",
Chris Cain12d0b822022-04-22 17:29:18 -0500236 instance)
237 .c_str());
238 }
239 else if (eventState ==
240 static_cast<EventState>(SBE_HRESET_READY))
241 {
242 sbeCallBack(instance, true);
243 }
244 else if (eventState ==
245 static_cast<EventState>(SBE_HRESET_FAILED))
246 {
247 sbeCallBack(instance, false);
248 }
Eddie James432dc482021-11-19 15:29:31 -0600249 }
Chris Cain12d0b822022-04-22 17:29:18 -0500250 // else request was not from us
Eddie Jamescbad2192021-10-07 09:39:39 -0500251 }
252 }
Patrick Williams05e95592021-09-02 09:28:14 -0500253}
254
Patrick Williamsaf408082022-07-22 19:26:54 -0500255void Interface::hostStateEvent(sdbusplus::message_t& msg)
Chris Cain157467d2022-06-24 11:25:23 -0500256{
257 std::map<std::string, std::variant<std::string>> properties{};
258 std::string interface;
259 msg.read(interface, properties);
260 const auto stateEntry = properties.find("CurrentHostState");
261 if (stateEntry != properties.end())
262 {
263 auto stateEntryValue = stateEntry->second;
264 auto propVal = std::get<std::string>(stateEntryValue);
265 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
266 {
267 clearData();
268 }
269 }
270}
271
Chris Cainbae4d072022-02-28 09:46:50 -0600272void Interface::clearData()
273{
Chris Cain72d01aa2022-06-14 16:28:03 -0500274 if (!sensorToOCCInstance.empty())
275 {
276 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600277 std::format("clearData: Clearing sensorToOCCInstance ({} entries)",
Chris Cain72d01aa2022-06-14 16:28:03 -0500278 sensorToOCCInstance.size())
279 .c_str());
280 for (auto entry : sensorToOCCInstance)
281 {
282 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600283 std::format("clearData: OCC{} / sensorID: 0x{:04X}",
Chris Cain72d01aa2022-06-14 16:28:03 -0500284 entry.second, entry.first)
285 .c_str());
Chris Cain082a6ca2023-03-21 10:27:26 -0500286 callBack(entry.second, false);
Chris Cain72d01aa2022-06-14 16:28:03 -0500287 }
288 sensorToOCCInstance.clear();
289 }
290 if (!occInstanceToEffecter.empty())
291 {
292 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600293 std::format(
Chris Cain72d01aa2022-06-14 16:28:03 -0500294 "clearData: Clearing occInstanceToEffecter ({} entries)",
295 occInstanceToEffecter.size())
296 .c_str());
297 occInstanceToEffecter.clear();
298 }
299 if (!sensorToSBEInstance.empty())
300 {
301 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600302 std::format("clearData: Clearing sensorToSBEInstance ({} entries)",
Chris Cain72d01aa2022-06-14 16:28:03 -0500303 sensorToSBEInstance.size())
304 .c_str());
305 sensorToSBEInstance.clear();
306 }
307 if (!sbeInstanceToEffecter.empty())
308 {
309 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600310 std::format(
Chris Cain72d01aa2022-06-14 16:28:03 -0500311 "clearData: Clearing sbeInstanceToEffecter ({} entries)",
312 sbeInstanceToEffecter.size())
313 .c_str());
314 sbeInstanceToEffecter.clear();
315 }
Chris Cainbae4d072022-02-28 09:46:50 -0600316}
317
Eddie James432dc482021-11-19 15:29:31 -0600318void Interface::fetchEffecterInfo(uint16_t stateSetId,
Eddie Jamescbad2192021-10-07 09:39:39 -0500319 InstanceToEffecter& instanceToEffecterMap,
320 CompositeEffecterCount& effecterCount,
321 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
393std::vector<uint8_t>
Chris Cain8b508bf2022-05-26 14:01:31 -0500394 Interface::prepareSetEffecterReq(EffecterID effecterId,
Patrick Williams05e95592021-09-02 09:28:14 -0500395 CompositeEffecterCount effecterCount,
Eddie Jamescbad2192021-10-07 09:39:39 -0500396 uint8_t stateIdPos, uint8_t stateSetValue)
Patrick Williams05e95592021-09-02 09:28:14 -0500397{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100398 if (!getPldmInstanceId())
Chris Cain8b508bf2022-05-26 14:01:31 -0500399 {
400 return std::vector<uint8_t>();
401 }
402
Patrick Williams05e95592021-09-02 09:28:14 -0500403 std::vector<uint8_t> request(
404 sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(effecterCount) +
405 (effecterCount * sizeof(set_effecter_state_field)));
406 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
407 std::vector<set_effecter_state_field> stateField;
408
409 for (uint8_t effecterPos = 0; effecterPos < effecterCount; effecterPos++)
410 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500411 if (effecterPos == stateIdPos)
Patrick Williams05e95592021-09-02 09:28:14 -0500412 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500413 stateField.emplace_back(
414 set_effecter_state_field{PLDM_REQUEST_SET, stateSetValue});
Patrick Williams05e95592021-09-02 09:28:14 -0500415 }
416 else
417 {
418 stateField.emplace_back(
419 set_effecter_state_field{PLDM_NO_CHANGE, 0});
420 }
421 }
422 auto rc = encode_set_state_effecter_states_req(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100423 pldmInstanceID.value(), effecterId, effecterCount, stateField.data(),
Chris Cain8b508bf2022-05-26 14:01:31 -0500424 requestMsg);
Patrick Williams05e95592021-09-02 09:28:14 -0500425 if (rc != PLDM_SUCCESS)
426 {
427 log<level::ERR>("encode set effecter states request returned error ",
428 entry("RC=%d", rc));
429 request.clear();
430 }
431 return request;
432}
433
434void Interface::resetOCC(open_power::occ::instanceID occInstanceId)
435{
Chris Cainbae4d072022-02-28 09:46:50 -0600436 if (open_power::occ::utils::isHostRunning())
Patrick Williams05e95592021-09-02 09:28:14 -0500437 {
Chris Cainbae4d072022-02-28 09:46:50 -0600438 if (!isPDREffecterCacheValid())
439 {
440 fetchEffecterInfo(PLDM_STATE_SET_BOOT_RESTART_CAUSE,
441 occInstanceToEffecter, OCCEffecterCount,
442 bootRestartPosition);
443 }
Patrick Williams05e95592021-09-02 09:28:14 -0500444
Chris Cainbae4d072022-02-28 09:46:50 -0600445 // Find the matching effecter for the OCC instance
446 auto effecterEntry = occInstanceToEffecter.find(occInstanceId);
447 if (effecterEntry == occInstanceToEffecter.end())
448 {
449 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600450 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600451 "pldm: Failed to find a matching effecter for OCC instance {}",
452 occInstanceId)
453 .c_str());
454
455 return;
456 }
457
Chris Cainbae4d072022-02-28 09:46:50 -0600458 // Prepare the SetStateEffecterStates request to reset the OCC
459 auto request = prepareSetEffecterReq(
Chris Cain8b508bf2022-05-26 14:01:31 -0500460 effecterEntry->second, OCCEffecterCount, bootRestartPosition,
461 PLDM_STATE_SET_BOOT_RESTART_CAUSE_WARM_RESET);
Chris Cainbae4d072022-02-28 09:46:50 -0600462
463 if (request.empty())
464 {
465 log<level::ERR>(
466 "pldm: SetStateEffecterStates OCC reset request empty");
467 return;
468 }
469
470 // Send request to reset the OCCs/PM Complex (ignore response)
471 sendPldm(request, occInstanceId, false);
472 }
473 else
Patrick Williams05e95592021-09-02 09:28:14 -0500474 {
475 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600476 std::format("resetOCC: HOST is not running (OCC{})", occInstanceId)
Chris Cain0f516522022-02-07 14:48:28 -0600477 .c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600478 clearData();
Patrick Williams05e95592021-09-02 09:28:14 -0500479 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500480}
481
482void Interface::sendHRESET(open_power::occ::instanceID sbeInstanceId)
483{
Chris Cainbae4d072022-02-28 09:46:50 -0600484 if (open_power::occ::utils::isHostRunning())
Eddie Jamescbad2192021-10-07 09:39:39 -0500485 {
Chris Cainbae4d072022-02-28 09:46:50 -0600486 if (sbeInstanceToEffecter.empty())
487 {
488 fetchEffecterInfo(PLDM_OEM_IBM_SBE_MAINTENANCE_STATE,
489 sbeInstanceToEffecter, SBEEffecterCount,
490 sbeMaintenanceStatePosition);
491 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500492
Chris Cainbae4d072022-02-28 09:46:50 -0600493 auto effecterEntry = sbeInstanceToEffecter.find(sbeInstanceId);
494 if (effecterEntry == sbeInstanceToEffecter.end())
495 {
496 log<level::ERR>(
497 "pldm: Failed to find a matching effecter for SBE instance",
498 entry("SBE=%d", sbeInstanceId));
499 return;
500 }
501
Chris Cainbae4d072022-02-28 09:46:50 -0600502 // Prepare the SetStateEffecterStates request to HRESET the SBE
503 auto request = prepareSetEffecterReq(
Chris Cain8b508bf2022-05-26 14:01:31 -0500504 effecterEntry->second, SBEEffecterCount,
Chris Cainbae4d072022-02-28 09:46:50 -0600505 sbeMaintenanceStatePosition, SBE_RETRY_REQUIRED);
506
507 if (request.empty())
508 {
509 log<level::ERR>(
510 "pldm: SetStateEffecterStates HRESET request empty");
511 return;
512 }
513
514 // Send request to issue HRESET of SBE (ignore response)
515 sendPldm(request, sbeInstanceId, false);
Chris Cain12d0b822022-04-22 17:29:18 -0500516 outstandingHResets.insert(sbeInstanceId);
Chris Cainbae4d072022-02-28 09:46:50 -0600517 }
518 else
Eddie Jamescbad2192021-10-07 09:39:39 -0500519 {
Patrick Williams48002492024-02-13 21:43:32 -0600520 log<level::ERR>(std::format("sendHRESET: HOST is not running (OCC{})",
Chris Cainbae4d072022-02-28 09:46:50 -0600521 sbeInstanceId)
522 .c_str());
523 clearData();
Eddie Jamescbad2192021-10-07 09:39:39 -0500524 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500525}
526
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100527bool Interface::getPldmInstanceId()
Eddie Jamescbad2192021-10-07 09:39:39 -0500528{
Rashmica Guptadb38e912023-05-25 10:33:46 +1000529 pldm_instance_id_t id;
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100530 if (!pldmInstanceID)
Patrick Williams05e95592021-09-02 09:28:14 -0500531 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500532 // Request new instance ID
Rashmica Guptadb38e912023-05-25 10:33:46 +1000533 int rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
534 if (rc == -EAGAIN)
Chris Cain8b508bf2022-05-26 14:01:31 -0500535 {
Rashmica Guptadb38e912023-05-25 10:33:46 +1000536 std::this_thread::sleep_for(std::chrono::milliseconds(100));
537 rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
Chris Cain8b508bf2022-05-26 14:01:31 -0500538 }
Rashmica Guptadb38e912023-05-25 10:33:46 +1000539
540 if (rc)
Chris Cain8b508bf2022-05-26 14:01:31 -0500541 {
542 log<level::ERR>(
Rashmica Guptadb38e912023-05-25 10:33:46 +1000543 std::format(
544 "getPldmInstanceId: Failed to alloc ID for TID {}. RC{}",
545 tid, rc)
Chris Cain8b508bf2022-05-26 14:01:31 -0500546 .c_str());
547 return false;
548 }
Rashmica Guptadb38e912023-05-25 10:33:46 +1000549 pldmInstanceID.emplace(id);
550 if (!throttleTraces)
551 {
552 log<level::INFO>(
553 std::format("got id {} and set PldmInstanceId to {}", id,
554 pldmInstanceID.value())
555 .c_str());
556 }
Patrick Williams05e95592021-09-02 09:28:14 -0500557 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500558 return true;
559}
Patrick Williams05e95592021-09-02 09:28:14 -0500560
Rashmica Guptadb38e912023-05-25 10:33:46 +1000561void Interface::freePldmInstanceId()
562{
563 if (pldmInstanceID)
564 {
565 int rc = pldm_instance_id_free(pldmInstanceIdDb, tid,
566 pldmInstanceID.value());
567 if (rc)
568 {
569 log<level::ERR>(
570 std::format(
571 "freePldmInstanceId: Failed to free ID {} for TID {}. RC{}",
572 pldmInstanceID.value(), tid, rc)
573 .c_str());
574 return;
575 }
576 if (!throttleTraces)
577 {
578 log<level::INFO>(
579 std::format("Freed PLDM instance ID {}", pldmInstanceID.value())
580 .c_str());
581 }
582 pldmInstanceID = std::nullopt;
583 }
584}
585
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100586int Interface::openMctpDemuxTransport()
587{
588 mctpDemux = nullptr;
589 int rc = pldm_transport_mctp_demux_init(&mctpDemux);
590 if (rc)
591 {
592 log<level::ERR>(
593 std::format(
594 "openMctpDemuxTransport: Failed to init MCTP demux transport, errno={}/{}",
595 rc, strerror(rc))
596 .c_str());
597 return -1;
598 }
599
600 if (pldm_transport_mctp_demux_map_tid(mctpDemux, mctpEid, mctpEid))
601 {
602 log<level::ERR>(
603 std::format(
604 "openMctpDemuxTransport: Failed to setup tid to eid mapping, errno={}/{}",
605 errno, strerror(errno))
606 .c_str());
607 pldmClose();
608 return -1;
609 }
610 pldmTransport = pldm_transport_mctp_demux_core(mctpDemux);
611
612 struct pollfd pollfd;
613 if (pldm_transport_mctp_demux_init_pollfd(pldmTransport, &pollfd))
614 {
615 log<level::ERR>(
616 std::format(
617 "openMctpDemuxTransport: Failed to get pollfd , errno={}/{}",
618 errno, strerror(errno))
619 .c_str());
620 pldmClose();
621 return -1;
622 }
623 pldmFd = pollfd.fd;
624 if (!throttleTraces)
625 {
626 log<level::INFO>(
627 std::format("openMctpDemuxTransport: pldmFd has fd={}", pldmFd)
628 .c_str());
629 }
630 return 0;
631}
632
633int Interface::pldmOpen()
634{
635 if (pldmTransport)
636 {
637 log<level::ERR>(
638 std::format("pldmOpen: pldmTransport already setup!, errno={}/{}",
639 errno, strerror(errno))
640 .c_str());
641 return -1;
642 }
643 return openMctpDemuxTransport();
644}
645
Chris Cainbae4d072022-02-28 09:46:50 -0600646void Interface::sendPldm(const std::vector<uint8_t>& request,
647 const uint8_t instance, const bool rspExpected)
Eddie Jamescbad2192021-10-07 09:39:39 -0500648{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100649 if (!pldmInstanceID)
Chris Cain8b508bf2022-05-26 14:01:31 -0500650 {
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100651 log<level::ERR>("sendPldm: No PLDM Instance ID found!");
Chris Cain8b508bf2022-05-26 14:01:31 -0500652 return;
653 }
654
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100655 auto rc = pldmOpen();
656 if (rc)
Patrick Williams05e95592021-09-02 09:28:14 -0500657 {
Chris Caind1b68262022-02-28 09:56:50 -0600658 log<level::ERR>(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100659 std::format("sendPldm: pldmOpen failed rc={}", rc).c_str());
Rashmica Guptadb38e912023-05-25 10:33:46 +1000660 freePldmInstanceId();
Patrick Williams05e95592021-09-02 09:28:14 -0500661 return;
662 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500663
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100664 pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEid);
Patrick Williams05e95592021-09-02 09:28:14 -0500665 // Send the PLDM request message to HBRT
Chris Cainbae4d072022-02-28 09:46:50 -0600666 if (rspExpected)
Patrick Williams05e95592021-09-02 09:28:14 -0500667 {
Chris Cainbae4d072022-02-28 09:46:50 -0600668 // Register callback when response is available
669 registerPldmRspCallback();
670
671 // Send PLDM request
Chris Cain755af102024-02-27 16:09:51 -0600672 if (!throttleTraces)
673 {
674 log<level::INFO>(
675 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100676 "sendPldm: calling pldm_transport_send_msg(OCC{}, instance:{}, {} bytes)",
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100677 instance, pldmInstanceID.value(), request.size())
Chris Cain755af102024-02-27 16:09:51 -0600678 .c_str());
679 }
Chris Cainbae4d072022-02-28 09:46:50 -0600680 pldmResponseReceived = false;
681 pldmResponseTimeout = false;
682 pldmResponseOcc = instance;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100683 auto pldmRc = pldm_transport_send_msg(pldmTransport, pldmTID,
684 request.data(), request.size());
Chris Cainbae4d072022-02-28 09:46:50 -0600685 auto sendErrno = errno;
686 if (pldmRc != PLDM_REQUESTER_SUCCESS)
687 {
688 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600689 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100690 "sendPldm: pldm_transport_send_msg failed with rc={} and errno={}/{}",
Chris Cain5161a022023-08-15 10:07:12 -0500691 static_cast<
692 std::underlying_type_t<pldm_requester_error_codes>>(
693 pldmRc),
694 sendErrno, strerror(sendErrno))
Chris Cainbae4d072022-02-28 09:46:50 -0600695 .c_str());
696 pldmClose();
697 return;
698 }
699
700 // start timer waiting for the response
701 using namespace std::literals::chrono_literals;
Chris Cainbd551de2022-04-26 13:41:16 -0500702 pldmRspTimer.restartOnce(8s);
Chris Cainbae4d072022-02-28 09:46:50 -0600703
704 // Wait for response/timeout
705 }
706 else // not expecting the response
707 {
Chris Cain755af102024-02-27 16:09:51 -0600708 if (!throttleTraces)
709 {
710 log<level::INFO>(
711 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100712 "sendPldm: calling pldm_transport_send_msg(mctpID:{}, fd:{}, {} bytes) for OCC{}",
Chris Cain755af102024-02-27 16:09:51 -0600713 mctpEid, pldmFd, request.size(), instance)
714 .c_str());
715 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100716 auto rc = pldm_transport_send_msg(pldmTransport, pldmTID,
717 request.data(), request.size());
Chris Cainbae4d072022-02-28 09:46:50 -0600718 auto sendErrno = errno;
Chris Caind1b68262022-02-28 09:56:50 -0600719 if (rc)
720 {
721 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600722 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100723 "sendPldm: pldm_transport_send_msg(mctpID:{}, fd:{}, {} bytes) failed with rc={} and errno={}/{}",
Chris Cain5161a022023-08-15 10:07:12 -0500724 mctpEid, pldmFd, request.size(),
725 static_cast<
726 std::underlying_type_t<pldm_requester_error_codes>>(rc),
727 sendErrno, strerror(sendErrno))
Chris Caind1b68262022-02-28 09:56:50 -0600728 .c_str());
729 }
Chris Cainbae4d072022-02-28 09:46:50 -0600730 pldmClose();
731 }
732}
Patrick Williams05e95592021-09-02 09:28:14 -0500733
Chris Cainbae4d072022-02-28 09:46:50 -0600734// Attaches the FD to event loop and registers the callback handler
735void Interface::registerPldmRspCallback()
736{
737 decltype(eventSource.get()) sourcePtr = nullptr;
738 auto rc = sd_event_add_io(event.get(), &sourcePtr, pldmFd, EPOLLIN,
739 pldmRspCallback, this);
740 if (rc < 0)
741 {
742 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600743 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600744 "registerPldmRspCallback: sd_event_add_io: Error({})={} : fd={}",
745 rc, strerror(-rc), pldmFd)
746 .c_str());
Chris Caind1b68262022-02-28 09:56:50 -0600747 }
748 else
Patrick Williams05e95592021-09-02 09:28:14 -0500749 {
Chris Cainbae4d072022-02-28 09:46:50 -0600750 // puts sourcePtr in the event source.
751 eventSource.reset(sourcePtr);
752 }
753}
754
755// Add a timer to the event loop, default 30s.
756void Interface::pldmRspExpired()
757{
758 if (!pldmResponseReceived)
759 {
Chris Cain755af102024-02-27 16:09:51 -0600760 if (!throttleTraces)
761 {
762 log<level::WARNING>(
763 std::format(
764 "pldmRspExpired: timerCallback - timeout waiting for pldm response for OCC{}",
765 pldmResponseOcc)
766 .c_str());
767 }
Chris Cainbae4d072022-02-28 09:46:50 -0600768 pldmResponseTimeout = true;
769 if (pldmFd)
770 {
771 pldmClose();
772 }
773 }
774 return;
775};
776
777void Interface::pldmClose()
778{
Rashmica Guptadb38e912023-05-25 10:33:46 +1000779 freePldmInstanceId();
Chris Cainbae4d072022-02-28 09:46:50 -0600780 if (pldmRspTimer.isEnabled())
781 {
782 // stop PLDM response timer
783 pldmRspTimer.setEnabled(false);
784 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100785
786 pldm_transport_mctp_demux_destroy(mctpDemux);
787 mctpDemux = NULL;
Chris Cainbae4d072022-02-28 09:46:50 -0600788 pldmFd = -1;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100789 pldmTransport = NULL;
Chris Cainbae4d072022-02-28 09:46:50 -0600790 eventSource.reset();
791}
792
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100793int Interface::pldmRspCallback(sd_event_source* /*es*/,
794 __attribute__((unused)) int fd, uint32_t revents,
795 void* userData)
Chris Cainbae4d072022-02-28 09:46:50 -0600796{
797 if (!(revents & EPOLLIN))
798 {
799 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600800 std::format("pldmRspCallback - revents={:08X}", revents).c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600801 return -1;
802 }
803
804 auto pldmIface = static_cast<Interface*>(userData);
805
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100806 if (!pldmIface->pldmInstanceID)
Chris Cain8b508bf2022-05-26 14:01:31 -0500807 {
808 log<level::ERR>(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100809 "pldmRspCallback: No outstanding PLDM Instance ID found");
Chris Cain8b508bf2022-05-26 14:01:31 -0500810 return -1;
811 }
812
Chris Cainbae4d072022-02-28 09:46:50 -0600813 uint8_t* responseMsg = nullptr;
814 size_t responseMsgSize{};
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100815 pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEid);
Chris Cainbae4d072022-02-28 09:46:50 -0600816
Chris Cain755af102024-02-27 16:09:51 -0600817 if (!throttleTraces)
818 {
819 log<level::INFO>(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100820 std::format(
821 "pldmRspCallback: calling pldm_transport_recv_msg() instance:{}",
822 pldmIface->pldmInstanceID.value())
Chris Cain755af102024-02-27 16:09:51 -0600823 .c_str());
824 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100825 auto rc = pldm_transport_recv_msg(pldmIface->pldmTransport, &pldmTID,
826 (void**)&responseMsg, &responseMsgSize);
Chris Cainbae4d072022-02-28 09:46:50 -0600827 int lastErrno = errno;
828 if (rc)
829 {
Chris Cain755af102024-02-27 16:09:51 -0600830 if (!throttleTraces)
831 {
832 log<level::ERR>(
833 std::format(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100834 "pldmRspCallback: pldm_transport_recv_msg failed with rc={}, errno={}/{}",
Chris Cain755af102024-02-27 16:09:51 -0600835 static_cast<
836 std::underlying_type_t<pldm_requester_error_codes>>(rc),
837 lastErrno, strerror(lastErrno))
838 .c_str());
839 }
Chris Cainbae4d072022-02-28 09:46:50 -0600840 return -1;
841 }
Chris Cain8b508bf2022-05-26 14:01:31 -0500842
843 // We got the response for the PLDM request msg that was sent
Chris Cain755af102024-02-27 16:09:51 -0600844 if (!throttleTraces)
845 {
846 log<level::INFO>(
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100847 std::format(
848 "pldmRspCallback: pldm_transport_recv_msg() rsp was {} bytes",
849 responseMsgSize)
Chris Cain755af102024-02-27 16:09:51 -0600850 .c_str());
851 }
Chris Cainbae4d072022-02-28 09:46:50 -0600852
853 if (pldmIface->pldmRspTimer.isEnabled())
854 {
855 // stop PLDM response timer
856 pldmIface->pldmRspTimer.setEnabled(false);
857 }
858
Chris Cain8b508bf2022-05-26 14:01:31 -0500859 // instance ID should be freed
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100860 pldmIface->pldmInstanceID = std::nullopt;
Chris Cain8b508bf2022-05-26 14:01:31 -0500861
Chris Cainbae4d072022-02-28 09:46:50 -0600862 // Set pointer to autodelete
863 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{responseMsg,
864 std::free};
865
Chris Cainbae4d072022-02-28 09:46:50 -0600866 auto response = reinterpret_cast<pldm_msg*>(responseMsgPtr.get());
867 if (response->payload[0] != PLDM_SUCCESS)
868 {
869 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600870 std::format("pldmRspCallback: payload[0] was not success: {}",
Chris Cainbae4d072022-02-28 09:46:50 -0600871 response->payload[0])
872 .c_str());
873 pldmIface->pldmClose();
874 return -1;
875 }
876
877 // Decode the response
878 uint8_t compCode = 0, sensorCount = 1;
879 get_sensor_state_field field[6];
880 responseMsgSize -= sizeof(pldm_msg_hdr);
881 auto msgRc = decode_get_state_sensor_readings_resp(
882 response, responseMsgSize, &compCode, &sensorCount, field);
883 if ((msgRc != PLDM_SUCCESS) || (compCode != PLDM_SUCCESS))
884 {
885 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600886 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600887 "pldmRspCallback: decode_get_state_sensor_readings failed with rc={} and compCode={}",
888 msgRc, compCode)
889 .c_str());
890 pldmIface->pldmClose();
891 return -1;
892 }
893
894 pldmIface->pldmClose();
895
896 const uint8_t instance = pldmIface->pldmResponseOcc;
897 const uint8_t occSensorState = field[0].present_state;
898 pldmIface->pldmResponseReceived = true;
899
900 if (occSensorState == PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE)
901 {
902 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600903 std::format("pldmRspCallback: OCC{} is RUNNING", instance).c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600904 pldmIface->callBack(instance, true);
905 }
Chris Cain733b2012022-05-04 11:54:06 -0500906 else if (occSensorState ==
907 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT)
908 {
Chris Cain755af102024-02-27 16:09:51 -0600909 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600910 std::format(
Chris Cain733b2012022-05-04 11:54:06 -0500911 "pldmRspCallback: OCC{} has now STOPPED and system is in SAFE MODE",
912 instance)
913 .c_str());
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500914
915 // Setting safe mode true
916 pldmIface->safeModeCallBack(true);
917
Chris Cain733b2012022-05-04 11:54:06 -0500918 pldmIface->callBack(instance, false);
919 }
Chris Cain755af102024-02-27 16:09:51 -0600920 else if (occSensorState ==
921 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED)
Chris Cainbae4d072022-02-28 09:46:50 -0600922 {
923 log<level::INFO>(
Chris Cain755af102024-02-27 16:09:51 -0600924 std::format("pldmRspCallback: OCC{} is not running", instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600925 .c_str());
Chris Cain755af102024-02-27 16:09:51 -0600926 pldmIface->callBack(instance, false);
927 }
928 else
929 {
930 const size_t rspLength = responseMsgSize + sizeof(pldm_msg_hdr);
931 std::vector<std::uint8_t> pldmResponse(rspLength);
932 memcpy(&pldmResponse[0], reinterpret_cast<std::uint8_t*>(response),
933 rspLength);
934 if (!throttleTraces)
Chris Cainc9dc4412023-03-06 15:56:34 -0600935 {
Chris Cain755af102024-02-27 16:09:51 -0600936 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -0600937 std::format(
Chris Cain755af102024-02-27 16:09:51 -0600938 "pldmRspCallback: Unexpected State: {} - PLDM response ({} bytes) for OCC{}:",
939 occSensorState, rspLength, instance)
Chris Cainc9dc4412023-03-06 15:56:34 -0600940 .c_str());
941 dump_hex(pldmResponse);
942 }
Chris Cainbae4d072022-02-28 09:46:50 -0600943 }
944
945 return 0;
946};
947
948std::vector<uint8_t> Interface::encodeGetStateSensorRequest(uint8_t instance,
949 uint16_t sensorId)
950{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100951 if (!getPldmInstanceId())
Chris Cain8b508bf2022-05-26 14:01:31 -0500952 {
953 log<level::ERR>(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100954 "encodeGetStateSensorRequest: failed to getPldmInstanceId");
Chris Cain8b508bf2022-05-26 14:01:31 -0500955 return std::vector<uint8_t>();
956 }
957
Chris Cainbae4d072022-02-28 09:46:50 -0600958 bitfield8_t sRearm = {0};
Patrick Williamsa49c9872023-05-10 07:50:35 -0500959 const size_t msgSize = sizeof(pldm_msg_hdr) +
960 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES;
Chris Cainbae4d072022-02-28 09:46:50 -0600961 std::vector<uint8_t> request(msgSize);
Chris Cain8b508bf2022-05-26 14:01:31 -0500962
Chris Cainbae4d072022-02-28 09:46:50 -0600963 auto msg = reinterpret_cast<pldm_msg*>(request.data());
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100964 auto msgRc = encode_get_state_sensor_readings_req(pldmInstanceID.value(),
Chris Cain8b508bf2022-05-26 14:01:31 -0500965 sensorId, sRearm, 0, msg);
Chris Cainbae4d072022-02-28 09:46:50 -0600966 if (msgRc != PLDM_SUCCESS)
967 {
968 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600969 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600970 "encodeGetStateSensorRequest: Failed to encode sensorId:0x{:08X} for OCC{} (rc={})",
971 sensorId, instance, msgRc)
972 .c_str());
973 }
974 return request;
975}
976
977// Initiate query of the specified OCC Active Sensor
978void Interface::checkActiveSensor(uint8_t instance)
979{
980 static bool tracedOnce = false;
981 if (pldmFd > 0)
982 {
Chris Cain755af102024-02-27 16:09:51 -0600983 if (!throttleTraces && !tracedOnce)
Chris Caind1b68262022-02-28 09:56:50 -0600984 {
Chris Cain755af102024-02-27 16:09:51 -0600985 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -0600986 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600987 "checkActiveSensor: already waiting on OCC{} (fd={})",
988 pldmResponseOcc, pldmFd)
Chris Caind1b68262022-02-28 09:56:50 -0600989 .c_str());
Chris Cainbae4d072022-02-28 09:46:50 -0600990 tracedOnce = true;
Chris Caind1b68262022-02-28 09:56:50 -0600991 }
Chris Cainbae4d072022-02-28 09:46:50 -0600992 return;
993 }
994 tracedOnce = false;
995
996 if (!isOCCSensorCacheValid())
997 {
998 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
999 sensorToOCCInstance, OCCSensorOffset);
1000 }
1001
1002 // look up sensor id (key) based on instance
1003 auto entry = std::find_if(
1004 sensorToOCCInstance.begin(), sensorToOCCInstance.end(),
1005 [instance](const auto& entry) { return instance == entry.second; });
1006 if (entry != sensorToOCCInstance.end())
1007 {
1008 // Query the OCC Active Sensor state for this instance
Chris Cain755af102024-02-27 16:09:51 -06001009 if (!throttleTraces)
1010 {
1011 log<level::INFO>(
1012 std::format("checkActiveSensor: OCC{} / sensorID: 0x{:04X}",
1013 instance, entry->first)
1014 .c_str());
1015 }
Chris Cainbae4d072022-02-28 09:46:50 -06001016
Chris Cainbae4d072022-02-28 09:46:50 -06001017 // Encode GetStateSensorReadings PLDM message
1018 auto request = encodeGetStateSensorRequest(instance, entry->first);
1019 if (request.empty())
1020 {
1021 return;
1022 }
1023
1024 // Send request to PLDM and setup callback for response
1025 sendPldm(request, instance, true);
1026 }
1027 else
1028 {
Chris Cain755af102024-02-27 16:09:51 -06001029 if (!throttleTraces)
1030 {
1031 log<level::ERR>(
1032 std::format(
1033 "checkActiveSensor: Unable to find PLDM sensor for OCC{}",
1034 instance)
1035 .c_str());
1036 log<level::INFO>(
1037 "checkActiveSensor: fetching STATE_SET_OPERATIONAL_RUNNING_STATUS");
1038 }
Chris Cain8cf74962022-06-29 08:45:16 -05001039 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
1040 sensorToOCCInstance, OCCSensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -05001041 }
Patrick Williams05e95592021-09-02 09:28:14 -05001042}
1043
Chris Cain755af102024-02-27 16:09:51 -06001044void Interface::setTraceThrottle(const bool throttle)
1045{
1046 if (throttle != throttleTraces)
1047 {
1048 if (throttle)
1049 {
1050 log<level::WARNING>("PLDM traces being throttled");
1051 }
1052 else
1053 {
1054 log<level::INFO>("PLDM traces no longer being throttled");
1055 }
1056 throttleTraces = throttle;
1057 }
1058}
1059
Patrick Williams05e95592021-09-02 09:28:14 -05001060} // namespace pldm