xref: /openbmc/openpower-occ-control/pldm.hpp (revision aeba51cd)
1 #pragma once
2 #include "occ_events.hpp"
3 #include "occ_status.hpp"
4 #include "utils.hpp"
5 
6 #include <libpldm/pldm.h>
7 
8 #include <sdbusplus/bus/match.hpp>
9 #include <sdeventplus/event.hpp>
10 #include <sdeventplus/utility/timer.hpp>
11 
12 namespace pldm
13 {
14 
15 namespace MatchRules = sdbusplus::bus::match::rules;
16 using namespace open_power::occ;
17 
18 using CompositeEffecterCount = uint8_t;
19 using EffecterID = uint16_t;
20 using EntityType = uint16_t;
21 using EntityInstance = uint16_t;
22 using EventState = uint8_t;
23 using InstanceToEffecter = std::map<open_power::occ::instanceID, EffecterID>;
24 using PdrList = std::vector<std::vector<uint8_t>>;
25 using SensorID = uint16_t;
26 using SensorOffset = uint8_t;
27 using SensorToInstance = std::map<SensorID, open_power::occ::instanceID>;
28 using TerminusID = uint8_t;
29 
30 /** @brief Hardcoded TID */
31 constexpr TerminusID tid = 0;
32 
33 /** @brief OCC instance starts with 0 for example "occ0" */
34 constexpr open_power::occ::instanceID start = 0;
35 
36 /** @brief Hardcoded mctpEid for HBRT */
37 constexpr mctp_eid_t mctpEid = 10;
38 
39 /** @class Interface
40  *
41  *  @brief Abstracts the PLDM details related to the OCC
42  */
43 class 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      */
Interface(std::function<bool (open_power::occ::instanceID,bool)> callBack,std::function<void (open_power::occ::instanceID,bool)> sbeCallBack,std::function<void (bool)> safeModeCallBack,EventPtr & event)58     explicit Interface(
59         std::function<bool(open_power::occ::instanceID, bool)> callBack,
60         std::function<void(open_power::occ::instanceID, bool)> sbeCallBack,
61         std::function<void(bool)> safeModeCallBack, EventPtr& event) :
62         callBack(callBack),
63         sbeCallBack(sbeCallBack), safeModeCallBack(safeModeCallBack),
64         event(event),
65         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)),
73         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)),
79         sdpEvent(sdeventplus::Event::get_default()),
80         pldmRspTimer(
81             sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>(
82                 sdpEvent, std::bind(&Interface::pldmRspExpired, this)))
83     {}
84 
85     /** @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.
88      *
89      *  @param[in] stateSetId - the state set ID to look for
90      *  @param[out] sensorInstanceMap - map of sensorID to instance
91      *  @param[out] sensorOffset - sensor offset of interested state set ID
92      */
93     void fetchSensorInfo(uint16_t stateSetId,
94                          SensorToInstance& sensorInstanceMap,
95                          SensorOffset& sensorOffset);
96 
97     /** @brief Fetch the OCC/SBE state effecter PDRs and populate the cache
98      *         with OCC/SBE instance to EffecterID information.
99      *
100      *  @param[in] stateSetId - the state set ID to look for
101      *  @param[out] instanceToEffecterMap - map of instance to effecterID
102      *  @param[out] count - sensor offset of interested state set ID
103      *  @param[out] stateIdPos - position of the stateSetID
104      */
105     void fetchEffecterInfo(uint16_t stateSetId,
106                            InstanceToEffecter& instanceToEffecterMap,
107                            CompositeEffecterCount& count, uint8_t& stateIdPos);
108 
109     /** @brief Prepare the request for SetStateEffecterStates command
110      *
111      *  @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
115      *
116      *  @return PLDM request message to be sent to host for OCC reset or SBE
117      *          HRESET, empty response in the case of failure.
118      */
119     std::vector<uint8_t>
120         prepareSetEffecterReq(EffecterID effecterId,
121                               CompositeEffecterCount effecterCount,
122                               uint8_t stateIdPos, uint8_t stateSetValue);
123 
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 
131     /** @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 
137     /** @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 
145     /** @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 
151   private:
152     /** @brief PLDM instance number used in PLDM requests
153      */
154     std::optional<uint8_t> pldmInstanceID;
155 
156     /** @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 
161     /** @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 
167     /** @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 
172     /** @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 
178     /** @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 
183     /** @brief Used to subscribe for host state change signal */
184     sdbusplus::bus::match_t hostStateSignal;
185 
186     /** @brief PLDM Sensor ID to OCC Instance mapping
187      */
188     SensorToInstance sensorToOCCInstance;
189 
190     /** @brief PLDM Sensor ID to SBE Instance mapping
191      */
192     SensorToInstance sensorToSBEInstance;
193 
194     /** @brief Sensor offset of OCC state set ID
195      * PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS in state sensor PDR.
196      */
197     SensorOffset OCCSensorOffset = 0;
198 
199     /** @brief Sensor offset of the SBE state set ID
200      * PLDM_OEM_IBM_SBE_HRESET_STATE in state sensor PDR.
201      */
202     SensorOffset SBESensorOffset = 0;
203 
204     /** @brief OCC Instance mapping to PLDM Effecter ID
205      */
206     InstanceToEffecter occInstanceToEffecter;
207 
208     /** @brief SBE instance mapping to PLDM Effecter ID
209      */
210     InstanceToEffecter sbeInstanceToEffecter;
211 
212     /** @brief compositeEffecterCount for OCC reset state effecter PDR */
213     CompositeEffecterCount OCCEffecterCount = 0;
214 
215     /** @brief compositeEffecterCount for SBE HRESET state effecter PDR */
216     CompositeEffecterCount SBEEffecterCount = 0;
217 
218     /** @brief Position of Boot/Restart Cause stateSetID in OCC state
219      *         effecter PDR
220      */
221     uint8_t bootRestartPosition = 0;
222 
223     /** @brief Position of the SBE maintenance stateSetID in the state
224      *         effecter PDR
225      */
226     uint8_t sbeMaintenanceStatePosition = 0;
227 
228     /** @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 
234     /** @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 
249     std::set<uint8_t> outstandingHResets;
250 
251     /** @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 
256     /** @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 
264     /** @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      */
271     void sensorEvent(sdbusplus::message_t& msg);
272 
273     /** @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      */
279     void hostStateEvent(sdbusplus::message_t& msg);
280 
281     /** @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 
286     /** @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      */
isOCCSensorCacheValid()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      */
isPDREffecterCacheValid()301     auto isPDREffecterCacheValid()
302     {
303         return (occInstanceToEffecter.empty() ? false : true);
304     }
305 
306     /** @brief Query PLDM for the MCTP requester instance id
307      *
308      * @return true if the id was found and false if not
309      */
310     bool getPldmInstanceId();
311 
312     /** @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);
320     /** @brief Send the PLDM request
321      *
322      * @param[in] request - the request data
323      * @param[in] rspExpected - false: no need to wait for the response
324      *                          true: will need to process response in callback
325      */
326     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);
344 };
345 
346 } // namespace pldm
347