blob: 5d093a1aa1d6dc561abea19b10ade5dffadfefca [file] [log] [blame]
Patrick Williams05e95592021-09-02 09:28:14 -05001#pragma once
Chris Cainbae4d072022-02-28 09:46:50 -06002#include "occ_events.hpp"
Patrick Williams05e95592021-09-02 09:28:14 -05003#include "occ_status.hpp"
4#include "utils.hpp"
5
6#include <libpldm/pldm.h>
7
8#include <sdbusplus/bus/match.hpp>
Chris Cainbae4d072022-02-28 09:46:50 -06009#include <sdeventplus/event.hpp>
10#include <sdeventplus/utility/timer.hpp>
Patrick Williams05e95592021-09-02 09:28:14 -050011
12namespace pldm
13{
14
15namespace MatchRules = sdbusplus::bus::match::rules;
Chris Cainbae4d072022-02-28 09:46:50 -060016using namespace open_power::occ;
Patrick Williams05e95592021-09-02 09:28:14 -050017
18using CompositeEffecterCount = uint8_t;
19using EffecterID = uint16_t;
20using EntityType = uint16_t;
21using EntityInstance = uint16_t;
22using EventState = uint8_t;
Eddie Jamescbad2192021-10-07 09:39:39 -050023using InstanceToEffecter = std::map<open_power::occ::instanceID, EffecterID>;
Patrick Williams05e95592021-09-02 09:28:14 -050024using PdrList = std::vector<std::vector<uint8_t>>;
25using SensorID = uint16_t;
26using SensorOffset = uint8_t;
Eddie Jamescbad2192021-10-07 09:39:39 -050027using SensorToInstance = std::map<SensorID, open_power::occ::instanceID>;
Patrick Williams05e95592021-09-02 09:28:14 -050028using TerminusID = uint8_t;
29
30/** @brief Hardcoded TID */
31constexpr TerminusID tid = 0;
32
33/** @brief OCC instance starts with 0 for example "occ0" */
34constexpr open_power::occ::instanceID start = 0;
35
36/** @brief Hardcoded mctpEid for HBRT */
37constexpr mctp_eid_t mctpEid = 10;
38
39/** @class Interface
40 *
41 * @brief Abstracts the PLDM details related to the OCC
42 */
43class Interface
44{
45 public:
46 Interface() = delete;
47 ~Interface() = default;
48 Interface(const Interface&) = delete;
49 Interface& operator=(const Interface&) = delete;
50 Interface(Interface&&) = delete;
51 Interface& operator=(Interface&&) = delete;
52
53 /** @brief Constructs the PLDM Interface object for OCC functions
54 *
55 * @param[in] callBack - callBack handler to invoke when the OCC state
56 * changes.
57 */
58 explicit Interface(
Eddie Jamescbad2192021-10-07 09:39:39 -050059 std::function<bool(open_power::occ::instanceID, bool)> callBack,
Chris Cainbae4d072022-02-28 09:46:50 -060060 std::function<void(open_power::occ::instanceID, bool)> sbeCallBack,
Sheldon Bailey31a2f132022-05-20 11:31:52 -050061 std::function<void(bool)> safeModeCallBack, EventPtr& event) :
Patrick Williams05e95592021-09-02 09:28:14 -050062 callBack(callBack),
Sheldon Bailey31a2f132022-05-20 11:31:52 -050063 sbeCallBack(sbeCallBack), safeModeCallBack(safeModeCallBack),
64 event(event),
Patrick Williams05e95592021-09-02 09:28:14 -050065 pldmEventSignal(
66 open_power::occ::utils::getBus(),
67 MatchRules::type::signal() +
68 MatchRules::member("StateSensorEvent") +
69 MatchRules::path("/xyz/openbmc_project/pldm") +
70 MatchRules::interface("xyz.openbmc_project.PLDM.Event"),
71 std::bind(std::mem_fn(&Interface::sensorEvent), this,
72 std::placeholders::_1)),
Chris Cain157467d2022-06-24 11:25:23 -050073 hostStateSignal(
74 open_power::occ::utils::getBus(),
75 MatchRules::propertiesChanged("/xyz/openbmc_project/state/host0",
76 "xyz.openbmc_project.State.Host"),
77 std::bind(std::mem_fn(&Interface::hostStateEvent), this,
78 std::placeholders::_1)),
Chris Cainbae4d072022-02-28 09:46:50 -060079 sdpEvent(sdeventplus::Event::get_default()),
80 pldmRspTimer(
81 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>(
82 sdpEvent, std::bind(&Interface::pldmRspExpired, this)))
George Liub5ca1012021-09-10 12:53:11 +080083 {}
Patrick Williams05e95592021-09-02 09:28:14 -050084
Eddie Jamescbad2192021-10-07 09:39:39 -050085 /** @brief Fetch the state sensor PDRs and populate the cache with
86 * sensorId to OCC/SBE instance mapping information and the sensor
87 * offset for the relevent state set.
Patrick Williams05e95592021-09-02 09:28:14 -050088 *
Eddie Jamescbad2192021-10-07 09:39:39 -050089 * @param[in] stateSetId - the state set ID to look for
90 * @param[out] sensorInstanceMap - map of sensorID to instance
Patrick Williams05e95592021-09-02 09:28:14 -050091 * @param[out] sensorOffset - sensor offset of interested state set ID
92 */
Eddie Jamescbad2192021-10-07 09:39:39 -050093 void fetchSensorInfo(uint16_t stateSetId,
94 SensorToInstance& sensorInstanceMap,
95 SensorOffset& sensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -050096
Eddie Jamescbad2192021-10-07 09:39:39 -050097 /** @brief Fetch the OCC/SBE state effecter PDRs and populate the cache
98 * with OCC/SBE instance to EffecterID information.
Patrick Williams05e95592021-09-02 09:28:14 -050099 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500100 * @param[in] stateSetId - the state set ID to look for
101 * @param[out] instanceToEffecterMap - map of instance to effecterID
Patrick Williams05e95592021-09-02 09:28:14 -0500102 * @param[out] count - sensor offset of interested state set ID
Eddie Jamescbad2192021-10-07 09:39:39 -0500103 * @param[out] stateIdPos - position of the stateSetID
Patrick Williams05e95592021-09-02 09:28:14 -0500104 */
Eddie James432dc482021-11-19 15:29:31 -0600105 void fetchEffecterInfo(uint16_t stateSetId,
Eddie Jamescbad2192021-10-07 09:39:39 -0500106 InstanceToEffecter& instanceToEffecterMap,
107 CompositeEffecterCount& count, uint8_t& stateIdPos);
Patrick Williams05e95592021-09-02 09:28:14 -0500108
109 /** @brief Prepare the request for SetStateEffecterStates command
110 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500111 * @param[in] effecterId - the instance effecter ID
112 * @param[in] effecterCount - compositeEffecterCount for the effecter PDR
113 * @param[in] stateIdPos - position of the stateSetID
114 * @param[in] stateSetValue - the value to set the state set to
Patrick Williams05e95592021-09-02 09:28:14 -0500115 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500116 * @return PLDM request message to be sent to host for OCC reset or SBE
117 * HRESET, empty response in the case of failure.
Patrick Williams05e95592021-09-02 09:28:14 -0500118 */
119 std::vector<uint8_t>
Chris Cain8b508bf2022-05-26 14:01:31 -0500120 prepareSetEffecterReq(EffecterID effecterId,
Patrick Williams05e95592021-09-02 09:28:14 -0500121 CompositeEffecterCount effecterCount,
Eddie Jamescbad2192021-10-07 09:39:39 -0500122 uint8_t stateIdPos, uint8_t stateSetValue);
Patrick Williams05e95592021-09-02 09:28:14 -0500123
124 /** @brief Send the PLDM message to reset the OCC
125 *
126 * @param[in] instanceId - OCC instance to reset
127 *
128 */
129 void resetOCC(open_power::occ::instanceID occInstanceId);
130
Eddie Jamescbad2192021-10-07 09:39:39 -0500131 /** @brief Send the PLDM message to perform the HRESET
132 *
133 * @param[in] instanceID - SBE instance to HRESET
134 */
135 void sendHRESET(open_power::occ::instanceID sbeInstanceId);
136
Chris Cainbae4d072022-02-28 09:46:50 -0600137 /** @brief Check if the OCC active sensor is available
138 * On successful read, the Manager callback will be called to update
139 * the status
140 *
141 * @param[in] instance - OCC instance to check
142 */
143 void checkActiveSensor(uint8_t instance);
144
Chris Cain755af102024-02-27 16:09:51 -0600145 /** @brief Set the throttleTraces flag
146 *
147 * @param[in] throttle - Flag to indicate if traces should be throttled
148 */
149 void setTraceThrottle(const bool throttle);
150
Patrick Williams05e95592021-09-02 09:28:14 -0500151 private:
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100152 /** @brief PLDM instance number used in PLDM requests
Chris Cain8b508bf2022-05-26 14:01:31 -0500153 */
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100154 std::optional<uint8_t> pldmInstanceID;
Chris Cain8b508bf2022-05-26 14:01:31 -0500155
Patrick Williams05e95592021-09-02 09:28:14 -0500156 /** @brief Callback handler to be invoked when the state of the OCC
157 * changes
158 */
159 std::function<bool(open_power::occ::instanceID, bool)> callBack = nullptr;
160
Eddie Jamescbad2192021-10-07 09:39:39 -0500161 /** @brief Callback handler to be invoked when the maintenance state of the
162 * SBE changes
163 */
164 std::function<void(open_power::occ::instanceID, bool)> sbeCallBack =
165 nullptr;
166
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500167 /** @brief Callback handler to be invoked when the OCC is in SAFE Mode =
168 * true or when OCCs are in_service = false.
169 */
170 std::function<void(bool)> safeModeCallBack = nullptr;
171
Chris Cainbae4d072022-02-28 09:46:50 -0600172 /** @brief reference to sd_event wrapped in unique_ptr */
173 EventPtr& event;
174
175 /** @brief event source wrapped in unique_ptr */
176 EventSourcePtr eventSource;
177
Patrick Williams05e95592021-09-02 09:28:14 -0500178 /** @brief Used to subscribe to D-Bus PLDM StateSensorEvent signal and
179 * processes if the event corresponds to OCC state change.
180 */
181 sdbusplus::bus::match_t pldmEventSignal;
182
Chris Cain157467d2022-06-24 11:25:23 -0500183 /** @brief Used to subscribe for host state change signal */
184 sdbusplus::bus::match_t hostStateSignal;
185
Patrick Williams05e95592021-09-02 09:28:14 -0500186 /** @brief PLDM Sensor ID to OCC Instance mapping
187 */
Eddie Jamescbad2192021-10-07 09:39:39 -0500188 SensorToInstance sensorToOCCInstance;
Patrick Williams05e95592021-09-02 09:28:14 -0500189
Eddie Jamescbad2192021-10-07 09:39:39 -0500190 /** @brief PLDM Sensor ID to SBE Instance mapping
191 */
192 SensorToInstance sensorToSBEInstance;
193
194 /** @brief Sensor offset of OCC state set ID
Patrick Williams05e95592021-09-02 09:28:14 -0500195 * PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS in state sensor PDR.
196 */
George Liuf3a4a692021-12-28 13:59:51 +0800197 SensorOffset OCCSensorOffset = 0;
Eddie Jamescbad2192021-10-07 09:39:39 -0500198
199 /** @brief Sensor offset of the SBE state set ID
200 * PLDM_OEM_IBM_SBE_HRESET_STATE in state sensor PDR.
201 */
George Liuf3a4a692021-12-28 13:59:51 +0800202 SensorOffset SBESensorOffset = 0;
Patrick Williams05e95592021-09-02 09:28:14 -0500203
204 /** @brief OCC Instance mapping to PLDM Effecter ID
205 */
Eddie Jamescbad2192021-10-07 09:39:39 -0500206 InstanceToEffecter occInstanceToEffecter;
207
208 /** @brief SBE instance mapping to PLDM Effecter ID
209 */
210 InstanceToEffecter sbeInstanceToEffecter;
Patrick Williams05e95592021-09-02 09:28:14 -0500211
212 /** @brief compositeEffecterCount for OCC reset state effecter PDR */
Eddie Jamescbad2192021-10-07 09:39:39 -0500213 CompositeEffecterCount OCCEffecterCount = 0;
214
215 /** @brief compositeEffecterCount for SBE HRESET state effecter PDR */
216 CompositeEffecterCount SBEEffecterCount = 0;
Patrick Williams05e95592021-09-02 09:28:14 -0500217
218 /** @brief Position of Boot/Restart Cause stateSetID in OCC state
219 * effecter PDR
220 */
221 uint8_t bootRestartPosition = 0;
222
Eddie Jamescbad2192021-10-07 09:39:39 -0500223 /** @brief Position of the SBE maintenance stateSetID in the state
224 * effecter PDR
225 */
226 uint8_t sbeMaintenanceStatePosition = 0;
227
Chris Cainbae4d072022-02-28 09:46:50 -0600228 /** @brief OCC instance number for the PLDM message */
229 uint8_t pldmResponseOcc = 0;
230
231 /** @brief File descriptor for PLDM messages */
232 int pldmFd = -1;
233
Chris Cainbae4d072022-02-28 09:46:50 -0600234 /** @brief The response for the PLDM request msg is received flag.
235 */
236 bool pldmResponseReceived = false;
237
238 /** @brief The response for the PLDM request has timed out.
239 */
240 bool pldmResponseTimeout = false;
241
242 /** @brief timer event */
243 sdeventplus::Event sdpEvent;
244
245 /** @brief Timer that is started when PLDM command is sent
246 */
247 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> pldmRspTimer;
248
Chris Cain12d0b822022-04-22 17:29:18 -0500249 std::set<uint8_t> outstandingHResets;
250
Chris Cain755af102024-02-27 16:09:51 -0600251 /** @brief Flag to indicate that traces should be throttled.
252 Used to limit traces when there are issues getting OCC status.
253 */
254 static bool throttleTraces;
255
Chris Cainbae4d072022-02-28 09:46:50 -0600256 /** @brief Callback when PLDM response has not been received within the
257 * timeout period.
258 */
259 void pldmRspExpired();
260
261 /** @brief Close the MCTP file */
262 void pldmClose();
263
Patrick Williams05e95592021-09-02 09:28:14 -0500264 /** @brief When the OCC state changes host sends PlatformEventMessage
265 * StateSensorEvent, this function processes the D-Bus signal
266 * with the sensor event information and invokes the callback
267 * to change the OCC state.
268 *
269 * @param[in] msg - data associated with the subscribed signal
270 */
Patrick Williamsaf408082022-07-22 19:26:54 -0500271 void sensorEvent(sdbusplus::message_t& msg);
Patrick Williams05e95592021-09-02 09:28:14 -0500272
Chris Cain157467d2022-06-24 11:25:23 -0500273 /** @brief When the host state changes and if the CurrentHostState is
274 * xyz.openbmc_project.State.Host.HostState.Off then
275 * the cache of OCC sensors and effecters mapping is cleared.
276 *
277 * @param[in] msg - data associated with the subscribed signal
278 */
Patrick Williamsaf408082022-07-22 19:26:54 -0500279 void hostStateEvent(sdbusplus::message_t& msg);
Chris Cain157467d2022-06-24 11:25:23 -0500280
Chris Cainbae4d072022-02-28 09:46:50 -0600281 /** @brief Called when it is determined that the Host is not running.
282 * The cache of OCC sensors and effecters mapping is cleared.
283 */
284 void clearData();
285
Patrick Williams05e95592021-09-02 09:28:14 -0500286 /** @brief Check if the PDR cache for PLDM OCC sensors is valid
287 *
288 * @return true if cache is populated and false if the cache is not
289 * populated.
290 */
291 auto isOCCSensorCacheValid()
292 {
293 return (sensorToOCCInstance.empty() ? false : true);
294 }
295
296 /** @brief Check if the PDR cache for PLDM OCC effecters is valid
297 *
298 * @return true if cache is populated and false if the cache is not
299 * populated.
300 */
301 auto isPDREffecterCacheValid()
302 {
303 return (occInstanceToEffecter.empty() ? false : true);
304 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500305
306 /** @brief Query PLDM for the MCTP requester instance id
307 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500308 * @return true if the id was found and false if not
309 */
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100310 bool getPldmInstanceId();
Eddie Jamescbad2192021-10-07 09:39:39 -0500311
Chris Cainbae4d072022-02-28 09:46:50 -0600312 /** @brief Encode a GetStateSensor command into a PLDM request
313 * @param[in] instance - OCC instance number
314 * @param[in] sensorId - OCC Active sensor ID number
315 *
316 * @return request - The encoded PLDM messsage to be sent
317 */
318 std::vector<uint8_t> encodeGetStateSensorRequest(uint8_t instance,
319 uint16_t sensorId);
Eddie Jamescbad2192021-10-07 09:39:39 -0500320 /** @brief Send the PLDM request
321 *
Chris Caind1b68262022-02-28 09:56:50 -0600322 * @param[in] request - the request data
Chris Cainbae4d072022-02-28 09:46:50 -0600323 * @param[in] rspExpected - false: no need to wait for the response
324 * true: will need to process response in callback
Eddie Jamescbad2192021-10-07 09:39:39 -0500325 */
Chris Cainbae4d072022-02-28 09:46:50 -0600326 void sendPldm(const std::vector<uint8_t>& request, const uint8_t instance,
327 const bool rspExpected = false);
328
329 /** @brief Register a callback function to handle the PLDM response */
330 void registerPldmRspCallback();
331
332 /** @brief callback for the PLDM response event
333 *
334 * @param[in] es - Populated event source
335 * @param[in] fd - Associated File descriptor
336 * @param[in] revents - Type of event
337 * @param[in] userData - User data that was passed during registration
338 *
339 * @return - 0 or positive number on success and negative
340 * errno otherwise
341 */
342 static int pldmRspCallback(sd_event_source* es, int fd, uint32_t revents,
343 void* userData);
Patrick Williams05e95592021-09-02 09:28:14 -0500344};
345
346} // namespace pldm