blob: 641153fc0ed3c081098b6a5da99efbd687da5071 [file] [log] [blame]
Patrick Williams05e95592021-09-02 09:28:14 -05001#pragma once
Rashmica Guptadb38e912023-05-25 10:33:46 +10002
Chris Cainbae4d072022-02-28 09:46:50 -06003#include "occ_events.hpp"
Patrick Williams05e95592021-09-02 09:28:14 -05004#include "occ_status.hpp"
5#include "utils.hpp"
6
Rashmica Guptadb38e912023-05-25 10:33:46 +10007#include <libpldm/instance-id.h>
Patrick Williams05e95592021-09-02 09:28:14 -05008#include <libpldm/pldm.h>
9
10#include <sdbusplus/bus/match.hpp>
Chris Cainbae4d072022-02-28 09:46:50 -060011#include <sdeventplus/event.hpp>
12#include <sdeventplus/utility/timer.hpp>
Patrick Williams05e95592021-09-02 09:28:14 -050013
14namespace pldm
15{
16
17namespace MatchRules = sdbusplus::bus::match::rules;
Chris Cainbae4d072022-02-28 09:46:50 -060018using namespace open_power::occ;
Patrick Williams05e95592021-09-02 09:28:14 -050019
20using CompositeEffecterCount = uint8_t;
21using EffecterID = uint16_t;
22using EntityType = uint16_t;
23using EntityInstance = uint16_t;
24using EventState = uint8_t;
Eddie Jamescbad2192021-10-07 09:39:39 -050025using InstanceToEffecter = std::map<open_power::occ::instanceID, EffecterID>;
Patrick Williams05e95592021-09-02 09:28:14 -050026using PdrList = std::vector<std::vector<uint8_t>>;
27using SensorID = uint16_t;
28using SensorOffset = uint8_t;
Eddie Jamescbad2192021-10-07 09:39:39 -050029using SensorToInstance = std::map<SensorID, open_power::occ::instanceID>;
Patrick Williams05e95592021-09-02 09:28:14 -050030using TerminusID = uint8_t;
31
32/** @brief Hardcoded TID */
33constexpr TerminusID tid = 0;
34
35/** @brief OCC instance starts with 0 for example "occ0" */
36constexpr open_power::occ::instanceID start = 0;
37
38/** @brief Hardcoded mctpEid for HBRT */
39constexpr mctp_eid_t mctpEid = 10;
40
41/** @class Interface
42 *
43 * @brief Abstracts the PLDM details related to the OCC
44 */
45class Interface
46{
47 public:
48 Interface() = delete;
Rashmica Guptadb38e912023-05-25 10:33:46 +100049 //~Interface() = default;
Patrick Williams05e95592021-09-02 09:28:14 -050050 Interface(const Interface&) = delete;
51 Interface& operator=(const Interface&) = delete;
52 Interface(Interface&&) = delete;
53 Interface& operator=(Interface&&) = delete;
54
55 /** @brief Constructs the PLDM Interface object for OCC functions
56 *
57 * @param[in] callBack - callBack handler to invoke when the OCC state
58 * changes.
59 */
60 explicit Interface(
Eddie Jamescbad2192021-10-07 09:39:39 -050061 std::function<bool(open_power::occ::instanceID, bool)> callBack,
Chris Cainbae4d072022-02-28 09:46:50 -060062 std::function<void(open_power::occ::instanceID, bool)> sbeCallBack,
Sheldon Bailey31a2f132022-05-20 11:31:52 -050063 std::function<void(bool)> safeModeCallBack, EventPtr& event) :
Patrick Williams05e95592021-09-02 09:28:14 -050064 callBack(callBack),
Sheldon Bailey31a2f132022-05-20 11:31:52 -050065 sbeCallBack(sbeCallBack), safeModeCallBack(safeModeCallBack),
66 event(event),
Patrick Williams05e95592021-09-02 09:28:14 -050067 pldmEventSignal(
68 open_power::occ::utils::getBus(),
69 MatchRules::type::signal() +
70 MatchRules::member("StateSensorEvent") +
71 MatchRules::path("/xyz/openbmc_project/pldm") +
72 MatchRules::interface("xyz.openbmc_project.PLDM.Event"),
73 std::bind(std::mem_fn(&Interface::sensorEvent), this,
74 std::placeholders::_1)),
Chris Cain157467d2022-06-24 11:25:23 -050075 hostStateSignal(
76 open_power::occ::utils::getBus(),
77 MatchRules::propertiesChanged("/xyz/openbmc_project/state/host0",
78 "xyz.openbmc_project.State.Host"),
79 std::bind(std::mem_fn(&Interface::hostStateEvent), this,
80 std::placeholders::_1)),
Chris Cainbae4d072022-02-28 09:46:50 -060081 sdpEvent(sdeventplus::Event::get_default()),
82 pldmRspTimer(
83 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>(
84 sdpEvent, std::bind(&Interface::pldmRspExpired, this)))
Rashmica Guptadb38e912023-05-25 10:33:46 +100085 {
86 int rc = pldm_instance_db_init_default(&pldmInstanceIdDb);
87 if (rc)
88 {
89 throw std::system_category().default_error_condition(rc);
90 }
91 }
92
93 ~Interface()
94 {
95 int rc = pldm_instance_db_destroy(pldmInstanceIdDb);
96 if (rc)
97 {
98 std::cout << "pldm_instance_db_destroy failed, rc =" << rc << "\n";
99 }
100 }
Patrick Williams05e95592021-09-02 09:28:14 -0500101
Eddie Jamescbad2192021-10-07 09:39:39 -0500102 /** @brief Fetch the state sensor PDRs and populate the cache with
103 * sensorId to OCC/SBE instance mapping information and the sensor
104 * offset for the relevent state set.
Patrick Williams05e95592021-09-02 09:28:14 -0500105 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500106 * @param[in] stateSetId - the state set ID to look for
107 * @param[out] sensorInstanceMap - map of sensorID to instance
Patrick Williams05e95592021-09-02 09:28:14 -0500108 * @param[out] sensorOffset - sensor offset of interested state set ID
109 */
Eddie Jamescbad2192021-10-07 09:39:39 -0500110 void fetchSensorInfo(uint16_t stateSetId,
111 SensorToInstance& sensorInstanceMap,
112 SensorOffset& sensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -0500113
Eddie Jamescbad2192021-10-07 09:39:39 -0500114 /** @brief Fetch the OCC/SBE state effecter PDRs and populate the cache
115 * with OCC/SBE instance to EffecterID information.
Patrick Williams05e95592021-09-02 09:28:14 -0500116 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500117 * @param[in] stateSetId - the state set ID to look for
118 * @param[out] instanceToEffecterMap - map of instance to effecterID
Patrick Williams05e95592021-09-02 09:28:14 -0500119 * @param[out] count - sensor offset of interested state set ID
Eddie Jamescbad2192021-10-07 09:39:39 -0500120 * @param[out] stateIdPos - position of the stateSetID
Patrick Williams05e95592021-09-02 09:28:14 -0500121 */
Eddie James432dc482021-11-19 15:29:31 -0600122 void fetchEffecterInfo(uint16_t stateSetId,
Eddie Jamescbad2192021-10-07 09:39:39 -0500123 InstanceToEffecter& instanceToEffecterMap,
124 CompositeEffecterCount& count, uint8_t& stateIdPos);
Patrick Williams05e95592021-09-02 09:28:14 -0500125
126 /** @brief Prepare the request for SetStateEffecterStates command
127 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500128 * @param[in] effecterId - the instance effecter ID
129 * @param[in] effecterCount - compositeEffecterCount for the effecter PDR
130 * @param[in] stateIdPos - position of the stateSetID
131 * @param[in] stateSetValue - the value to set the state set to
Patrick Williams05e95592021-09-02 09:28:14 -0500132 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500133 * @return PLDM request message to be sent to host for OCC reset or SBE
134 * HRESET, empty response in the case of failure.
Patrick Williams05e95592021-09-02 09:28:14 -0500135 */
136 std::vector<uint8_t>
Chris Cain8b508bf2022-05-26 14:01:31 -0500137 prepareSetEffecterReq(EffecterID effecterId,
Patrick Williams05e95592021-09-02 09:28:14 -0500138 CompositeEffecterCount effecterCount,
Eddie Jamescbad2192021-10-07 09:39:39 -0500139 uint8_t stateIdPos, uint8_t stateSetValue);
Patrick Williams05e95592021-09-02 09:28:14 -0500140
141 /** @brief Send the PLDM message to reset the OCC
142 *
143 * @param[in] instanceId - OCC instance to reset
144 *
145 */
146 void resetOCC(open_power::occ::instanceID occInstanceId);
147
Eddie Jamescbad2192021-10-07 09:39:39 -0500148 /** @brief Send the PLDM message to perform the HRESET
149 *
150 * @param[in] instanceID - SBE instance to HRESET
151 */
152 void sendHRESET(open_power::occ::instanceID sbeInstanceId);
153
Chris Cainbae4d072022-02-28 09:46:50 -0600154 /** @brief Check if the OCC active sensor is available
155 * On successful read, the Manager callback will be called to update
156 * the status
157 *
158 * @param[in] instance - OCC instance to check
159 */
160 void checkActiveSensor(uint8_t instance);
161
Chris Cain755af102024-02-27 16:09:51 -0600162 /** @brief Set the throttleTraces flag
163 *
164 * @param[in] throttle - Flag to indicate if traces should be throttled
165 */
166 void setTraceThrottle(const bool throttle);
167
Patrick Williams05e95592021-09-02 09:28:14 -0500168 private:
Rashmica Guptadb38e912023-05-25 10:33:46 +1000169 /** @brief PLDM instance ID database object used to get instance IDs
170 */
171 pldm_instance_db* pldmInstanceIdDb = nullptr;
172
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100173 /** @brief PLDM instance number used in PLDM requests
Chris Cain8b508bf2022-05-26 14:01:31 -0500174 */
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100175 std::optional<uint8_t> pldmInstanceID;
Chris Cain8b508bf2022-05-26 14:01:31 -0500176
Patrick Williams05e95592021-09-02 09:28:14 -0500177 /** @brief Callback handler to be invoked when the state of the OCC
178 * changes
179 */
180 std::function<bool(open_power::occ::instanceID, bool)> callBack = nullptr;
181
Eddie Jamescbad2192021-10-07 09:39:39 -0500182 /** @brief Callback handler to be invoked when the maintenance state of the
183 * SBE changes
184 */
185 std::function<void(open_power::occ::instanceID, bool)> sbeCallBack =
186 nullptr;
187
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500188 /** @brief Callback handler to be invoked when the OCC is in SAFE Mode =
189 * true or when OCCs are in_service = false.
190 */
191 std::function<void(bool)> safeModeCallBack = nullptr;
192
Chris Cainbae4d072022-02-28 09:46:50 -0600193 /** @brief reference to sd_event wrapped in unique_ptr */
194 EventPtr& event;
195
196 /** @brief event source wrapped in unique_ptr */
197 EventSourcePtr eventSource;
198
Patrick Williams05e95592021-09-02 09:28:14 -0500199 /** @brief Used to subscribe to D-Bus PLDM StateSensorEvent signal and
200 * processes if the event corresponds to OCC state change.
201 */
202 sdbusplus::bus::match_t pldmEventSignal;
203
Chris Cain157467d2022-06-24 11:25:23 -0500204 /** @brief Used to subscribe for host state change signal */
205 sdbusplus::bus::match_t hostStateSignal;
206
Patrick Williams05e95592021-09-02 09:28:14 -0500207 /** @brief PLDM Sensor ID to OCC Instance mapping
208 */
Eddie Jamescbad2192021-10-07 09:39:39 -0500209 SensorToInstance sensorToOCCInstance;
Patrick Williams05e95592021-09-02 09:28:14 -0500210
Eddie Jamescbad2192021-10-07 09:39:39 -0500211 /** @brief PLDM Sensor ID to SBE Instance mapping
212 */
213 SensorToInstance sensorToSBEInstance;
214
215 /** @brief Sensor offset of OCC state set ID
Patrick Williams05e95592021-09-02 09:28:14 -0500216 * PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS in state sensor PDR.
217 */
George Liuf3a4a692021-12-28 13:59:51 +0800218 SensorOffset OCCSensorOffset = 0;
Eddie Jamescbad2192021-10-07 09:39:39 -0500219
220 /** @brief Sensor offset of the SBE state set ID
221 * PLDM_OEM_IBM_SBE_HRESET_STATE in state sensor PDR.
222 */
George Liuf3a4a692021-12-28 13:59:51 +0800223 SensorOffset SBESensorOffset = 0;
Patrick Williams05e95592021-09-02 09:28:14 -0500224
225 /** @brief OCC Instance mapping to PLDM Effecter ID
226 */
Eddie Jamescbad2192021-10-07 09:39:39 -0500227 InstanceToEffecter occInstanceToEffecter;
228
229 /** @brief SBE instance mapping to PLDM Effecter ID
230 */
231 InstanceToEffecter sbeInstanceToEffecter;
Patrick Williams05e95592021-09-02 09:28:14 -0500232
233 /** @brief compositeEffecterCount for OCC reset state effecter PDR */
Eddie Jamescbad2192021-10-07 09:39:39 -0500234 CompositeEffecterCount OCCEffecterCount = 0;
235
236 /** @brief compositeEffecterCount for SBE HRESET state effecter PDR */
237 CompositeEffecterCount SBEEffecterCount = 0;
Patrick Williams05e95592021-09-02 09:28:14 -0500238
239 /** @brief Position of Boot/Restart Cause stateSetID in OCC state
240 * effecter PDR
241 */
242 uint8_t bootRestartPosition = 0;
243
Eddie Jamescbad2192021-10-07 09:39:39 -0500244 /** @brief Position of the SBE maintenance stateSetID in the state
245 * effecter PDR
246 */
247 uint8_t sbeMaintenanceStatePosition = 0;
248
Chris Cainbae4d072022-02-28 09:46:50 -0600249 /** @brief OCC instance number for the PLDM message */
250 uint8_t pldmResponseOcc = 0;
251
252 /** @brief File descriptor for PLDM messages */
253 int pldmFd = -1;
254
Chris Cainbae4d072022-02-28 09:46:50 -0600255 /** @brief The response for the PLDM request msg is received flag.
256 */
257 bool pldmResponseReceived = false;
258
259 /** @brief The response for the PLDM request has timed out.
260 */
261 bool pldmResponseTimeout = false;
262
263 /** @brief timer event */
264 sdeventplus::Event sdpEvent;
265
266 /** @brief Timer that is started when PLDM command is sent
267 */
268 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> pldmRspTimer;
269
Chris Cain12d0b822022-04-22 17:29:18 -0500270 std::set<uint8_t> outstandingHResets;
271
Chris Cain755af102024-02-27 16:09:51 -0600272 /** @brief Flag to indicate that traces should be throttled.
273 Used to limit traces when there are issues getting OCC status.
274 */
275 static bool throttleTraces;
276
Chris Cainbae4d072022-02-28 09:46:50 -0600277 /** @brief Callback when PLDM response has not been received within the
278 * timeout period.
279 */
280 void pldmRspExpired();
281
282 /** @brief Close the MCTP file */
283 void pldmClose();
284
Patrick Williams05e95592021-09-02 09:28:14 -0500285 /** @brief When the OCC state changes host sends PlatformEventMessage
286 * StateSensorEvent, this function processes the D-Bus signal
287 * with the sensor event information and invokes the callback
288 * to change the OCC state.
289 *
290 * @param[in] msg - data associated with the subscribed signal
291 */
Patrick Williamsaf408082022-07-22 19:26:54 -0500292 void sensorEvent(sdbusplus::message_t& msg);
Patrick Williams05e95592021-09-02 09:28:14 -0500293
Chris Cain157467d2022-06-24 11:25:23 -0500294 /** @brief When the host state changes and if the CurrentHostState is
295 * xyz.openbmc_project.State.Host.HostState.Off then
296 * the cache of OCC sensors and effecters mapping is cleared.
297 *
298 * @param[in] msg - data associated with the subscribed signal
299 */
Patrick Williamsaf408082022-07-22 19:26:54 -0500300 void hostStateEvent(sdbusplus::message_t& msg);
Chris Cain157467d2022-06-24 11:25:23 -0500301
Chris Cainbae4d072022-02-28 09:46:50 -0600302 /** @brief Called when it is determined that the Host is not running.
303 * The cache of OCC sensors and effecters mapping is cleared.
304 */
305 void clearData();
306
Patrick Williams05e95592021-09-02 09:28:14 -0500307 /** @brief Check if the PDR cache for PLDM OCC sensors is valid
308 *
309 * @return true if cache is populated and false if the cache is not
310 * populated.
311 */
312 auto isOCCSensorCacheValid()
313 {
314 return (sensorToOCCInstance.empty() ? false : true);
315 }
316
317 /** @brief Check if the PDR cache for PLDM OCC effecters is valid
318 *
319 * @return true if cache is populated and false if the cache is not
320 * populated.
321 */
322 auto isPDREffecterCacheValid()
323 {
324 return (occInstanceToEffecter.empty() ? false : true);
325 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500326
Rashmica Guptadb38e912023-05-25 10:33:46 +1000327 /** @brief Get a PLDM requester instance id
Eddie Jamescbad2192021-10-07 09:39:39 -0500328 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500329 * @return true if the id was found and false if not
330 */
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100331 bool getPldmInstanceId();
Eddie Jamescbad2192021-10-07 09:39:39 -0500332
Rashmica Guptadb38e912023-05-25 10:33:46 +1000333 /** @brief Free PLDM requester instance id */
334 void freePldmInstanceId();
335
Chris Cainbae4d072022-02-28 09:46:50 -0600336 /** @brief Encode a GetStateSensor command into a PLDM request
337 * @param[in] instance - OCC instance number
338 * @param[in] sensorId - OCC Active sensor ID number
339 *
340 * @return request - The encoded PLDM messsage to be sent
341 */
342 std::vector<uint8_t> encodeGetStateSensorRequest(uint8_t instance,
343 uint16_t sensorId);
Eddie Jamescbad2192021-10-07 09:39:39 -0500344 /** @brief Send the PLDM request
345 *
Chris Caind1b68262022-02-28 09:56:50 -0600346 * @param[in] request - the request data
Chris Cainbae4d072022-02-28 09:46:50 -0600347 * @param[in] rspExpected - false: no need to wait for the response
348 * true: will need to process response in callback
Eddie Jamescbad2192021-10-07 09:39:39 -0500349 */
Chris Cainbae4d072022-02-28 09:46:50 -0600350 void sendPldm(const std::vector<uint8_t>& request, const uint8_t instance,
351 const bool rspExpected = false);
352
353 /** @brief Register a callback function to handle the PLDM response */
354 void registerPldmRspCallback();
355
356 /** @brief callback for the PLDM response event
357 *
358 * @param[in] es - Populated event source
359 * @param[in] fd - Associated File descriptor
360 * @param[in] revents - Type of event
361 * @param[in] userData - User data that was passed during registration
362 *
363 * @return - 0 or positive number on success and negative
364 * errno otherwise
365 */
366 static int pldmRspCallback(sd_event_source* es, int fd, uint32_t revents,
367 void* userData);
Patrick Williams05e95592021-09-02 09:28:14 -0500368};
369
370} // namespace pldm